{"id":16753504,"url":"https://github.com/optimalstrategy/ppga","last_synced_at":"2025-08-12T14:45:19.064Z","repository":{"id":96616335,"uuid":"275403381","full_name":"optimalstrategy/ppga","owner":"optimalstrategy","description":"A scripting language that transpiles to LUA","archived":false,"fork":false,"pushed_at":"2021-04-05T03:48:04.000Z","size":530,"stargazers_count":2,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"master","last_synced_at":"2025-07-11T09:32:04.070Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"C++","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/optimalstrategy.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"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":"2020-06-27T15:46:27.000Z","updated_at":"2024-04-25T12:17:32.000Z","dependencies_parsed_at":null,"dependency_job_id":"2ea1e552-39ec-423f-97f1-f2eac2963b0b","html_url":"https://github.com/optimalstrategy/ppga","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/optimalstrategy/ppga","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/optimalstrategy%2Fppga","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/optimalstrategy%2Fppga/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/optimalstrategy%2Fppga/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/optimalstrategy%2Fppga/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/optimalstrategy","download_url":"https://codeload.github.com/optimalstrategy/ppga/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/optimalstrategy%2Fppga/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":270079910,"owners_count":24523622,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","status":"online","status_checked_at":"2025-08-12T02:00:09.011Z","response_time":80,"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":[],"created_at":"2024-10-13T02:50:18.169Z","updated_at":"2025-08-12T14:45:19.012Z","avatar_url":"https://github.com/optimalstrategy.png","language":"C++","funding_links":[],"categories":[],"sub_categories":[],"readme":"# PPGA Script\nPPGA Script is a scripting language that transpiles to Lua, original designed to be used in [https://github.com/jprochazk/anikibot](). \nIt provides a more familiar C-style syntax and syntactic sugar, designed to reduce the amount of boilerplate when writing scripting commands in lua.\n\nSee [tour.ppga](tour.ppga) for a quick tour.\n\n## Binary Installation\n* You may clone the repo and build from source, then use the scripts `ppga.sh` and `ppga.bat`.\n\nOR\n\n* You may install the binary with `cargo install` from this repo:\n\n    ```bash\n    $ cargo install --git https://github.com/OptimalStrategy/ppga/ --features=build-binary\n    ```\n\n## Library\nThere's two implementations of the transpiler, in [Rust](ppga) and [C++](./ppga-cpp/README.md).\n\n## Syntax Highlighting\nThere's a syntax highlighting plugin for vscode. It can be installed from the [vscode-ppga](vscode-ppga) directory.\n\n\n## Language Reference\n\n\u003ctable\u003e\n\u003cthead\u003e\n\u003ctr\u003e\n\u003cth\u003eFeature\u003c/th\u003e\n\u003cth\u003eDescription\u003c/th\u003e\n\u003cth\u003eExample\u003c/th\u003e\n\u003cth\u003eGenerated Lua\u003c/th\u003e\n\u003c/tr\u003e\n\u003c/thead\u003e\n\u003ctbody\u003e\n\u003ctr\u003e\n\u003ctd\u003eLiterals\u003c/td\u003e\n\u003ctd\u003eNone.\u003c/td\u003e    \n\u003ctd\u003e\n\u003cpre lang=\"js\"\u003e1;\n3.141592; \ntrue; \nfalse; \nnil; \n\"a string\";\u003c/pre\u003e\u003c/td\u003e\n\u003ctd\u003e\n\u003cpre lang=\"lua\"\u003e\n1\n3.141592\ntrue\nfalse\nnil\n\"a string\"\n\u003c/pre\u003e\n\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003eArray and Dict literals\u003c/td\u003e\n\u003ctd\u003eNone.\u003c/td\u003e\n\u003ctd\u003e\u003cpre lang=\"js\"\u003e\n\n    // Arrays use python-style syntax \n    // and are initialized from 0.\n    let arr = [1, 2, 3];\n\n    // Dicts are similar to Lua but \n    // don't require the `[]`\n    let dict = {1 = 2, 3 = 4};\n\n    // Indexing uses the [] syntax: \n    let empty = {};\n    empty[\"string\"] = \"hello\";\n\u003c/pre\u003e\u003c/td\u003e\n\u003ctd\u003e\u003cpre lang=\"lua\"\u003e\n\n    local arr = {[0] = 1, [1] = 2, [2] = 3}\n\n    local dict = {\n        [1] = 2,\n        [3] = 4\n    }\n\n    local empty = {}\n    empty[\"string\"] = \"hello\"\n\u003c/pre\u003e\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003eF-strings\u003c/td\u003e\n\u003ctd\u003eAn interpolated string expression that compiles to concatenation of string literals and \u003ccode\u003etostring()\u003c/code\u003e calls. A backslash can be used to escape formatter brackets: \u003ccode\u003e\\{}\u003c/code\u003e.\u003c/td\u003e\n\u003ctd\u003e\u003cpre lang=\"js\"\u003e\nprint(f\"{a} + {b} = {a + b}\");\nprint(f\"\\{escaped}\");\n\u003c/pre\u003e\u003c/td\u003e\n\u003ctd\u003e\u003cpre lang=\"lua\"\u003e\nprint(tostring(a) .. \" + \" .. tostring(b) \n    .. \" = \" .. tostring(a + b))\nprint(\"{escaped}\")\n\u003c/pre\u003e\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003eArithmetic Expressions\u003c/td\u003e\n\u003ctd\u003eNone.\u003c/td\u003e\n\u003ctd\u003e\u003cpre lang=\"lua\"\u003e\nprint(1 + 2 * 3 / 4 ** 5 % 10);\n\u003c/pre\u003e\u003c/td\u003e\n\u003ctd\u003e\u003cpre lang=\"lua\"\u003e\nprint(1 + 2 * 3 / 4 ^ 5 % 10)\n\u003c/pre\u003e\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003eInteger Division\u003c/td\u003e\n\u003ctd\u003eInteger division operator.\u003c/td\u003e\n\u003ctd\u003e\u003cpre lang=\"lua\"\u003eprint(1 \\ 2);\u003c/pre\u003e\u003c/td\u003e\n\u003ctd\u003e\u003cpre lang=\"lua\"\u003eprint(1 // 2)\u003c/pre\u003e\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003eComparison and Equality operators\u003c/td\u003e\n\u003ctd\u003eNone.\u003c/td\u003e\n\u003ctd\u003e\u003cpre lang=\"js\"\u003e\nprint(3 \u003c 4, 5 \u003c= 6, 8 \u003e 7, 9 \u003e= 8, 10 != 11, \n    7 == 7);\n\u003c/pre\u003e\u003c/td\u003e\n\u003ctd\u003e\u003cpre lang=\"lua\"\u003e\nprint(3 \u003c 4, 5 \u003c= 6, 8 \u003e 7, 9 \u003e= 8, 10 ~= 11, \n    7 == 7)\n\u003c/pre\u003e\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003eLogic operators \u003c/td\u003e\n\u003ctd\u003eNone.\u003c/td\u003e\n\u003ctd\u003e\u003cpre lang=\"lua\"\u003eprint(true and false or true);\u003c/pre\u003e\u003c/td\u003e\n\u003ctd\u003e\u003cpre lang=\"lua\"\u003eprint(true and false or true)\u003c/pre\u003e\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003eConcatenation Operator\u003c/td\u003e\n\u003ctd\u003eThis operator is the same as in lua. Reusing `+` for concatenation is not possible without rolling out a type system.\u003c/td\u003e\n\u003ctd\u003e\u003cpre lang=\"lua\"\u003e\n\n    print(\"a\" .. \"b\");\n\u003c/pre\u003e\u003c/td\u003e\n\u003ctd\u003e\u003cpre lang=\"lua\"\u003e\n\n    print(\"a\" .. \"b\")\n\u003c/pre\u003e\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003eDefault Operator\u003c/td\u003e\n\u003ctd\u003eThis operator is similar to `??` in C#. If `a` is not `nil`, its value will be returned, otherwise, the `b` value will be returned. This feature requires the PPGA internals included. \u003c/td\u003e\n\u003ctd\u003e\u003cpre lang=\"js\"\u003eprint(a ?? b);\u003c/pre\u003e\u003c/td\u003e\n\u003ctd\u003e\u003cpre lang=\"lua\"\u003e\n\n    print(__PPGA_INTERNAL_DEFAULT(a, b))\n\u003c/pre\u003e\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003eVariable Declarations\u003c/td\u003e\n\u003ctd\u003eLet bindings correspond to `local` lua variables, while `global` ones transpile to variables without a binding keyword. A `global` variable must be initialized at declaration.\u003c/td\u003e\n\u003ctd\u003e\u003cpre lang=\"js\"\u003e\n\n    let a; \n    global b = 4;\n\u003c/pre\u003e\u003c/td\u003e\n\u003ctd\u003e\u003cpre lang=\"lua\"\u003e\n\n    local a\n    b = 4\n\u003c/pre\u003e\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003eFunction Declarations \u003c/td\u003e\n\u003ctd\u003eAll functions are `local` by default. The `global` keyword may be used to make them global. \nThe \"fat arrow\" syntax can be used if the function's body is a single expression.\u003c/td\u003e\n\u003ctd\u003e\u003cpre lang=\"lua\"\u003e\n\n    global fn f() {}\n    fn g() {}\n    fn h(x) =\u003e x * x\n\u003c/pre\u003e\u003c/td\u003e\n\u003ctd\u003e\u003cpre lang=\"lua\"\u003e\n\n    function f()\n    end\n    \n    local function g()\n    end\n    \n    local function h(x)\n        return (x * x)\n    end\n\u003c/pre\u003e\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003eLambda Expressions\u003c/td\u003e\n\u003ctd\u003eLambdas use the same syntax as named functions, except that they don't need an identifier.\u003c/td\u003e\n\u003ctd\u003e\u003cpre lang=\"js\"\u003e\n\n    print(fn(y, f) {});\n    print(fn(x) =\u003e x * x);\n\u003c/pre\u003e\u003c/td\u003e\n\u003ctd\u003e\u003cpre lang=\"lua\"\u003e\n\n    print(function (y, f)\n        end)\n    print(function (x)\n            return (x * x)\n        end)\n\u003c/pre\u003e\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003eRest Arguments / Variadics\u003c/td\u003e\n\u003ctd\u003eRest arguments use the `@` symbol and transpile to `...`.\u003c/td\u003e\n\u003ctd\u003e\u003cpre lang=\"lua\"\u003e\n\n    fn f(a, @) {\n        print(a, @);\n    }\n\u003c/pre\u003e\u003c/td\u003e\n\u003ctd\u003e\u003cpre lang=\"lua\"\u003e\n\n    local function f(a, ...)\n        print(a, ...)\n    end\n\u003c/pre\u003e\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003eEllipsis / Unpacking\u003c/td\u003e\n\u003ctd\u003eStrips the parentheses and unpacks the given expression with `table.unpack`.\u003c/td\u003e\n\u003ctd\u003e\u003cpre lang=\"rust\"\u003e\n\n    fn f(x) {\n        fn packed() {\n            return x, 5;\n        }\n\n        if not x {\n            // returns the result of packed \n            // as a single value:\n            // =\u003e return (packed())\n            return packed();  \n        }\n\n        // unpacks the result of packed() as two values:\n        // =\u003e return unpack({packed()})\n        return ...packed();  \n    }\n\u003c/pre\u003e\u003c/td\u003e\n\u003ctd\u003e\u003cpre lang=\"lua\"\u003e\n\n    local function f(x)\n        local function packed()\n            return (y), (5)\n        end\n\n        if not(x) then\n            return (packed())\n        end\n\n        return __PPGA_INTERNAL_UNPACK(packed())\n    end\n\u003c/pre\u003e\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003eFor Loop (ranges)\u003c/td\u003e\n\u003ctd\u003eFor-range loops transpile to Lua range loops\u003c/td\u003e\n\u003ctd\u003e\u003cpre lang=\"rust\"\u003e\n\n    // From 0 to 3\n    for i in range(3) {\n        print(i);\n    }\n\n    // From 2 to 4\n    for i in range(2, 4) { \n        print(i);\n    }\n\n    // From 0 to 10 with step = 2\n    for i in range(0, 10, 2) { \n        print(i);\n    }\n\u003c/pre\u003e\u003c/td\u003e\n\u003ctd\u003e\u003cpre lang=\"lua\"\u003e\n\n    for i = 0, 3, 1 do\n        print(i)\n    end\n\n    for i = 2, 4, 1 do\n        print(i)\n    end\n\n    for i = 0, 10, 2 do\n        print(i)\n    end\n\u003c/pre\u003e\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003eFor Loop (containers)\u003c/td\u003e\n\u003ctd\u003eFor-in loops transpile to `pairs` or `ipairs` depending on the keyword used.\u003c/td\u003e\n\u003ctd\u003e\u003cpre lang=\"rust\"\u003e\n\n    let container = [1, 2, 3];\n    container[\"string\"] = \"hello\";\n\n    // Table iteration, uses pairs\n    for key, value in container {\n        print(key, value);\n    }\n\n    // Array iteration, uses ipairs\n    fori idx, value in container {\n        print(idx, value);\n    }\n\u003c/pre\u003e\u003c/td\u003e\n\u003ctd\u003e\u003cpre lang=\"lua\"\u003e\n\n    local container = {[0] = 1, [1] = 2, [2] = 3}\n    container[\"string\"] = \"hello\"\n\n    for key, value in pairs(container) do\n        print(key, value)\n    end\n\n    for idx, value in ipairs(container) do\n        print(idx, value)\n    end\n\u003c/pre\u003e\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003eError Propagation with `?` and `err` Blocks\u003c/td\u003e\n\u003ctd\u003eNone.\u003c/td\u003e\n\u003ctd\u003e\u003cpre lang=\"rust\"\u003e\n\n    fn may_fail(fail) {\n        if fail {\n            return nil, \"error\";\n        }\n        return \"success\", nil;\n    }\n\n    fn main() {\n        // The ? operator simplifies Go-style \n        // error handling. By default, this \n        // will make the whole program \n        // crash if an error is encountered.\n        let ok = may_fail(false)?;\n        print(f\"First result: {ok}\");\n\n        // Sometimes it is desirable to log or \n        // try to recover from the error.\n        // An err block may be used for this purpose:\n        let ok = may_fail(true) err {\n            print(f\"An error has occurred: {err}\");\n            return ...recovery();\n        }?;\n        return ok;\n    }\n\u003c/pre\u003e\u003c/td\u003e\n\u003ctd\u003e\n    \u003cpre lang=\"lua\"\u003e\n\n    local function may_fail(fail)\n        if fail then\n            return (nil), (\"error\")\n        end\n        return (\"success\"), (nil)\n    end\n\n    local function main()\n        local ok = nil\n        do\n            local _ok_L10S283, _err_L10S283 = \n            __PPGA_INTERNAL_HANDLE_ERR(\n                __PPGA_INTERNAL_DFLT_ERR_CB, \n                may_fail(false)\n            )\n            if _err_L10S283 ~= nil then\n                return (nil), (_err_L10S283)\n            end\n            ok = _ok_L10S283\n        end\n        print(\"First result: \" .. tostring(ok))\n\n        local ok = nil\n        do\n            local _ok_L18S562, _err_L18S562 = \n            __PPGA_INTERNAL_HANDLE_ERR(\n                function (err) \n                    print(\"An error has occurred: \" \n                        .. tostring(err))\n                    return (unpack(recovery()))\n                end,\n                may_fail(true)\n            )\n            if _err_L18S562 ~= nil then\n                return (nil), (_err_L18S562)\n            end\n            ok = _ok_L18S562\n        end\n        \n        return (ok)\n    end\n\u003c/pre\u003e\n\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e\u003c/td\u003e\n\u003ctd\u003e\u003cpre\u003e\n    \na hack to widen the column\n\u003c/pre\u003e\u003c/td\u003e\n\u003c/tr\u003e\n\u003c/tbody\u003e\n\u003c/table\u003e\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Foptimalstrategy%2Fppga","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Foptimalstrategy%2Fppga","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Foptimalstrategy%2Fppga/lists"}