|
#let ( |
|
add, |
|
sub, |
|
mul, |
|
div, |
|
mod, |
|
pow, |
|
bit-and, |
|
bit-or, |
|
bit-xor, |
|
bit-lshift, |
|
bit-rshift, |
|
neg, |
|
bit-not, |
|
cmp, |
|
str, |
|
) = { |
|
import "@preview/jogs:0.2.4": * |
|
|
|
|
|
let prefix = "bigcal" |
|
let js-func-templates = ( |
|
operate2: ``` |
|
function !NAME!(in1, in2) { |
|
let num1 = (typeof in1 === 'string' && in1.startsWith('-')) ? |
|
(-BigInt(in1.substring(1))) : BigInt(in1); |
|
let num2 = (typeof in2 === 'string' && in2.startsWith('-')) ? |
|
(-BigInt(in2.substring(1))) : BigInt(in2); |
|
let num0 = num1 !OP! num2; |
|
return (num0 < 0n) ? |
|
("-0x" + (-num0).toString(16)) : ("0x" + num0.toString(16)); |
|
} |
|
```.text, |
|
operate1: ``` |
|
function !NAME!(in1) { |
|
let num1 = (typeof in1 === 'string' && in1.startsWith('-')) ? |
|
(-BigInt(in1.substring(1))) : BigInt(in1); |
|
let num0 = !OP! num1; |
|
return (num0 < 0n) ? |
|
("-0x" + (-num0).toString(16)) : ("0x" + num0.toString(16)); |
|
} |
|
```.text, |
|
compare: ``` |
|
function !NAME!(in1, in2) { |
|
let num1 = (typeof in1 === 'string' && in1.startsWith('-')) ? |
|
(-BigInt(in1.substring(1))) : BigInt(in1); |
|
let num2 = (typeof in2 === 'string' && in2.startsWith('-')) ? |
|
(-BigInt(in2.substring(1))) : BigInt(in2); |
|
return (num1 === num2) ? 0 : (num1 < num2) ? -1 : 1; |
|
} |
|
```.text, |
|
string: ``` |
|
function !NAME!(in1) { |
|
let num1 = (typeof in1 === 'string' && in1.startsWith('-')) ? |
|
(-BigInt(in1.substring(1))) : BigInt(in1); |
|
return num1.toString(); |
|
} |
|
```.text, |
|
) |
|
|
|
let functions = ( |
|
("Add", 2, "operate2", "+"), |
|
("Sub", 2, "operate2", "-"), |
|
("Mul", 2, "operate2", "*"), |
|
("Div", 2, "operate2", "/"), |
|
("Mod", 2, "operate2", "%"), |
|
("Pow", 2, "operate2", "**"), |
|
("And", 2, "operate2", "&"), |
|
("Or", 2, "operate2", "|"), |
|
("Xor", 2, "operate2", "^"), |
|
("Lsh", 2, "operate2", "<<"), |
|
("Rsh", 2, "operate2", ">>"), |
|
("Neg", 1, "operate1", "-"), |
|
("Not", 1, "operate1", "~"), |
|
("Cmp", 2, "compare", ""), |
|
("Str", 1, "string", ""), |
|
) |
|
|
|
let js-func-source(entry) = { |
|
let (name, arity, kind, operate) = entry |
|
js-func-templates.at(kind).replace( |
|
"!NAME!", prefix + name |
|
).replace( |
|
"!OP!", operate |
|
) |
|
} |
|
|
|
let bytecode = compile-js( |
|
functions.map(js-func-source).join() |
|
) |
|
|
|
let typst-func(entry) = { |
|
let (name, arity, kind, operate) = entry |
|
let real-name = bytes(prefix + name) |
|
if arity == 2 { |
|
(a, b) => { |
|
call-js-function(bytecode, real-name, a, b) |
|
} |
|
} else if arity == 1 { |
|
(a) => { |
|
call-js-function(bytecode, real-name, a) |
|
} |
|
} |
|
} |
|
|
|
functions.map(typst-func) |
|
} |