├── misc ├── brachylog_logo.png ├── brachylog_mini_logo.png └── brachylog_logo.svg ├── .gitignore ├── LICENSE ├── README.md └── src ├── constraint_variables.pl ├── utils.pl ├── brachylog.pl ├── symbols.pl ├── tokenize.pl ├── tests.pl ├── transpile.pl └── metapredicates.pl /misc/brachylog_logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JCumin/Brachylog/HEAD/misc/brachylog_logo.png -------------------------------------------------------------------------------- /misc/brachylog_mini_logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JCumin/Brachylog/HEAD/misc/brachylog_mini_logo.png -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *.class 2 | 3 | # Mobile Tools for Java (J2ME) 4 | .mtj.tmp/ 5 | 6 | # virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml 7 | hs_err_pid* 8 | 9 | compiled_brachylog.pl 10 | *.brachylog 11 | *.aux 12 | *.bbl 13 | *.blg 14 | *.log 15 | *.gz 16 | src/compiled_brachylog_eval.pl 17 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2016 - 2019 Julien Cumin 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 |
2 | 3 | # What is it? 4 | 5 | Brachylog is a declarative logic programming language much like Prolog. Brachylog is designed to be much terser than Prolog, while retaining some readability. 6 | 7 | Currently in development. 8 | 9 | Brachylog uses [SWI-Prolog](http://www.swi-prolog.org/) as Prolog engine. 10 | 11 | ## How do I use this? 12 | 13 | ### Documentation 14 | 15 | Check out [Brachylog's Wiki](https://github.com/JCumin/Brachylog/wiki) if you want to learn how to write programs in this language. 16 | 17 | You may want to watch this [**short video introduction to Brachylog**](https://www.youtube.com/watch?v=XYVhZ-MFcUs). 18 | 19 | ### Try it online! 20 | 21 | You can try out Brachylog on [Try it online!](https://tio.run/nexus/brachylog2), thanks to @DennisMitchell. 22 | 23 | ### Brachylog language bar 24 | 25 | [You can find here](https://abrudz.github.io/lb/brachylog) the Brachylog language bar which gives you access to all symbols used in Brachylog on any webpage (by clicking on the symbols or by inputing shortcuts), thanks to @abrudz. 26 | 27 | ### The interpreter 28 | 29 | Brachylog's interpreter is entirely written in Prolog. Therefore, installing [SWI-Prolog](http://www.swi-prolog.org/) (version 7 and up) is mandatory to use Brachylog (We do not guarantee that Brachylog's interpreter will be compatible with any other Prolog implementation). 30 | 31 | To run Brachylog's interpreter, start SWI-Prolog's interpreter inside the `src` directory available in this repository, and consult the file `brachylog.pl` (`consult(brachylog).`). Alternatively, you can run the interpreter with: 32 | 33 | $ swipl src/brachylog.pl 34 | 35 | You can then run Brachylog programs using different predicates: 36 | 37 | - `run_from_file(FileName, Input, Output)`: `FileName` is an atom (i.e. between single quotes `'`) representing the file containing your Brachylog code. For example: `run_from_file('code.brachylog',"Test Input",Z)`. 38 | 39 | - `run_from_atom(Code, Input, Output)`: `Code` is an atom (i.e. between single quotes `'`) containing your Brachylog code. For example: `run_from_atom('∧"Hello, World!"w',_,_)`. Note that you will have to escape certain characters in `Code`. 40 | 41 | - `run(Input, Output)`: This will run a Brachylog program that has already been transpiled to Prolog using either of the two previous predicates. More precisely, this will query `brachylog_main/2` in the file `compiled_brachylog.pl`. 42 | 43 | The first two predicates will transpile your Brachylog program into Prolog, subsequently generating a file called `compiled_brachylog.pl` in the same directory that contains `brachylog.pl`. The three run predicates will then consult it and query `brachylog_main/3`. 44 | 45 | Note that the first two run predicates also exist with either no `Output` argument, or with no `Input` nor `Output` argument, if necessary. For example, `run_from_file('code.brachylog')` is equivalent to `run_from_file('code.brachylog', _, _)`. 46 | 47 | 48 | ### Contributors 49 | 50 | - Julien Cumin - [@JCumin](https://github.com/JCumin) 51 | 52 | - Markus Triska - [@triska](https://github.com/triska) 53 | 54 | - ais523 55 | 56 | - [@UnrelatedString](https://github.com/UnrelatedString) 57 | -------------------------------------------------------------------------------- /src/constraint_variables.pl: -------------------------------------------------------------------------------- 1 | /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 2 | ____ ____ 3 | \ \ / / 4 | \ \ ____ / / 5 | \ \/ \/ / 6 | \ /\ / BRACHYLOG 7 | \ / \ / A terse declarative logic programming language 8 | / \ / \ 9 | / \/ \ Written by Julien Cumin - 2017 10 | / /\____/\ \ https://github.com/JCumin/Brachylog 11 | / / ___ \ \ 12 | /___/ /__/ \___\ 13 | 14 | - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ 15 | 16 | 17 | :- module(constraint_variables, [constraintA/1, 18 | constraintB/1, 19 | constraintC/1, 20 | constraintD/1, 21 | constraintE/1, 22 | constraintF/1, 23 | constraintG/1, 24 | constraintH/1, 25 | constraintI/1, 26 | constraintJ/1, % Unused 27 | constraintK/1, % Unused 28 | constraintL/1, % Unused 29 | constraintM/1, 30 | constraintN/1, 31 | constraintO/1, 32 | constraintP/1, 33 | constraintQ/1, % Unused 34 | constraintR/1, 35 | constraintS/1, 36 | constraintT/1, 37 | constraintU/1, % Unused 38 | constraintV/1, % Unused 39 | constraintW/1, 40 | constraintX/1, 41 | constraintY/1, 42 | constraintZ/1 43 | ]). 44 | 45 | :- use_module(library(clpfd)). 46 | :- use_module(utils). 47 | 48 | 49 | /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 50 | CONSTRAINT[A-Z]/1 51 | - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ 52 | constraintA(_) :- 53 | true. 54 | 55 | 56 | constraintB(_) :- 57 | true. 58 | 59 | 60 | constraintC([_,_]). 61 | 62 | 63 | constraintD('integer':X) :- 64 | X in 0..9. 65 | 66 | 67 | constraintE([]). 68 | 69 | 70 | constraintF(_) :- 71 | true. 72 | 73 | 74 | constraintG(_) :- 75 | true. 76 | 77 | 78 | constraintH(_) :- 79 | true. 80 | 81 | 82 | constraintI('integer':X) :- 83 | X in inf..sup. 84 | 85 | 86 | constraintJ(_) :- % Unused 87 | true. 88 | 89 | 90 | constraintK(_) :- % Unused 91 | true. 92 | 93 | 94 | constraintL(_) :- % Unused 95 | true. 96 | 97 | 98 | constraintM([_,_|_]). 99 | 100 | 101 | constraintN(_) :- 102 | true. 103 | 104 | 105 | constraintO([_]). 106 | 107 | 108 | constraintP(_) :- 109 | true. 110 | 111 | 112 | constraintQ(_) :- % Unused 113 | true. 114 | 115 | 116 | constraintR(_) :- 117 | true. 118 | 119 | 120 | constraintS('string':_). 121 | 122 | 123 | constraintT([_,_,_]). 124 | 125 | 126 | constraintU(_) :- % Unused 127 | true. 128 | 129 | 130 | constraintV(_) :- % Unused 131 | true. 132 | 133 | 134 | constraintW(_) :- 135 | true. 136 | 137 | 138 | constraintX(_) :- 139 | true. 140 | 141 | 142 | constraintY(_) :- 143 | true. 144 | 145 | 146 | constraintZ(_) :- 147 | true. 148 | -------------------------------------------------------------------------------- /src/utils.pl: -------------------------------------------------------------------------------- 1 | /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 2 | ____ ____ 3 | \ \ / / 4 | \ \ ____ / / 5 | \ \/ \/ / 6 | \ /\ / BRACHYLOG 7 | \ / \ / A terse declarative logic programming language 8 | / \ / \ 9 | / \/ \ Written by Julien Cumin - 2017 10 | / /\____/\ \ https://github.com/JCumin/Brachylog 11 | / / ___ \ \ 12 | /___/ /__/ \___\ 13 | 14 | - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ 15 | 16 | 17 | :- module(utils, [integer_value/2, 18 | brachylog_prolog_variable/2, 19 | length_/2, 20 | prepend_string/2, 21 | prepend_integer/2, 22 | is_brachylog_list/1, 23 | single_atom_code/2, 24 | ceiled_square_root/2, 25 | scompare/4, 26 | if_/3, 27 | (=)/3, 28 | (#>)/3, 29 | (===)/6 30 | ]). 31 | 32 | :- use_module(library(clpfd)). 33 | 34 | 35 | /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 36 | INTEGER_VALUE 37 | - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ 38 | integer_value('integer':Sign:I, E) :- 39 | integer_value('integer':Sign:I, 0, E, E). 40 | 41 | integer_value('integer':Sign:[], N0, N, _) :- 42 | ( Sign = 'positive', 43 | N #= N0 44 | ; Sign = 'negative', 45 | N #= - N0 46 | ). 47 | integer_value('integer':Sign:[H], N0, N, M) :- 48 | H in 0..9, 49 | N1 #= H + N0 * 10, 50 | abs(M) #>= abs(N1), 51 | integer_value('integer':Sign:[], N1, N, M). 52 | integer_value('integer':Sign:[H,I|T], N0, N, M) :- 53 | H in 0..9, 54 | N1 #= H + N0 * 10, 55 | abs(M) #>= abs(N1), 56 | integer_value('integer':Sign:[I|T], N1, N, M). 57 | 58 | 59 | /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 60 | BRACHYLOG_PROLOG_VARIABLE 61 | - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ 62 | brachylog_prolog_variable('integer':I, I) :- !. 63 | brachylog_prolog_variable('float':F, F) :- !. 64 | brachylog_prolog_variable('string':S, String) :- !, 65 | escape_string_list(S, T), 66 | atomic_list_concat(T, U), 67 | atomic_list_concat(['"',U,'"'], A), 68 | term_to_atom(String, A). 69 | brachylog_prolog_variable(List, PrologList) :- 70 | is_list(List), 71 | maplist(brachylog_prolog_variable, List, PrologList). 72 | 73 | escape_string_list([], []). 74 | escape_string_list(['"'|T], ['\\','"'|T2]) :- 75 | escape_string_list(T, T2). 76 | escape_string_list(['\\'|T], ['\\','\\'|T2]) :- 77 | escape_string_list(T, T2). 78 | escape_string_list([H|T], [H|T2]) :- 79 | H \= '"', 80 | H \= '\\', 81 | escape_string_list(T, T2). 82 | 83 | 84 | /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 85 | LENGTH_ 86 | - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ 87 | length_(Length, List) :- 88 | length(List, Length). 89 | 90 | 91 | /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 92 | PREPEND_STRING 93 | - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ 94 | prepend_string(S, 'string':S). 95 | 96 | 97 | /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 98 | PREPEND_INTEGER 99 | - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ 100 | prepend_integer(I, 'integer':I). 101 | 102 | 103 | /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 104 | IS_BRACHYLOG_LIST 105 | - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ 106 | is_brachylog_list([]). 107 | is_brachylog_list([_|_]). 108 | 109 | 110 | /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 111 | SINGLE_ATOM_CODE 112 | - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ 113 | single_atom_code(A, C) :- 114 | catch(atom_codes(A, [C]), _, false). 115 | 116 | 117 | /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 118 | CEILED_SQUARE_ROOT 119 | - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ 120 | ceiled_square_root(0, 0). 121 | ceiled_square_root(N0, Root) :- 122 | N1 #= N0 - 1, 123 | Max in 0..N1, 124 | R0^2 #= Max, 125 | Root #= Root0 + 1, 126 | fd_sup(R0, Root0). 127 | 128 | 129 | /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 130 | SCOMPARE 131 | - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ 132 | scompare(@>, TypeX:X, TypeY:Y, TypeZ:Z) :- 133 | ( X @> Y -> 134 | TypeZ:Z = TypeX:X 135 | ; TypeZ:Z = TypeY:Y 136 | ). 137 | scompare(@<, TypeX:X, TypeY:Y, TypeZ:Z) :- 138 | ( X @< Y -> 139 | TypeZ:Z = TypeX:X 140 | ; TypeZ:Z = TypeY:Y 141 | ). 142 | 143 | 144 | /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 145 | IF_/3 146 | Credits to Ulrich Neumerkel 147 | See: http://www.complang.tuwien.ac.at/ulrich/Prolog-inedit/sicstus/reif.pl 148 | - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ 149 | if_(If_1, Then_0, Else_0) :- 150 | call(If_1, T), 151 | ( T == true -> Then_0 152 | ; T == false -> Else_0 153 | ; nonvar(T) -> throw(error(type_error(boolean,T), 154 | type_error(call(If_1,T),2,boolean,T))) 155 | ; throw(error(instantiation_error,instantiation_error(call(If_1,T),2))) 156 | ). 157 | 158 | 159 | /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 160 | (=)/3 161 | Credits to Ulrich Neumerkel 162 | See: http://www.complang.tuwien.ac.at/ulrich/Prolog-inedit/sicstus/reif.pl 163 | - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ 164 | =(X, Y, T) :- 165 | ( X == Y -> T = true 166 | ; X \= Y -> T = false 167 | ; T = true, X = Y 168 | ; T = false, 169 | dif(X, Y) 170 | ). 171 | 172 | 173 | /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 174 | (#>)/3 175 | - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ 176 | #>(X, Y, T) :- 177 | zcompare(C, X, Y), 178 | greater_true(C, T). 179 | 180 | greater_true(>, true). 181 | greater_true(<, false). 182 | greater_true(=, false). 183 | 184 | 185 | /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 186 | (===)/6 187 | - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ 188 | ===(X1, Y1, X2, Y2, T1, T) :- 189 | ( X1 == Y1 -> T1 = true, T = true 190 | ; X1 \= Y1 -> T1 = true, T = false 191 | ; X2 == Y2 -> T1 = false, T = true 192 | ; X2 \= Y2 -> T1 = false, T = false 193 | ; T1 = true, T = true, X1 = Y1 194 | ; T1 = true, T = false, dif(X1, Y1) 195 | ). 196 | -------------------------------------------------------------------------------- /src/brachylog.pl: -------------------------------------------------------------------------------- 1 | /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 2 | ____ ____ 3 | \ \ / / 4 | \ \ ____ / / 5 | \ \/ \/ / 6 | \ /\ / BRACHYLOG 7 | \ / \ / A terse declarative logic programming language 8 | / \ / \ 9 | / \/ \ Written by Julien Cumin - 2017 10 | / /\____/\ \ https://github.com/JCumin/Brachylog 11 | / / ___ \ \ 12 | /___/ /__/ \___\ 13 | 14 | - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ 15 | 16 | 17 | :- use_module(transpile). 18 | :- use_module(symbols). 19 | :- use_module(utils). 20 | :- use_module(predicates). 21 | :- use_module(metapredicates). 22 | :- use_module(constraint_variables). 23 | 24 | 25 | /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 26 | RUN_FROM_FILE 27 | - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ 28 | run_from_file(FilePath) :- 29 | run_from_file(FilePath, 'ignore', 'ignore'). 30 | run_from_file(FilePath, Input) :- 31 | run_from_file(FilePath, Input, 'ignore'). 32 | run_from_file(FilePath, Input, Output) :- 33 | read_file(FilePath, Code), 34 | !, 35 | run_from_atom(Code, Input, Output). 36 | 37 | 38 | /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 39 | RUN_FROM_ATOM 40 | - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ 41 | run_from_atom(Code) :- 42 | run_from_atom(Code, 'ignore', 'ignore'). 43 | run_from_atom(Code, Input) :- 44 | run_from_atom(Code, Input, 'ignore'). 45 | run_from_atom(Code, Input, Output) :- 46 | parse(Code, 'compiled_brachylog.pl'), 47 | !, 48 | run(Input, Output). 49 | 50 | 51 | /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 52 | RUN 53 | - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ 54 | run(Input, Output) :- 55 | set_prolog_flag(answer_write_options, [quoted(true), 56 | portray(true), 57 | max_depth(10), 58 | spacing(next_argument), 59 | max_depth(0)]), 60 | set_prolog_flag(print_write_options, [portray(true), 61 | quoted(true), 62 | numbervars(true), 63 | max_depth(0)]), 64 | consult('compiled_brachylog.pl'), 65 | ( \+ var(Input), 66 | Input \= 'ignore', 67 | parse_argument(Input, ParsedInput) 68 | ; true 69 | ), 70 | ( \+ var(Output), 71 | Output \= 'ignore', 72 | parse_argument(Output, ParsedOutput) 73 | ; true 74 | ), 75 | !, 76 | call(brachylog_main, _, _, ParsedInput, ParsedOutput), 77 | ( var(Input) -> 78 | brachylog_prolog_variable(ParsedInput, Input) 79 | ; true 80 | ), 81 | ( var(Output) -> 82 | brachylog_prolog_variable(ParsedOutput, Output) 83 | ; true 84 | ). 85 | 86 | 87 | /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 88 | RUN_FROM_FILES_NO_FILE 89 | - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ 90 | run_from_files_no_file(FilePath, InputPath, OutputPath) :- 91 | read_file(FilePath, Atom), 92 | !, 93 | ( read_file(InputPath, Input), 94 | Input \= '' 95 | ; Input = 'ignore' 96 | ), 97 | !, 98 | ( read_file(OutputPath, Output), 99 | Output \= '' 100 | ; Output = 'ignore' 101 | ), 102 | !, 103 | parse_no_file(Atom, Predicates), 104 | !, 105 | ( contains_write(Atom) -> 106 | ContainsWrite = 'yes' 107 | ; ContainsWrite = 'no' 108 | ), 109 | !, 110 | set_prolog_flag(answer_write_options, [quoted(true), 111 | portray(true), 112 | max_depth(10), 113 | spacing(next_argument), 114 | max_depth(0)]), 115 | set_prolog_flag(print_write_options, [portray(true), 116 | quoted(true), 117 | numbervars(true), 118 | max_depth(0)]), 119 | maplist(atomic_list_concat, Predicates, ConcatenatedPredicates), 120 | maplist(read_term_from_atom_, ConcatenatedPredicates, AssertablePredicates), 121 | maplist(assertz, AssertablePredicates), 122 | ( Input \= 'ignore', 123 | parse_argument(Input, ParsedInput), 124 | \+ var(ParsedInput), 125 | ReportInput = 'no' 126 | ; Input == 'ignore', 127 | ReportInput = 'no' 128 | ; ReportInput = 'yes', 129 | true 130 | ), 131 | ( Output \= 'ignore', 132 | parse_argument(Output, ParsedOutput), 133 | \+ var(ParsedOutput), 134 | ReportOutput = 'no' 135 | ; Output == 'ignore', 136 | ReportOutput = 'no' 137 | ; ReportOutput = 'yes', 138 | true 139 | ), 140 | !, 141 | ( call(brachylog_main, _, _, ParsedInput, ParsedOutput) -> 142 | ( ReportInput = 'yes' -> 143 | brachylog_prolog_variable(ParsedInput, InputProlog) 144 | ; true 145 | ), 146 | ( ReportOutput = 'yes' -> 147 | brachylog_prolog_variable(ParsedOutput, OutputProlog) 148 | ; true 149 | ), 150 | ( ReportInput = 'yes', 151 | Bindings = [Input=InputProlog] 152 | ; Bindings = [] 153 | ), 154 | ( ReportOutput = 'yes', 155 | BindingsFinal = [Output=OutputProlog|Bindings] 156 | ; BindingsFinal = Bindings, 157 | true 158 | ), 159 | ( (ReportInput = 'yes' ; ReportOutput = 'yes'), 160 | write('\n') 161 | ; true 162 | ), 163 | reverse(BindingsFinal, RBindings), 164 | report_bindings(RBindings), 165 | ( ReportInput = 'no', 166 | ReportOutput = 'no', 167 | ContainsWrite = 'no', 168 | write('true.') 169 | ; true 170 | ) 171 | ; ( ContainsWrite = 'no', 172 | write('false.') 173 | ; true 174 | ) 175 | ). 176 | 177 | read_term_from_atom_(A, B) :- 178 | read_term_from_atom(A, B, []). 179 | 180 | % Credits to M. Triska 181 | % See: http://stackoverflow.com/a/38284692/2554145 182 | report_bindings(NameVars) :- 183 | phrase(bindings(NameVars), Bs), 184 | format("~s", [Bs]). 185 | 186 | bindings([]) --> []. 187 | bindings([E]) --> name_var(E). 188 | bindings([E1,E2|Rest]) --> name_var(E1), ",\n", bindings([E2|Rest]). 189 | 190 | name_var(Name=Var) --> 191 | format_("~w = ~q", [Name,Var]). 192 | 193 | format_(Format, Ls) --> 194 | call(format_codes(Format, Ls)). 195 | 196 | format_codes(Format, Ls, Cs0, Cs) :- 197 | format(codes(Cs0, Cs), Format, Ls). 198 | 199 | 200 | /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 201 | READ_FILE 202 | - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ 203 | read_file(FilePath, Code) :- 204 | ( exists_file(FilePath), 205 | open(FilePath, read, File), 206 | read_file_(File, Chars), 207 | close(File), 208 | atomic_list_concat(Chars, Code) 209 | ; throw('The file does not exist.') 210 | ), 211 | !. 212 | 213 | read_file_(File, []) :- 214 | at_end_of_stream(File). 215 | read_file_(File, [H|T]) :- 216 | \+ at_end_of_stream(File), 217 | get_char(File, H), 218 | read_file_(File, T). 219 | -------------------------------------------------------------------------------- /src/symbols.pl: -------------------------------------------------------------------------------- 1 | /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 2 | ____ ____ 3 | \ \ / / 4 | \ \ ____ / / 5 | \ \/ \/ / 6 | \ /\ / BRACHYLOG 7 | \ / \ / A terse declarative logic programming language 8 | / \ / \ 9 | / \/ \ Written by Julien Cumin - 2017 10 | / /\____/\ \ https://github.com/JCumin/Brachylog 11 | / / ___ \ \ 12 | /___/ /__/ \___\ 13 | 14 | - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ 15 | 16 | 17 | :- module(symbols, [token_predicate/2, 18 | token_variable/2, 19 | token_metapredicate/2 20 | ]). 21 | 22 | 23 | /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 24 | TOKEN_PREDICATE 25 | - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ 26 | token_predicate('≤', 'brachylog_lessequal'). 27 | token_predicate('≥', 'brachylog_greaterequal'). 28 | token_predicate('∈', 'brachylog_contains'). 29 | token_predicate('∋', 'brachylog_in'). 30 | token_predicate('⊆', 'brachylog_superset'). 31 | token_predicate('⊇', 'brachylog_subset'). 32 | token_predicate('↔', 'brachylog_reverse'). 33 | token_predicate('↰', 'brachylog_call_predicate'). 34 | token_predicate('↺', 'brachylog_circular_permute_counterclockwise'). 35 | token_predicate('↻', 'brachylog_circular_permute_clockwise'). 36 | token_predicate('√', 'brachylog_root'). 37 | token_predicate('⌉', 'brachylog_ceil'). 38 | token_predicate('⌋', 'brachylog_floor'). 39 | token_predicate('⟦', 'brachylog_range_ascending'). 40 | token_predicate('⟧', 'brachylog_range_descending'). 41 | token_predicate('ℕ', 'brachylog_natural_integer'). 42 | token_predicate('ℤ', 'brachylog_integer'). 43 | token_predicate('ℝ', 'brachylog_float'). 44 | token_predicate('≠', 'brachylog_different'). 45 | token_predicate('≡', 'brachylog_identity'). 46 | token_predicate('÷', 'brachylog_integer_division'). 47 | token_predicate('×', 'brachylog_multiply'). 48 | token_predicate('%', 'brachylog_modulo'). 49 | token_predicate('*', 'brachylog_exp'). 50 | token_predicate('+', 'brachylog_plus'). 51 | token_predicate('-', 'brachylog_minus'). 52 | token_predicate('/', 'brachylog_divide'). 53 | token_predicate('<', 'brachylog_less'). 54 | token_predicate('=', 'brachylog_equal'). 55 | token_predicate('>', 'brachylog_greater'). 56 | token_predicate('\\', 'brachylog_transpose'). 57 | token_predicate('^', 'brachylog_power'). 58 | token_predicate('≜', 'brachylog_label'). 59 | 60 | token_predicate('a', 'brachylog_adfix'). 61 | token_predicate('b', 'brachylog_behead'). 62 | token_predicate('c', 'brachylog_concatenate'). 63 | token_predicate('d', 'brachylog_duplicates'). 64 | token_predicate('e', ''). 65 | token_predicate('f', 'brachylog_factors'). 66 | token_predicate('g', 'brachylog_group'). 67 | token_predicate('h', 'brachylog_head'). 68 | token_predicate('i', 'brachylog_index'). 69 | token_predicate('j', 'brachylog_juxtapose'). 70 | token_predicate('k', 'brachylog_knife'). 71 | token_predicate('l', 'brachylog_length'). 72 | token_predicate('m', ''). 73 | token_predicate('n', ''). 74 | token_predicate('o', 'brachylog_order'). 75 | token_predicate('p', 'brachylog_permute'). 76 | token_predicate('q', ''). 77 | token_predicate('r', ''). 78 | token_predicate('s', 'brachylog_substring'). 79 | token_predicate('t', 'brachylog_tail'). 80 | token_predicate('u', ''). 81 | token_predicate('v', ''). 82 | token_predicate('w', 'brachylog_write'). 83 | token_predicate('x', 'brachylog_xterminate'). 84 | token_predicate('y', ''). 85 | token_predicate('z', 'brachylog_zip'). 86 | 87 | token_predicate('ạ', 'brachylog_to_codes'). 88 | token_predicate('ḅ', 'brachylog_blocks'). 89 | token_predicate('ḍ', 'brachylog_dichotomize'). 90 | token_predicate('ẹ', 'brachylog_elements'). 91 | token_predicate('ḥ', ''). 92 | token_predicate('ị', 'brachylog_to_number'). 93 | token_predicate('ḳ', ''). 94 | token_predicate('ḷ', 'brachylog_lowercase'). 95 | token_predicate('ṃ', ''). 96 | token_predicate('ṇ', 'brachylog_split_lines'). 97 | token_predicate('ọ', 'brachylog_occurences'). 98 | token_predicate('ṛ', 'brachylog_random_element'). 99 | token_predicate('ṣ', 'brachylog_shuffle'). 100 | token_predicate('ṭ', ''). 101 | token_predicate('ụ', 'brachylog_uppercase'). 102 | token_predicate('ṿ', ''). 103 | token_predicate('ẉ', 'brachylog_writeln'). 104 | token_predicate('ỵ', ''). 105 | token_predicate('ẓ', ''). 106 | 107 | token_predicate('ȧ', 'brachylog_absolute_value'). 108 | token_predicate('ḃ', 'brachylog_base'). 109 | token_predicate('ċ', 'brachylog_coerce'). 110 | token_predicate('ḋ', 'brachylog_prime_decomposition'). 111 | token_predicate('ė', ''). 112 | token_predicate('ḟ', 'brachylog_factorial'). 113 | token_predicate('ġ', 'brachylog_groups'). 114 | token_predicate('ḣ', ''). 115 | token_predicate('ṁ', 'brachylog_matrix'). 116 | token_predicate('ṅ', 'brachylog_negate'). 117 | token_predicate('ȯ', ''). 118 | token_predicate('ṗ', 'brachylog_prime'). 119 | token_predicate('ṙ', 'brachylog_random_number'). 120 | token_predicate('ṡ', 'brachylog_sign'). 121 | token_predicate('ṫ', 'brachylog_to_string'). 122 | token_predicate('ẇ', ''). 123 | token_predicate('ẋ', 'brachylog_cartesian_product'). 124 | token_predicate('ẏ', ''). 125 | token_predicate('ż', ''). 126 | 127 | 128 | /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 129 | TOKEN_VARIABLE 130 | - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ 131 | token_variable('Ạ', '\'string\':[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]'). 132 | token_variable('Ḅ', '\'string\':[b,c,d,f,g,h,j,k,l,m,n,p,q,r,s,t,v,w,x,y,z]'). 133 | %token_variable('', ''). 134 | token_variable('Ḍ', '\'string\':[b,c,d,f,g,h,j,k,l,m,n,p,q,r,s,t,v,w,x,z]'). 135 | token_variable('Ẹ', '\'string\':[]'). 136 | %token_variable('', ''). 137 | %token_variable('', ''). 138 | token_variable('Ḥ', '\'string\':[\'H\',e,l,l,o,\',\',\' \',\'W\',o,r,l,d,\'!\']'). 139 | token_variable('Ị', '\'string\':[\'0\',\'1\',\'2\',\'3\',\'4\',\'5\',\'6\',\'7\',\'8\',\'9\']'). 140 | %token_variable('', ''). 141 | token_variable('Ḳ', ''). 142 | token_variable('Ḷ', '\'string\':[\'\n\']'). 143 | token_variable('Ṃ', ''). 144 | token_variable('Ṇ', '\'string\':[\'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\',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,0,1,2,3,4,5,6,7,8,9]'). 145 | token_variable('Ọ', ''). 146 | %token_variable('', ''). 147 | %token_variable('', ''). 148 | token_variable('Ṛ', ''). 149 | token_variable('Ṣ', '\'string\':[\' \']'). 150 | token_variable('Ṭ', '\'string\':[\' \',\'!\',\'"\',\'#\',\'$\',\'%\',\'&\',\'\\\'\',\'(\',\')\',\'*\',\'+\',\',\',\'-\',\'.\',\'/\',\'0\',\'1\',\'2\',\'3\',\'4\',\'5\',\'6\',\'7\',\'8\',\'9\',\':\',\';\',\'<\',\'=\',\'>\',\'?\',\'@\',\'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\',\'[\',\'\\\\\',\']\',\'^\',\'_\',\'`\',\'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\',\'{\',\'|\',\'}\',\'~\']'). 151 | token_variable('Ụ', ''). 152 | token_variable('Ṿ', '\'string\':[a,e,i,o,u]'). 153 | token_variable('Ẉ', '\'string\':[a,e,i,o,u,y]'). 154 | %token_variable('', ''). 155 | token_variable('Ỵ', ''). 156 | token_variable('Ẓ', '\'string\':[z,y,x,w,v,u,t,s,r,q,p,o,n,m,l,k,j,i,h,g,f,e,d,c,b,a]'). 157 | 158 | token_variable('Ȧ', 'ConstraintA'). 159 | token_variable('Ḃ', 'ConstraintB'). 160 | token_variable('Ċ', 'ConstraintC'). 161 | token_variable('Ḋ', 'ConstraintD'). 162 | token_variable('Ė', 'ConstraintE'). 163 | token_variable('Ḟ', 'ConstraintF'). 164 | token_variable('Ġ', 'ConstraintG'). 165 | token_variable('Ḣ', 'ConstraintH'). 166 | token_variable('İ', 'ConstraintI'). 167 | %token_variable('', 'ConstraintJ'). 168 | %token_variable('', 'ConstraintK'). 169 | %token_variable('', 'ConstraintL'). 170 | token_variable('Ṁ', 'ConstraintM'). 171 | token_variable('Ṅ', 'ConstraintN'). 172 | token_variable('Ȯ', 'ConstraintO'). 173 | token_variable('Ṗ', 'ConstraintP'). 174 | %token_variable('', 'ConstraintQ'). 175 | token_variable('Ṙ', 'ConstraintR'). 176 | token_variable('Ṡ', 'ConstraintS'). 177 | token_variable('Ṫ', 'ConstraintT'). 178 | %token_variable('', 'ConstraintU'). 179 | %token_variable('', 'ConstraintV'). 180 | token_variable('Ẇ', 'ConstraintW'). 181 | token_variable('Ẋ', 'ConstraintX'). 182 | token_variable('Ẏ', 'ConstraintY'). 183 | token_variable('Ż', 'ConstraintZ'). 184 | 185 | token_variable('π', '\'float\':3.14159265359'). 186 | token_variable('φ', '\'float\':1.61803398875'). 187 | 188 | /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 189 | TOKEN_METAPREDICATE 190 | - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ 191 | token_metapredicate('ᵃ', 'brachylog_meta_accumulate'). 192 | token_metapredicate('ᵇ', 'brachylog_meta_bagof'). 193 | token_metapredicate('ᶜ', 'brachylog_meta_count'). 194 | token_metapredicate('ᵈ', 'brachylog_meta_declare'). 195 | token_metapredicate('ᵉ', 'brachylog_meta_existence'). 196 | token_metapredicate('ᶠ', 'brachylog_meta_find'). 197 | token_metapredicate('ᵍ', 'brachylog_meta_groupby'). 198 | token_metapredicate('ʰ', 'brachylog_meta_head'). 199 | token_metapredicate('ⁱ', 'brachylog_meta_iterate'). 200 | token_metapredicate('ʲ', ''). 201 | token_metapredicate('ᵏ', ''). 202 | token_metapredicate('ˡ', 'brachylog_meta_leftfold'). 203 | token_metapredicate('ᵐ', 'brachylog_meta_map'). 204 | token_metapredicate('ⁿ', 'brachylog_meta_nonexistence'). 205 | token_metapredicate('ᵒ', 'brachylog_meta_orderby'). 206 | token_metapredicate('ᵖ', ''). 207 | token_metapredicate('ʳ', 'brachylog_meta_rightfold'). 208 | token_metapredicate('ˢ', 'brachylog_meta_select'). 209 | token_metapredicate('ᵗ', 'brachylog_meta_tail'). 210 | token_metapredicate('ᵘ', 'brachylog_meta_unique'). 211 | token_metapredicate('ᵛ', 'brachylog_meta_verify'). 212 | token_metapredicate('ʷ', ''). 213 | token_metapredicate('ˣ', ''). 214 | token_metapredicate('ʸ', ''). 215 | token_metapredicate('ᶻ', 'brachylog_meta_zip'). 216 | -------------------------------------------------------------------------------- /src/tokenize.pl: -------------------------------------------------------------------------------- 1 | /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 2 | ____ ____ 3 | \ \ / / 4 | \ \ ____ / / 5 | \ \/ \/ / 6 | \ /\ / BRACHYLOG 7 | \ / \ / A terse declarative logic programming language 8 | / \ / \ 9 | / \/ \ Written by Julien Cumin - 2017 10 | / /\____/\ \ https://github.com/JCumin/Brachylog 11 | / / ___ \ \ 12 | /___/ /__/ \___\ 13 | 14 | - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ 15 | 16 | 17 | :- module(tokenize, [tokenize/2]). 18 | 19 | :- use_module(symbols). 20 | 21 | 22 | /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 23 | TOKENIZE 24 | - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ 25 | tokenize([], []). 26 | tokenize([' '|T], T2) :- 27 | tokenize(T, T2). 28 | tokenize([Variable|T], ['variable':VariableName:'sup':Sup|T2]) :- 29 | is_variable_character(Variable), 30 | tokenize_variable([Variable|T], Rest, VariableName), 31 | tokenize_superscript(Rest, Rest2, Sup), 32 | tokenize(Rest2, T2). 33 | tokenize([Variable|T], ['variable':R|T2]) :- 34 | ( is_variable_character_dot_above(Variable) 35 | -> token_variable(Variable, RealVariable), 36 | tokenize_superscript(T, Rest, Sup), 37 | R = RealVariable:'sup':Sup 38 | ; is_variable_character_dot_below(Variable) 39 | -> token_variable(Variable, R), 40 | Rest = T 41 | ), 42 | tokenize(Rest, T2). 43 | tokenize([Variable|T], ['variable':RealVariable|T2]) :- 44 | is_math_constant_character(Variable), 45 | token_variable(Variable, RealVariable), 46 | tokenize(T, T2). 47 | tokenize([H|T], ['variable':'Input':'sup':Sup|T2]) :- 48 | is_input_character(H), 49 | tokenize_superscript(T, Rest, Sup), 50 | tokenize(Rest, T2). 51 | tokenize([H|T], ['variable':'Output':'sup':Sup|T2]) :- 52 | is_output_character(H), 53 | tokenize_superscript(T, Rest, Sup), 54 | tokenize(Rest, T2). 55 | tokenize([Modifier,Predicate|T], ['predicate':PredName:Sub|T2]) :- 56 | is_modifier_character(Modifier), 57 | \+ (is_variable_character(Predicate)), 58 | atomic_list_concat([Modifier,Predicate], Pred), 59 | token_predicate(Pred, PredName), 60 | tokenize_subscript(T, Rest, Sub), 61 | tokenize(Rest, T2). 62 | tokenize([Predicate|T], ['predicate':PredName:Sub|T2]) :- 63 | is_predicate_character(Predicate), 64 | token_predicate(Predicate, PredName), 65 | tokenize_subscript(T, Rest, Sub), 66 | tokenize(Rest, T2). 67 | tokenize([MetaPred|T], ['metapredicate':PredName:Sup|T2]) :- 68 | is_metapredicate_character(MetaPred), 69 | token_metapredicate(MetaPred, PredName), 70 | tokenize_superscript(T, Rest, Sup), 71 | tokenize(Rest, T2). 72 | tokenize(['"'|T], ['variable':Variable|T2]) :- 73 | tokenize_string(['"'|T], Rest, Variable), 74 | tokenize(Rest, T2). 75 | tokenize(['_',Digit|T], ['variable':Type:N|T2]) :- 76 | is_digit_character(Digit), 77 | tokenize_number([Digit|T] ,Rest, Type:X), 78 | N is -X, 79 | tokenize(Rest, T2). 80 | tokenize(['_','_'|T], T2) :- 81 | tokenize(T, T2). 82 | tokenize([Digit|T], ['variable':Type:X|T2]) :- 83 | is_digit_character(Digit), 84 | tokenize_number([Digit|T], Rest, Type:X), 85 | tokenize(Rest, T2). 86 | tokenize(['['|T], ['variable':List|T2]) :- 87 | tokenize_list(['['|T], Rest, List), 88 | tokenize(Rest, T2). 89 | tokenize([Modifier,Variable|T], ['variable':RealVariable|T2]) :- 90 | is_modifier_character(Modifier), 91 | is_variable_character(Variable), 92 | token_variable(Modifier:Variable, RealVariable), 93 | tokenize(T, T2). 94 | tokenize([ControlFlow|T], ['control':ControlFlow|T2]) :- 95 | is_control_character(ControlFlow), 96 | tokenize(T, T2). 97 | 98 | 99 | /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 100 | TOKENIZE_VARIABLE 101 | - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ 102 | tokenize_variable([], [], ''). 103 | tokenize_variable([H|T], R, Name) :- 104 | ( is_variable_character(H) -> 105 | tokenize_variable(T, R, TName), 106 | atomic_list_concat([H, TName], Name) 107 | ; Name = '', 108 | R = [H|T] 109 | ). 110 | 111 | 112 | /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 113 | TOKENIZE_STRING 114 | - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ 115 | tokenize_string(['"'|T], Rest, 'string':T2) :- 116 | tokenize_string_(T, Rest, T2). 117 | 118 | tokenize_string_([], [], []). 119 | tokenize_string_([X,'"'|Rest], Rest, [X]) :- 120 | X \= '\\', 121 | X \= '"', 122 | Rest \= ['"'|_], 123 | !. 124 | tokenize_string_(['\\','"'|T], Rest, ['"'|T2]) :- 125 | tokenize_string_(T, Rest, T2). 126 | tokenize_string_(['"','"'|T], Rest, ['"'|T2]) :- 127 | tokenize_string_(T, Rest, T2). 128 | tokenize_string_([X|T], Rest, L) :- 129 | ( X \= '"' -> 130 | L = [X|T2], 131 | tokenize_string_(T, Rest, T2) 132 | ; Rest = T, 133 | L = [] 134 | ). 135 | 136 | 137 | /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 138 | TOKENIZE_NUMBER 139 | - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ 140 | tokenize_number(N, Rest, Type:Number) :- 141 | tokenize_number_(N, Rest, T2), 142 | ( member('.', T2), 143 | !, 144 | Type = 'float' 145 | ; Type = 'integer' 146 | ), 147 | atomic_list_concat(T2, A), 148 | atom_number(A, Number). 149 | 150 | tokenize_number_([], [], []). 151 | tokenize_number_(['.',I|T], Rest, ['.',J|T2]) :- 152 | is_digit_character(I), 153 | atom_number(I, J), 154 | tokenize_integer(T, Rest, T2). 155 | tokenize_number_(['.'], ['.'], []). 156 | tokenize_number_(['.',X|T], ['.',X|T], []) :- 157 | \+ (is_digit_character(X)). 158 | tokenize_number_([X|T], [X|T], []) :- 159 | \+ (is_digit_character(X)), 160 | X \= '.'. 161 | tokenize_number_([I|T], Rest, [J|T2]) :- 162 | is_digit_character(I), 163 | atom_number(I, J), 164 | tokenize_number_(T, Rest, T2). 165 | 166 | tokenize_integer([], [], []). 167 | tokenize_integer([I|T], Rest, [J|T2]) :- 168 | is_digit_character(I), 169 | atom_number(I, J), 170 | tokenize_integer(T, Rest, T2). 171 | tokenize_integer([X|T], [X|T], []) :- 172 | \+ (is_digit_character(X)). 173 | 174 | 175 | /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 176 | TOKENIZE_LIST 177 | - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ 178 | tokenize_list(['['|T], Rest, List) :- 179 | isolate_list(T, L, Rest), 180 | tokenize(L, List). 181 | 182 | isolate_list(T, List, Rest) :- 183 | isolate_list(T, 1, [], L, Rest), 184 | reverse(L, List). 185 | isolate_list([], _, L, L, []). 186 | isolate_list([']'|T], 1, L, L, T). 187 | isolate_list([']'|T], X, L, M, Rest) :- 188 | X > 1, 189 | Y is X - 1, 190 | isolate_list(T, Y, [']'|L], M, Rest). 191 | isolate_list(['['|T], X, L, M, Rest) :- 192 | Y is X + 1, 193 | isolate_list(T, Y, ['['|L], M, Rest). 194 | isolate_list([H|T], X, L, M, Rest) :- 195 | H \= '[', 196 | H \= ']', 197 | isolate_list(T, X, [H|L], M, Rest). 198 | 199 | 200 | /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 201 | TOKENIZE_SUBSCRIPT 202 | - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ 203 | tokenize_subscript(L, Rest, Sub) :- 204 | tokenize_subscript_(L, Rest, LSub), 205 | ( LSub = 'first' -> 206 | Sub = LSub 207 | ; LSub = 'last' -> 208 | Sub = 'last' 209 | ; LSub = [] -> 210 | Sub = 'default' 211 | ; maplist(number_codes, LSub, LC), 212 | append(LC, C), 213 | number_codes(ISub, C), 214 | term_to_atom('integer':ISub, Sub) 215 | ). 216 | 217 | tokenize_subscript_([], [], []). 218 | tokenize_subscript_([H|T], Rest, Ds) :- 219 | ( is_subscript_character(H, D) -> 220 | tokenize_subscript_(T, Rest, TDs), 221 | Ds = [D|TDs] 222 | ; is_subscript_parenthesis(H, D) -> 223 | Rest = T, 224 | Ds = D 225 | ; Rest = [H|T], 226 | Ds = [] 227 | ). 228 | 229 | 230 | /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 231 | TOKENIZE_SUPERSCRIPT 232 | - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ 233 | tokenize_superscript(L, Rest, Sup) :- 234 | tokenize_superscript_(L, Rest, LSup), 235 | ( LSup = 'first' -> 236 | Sup = LSup 237 | ; LSup = 'last' -> 238 | Sup = 'last' 239 | ; LSup = [] -> 240 | Sup = 'default' 241 | ; maplist(number_codes, LSup, LC), 242 | append(LC, C), 243 | number_codes(ISup, C), 244 | term_to_atom('integer':ISup, Sup) 245 | ). 246 | 247 | tokenize_superscript_([], [], []). 248 | tokenize_superscript_([H|T], Rest, Ds) :- 249 | ( is_superscript_character(H, D) -> 250 | tokenize_superscript_(T, Rest, TDs), 251 | Ds = [D|TDs] 252 | ; is_superscript_parenthesis(H, D) -> 253 | Rest = T, 254 | Ds = D 255 | ; Rest = [H|T], 256 | Ds = [] 257 | ). 258 | 259 | 260 | /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 261 | IS_X_CHARACTER 262 | - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ 263 | is_variable_character(X) :- 264 | member(X, ['A', 'B', 'C', 'D', 'E', 265 | 'F', 'G', 'H', 'I', 'J', 266 | 'K', 'L', 'M', 'N', 'O', 267 | 'P', 'Q', 'R', 'S', 'T', 268 | 'U', 'V', 'W', 'X', 'Y', 'Z']). 269 | 270 | is_variable_character_dot_below(X) :- 271 | member(X, ['Ạ', 'Ḅ', 'Ḍ', 'Ẹ', 272 | 'Ḥ', 'Ị', 'Ḳ', 'Ḷ', 273 | 'Ṃ', 'Ṇ', 'Ọ', 'Ṛ', 274 | 'Ṣ', 'Ṭ', 'Ụ', 'Ṿ', 275 | 'Ẉ', 'Ỵ', 'Ẓ']). 276 | 277 | is_variable_character_dot_above(X) :- 278 | member(X, ['Ȧ', 'Ḃ', 'Ċ', 'Ḋ', 'Ė', 279 | 'Ḟ', 'Ġ', 'Ḣ', 'İ', 'Ṁ', 280 | 'Ṅ', 'Ȯ', 'Ṗ', 'Ṙ', 'Ṡ', 281 | 'Ṫ', 'Ẇ', 'Ẋ', 'Ẏ', 'Ż']). 282 | 283 | is_digit_character(X) :- 284 | member(X, ['0', '1', '2', '3', '4', 285 | '5', '6', '7', '8', '9']). 286 | 287 | is_predicate_character(X) :- 288 | member(X, ['≤', '≥', '∈', '∋', '⊆', '⊇', 289 | '↔', '↰', '↺', 290 | '↻', '√', '⌉', '⌋', '⟦', '⟧', 291 | 'ℕ', 'ℤ', 'ℝ', '∅', '≠', '≡', 292 | '÷', '×', '%', '*', '+', 293 | '-', '/', '<', '=', '>', '\\', 294 | '^', 'a', 'b', 'c', 'd', 'e', 295 | 'f', 'g', 'h', 'i', 'j', 'k', 296 | 'l', 'm', 'n', 'o', 'p', 'q', 297 | 'r', 's', 't', 'u', 'v', 'w', 298 | 'x', 'y', 'z', 'ạ', 'ḅ', 'ḍ', 299 | 'ẹ', 'ḥ', 'ị', 'ḳ', 'ḷ', 'ṃ', 300 | 'ṇ', 'ọ', 'ṛ', 'ṣ', 'ṭ', 'ụ', 301 | 'ṿ', 'ẉ', 'ỵ', 'ẓ', 'ȧ', 'ḃ', 302 | 'ċ', 'ḋ', 'ė', 'ḟ', 'ġ', 'ḣ', 303 | 'ṁ', 'ṅ', 'ȯ', 'ṗ', 'ṙ', 'ṡ', 304 | 'ṫ', 'ẇ', 'ẋ', 'ẏ', 'ż', '≜']). 305 | 306 | is_math_constant_character(X) :- 307 | member(X, ['π', 'φ']). 308 | 309 | is_modifier_character(X) :- 310 | member(X, ['$', '@', '#']). 311 | 312 | is_input_character('?'). 313 | 314 | is_output_character('.'). 315 | 316 | is_metapredicate_character(X) :- 317 | member(X, ['ᵃ', 'ᵇ', 'ᶜ', 'ᵈ', 'ᵉ', 318 | 'ᶠ', 'ᵍ', 'ʰ', 'ⁱ', 'ʲ', 319 | 'ᵏ', 'ˡ', 'ᵐ', 'ⁿ', 'ᵒ', 320 | 'ᵖ', 'ʳ', 'ˢ', 'ᵗ', 'ᵘ', 321 | 'ᵛ', 'ʷ', 'ˣ', 'ʸ', 'ᶻ']). 322 | 323 | is_subscript_character(C, D) :- 324 | nth0(D, ['₀','₁','₂','₃','₄', 325 | '₅','₆','₇','₈','₉'], C). 326 | 327 | is_subscript_parenthesis('₍', 'first'). 328 | is_subscript_parenthesis('₎', 'last'). 329 | 330 | is_superscript_character(C, D) :- 331 | nth0(D, ['⁰','¹','²','³','⁴', 332 | '⁵','⁶','⁷','⁸','⁹'], C). 333 | 334 | is_superscript_parenthesis('⁽', 'first'). 335 | is_superscript_parenthesis('⁾', 'last'). 336 | 337 | is_control_character(X) :- 338 | member(X, ['∧', '∨', '⊥', '\n', '!', '↖', '↙', 339 | '\'', '(', ')', ',', ':', 340 | ':', '|', '{', '}', '`', 341 | '¬', '~', ';', '&', '⟨', '⟩']). 342 | -------------------------------------------------------------------------------- /misc/brachylog_logo.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 163 | -------------------------------------------------------------------------------- /src/tests.pl: -------------------------------------------------------------------------------- 1 | /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 2 | ____ ____ 3 | \ \ / / 4 | \ \ ____ / / 5 | \ \/ \/ / 6 | \ /\ / BRACHYLOG 7 | \ / \ / A terse declarative logic programming language 8 | / \ / \ 9 | / \/ \ Written by Julien Cumin - 2017 10 | / /\____/\ \ https://github.com/JCumin/Brachylog 11 | / / ___ \ \ 12 | /___/ /__/ \___\ 13 | 14 | - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ 15 | 16 | 17 | :- consult(brachylog). 18 | 19 | 20 | :- begin_tests(predicates). 21 | 22 | 23 | /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 24 | BRACHYLOG_LESSEQUAL 25 | - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ 26 | test('lessequal_1', all(X == [2])) :- 27 | run_from_atom('1≤2', _, X). 28 | test('lessequal_2', all(X == [2])) :- 29 | run_from_atom('_1≤2', _, X). 30 | test('lessequal_3', all(X == [0])) :- 31 | run_from_atom('0≤0', _, X). 32 | test('lessequal_4', all(X == [13])) :- 33 | run_from_atom('13≤13', _, X). 34 | test('lessequal_5', all(X == [-42])) :- 35 | run_from_atom('_42≤_42', _, X). 36 | test('lessequal_6', all(X == [[1,2,3]])) :- 37 | run_from_atom('[1,2,3]≤₁', _, X). 38 | test('lessequal_7', all(X == [[-1,0,1]])) :- 39 | run_from_atom('[_1,0,1]≤₁', _, X). 40 | test('lessequal_8', all(X == [[-42,-23,-16]])) :- 41 | run_from_atom('[_42,_23,_16]≤₁', _, X). 42 | test('lessequal_9', all(X == [[1,1,3],[1,2,3],[1,3,3]])) :- 43 | run_from_atom('[1,I,3]≤₁', _, X). 44 | test('lessequal_10', fail) :- 45 | run_from_atom('2≤1', _, _). 46 | test('lessequal_11', fail) :- 47 | run_from_atom('2≤_1', _, _). 48 | test('lessequal_12', fail) :- 49 | run_from_atom('[1,3,2]≤₁', _, _). 50 | test('lessequal_13', fail) :- 51 | run_from_atom('[1,I,_1]≤₁', _, _). 52 | 53 | 54 | /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 55 | BRACHYLOG_GREATEREQUAL 56 | - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ 57 | test('greaterequal_1', all(X == [1])) :- 58 | run_from_atom('2≥1', _, X). 59 | test('greaterequal_2', all(X == [-1])) :- 60 | run_from_atom('2≥_1', _, X). 61 | test('greaterequal_3', all(X == [0])) :- 62 | run_from_atom('0≥0', _, X). 63 | test('greaterequal_4', all(X == [13])) :- 64 | run_from_atom('13≥13', _, X). 65 | test('greaterequal_5', all(X == [-42])) :- 66 | run_from_atom('_42≥_42', _, X). 67 | test('greaterequal_6', all(X == [[3,2,1]])) :- 68 | run_from_atom('[3,2,1]≥₁', _, X). 69 | test('greaterequal_7', all(X == [[1,0,-1]])) :- 70 | run_from_atom('[1,0,_1]≥₁', _, X). 71 | test('greaterequal_8', all(X == [[-16,-23,-42]])) :- 72 | run_from_atom('[_16,_23,_42]≥₁', _, X). 73 | test('greaterequal_9', all(X == [[3,1,1],[3,2,1],[3,3,1]])) :- 74 | run_from_atom('[3,I,1]≥₁', _, X). 75 | test('greaterequal_10', fail) :- 76 | run_from_atom('1≥2', _, _). 77 | test('greaterequal_11', fail) :- 78 | run_from_atom('_1≥2', _, _). 79 | test('greaterequal_12', fail) :- 80 | run_from_atom('[1,3,2]≥₁', _, _). 81 | test('greaterequal_13', fail) :- 82 | run_from_atom('[_1,I,1]≥₁', _, _). 83 | 84 | 85 | /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 86 | BRACHYLOG_CONTAINS 87 | - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ 88 | % Nothing, same code as brachylog_in 89 | 90 | 91 | /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 92 | BRACHYLOG_IN 93 | - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ 94 | test('in_1', fail) :- 95 | run_from_atom('∋', [], _). 96 | test('in_2', fail) :- 97 | run_from_atom('∋', "", _). 98 | test('in_3', all(X == [0])) :- 99 | run_from_atom('∋', 0, X). 100 | test('in_4', all(X == [7])) :- 101 | run_from_atom('∋', 7, X). 102 | test('in_5', all(X == [7])) :- 103 | run_from_atom('∋', '_7', X). 104 | test('in_6', all(X == [1,0,2,3])) :- 105 | run_from_atom('∋', 1023, X). 106 | test('in_7', all(X == [1,0,2,3])) :- 107 | run_from_atom('∋', [1,0,2,3], X). 108 | test('in_8', all(X == [1023,"test"])) :- 109 | run_from_atom('∋', [1023,"test"], X). 110 | test('in_9', all(X == ["test"])) :- 111 | run_from_atom('∋', ["test"], X). 112 | test('in_10', all(X == ["t","e","s","t"])) :- 113 | run_from_atom('∋', "test", X). 114 | test('in_11', all(X == [1])) :- 115 | run_from_atom('∋₀', 1023, X). 116 | test('in_12', all(X == ["t"])) :- 117 | run_from_atom('∋₀', "test", X). 118 | test('in_13', all(X == [1023])) :- 119 | run_from_atom('∋₀', [1023,"test"], X). 120 | test('in_14', all(X == [0])) :- 121 | run_from_atom('∋₁', 1023, X). 122 | test('in_15', fail) :- 123 | run_from_atom('∋₄', 1023, _). 124 | 125 | 126 | /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 127 | BRACHYLOG_SUPERSET 128 | - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ 129 | % Nothing, same code as brachylog_subset 130 | 131 | 132 | /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 133 | BRACHYLOG_SUBSET 134 | - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ 135 | test('subset_1', all(X == [[]])) :- 136 | run_from_atom('⊇', [], X). 137 | test('subset_2', all(X == [""])) :- 138 | run_from_atom('⊇', "", X). 139 | test('subset_3', all(X == [0])) :- 140 | run_from_atom('⊇', 0, X). 141 | test('subset_4', all(X == [7])) :- 142 | run_from_atom('⊇', 7, X). 143 | test('subset_5', all(X == [123,12,13,23,1,2,3])) :- 144 | run_from_atom('⊇', 123, X). 145 | test('subset_6', all(X == [[1,2,3],[1,2],[1,3],[2,3],[1],[2],[3],[]])) :- 146 | run_from_atom('⊇', [1,2,3], X). 147 | test('subset_7', all(X == ["test","tes","tet","tst","est","te","ts","tt","es","et","st","t","e","s","t",""])) :- 148 | run_from_atom('⊇', "test", X). 149 | test('subset_8', fail) :- 150 | run_from_atom('⊇', [1,2,3], [1,5]). 151 | 152 | 153 | /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 154 | BRACHYLOG_REVERSE 155 | - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ 156 | test('reverse_1', all(X == [0])) :- 157 | run_from_atom('↔', 0, X). 158 | test('reverse_2', all(X == [[]])) :- 159 | run_from_atom('↔', [], X). 160 | test('reverse_3', all(X == [""])) :- 161 | run_from_atom('↔', "", X). 162 | test('reverse_4', all(X == [321])) :- 163 | run_from_atom('↔', 123, X). 164 | test('reverse_5', all(X == [321])) :- 165 | run_from_atom('↔', 1230, X). 166 | test('reverse_6', all(X == ["tset"])) :- 167 | run_from_atom('↔', "test", X). 168 | test('reverse_7', all(X == [[0,3,2,1]])) :- 169 | run_from_atom('↔', [1,2,3,0], X). 170 | test('reverse_8', all(X == [[1,2,3,2,1]])) :- 171 | run_from_atom('↔?', '[1,2,3,I,J]', X). 172 | test('reverse_9', all(X == [["a","b","c","b","a"]])) :- 173 | run_from_atom('↔?', '["a","b","c",I,J]', X). 174 | 175 | 176 | /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 177 | BRACHYLOG_CALL_PREDICATE 178 | - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ 179 | % TODO 180 | 181 | 182 | /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 183 | BRACHYLOG_CIRCULAR_PERMUTE_COUNTERCLOCKWISE 184 | - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ 185 | test('circular_permute_counterclockwise_1', all(X == [[]])) :- 186 | run_from_atom('↺', [], X). 187 | test('circular_permute_counterclockwise_2', all(X == [""])) :- 188 | run_from_atom('↺', "", X). 189 | test('circular_permute_counterclockwise_3', all(X == [0])) :- 190 | run_from_atom('↺', 0, X). 191 | test('circular_permute_counterclockwise_4', all(X == [231])) :- 192 | run_from_atom('↺', 123, X). 193 | test('circular_permute_counterclockwise_5', all(X == ["estt"])) :- 194 | run_from_atom('↺', "test", X). 195 | test('circular_permute_counterclockwise_6', all(X == [[2,"test",1]])) :- 196 | run_from_atom('↺', [1,2,"test"], X). 197 | test('circular_permute_counterclockwise_7', all(X == [[4,5,6,1,2,3]])) :- 198 | run_from_atom('↺₃', [1,2,3,4,5,6], X). 199 | 200 | 201 | /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 202 | BRACHYLOG_CIRCULAR_PERMUTE_CLOCKWISE 203 | - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ 204 | test('circular_permute_clockwise_1', all(X == [[]])) :- 205 | run_from_atom('↻', [], X). 206 | test('circular_permute_clockwise_2', all(X == [""])) :- 207 | run_from_atom('↻', "", X). 208 | test('circular_permute_clockwise_3', all(X == [0])) :- 209 | run_from_atom('↻', 0, X). 210 | test('circular_permute_clockwise_4', all(X == [312])) :- 211 | run_from_atom('↻', 123, X). 212 | test('circular_permute_clockwise_5', all(X == ["ttes"])) :- 213 | run_from_atom('↻', "test", X). 214 | test('circular_permute_clockwise_6', all(X == [["test",1,2]])) :- 215 | run_from_atom('↻', [1,2,"test"], X). 216 | test('circular_permute_clockwise_7', all(X == [[4,5,6,1,2,3]])) :- 217 | run_from_atom('↻₃', [1,2,3,4,5,6], X). 218 | 219 | 220 | /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 221 | BRACHYLOG_ROOT 222 | - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ 223 | test('root_1', all(X == [-1,1])) :- 224 | run_from_atom('√', 1, X). 225 | test('root_2', all(X == [0])) :- 226 | run_from_atom('√', 0, X). 227 | test('root_3', all(X == [-12,12])) :- 228 | run_from_atom('√', 144, X). 229 | test('root_4', all(X == [2.23606797749979])) :- 230 | run_from_atom('√', 5, X). 231 | test('root_5', throws(_)) :- 232 | run_from_atom('√', '_5', _). 233 | test('root_6', all(X == [2.04939015319192])) :- 234 | run_from_atom('√', 4.2, X). 235 | test('root_7', all(X == [3])) :- 236 | run_from_atom('√₃', 27, X). 237 | test('root_8', all(X == [-3])) :- 238 | run_from_atom('√₃', '_27', X). 239 | 240 | 241 | /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 242 | BRACHYLOG_CEIL 243 | - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ 244 | test('ceil_1', fail) :- 245 | run_from_atom('⌉', [], _). 246 | test('ceil_2', all(X == [3])) :- 247 | run_from_atom('⌉', [1,2,3], X). 248 | test('ceil_3', all(X == [-5])) :- 249 | run_from_atom('⌉', '[_9,_5,_13]', X). 250 | test('ceil_4', all(X == ["test"])) :- 251 | run_from_atom('⌉', ["test",2,3], X). 252 | test('ceil_5', all(X == ["z"])) :- 253 | run_from_atom('⌉', ["test","z"], X). 254 | test('ceil_6', all(X == [123])) :- 255 | run_from_atom('⌉₁', 123, X). 256 | test('ceil_7', all(X == [124])) :- 257 | run_from_atom('⌉₁', 123.45, X). 258 | test('ceil_8', all(X == [-123])) :- 259 | run_from_atom('⌉₁', '_123.45', X). 260 | 261 | 262 | /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 263 | BRACHYLOG_FLOOR 264 | - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ 265 | test('floor_1', fail) :- 266 | run_from_atom('⌋', [], _). 267 | test('floor_2', all(X == [1])) :- 268 | run_from_atom('⌋', [1,2,3], X). 269 | test('floor_3', all(X == [-13])) :- 270 | run_from_atom('⌋', '[_9,_5,_13]', X). 271 | test('floor_4', all(X == [2])) :- 272 | run_from_atom('⌋', ["test",2,3], X). 273 | test('floor_5', all(X == ["test"])) :- 274 | run_from_atom('⌋', ["test","z"], X). 275 | test('floor_6', all(X == [123])) :- 276 | run_from_atom('⌋₁', 123, X). 277 | test('floor_7', all(X == [123])) :- 278 | run_from_atom('⌋₁', 123.45, X). 279 | test('floor_8', all(X == [-124])) :- 280 | run_from_atom('⌋₁', '_123.45', X). 281 | 282 | 283 | /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 284 | BRACHYLOG_RANGE_ASCENDING 285 | - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ 286 | test('range_ascending_1', all(X == [[0]])) :- 287 | run_from_atom('⟦', 0, X). 288 | test('range_ascending_2', all(X == [[0,1,2,3,4,5]])) :- 289 | run_from_atom('⟦', 5, X). 290 | test('range_ascending_3', all(X == [[-5,-4,-3,-2,-1,0]])) :- 291 | run_from_atom('⟦', '_5', X). 292 | test('range_ascending_4', all(X == [[1,2,3,4,5]])) :- 293 | run_from_atom('⟦₁', 5, X). 294 | test('range_ascending_5', all(X == [[9,10,11,12,13]])) :- 295 | run_from_atom('⟦₂', [9,13], X). 296 | 297 | 298 | /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 299 | BRACHYLOG_RANGE_DESCENDING 300 | - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ 301 | test('range_descending_1', all(X == [[0]])) :- 302 | run_from_atom('⟧', 0, X). 303 | test('range_descending_2', all(X == [[5,4,3,2,1,0]])) :- 304 | run_from_atom('⟧', 5, X). 305 | test('range_descending_3', all(X == [[0,-1,-2,-3,-4,-5]])) :- 306 | run_from_atom('⟧', '_5', X). 307 | test('range_descending_4', all(X == [[5,4,3,2,1]])) :- 308 | run_from_atom('⟧₁', 5, X). 309 | test('range_descending_5', all(X == [[13,12,11,10,9]])) :- 310 | run_from_atom('⟧₂', [9,13], X). 311 | 312 | 313 | /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 314 | BRACHYLOG_NATURAL_INTEGER 315 | - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ 316 | test('natural_integer_1', all(X == [0])) :- 317 | run_from_atom('ℕ', 0, X). 318 | test('natural_integer_2', all(X == [42])) :- 319 | run_from_atom('ℕ', 42, X). 320 | test('natural_integer_3', fail) :- 321 | run_from_atom('ℕ', "test", _). 322 | test('natural_integer_4', fail) :- 323 | run_from_atom('ℕ', '_3', _). 324 | test('natural_integer_5', fail) :- 325 | run_from_atom('ℕ', [1,2], _). 326 | test('natural_integer_6', fail) :- 327 | run_from_atom('ℕ', 4.2, _). 328 | test('natural_integer_7', all(X == [42])) :- 329 | run_from_atom('ℕ₄₂', 42, X). 330 | test('natural_integer_8', fail) :- 331 | run_from_atom('ℕ₄₂', 41, _). 332 | 333 | 334 | /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 335 | BRACHYLOG_INTEGER 336 | - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ 337 | test('integer_1', all(X == [0])) :- 338 | run_from_atom('ℤ', 0, X). 339 | test('integer_2', all(X == [42])) :- 340 | run_from_atom('ℤ', 42, X). 341 | test('integer_3', fail) :- 342 | run_from_atom('ℤ', "test", _). 343 | test('integer_4', all(X == [-3])) :- 344 | run_from_atom('ℤ', '_3', X). 345 | test('integer_5', fail) :- 346 | run_from_atom('ℤ', [1,2], _). 347 | test('integer_6', fail) :- 348 | run_from_atom('ℤ', 4.2, _). 349 | test('integer_7', all(X == [-42])) :- 350 | run_from_atom('ℤ₄₂', '_42', X). 351 | test('integer_8', fail) :- 352 | run_from_atom('ℤ₄₂', '_41', _). 353 | 354 | 355 | /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 356 | BRACHYLOG_FLOAT 357 | - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ 358 | test('float_1', all(X == [4.2])) :- 359 | run_from_atom('ℝ', 4.2, X). 360 | test('float_2', all(X == [0.0])) :- 361 | run_from_atom('ℝ', 0.0, X). 362 | test('float_3', all(X == [-4.2])) :- 363 | run_from_atom('ℝ', '_4.2', X). 364 | test('float_4', fail) :- 365 | run_from_atom('ℝ', 0, _). 366 | test('float_5', fail) :- 367 | run_from_atom('ℝ', 42, _). 368 | test('float_6', all(X == [42])) :- 369 | run_from_atom('ℝ₁', 42, X). 370 | 371 | 372 | /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 373 | BRACHYLOG_EMPTY 374 | - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ 375 | test('empty_1', nondet) :- 376 | run_from_atom('∅', [], _). 377 | test('empty_2', nondet) :- 378 | run_from_atom('∅', 0, _). 379 | test('empty_3', nondet) :- 380 | run_from_atom('∅', "", _). 381 | test('empty_4', nondet) :- 382 | run_from_atom('∅', 0.0, _). 383 | test('empty_5', fail) :- 384 | run_from_atom('∅', [1], _). 385 | test('empty_6', fail) :- 386 | run_from_atom('∅', 1, _). 387 | test('empty_7', fail) :- 388 | run_from_atom('∅', "a", _). 389 | 390 | 391 | /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 392 | BRACHYLOG_DIFFERENT 393 | - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ 394 | test('different_1', all(X == [12345])) :- 395 | run_from_atom('≠', 12345, X). 396 | test('different_1', fail) :- 397 | run_from_atom('≠', 12344, _). 398 | test('different_1', all(X == [[1,2,3]])) :- 399 | run_from_atom('≠', [1,2,3], X). 400 | test('different_1', fail) :- 401 | run_from_atom('≠', [1,2,1], _). 402 | 403 | 404 | /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 405 | BRACHYLOG_INTEGER_DIVISION 406 | - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ 407 | test('integer_division_1', all(X == [3])) :- 408 | run_from_atom('÷', [6,2], X). 409 | test('integer_division_2', all(X == [3])) :- 410 | run_from_atom('÷', [7,2], X). 411 | test('integer_division_3', all(X == [-3])) :- 412 | run_from_atom('÷', '[_6,2]', X). 413 | test('integer_division_1', fail) :- 414 | run_from_atom('÷', '[6,0]', _). 415 | test('integer_division_1', all(X == [0])) :- 416 | run_from_atom('÷', '[0,_42]', X). 417 | test('integer_division_1', all(X == [3])) :- 418 | run_from_atom('÷', [6.2,2], X). 419 | test('integer_division_1', all(X == [2])) :- 420 | run_from_atom('÷₃', 6, X). 421 | 422 | 423 | /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 424 | BRACHYLOG_MULTIPLY 425 | - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ 426 | test('multiply_1', all(X == [1])) :- 427 | run_from_atom('×', [], X). 428 | test('multiply_2', all(X == [12])) :- 429 | run_from_atom('×', [6,2], X). 430 | test('multiply_3', all(X == [12])) :- 431 | run_from_atom('×', [2,6], X). 432 | test('multiply_4', all(X == [-12])) :- 433 | run_from_atom('×', '[_6,2]', X). 434 | test('multiply_5', all(X == [24])) :- 435 | run_from_atom('×', [2,3,4], X). 436 | test('multiply_6', all(X == [0])) :- 437 | run_from_atom('×', '[0,_42]', X). 438 | test('multiply_7', all(X == [12.4])) :- 439 | run_from_atom('×', [6.2,2], X). 440 | test('multiply_8', all(X == [18])) :- 441 | run_from_atom('×₃', 6, X). 442 | 443 | 444 | /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 445 | BRACHYLOG_MODULO 446 | - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ 447 | test('modulo_1', all(X == [1])) :- 448 | run_from_atom('%', [4,3], X). 449 | test('modulo_2', all(X == [0])) :- 450 | run_from_atom('%', [4,2], X). 451 | test('modulo_3', all(X == [4])) :- 452 | run_from_atom('%', [42,19], X). 453 | 454 | 455 | /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 456 | BRACHYLOG_EXP 457 | - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ 458 | test('exp_1', all(X == [22026.465794806718])) :- 459 | run_from_atom('*', 10, X). 460 | test('exp_2', all(X == [2.302585092994046])) :- 461 | run_from_atom('*₁', 10, X). 462 | test('exp_3', all(X == [-0.8390715290764524])) :- 463 | run_from_atom('*₂', 10, X). 464 | test('exp_4', all(X == [-0.5440211108893698])) :- 465 | run_from_atom('*₃', 10, X). 466 | test('exp_5', all(X == [0.6483608274590866])) :- 467 | run_from_atom('*₄', 10, X). 468 | test('exp_6', all(X == [1.0471975511965979])) :- 469 | run_from_atom('*₅', 0.5, X). 470 | test('exp_7', all(X == [0.5235987755982989])) :- 471 | run_from_atom('*₆', 0.5, X). 472 | test('exp_8', all(X == [1.4711276743037347])) :- 473 | run_from_atom('*₇', 10, X). 474 | test('exp_9', all(X == [11013.232920103323])) :- 475 | run_from_atom('*₈', 10, X). 476 | test('exp_10', all(X == [11013.232874703393])) :- 477 | run_from_atom('*₉', 10, X). 478 | test('exp_11', all(X == [0.9999999958776927])) :- 479 | run_from_atom('*₁₀', 10, X). 480 | test('exp_12', all(X == [2.993222846126381])) :- 481 | run_from_atom('*₁₁', 10, X). 482 | test('exp_13', all(X == [2.99822295029797])) :- 483 | run_from_atom('*₁₂', 10, X). 484 | test('exp_14', all(X == [0.5493061443340549])) :- 485 | run_from_atom('*₁₃', 0.5, X). 486 | 487 | 488 | /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 489 | BRACHYLOG_PLUS 490 | - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ 491 | test('plus_1', all(X == [3])) :- 492 | run_from_atom('+', [1,2], X). 493 | test('plus_2', all(X == [2])) :- 494 | run_from_atom('+', '[_3,5]', X). 495 | test('plus_3', all(X == [-5])) :- 496 | run_from_atom('+', '[_3,_2]', X). 497 | test('plus_4', all(X == [21])) :- 498 | run_from_atom('+', [1,2,3,4,5,6], X). 499 | test('plus_5', all(X == [4.6])) :- 500 | run_from_atom('+', [1.2,3.4], X). 501 | test('plus_6', all(X == [13])) :- 502 | run_from_atom('+', [13,0,0,0,0], X). 503 | test('plus_7', all(X == [67])) :- 504 | run_from_atom('+₄₂', 25, X). 505 | 506 | 507 | /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 508 | BRACHYLOG_MINUS 509 | - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ 510 | test('minus_1', all(X == [-1])) :- 511 | run_from_atom('-', [1,2], X). 512 | test('minus_2', all(X == [-8])) :- 513 | run_from_atom('-', '[_3,5]', X). 514 | test('minus_3', all(X == [2])) :- 515 | run_from_atom('-', '[_1,_3]', X). 516 | test('minus_4', all(X == [-3])) :- 517 | run_from_atom('-', [1,2,3,4,5,6], X). 518 | test('minus_5', all(X == [-2.2])) :- 519 | run_from_atom('-', [1.2,3.4], X). 520 | test('minus_6', all(X == [13])) :- 521 | run_from_atom('-', [13,0,0,0,0], X). 522 | test('minus_7', all(X == [-17])) :- 523 | run_from_atom('-₄₂', 25, X). 524 | 525 | 526 | /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 527 | BRACHYLOG_DIVIDE 528 | - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ 529 | test('divide_1', all(X == [0.5])) :- 530 | run_from_atom('/', [1,2], X). 531 | test('divide_2', all(X == [3])) :- 532 | run_from_atom('/', [6,2], X). 533 | test('divide_3', all(X == [-0.5])) :- 534 | run_from_atom('/', '[1,_2]', X). 535 | test('divide_4', all(X == [0.1111111111111111])) :- 536 | run_from_atom('/₁', 9, X). 537 | 538 | 539 | /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 540 | BRACHYLOG_LESS 541 | - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ 542 | test('less_1', all(X == [2])) :- 543 | run_from_atom('1<2', _, X). 544 | test('less_2', all(X == [2])) :- 545 | run_from_atom('_1<2', _, X). 546 | test('less_3', fail) :- 547 | run_from_atom('0<0', _, _). 548 | test('less_4', fail) :- 549 | run_from_atom('13<13', _, _). 550 | test('less_5', fail) :- 551 | run_from_atom('_42<_42', _, _). 552 | test('less_6', all(X == [[1,2,3]])) :- 553 | run_from_atom('[1,2,3]<₁', _, X). 554 | test('less_7', all(X == [[-1,0,1]])) :- 555 | run_from_atom('[_1,0,1]<₁', _, X). 556 | test('less_8', all(X == [[-42,-23,-16]])) :- 557 | run_from_atom('[_42,_23,_16]<₁', _, X). 558 | test('less_9', all(X == [[1,2,3]])) :- 559 | run_from_atom('[1,I,3]<₁', _, X). 560 | test('less_10', fail) :- 561 | run_from_atom('2<1', _, _). 562 | test('less_11', fail) :- 563 | run_from_atom('2<_1', _, _). 564 | test('less_12', fail) :- 565 | run_from_atom('[1,3,2]<₁', _, _). 566 | test('less_13', fail) :- 567 | run_from_atom('[1,I,_1]<₁', _, _). 568 | 569 | 570 | /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 571 | BRACHYLOG_EQUAL 572 | - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ 573 | test('equal_1', all(X == [1111])) :- 574 | run_from_atom('=', 1111, X). 575 | test('equal_2', all(X == [[]])) :- 576 | run_from_atom('=', [], X). 577 | test('equal_3', all(X == [0])) :- 578 | run_from_atom('=', 0, X). 579 | test('equal_4', all(X == [[42,42,42,42]])) :- 580 | run_from_atom('=', '[X,Y,42,Z]', X). 581 | test('equal_5', fail) :- 582 | run_from_atom('=', [1,1,1,2,1], _). 583 | 584 | 585 | /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 586 | BRACHYLOG_GREATER 587 | - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ 588 | test('greater_1', all(X == [1])) :- 589 | run_from_atom('2>1', _, X). 590 | test('greater_2', all(X == [-1])) :- 591 | run_from_atom('2>_1', _, X). 592 | test('greater_3', fail) :- 593 | run_from_atom('0>0', _, _). 594 | test('greater_4', fail) :- 595 | run_from_atom('13>13', _, _). 596 | test('greater_5', fail) :- 597 | run_from_atom('_42>_42', _, _). 598 | test('greater_6', all(X == [[3,2,1]])) :- 599 | run_from_atom('[3,2,1]>₁', _, X). 600 | test('greater_7', all(X == [[1,0,-1]])) :- 601 | run_from_atom('[1,0,_1]>₁', _, X). 602 | test('greater_8', all(X == [[-16,-23,-42]])) :- 603 | run_from_atom('[_16,_23,_42]>₁', _, X). 604 | test('greater_9', all(X == [[3,2,1]])) :- 605 | run_from_atom('[3,I,1]>₁', _, X). 606 | test('greater_10', fail) :- 607 | run_from_atom('1>2', _, _). 608 | test('greater_11', fail) :- 609 | run_from_atom('_1>2', _, _). 610 | test('greater_12', fail) :- 611 | run_from_atom('[1,3,2]>₁', _, _). 612 | test('greater_13', fail) :- 613 | run_from_atom('[_1,I,1]>₁', _, _). 614 | 615 | 616 | /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 617 | BRACHYLOG_TRANSPOSE 618 | - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ 619 | test('transpose_1', all(X == [[[1,4,7],[2,5,8],[3,6,9]]])) :- 620 | run_from_atom('\\', [[1,2,3],[4,5,6],[7,8,9]], X). 621 | 622 | 623 | /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 624 | BRACHYLOG_POWER 625 | - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ 626 | test('power_1', all(X == [8])) :- 627 | run_from_atom('^', [2,3], X). 628 | test('power_2', all(X == [-8])) :- 629 | run_from_atom('^', '[_2,3]', X). 630 | test('power_3', all(X == [1])) :- 631 | run_from_atom('^', [1,50], X). 632 | test('power_4', all(X == [0])) :- 633 | run_from_atom('^', [0,42], X). 634 | test('power_5', all(X == [1])) :- 635 | run_from_atom('^', [7,0], X). 636 | test('power_6', all(X == [49])) :- 637 | run_from_atom('^₂', 7, X). 638 | 639 | 640 | :- end_tests(predicates). 641 | 642 | 643 | % Useful templates 644 | test('_', all(X == [])) :- 645 | run_from_atom('', _, X). 646 | 647 | test('_', fail) :- 648 | run_from_atom('', _, _). 649 | -------------------------------------------------------------------------------- /src/transpile.pl: -------------------------------------------------------------------------------- 1 | /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 2 | ____ ____ 3 | \ \ / / 4 | \ \ ____ / / 5 | \ \/ \/ / 6 | \ /\ / BRACHYLOG 7 | \ / \ / A terse declarative logic programming language 8 | / \ / \ 9 | / \/ \ Written by Julien Cumin - 2017 10 | / /\____/\ \ https://github.com/JCumin/Brachylog 11 | / / ___ \ \ 12 | /___/ /__/ \___\ 13 | 14 | - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ 15 | 16 | 17 | :- module(transpile, [parse/2, 18 | parse_no_file/2, 19 | parse_argument/2, 20 | contains_write/1 21 | ]). 22 | 23 | :- use_module(tokenize). 24 | :- use_module(symbols). 25 | 26 | 27 | /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 28 | PARSE 29 | - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ 30 | parse(Code, TranspiledPath) :- 31 | parse_no_file(Code, Predicates), 32 | open(TranspiledPath, write, File), 33 | maplist(write_to_file(File), Predicates), 34 | close(File). 35 | 36 | parse_no_file(Code, Predicates) :- 37 | atom_chars(Code, SplittedCode), 38 | tokenize(SplittedCode, TokensNoOutputs), 39 | append_trailing_output(TokensNoOutputs, Tokens), 40 | fix_predicates(Tokens, FixedPredicates), 41 | fix_metapredicates(FixedPredicates, FixedMetapredicates), 42 | fill_implicit_variables(FixedMetapredicates, FilledTokens), 43 | fix_variables_superscripts(FilledTokens, FixedVariables, GlobalVariables), 44 | fix_lists(FixedVariables, FixedLists), 45 | fix_forks(FixedLists, FixedForks), 46 | fix_arrows(FixedForks, Program), 47 | atomic_list_concat(GlobalVariables, ',', G), 48 | atomic_list_concat(['[', G, ']'], GlobalVariablesAtom), 49 | transpile(Program, Predicates, GlobalVariablesAtom), 50 | !. 51 | 52 | 53 | /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 54 | PARSE_ARGUMENT 55 | - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ 56 | parse_argument(Arg, Term) :- 57 | ( atom(Arg), 58 | AtomArg = Arg 59 | ; \+ atom(Arg), 60 | term_to_atom(Arg, AtomArg) 61 | ), 62 | atom_chars(AtomArg, SplittedArg), 63 | tokenize(SplittedArg, Token), 64 | fix_variables_superscripts(Token, FixedSuperscripts, _), 65 | fix_lists(FixedSuperscripts, Program), 66 | transpile(Program, Parsed, '[]'), 67 | !, 68 | reverse(Parsed, [TempMainPredicate|_]), 69 | nth0(3, TempMainPredicate, Atom), 70 | atom_concat(',\n ', AtomT, Atom), 71 | atom_concat(ParsedArg, ' = Var_Input_Local', AtomT), 72 | term_to_atom(Term, ParsedArg) 73 | ; 74 | throw('Incorrect variable format.'). 75 | 76 | 77 | /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 78 | APPEND_TRAILING_OUTPUT 79 | - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ 80 | append_trailing_output([], ['variable':'Output':'sup':'default']). 81 | append_trailing_output(['control':'\n'|T], ['variable':'Output':'sup':'default','control':'\n'|T2]) :- 82 | append_trailing_output(T, T2). 83 | append_trailing_output(['control':'}'|T], ['variable':'Output':'sup':'default','control':'}'|T2]) :- 84 | append_trailing_output(T, T2). 85 | append_trailing_output(['control':'⟩'|T], ['variable':'Output':'sup':'default','control':'⟩'|T2]) :- 86 | append_trailing_output(T, T2). 87 | append_trailing_output(['control':'|'|T], ['variable':'Output':'sup':'default','control':'|'|T2]) :- 88 | append_trailing_output(T, T2). 89 | append_trailing_output([H|T], [H|T2]) :- 90 | H \= 'control':'\n', 91 | H \= 'control':'}', 92 | H \= 'control':'⟩', 93 | H \= 'control':'|', 94 | append_trailing_output(T, T2). 95 | 96 | 97 | /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 98 | FIX_PREDICATES'⟨', '⟩' 99 | - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ 100 | fix_predicates(Tokens, FixedPredicates) :- 101 | fix_predicates(Tokens, 1, L), 102 | append(L, FixedPredicates). 103 | 104 | fix_predicates([], _, [[]]). 105 | fix_predicates(['control':'{'|T], I, [['predicate':PredName:0|Rest], ['control':'\n'|Predicate]|AllOtherPredicates]) :- 106 | atomic_list_concat(['brachylog_predicate_',I], PredName), 107 | J is I + 1, 108 | fix_predicates_(T, J, [Predicate|OtherPredicates1], Z, Remaining), 109 | fix_predicates(Remaining, Z, [Rest|OtherPredicates2]), 110 | append(OtherPredicates1, OtherPredicates2, AllOtherPredicates). 111 | fix_predicates(['control':'⟨'|T], I, [['predicate':PredName:0|Rest], ['control':'\n','fork':'start'|Predicate]|AllOtherPredicates]) :- 112 | atomic_list_concat(['brachylog_predicate_',I], PredName), 113 | J is I + 1, 114 | fix_predicates_(T, J, [Predicate|OtherPredicates1], Z, Remaining), 115 | fix_predicates(Remaining, Z, [Rest|OtherPredicates2]), 116 | append(OtherPredicates1, OtherPredicates2, AllOtherPredicates). 117 | fix_predicates(['control':'\n'|T], I, [[],['control':'\n'|Rest]|OtherPredicates]) :- 118 | J is I + 1, 119 | fix_predicates(T, J, [Rest|OtherPredicates]). 120 | fix_predicates([Type:A|T], I, [[Type:A|Rest]|OtherPredicates]) :- 121 | \+ (Type = 'control', A = '{'), 122 | \+ (Type = 'control', A = '}'), 123 | \+ (Type = 'control', A = '⟨'), 124 | \+ (Type = 'control', A = '⟩'), 125 | \+ (Type = 'control', A = '\n'), 126 | fix_predicates(T, I, [Rest|OtherPredicates]). 127 | 128 | fix_predicates_([], _, [[]]). 129 | fix_predicates_(['control':'{'|T], I, [['predicate':PredName:0|Rest], ['control':'\n'|Predicate]|AllOtherPredicates], Z, Remaining) :- 130 | atomic_list_concat(['brachylog_predicate_',I], PredName), 131 | J is I + 1, 132 | fix_predicates_(T, J, [Predicate|OtherPredicates1], Z2, Remaining2), 133 | fix_predicates_(Remaining2, Z2, [Rest|OtherPredicates2], Z, Remaining), 134 | append(OtherPredicates1, OtherPredicates2, AllOtherPredicates). 135 | fix_predicates_(['control':'⟨'|T], I, [['predicate':PredName:0|Rest], ['control':'\n','fork':'start'|Predicate]|AllOtherPredicates], Z, Remaining) :- 136 | atomic_list_concat(['brachylog_predicate_',I], PredName), 137 | J is I + 1, 138 | fix_predicates_(T, J, [Predicate|OtherPredicates1], Z2, Remaining2), 139 | fix_predicates_(Remaining2, Z2, [Rest|OtherPredicates2], Z, Remaining), 140 | append(OtherPredicates1, OtherPredicates2, AllOtherPredicates). 141 | fix_predicates_(['control':'}'|T], I, [[]], I, T). 142 | fix_predicates_(['control':'⟩'|T], I, [['fork':'end']], I, T). 143 | fix_predicates_([Type:A|T], I, [[Type:A|Rest]|OtherPredicates], Z, Remaining) :- 144 | \+ (Type = 'control', A = '{'), 145 | \+ (Type = 'control', A = '}'), 146 | \+ (Type = 'control', A = '⟨'), 147 | \+ (Type = 'control', A = '⟩'), 148 | \+ (Type = 'control', A = '\n'), 149 | fix_predicates_(T, I, [Rest|OtherPredicates], Z, Remaining). 150 | 151 | 152 | /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 153 | FIX_METAPREDICATES 154 | - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ 155 | fix_metapredicates([], []). 156 | fix_metapredicates(['predicate':PredName:Sub,'metapredicate':MetapredName:Sup|T], ['predicate':PredName:Sub:MetapredName:Sup|T2]) :- 157 | fix_metapredicates(T, T2). 158 | fix_metapredicates(['predicate':PredName:Sub|T], ['predicate':PredName:Sub:'no':0|T2]) :- 159 | fix_metapredicates(T, T2). 160 | fix_metapredicates([H|T], [H|T2]) :- 161 | fix_metapredicates(T, T2). 162 | 163 | 164 | /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 165 | FILL_IMPLICIT_VARIABLES 166 | - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ 167 | fill_implicit_variables(Tokens, Program) :- 168 | fill_implicit_variables(Tokens, 0, Program). 169 | 170 | fill_implicit_variables([], _, []). 171 | fill_implicit_variables(['control':':','predicate':A|T], I, ['control':':','predicate':A|T2]) :- 172 | fill_implicit_variables(T, I, T2). 173 | fill_implicit_variables(['predicate':A,Type:B|T], I, ['predicate':A,'variable':V|T2]) :- 174 | Type \= 'variable', 175 | atom_concat('V', I, V), 176 | J is I + 1, 177 | fill_implicit_variables([Type:B|T], J, T2). 178 | fill_implicit_variables(['predicate':A], I, ['predicate':A,'variable':V]) :- 179 | atom_concat('V', I, V). 180 | fill_implicit_variables(['predicate':A,'variable':B|T], I, ['predicate':A,'variable':B|T2]) :- 181 | fill_implicit_variables(T, I, T2). 182 | fill_implicit_variables(['control':H,Type:B|T], I, ['control':H,'variable':V|T2]) :- 183 | Type \= 'variable', 184 | ( H = '∧' 185 | ; H = '∨' 186 | ), 187 | atom_concat('V', I, V), 188 | J is I + 1, 189 | fill_implicit_variables([Type:B|T], J, T2). 190 | fill_implicit_variables(['control':H,'variable':B,Type:C|T], I, ['control':H,'variable':B,'variable':V|T2]) :- 191 | Type \= 'variable', 192 | ( H = '↖' 193 | ; H = '↙' 194 | ), 195 | atom_concat('V', I, V), 196 | J is I + 1, 197 | fill_implicit_variables([Type:C|T], J, T2). 198 | fill_implicit_variables([Type:A|T], I, [Type:A|T2]) :- 199 | Type \= 'predicate', 200 | \+ (Type = 'control', A = ':', T = ['predicate':_|_]), 201 | \+ (Type = 'control', A = '∧', T \= ['variable':_|_]), 202 | \+ (Type = 'control', A = '∨', T \= ['variable':_|_]), 203 | \+ (Type = 'control', A = '↖', T \= ['variable':_|_]), 204 | \+ (Type = 'control', A = '↙', T \= ['variable':_|_]), 205 | fill_implicit_variables(T, I, T2). 206 | 207 | 208 | /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 209 | FIX_VARIABLES_SUPERSCRIPTS 210 | - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ 211 | fix_variables_superscripts(Input, Output, GlobalVariables) :- 212 | fix_variables_superscripts_(Input, Output, GlobVars), 213 | sort(GlobVars, GlobalVariables). % Remove duplicates 214 | 215 | fix_variables_superscripts_([], [], []). 216 | fix_variables_superscripts_(['variable':A:'sup':Sup|T], ['variable':V|T2], [V|GlobalVariables]) :- 217 | atomic_list_concat(['integer', SupAtom], ':', Sup), 218 | atom_number(SupAtom, J), 219 | atomic_list_concat(['Var_',A,'_',J], V), 220 | fix_variables_superscripts_(T, T2, GlobalVariables). 221 | fix_variables_superscripts_(['variable':A:'sup':'default'|T], ['variable':V|T2], GlobalVariables) :- 222 | atomic_list_concat(['Var_',A,'_Local'], V), 223 | fix_variables_superscripts_(T, T2, GlobalVariables). 224 | fix_variables_superscripts_(['variable':List|T], ['variable':FixedList|T2], GlobalVariables) :- 225 | is_list(List), 226 | fix_variables_superscripts_(List, FixedList, Vars), 227 | fix_variables_superscripts_(T, T2, GlobalVariables2), 228 | append(Vars, GlobalVariables2, GlobalVariables). 229 | fix_variables_superscripts_([X|T], [X|T2], GlobalVariables) :- 230 | fix_variables_superscripts_(T, T2, GlobalVariables). 231 | 232 | 233 | 234 | /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 235 | FIX_LISTS 236 | - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ 237 | fix_lists([], []). 238 | fix_lists(['variable':List|T], ['variable':FixedList|T2]) :- 239 | is_list(List), 240 | fix_list(List, FixedList), 241 | fix_lists(T, T2). 242 | fix_lists([X|T], [X|T2]) :- 243 | ( X = 'variable':L, 244 | \+ (is_list(L)) 245 | ; X \= 'variable':_ 246 | ), 247 | fix_lists(T, T2). 248 | 249 | fix_list([], []). 250 | fix_list(['control':','|T], T2) :- 251 | fix_list(T, T2). 252 | fix_list([X|T], [Y|T2]) :- 253 | X \= 'control':',', 254 | ( X = 'variable':L, 255 | is_list(L), 256 | fix_list(L, Y) 257 | ; X = 'variable':Y 258 | ; X = 'predicate':_, 259 | Y = X 260 | ; Y = X 261 | ), 262 | fix_list(T, T2). 263 | 264 | 265 | /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 266 | FIX_FORKS 267 | - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ 268 | fix_forks(L, Z) :- 269 | fix_forks(L, 0, Z). 270 | 271 | fix_forks([], _, []). % Ignore each useless implicit var after 272 | fix_forks(['fork':'start', F1, _, F2, Output, 'fork':'end'|T], I, ['control':'unpair','variable':V1,F1,Output,F2,'variable':V1,'control':'∧'|T2]) :- 273 | atom_concat('Fork', I, V1), 274 | J is I + 1, 275 | fix_forks(T, J, T2). 276 | 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]) :- 277 | atom_concat('Fork', I, V1), 278 | J is I + 1, 279 | atom_concat('Fork', J, V2), 280 | K is I + 1, 281 | fix_forks(T, K, T2). 282 | fix_forks([H|T], I, [H|T2]) :- 283 | dif(H, 'fork':'start'), 284 | fix_forks(T, I, T2). 285 | 286 | 287 | /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 288 | FIX_ARROWS 289 | - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ 290 | fix_arrows([], []). 291 | fix_arrows(['predicate':P:_:Meta:Sup,'variable':_,'control':'↙','variable':V|T], T2) :- !, 292 | ( atom(V) -> 293 | V = VA 294 | ; term_to_atom(V, VA) 295 | ), 296 | fix_arrows(['predicate':P:VA:Meta:Sup|T], T2). 297 | fix_arrows(['predicate':P:Sub:Meta:_,'variable':_,'control':'↖','variable':V|T], T2) :- !, 298 | ( atom(V) -> 299 | V = VA 300 | ; term_to_atom(V, VA) 301 | ), 302 | fix_arrows(['predicate':P:Sub:Meta:VA|T], T2). 303 | fix_arrows(['predicate':P:_:Meta:Sup,'control':'↙','variable':V|T], T2) :- !, 304 | ( atom(V) -> 305 | V = VA 306 | ; term_to_atom(V, VA) 307 | ), 308 | fix_arrows(['predicate':P:VA:Meta:Sup|T], T2). 309 | fix_arrows(['predicate':P:Sub:Meta:_,'control':'↖','variable':V|T], T2) :- !, 310 | ( atom(V) -> 311 | V = VA 312 | ; term_to_atom(V, VA) 313 | ), 314 | fix_arrows(['predicate':P:Sub:Meta:VA|T], T2). 315 | fix_arrows([H|T], [H|T2]) :- 316 | fix_arrows(T, T2). 317 | 318 | 319 | /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 320 | TRANSPILE 321 | - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ 322 | transpile(Program, [[':- style_check(-singleton).'], 323 | [':- use_module(library(clpfd)).'], 324 | [':- use_module(predicates).'], 325 | [':- use_module(metapredicates).'], 326 | [':- use_module(constraint_variables).\n'], 327 | [MainPredHeader, 328 | ConstraintVariables, 329 | ' (1=1'|MainPred]|OtherPredicates], GlobalVariables) :- 330 | atomic_list_concat(['brachylog_main(', 331 | GlobalVariables, 332 | ',_, Var_Input_Local,Var_Output_Local) :-\n', 333 | ' Name = brachylog_main,\n', 334 | ' GlobalVariables = ', 335 | GlobalVariables,',\n', 336 | ' nb_setval(\'declw\',[]),\n'], % Initialize declarative write variable 337 | MainPredHeader), 338 | constraint_variables(GlobalVariables, ConstraintVariables), 339 | transpile_(Program, 'Var_Input_Local', no, no, 0, 0, [T|OtherPredicates], GlobalVariables), 340 | reverse(T, [_|RT]), 341 | reverse(RT, T2), 342 | append(T2, ['\n', 343 | ' ),\n', 344 | ' (', 345 | '(Var_Output_Local = integer:_ ; ', 346 | 'Var_Output_Local = [_|_], ', 347 | 'forall(member(E, Var_Output_Local), E = integer:_)) ', 348 | '-> brachylog_label(default, Var_Output_Local, _) ', 349 | '; true),\n', 350 | ' nb_getval(\'declw\', DeclwFinal),\n', 351 | ' maplist(write, DeclwFinal).'], % execute declarative write 352 | MainPred). 353 | 354 | transpile_([], _, _, _, _, _, [['\n ).\n']], _). 355 | transpile_(['variable':B|T], A, Reverse, Negate, AppendNumber, PredNumber, [[Unification|T2]|OtherPredicates], GlobalVariables) :- 356 | A \= 'nothing', 357 | ( is_list(A), 358 | brachylog_list_to_atom(A, Var1) 359 | ; A = Type:L, 360 | term_to_atom(Type:L, Var1) 361 | ; A = Var1 362 | ), 363 | ( is_list(B), 364 | brachylog_list_to_atom(B, Var2) 365 | ; B = _:_, 366 | term_to_atom(B, Var2) 367 | ; Var2 = B 368 | ), 369 | ( Negate = yes, 370 | UnificationAtom = ' \\= ' 371 | ; Negate = no, 372 | UnificationAtom = ' = ' 373 | ), 374 | ( Reverse = no, 375 | atomic_list_concat([',\n ',Var2,UnificationAtom,Var1], Unification), 376 | transpile_(T, B, no, no, AppendNumber, PredNumber, [T2|OtherPredicates], GlobalVariables) 377 | ; Reverse = yes, 378 | atomic_list_concat([',\n ',Var1,UnificationAtom,Var2], Unification), 379 | transpile_(T, B, no, no, AppendNumber, PredNumber, [T2|OtherPredicates], GlobalVariables) 380 | ). 381 | transpile_(['variable':B|T], 'nothing', _, _, AppendNumber, PredNumber, [T2|OtherPredicates], GlobalVariables) :- 382 | transpile_(T, B, no, no, AppendNumber, PredNumber, [T2|OtherPredicates], GlobalVariables). 383 | transpile_(['predicate':P:Sub:Meta:Sup,'variable':B|T], A, Reverse, Negate, AppendNumber, PredNumber, [[Predicate|T2]|OtherPredicates], GlobalVariables) :- 384 | A \= 'nothing', 385 | ( P = 'brachylog_call_predicate', 386 | ( Sub = 'default' -> 387 | RealSub = 'Name-GlobalVariables' 388 | ; atomic_list_concat(['(',Sub,')-','GlobalVariables'], RealSub) 389 | ) 390 | ; P \= 'brachylog_call_predicate', 391 | RealSub = Sub 392 | ), 393 | ( is_list(A), 394 | brachylog_list_to_atom(A, Var1) 395 | ; A = Type:L, 396 | term_to_atom(Type:L, Var1) 397 | ; A = Var1 398 | ), 399 | ( is_list(B), 400 | brachylog_list_to_atom(B, Var2) 401 | ; B = _:_, 402 | term_to_atom(B, Var2) 403 | ; Var2 = B 404 | ), 405 | ( Negate = yes, 406 | NegateAtom = '\\+ ' 407 | ; Negate = no, 408 | NegateAtom = '' 409 | ), 410 | ( Reverse = no -> 411 | PredName = P 412 | ; atomic_list_concat([P,'_reversed'], PredName) 413 | ), 414 | ( atomic_list_concat(['brachylog','predicate',_], '_', P) 415 | -> atomic_list_concat([GlobalVariables,','], GlobVars) 416 | ; GlobVars = '' 417 | ), 418 | ( Meta = no -> 419 | atomic_list_concat([',\n ',NegateAtom,PredName,'(',GlobVars,RealSub,',',Var1,',',Var2,')'], Predicate) 420 | ; ( atomic_list_concat(['brachylog','predicate',_], '_', P) 421 | -> atomic_list_concat([GlobalVariables,','], GlobVarsMeta) 422 | ; GlobVarsMeta = 'ignore,' 423 | ), 424 | atomic_list_concat([',\n ',NegateAtom,Meta,'(',GlobVarsMeta,Sup,',',PredName,',',RealSub,',',Var1,',',Var2,')'], Predicate) 425 | ), 426 | transpile_(T, B, no, no, AppendNumber, PredNumber, [T2|OtherPredicates], GlobalVariables). 427 | transpile_(['control':'∧'|T], _, _, _, AppendNumber, PredNumber, [T2|OtherPredicates], GlobalVariables) :- 428 | transpile_(T, 'nothing', no, no, AppendNumber, PredNumber, [T2|OtherPredicates], GlobalVariables). 429 | transpile_(['control':'&'|T], _, _, _, AppendNumber, PredNumber, [T2|OtherPredicates], GlobalVariables) :- 430 | transpile_(T, 'Var_Input_Local', no, no, AppendNumber, PredNumber, [T2|OtherPredicates], GlobalVariables). 431 | transpile_(['control':'`'|T], B, _, _, AppendNumber, PredNumber, [['\n *->\n 1=1'|T2]|OtherPredicates], GlobalVariables) :- 432 | transpile_(T, B, no, no, AppendNumber, PredNumber, [T2|OtherPredicates], GlobalVariables). 433 | transpile_(['control':'∨'|T], _, _, _, AppendNumber, PredNumber, [['\n ;\n 1=1'|T2]|OtherPredicates], GlobalVariables) :- 434 | transpile_(T, 'nothing', no, no, AppendNumber, PredNumber, [T2|OtherPredicates], GlobalVariables). 435 | transpile_(['control':'('|T], B, _, Negate, AppendNumber, PredNumber, [[Parenthesis|T2]|OtherPredicates], GlobalVariables) :- 436 | ( Negate = yes, 437 | Parenthesis = ',\n \\+ (\n 1=1' 438 | ; Negate = no, 439 | Parenthesis = ',\n (\n 1=1' 440 | ), 441 | transpile_(T, B, no, no, AppendNumber, PredNumber, [T2|OtherPredicates], GlobalVariables). 442 | transpile_(['control':')'|T], B, _, _, AppendNumber, PredNumber, [['\n )'|T2]|OtherPredicates], GlobalVariables) :- 443 | transpile_(T, B, no, no, AppendNumber, PredNumber, [T2|OtherPredicates], GlobalVariables). 444 | transpile_(['control':'!'|T], B, _, _, AppendNumber, PredNumber, [[',\n !'|T2]|OtherPredicates], GlobalVariables) :- 445 | transpile_(T, B, no, no, AppendNumber, PredNumber, [T2|OtherPredicates], GlobalVariables). 446 | transpile_(['control':'⊥'|T], B, _, _, AppendNumber, PredNumber, [[',\n false'|T2]|OtherPredicates], GlobalVariables) :- 447 | transpile_(T, B, no, no, AppendNumber, PredNumber, [T2|OtherPredicates], GlobalVariables). 448 | transpile_(['control':'~'|T], B, Reverse, Negate, AppendNumber, PredNumber, [T2|OtherPredicates], GlobalVariables) :- 449 | ( Reverse = yes, 450 | NewReverse = no 451 | ; Reverse = no, 452 | NewReverse = yes 453 | ), 454 | transpile_(T, B, NewReverse, Negate, AppendNumber, PredNumber, [T2|OtherPredicates], GlobalVariables). 455 | transpile_(['control':'¬'|T], B, Reverse, Negate, AppendNumber, PredNumber, [T2|OtherPredicates], GlobalVariables) :- 456 | ( Negate = yes, 457 | NewNegate = no 458 | ; Negate = no, 459 | NewNegate = yes 460 | ), 461 | transpile_(T, B, Reverse, NewNegate, AppendNumber, PredNumber, [T2|OtherPredicates], GlobalVariables). 462 | transpile_(['control':'unpair','variable':A|T], B, _, _, AppendNumber, PredNumber, [[Unpair|T2]|OtherPredicates], GlobalVariables) :- 463 | ( A = TypeA:LA, 464 | term_to_atom(TypeA:LA, TailElem) 465 | ; A = TailElem 466 | ), 467 | ( B = TypeB:LB, 468 | term_to_atom(TypeB:LB, Pair) 469 | ; B = Pair 470 | ), 471 | atomic_list_concat(['UnpairTemp',AppendNumber],HeadElem), 472 | atomic_list_concat([',\n ', 473 | Pair,'=[',HeadElem,',',TailElem,']'],Unpair), 474 | NewAppendNumber is AppendNumber + 1, 475 | transpile_(T, HeadElem, no, no, NewAppendNumber, PredNumber, [T2|OtherPredicates], GlobalVariables). 476 | transpile_(['control':';',Type:A|T], B, _, _, AppendNumber, PredNumber, [T2|OtherPredicates], GlobalVariables) :- 477 | ( Type = 'variable' 478 | ; Type = 'predicate' 479 | ), 480 | append([B], [A], NewVar), 481 | transpile_(T, NewVar, no, no, AppendNumber, PredNumber, [T2|OtherPredicates], GlobalVariables). 482 | transpile_(['control':',','variable':A|T], B, _, _, AppendNumber, PredNumber, [[Append|T2]|OtherPredicates], GlobalVariables) :- 483 | ( is_list(A), 484 | brachylog_list_to_atom(A, Arg1) 485 | ; A = TypeA:LA, 486 | term_to_atom(TypeA:LA, Arg1) 487 | ; A = Arg1 488 | ), 489 | ( is_list(B), 490 | brachylog_list_to_atom(B, Arg2) 491 | ; B = TypeB:LB, 492 | term_to_atom(TypeB:LB, Arg2) 493 | ; B = Arg2 494 | ), 495 | atomic_list_concat(['AppendTemp',AppendNumber],TempVar), 496 | atomic_list_concat([',\n ', 497 | '((',Arg2,' == [], \\+ is_brachylog_list(',Arg1,')) -> ',TempVar,' = [',Arg1,'] ; ', 498 | 'brachylog_concatenate(default,', 499 | '[',Arg2,',',Arg1,']', 500 | ',',TempVar,') -> true ; is_brachylog_list(', 501 | Arg2, 502 | '), brachylog_concatenate(default,', 503 | '[',Arg2,',[',Arg1,']]', 504 | ',',TempVar,') -> true ; brachylog_concatenate(default,', 505 | '[[',Arg2,'],[',Arg1,']],',TempVar,'))' 506 | ], Append), 507 | NewAppendNumber is AppendNumber + 1, 508 | transpile_(T, TempVar, no, no, NewAppendNumber, PredNumber, [T2|OtherPredicates], GlobalVariables). 509 | transpile_(['control':'\n'|T], _, _, _, AppendNumber, PredNumber, [['\n ).\n'],[ReversedPred],[PredHead|T2]|OtherPredicates], GlobalVariables) :- 510 | J is PredNumber + 1, 511 | constraint_variables(GlobalVariables, ConstraintVariables), 512 | atomic_list_concat(['brachylog_predicate_', 513 | J, 514 | '_reversed(', 515 | GlobalVariables, 516 | ',_, Input, Output', 517 | ') :-\n', 518 | ' brachylog_predicate_', 519 | J, 520 | '(', 521 | GlobalVariables, 522 | ',_, Output, Input', 523 | ').\n'], ReversedPred), 524 | atomic_list_concat(['brachylog_predicate_', 525 | J, 526 | '(', 527 | GlobalVariables, 528 | ',_, ', 529 | 'Var_Input_Local', 530 | ',Var_Output_Local', 531 | ') :-\n Name = brachylog_predicate_', 532 | J, 533 | ',\n GlobalVariables = ', 534 | GlobalVariables, 535 | ',\n', 536 | ConstraintVariables, 537 | ' (1=1'], PredHead), 538 | transpile_(T, 'Var_Input_Local', no, no, AppendNumber, J, [T2|OtherPredicates], GlobalVariables). 539 | transpile_(['control':'|'|T], _, _, _, AppendNumber, PredNumber, [['\n ).\n'],[PredHead|T2]|OtherPredicates], GlobalVariables) :- 540 | ( PredNumber = 0, 541 | PredName = 'brachylog_main' 542 | ; PredNumber \= 0, 543 | atomic_list_concat(['brachylog_predicate_',PredNumber], PredName) 544 | ), 545 | constraint_variables(GlobalVariables, ConstraintVariables), 546 | atomic_list_concat([PredName, 547 | '(', 548 | GlobalVariables, 549 | ',_, ', 550 | 'Var_Input_Local', 551 | ',Var_Output_Local', 552 | ') :-\n Name = ', 553 | PredName, 554 | ',\n GlobalVariables = ', 555 | GlobalVariables, 556 | ',\n', 557 | ConstraintVariables, 558 | ' (1=1'], PredHead), 559 | transpile_(T, 'Var_Input_Local', no, no, AppendNumber, PredNumber, [T2|OtherPredicates], GlobalVariables). 560 | 561 | 562 | /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 563 | CONTAINS_WRITE 564 | - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ 565 | contains_write(Code) :- 566 | atom_chars(Code, SplittedCode), 567 | tokenize(SplittedCode, Tokens), 568 | fix_predicates(Tokens, FixedPredicates), 569 | ( member(predicate:brachylog_write:_, FixedPredicates) 570 | ; member(predicate:brachylog_writeln:_, FixedPredicates) 571 | ). 572 | 573 | 574 | /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 575 | CONSTRAINT_VARIABLES 576 | - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ 577 | constraint_variables(GlobalVariables, ConstraintVariables) :- 578 | atom_chars(GlobalVariables, [_|Gs]), 579 | reverse(Gs, [_|RGs]), 580 | reverse(RGs, RRGs), 581 | atomic_list_concat(RRGs, GGs), 582 | atomic_list_concat(GlobVars, ',', GGs), 583 | findall(S, (member(X, GlobVars), 584 | atomic_list_concat(['Var', Name, _], '_', X), 585 | atom_chars(Name, CName), 586 | reverse(CName, [_,'t','n','i','a','r','t','s','n','o','C']), 587 | constraint_variable(X, S)), Ss), 588 | atomic_list_concat(Ss, GlobalConstraintVariables), 589 | 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']), 590 | atomic_list_concat([' constraint',X,'(Var_Constraint',X,'_Local','),\n'], T)), 591 | Ts 592 | ), 593 | atomic_list_concat(Ts, LocalConstraintVariables), 594 | atomic_list_concat([GlobalConstraintVariables, LocalConstraintVariables], ConstraintVariables). 595 | 596 | constraint_variable(X, S) :- 597 | atomic_list_concat(['Var', ConstraintName, _], '_', X), 598 | atom_chars(ConstraintName, [C|Cs]), 599 | downcase_atom(C, CDown), 600 | atomic_list_concat([CDown|Cs], PredName), 601 | atomic_list_concat([' ',PredName,'(',X,'),\n'], S). 602 | 603 | 604 | /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 605 | BRACHYLOG_LIST_TO_ATOM 606 | - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ 607 | brachylog_list_to_atom(List, Atom) :- 608 | brachylog_list_to_atom_(List, T2), 609 | atomic_list_concat(['[',T2,']'], Atom). 610 | 611 | brachylog_list_to_atom_([], ''). 612 | brachylog_list_to_atom_([A], AtomA) :- 613 | ( is_list(A), 614 | brachylog_list_to_atom(A, AtomA) 615 | ; A = _:_, 616 | term_to_atom(A, AtomA) 617 | ; \+ is_list(A), 618 | A \= _:_, 619 | AtomA = A 620 | ). 621 | brachylog_list_to_atom_([A,B|T], Atom) :- 622 | ( is_list(A), 623 | brachylog_list_to_atom(A, AtomA) 624 | ; A = _:_, 625 | term_to_atom(A, AtomA) 626 | ; \+ is_list(A), 627 | A \= _:_, 628 | AtomA = A 629 | ), 630 | brachylog_list_to_atom_([B|T], T2), 631 | atomic_list_concat([AtomA,',',T2], Atom). 632 | 633 | 634 | /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 635 | WRITE_TO_FILE 636 | - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ 637 | write_to_file(File, []) :- 638 | write(File, '\n\n'). 639 | write_to_file(File, [H|T]) :- 640 | write(File, H), 641 | write_to_file(File, T). 642 | -------------------------------------------------------------------------------- /src/metapredicates.pl: -------------------------------------------------------------------------------- 1 | /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 2 | ____ ____ 3 | \ \ / / 4 | \ \ ____ / / 5 | \ \/ \/ / 6 | \ /\ / BRACHYLOG 7 | \ / \ / A terse declarative logic programming language 8 | / \ / \ 9 | / \/ \ Written by Julien Cumin - 2017 10 | / /\____/\ \ https://github.com/JCumin/Brachylog 11 | / / ___ \ \ 12 | /___/ /__/ \___\ 13 | 14 | - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ 15 | 16 | 17 | :- module(metapredicates, [brachylog_meta_accumulate/6, 18 | brachylog_meta_bagof/6, 19 | brachylog_meta_count/6, 20 | brachylog_meta_declare/6, 21 | brachylog_meta_existence/6, 22 | brachylog_meta_find/6, 23 | brachylog_meta_groupby/6, 24 | brachylog_meta_head/6, 25 | brachylog_meta_iterate/6, 26 | brachylog_meta_leftfold/6, 27 | brachylog_meta_map/6, 28 | brachylog_meta_nonexistence/6, 29 | brachylog_meta_orderby/6, 30 | brachylog_meta_select/6, 31 | brachylog_meta_tail/6, 32 | brachylog_meta_unique/6, 33 | brachylog_meta_verify/6, 34 | brachylog_meta_zip/6 35 | ]). 36 | 37 | :- use_module(library(clpfd)). 38 | :- use_module(predicates). 39 | 40 | 41 | /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 42 | BRACHYLOG_META_ACCUMULATE 43 | - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ 44 | brachylog_meta_accumulate(GlobalVariables, 'first', P, Sub, ['integer':I|Input], Output) :- 45 | ( Input = [Arg] -> true 46 | ; Input = Arg 47 | ), 48 | brachylog_meta_accumulate(GlobalVariables, 'integer':I, P, Sub, Arg, Output). 49 | brachylog_meta_accumulate(GlobalVariables, 'last', P, Sub, Input, Output) :- 50 | reverse(Input, ['integer':I|T]), 51 | ( T = [Arg] -> true 52 | ; reverse(T, Arg) 53 | ), 54 | brachylog_meta_accumulate(GlobalVariables, 'integer':I, P, Sub, Arg, Output). 55 | brachylog_meta_accumulate(GlobalVariables, 'default', P, Sub, Input, Output) :- 56 | brachylog_meta_accumulate(GlobalVariables, 'integer':1, P, Sub, Input, Output). 57 | brachylog_meta_accumulate(GlobalVariables, Sup, P, Sub, 'string':Input, Output) :- 58 | brachylog_meta_accumulate(GlobalVariables, Sup, P, Sub, ['string':Input], Output). 59 | brachylog_meta_accumulate(GlobalVariables, Sup, P, Sub, 'integer':Input, Output) :- 60 | brachylog_meta_accumulate(GlobalVariables, Sup, P, Sub, ['integer':Input], Output). 61 | brachylog_meta_accumulate(GlobalVariables, Sup, P, Sub, 'float':Input, Output) :- 62 | brachylog_meta_accumulate(GlobalVariables, Sup, P, Sub, ['float':Input], Output). 63 | brachylog_meta_accumulate(_, 'integer':0, _P, _Sub, Input, Input). 64 | brachylog_meta_accumulate(GlobalVariables, 'integer':I, P, Sub, Input, Output) :- 65 | I #> 0, 66 | is_brachylog_list(Input), 67 | ( GlobalVariables = 'ignore', 68 | call(P, Sub, Input, E) 69 | ; dif(GlobalVariables, 'ignore'), 70 | call(P, GlobalVariables, Sub, Input, E) 71 | ), 72 | J #= I - 1, 73 | append(Input, [E], F), 74 | brachylog_meta_accumulate(GlobalVariables, 'integer':J, P, Sub, F, Output). 75 | 76 | 77 | /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 78 | BRACHYLOG_META_BAGOF 79 | - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ 80 | brachylog_meta_bagof(GlobalVariables, 'first', P, Sub, ['integer':I|Input], Output) :- 81 | ( Input = [Arg] -> true 82 | ; Input = Arg 83 | ), 84 | brachylog_meta_bagof(GlobalVariables, 'integer':I, P, Sub, Arg, Output). 85 | brachylog_meta_bagof(GlobalVariables, 'last', P, Sub, Input, Output) :- 86 | reverse(Input, ['integer':I|T]), 87 | ( T = [Arg] -> true 88 | ; reverse(T, Arg) 89 | ), 90 | brachylog_meta_bagof(GlobalVariables, 'integer':I, P, Sub, Arg, Output). 91 | brachylog_meta_bagof(_, 'integer':0, _, _, _, []). 92 | brachylog_meta_bagof(GlobalVariables, 'default', P, Sub, Input, Output) :- 93 | bagof(X, 94 | ( GlobalVariables = 'ignore', 95 | call(P, Sub, Input, X) 96 | ; dif(GlobalVariables, 'ignore'), 97 | call(P, GlobalVariables, Sub, Input, X) 98 | ), 99 | Output). 100 | brachylog_meta_bagof(GlobalVariables, 'integer':I, P, Sub, Input, Output) :- 101 | I #> 0, 102 | bagof(X, call_firstn( 103 | ( GlobalVariables = 'ignore', 104 | call(P, Sub, Input, X) 105 | ; dif(GlobalVariables, 'ignore'), 106 | call(P, GlobalVariables, Sub, Input, X) 107 | ), I), 108 | Output). 109 | 110 | 111 | /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 112 | BRACHYLOG_META_COUNT 113 | - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ 114 | brachylog_meta_count(GlobalVariables, 'first', P, Sub, ['integer':I|Input], Output) :- 115 | ( Input = [Arg] -> true 116 | ; Input = Arg 117 | ), 118 | brachylog_meta_count(GlobalVariables, 'integer':I, P, Sub, Arg, Output). 119 | brachylog_meta_count(GlobalVariables, 'last', P, Sub, Input, Output) :- 120 | reverse(Input, ['integer':I|T]), 121 | ( T = [Arg] -> true 122 | ; reverse(T, Arg) 123 | ), 124 | brachylog_meta_count(GlobalVariables, 'integer':I, P, Sub, Arg, Output). 125 | brachylog_meta_count(GlobalVariables, 'default', P, Sub, Input, Output) :- 126 | brachylog_meta_count(GlobalVariables, 'integer':0, P, Sub, Input, Output). 127 | brachylog_meta_count(GlobalVariables, 'integer':0, P, Sub, Input, Output) :- 128 | brachylog_meta_find(GlobalVariables, 'default', P, Sub, Input, E), 129 | brachylog_length('default', E, Output). 130 | brachylog_meta_count(GlobalVariables, 'integer':1, P, Sub, Input, Output) :- 131 | brachylog_meta_unique(GlobalVariables, 'default', P, Sub, Input, E), 132 | brachylog_length('default', E, Output). 133 | 134 | 135 | /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 136 | BRACHYLOG_META_DECLARE 137 | - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ 138 | brachylog_meta_declare(GlobalVariables, 'first', P, Sub, ['integer':I|Input], Output) :- 139 | ( Input = [Arg] -> true 140 | ; Input = Arg 141 | ), 142 | brachylog_meta_declare(GlobalVariables, 'integer':I, P, Sub, Arg, Output). 143 | brachylog_meta_declare(GlobalVariables, 'last', P, Sub, Input, Output) :- 144 | reverse(Input, ['integer':I|T]), 145 | ( T = [Arg] -> true 146 | ; reverse(T, Arg) 147 | ), 148 | brachylog_meta_declare(GlobalVariables, 'integer':I, P, Sub, Arg, Output). 149 | brachylog_meta_declare(GlobalVariables, 'default', P, Sub, [H,T], T) :- 150 | ( GlobalVariables = 'ignore', 151 | call(P, Sub, H, T) 152 | ; dif(GlobalVariables, 'ignore'), 153 | call(P, GlobalVariables, Sub, H, T) 154 | ). 155 | brachylog_meta_declare(GlobalVariables, 'integer':0, P, Sub, [H,T], [H,T]) :- 156 | ( GlobalVariables = 'ignore', 157 | call(P, Sub, H, T) 158 | ; dif(GlobalVariables, 'ignore'), 159 | call(P, GlobalVariables, Sub, H, T) 160 | ). 161 | brachylog_meta_declare(GlobalVariables, 'integer':1, P, Sub, [H,T], H) :- 162 | ( GlobalVariables = 'ignore', 163 | call(P, Sub, T, H) 164 | ; dif(GlobalVariables, 'ignore'), 165 | call(P, GlobalVariables, Sub, T, H) 166 | ). 167 | brachylog_meta_declare(GlobalVariables, 'integer':2, P, Sub, [H,T], [H,T]) :- 168 | ( GlobalVariables = 'ignore', 169 | call(P, Sub, T, H) 170 | ; dif(GlobalVariables, 'ignore'), 171 | call(P, GlobalVariables, Sub, T, H) 172 | ). 173 | 174 | 175 | /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 176 | BRACHYLOG_META_EXISTENCE 177 | - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ 178 | brachylog_meta_existence(GlobalVariables, 'first', P, Sub, [I|Input], Arg) :- 179 | ( Input = [Arg] -> true 180 | ; Input = Arg 181 | ), 182 | brachylog_meta_existence(GlobalVariables, P, Sub, Arg, I). 183 | brachylog_meta_existence(GlobalVariables, 'last', P, Sub, Input, Arg) :- 184 | reverse(Input, [I|T]), 185 | ( T = [Arg] -> true 186 | ; reverse(T, Arg) 187 | ), 188 | brachylog_meta_existence(GlobalVariables, P, Sub, Arg, I). 189 | brachylog_meta_existence(GlobalVariables, 'integer':I, P, Sub, Input, Input) :- 190 | dif(I, 'default'), 191 | brachylog_meta_existence(GlobalVariables, P, Sub, Input, 'integer':I). 192 | brachylog_meta_existence(GlobalVariables, 'default', P, Sub, Input, Output) :- 193 | brachylog_meta_existence(GlobalVariables, P, Sub, Input, Output). 194 | 195 | brachylog_meta_existence(GlobalVariables, P, Sub, Input, Output) :- 196 | brachylog_in('default', Input, E), 197 | ( GlobalVariables = 'ignore', 198 | call(P, Sub, E, Output) 199 | ; dif(GlobalVariables, 'ignore'), 200 | call(P, GlobalVariables, Sub, E, Output) 201 | ). 202 | 203 | 204 | /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 205 | BRACHYLOG_META_FIND 206 | 207 | Credits to @false for call_firstf/2 and call_nth/2 208 | http://stackoverflow.com/a/20866206/2554145 209 | http://stackoverflow.com/a/11400256/2554145 210 | - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ 211 | brachylog_meta_find(GlobalVariables, 'first', P, Sub, ['integer':I|Input], Output) :- 212 | ( Input = [Arg] -> true 213 | ; Input = Arg 214 | ), 215 | brachylog_meta_find(GlobalVariables, 'integer':I, P, Sub, Arg, Output). 216 | brachylog_meta_find(GlobalVariables, 'last', P, Sub, Input, Output) :- 217 | reverse(Input, ['integer':I|T]), 218 | ( T = [Arg] -> true 219 | ; reverse(T, Arg) 220 | ), 221 | brachylog_meta_find(GlobalVariables, 'integer':I, P, Sub, Arg, Output). 222 | brachylog_meta_find(_, 'integer':0, _, _, _, []). 223 | brachylog_meta_find(GlobalVariables, 'default', P, Sub, Input, Output) :- 224 | findall(X, 225 | ( GlobalVariables = 'ignore', 226 | call(P, Sub, Input, X) 227 | ; dif(GlobalVariables, 'ignore'), 228 | call(P, GlobalVariables, Sub, Input, X) 229 | ), 230 | Output). 231 | brachylog_meta_find(GlobalVariables, 'integer':I, P, Sub, Input, Output) :- 232 | I #> 0, 233 | findall(X, call_firstn( 234 | ( GlobalVariables = 'ignore', 235 | call(P, Sub, Input, X) 236 | ; dif(GlobalVariables, 'ignore'), 237 | call(P, GlobalVariables, Sub, Input, X) 238 | ), I), 239 | Output). 240 | 241 | call_firstn(Goal_0, N) :- 242 | N + N mod 1 >= 0, % ensures that N >=0 and N is an integer 243 | call_nth(Goal_0, Nth), 244 | ( Nth == N -> ! ; true ). 245 | 246 | call_nth(Goal_0, C) :- 247 | State = count(0, _), 248 | Goal_0, 249 | arg(1, State, C1), 250 | C2 is C1+1, 251 | nb_setarg(1, State, C2), 252 | C = C2. 253 | 254 | 255 | /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 256 | BRACHYLOG_META_GROUPBY 257 | - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ 258 | brachylog_meta_groupby(GlobalVariables, 'first', P, Sub, ['integer':I|Input], Output) :- 259 | ( Input = [Arg] -> true 260 | ; Input = Arg 261 | ), 262 | brachylog_meta_groupby(GlobalVariables, 'integer':I, P, Sub, Arg, Output). 263 | brachylog_meta_groupby(GlobalVariables, 'last', P, Sub, Input, Output) :- 264 | reverse(Input, ['integer':I|T]), 265 | ( T = [Arg] -> true 266 | ; reverse(T, Arg) 267 | ), 268 | brachylog_meta_groupby(GlobalVariables, 'integer':I, P, Sub, Arg, Output). 269 | brachylog_meta_groupby(GlobalVariables, 'default', P, Sub, Input, Output) :- 270 | ( is_brachylog_list(Input) -> FixedInput = Input 271 | ; brachylog_elements('default', Input, FixedInput) 272 | ), 273 | brachylog_meta_map(GlobalVariables, 'default', P, Sub, FixedInput, L), 274 | brachylog_zip('default', [L,Input], L2), 275 | brachylog_meta_groupby_group(L2, L3), 276 | maplist(brachylog_meta_groupby_tail, L3, Output). 277 | 278 | brachylog_meta_groupby_group(L, Gs) :- 279 | brachylog_meta_groupby_group(L, [], Gs). 280 | 281 | brachylog_meta_groupby_group([], Gs, Gs). 282 | brachylog_meta_groupby_group([[G,H]|T], TempGs, Gs) :- 283 | ( member(G:L, TempGs) -> 284 | reverse(L, RL), 285 | reverse([H|RL], L2), 286 | select(G:L, TempGs, G:L2, TempGs2) 287 | ; append(TempGs, [G:[H]], TempGs2) 288 | ), 289 | brachylog_meta_groupby_group(T, TempGs2, Gs). 290 | 291 | brachylog_meta_groupby_tail(_:T, T). 292 | 293 | 294 | /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 295 | BRACHYLOG_META_HEAD 296 | - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ 297 | brachylog_meta_head(GlobalVariables, 'first', P, Sub, ['integer':I|Input], Output) :- 298 | ( Input = [Arg] -> true 299 | ; Input = Arg 300 | ), 301 | brachylog_meta_head(GlobalVariables, 'integer':I, P, Sub, Arg, Output). 302 | brachylog_meta_head(GlobalVariables, 'last', P, Sub, Input, Output) :- 303 | reverse(Input, ['integer':I|T]), 304 | ( T = [Arg] -> true 305 | ; reverse(T, Arg) 306 | ), 307 | brachylog_meta_head(GlobalVariables, 'integer':I, P, Sub, Arg, Output). 308 | brachylog_meta_head(GlobalVariables, 'default', P, Sub, Input, Output) :- 309 | brachylog_meta_head(GlobalVariables, 'integer':1, P, Sub, Input, Output). 310 | brachylog_meta_head(_, 'integer':0, _, _, Input, Input). 311 | brachylog_meta_head(GlobalVariables, 'integer':I, P, Sub, Input, Output) :- 312 | I #> 0, 313 | brachylog_head('integer':I, Input, Heads), 314 | brachylog_behead('integer':I, Input, Tails), 315 | brachylog_meta_map(GlobalVariables, 'default', P, Sub, Heads, NewHeads), 316 | brachylog_concatenate('default', [NewHeads,Tails], Output). 317 | 318 | 319 | /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 320 | BRACHYLOG_META_ITERATE 321 | - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ 322 | brachylog_meta_iterate(GlobalVariables, 'first', P, Sub, ['integer':I|Input], Output) :- 323 | ( Input = [Arg] -> true 324 | ; Input = Arg 325 | ), 326 | brachylog_meta_iterate(GlobalVariables, 'integer':I, P, Sub, Arg, Output). 327 | brachylog_meta_iterate(GlobalVariables, 'last', P, Sub, Input, Output) :- 328 | reverse(Input, ['integer':I|T]), 329 | ( T = [Arg] -> true 330 | ; reverse(T, Arg) 331 | ), 332 | brachylog_meta_iterate(GlobalVariables, 'integer':I, P, Sub, Arg, Output). 333 | brachylog_meta_iterate(_, 'integer':0, _, _, Input, Input). 334 | brachylog_meta_iterate(GlobalVariables, 'default', P, Sub, Input, Output) :- 335 | I #>= 1, 336 | brachylog_meta_iterate(GlobalVariables, 'integer':I, P, Sub, Input, Output). 337 | brachylog_meta_iterate(GlobalVariables, 'integer':1, P, Sub, Input, Output) :- 338 | ( GlobalVariables = 'ignore', 339 | call(P, Sub, Input, Output) 340 | ; dif(GlobalVariables, 'ignore'), 341 | call(P, GlobalVariables, Sub, Input, Output) 342 | ). 343 | brachylog_meta_iterate(GlobalVariables, 'integer':I, P, Sub, Input, Output) :- 344 | I #> 1, 345 | ( GlobalVariables = 'ignore', 346 | call(P, Sub, Input, TOutput) 347 | ; dif(GlobalVariables, 'ignore'), 348 | call(P, GlobalVariables, Sub, Input, TOutput) 349 | ), 350 | J #= I - 1, 351 | brachylog_meta_iterate(GlobalVariables, 'integer':J, P, Sub, TOutput, Output). 352 | 353 | 354 | /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 355 | BRACHYLOG_META_LEFTFOLD 356 | - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ 357 | brachylog_meta_leftfold(GlobalVariables, 'first', P, Sub, ['integer':I|Input], Output) :- 358 | ( Input = [Arg] -> true 359 | ; Input = Arg 360 | ), 361 | brachylog_meta_leftfold(GlobalVariables, 'integer':I, P, Sub, Arg, Output). 362 | brachylog_meta_leftfold(GlobalVariables, 'last', P, Sub, Input, Output) :- 363 | reverse(Input, ['integer':I|T]), 364 | ( T = [Arg] -> true 365 | ; reverse(T, Arg) 366 | ), 367 | brachylog_meta_leftfold(GlobalVariables, 'integer':I, P, Sub, Arg, Output). 368 | brachylog_meta_leftfold(GlobalVariables, 'default', P, Sub, 'string':S, Output) :- 369 | brachylog_elements('default', 'string':S, E), 370 | brachylog_meta_leftfold(GlobalVariables, 'default', P, Sub, E, O), 371 | ( brachylog_concatenate('default', O, X), 372 | X = 'string':_ -> 373 | Output = X 374 | ; Output = O 375 | ). 376 | brachylog_meta_leftfold(GlobalVariables, 'default', P, Sub, 'integer':Input, Output) :- 377 | brachylog_elements('default', 'integer':Input, E), 378 | brachylog_meta_leftfold(GlobalVariables, 'default', P, Sub, E, O), 379 | ( brachylog_concatenate('default', O, X), 380 | X = 'integer':_ -> 381 | Output = X 382 | ; Output = O 383 | ). 384 | brachylog_meta_leftfold(_, 'default', _P, _Sub, [], []). 385 | brachylog_meta_leftfold(_, 'default', _P, _Sub, [X], [X]). 386 | brachylog_meta_leftfold(GlobalVariables, 'default', P, Sub, [H,I|T], Output) :- 387 | brachylog_meta_leftfold_(GlobalVariables, P, Sub, [I|T], H, Output). 388 | 389 | brachylog_meta_leftfold_(_, _P, _Sub, [], Output, Output). 390 | brachylog_meta_leftfold_(GlobalVariables, P, Sub, [H|T], A, Output) :- 391 | ( GlobalVariables = 'ignore', 392 | call(P, Sub, [A,H], E) 393 | ; dif(GlobalVariables, 'ignore'), 394 | call(P, GlobalVariables, Sub, [A,H], E) 395 | ), 396 | brachylog_meta_leftfold_(GlobalVariables, P, Sub, T, E, Output). 397 | 398 | 399 | /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 400 | BRACHYLOG_META_MAP 401 | - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ 402 | brachylog_meta_map(GlobalVariables, 'first', P, Sub, ['integer':I|Input], Output) :- 403 | ( Input = [Arg] -> true 404 | ; Input = Arg 405 | ), 406 | brachylog_meta_map(GlobalVariables, 'integer':I, P, Sub, Arg, Output). 407 | brachylog_meta_map(GlobalVariables, 'last', P, Sub, Input, Output) :- 408 | reverse(Input, ['integer':I|T]), 409 | ( T = [Arg] -> true 410 | ; reverse(T, Arg) 411 | ), 412 | brachylog_meta_map(GlobalVariables, 'integer':I, P, Sub, Arg, Output). 413 | brachylog_meta_map(GlobalVariables, 'integer':0, P, Sub, Input, Output) :- 414 | ( GlobalVariables = 'ignore', 415 | call(P, Sub, Input, Output) 416 | ; dif(GlobalVariables, 'ignore'), 417 | call(P, GlobalVariables, Sub, Input, Output) 418 | ). 419 | brachylog_meta_map(GlobalVariables, 'default', P, Sub, Input, Output) :- 420 | brachylog_meta_map(GlobalVariables, 'integer':1, P, Sub, Input, Output). 421 | brachylog_meta_map(GlobalVariables, 'integer':I, P, Sub, 'string':S, Output) :- 422 | brachylog_elements('default', 'string':S, E), 423 | brachylog_meta_map(GlobalVariables, 'integer':I, P, Sub, E, O), 424 | ( brachylog_concatenate('default', O, X), 425 | X = 'string':_ -> 426 | Output = X 427 | ; Output = O 428 | ). 429 | brachylog_meta_map(GlobalVariables, 'integer':I, P, Sub, 'integer':Input, Output) :- 430 | brachylog_elements('default', 'integer':Input, E), 431 | brachylog_meta_map(GlobalVariables, 'integer':I, P, Sub, E, O), 432 | ( brachylog_concatenate('default', O, X), 433 | X = 'integer':_ -> 434 | Output = X 435 | ; Output = O 436 | ). 437 | brachylog_meta_map(GlobalVariables, 'integer':1, P, Sub, Input, Output) :- 438 | ( GlobalVariables = 'ignore', 439 | Pred =.. [P, Sub] 440 | ; dif(GlobalVariables, 'ignore'), 441 | Pred =.. [P, GlobalVariables, Sub] 442 | ), 443 | is_brachylog_list(Input), 444 | maplist(Pred, Input, Output). 445 | brachylog_meta_map(GlobalVariables, 'integer':I, P, Sub, Input, Output) :- 446 | I #> 1, 447 | J #= I - 1, 448 | is_brachylog_list(Input), 449 | maplist(brachylog_meta_map(GlobalVariables, 'integer':J, P, Sub), Input, Output). 450 | 451 | 452 | /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 453 | BRACHYLOG_META_NONEXISTENCE 454 | - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ 455 | brachylog_meta_nonexistence(GlobalVariables, 'first', P, Sub, [I|Input], Arg) :- 456 | ( Input = [Arg] -> true 457 | ; Input = Arg 458 | ), 459 | brachylog_meta_nonexistence(GlobalVariables, P, Sub, Arg, I). 460 | brachylog_meta_nonexistence(GlobalVariables, 'last', P, Sub, Input, Arg) :- 461 | reverse(Input, [I|T]), 462 | ( T = [Arg] -> true 463 | ; reverse(T, Arg) 464 | ), 465 | brachylog_meta_nonexistence(GlobalVariables, P, Sub, Arg, I). 466 | brachylog_meta_nonexistence(GlobalVariables, 'integer':I, P, Sub, Input, Input) :- 467 | dif(I, 'default'), 468 | brachylog_meta_nonexistence(GlobalVariables, P, Sub, Input, 'integer':I). 469 | brachylog_meta_nonexistence(GlobalVariables, 'default', P, Sub, Input, Output) :- 470 | brachylog_meta_nonexistence(GlobalVariables, P, Sub, Input, Output). 471 | 472 | brachylog_meta_nonexistence(GlobalVariables, P, Sub, Input, Output) :- 473 | brachylog_meta_map(GlobalVariables, 'default', P, Sub, Input, T), 474 | brachylog_zip('default', [T,[Output]], Z), 475 | brachylog_meta_map(GlobalVariables, 'default', brachylog_different, 'default', Z, _). 476 | 477 | 478 | /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 479 | BRACHYLOG_META_ORDERBY 480 | - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ 481 | brachylog_meta_orderby(GlobalVariables, 'first', P, Sub, ['integer':I|Input], Output) :- 482 | ( Input = [Arg] -> true 483 | ; Input = Arg 484 | ), 485 | brachylog_meta_orderby(GlobalVariables, 'integer':I, P, Sub, Arg, Output). 486 | brachylog_meta_orderby(GlobalVariables, 'last', P, Sub, Input, Output) :- 487 | reverse(Input, ['integer':I|T]), 488 | ( T = [Arg] -> true 489 | ; reverse(T, Arg) 490 | ), 491 | brachylog_meta_orderby(GlobalVariables, 'integer':I, P, Sub, Arg, Output). 492 | brachylog_meta_orderby(GlobalVariables, 'default', P, Sub, Input, Output) :- 493 | brachylog_meta_orderby(GlobalVariables, 'integer':0, P, Sub, Input, Output). 494 | brachylog_meta_orderby(GlobalVariables, 'integer':0, P, Sub, Input, Output) :- 495 | ( is_brachylog_list(Input) -> FixedInput = Input 496 | ; brachylog_elements('default', Input, FixedInput) 497 | ), 498 | brachylog_meta_map(GlobalVariables, 'default', P, Sub, FixedInput, L), 499 | brachylog_zip('default', [L,Input], L2), 500 | brachylog_order(integer:0, L2, SL2), 501 | ( SL2 = [] -> 502 | Output = [] 503 | ; brachylog_zip('default', SL2, [_,Output]) 504 | ). 505 | brachylog_meta_orderby(GlobalVariables, 'integer':1, P, Sub, Input, Output) :- 506 | ( is_brachylog_list(Input) -> FixedInput = Input 507 | ; brachylog_elements('default', Input, FixedInput) 508 | ), 509 | brachylog_meta_map(GlobalVariables, 'default', P, Sub, FixedInput, L), 510 | brachylog_zip('default', [L,Input], L2), 511 | brachylog_order(integer:1, L2, SL2), 512 | ( SL2 = [] -> 513 | Output = [] 514 | ; brachylog_zip('default', SL2, [_,Output]) 515 | ). 516 | brachylog_meta_orderby(GlobalVariables, 'integer':2, P, Sub, Input, Output) :- 517 | ( is_brachylog_list(Input) -> FixedInput = Input 518 | ; brachylog_elements('default', Input, FixedInput) 519 | ), 520 | brachylog_meta_map(GlobalVariables, 'default', P, Sub, FixedInput, L), 521 | brachylog_order(integer:0, L, Output). 522 | brachylog_meta_orderby(GlobalVariables, 'integer':3, P, Sub, Input, Output) :- 523 | ( is_brachylog_list(Input) -> FixedInput = Input 524 | ; brachylog_elements('default', Input, FixedInput) 525 | ), 526 | brachylog_meta_map(GlobalVariables, 'default', P, Sub, FixedInput, L), 527 | brachylog_order(integer:1, L, Output). 528 | 529 | 530 | /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 531 | BRACHYLOG_META_SELECT 532 | - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ 533 | brachylog_meta_select(GlobalVariables, 'first', P, Sub, ['integer':I|Input], Output) :- 534 | ( Input = [Arg] -> true 535 | ; Input = Arg 536 | ), 537 | brachylog_meta_select(GlobalVariables, 'integer':I, P, Sub, Arg, Output). 538 | brachylog_meta_select(GlobalVariables, 'last', P, Sub, Input, Output) :- 539 | reverse(Input, ['integer':I|T]), 540 | ( T = [Arg] -> true 541 | ; reverse(T, Arg) 542 | ), 543 | brachylog_meta_select(GlobalVariables, 'integer':I, P, Sub, Arg, Output). 544 | brachylog_meta_select(GlobalVariables, 'default', P, Sub, 'string':S, Output) :- 545 | brachylog_elements('default', 'string':S, E), 546 | brachylog_meta_select(GlobalVariables, 'default', P, Sub, E, O), 547 | ( brachylog_concatenate('default', O, X), 548 | X = 'string':_ -> 549 | Output = X 550 | ; Output = O 551 | ). 552 | brachylog_meta_select(GlobalVariables, 'default', P, Sub, 'integer':S, Output) :- 553 | brachylog_elements('default', 'integer':S, E), 554 | brachylog_meta_select(GlobalVariables, 'default', P, Sub, E, O), 555 | ( brachylog_concatenate('default', O, X), 556 | X = 'integer':_ -> 557 | Output = X 558 | ; Output = O 559 | ). 560 | brachylog_meta_select(_, 'default', _, _, [], []). 561 | brachylog_meta_select(GlobalVariables, 'default', P, Sub, [H|T], Output) :- 562 | ( ( GlobalVariables = 'ignore', 563 | call(P, Sub, H, H2) 564 | ; dif(GlobalVariables, 'ignore'), 565 | call(P, GlobalVariables, Sub, H, H2) 566 | ) 567 | *-> Output = [H2|T2] 568 | ; Output = T2 569 | ), 570 | brachylog_meta_select(GlobalVariables, 'default', P, Sub, T, T2). 571 | 572 | 573 | /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 574 | BRACHYLOG_META_TAIL 575 | - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ 576 | brachylog_meta_tail(GlobalVariables, 'first', P, Sub, ['integer':I|Input], Output) :- 577 | ( Input = [Arg] -> true 578 | ; Input = Arg 579 | ), 580 | brachylog_meta_tail(GlobalVariables, 'integer':I, P, Sub, Arg, Output). 581 | brachylog_meta_tail(GlobalVariables, 'last', P, Sub, Input, Output) :- 582 | reverse(Input, ['integer':I|T]), 583 | ( T = [Arg] -> true 584 | ; reverse(T, Arg) 585 | ), 586 | brachylog_meta_tail(GlobalVariables, 'integer':I, P, Sub, Arg, Output). 587 | brachylog_meta_tail(GlobalVariables, 'default', P, Sub, Input, Output) :- 588 | brachylog_meta_tail(GlobalVariables, 'integer':1, P, Sub, Input, Output). 589 | brachylog_meta_tail(_, 'integer':0, _, _, Input, Input). 590 | brachylog_meta_tail(GlobalVariables, 'integer':I, P, Sub, Input, Output) :- 591 | I #> 0, 592 | brachylog_tail('integer':I, Input, Tails), 593 | brachylog_knife('integer':I, Input, Heads), 594 | brachylog_meta_map(GlobalVariables, 'default', P, Sub, Tails, NewTails), 595 | brachylog_concatenate('default', [Heads,NewTails], Output). 596 | 597 | 598 | /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 599 | BRACHYLOG_META_UNIQUE 600 | - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ 601 | brachylog_meta_unique(GlobalVariables, 'first', P, Sub, ['integer':I|Input], Output) :- 602 | ( Input = [Arg] -> true 603 | ; Input = Arg 604 | ), 605 | brachylog_meta_unique(GlobalVariables, 'integer':I, P, Sub, Arg, Output). 606 | brachylog_meta_unique(GlobalVariables, 'last', P, Sub, Input, Output) :- 607 | reverse(Input, ['integer':I|T]), 608 | ( T = [Arg] -> true 609 | ; reverse(T, Arg) 610 | ), 611 | brachylog_meta_unique(GlobalVariables, 'integer':I, P, Sub, Arg, Output). 612 | brachylog_meta_unique(GlobalVariables, 'default', P, Sub, Input, Output) :- 613 | brachylog_meta_unique_(GlobalVariables, 1, -1, P, Sub, Input, [], Output). 614 | brachylog_meta_unique(_, 'integer':0, _, _, _, []). 615 | brachylog_meta_unique(GlobalVariables, 'integer':I, P, Sub, Input, Output) :- 616 | brachylog_meta_unique_(GlobalVariables, 1, I, P, Sub, Input, [], Output). 617 | 618 | brachylog_meta_unique_(_, _, 0, _, _, _, ROutput, Output) :- 619 | reverse(ROutput, Output). 620 | brachylog_meta_unique_(GlobalVariables, Nth, J, P, Sub, Input, A, Output) :- 621 | J #\= 0, 622 | ( call_nth( ( GlobalVariables = 'ignore', 623 | call(P, Sub, Input, X) 624 | ; dif(GlobalVariables, 'ignore'), 625 | call(P, GlobalVariables, Sub, Input, X) 626 | ), Nth) -> 627 | ( \+ member(X, A) -> 628 | M #= Nth + 1, 629 | K #= J - 1, 630 | brachylog_meta_unique_(GlobalVariables, M, K, P, Sub, Input, [X|A], Output) 631 | ; M #= Nth + 1, 632 | brachylog_meta_unique_(GlobalVariables, M, J, P, Sub, Input, A, Output) 633 | ) 634 | ; reverse(A, Output) 635 | ). 636 | 637 | 638 | /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 639 | BRACHYLOG_META_VERIFY 640 | - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ 641 | brachylog_meta_verify(GlobalVariables, 'first', P, Sub, [I|Input], Arg) :- 642 | ( Input = [Arg] -> true 643 | ; Input = Arg 644 | ), 645 | brachylog_meta_verify(GlobalVariables, P, Sub, Arg, I). 646 | brachylog_meta_verify(GlobalVariables, 'last', P, Sub, Input, Arg) :- 647 | reverse(Input, [I|T]), 648 | ( T = [Arg] -> true 649 | ; reverse(T, Arg) 650 | ), 651 | brachylog_meta_verify(GlobalVariables, P, Sub, Arg, I). 652 | brachylog_meta_verify(GlobalVariables, 'integer':I, P, Sub, Input, Input) :- 653 | dif(I, 'default'), 654 | brachylog_meta_verify(GlobalVariables, P, Sub, Input, 'integer':I). 655 | brachylog_meta_verify(GlobalVariables, 'default', P, Sub, Input, Output) :- 656 | brachylog_meta_verify(GlobalVariables, P, Sub, Input, Output). 657 | 658 | brachylog_meta_verify(GlobalVariables, P, Sub, Input, Output) :- 659 | brachylog_length('default', Input, L), 660 | brachylog_length('default', T, L), 661 | brachylog_equal('default', T, _), 662 | brachylog_head('default', T, Output), 663 | brachylog_meta_map(GlobalVariables, 'default', P, Sub, Input, T). 664 | 665 | /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 666 | BRACHYLOG_META_ZIP 667 | - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ 668 | brachylog_meta_zip(GlobalVariables, 'first', P, Sub, ['integer':I|Input], Output) :- 669 | ( Input = [Arg] -> true 670 | ; Input = Arg 671 | ), 672 | brachylog_meta_zip(GlobalVariables, 'integer':I, P, Sub, Arg, Output). 673 | brachylog_meta_zip(GlobalVariables, 'last', P, Sub, Input, Output) :- 674 | reverse(Input, ['integer':I|T]), 675 | ( T = [Arg] -> true 676 | ; reverse(T, Arg) 677 | ), 678 | brachylog_meta_zip(GlobalVariables, 'integer':I, P, Sub, Arg, Output). 679 | brachylog_meta_zip(GlobalVariables, 'default', P, Sub, Arg, Output) :- 680 | brachylog_meta_map(GlobalVariables, 'default', P, Sub, Arg, O), 681 | brachylog_zip('default', [Arg,O], Output). 682 | brachylog_meta_zip(GlobalVariables, 'integer':0, P, Sub, Arg, Output) :- 683 | brachylog_meta_find(GlobalVariables, 'default', P, Sub, Arg, O), 684 | brachylog_zip('default', [Arg,O], Output). 685 | brachylog_meta_zip(GlobalVariables, 'integer':1, P, Sub, Arg, Output) :- 686 | brachylog_meta_map(GlobalVariables, 'default', P, Sub, Arg, O), 687 | brachylog_zip('default', [O,Arg], Output). 688 | brachylog_meta_zip(GlobalVariables, 'integer':2, P, Sub, Arg, Output) :- 689 | brachylog_meta_find(GlobalVariables, 'default', P, Sub, Arg, O), 690 | brachylog_zip('default', [O,Arg], Output). 691 | --------------------------------------------------------------------------------