Demo

Parses a FunctionalScript module and draws its source AST beside the Foundation AST (FAST) it normalizes to. A binding is one node however many places use it; source bindings carry their names, FAST bindings are numbered in definition order. Dashed arrows mark operands that may not be evaluated, and arrows back to a function or loop are the exits that leave it. Expand "As DataJS" under a graph to check it against the exact tree.

Source AST

module [body] → blockblock [initialize] → initializeblock [initialize] → initializeblock [yield] → {}initialize [=] → ainitialize [value] → +initialize [=] → checkedinitialize [value] → .{} [default] → []. [obj] → a[] [0] → a[] [1] → a[] [2] → *[] [3] → &&[] [4] → =>* [left] → a&& [left] → <&& [right] → a=> [rest] → x=> [body] → block< [left] → ablock [return] → returnreturn [to] → => (recursive)return [value] → xmodulebodyblockinitializeinitializeyieldinitialize=valueinitialize=value{}default+leftright12checked.objkeya"x"[]012345aa*&&=>undefined*leftrighta3&&leftright=>lengthrestbody0xblock<leftrighta4blockreturnareturntovaluex
As DataJS
const $0={"index":0};const $1={"kind":"function","index":9};const $2={"index":0};export default {"imports":[],"body":{"statements":[["initialize",{"reads":[{"source":null,"spread":false}],"ids":[$0]},["+",1,2]],["initialize",{"reads":[{"source":null,"spread":false}],"ids":[{"index":0}]},[".",["ref",$0],"x"]]],"exit":["yield",["object",[[":","default",["array",[["ref",$0],["ref",$0],["*",["ref",$0],3],["&&",["<",["ref",$0],4],["ref",$0]],["function",{"target":$1,"length":0,"parameters":[],"rest":{"reads":[{"source":null,"spread":false}],"ids":[$2]},"self":null,"body":{"statements":[],"exit":["return",$1,["ref",$2]]}}],undefined]]]]]]}};

FAST

module [body] → blockblock [define] → $0block [define] → $1block [yield] → {}$1 [value] → .{} [default] → []. [obj] → $0[] [0] → $0[] [1] → $0[] [2] → *[] [3] → block[] [4] → =>* [left] → $0block [define] → $2block [yield] → if=> [rest] → $3=> [body] → blockif [cond] → $2if [then] → blockif [else] → blockblock [return] → returnblock [yield] → $0block [yield] → $2return [to] → => (recursive)return [value] → $3$2 [value] → << [left] → $0$0 [value] → +modulebodyblockdefinedefineyield$1value{}default.objkey$0"x"[]012345$0$0*block=>undefined*leftright$03blockdefineyield=>restbodyifcondthenelseblockreturnblockyieldblockyieldreturntovalue$2value$3<leftright$04$0value+leftright12
As DataJS
const $0={"index":0};const $1=["ref",$0];const $2={"index":0};const $3=["ref",$2];const $4={"kind":"function","index":9};const $5={"index":0};export default {"parameters":[],"body":{"statements":[["define",$0,["+",1,2],"required"],["define",{"index":0},[".",$1,"x"],"required"]],"exit":["yield",[["object",[[":","default",["array",[$1,$1,["*",$1,3],["block",{"statements":[["define",$2,["<",$1,4],"required"]],"exit":["yield",[["if",$3,{"statements":[],"exit":["yield",[$1]]},{"statements":[],"exit":["yield",[$3]]}]]]}],["function",{"target":$4,"parameters":[],"rest":$5,"self":null,"captures":[],"body":{"statements":[],"exit":["return",$4,["ref",$5]]}}],undefined]]]]]]]}};

Emergent Testing

Idle. Press Run to start the suite.

  • ./demo.proof.f.mjs