| Crates.io | insign |
| lib.rs | insign |
| version | 0.1.1 |
| created_at | 2025-09-02 04:36:51.574397+00 |
| updated_at | 2025-09-02 07:03:11.697966+00 |
| description | Insign: a tiny DSL for Minecraft build regions & metadata |
| homepage | |
| repository | https://github.com/Schem-at/Insign |
| max_upload_size | |
| id | 1820612 |
| size | 240,702 |
Goal: author compact annotations on signs/books (or any text source) that compile into a deterministic regions + metadata structure you can ship with schematics and tools.
cpu.core$global and wildcards like cpu.*)This repository currently contains the spec and examples. Implementation comes next.
An ordered array of tuples: ([sx, sy, sz], text).
[
{
"pos": [10, 64, 10],
"text": "@rc([0,0,0],[3,2,1])\n#doc.label=\"Patch A\""
},
{
"pos": [0, 64, 0],
"text": "@cpu.core=ac([100,70,-20],[104,72,-18])\n#cpu.core:logic.clock_hz=4\n#cpu.*:power.budget=\"low\"\n#$global:io.bus_width=8"
}
]
pos is the source block’s world coords (sign/lectern).text is raw DSL; newlines allowed.{
"$global": { "metadata": { "io.bus_width": 8 } },
"cpu.*": { "metadata": { "power.budget": "low" } },
"__anon:0:0": {
"bounding_boxes": [[[10,64,10],[13,66,11]]],
"metadata": { "doc.label": "Patch A" }
},
"cpu.core": {
"bounding_boxes": [[[100,70,-20],[104,72,-18]]],
"metadata": { "logic.clock_hz": 4 }
}
}
Notes
rc is relative to pos; ac is absolute.@#A statement starts at @ or # and ends right before the next @/# (or end of text). Newlines are allowed inside a statement.
@…)Named regions (unified form)
@<region>=rc([x1,y1,z1],[x2,y2,z2]) // relative to this tuple’s pos
@<region>=ac([x1,y1,z1],[x2,y2,z2]) // absolute world coords
@<region>=<expr> // boolean expression over regions
Anonymous regions (no =; sign-local only)
@rc([x1,y1,z1],[x2,y2,z2])
@ac([x1,y1,z1],[x2,y2,z2])
@def(<expr>)
Booleans (Phase 0 / MVP)
<expr> := term { + term }*
term := <region> | ( <expr> )
+ union only in Phase 0.-, &, ^) are reserved for a later phase.Current region .
#…)Attach to current region (this tuple):
#key=<json>
Attach to an explicit target (dense):
#<target>:<key>=<json>
Where <target> is:
foo or foo.bar)prefix.*)$globalValues: strict JSON (string/number/bool/null/array/object). (No computed value functions in v0.1; reserved for future.)
Read-time precedence per key: Exact region > longest matching wildcard(s) > $global.
Conflicts: different values for the same <named target, key> across tuples → compile error (identical duplicates allowed).
A named region is either:
rc/ac append boxes), or@<region>=<expr>).
Mixing both modes is an error.Anonymous region IDs derive from (tuple_index, statement_index)—never random UUIDs.
Deterministic output ordering is recommended: $global, then wildcards (lexicographic), then regions (lexicographic).
@rc([0,64,0],
[31,72,15])
#doc.label="Data Loop"
#logic.clock_hz=4
@dataloop=rc([0,64,0],[31,72,15])
@dataloop.alu=rc([8,64,8],[22,70,14])
@dataloop.registers=rc([2,64,2],[12,69,6])+rc([14,64,2],[24,69,6])
#dataloop:doc.label="Data Loop"
#dataloop.registers:logic.word_size=8
@core=dataloop.alu+dataloop.registers
#core:doc.note="ALU ∪ registers"
@cpu.bus=ac([100,70,-20],[132,78,-5])
#cpu.bus:io.direction="east-west"
#cpu.*:logic.clock_hz=4
#$global:io.bus_width=8
@dataloop.registers=rc([2,64,2],
[12,69,6])
+ rc([14,64,2],
[24,69,6])
#dataloop.registers:doc.note="two banks"
Lexical
digit = "0"…"9" ;
int = ["-"], digit, { digit } ;
region-id = 1*( ALNUM | "_" | "." ) ; // [A-Za-z0-9_.]+
key = region-id ;
vec3 = "[", int, ",", int, ",", int, "]" ;
box = vec3, ",", vec3 ;
Program
input = { stmt } ;
stmt = geom | meta ;
Geometry
geom = "@", ( named-geom | anon-geom ) ;
named-geom = region-id, "=", ( "rc(", box, ")"
| "ac(", box, ")"
| expr ) ;
anon-geom = "rc(", box, ")"
| "ac(", box, ")"
| "def(", expr, ")" ;
expr = term, { "+", term } ; // Phase 0: union only
term = region-id | "(", expr, ")" ;
Metadata
meta = "#", ( targeted-meta | current-meta ) ;
targeted-meta = meta-target, ":", key, "=", json ;
current-meta = key, "=", json ;
meta-target = "$global" | region-id | region-id, ".*" ;
json = RFC 8259 JSON literal ;
Add to your Cargo.toml:
[dependencies]
insign-core = "0.1.1"
# For FFI bindings (Kotlin/JVM integration)
insign-ffi = "0.1.1"
# For WASM bindings (Web/Node.js)
insign-wasm = "0.1.1"
Basic usage:
use insign_core::compile;
let input = vec![
([10, 64, 10], "@rc([0,0,0],[3,2,1])\n#doc.label=\"Patch A\"".to_string()),
];
let result = compile(&input)?;
let json = serde_json::to_string_pretty(&result)?;
println!("{}", json);
Install from crates.io:
cargo install insign-core --features=cli
Or download pre-built binaries from the GitHub Releases page.
echo '{"pos": [0,0,0], "text": "@rc([0,0,0],[1,1,1])\\n#test=1"}' | insign-cli --pretty
Download the appropriate native library from GitHub Releases:
libinsign_ffi.solibinsign_ffi.dylibinsign_ffi.dll// Example Kotlin integration (requires JNA)
val library = Native.load("insign_ffi", InsignLibrary::class.java)
val json = "[{\"pos\":[0,0,0],\"text\":\"@rc([0,0,0],[1,1,1])\"}]"
val result = library.compile_json(json)
println(result)
Node.js:
npm install @schem-at/insign-wasm
const { compile_json } = require('@schem-at/insign-wasm');
const input = JSON.stringify([
{ pos: [0,0,0], text: "@rc([0,0,0],[1,1,1])\n#test=1" }
]);
const result = compile_json(input);
console.log(JSON.parse(result));
Browser:
<script type="module">
import init, { compile_json } from './pkg/insign.js';
async function run() {
await init();
const input = JSON.stringify([
{ pos: [0,0,0], text: "@rc([0,0,0],[1,1,1])\n#test=1" }
]);
const result = compile_json(input);
console.log(JSON.parse(result));
}
run();
</script>
# Clone the repository
git clone https://github.com/Schem-at/Insign.git
cd Insign
# Build all packages
cargo build --all --release
# Run tests
cargo test --all
# Build FFI library
cargo build -p insign-ffi --release
# Build WASM package
cd crates/insign-wasm
wasm-pack build --release --target nodejs --out-dir pkg --out-name insign
To verify that FFI and WASM produce identical outputs:
./tools/scripts/parity-simple.sh
MIT (see LICENSE in this repository).