{"id":26448770,"url":"https://github.com/mohamadcs/prologtranspiler","last_synced_at":"2026-02-27T04:04:43.312Z","repository":{"id":267468651,"uuid":"901349794","full_name":"MohamadCS/PrologTranspiler","owner":"MohamadCS","description":"Extended Prolog.","archived":false,"fork":false,"pushed_at":"2025-02-07T05:23:05.000Z","size":39975,"stargazers_count":2,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"master","last_synced_at":"2025-10-26T20:50:51.455Z","etag":null,"topics":["antlr4","compiler","cpp","prolog","transpiler"],"latest_commit_sha":null,"homepage":"","language":"C++","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":"emily-dror/prolog_antlr","license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/MohamadCS.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2024-12-10T13:52:16.000Z","updated_at":"2025-02-07T05:23:08.000Z","dependencies_parsed_at":"2025-02-07T06:21:36.957Z","dependency_job_id":"74e3dbd7-e9c1-48fe-ad15-a88ea23729ba","html_url":"https://github.com/MohamadCS/PrologTranspiler","commit_stats":null,"previous_names":["mohamadcs/prolog_antlr","mohamadcs/prologtranspiler"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/MohamadCS/PrologTranspiler","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/MohamadCS%2FPrologTranspiler","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/MohamadCS%2FPrologTranspiler/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/MohamadCS%2FPrologTranspiler/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/MohamadCS%2FPrologTranspiler/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/MohamadCS","download_url":"https://codeload.github.com/MohamadCS/PrologTranspiler/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/MohamadCS%2FPrologTranspiler/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":29884515,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-02-26T23:51:21.483Z","status":"online","status_checked_at":"2026-02-27T02:00:06.759Z","response_time":57,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["antlr4","compiler","cpp","prolog","transpiler"],"created_at":"2025-03-18T14:42:22.386Z","updated_at":"2026-02-27T04:04:43.298Z","avatar_url":"https://github.com/MohamadCS.png","language":"C++","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Introduction\n\n`Prolog*` is a an extention to the Prolog programming language. It aims\nto combine the functional features of Prolog, with modern features found\non other functional and oop programming languages.\n\n`Prolog*` introduces many features, from complete functions, to\nintuitive syntactic sugar.\n\n# Compiler\n\n## Usage\n\nIn order to compile a `Prolog*` file we can use\n\n``` {.bash language=\"bash\"}\nprolog -i my_file.txt \n```\n\nthis will compile `my_file.txt` to the prolog file `my_file.pl`.\n\n## Flags\n\n-   `-i –input` : To specify the input `Prolog*` file.\n\n-   `-o –output` : Followed by the name of the prolog output file.\n\n-   `–format`: Formats the output file.\n\n-   `–no-semantics`: Disables the semantic checker.\n\n::: note\n*Note 1*. The output file must be interpreted using `swipl`, as its the\nonly interpreter tested for this project.\n:::\n\n# Expressions\n\nExpressions in `Prolog*` are on of the following\n\n-   Tuples.\n\n-   Functions invocation.\n\n-   Extended Prolog term.\n\n-   Lambda.\n\n-   Matching statment.\n\n-   If-else statements.\n\nWe will expand on each one of them later.\n\n## Extended Prolog Term\n\nYou can expect each prolog term to work as it is in regular prolog,\nhowever `Prolog*` allows for new expressions that we defined above to be\nused inside lists and predicate calls.\n\n# Tuples\n\nTuples are simply lists of\n\n-   Expressions\n\n-   Bindings.\n\n-   If statments (Without else).\n\nTuples follows the following rules\n\n-   If the expression is followed by the seperator `,` then the\n    expression is non-vanishing, that is its value is evaluated, and is\n    is an entry in the final tuple.\n\n-   If the expression is is followed by the seperator `;` then the\n    expression is vanishing, that is its value is evaluated, and its not\n    an entry in the final tuple.\n\n-   If the last item is not followed by a seperator, then it is treated\n    as a non-vanishing entry.\n\n-   If the tuple is empty then its a vanishing entry regardless of the\n    following seperater.\n\n-   If the tuple entry is a direct predicate call then it has a special\n    behavior: if the predicate call evaluates to true, then the\n    execution of function will continue as it its, otherwise it the\n    function will fail(like in regular predicates).\n\n    Regardeless of the predicate call result, the predicate call's entry\n    in the tuple is **always** vanishing.\n\nTuples are compiled to the predicate `tuple(...)` when `...` are the\nnon-vanishing entries of the tuple.\n\n## Examples\n\n1.  `(1,2)`.\n\n2.  `([3,4],Max(4,3),(1,2))`, evalutes to `tuple([3,4],Max(4,3),(1,2))`.\n\n3.  `([3,4];Max(4,3),(1,2);)`, evalutes to `tuple(Max(4,3),(1,2))`.\n\n::: note\n*Note 2*. The number of entries in the tuple's predicate is determined\nat compile time, for this reason, an if statement (Without else) can\nonly be a vanishing statement.\n:::\n\n# Binding\n\nBinding is used for matching a variable, or a tuple of variables to\nanother expression. It does matching automatically, that is, if the\nexpression is an arithmitic term, it evalutes the term, and matches the\nvariable with the value of the term (like `is` operator) otherwise it\nacts like `=` operator.\n\nIt have the intuitive syntax `Var \u003c- Expr`.\n\n## Tuple unpacking\n\nFor convinence, the language allows you to unpack the tuple such that it\nentries match with named variables, using the syntax\n`TupleOfVar \u003c- Expr` when `Expr` is evaluted to a tuple with the same\nsize as the tuple of variables.\n\n## Examples\n\n-   `X \u003c- 3 * Y;`, evalues `3*Y` then matches it with `X`.\n\n-   `(X,Y) \u003c- getMinMax(List);`, evalues `getMinMax(List)` to\n    `tuple(Min,Max)` then matches `X` with `Min` and `Max` with `Y`.\n\n# Matching\n\nMatches are expression that evalutes to a value and they have the\nfollowing syntax\n\n``` {.prolog language=\"Prolog\"}\nmatch Expression {\n        Exp1 =\u003e Result1,\n        Exp2 =\u003e Result2,\n        ...\n        ExpN =\u003e ResultN,\n        else =\u003e Result\n    }\n```\n\nWhen `Resulti` are tuples or tuple entries.\n\nNote that the `else` is optional.\n\n## Example\n\n``` {.prolog language=\"Prolog\"}\nmatch List {\n            [] =\u003e [],\n            [L | Ls] =\u003e [1 | Ls]\n        }\n```\n\n# Conditionals\n\nThere are two types of conditionals if statements, and if-else\nexpressions.\n\nIf statements evaluates the tuple in the `if` body if the condition is\ntrue, while if-else evalutes one of them according to the condition.\n\nThe reason that `if` is a statement is that it must be always vanishing\nto avoid ambiguity, since if the condition is false the if must not\nevalute to a value, but a tuple entry must be known if its a vanishing\nor non-vanishing at compile time.\n\nIn the otherhand, if-else provide us with a way to tell if the\nexpression is vanishing or not.\n\nWe can add some bindings at the head of the if condition in order for a\nmore compact syntax, this is an optional.\n\nIn order to allow for more readable nested if-else statements, if the\ntuple has one entry only, and its non-vanishing, then we can remove the\nparentheses.\n\n## Syntax\n\n``` {.prolog language=\"Prolog\"}\nif  optional( if_head |)  Condition then \n        tuple\n```\n\n``` {.prolog language=\"Prolog\"}\nif optional(if_head |) Condition then \n        tuple\n    else \n        tuple\n```\n\n## Example\n\n``` {.prolog language=\"Prolog\"}\nif ListSize \u003c- std:Size(List) | Idx \u003c 0 ; Idx \u003e ListSize - 1 then (\n        write('Wrong Idx');\n        Exit();\n    );\n\n    if Idx = 0 then (\n        match List {\n            [] =\u003e [],\n            [L | Ls] =\u003e [NewVal | Ls]\n        }\n    ) else (\n        List \u003c- [L | Ls]; \n        [L | Replace(Ls,Idx - 1, NewVal)]\n    )\n```\n\n# Functions\n\nFunctions takes arguments and returns a result.\n\nA function's result is a tuple, unless the tuple has one entry, then the\nfunction returns the expression that the tuple contain's.\n\nA function's name must be a valid variable's name that starts with a\ncapital letter.\n\nThe function will compile to a regular `Prolog` predicate but with the\nfirst letter being a small letter, and with an extra argument as the\nlast arguments that stores the function's result.\n\n## Syntax\n\n``` {.prolog language=\"Prolog\"}\nFunc(Arg1, Arg2, ..., ArgN) :: tuple .\n```\n\n**Example**\n\n``` {.prolog language=\"Prolog\"}\nReplace(List,Idx,NewVal) :: (\n\n    if ListSize \u003c- std:Size(List) | Idx \u003c 0 ; Idx \u003e ListSize - 1 then (\n        write('Wrong Idx');\n        Exit();\n    );\n\n    if Idx = 0 then (\n        match List {\n            [] =\u003e [],\n            [L | Ls] =\u003e [NewVal | Ls]\n        }\n    ) else (\n        List \u003c- [L | Ls]; \n        [L | Replace(Ls,Idx - 1, NewVal)]\n    )\n)\n.\n```\n\n## Arguments Alias\n\nWe can refer to the i-th argument of the function with the synatx `#i`.\n\n`i` must be within the range of the function's arguments number.\n\nWe can also refer to the tuple that contains all the function's\narguments using `#`.\n\nExample:\n\n``` {.prolog language=\"Prolog\"}\nMax(X,Y) :: (if #1 \u003e= #2 then #1 else #2).\n```\n\n``` {.prolog language=\"Prolog\"}\nF(X) :: (if tuple(X) = # then 1 else 0). // Evaluates to 1\n```\n\n## Lambdas\n\nLambdas are annonymos functions, and they are considered as expression,\nmeaning they can be binded to variables, returned from functions, passed\nas an argument \\...\n\n## Syntax\n\n``` {.prolog language=\"Prolog\"}\n(Arg1, Arg2, ..., ArgN) =\u003e (stmts)\n```\n\n## Example\n\n``` {.prolog language=\"Prolog\"}\nFoo(X,Y) :: (\n        Max \u003c- (X,Y) =\u003e (if #1 \u003e= #2 then #1 else #2)\n        Max(X,Y)\n    )\n    .\n```\n\nNote that `X,Y` are local to the lambdas.\n\n# The Main Function\n\nIf the special function `Main/0` is defined, then prolog generates a\npredicate with no arguments that defines this function, and it generates\na directive that runs the function automatically at the end of the file.\n\n``` {.prolog language=\"Prolog\"}\nMain() :: (\n        std:PrintLn(\"Hello\");\n    )\n    .\n```\n\nIn this example, if we load the file that contains this function, it\nwill print `Hello` without the need to call the predicate `main`.\n\n# Modules\n\nModules are an abstraction of the current modules system of Prolog, they\ncontain functions or types, that can be marked as public using the\nkeyword `pub` for other files to use when the import the module\n\n## Syntax\n\nWe can define a module using\n\n``` {.prolog language=\"Prolog\"}\nmodule my_module {\n        pub Foo() :: (...).\n        pub type :: (...).\n    }\n```\n\nAnd we can import the file that contains the module by listing the file\nname without extenstion\n\n``` {.prolog language=\"Prolog\"}\nimport {\n        'stdlib',\n        'testlib',\n        'heap',\n    }\n```\n\nIf we want to use a function from a module we've imported, we must\ndeclare the module name before the function's name.\n\n``` {.prolog language=\"Prolog\"}\nimport {\n        'm1', // Has Foo/0 that prints 'hello'\n        'm2'  // Has Foo/0 that prints 'world'\n    }\n\n\n    Main() :: (\n        m1:Foo(); // Prints 'hello'\n        m2:Foo(); // Prints 'world'\n    )\n    .\n```\n\n# Testing\n\n`Prolog*` provides a builtin testing features.\n\nA test function is defined like a regular function, but it has no name\nand no arguments, instead, a describtion string must be provided.\n\n## Syntax\n\n``` {.prolog language=\"Prolog\"}\ntest '\u003cstring of test desc\u003e' tuple .\n```\n\n**Example**\n\n``` {.prolog language=\"Prolog\"}\ntest 'HeapSort test on random list' (\n\n    RandomList \u003c- std:ForEach( \n                              std:MakeList(100,0), \n                              (X) =\u003e (std:RandomNum(1,100))\n    );\n\n    testing:EXPECT_EQ(bin_heap:HeapSort(RandomList),\n                      std:SortList(RandomList)\n    );\n)\n.\n```\n\nIf at least one test is defined, `Prolog*` will define a new function\ncalled `RunTests/0`, which will run all tests, in the order of their\ndefinitions.\n\n# Types - deprecated\n\n::: note\n*Note 3*. This feature is deprecated for now, it needs a\nreimplementation.\n:::\n\nTypes can be used for type checking, that is, inforcing the user to use\na pass a specific type to the function.\n\nFunction arguments and binding to a variable can declare the variable's\ntype using the syntax `Var : type`, if the type is a part of a module\nthen it must declare the module name before the type `Var : std:type`.\n\nIf the type is nullable then we pair it with `?`.\n\nExample\n\n``` {.prolog language=\"Prolog\"}\n\n    import {\n        'stdlib'\n    }\n\n    Sort(List : std:list, Func) :: (\n        ...\n    )\n    .\n\n    Main() :: (\n        Sort(1, _); // Type mismatch.\n        Sort([], Min); // ok.\n\n        X : std:list \u003c- 1; // Type mismatch.\n    )\n    .\n```\n\n## Syntax\n\nWe can define a type by\n\n``` {.prolog language=\"Prolog\"}\ntype node :: (number , node?, node?).\n\n\n    Foo(Node : node) :: (\n\n    )\n    .\n\n    Main() :: (\n        Foo(node(100,1,1)); // Type mismatch\n        Foo(node(100,nil,nil)); // ok\n        Foo(node(100,node(100,nil,nil),nil)); // ok\n    )\n    .\n```\n\n# Implementing Heap Sort in `Prolog*`\n\nIn this example, we are going to explore all of the language's features,\nby implementing `HeapSort/1` using binomial heaps.\n\n``` {.prolog language=\"Prolog\"}\nimport {\n    'stdlib'\n}\n\n\nmodule bin_heap {\n\nMergeBt(Bt1, Bt2) :: (\n\n        Bt1 \u003c- bt(Value1, List1);\n        Bt2 \u003c- bt(Value2, List2);\n\n\n        if Value1 \u003e= Value2 then (\n            R \u003c- bt(Value2,[Bt1 | List2]);\n        ) else (\n            R \u003c- bt(Value1,[Bt2 | List1]);\n        );\n\n        R\n)\n.\n\n\nAddBtAux(Bt , Heap : std:list, I : number) :: (\n    Bt \u003c- bt(Value, Children);\n    Order \u003c- std:Size(Children);\n\n    if I = Order then (\n        match Heap {\n            [] =\u003e [Bt],\n            [empty | HeapTail] =\u003e [Bt | HeapTail],\n            [CurrentBt | HeapTail] =\u003e \n             [ empty | AddBtAux(MergeBt(CurrentBt,Bt),HeapTail,I+1)]\n        }\n\n    ) else (\n        Heap \u003c- [ H | HeapTail];\n        [H | AddBtAux(Bt,HeapTail, I + 1)]\n    )\n)\n.\n\nAddBt(Bt , Heap : std:list) :: (\n    AddBtAux(Bt,Heap,0)\n)\n.\n\n\nRemoveBt(Bt, Heap : std:list) :: (\n    match Heap  {\n        [] =\u003e [], \n        [Bt] =\u003e [],\n        [Bt | HeapTail] =\u003e [empty | HeapTail],\n        [H | HeapTail] =\u003e [H | RemoveBt(Bt,HeapTail)]\n    }\n)\n.\n\nPopMin(Heap : std:list)  :: (\n    MinBt \u003c- std:MinMember(Heap, (Bt1 ,Bt2 ) =\u003e (\n        if Bt1 = empty then (\n            Bt2\n        ) else if Bt2 = empty then (\n            Bt1\n        ) else (\n            Bt1 \u003c- bt(Value1, _);\n            Bt2 \u003c- bt(Value2, _);\n            if Value1 =\u003c Value2 then (\n                Bt1 \n            ) else (\n                Bt2\n            )\n        )\n    ));\n\n    MinBt \u003c- bt(Value,List);\n    ResultHeap \u003c- AddList(List,RemoveBt(MinBt,Heap));\n\n    (MinBt,ResultHeap)\n)\n.\n\nAdd(Num : number,Heap : std:list) :: (\n    AddBt(bt(Num, []),Heap)\n)\n.\n\nAddList(List , Heap) :: (\n    match List {\n        [] =\u003e Heap,\n        [Bt | ListTail] =\u003e AddBt(Bt,AddList(ListTail,Heap))\n    }\n)\n.\n\n\nListToHeap(List : std:list) :: (\n    match List  {\n        [] =\u003e [],\n        [L | Ls] =\u003e Add(L,ListToHeap(Ls))\n    }\n)\n.\n\nHeapToList(Heap : std:list) :: (\n    if HeapSize \u003c- std:Size(Heap) | HeapSize = 0 then (\n        []\n    ) else (\n        (MinBt, NewHeap) \u003c- PopMin(Heap);\n        MinBt \u003c- bt(Value , _);\n        [Value | HeapToList(NewHeap)]\n    )\n)\n.\n\npub HeapSort(List : std:list) :: (\n    HeapToList(ListToHeap(List))\n)\n.\n\n}\n\nbt(_, []).\n\nbt(Value , [bt(ChildValue,ChildList) | RootListTail] ) :- \n    length(RootListTail, K), \n    length(ChildList, K),\n    Value =\u003c ChildValue,\n    bt(Value,RootListTail)\n    .\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmohamadcs%2Fprologtranspiler","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fmohamadcs%2Fprologtranspiler","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmohamadcs%2Fprologtranspiler/lists"}