https://github.com/onelivesleft/metaprogram
https://github.com/onelivesleft/metaprogram
Last synced: 3 months ago
JSON representation
- Host: GitHub
- URL: https://github.com/onelivesleft/metaprogram
- Owner: onelivesleft
- Created: 2021-12-27T14:23:55.000Z (over 4 years ago)
- Default Branch: main
- Last Pushed: 2022-01-16T00:11:25.000Z (over 4 years ago)
- Last Synced: 2025-01-28T22:46:59.945Z (over 1 year ago)
- Size: 141 KB
- Stars: 3
- Watchers: 3
- Forks: 0
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
- Changelog: CHANGELOG.md
Awesome Lists containing this project
README
# Metaprogram
An 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.
Below the line `files, run_strings := compiler_get_source_files();` add:
```jai
{
// User-added block for Metaprogram module, non-standard!
metaprogram :: #import "Metaprogram";
metaprogram.update_options();
}
```
Below the line `if !message break;` add:
```jai
{
// User-added block for Metaprogram module, non-standard!
metaprogram :: #import "Metaprogram";
metaprogram.check_message(message);
}
```
If 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.
You can toggle the metaprogram features by editing the constants at the top of `Metaprogram.jai`
Features:
* Use Environment Variables
* Pointer-into-resizable-array check
* Carriage-Return check
* `build` string for single file programs
* Managed Imports
## Use Environment Variables
When enabled the metaprogram will check for the following environment variables:
* `JAI_IMPORT_DIR` - set to a collection of folder paths separated by `;` to add them as if with `-import_dir`
* `JAI_CHECK_BINDINGS` - if set to non-zero will enable the `-check_bindings` option.
* `JAI_QUIET` - if set to non-zero will enable the `-quiet` option.
## Pointer into resizable array check
Enable 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).
## Carriage-Return check
When enabled as either `.WARNING` or `.ERROR` it will report any string literal which contains a carriage return (`\r`) character.
When 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`)
You may mark a string with `@Contains_Carriage_Return` to have it ignore this check.
## Build String
Allows you to create a build script inside your program, so even a simple single-file program can set compiler options, check compiler messages, etc.
Add a #string to your program called `build`, and it will be ran as a build script for your program. For example:
```jai
build :: #string __jai
#import "Compiler";
build_options := get_build_options();
build_options.output_executable_name = "not_the_same_name.exe";
workspace := compiler_create_workspace();
set_build_options(build_options, workspace);
add_build_file(#file, workspace);
__jai
```
## Managed Imports
Managed 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).
### Warning!
Since 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!
### Disclaimer!
This 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.
### Dependencies
* You need to be on compiler version `beta 0.0.101` or later.
* For downloading you need `git` installed and working.
### Path Syntax
To specify a path for a module place it after a `|` character in the import string. i.e.:
```jai
#import "|";
```
For example:
```jai
#import "Foo|c:/repos/modules";
```
The path can be absolute or relative (to the project);
### Github Syntax
The syntax to download a module from Github is:
```jai
#import "||.";
```
For example:
```jai
#import "Strings|v1.0.8|jai-string.onelivesleft";
```
*Note that `` must be in the form `v#.#.#`.*
When 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.
Alternatively, you may import directly into your program by prefixing the module name with a `.`:
```jai
#import ".||.";
```
For example:
```jai
#import ".Strings|v1.0.8|jai-string.onelivesleft";
```
This will search inside / download into your program directory in the `modules` sub-folder.
### Github modules
To set up a module which can be downloaded automatically in this manner:
* Create a github repository for it.
* Create the module as a folder in that repo, with a `module.jai` file inside (as normal).
* Create a `modules.lst` file in the root of the repo, which lists every folder ni the repo that is a module.
* 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`.
Example module: https://github.com/onelivesleft/jai-string
*(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)*
### Awful bonus feature
You can inline a module directly in the string if you use a `#string`. For example:
```jai
Foo :: #import #string __jai
my_module_has_a_string :: "It does!\n";
__jai;
main :: () {
write_string(Foo.my_module_has_a_string);
}
```