core.bend source
core.bend on the hub · documented module
import Base# Tiny Haskell-Core-like language in Bend: de Bruijn indices (no names, so# no equality dispatch is ever needed), lazy thunks, Nat-shaped case# (zero branch vs succ branch binding the predecessor -- no comparison# primop required). ONE fuel-stepped def (c_run); Bend forbids mutual# recursion, so sequencing uses explicit tasks + continuations, exactly# like the lisp.bend machine. Parallel from the start: CAdd evaluates# both sides as a parallel pair, c_batch runs whole programs in parallel,# c_batch_gpu is the same runner handed to the GPU with `!`.type CExp is Data: CVar{idx: U32} CLit{val: Nat} CAdd{a: CExp, b: CExp} CLam{body: CExp} CApp{f: CExp, x: CExp} CLet{v: CExp, b: CExp} CCase{s: CExp, z: CExp, sd: CExp}type CVal is Data: VNum{v: Nat} VClos{body: CExp, env: List<&2, CVal>} VThunk{e: CExp, env: List<&2, CVal>}type CK is Data: CDone{} CAddR{a: CVal, k: CK} CAppA{x: CExp, env: List<&2, CVal>, k: CK} CCaseK{z: CExp, sd: CExp, env: List<&2, CVal>, k: CK}type CTask is Data: CEval{e: CExp, env: List<&2, CVal>, k: CK} CRet{k: CK, v: CVal} CLook{n: Nat, env: List<&2, CVal>, k: CK}def c_num_add(+a: CVal, +b: CVal) -> CVal: match a b: case VNum{x} VNum{y}: VNum{Nat.add(x, y)} case _ _: VNum{0n}def c_run(+f: Nat, +t: CTask) -> CVal: match f: case 0n: VNum{0n} case 1n+p: match t: case CEval{e, env, k}: match e: case CVar{i}: c_run(p, CLook{U32.to_nat(i), env, k}) case CLit{v}: c_run(p, CRet{k, VNum{v}}) case CAdd{a, b}: av bv = c_run(p, CEval{a, env, CDone{}}) c_run(p, CEval{b, env, CDone{}}) c_num_add(av, bv) case CLam{body}: c_run(p, CRet{k, VClos{body, env}}) case CApp{f, x}: c_run(p, CEval{f, env, CAppA{x, env, k}}) case CLet{v, b}: c_run(p, CEval{b, Con{VThunk{v, env}, env}, k}) case CCase{s, z, sd}: c_run(p, CEval{s, env, CCaseK{z, sd, env, k}}) case CRet{k, v}: match k: case CDone{}: v case CAddR{a, k2}: c_num_add(a, v) case CAppA{x, env, k2}: match v: case VClos{body, cenv}: c_run(p, CEval{body, Con{VThunk{x, env}, cenv}, k2}) case VThunk{e, eenv}: c_run(p, CEval{e, eenv, CAppA{x, env, k2}}) case _: c_run(p, CRet{k2, VNum{0n}}) case CCaseK{z, sd, env, k2}: match v: case VNum{n}: match n: case 0n: c_run(p, CEval{z, env, k2}) case 1n+m: c_run(p, CEval{sd, Con{VNum{m}, env}, k2}) case _: c_run(p, CRet{k2, VNum{0n}}) case CLook{n, env, k}: match n env: case 0n Con{v, vs}: match v: case VThunk{e, eenv}: c_run(p, CEval{e, eenv, k}) case _: c_run(p, CRet{k, v}) case 1n+m Con{v, vs}: c_run(p, CLook{m, vs, k}) case _ _: c_run(p, CRet{k, VNum{0n}})def c_eval(+f: Nat, +e: CExp) -> CVal: c_run(f, CEval{e, Nil{}, CDone{}})def c_batch(+f: Nat, +es: List<&2, CExp>) -> List<&2, CVal>: match es: case Nil{}: Nil{} case Con{h, t}: r rs = c_eval(f, h) c_batch(f, t) Con{r, rs}def c_batch_gpu(+f: Nat, +es: List<&2, CExp>) -> List<&2, CVal>: c_batch!(f, es)def main() -> List<&2, CVal>: c_batch(30n, [CLit{5n}, CAdd{CLit{2n}, CLit{3n}}, CLet{CLit{3n}, CAdd{CVar{0}, CLit{4n}}}])