{"id":"s-o-madi/exprlang","name":"exprlang","scope":"s-o-madi","platform":"roblox","description":"A small DSL engine for evaluating string-based expressions like ADD(VAR(A), VAR(B)).","version":"0.1.0","latest":"0.1.0","versions":["0.1.0"],"license":"MIT","licenseRating":"safe","licenseCaveats":["The package archive does not include its license text; the license is declared in its manifest metadata."],"licenseVerified":false,"dependencies":{},"integrity":"7a9701f30d51c090accc3e5545a7b0ab923f079137e16a972fbcd87292f7974f","likes":0,"downloads":0,"install":"forest install s-o-madi/exprlang","url":"https://forest.dev/p/roblox/s-o-madi/exprlang","files":"https://api.forest.dev/ai/package/roblox/s-o-madi/exprlang/files","readme":"# ASM\n\nA small DSL engine for Luau: evaluate string-based expressions like\n`ADD(VAR(\"A\"), VAR(\"B\"))` against a table of variables.\n\n## Installation (Wally)\n\nAdd to your `wally.toml`:\n\n```toml\n[dependencies]\nASM = \"gt/asm@0.1.0\"\n```\n\nThen:\n\n```bash\nwally install\n```\n\n## Usage\n\n```luau\nlocal ASM = require(Packages.ASM)\n\nlocal result = ASM:Eval([[ADD(VAR(\"A\"), VAR(\"B\"))]], { A = 10, B = 15 })\nprint(result) --> 25\n\n-- Compile once, run many times with different variables\nlocal compiled = ASM:Build([[POW(VAR(\"base\"), VAR(\"exp\"))]])\nprint(compiled({ base = 2, exp = 10 })) --> 1024\n\n-- Non-throwing variant\nlocal ok, resultOrErr = ASM:TryEval([[ADD(VAR(\"A\"), VAR(\"B\"))]], { A = 1 })\nif not ok then\n\twarn(tostring(resultOrErr))\nend\n```\n\n### Registering custom functions\n\n```luau\nASM:Register(\"DOUBLE\", function(x: number)\n\treturn x * 2\nend)\n\nASM:Eval(\"DOUBLE(21)\") --> 42\n```\n\n### Conditional logic\n\n`true` / `false` are recognized as boolean literals. `IF`, `AND`, `OR`, and\n`NOT` are built into the parser (not regular registered functions), so they\nevaluate **lazily** — `IF(cond, a, b)` only evaluates the taken branch, and\n`AND`/`OR` short-circuit:\n\n```luau\nASM:Eval([[IF(GT(VAR(\"hp\"), 0), \"alive\", \"dead\")]], { hp = 0 })\n--> \"dead\"\n\n-- The else-branch never runs DIV(1, 0) since the condition is true:\nASM:Eval([[IF(true, 42, DIV(1, 0))]])\n--> 42\n\nASM:Eval([[AND(GT(VAR(\"hp\"), 0), NOT(VAR(\"isStunned\")))]], { hp = 10, isStunned = false })\n--> true\n```\n\nComparison built-ins: `EQ`, `NEQ`, `LT`, `GT`, `LTE`, `GTE`.\n\n## Local development\n\nRequires [Aftman](https://github.com/LPGhatguy/aftman) to pin tool versions.\n\n```bash\naftman install        # installs rojo, wally, selene, stylua at pinned versions\nwally install         # installs TestEZ as a dev-dependency\n```\n\n### Serve the package alone (no game, just for sourcemap/inspection)\n\n```bash\nrojo serve default.project.json\n```\n\n### Run tests\n\nOpen `test.project.json` in Rojo, connect Studio, then press Play —\n`test/init.server.luau` boots TestEZ against every `*.spec.luau` file\nunder `src/`.\n\nHeadless (CI), see `.github/workflows/ci.yml`.\n\n### Lint / format\n\n```bash\nselene src\nstylua --check src\n```\n\n## Publishing a new version\n\n1. Bump `version` in `wally.toml`.\n2. Add an entry to `CHANGELOG.md`.\n3. `wally publish`.\n","readmeTruncated":false}