diff ibin/brachylog/Brachylog-master/src/transpile.pl @ 11865:318de151d0ec draft

<b_jonas> python3 -cimport os,zipfile; os.chdir("ibin/brachylog"); zipfile.ZipFile("master.zip").extractall()
author HackEso <hackeso@esolangs.org>
date Tue, 16 Jul 2019 21:37:27 +0000
parents
children
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/ibin/brachylog/Brachylog-master/src/transpile.pl	Tue Jul 16 21:37:27 2019 +0000
@@ -0,0 +1,641 @@
+/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+____            ____
+\   \          /   /
+ \   \  ____  /   /
+  \   \/    \/   /
+   \     /\     /     BRACHYLOG
+    \   /  \   /      A terse declarative logic programming language
+    /   \  /   \
+   /     \/     \     Written by Julien Cumin - 2017
+  /   /\____/\   \    https://github.com/JCumin/Brachylog
+ /   /  ___   \   \
+/___/  /__/    \___\
+
+- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
+
+
+:- module(transpile, [parse/2,
+                      parse_no_file/2,
+                      parse_argument/2,
+                      contains_write/1
+                     ]).
+
+:- use_module(tokenize).
+:- use_module(symbols).
+
+
+/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+   PARSE
+- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
+parse(Code, TranspiledPath) :-
+    parse_no_file(Code, Predicates),
+    open(TranspiledPath, write, File),
+    maplist(write_to_file(File), Predicates),
+    close(File).
+
+parse_no_file(Code, Predicates) :-
+    atom_chars(Code, SplittedCode),
+    tokenize(SplittedCode, TokensNoOutputs),
+    append_trailing_output(TokensNoOutputs, Tokens),
+    fix_predicates(Tokens, FixedPredicates),
+    fix_metapredicates(FixedPredicates, FixedMetapredicates),
+    fill_implicit_variables(FixedMetapredicates, FilledTokens),
+    fix_variables_superscripts(FilledTokens, FixedVariables, GlobalVariables),
+    fix_lists(FixedVariables, FixedLists),
+    fix_forks(FixedLists, FixedForks),
+    fix_arrows(FixedForks, Program),
+    atomic_list_concat(GlobalVariables, ',', G),
+    atomic_list_concat(['[', G, ']'], GlobalVariablesAtom),
+    transpile(Program, Predicates, GlobalVariablesAtom),
+    !.
+
+
+/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+   PARSE_ARGUMENT
+- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
+parse_argument(Arg, Term) :-
+    (   atom(Arg),
+        AtomArg = Arg
+    ;   \+ atom(Arg),
+        term_to_atom(Arg, AtomArg)
+    ),
+    atom_chars(AtomArg, SplittedArg),
+    tokenize(SplittedArg, Token),
+    fix_variables_superscripts(Token, FixedSuperscripts, _),
+    fix_lists(FixedSuperscripts, Program),
+    transpile(Program, Parsed, '[]'),
+    !,
+    reverse(Parsed, [TempMainPredicate|_]),
+    nth0(3, TempMainPredicate, Atom),
+    atom_concat(',\n    ', AtomT, Atom),
+    atom_concat(ParsedArg, ' = Var_Input_Local', AtomT),
+    term_to_atom(Term, ParsedArg)
+    ;
+    throw('Incorrect variable format.').
+
+
+/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+   APPEND_TRAILING_OUTPUT
+- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
+append_trailing_output([], ['variable':'Output':'sup':'default']).
+append_trailing_output(['control':'\n'|T], ['variable':'Output':'sup':'default','control':'\n'|T2]) :-
+    append_trailing_output(T, T2).
+append_trailing_output(['control':'}'|T], ['variable':'Output':'sup':'default','control':'}'|T2]) :-
+    append_trailing_output(T, T2).
+append_trailing_output(['control':'⟩'|T], ['variable':'Output':'sup':'default','control':'⟩'|T2]) :-
+    append_trailing_output(T, T2).
+append_trailing_output(['control':'|'|T], ['variable':'Output':'sup':'default','control':'|'|T2]) :-
+    append_trailing_output(T, T2).
+append_trailing_output([H|T], [H|T2]) :-
+    H \= 'control':'\n',
+    H \= 'control':'}',
+    H \= 'control':'⟩',
+    H \= 'control':'|',
+    append_trailing_output(T, T2).
+
+
+/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+   FIX_PREDICATES'⟨', '⟩'
+- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
+fix_predicates(Tokens, FixedPredicates) :-
+    fix_predicates(Tokens, 1, L),
+    append(L, FixedPredicates).
+
+fix_predicates([], _, [[]]).
+fix_predicates(['control':'{'|T], I, [['predicate':PredName:0|Rest], ['control':'\n'|Predicate]|AllOtherPredicates]) :-
+    atomic_list_concat(['brachylog_predicate_',I], PredName),
+    J is I + 1,
+    fix_predicates_(T, J, [Predicate|OtherPredicates1], Z, Remaining),
+    fix_predicates(Remaining, Z, [Rest|OtherPredicates2]),
+    append(OtherPredicates1, OtherPredicates2, AllOtherPredicates).
+fix_predicates(['control':'⟨'|T], I, [['predicate':PredName:0|Rest], ['control':'\n','fork':'start'|Predicate]|AllOtherPredicates]) :-
+    atomic_list_concat(['brachylog_predicate_',I], PredName),
+    J is I + 1,
+    fix_predicates_(T, J, [Predicate|OtherPredicates1], Z, Remaining),
+    fix_predicates(Remaining, Z, [Rest|OtherPredicates2]),
+    append(OtherPredicates1, OtherPredicates2, AllOtherPredicates).
+fix_predicates(['control':'\n'|T], I, [[],['control':'\n'|Rest]|OtherPredicates]) :-
+    J is I + 1,
+    fix_predicates(T, J, [Rest|OtherPredicates]).
+fix_predicates([Type:A|T], I, [[Type:A|Rest]|OtherPredicates]) :-
+    \+ (Type = 'control', A = '{'),
+    \+ (Type = 'control', A = '}'),
+    \+ (Type = 'control', A = '⟨'),
+    \+ (Type = 'control', A = '⟩'),
+    \+ (Type = 'control', A = '\n'),
+    fix_predicates(T, I, [Rest|OtherPredicates]).
+
+fix_predicates_([], _, [[]]).
+fix_predicates_(['control':'{'|T], I, [['predicate':PredName:0|Rest], ['control':'\n'|Predicate]|AllOtherPredicates], Z, Remaining) :-
+    atomic_list_concat(['brachylog_predicate_',I], PredName),
+    J is I + 1,
+    fix_predicates_(T, J, [Predicate|OtherPredicates1], Z2, Remaining2),
+    fix_predicates_(Remaining2, Z2, [Rest|OtherPredicates2], Z, Remaining),
+    append(OtherPredicates1, OtherPredicates2, AllOtherPredicates).
+fix_predicates_(['control':'⟨'|T], I, [['predicate':PredName:0|Rest], ['control':'\n','fork':'start'|Predicate]|AllOtherPredicates], Z, Remaining) :-
+    atomic_list_concat(['brachylog_predicate_',I], PredName),
+    J is I + 1,
+    fix_predicates_(T, J, [Predicate|OtherPredicates1], Z2, Remaining2),
+    fix_predicates_(Remaining2, Z2, [Rest|OtherPredicates2], Z, Remaining),
+    append(OtherPredicates1, OtherPredicates2, AllOtherPredicates).
+fix_predicates_(['control':'}'|T], I, [[]], I, T).
+fix_predicates_(['control':'⟩'|T], I, [['fork':'end']], I, T).
+fix_predicates_([Type:A|T], I, [[Type:A|Rest]|OtherPredicates], Z, Remaining) :-
+    \+ (Type = 'control', A = '{'),
+    \+ (Type = 'control', A = '}'),
+    \+ (Type = 'control', A = '⟨'),
+    \+ (Type = 'control', A = '⟩'),
+    \+ (Type = 'control', A = '\n'),
+    fix_predicates_(T, I, [Rest|OtherPredicates], Z, Remaining).
+
+
+/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+   FIX_METAPREDICATES
+- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
+fix_metapredicates([], []).
+fix_metapredicates(['predicate':PredName:Sub,'metapredicate':MetapredName:Sup|T], ['predicate':PredName:Sub:MetapredName:Sup|T2]) :-
+    fix_metapredicates(T, T2).
+fix_metapredicates(['predicate':PredName:Sub|T], ['predicate':PredName:Sub:'no':0|T2]) :-
+    fix_metapredicates(T, T2).
+fix_metapredicates([H|T], [H|T2]) :-
+    fix_metapredicates(T, T2).
+
+
+/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+   FILL_IMPLICIT_VARIABLES
+- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
+fill_implicit_variables(Tokens, Program) :-
+    fill_implicit_variables(Tokens, 0, Program).
+
+fill_implicit_variables([], _, []).
+fill_implicit_variables(['control':':','predicate':A|T], I, ['control':':','predicate':A|T2]) :-
+    fill_implicit_variables(T, I, T2).
+fill_implicit_variables(['predicate':A,Type:B|T], I, ['predicate':A,'variable':V|T2]) :-
+    Type \= 'variable',
+    atom_concat('V', I, V),
+    J is I + 1,
+    fill_implicit_variables([Type:B|T], J, T2).
+fill_implicit_variables(['predicate':A], I, ['predicate':A,'variable':V]) :-
+    atom_concat('V', I, V).
+fill_implicit_variables(['predicate':A,'variable':B|T], I, ['predicate':A,'variable':B|T2]) :-
+    fill_implicit_variables(T, I, T2).
+fill_implicit_variables(['control':H,Type:B|T], I, ['control':H,'variable':V|T2]) :-
+    Type \= 'variable',
+    (   H = '∧'
+    ;   H = '∨'
+    ),
+    atom_concat('V', I, V),
+    J is I + 1,
+    fill_implicit_variables([Type:B|T], J, T2).
+fill_implicit_variables(['control':H,'variable':B,Type:C|T], I, ['control':H,'variable':B,'variable':V|T2]) :-
+    Type \= 'variable',
+    (   H = '↖'
+    ;   H = '↙'
+    ),
+    atom_concat('V', I, V),
+    J is I + 1,
+    fill_implicit_variables([Type:C|T], J, T2).
+fill_implicit_variables([Type:A|T], I, [Type:A|T2]) :-
+    Type \= 'predicate',
+    \+ (Type = 'control', A = ':', T = ['predicate':_|_]),
+    \+ (Type = 'control', A = '∧', T \= ['variable':_|_]),
+    \+ (Type = 'control', A = '∨', T \= ['variable':_|_]),
+    \+ (Type = 'control', A = '↖', T \= ['variable':_|_]),
+    \+ (Type = 'control', A = '↙', T \= ['variable':_|_]),
+    fill_implicit_variables(T, I, T2).
+
+
+/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+   FIX_VARIABLES_SUPERSCRIPTS
+- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
+fix_variables_superscripts(Input, Output, GlobalVariables) :-
+    fix_variables_superscripts_(Input, Output, GlobVars),
+    sort(GlobVars, GlobalVariables).  % Remove duplicates
+
+fix_variables_superscripts_([], [], []).
+fix_variables_superscripts_(['variable':A:'sup':Sup|T], ['variable':V|T2], [V|GlobalVariables]) :-
+    atomic_list_concat(['integer',  SupAtom], ':', Sup),
+    atom_number(SupAtom, J),
+    atomic_list_concat(['Var_',A,'_',J], V),
+    fix_variables_superscripts_(T, T2, GlobalVariables).
+fix_variables_superscripts_(['variable':A:'sup':'default'|T], ['variable':V|T2], GlobalVariables) :-
+    atomic_list_concat(['Var_',A,'_Local'], V),
+    fix_variables_superscripts_(T, T2, GlobalVariables).
+fix_variables_superscripts_(['variable':List|T], ['variable':FixedList|T2], GlobalVariables) :-
+    is_list(List),
+    fix_variables_superscripts_(List, FixedList, Vars),
+    fix_variables_superscripts_(T, T2, GlobalVariables2),
+    append(Vars, GlobalVariables2, GlobalVariables).
+fix_variables_superscripts_([X|T], [X|T2], GlobalVariables) :-
+    fix_variables_superscripts_(T, T2, GlobalVariables).
+
+
+
+/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+   FIX_LISTS
+- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
+fix_lists([], []).
+fix_lists(['variable':List|T], ['variable':FixedList|T2]) :-
+    is_list(List),
+    fix_list(List, FixedList),
+    fix_lists(T, T2).
+fix_lists([X|T], [X|T2]) :-
+    (   X = 'variable':L,
+        \+ (is_list(L))
+    ;   X \= 'variable':_
+    ),
+    fix_lists(T, T2).
+
+fix_list([], []).
+fix_list(['control':','|T], T2) :-
+    fix_list(T, T2).
+fix_list([X|T], [Y|T2]) :-
+    X \= 'control':',',
+    (   X = 'variable':L,
+        is_list(L),
+        fix_list(L, Y)
+    ;   X = 'variable':Y
+    ;   X = 'predicate':_,
+        Y = X
+    ;   Y = X
+    ),
+    fix_list(T, T2).
+
+
+/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+   FIX_FORKS
+- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
+fix_forks(L, Z) :-
+    fix_forks(L, 0, Z).
+
+fix_forks([], _, []).     % Ignore each useless implicit var after
+fix_forks(['fork':'start', F1, _, F2, Output, 'fork':'end'|T], I, ['control':'unpair','variable':V1,F1,Output,F2,'variable':V1,'control':'∧'|T2]) :-
+    atom_concat('Fork', I, V1),
+    J is I + 1,
+    fix_forks(T, J,  T2).
+fix_forks(['fork':'start', F1, _, F2, _, F3, Output, 'fork':'end'|T], I, ['control':'&',F1,'variable':V1,'control':'&',F3,'variable':V2,'control':'∧','variable':V1,'control':';','variable':V2,F2,Output|T2]) :-
+    atom_concat('Fork', I, V1),
+    J is I + 1,
+    atom_concat('Fork', J, V2),
+    K is I + 1,
+    fix_forks(T, K, T2).
+fix_forks([H|T], I, [H|T2]) :-
+    dif(H, 'fork':'start'),
+    fix_forks(T, I, T2).
+
+
+/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+   FIX_ARROWS
+- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
+fix_arrows([], []).
+fix_arrows(['predicate':P:_:Meta:Sup,'variable':_,'control':'↙','variable':V|T], T2) :- !,
+    (   atom(V) ->
+        V = VA
+    ;   term_to_atom(V, VA)
+    ),
+    fix_arrows(['predicate':P:VA:Meta:Sup|T], T2).
+fix_arrows(['predicate':P:Sub:Meta:_,'variable':_,'control':'↖','variable':V|T], T2) :- !,
+    (   atom(V) ->
+        V = VA
+    ;   term_to_atom(V, VA)
+    ),
+    fix_arrows(['predicate':P:Sub:Meta:VA|T], T2).
+fix_arrows(['predicate':P:_:Meta:Sup,'control':'↙','variable':V|T], T2) :- !,
+    (   atom(V) ->
+        V = VA
+    ;   term_to_atom(V, VA)
+    ),
+    fix_arrows(['predicate':P:VA:Meta:Sup|T], T2).
+fix_arrows(['predicate':P:Sub:Meta:_,'control':'↖','variable':V|T], T2) :- !,
+    (   atom(V) ->
+        V = VA
+    ;   term_to_atom(V, VA)
+    ),
+    fix_arrows(['predicate':P:Sub:Meta:VA|T], T2).
+fix_arrows([H|T], [H|T2]) :-
+    fix_arrows(T, T2).
+
+
+/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+   TRANSPILE
+- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
+transpile(Program, [[':- style_check(-singleton).'],
+                    [':- use_module(library(clpfd)).'],
+                    [':- use_module(predicates).'],
+                    [':- use_module(metapredicates).'],
+                    [':- use_module(constraint_variables).\n'],
+                    [MainPredHeader,
+                    ConstraintVariables,
+                    '    (1=1'|MainPred]|OtherPredicates], GlobalVariables) :-
+    atomic_list_concat(['brachylog_main(',
+                        GlobalVariables,
+                        ',_, Var_Input_Local,Var_Output_Local) :-\n',
+                        '    Name = brachylog_main,\n',
+                        '    GlobalVariables = ',
+                        GlobalVariables,',\n',
+                        '    nb_setval(\'declw\',[]),\n'],    % Initialize declarative write variable
+                       MainPredHeader),
+    constraint_variables(GlobalVariables, ConstraintVariables),
+    transpile_(Program, 'Var_Input_Local', no, no, 0, 0, [T|OtherPredicates], GlobalVariables),
+    reverse(T, [_|RT]),
+    reverse(RT, T2),
+    append(T2, ['\n',
+                '    ),\n',
+                '    (',
+                '(Var_Output_Local = integer:_ ; ',
+                'Var_Output_Local = [_|_], ',
+                'forall(member(E, Var_Output_Local), E = integer:_)) ',
+                '-> brachylog_label(default, Var_Output_Local, _) ',
+                '; true),\n',
+                '    nb_getval(\'declw\', DeclwFinal),\n',
+                '    maplist(write, DeclwFinal).'],    % execute declarative write
+               MainPred).
+
+transpile_([], _, _, _, _, _, [['\n    ).\n']], _).
+transpile_(['variable':B|T], A, Reverse, Negate, AppendNumber, PredNumber, [[Unification|T2]|OtherPredicates], GlobalVariables) :-
+    A \= 'nothing',
+    (   is_list(A),
+        brachylog_list_to_atom(A, Var1)
+    ;   A = Type:L,
+        term_to_atom(Type:L, Var1)
+    ;   A = Var1
+    ),
+    (   is_list(B),
+        brachylog_list_to_atom(B, Var2)
+    ;   B = _:_,
+        term_to_atom(B, Var2)
+    ;   Var2 = B
+    ),
+    (   Negate = yes,
+        UnificationAtom = ' \\= '
+    ;   Negate = no,
+        UnificationAtom = ' = '
+    ),
+    (   Reverse = no,
+        atomic_list_concat([',\n    ',Var2,UnificationAtom,Var1], Unification),
+        transpile_(T, B, no, no, AppendNumber, PredNumber, [T2|OtherPredicates], GlobalVariables)
+    ;   Reverse = yes,
+        atomic_list_concat([',\n    ',Var1,UnificationAtom,Var2], Unification),
+        transpile_(T, B, no, no, AppendNumber, PredNumber, [T2|OtherPredicates], GlobalVariables)
+    ).
+transpile_(['variable':B|T], 'nothing', _, _, AppendNumber, PredNumber, [T2|OtherPredicates], GlobalVariables) :-
+    transpile_(T, B, no, no, AppendNumber, PredNumber, [T2|OtherPredicates], GlobalVariables).
+transpile_(['predicate':P:Sub:Meta:Sup,'variable':B|T], A, Reverse, Negate, AppendNumber, PredNumber, [[Predicate|T2]|OtherPredicates], GlobalVariables) :-
+    A \= 'nothing',
+    (   P = 'brachylog_call_predicate',
+        (   Sub = 'default' ->
+            RealSub = 'Name-GlobalVariables'
+        ;   atomic_list_concat(['(',Sub,')-','GlobalVariables'], RealSub)
+        )
+    ;   P \= 'brachylog_call_predicate',
+        RealSub = Sub
+    ),
+    (   is_list(A),
+        brachylog_list_to_atom(A, Var1)
+    ;   A = Type:L,
+        term_to_atom(Type:L, Var1)
+    ;   A = Var1
+    ),
+    (   is_list(B),
+        brachylog_list_to_atom(B, Var2)
+    ;   B = _:_,
+        term_to_atom(B, Var2)
+    ;   Var2 = B
+    ),
+    (   Negate = yes,
+        NegateAtom = '\\+ '
+    ;   Negate = no,
+        NegateAtom = ''
+    ),
+    (   Reverse = no ->
+        PredName = P
+    ;   atomic_list_concat([P,'_reversed'], PredName)
+    ),
+    (   atomic_list_concat(['brachylog','predicate',_], '_', P)
+    ->  atomic_list_concat([GlobalVariables,','], GlobVars)
+    ;   GlobVars = ''
+    ),
+    (   Meta = no ->
+        atomic_list_concat([',\n    ',NegateAtom,PredName,'(',GlobVars,RealSub,',',Var1,',',Var2,')'], Predicate)
+    ;   (   atomic_list_concat(['brachylog','predicate',_], '_', P)
+        ->  atomic_list_concat([GlobalVariables,','], GlobVarsMeta)
+        ;   GlobVarsMeta = 'ignore,'
+        ),
+        atomic_list_concat([',\n    ',NegateAtom,Meta,'(',GlobVarsMeta,Sup,',',PredName,',',RealSub,',',Var1,',',Var2,')'], Predicate)
+    ),
+    transpile_(T, B, no, no, AppendNumber, PredNumber, [T2|OtherPredicates], GlobalVariables).
+transpile_(['control':'∧'|T], _, _, _, AppendNumber, PredNumber, [T2|OtherPredicates], GlobalVariables) :-
+    transpile_(T, 'nothing', no, no, AppendNumber, PredNumber, [T2|OtherPredicates], GlobalVariables).
+transpile_(['control':'&'|T], _, _, _, AppendNumber, PredNumber, [T2|OtherPredicates], GlobalVariables) :-
+    transpile_(T, 'Var_Input_Local', no, no, AppendNumber, PredNumber, [T2|OtherPredicates], GlobalVariables).
+transpile_(['control':'`'|T], B, _, _, AppendNumber, PredNumber, [['\n    *->\n    1=1'|T2]|OtherPredicates], GlobalVariables) :-
+    transpile_(T, B, no, no, AppendNumber, PredNumber, [T2|OtherPredicates], GlobalVariables).
+transpile_(['control':'∨'|T], _, _, _, AppendNumber, PredNumber, [['\n    ;\n    1=1'|T2]|OtherPredicates], GlobalVariables) :-
+    transpile_(T, 'nothing', no, no, AppendNumber, PredNumber, [T2|OtherPredicates], GlobalVariables).
+transpile_(['control':'('|T], B, _, Negate, AppendNumber, PredNumber, [[Parenthesis|T2]|OtherPredicates], GlobalVariables) :-
+    (   Negate = yes,
+        Parenthesis = ',\n    \\+ (\n    1=1'
+    ;   Negate = no,
+        Parenthesis = ',\n    (\n    1=1'
+    ),
+    transpile_(T, B, no, no, AppendNumber, PredNumber, [T2|OtherPredicates], GlobalVariables).
+transpile_(['control':')'|T], B, _, _, AppendNumber, PredNumber, [['\n    )'|T2]|OtherPredicates], GlobalVariables) :-
+    transpile_(T, B, no, no, AppendNumber, PredNumber, [T2|OtherPredicates], GlobalVariables).
+transpile_(['control':'!'|T], B, _, _, AppendNumber, PredNumber, [[',\n    !'|T2]|OtherPredicates], GlobalVariables) :-
+    transpile_(T, B, no, no, AppendNumber, PredNumber, [T2|OtherPredicates], GlobalVariables).
+transpile_(['control':'⊥'|T], B, _, _, AppendNumber, PredNumber, [[',\n    false'|T2]|OtherPredicates], GlobalVariables) :-
+    transpile_(T, B, no, no, AppendNumber, PredNumber, [T2|OtherPredicates], GlobalVariables).
+transpile_(['control':'~'|T], B, Reverse, Negate, AppendNumber, PredNumber, [T2|OtherPredicates], GlobalVariables) :-
+    (   Reverse = yes,
+        NewReverse = no
+    ;   Reverse = no,
+        NewReverse = yes
+    ),
+    transpile_(T, B, NewReverse, Negate, AppendNumber, PredNumber, [T2|OtherPredicates], GlobalVariables).
+transpile_(['control':'¬'|T], B, Reverse, Negate, AppendNumber, PredNumber, [T2|OtherPredicates], GlobalVariables) :-
+    (   Negate = yes,
+        NewNegate = no
+    ;   Negate = no,
+        NewNegate = yes
+    ),
+    transpile_(T, B, Reverse, NewNegate, AppendNumber, PredNumber, [T2|OtherPredicates], GlobalVariables).
+transpile_(['control':'unpair','variable':A|T], B, _, _, AppendNumber, PredNumber, [[Unpair|T2]|OtherPredicates], GlobalVariables) :-
+    (   A = TypeA:LA,
+        term_to_atom(TypeA:LA, TailElem)
+    ;   A = TailElem
+    ),
+    (   B = TypeB:LB,
+        term_to_atom(TypeB:LB, Pair)
+    ;   B = Pair
+    ),
+    atomic_list_concat(['UnpairTemp',AppendNumber],HeadElem),
+    atomic_list_concat([',\n    ',
+                        Pair,'=[',HeadElem,',',TailElem,']'],Unpair),
+    NewAppendNumber is AppendNumber + 1,
+    transpile_(T, HeadElem, no, no, NewAppendNumber, PredNumber, [T2|OtherPredicates], GlobalVariables).
+transpile_(['control':';',Type:A|T], B, _, _, AppendNumber, PredNumber, [T2|OtherPredicates], GlobalVariables) :-
+    (   Type = 'variable'
+    ;   Type = 'predicate'
+    ),
+    append([B], [A], NewVar),
+    transpile_(T, NewVar, no, no, AppendNumber, PredNumber, [T2|OtherPredicates], GlobalVariables).
+transpile_(['control':',','variable':A|T], B, _, _, AppendNumber, PredNumber, [[Append|T2]|OtherPredicates], GlobalVariables) :-
+    (   is_list(A),
+        brachylog_list_to_atom(A, Arg1)
+    ;   A = TypeA:LA,
+        term_to_atom(TypeA:LA, Arg1)
+    ;   A = Arg1
+    ),
+    (   is_list(B),
+        brachylog_list_to_atom(B, Arg2)
+    ;   B = TypeB:LB,
+        term_to_atom(TypeB:LB, Arg2)
+    ;   B = Arg2
+    ),
+    atomic_list_concat(['AppendTemp',AppendNumber],TempVar),
+    atomic_list_concat([',\n    ',
+                        '((',Arg2,' == [], \\+ is_brachylog_list(',Arg1,')) -> ',TempVar,' = [',Arg1,'] ; ',
+                        'brachylog_concatenate(default,',
+                        '[',Arg2,',',Arg1,']',
+                        ',',TempVar,') -> true ; is_brachylog_list(',
+                        Arg2,
+                        '), brachylog_concatenate(default,',
+                        '[',Arg2,',[',Arg1,']]',
+                        ',',TempVar,') -> true ; brachylog_concatenate(default,',
+                        '[[',Arg2,'],[',Arg1,']],',TempVar,'))'
+                       ], Append),
+    NewAppendNumber is AppendNumber + 1,
+    transpile_(T, TempVar, no, no, NewAppendNumber, PredNumber, [T2|OtherPredicates], GlobalVariables).
+transpile_(['control':'\n'|T], _, _, _, AppendNumber, PredNumber, [['\n    ).\n'],[ReversedPred],[PredHead|T2]|OtherPredicates], GlobalVariables) :-
+    J is PredNumber + 1,
+    constraint_variables(GlobalVariables, ConstraintVariables),
+    atomic_list_concat(['brachylog_predicate_',
+                        J,
+                        '_reversed(',
+                        GlobalVariables,
+                        ',_, Input, Output',
+                        ') :-\n',
+                        '    brachylog_predicate_',
+                        J,
+                        '(',
+                        GlobalVariables,
+                        ',_, Output, Input',
+                        ').\n'], ReversedPred),
+    atomic_list_concat(['brachylog_predicate_',
+                        J,
+                        '(',
+                        GlobalVariables,
+                        ',_, ',
+                        'Var_Input_Local',
+                        ',Var_Output_Local',
+                        ') :-\n    Name = brachylog_predicate_',
+                        J,
+                        ',\n    GlobalVariables = ',
+                        GlobalVariables,
+                        ',\n',
+                        ConstraintVariables,
+                        '    (1=1'], PredHead),
+    transpile_(T, 'Var_Input_Local', no, no, AppendNumber, J, [T2|OtherPredicates], GlobalVariables).
+transpile_(['control':'|'|T], _, _, _, AppendNumber, PredNumber, [['\n    ).\n'],[PredHead|T2]|OtherPredicates], GlobalVariables) :-
+    (   PredNumber = 0,
+        PredName = 'brachylog_main'
+    ;   PredNumber \= 0,
+        atomic_list_concat(['brachylog_predicate_',PredNumber], PredName)
+    ),
+    constraint_variables(GlobalVariables, ConstraintVariables),
+    atomic_list_concat([PredName,
+                        '(',
+                        GlobalVariables,
+                        ',_, ',
+                        'Var_Input_Local',
+                        ',Var_Output_Local',
+                        ') :-\n    Name = ',
+                        PredName,
+                        ',\n    GlobalVariables = ',
+                        GlobalVariables,
+                        ',\n',
+                        ConstraintVariables,
+                        '    (1=1'], PredHead),
+    transpile_(T, 'Var_Input_Local', no, no, AppendNumber, PredNumber, [T2|OtherPredicates], GlobalVariables).
+
+
+/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+   CONTAINS_WRITE
+- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
+contains_write(Code) :-
+    atom_chars(Code, SplittedCode),
+    tokenize(SplittedCode, Tokens),
+    fix_predicates(Tokens, FixedPredicates),
+    (   member(predicate:brachylog_write:_, FixedPredicates)
+    ;   member(predicate:brachylog_writeln:_, FixedPredicates)
+    ).
+
+
+/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+   CONSTRAINT_VARIABLES
+- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
+constraint_variables(GlobalVariables, ConstraintVariables) :-
+    atom_chars(GlobalVariables, [_|Gs]),
+    reverse(Gs, [_|RGs]),
+    reverse(RGs, RRGs),
+    atomic_list_concat(RRGs, GGs),
+    atomic_list_concat(GlobVars, ',', GGs),
+    findall(S, (member(X, GlobVars),
+                atomic_list_concat(['Var', Name, _], '_', X),
+                atom_chars(Name, CName),
+                reverse(CName, [_,'t','n','i','a','r','t','s','n','o','C']),
+                constraint_variable(X, S)), Ss),
+    atomic_list_concat(Ss, GlobalConstraintVariables),
+    findall(T, (member(X, ['A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z']),
+                atomic_list_concat(['    constraint',X,'(Var_Constraint',X,'_Local','),\n'], T)),
+            Ts
+    ),
+    atomic_list_concat(Ts, LocalConstraintVariables),
+    atomic_list_concat([GlobalConstraintVariables, LocalConstraintVariables], ConstraintVariables).
+
+constraint_variable(X, S) :-
+    atomic_list_concat(['Var', ConstraintName, _], '_', X),
+    atom_chars(ConstraintName, [C|Cs]),
+    downcase_atom(C, CDown),
+    atomic_list_concat([CDown|Cs], PredName),
+    atomic_list_concat(['   ',PredName,'(',X,'),\n'], S).
+
+
+/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+   BRACHYLOG_LIST_TO_ATOM
+- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
+brachylog_list_to_atom(List, Atom) :-
+    brachylog_list_to_atom_(List, T2),
+    atomic_list_concat(['[',T2,']'], Atom).
+
+brachylog_list_to_atom_([], '').
+brachylog_list_to_atom_([A], AtomA) :-
+    (   is_list(A),
+        brachylog_list_to_atom(A, AtomA)
+    ;   A = _:_,
+        term_to_atom(A, AtomA)
+    ;   \+ is_list(A),
+        A \= _:_,
+        AtomA = A
+    ).
+brachylog_list_to_atom_([A,B|T], Atom) :-
+    (   is_list(A),
+        brachylog_list_to_atom(A, AtomA)
+    ;   A = _:_,
+        term_to_atom(A, AtomA)
+    ;   \+ is_list(A),
+        A \= _:_,
+        AtomA = A
+    ),
+    brachylog_list_to_atom_([B|T], T2),
+    atomic_list_concat([AtomA,',',T2], Atom).
+
+
+/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+   WRITE_TO_FILE
+- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
+write_to_file(File, []) :-
+    write(File, '\n\n').
+write_to_file(File, [H|T]) :-
+    write(File, H),
+    write_to_file(File, T).