{
Let analyze. analyze
}
Where
Let analyze program.
Let program. (place_packages program)
In
Let program. (collect_constants program)
In
Let program. (collect_labels_and_layouts program)
In
Let program. (place_variables program)
In
Let program. (flatten program)
In
program
Where
Let place_packages program.
Let MAP. (SEARCH.MAP STRING.compare Func {key _}. key)
In
Let {_ packages}.
(LIST.reduce program {0 MAP.empty}
Func {i packages} package.
{(i + 1) (MAP.insert packages {package.path i})})
In
Define rewrite_expr expr.
Match expr
| `true expr
| `false expr
| `num._ expr
| `str._ expr
| `package.path
Let i.
Match (MAP.search packages path)
| `just.{_ i} i
| `nothing (die "Package not found.")
;
In
`package.i
| `prim._ expr
| `var._ expr
| `chain.{expr chain}
`chain.{(rewrite_expr expr) chain}
| `tuple.exprs
`tuple.(LIST.map exprs rewrite_expr)
| `module.binders
Let binders.
(LIST.map binders
Func binder.
Match binder
| `let.{pat expr} `let.{pat (rewrite_expr expr)}
;)
In
`module.binders
| `block.{binder_groups expr}
Let binder_groups.
(LIST.map binder_groups
Func binder_group.
(LIST.map binder_group
Func binder.
Match binder
| `let.{pat expr} `let.{pat (rewrite_expr expr)}
| `do.expr `do.(rewrite_expr expr)
;))
Let expr. (rewrite_expr expr)
In
`block.{binder_groups expr}
| `app.{func args}
Let func. (rewrite_expr func)
Let args. (LIST.map args rewrite_expr)
In
`app.{func args}
| `closure._ expr
| `func.{i self free param_pats expr}
`func.{i self free param_pats (rewrite_expr expr)}
| `goto.expr
`goto.(rewrite_expr expr)
| `switch.{expr clauses}
Let expr. (rewrite_expr expr)
Let clauses.
(LIST.map clauses
Func {pat body}. {pat (rewrite_expr body)})
In
`switch.{expr clauses}
| `cond.clauses
Let clauses.
(LIST.map clauses
Func {test body}.
{(rewrite_expr test) (rewrite_expr body)})
In
`cond.clauses
| `if.{test_expr then_expr else_expr}
Let test_expr. (rewrite_expr test_expr)
Let then_expr. (rewrite_expr then_expr)
Let else_expr. (rewrite_expr else_expr)
In
`if.{test_expr then_expr else_expr}
| `not.expr
`not.(rewrite_expr expr)
| `and.{test_expr then_expr}
Let test_expr. (rewrite_expr test_expr)
Let then_expr. (rewrite_expr then_expr)
In
`and.{test_expr then_expr}
| `or.{test_expr else_expr}
Let test_expr. (rewrite_expr test_expr)
Let else_expr. (rewrite_expr else_expr)
In
`or.{test_expr else_expr}
| `list.exprs
`list.(LIST.map exprs rewrite_expr)
| `labeled.{label expr}
`labeled.{label (rewrite_expr expr)}
| `match.{expr clauses}
Let expr. (rewrite_expr expr)
Let clauses.
(LIST.map clauses
Func {pat body}. {pat (rewrite_expr body)})
In
`match.{expr clauses}
;
In
(LIST.map program
Func package.
{
Let path. package.path
Let imports. package.imports
Let init. (rewrite_expr package.init)
Let functions. (LIST.map package.functions rewrite_expr)
})
Let collect_constants program.
Let MAP.
(SEARCH.MAP
Func a b.
Match a
| `str.sa
Match b
| `str.sb (STRING.compare sa sb)
| `prim._ `greater
;
| `prim.sa
Match b
| `str._ `less
| `prim.sb (STRING.compare sa sb)
;
| _ (die "Unexpected constant.")
;
Func {key _}. key)
Let counter. &0
In
Let constants. &MAP.empty
In
Let intern const.
Match (MAP.search ?constants const)
| `just.{_ i} i
| `nothing
Let i. ?counter
In
Do (counter ! i + 1)
Do (constants ! MAP.insert ?constants {const i})
In
i
;
In
Define rewrite_expr expr.
Match expr
| `true expr
| `false expr
| `num._ expr
| `str._ `const.(intern expr)
| `package._ expr
| `prim._ `const.(intern expr)
| `var._ expr
| `chain.{expr chain}
`chain.{(rewrite_expr expr) chain}
| `tuple.exprs
`tuple.(LIST.map exprs rewrite_expr)
| `module.binders
Let binders.
(LIST.map binders
Func binder.
Match binder
| `let.{pat expr} `let.{pat (rewrite_expr expr)}
;)
In
`module.binders
| `block.{binder_groups expr}
Let binder_groups.
(LIST.map binder_groups
Func binder_group.
(LIST.map binder_group
Func binder.
Match binder
| `let.{pat expr} `let.{pat (rewrite_expr expr)}
| `do.expr `do.(rewrite_expr expr)
;))
Let expr. (rewrite_expr expr)
In
`block.{binder_groups expr}
| `app.{func args}
Let func. (rewrite_expr func)
Let args. (LIST.map args rewrite_expr)
In
`app.{func args}
| `closure._ expr
| `func.{i self free param_pats expr}
`func.{i self free param_pats (rewrite_expr expr)}
| `goto.expr
`goto.(rewrite_expr expr)
| `switch.{expr clauses}
Let expr. (rewrite_expr expr)
Let clauses.
(LIST.map clauses
Func {pat body}. {pat (rewrite_expr body)})
In
`switch.{expr clauses}
| `cond.clauses
Let clauses.
(LIST.map clauses
Func {test body}.
{(rewrite_expr test) (rewrite_expr body)})
In
`cond.clauses
| `if.{test_expr then_expr else_expr}
Let test_expr. (rewrite_expr test_expr)
Let then_expr. (rewrite_expr then_expr)
Let else_expr. (rewrite_expr else_expr)
In
`if.{test_expr then_expr else_expr}
| `not.expr
`not.(rewrite_expr expr)
| `and.{test_expr then_expr}
Let test_expr. (rewrite_expr test_expr)
Let then_expr. (rewrite_expr then_expr)
In
`and.{test_expr then_expr}
| `or.{test_expr else_expr}
Let test_expr. (rewrite_expr test_expr)
Let else_expr. (rewrite_expr else_expr)
In
`or.{test_expr else_expr}
| `list.exprs
`list.(LIST.map exprs rewrite_expr)
| `labeled.{label expr}
`labeled.{label (rewrite_expr expr)}
| `match.{expr clauses}
Let expr. (rewrite_expr expr)
Let clauses.
(LIST.map clauses
Func {pat body}. {pat (rewrite_expr body)})
In
`match.{expr clauses}
;
In
Let packages.
(LIST.map program
Func package.
{
Let path. package.path
Let imports. package.imports
Let init. (rewrite_expr package.init)
Let functions. (LIST.map package.functions rewrite_expr)
})
In
{
Let constants.
(LIST.map
(SORT.list_insertion
Func {_ i} {_ j}. (Z.compare i j)
(MAP.list ?constants))
Func {const _}. const)
Let packages. packages
}
Let collect_labels_and_layouts program.
Let LABEL_MAP.
(SEARCH.MAP STRING.compare
Func {key _}. key)
Let LABEL_NAME_MAP.
(SEARCH.MAP Z.compare
Func {key _}. key)
Let LAYOUT_MAP.
(SEARCH.MAP
Func a b.
Let m. (LIST.length a)
Let n. (LIST.length b)
In
Cond
| (m < n) `less
| (m > n) `greater
| True
(LIST.reduce (LIST.zip a b) `equal
Func relation pair.
Match relation
| `equal
Let {ai bi}. pair
In
Cond
| (ai < bi) `less
| (ai > bi) `greater
| True `equal
;
| _ relation
;)
;
Func {key _}. key)
In
Let labels. &LABEL_MAP.empty
Let label_names. &LABEL_NAME_MAP.empty
Let layouts. &LAYOUT_MAP.empty
Let module_indexes. &[]
Let label_counter. &0
Let layout_counter. &0
In
Let intern_label name.
Match (LABEL_MAP.search ?labels name)
| `just.{_ i} i
| `nothing
Let i. ?label_counter
In
Do (label_counter ! (i + 1))
Do (labels ! (LABEL_MAP.insert ?labels {name i}))
Do (label_names ! (LABEL_NAME_MAP.insert ?label_names {i name}))
In
i
;
In
Let intern_layout labels.
Match (LAYOUT_MAP.search ?layouts labels)
| `just.{_ i} i
| `nothing
Let i. ?layout_counter
In
Do (layout_counter ! (i + (LIST.length labels) + 1))
Do (layouts ! (LAYOUT_MAP.insert ?layouts {labels i}))
Do (module_indexes ! (labels::?module_indexes))
In
i
;
In
Define rewrite_expr expr.
Match expr
| `true expr
| `false expr
| `num._ expr
| `const._ expr
| `package._ expr
| `var._ expr
| `chain.{expr chain}
Let chain.
(LIST.map chain
Func access.
Match access
| `id.name `module_fetch.(intern_label name)
| `num.i `tuple_fetch.i
;)
In
`chain.{(rewrite_expr expr) chain}
| `tuple.exprs
`tuple.(LIST.map exprs rewrite_expr)
| `module.binders
Let {binders labels}.
(LIST.fold binders {[] []}
Func binder {binders labels}.
Match binder
| `let.{pat expr}
Let binder. `let.{pat (rewrite_expr expr)}
Let label.
Match pat
| `var.var (intern_label var)
| _ (die "Invalid label in module expression.")
;
In
{(binder::binders) (label::labels)}
;)
In
Let labels. (SORT.list_insertion Z.compare labels)
In
Let layout. (intern_layout labels)
In
Let binders.
(LIST.fold labels []
Func label sorted_binders.
Let maybe_binder.
(LIST.reduce binders `nothing
Func choice binder.
Match choice
| `nothing
Match binder
| `let.{pat expr}
Match pat
| `var.var
If (label = (intern_label var))
`just.binder
`nothing
;
;
| `just._ choice
;)
In
Match maybe_binder
| `just.binder (binder::sorted_binders)
| `nothing (die "Label sorting bug in module expr.")
;)
In
`module.{layout binders}
| `block.{binder_groups expr}
Let binder_groups.
(LIST.map binder_groups
Func binder_group.
(LIST.map binder_group
Func binder.
Match binder
| `let.{pat expr} `let.{pat (rewrite_expr expr)}
| `do.expr `do.(rewrite_expr expr)
;))
Let expr. (rewrite_expr expr)
In
`block.{binder_groups expr}
| `app.{func args}
Let func. (rewrite_expr func)
Let args. (LIST.map args rewrite_expr)
In
`app.{func args}
| `closure._ expr
| `func.{i self free param_pats expr}
`func.{i self free param_pats (rewrite_expr expr)}
| `goto.expr
`goto.(rewrite_expr expr)
| `switch.{expr clauses}
Let expr. (rewrite_expr expr)
Let clauses.
(LIST.map clauses
Func {pat body}. {pat (rewrite_expr body)})
In
`switch.{expr clauses}
| `cond.clauses
Let clauses.
(LIST.map clauses
Func {test body}.
{(rewrite_expr test) (rewrite_expr body)})
In
`cond.clauses
| `if.{test_expr then_expr else_expr}
Let test_expr. (rewrite_expr test_expr)
Let then_expr. (rewrite_expr then_expr)
Let else_expr. (rewrite_expr else_expr)
In
`if.{test_expr then_expr else_expr}
| `not.expr
`not.(rewrite_expr expr)
| `and.{test_expr then_expr}
Let test_expr. (rewrite_expr test_expr)
Let then_expr. (rewrite_expr then_expr)
In
`and.{test_expr then_expr}
| `or.{test_expr else_expr}
Let test_expr. (rewrite_expr test_expr)
Let else_expr. (rewrite_expr else_expr)
In
`or.{test_expr else_expr}
| `list.exprs
`list.(LIST.map exprs rewrite_expr)
| `labeled.{label expr}
`labeled.{(intern_label label) (rewrite_expr expr)}
| `match.{expr clauses}
Let expr. (rewrite_expr expr)
Let clauses.
(LIST.fold clauses []
Func clause clauses.
Let {pat body}. clause
In
Let pat.
Match pat
| `default pat
| `labeled.{label vars}
Let label. (intern_label label)
In
`labeled.{label vars}
;
In
({pat (rewrite_expr body)}::clauses))
In
`match.{expr clauses}
;
In
Let packages.
(LIST.map program.packages
Func package.
{
Let path. package.path
Let imports. package.imports
Let init. (rewrite_expr package.init)
Let functions. (LIST.map package.functions rewrite_expr)
})
In
Let nil_label. (intern_label "nil")
Let cons_label. (intern_label "cons")
In
{
Let constants. program.constants
Let label_names. (LABEL_MAP.list ?label_names)
Let module_indexes. (LIST.reverse ?module_indexes)
Let packages. packages
Let nil_label. nil_label
Let cons_label. cons_label
}
Let place_variables program.
Let MAP.
(SEARCH.MAP STRING.compare
Func {key _}. key)
In
Define reduce_expr env i expr.
Match expr
| `true expr
| `false expr
| `num._ expr
| `const._ expr
| `package._ expr
| `var.name
Match (MAP.search env name)
| `just.{_ place} place
| `nothing (die "place_variables: Unexpected unbound variable.")
;
| `chain.{expr chain}
`chain.{(reduce_expr env i expr) chain}
| `tuple.exprs
Let {i exprs}.
(LIST.reduce exprs {i []}
Func {i exprs} expr.
Let expr. (reduce_expr env i expr)
In
{(i + 1) (expr::exprs)})
In
`tuple.(LIST.reverse exprs)
| `module.{layout binders}
Let {_ binders}.
(LIST.reduce binders {i []}
Func {i binders} binder.
Match binder
| `let.{var expr}
Let binder.
`let.{var (reduce_expr env i expr)}
In
{(i + 1) (binder::binders)}
;)
In
`module.{layout (LIST.reverse binders)}
| `block.{binder_groups expr}
Let {binder_groups i env}.
(LIST.fold binder_groups {[] i env}
Func binder_group {binder_groups i env}.
Let {binder_group i env}.
(LIST.fold binder_group {[] i env}
Func binder {binder_group i env'}.
Let binder.
Match binder
| `let.{pat expr}
Let pat.
Match pat
| `tuple.vars
`tuple.(LIST.length vars)
| `var._ `var
;
In
`let.{pat (reduce_expr env i expr)}
| `do.expr
`do.(reduce_expr env i expr)
;
Let {env' i}.
(LIST.reduce (binder_variables binder)
{env' i}
Func {env' i} var.
Let env'.
(MAP.insert env' {var `stack.i})
Let i. (i + 1)
In
{env' i})
In
Let binder_group. (binder::binder_group)
In
{binder_group i env'})
In
{(binder_group::binder_groups) i env})
In
Let expr. (reduce_expr env i expr)
In
`block.{binder_groups expr}
| `app.{func args}
Let n. (i + 3 + (LIST.length args))
In
Let func. (reduce_expr env n func)
Let {_ args}.
(LIST.fold args {(n + -1) []}
Func arg {i args}.
{(i + -1) ((reduce_expr env i arg)::args)})
In
`app.{func args}
| `closure.{j free num_params}
Let free.
(LIST.map free
Func name. (reduce_expr env i `var.name))
In
`closure.{j free num_params}
| `func.{j self free param_pats expr}
Let env.
Match self
| `nothing env
| `just.name (MAP.insert env {name `self})
;
In
Let {_ env}.
(LIST.reduce free {0 env}
Func {k env} name.
Let env. (MAP.insert env {name `free.k})
Let k. (k + 1)
In
{k env})
In
Let n. (LIST.length param_pats)
In
Let {i k env}.
(LIST.reduce param_pats {0 n env}
Func {i k env} pat.
Let {k env}.
Match pat
| `ignore {k env}
| `var.name {k (MAP.insert env {name `stack.i})}
| `tuple.names
(LIST.reduce names {k env}
Func {k env} name.
Let env.
(MAP.insert env {name `stack.k})
In
{(k + 1) env})
;
In
{(i + 1) k env})
In
Let expr. (reduce_expr env k expr)
In
`func.{j param_pats expr}
| `goto.expr
Let {func args}. Match expr | `app.pair pair ;
In
Let n. (i + (LIST.length args))
In
Let func. (reduce_expr env n func)
Let {_ args}.
(LIST.fold args {(n + -1) []}
Func arg {i args}.
{(i + -1) ((reduce_expr env i arg)::args)})
In
`goto.`app.{func args}
| `switch.{expr clauses}
Let expr. (reduce_expr env i expr)
In
Let clauses.
(LIST.fold clauses []
Func clause clauses.
Let {pat body}. clause
In
Let {i env pat}.
Match pat
| `default.maybe_name
Match maybe_name
| `just.name
Let i. (i + 1)
Let env. (MAP.insert env {name `stack.i})
In
{i env `default.`push}
| `nothing {i env `default.`no_push}
;
| `value._ {i env pat}
;
In
Let body. (reduce_expr env i body)
In
({pat body}::clauses))
In
`switch.{expr clauses}
| `cond.clauses
Let clauses.
(LIST.map clauses
Func {test body}.
{(reduce_expr env i test) (reduce_expr env i body)})
In
`cond.clauses
| `if.{test_expr then_expr else_expr}
Let test_expr. (reduce_expr env i test_expr)
Let then_expr. (reduce_expr env i then_expr)
Let else_expr. (reduce_expr env i else_expr)
In
`if.{test_expr then_expr else_expr}
| `not.expr
`not.(reduce_expr env i expr)
| `and.{test_expr then_expr}
`and.{(reduce_expr env i test_expr) (reduce_expr env i then_expr)}
| `or.{test_expr else_expr}
`or.{(reduce_expr env i test_expr) (reduce_expr env i else_expr)}
| `list.exprs
`list.(LIST.map exprs Func expr. (reduce_expr env i expr))
| `labeled.{label expr}
`labeled.{label (reduce_expr env i expr)}
| `match.{expr clauses}
Let expr. (reduce_expr env i expr)
In
Let clauses.
(LIST.fold clauses []
Func clause clauses.
Let {pat body}. clause
In
Let {pat names}.
Match pat
| `default {`default []}
| `labeled.{label vars}
Let {vars names}.
Match vars
| `default {`default []}
| `var.name {`var [name]}
| `tuple.names
{`tuple.(LIST.length names) names}
;
In
{`labeled.{label vars} names}
;
In
Let {i env}.
(LIST.reduce names {i env}
Func {i env} name.
{(i + 1) (MAP.insert env {name `stack.i})})
In
Let body. (reduce_expr env i body)
In
({pat body}::clauses))
In
`match.{expr clauses}
;
In
Let packages.
(LIST.map program.packages
Func package.
{
Let path. package.path
Let imports. package.imports
Let init. (reduce_expr MAP.empty 0 package.init)
Let functions.
(LIST.map package.functions
Func func.
(reduce_expr MAP.empty 0 func))
})
In
{
Let constants. program.constants
Let label_names. program.label_names
Let module_indexes. program.module_indexes
Let packages. packages
Let nil_label. program.nil_label
Let cons_label. program.cons_label
}
Let flatten program.
Let num_packages. (LIST.length program.packages)
In
Let {i _ init_code}.
(LIST.fold program.packages {0 (num_packages + -1) []}
Func package {i j instrs}.
Let {i instrs}.
(flatten_expr package.init `nontail i $
`package_env_store.j::instrs)
In
{i (j + -1) instrs})
In
Let {_ function_code}.
(LIST.fold program.packages {i []}
Func package {i instrs}.
(LIST.fold package.functions {i instrs}
Func func {i instrs}.
(flatten_expr func `tail i instrs)))
In
{
Let constants. program.constants
Let label_names. program.label_names
Let module_indexes. program.module_indexes
Let packages. program.packages
Let nil_label. program.nil_label
Let cons_label. program.cons_label
Let init_code. init_code
Let function_code. function_code
}
Where
Define flatten_expr expr position i instrs.
Let instrs.
Match position
| `tail
Match expr
| `goto._ instrs
| `block._ instrs
| `if._ instrs
| `match._ instrs
| `cond._ instrs
| `switch._ instrs
| `func._ instrs
| _ (`pop_frame::instrs)
;
| `nontail
Match expr
| `goto._ (die "Goto used in nontail position.")
| _ instrs
;
;
In
Let trivial. {i (expr::instrs)}
In
Match expr
| `true trivial
| `false trivial
| `num._ trivial
| `const._ trivial
| `package._ trivial
| `stack._ trivial
| `free._ trivial
| `self trivial
| `chain.{expr chain}
Let instrs.
(LIST.fold chain instrs
Func access instrs. (access::instrs))
In
(flatten_expr expr `nontail i instrs)
| `tuple.exprs
Let size. (LIST.length exprs)
In
(LIST.fold exprs {i (`alloc_tuple.size::instrs)}
Func expr {i instrs}.
(flatten_expr expr `nontail i $ `push::instrs))
| `module.{layout binders}
(LIST.fold binders
{i (`alloc_module.{layout (LIST.length binders)}::instrs)}
Func binder {i instrs}.
Match binder
| `let.{var expr}
Goto (flatten_expr expr `nontail i $ `push::instrs)
;)
| `block.{binder_groups expr}
Let num_vars.
(LIST.reduce binder_groups 0
Func sum binder_group.
(LIST.reduce binder_group sum
Func sum binder.
(sum + (binder_num_placed_variables binder))))
In
Let instrs.
If (num_vars = 0)
instrs
Match position
| `tail instrs
| `nontail (`pop_vars.num_vars::instrs)
;
In
(LIST.reduce binder_groups (flatten_expr expr position i instrs)
Func {i instrs} binder_group.
(LIST.reduce binder_group {i instrs}
Func {i instrs} binder.
Match binder
| `let.{pat expr}
Let instrs.
Match pat
| `tuple.n
Switch n
| 0 instrs
| _ (`open_tuple.n::instrs)
;
| `var (`push::instrs)
;
In
Goto (flatten_expr expr `nontail i instrs)
| `do.expr
Goto (flatten_expr expr `nontail i instrs)
;))
| `app.{func args}
Let num_args. (LIST.length args)
Let j. i
In
Let {i instrs}.
(flatten_expr func `nontail (i + 1) $
`call.num_args::`block.j::instrs)
In
Let {i instrs}.
(LIST.fold args {i instrs}
Func arg {i instrs}.
Goto (flatten_expr arg `nontail i $ `push::instrs))
In
{i (`push_frame.j::instrs)}
| `closure.{j free num_params}
{i (`alloc_closure.{j free num_params}::instrs)}
| `func.{j param_pats expr}
Let {i instrs}. (flatten_expr expr `tail i instrs)
Let k. ((LIST.length param_pats) + -1)
In
Let {_ instrs}.
(LIST.fold param_pats {k instrs}
Func pat {k instrs}.
Let instrs.
Match pat
| `ignore instrs
| `var._ instrs
| `tuple.names
(`stack.k::`open_tuple.(LIST.length names)::instrs)
;
In
{(k + -1) instrs})
In
{i (`entry.j::instrs)}
| `goto.expr
Match expr
| `app.{func args}
Let num_args. (LIST.length args)
In
Let {i instrs}.
(flatten_expr func `nontail i $ `tailcall.num_args::instrs)
In
(LIST.fold args {i instrs}
Func arg {i instrs}.
Goto (flatten_expr arg `nontail i $ `push::instrs))
;
| `switch.{expr clauses}
Let j. i
Let {i instrs}.
Match position
| `tail {i instrs}
| `nontail {(i + 1) (`block.i::instrs)}
;
In
Let {i instrs clauses}.
(LIST.fold clauses {i instrs []}
Func {pat body} {i instrs clauses}.
Let instrs.
Match position
| `tail instrs
| `nontail
Match pat
| `default.maybe_push
Match maybe_push
| `push (`pop_vars.1::`jump.j::instrs)
| `no_push (`jump.j::instrs)
;
| `value._ (`jump.j::instrs)
;
;
In
Let {i instrs}. (flatten_expr body position i instrs)
In
{(i + 1) (`block.i::instrs) ({pat i}::clauses)})
In
Let {clauses default}.
(LIST.fold clauses {[] `nothing}
Func {pat i} {clauses default}.
Match pat
| `default.maybe_push
Match maybe_push
| `push {clauses `just.`push_and_jump.i}
| `no_push {clauses `just.`jump.i}
;
| `value.n {({n i}::clauses) default}
;)
In
Let instrs. (`switch.{clauses default}::instrs)
In
(flatten_expr expr `nontail i instrs)
| `cond.clauses
Let j. i
Let {i instrs}.
Match position
| `nontail {(i + 1) (`block.i::instrs)}
| `tail {i instrs}
;
In
Let instrs. (`block.i::`halt::instrs)
In
Let {i instrs _}.
(LIST.fold clauses {(i + 1) instrs i}
Func {test body} {i instrs k}.
Let instrs.
Match position
| `tail instrs
| `nontail (`jump.j::instrs)
;
In
Let {i instrs}. (flatten_expr body position i instrs)
In
Let instrs. (`jump_if_false.k::instrs)
In
Let {i instrs}. (flatten_expr test `nontail i instrs)
In
{(i + 1) (`block.i::instrs) i})
In
{i instrs}
| `if.{test_expr then_expr else_expr}
Let j. i
Let {i instrs}.
Match position
| `nontail {(i + 1) (`block.i::instrs)}
| `tail {i instrs}
;
In
Let k. i
Let {i instrs}. (flatten_expr else_expr position (i + 1) instrs)
In
Let instrs. (`block.k::instrs)
In
Let instrs.
Match position | `tail instrs | `nontail (`jump.j::instrs) ;
In
Let {i instrs}. (flatten_expr then_expr position i instrs)
In
(flatten_expr test_expr `nontail i $ `jump_if_false.k::instrs)
| `not.expr
(flatten_expr expr `nontail i $ `not::instrs)
| `and.{test_expr then_expr}
Let j. i
Let i. (i + 1)
Let instrs. (`block.i::instrs)
In
Let {i instrs}. (flatten_expr then_expr position i instrs)
In
(flatten_expr test_expr `nontail i $ `jump_if_false.j::instrs)
| `or.{test_expr else_expr}
Let j. i
Let i. (i + 1)
Let instrs. (`block.i::instrs)
In
Let {i instrs}. (flatten_expr else_expr position i instrs)
In
(flatten_expr test_expr `nontail i $ `jump_if_true.j::instrs)
| `list.exprs
Let {i instrs}.
(LIST.reduce exprs {i instrs}
Func {i instrs} expr.
Let instrs.
(`push::`swap::`alloc_tuple.2::`cons::instrs)
In
Let {i instrs}. (flatten_expr expr `nontail i instrs)
In
{i (`push::instrs)})
In
{i (`nil::instrs)}
| `labeled.{label expr}
Match expr
| `tuple.exprs
Match exprs
| `nil {i (`labeled_empty_tuple.label::instrs)}
| `cons._ (flatten_expr expr `nontail i $ `label.label::instrs)
;
| _ (flatten_expr expr `nontail i $ `label.label::instrs)
;
| `match.{expr clauses}
Let j. i
Let {i instrs}.
Match position
| `tail {i instrs}
| `nontail {(i + 1) (`block.i::instrs)}
;
In
Let {i instrs clauses}.
(LIST.fold clauses {i instrs []}
Func {pat body} {i instrs clauses}.
Let instrs.
Match position
| `tail instrs
| `nontail
Let instrs. (`jump.j::instrs)
In
Match pat
| `default instrs
| `labeled.{_ vars}
Match vars
| `default instrs
| `var (`pop_vars.1::instrs)
| `tuple.num_vars (`pop_vars.num_vars::instrs)
;
;
;
In
Let {i instrs}. (flatten_expr body position i instrs)
In
{(i + 1) (`block.i::instrs) ({pat i}::clauses)})
In
Let {clauses default}.
(LIST.fold clauses {[] `nothing}
Func {pat i} {clauses default}.
Match pat
| `default {clauses `just.i}
| `labeled.{label vars}
Match vars
| `default {({`default.label i}::clauses) default}
| `var {({`var.label i}::clauses) default}
| `tuple.num_vars
{({`tuple.{label num_vars} i}::clauses) default}
;
;)
In
Let instrs. (`match.{clauses default}::instrs)
In
(flatten_expr expr `nontail i instrs)
;
Where
Let binder_variables binder.
Match binder
| `let.{pat _} Match pat | `tuple.vars vars | `var.var [var] ;
| `do._ []
;
Let binder_num_placed_variables binder.
Match binder
| `let.{pat _} Match pat | `tuple.n n | `var 1 ;
| `do._ 0
;
Where
Let die. Prim die
Where
Let LIST. Package "list"
Let SEARCH. Package "search"
Let SORT. Package "sort"
Let STDIO. Package "stdio"
Let STRING. Package "string"
Let Z. Package "z"