macros
Macros are functions that run while compiling and return code.
jihoo run examples/macros.jhjihoo emit-ir examples/macros.jh // `main` contains only the expanded code// `expr` parameters receive code; other parameters receive compile-time values.macro power(x: expr, n: i64) -> expr { let e = quote(1) let i = 0 while i < n { e = quote($e * $x) // `$x` is inserted in parentheses i = i + 1 } return e}
// `stringify` turns code back into text: handy for messages.macro expect(cond: expr) -> expr { return quote(report($cond, $(stringify(cond))))}
// Macros can make any expression, including struct literals and other macro calls.macro point(x: expr) -> expr { return quote(Point { x: $x, y: power!($x, 2) })}
// `stmts` macros add statements to the block they are used in. Macros are// hygienic: the template's `tmp` is the macro's own, so `swap!(tmp, x)` works// and `tmp` is gone after the macro. A name the caller should see goes through// a hole, as `fn $getter` in `getters!` below.macro swap(a: expr, b: expr) -> stmts { return quote { let tmp = $a $a = $b $b = tmp }}
// `items` macros define functions and types at the top level. `$name` in a name// position inserts a `str` as a name.macro getters(name: str, fields: i64) -> items { let out = quote items {} let i = 0 while i < fields { let getter = name + "_" + to_str(i) out = quote items { $out fn $getter(p: Point) -> i64 { return p.x * $i + p.y } } i = i + 1 } return out}
getters!("mix", 3) // defines mix_0, mix_1 and mix_2
struct Point { x: i64 y: i64}
fn report(ok: bool, what: str) -> i64 { if ok { print("ok: " + what) return 0 } print("FAILED: " + what) return 1}
fn main() -> i64 { let y = 3 print(power!(y, 4)) // 81, as y * y * y * y with no loop at runtime print(power!(y + 1, 2)) // 16: (y + 1) * (y + 1) let p = point!(y) let a = 1 let b = 2 swap!(a, b) print(a * 10 + b) // 21 print(mix_2(p)) // 3 * 2 + 9 = 15 let failures = expect!(p.y == 9) failures = failures + expect!(power!(2, 10) == 1024) failures = failures + expect!(p.x + 1 == 5) return failures // 1: the last check fails on purpose}