{"id":17092706,"url":"https://github.com/onelivesleft/metaprogram","last_synced_at":"2026-03-18T23:20:47.411Z","repository":{"id":171691257,"uuid":"442181607","full_name":"onelivesleft/Metaprogram","owner":"onelivesleft","description":null,"archived":false,"fork":false,"pushed_at":"2022-01-16T00:11:25.000Z","size":144,"stargazers_count":3,"open_issues_count":0,"forks_count":0,"subscribers_count":3,"default_branch":"main","last_synced_at":"2025-01-28T22:46:59.945Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":null,"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/onelivesleft.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","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":"2021-12-27T14:23:55.000Z","updated_at":"2023-09-28T18:06:08.000Z","dependencies_parsed_at":"2024-01-24T10:31:53.623Z","dependency_job_id":null,"html_url":"https://github.com/onelivesleft/Metaprogram","commit_stats":null,"previous_names":["onelivesleft/metaprogram"],"tags_count":6,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/onelivesleft%2FMetaprogram","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/onelivesleft%2FMetaprogram/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/onelivesleft%2FMetaprogram/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/onelivesleft%2FMetaprogram/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/onelivesleft","download_url":"https://codeload.github.com/onelivesleft/Metaprogram/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":245136345,"owners_count":20566586,"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","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-14T14:02:11.067Z","updated_at":"2026-01-04T09:47:49.686Z","avatar_url":"https://github.com/onelivesleft.png","language":null,"funding_links":[],"categories":[],"sub_categories":[],"readme":"# Metaprogram\n\nAn upgraded version of `Default_Metaprogram`.  To use it either copy the `Metaprogram` folder into your jai modules folder, or symlink it there.  Then edit the following code into the `modules/Default_Metaprogram.jai` file in the compiler.\n\n\nBelow the line `files, run_strings := compiler_get_source_files();` add:\n\n```jai\n    {\n        // User-added block for Metaprogram module, non-standard!\n        metaprogram :: #import \"Metaprogram\";\n        metaprogram.update_options();\n    }\n```\n\nBelow the line `if !message break;` add:\n\n```jai\n        {\n            // User-added block for Metaprogram module, non-standard!\n            metaprogram :: #import \"Metaprogram\";\n            metaprogram.check_message(message);\n        }\n```\n\nIf you'd rather not directly edit the compiler `Default_Metaprogram.jai` then copy it, make the edit, then use the `-meta` command line option to use your new version.\n\nYou can toggle the metaprogram features by editing the constants at the top of `Metaprogram.jai`\n\nFeatures:\n* Use Environment Variables\n* Pointer-into-resizable-array check\n* Carriage-Return check\n* `build` string for single file programs\n* Managed Imports\n\n\n## Use Environment Variables\n\nWhen enabled the metaprogram will check for the following environment variables:\n\n* `JAI_IMPORT_DIR` - set to a collection of folder paths separated by `;` to add them as if with `-import_dir`\n* `JAI_CHECK_BINDINGS` - if set to non-zero will enable the `-check_bindings` option.\n* `JAI_QUIET` - if set to non-zero will enable the `-quiet` option.\n\n\n## Pointer into resizable array check\n\nEnable as either a `.WARNING` or `.ERROR`: it will try and detect when you take a pointer into a resizable array (`[..] $T`); such a pointer will become invalid when the array reallocates itself (which can happen any time you add to it).\n\n\n## Carriage-Return check\n\nWhen enabled as either `.WARNING` or `.ERROR` it will report any string literal which contains a carriage return (`\\r`) character.\nWhen enabled as `.FIX` it will remove the carriage returns from the string. (WIP: currently it pads the end of the string with as many nulls as there were `\\r`)\nYou may mark a string with `@Contains_Carriage_Return` to have it ignore this check.\n\n\n## Build String\n\nAllows you to create a build script inside your program, so even a simple single-file program can set compiler options, check compiler messages, etc.\n\nAdd a #string to your program called `build`, and it will be ran as a build script for your program.  For example:\n\n```jai\nbuild :: #string __jai\n    #import \"Compiler\";\n    build_options := get_build_options();\n    build_options.output_executable_name = \"not_the_same_name.exe\";\n\n    workspace := compiler_create_workspace();\n    set_build_options(build_options, workspace);\n\n    add_build_file(#file, workspace);\n__jai\n```\n\n\n## Managed Imports\n\nManaged imports provides a mechanism to (a) allow for importing files via a specified path and (b) automatically download modules hosted on github (currently hard-coded to only use github, more sites can be added later).\n\n\n### Warning!\n\nSince jai provides arbitary compile-time execution, using this feature is a vector for RCE.  This is just the same as any other package manager, the only difference being you can get owned simply by compiling the code; you don't need to run it.  Only import modules you trust!\n\n\n### Disclaimer!\n\nThis is using a new compiler feature so is new code; it probably has bugs!  If you run into problems you can raise an issue, but it's probably easier to just msg me on the SB discord.\n\n\n### Dependencies\n\n* You need to be on compiler version `beta 0.0.101` or later.\n* For downloading you need `git` installed and working.\n\n\n### Path Syntax\n\nTo specify a path for a module place it after a `|` character in the import string.  i.e.:\n\n```jai\n#import \"\u003cmodule\u003e|\u003cpath\u003e\";\n```\n\nFor example:\n\n```jai\n#import \"Foo|c:/repos/modules\";\n```\n\nThe path can be absolute or relative (to the project);\n\n\n### Github Syntax\n\nThe syntax to download a module from Github is:\n\n```jai\n#import \"\u003cmodule\u003e|\u003cversion\u003e|\u003crepo\u003e.\u003cuser\u003e\";\n```\n\nFor example:\n```jai\n#import \"Strings|v1.0.8|jai-string.onelivesleft\";\n```\n\n*Note that `\u003cversion\u003e` must be in the form `v#.#.#`.*\n\nWhen you use this syntax the compiler will check the downloaded modules folder (a path set at the top of `Metaprogram.jai`) for the specified module.  If it doesn't find it it'll use `git` to download it.\n\nAlternatively, you may import directly into your program by prefixing the module name with a `.`:\n```jai\n#import \".\u003cmodule\u003e|\u003cversion\u003e|\u003crepo\u003e.\u003cuser\u003e\";\n```\n\nFor example:\n```jai\n#import \".Strings|v1.0.8|jai-string.onelivesleft\";\n```\n\nThis will search inside / download into your program directory in the `modules` sub-folder.\n\n\n### Github modules\n\nTo set up a module which can be downloaded automatically in this manner:\n* Create a github repository for it.\n* Create the module as a folder in that repo, with a `module.jai` file inside (as normal).\n* Create a `modules.lst` file in the root of the repo, which lists every folder ni the repo that is a module.\n* Create a release of the repo, and tag it with the version.  The version tag must be of the form `v#.#.#`.  For example, the tag for the `Strings` module above is `v1.0.8`.\n\nExample module: https://github.com/onelivesleft/jai-string\n\n*(Currently the entire repo is downloaded and held, but in future versions all files/folders in the repo which are not listed in the `modules.lst` file will be deleted)*\n\n\n### Awful bonus feature\n\nYou can inline a module directly in the string if you use a `#string`.  For example:\n\n```jai\nFoo :: #import #string __jai\n    my_module_has_a_string :: \"It does!\\n\";\n__jai;\n\nmain :: () {\n    write_string(Foo.my_module_has_a_string);\n}\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fonelivesleft%2Fmetaprogram","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fonelivesleft%2Fmetaprogram","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fonelivesleft%2Fmetaprogram/lists"}