From 71d7a4c7206155e09f3e1e1d8699561ea6967382 Mon Sep 17 00:00:00 2001 From: Eduardo Julian Date: Wed, 1 Nov 2017 00:04:43 -0400 Subject: - Re-organized synthesis. --- new-luxc/test/test/luxc/generator/case.lux | 1 - new-luxc/test/test/luxc/generator/function.lux | 1 - new-luxc/test/test/luxc/generator/primitive.lux | 1 - .../test/luxc/generator/procedure/common.jvm.lux | 1 - .../test/luxc/generator/procedure/host.jvm.lux | 1 - new-luxc/test/test/luxc/generator/structure.lux | 1 - .../test/test/luxc/lang/synthesis/case/special.lux | 68 +++++++++ new-luxc/test/test/luxc/lang/synthesis/common.lux | 37 +++++ .../test/test/luxc/lang/synthesis/function.lux | 150 +++++++++++++++++++ new-luxc/test/test/luxc/lang/synthesis/loop.lux | 159 +++++++++++++++++++++ .../test/test/luxc/lang/synthesis/primitive.lux | 45 ++++++ .../test/test/luxc/lang/synthesis/procedure.lux | 32 +++++ .../test/test/luxc/lang/synthesis/structure.lux | 49 +++++++ .../test/test/luxc/synthesizer/case/special.lux | 68 --------- new-luxc/test/test/luxc/synthesizer/common.lux | 37 ----- new-luxc/test/test/luxc/synthesizer/function.lux | 150 ------------------- new-luxc/test/test/luxc/synthesizer/loop.lux | 159 --------------------- new-luxc/test/test/luxc/synthesizer/primitive.lux | 45 ------ new-luxc/test/test/luxc/synthesizer/procedure.lux | 32 ----- new-luxc/test/test/luxc/synthesizer/structure.lux | 49 ------- new-luxc/test/tests.lux | 14 +- 21 files changed, 547 insertions(+), 553 deletions(-) create mode 100644 new-luxc/test/test/luxc/lang/synthesis/case/special.lux create mode 100644 new-luxc/test/test/luxc/lang/synthesis/common.lux create mode 100644 new-luxc/test/test/luxc/lang/synthesis/function.lux create mode 100644 new-luxc/test/test/luxc/lang/synthesis/loop.lux create mode 100644 new-luxc/test/test/luxc/lang/synthesis/primitive.lux create mode 100644 new-luxc/test/test/luxc/lang/synthesis/procedure.lux create mode 100644 new-luxc/test/test/luxc/lang/synthesis/structure.lux delete mode 100644 new-luxc/test/test/luxc/synthesizer/case/special.lux delete mode 100644 new-luxc/test/test/luxc/synthesizer/common.lux delete mode 100644 new-luxc/test/test/luxc/synthesizer/function.lux delete mode 100644 new-luxc/test/test/luxc/synthesizer/loop.lux delete mode 100644 new-luxc/test/test/luxc/synthesizer/primitive.lux delete mode 100644 new-luxc/test/test/luxc/synthesizer/procedure.lux delete mode 100644 new-luxc/test/test/luxc/synthesizer/structure.lux (limited to 'new-luxc/test') diff --git a/new-luxc/test/test/luxc/generator/case.lux b/new-luxc/test/test/luxc/generator/case.lux index 7763cd852..e4201a30b 100644 --- a/new-luxc/test/test/luxc/generator/case.lux +++ b/new-luxc/test/test/luxc/generator/case.lux @@ -11,7 +11,6 @@ (meta [code]) test) (luxc (lang ["ls" synthesis]) - [synthesizer] (generator ["@" case] [";G" expression] ["@;" eval] diff --git a/new-luxc/test/test/luxc/generator/function.lux b/new-luxc/test/test/luxc/generator/function.lux index e7a0e7d61..2db2719b7 100644 --- a/new-luxc/test/test/luxc/generator/function.lux +++ b/new-luxc/test/test/luxc/generator/function.lux @@ -14,7 +14,6 @@ [host] test) (luxc (lang ["ls" synthesis]) - [synthesizer] (generator [";G" expression] ["@;" eval] ["@;" runtime] diff --git a/new-luxc/test/test/luxc/generator/primitive.lux b/new-luxc/test/test/luxc/generator/primitive.lux index 6de14d0e5..1ce93cee9 100644 --- a/new-luxc/test/test/luxc/generator/primitive.lux +++ b/new-luxc/test/test/luxc/generator/primitive.lux @@ -13,7 +13,6 @@ test) (luxc [";L" host] (lang ["ls" synthesis]) - [synthesizer] (generator [";G" expression] ["@;" runtime] ["@;" eval] diff --git a/new-luxc/test/test/luxc/generator/procedure/common.jvm.lux b/new-luxc/test/test/luxc/generator/procedure/common.jvm.lux index 5e3c07bea..0c24a4020 100644 --- a/new-luxc/test/test/luxc/generator/procedure/common.jvm.lux +++ b/new-luxc/test/test/luxc/generator/procedure/common.jvm.lux @@ -17,7 +17,6 @@ [host] test) (luxc (lang ["ls" synthesis]) - [synthesizer] (generator [";G" expression] ["@;" eval] ["@;" runtime] diff --git a/new-luxc/test/test/luxc/generator/procedure/host.jvm.lux b/new-luxc/test/test/luxc/generator/procedure/host.jvm.lux index d571c578b..91b20d3d4 100644 --- a/new-luxc/test/test/luxc/generator/procedure/host.jvm.lux +++ b/new-luxc/test/test/luxc/generator/procedure/host.jvm.lux @@ -18,7 +18,6 @@ test) (luxc [";L" host] (lang ["ls" synthesis]) - [synthesizer] (generator [";G" expression] ["@;" eval] ["@;" runtime] diff --git a/new-luxc/test/test/luxc/generator/structure.lux b/new-luxc/test/test/luxc/generator/structure.lux index 37320fa99..7c342dbc4 100644 --- a/new-luxc/test/test/luxc/generator/structure.lux +++ b/new-luxc/test/test/luxc/generator/structure.lux @@ -17,7 +17,6 @@ test) (luxc [";L" host] (lang ["ls" synthesis]) - [synthesizer] (generator [";G" expression] ["@;" eval] ["@;" runtime] diff --git a/new-luxc/test/test/luxc/lang/synthesis/case/special.lux b/new-luxc/test/test/luxc/lang/synthesis/case/special.lux new file mode 100644 index 000000000..585c7d349 --- /dev/null +++ b/new-luxc/test/test/luxc/lang/synthesis/case/special.lux @@ -0,0 +1,68 @@ +(;module: + lux + (lux [io] + (control [monad #+ do] + pipe) + (meta [code]) + ["r" math/random "r/" Monad] + test) + (luxc (lang ["la" analysis] + ["ls" synthesis] + (synthesis [";S" expression]) + [";L" variable #+ Variable])) + (../.. common)) + +(context: "Dummy variables." + (<| (times +100) + (do @ + [maskedA gen-primitive + temp (|> r;nat (:: @ map (n.% +100))) + #let [maskA (` ("lux case" (~ maskedA) + {("lux case bind" (~ (code;nat temp))) + (~ (la;var (variableL;local temp)))}))]] + (test "Dummy variables created to mask expressions get eliminated during synthesis." + (|> (expressionS;synthesize maskA) + (corresponds? maskedA)))))) + +(context: "Let expressions." + (<| (times +100) + (do @ + [registerA r;nat + inputA gen-primitive + outputA gen-primitive + #let [letA (` ("lux case" (~ inputA) + {("lux case bind" (~ (code;nat registerA))) + (~ outputA)}))]] + (test "Can detect and reify simple 'let' expressions." + (|> (expressionS;synthesize letA) + (case> (^ [_ (#;Form (list [_ (#;Text "lux let")] [_ (#;Nat registerS)] inputS outputS))]) + (and (n.= registerA registerS) + (corresponds? inputA inputS) + (corresponds? outputA outputS)) + + _ + false)))))) + +(context: "If expressions." + (<| (times +100) + (do @ + [then|else r;bool + inputA gen-primitive + thenA gen-primitive + elseA gen-primitive + #let [ifA (if then|else + (` ("lux case" (~ inputA) + {true (~ thenA) + false (~ elseA)})) + (` ("lux case" (~ inputA) + {false (~ elseA) + true (~ thenA)})))]] + (test "Can detect and reify simple 'if' expressions." + (|> (expressionS;synthesize ifA) + (case> (^ [_ (#;Form (list [_ (#;Text "lux if")] inputS thenS elseS))]) + (and (corresponds? inputA inputS) + (corresponds? thenA thenS) + (corresponds? elseA elseS)) + + _ + false)))))) diff --git a/new-luxc/test/test/luxc/lang/synthesis/common.lux b/new-luxc/test/test/luxc/lang/synthesis/common.lux new file mode 100644 index 000000000..a74c64402 --- /dev/null +++ b/new-luxc/test/test/luxc/lang/synthesis/common.lux @@ -0,0 +1,37 @@ +(;module: + lux + (lux (data [bool "bool/" Eq] + [text "text/" Eq]) + (meta [code]) + ["r" math/random "r/" Monad]) + (luxc (lang ["la" analysis] + ["ls" synthesis]))) + +(def: #export gen-primitive + (r;Random la;Analysis) + (r;either (r;either (r;either (r/wrap (' [])) + (r/map code;bool r;bool)) + (r;either (r/map code;nat r;nat) + (r/map code;int r;int))) + (r;either (r;either (r/map code;deg r;deg) + (r/map code;frac r;frac)) + (r/map code;text (r;text +5))))) + +(def: #export (corresponds? analysis synthesis) + (-> la;Analysis ls;Synthesis Bool) + (case [analysis synthesis] + (^ [(^code []) (^code [])]) + true + + (^template [ ] + [[_ ( valueA)] [_ ( valueS)]] + ( valueA valueS)) + ([#;Bool bool/=] + [#;Nat n.=] + [#;Int i.=] + [#;Deg d.=] + [#;Frac f.=] + [#;Text text/=]) + + _ + false)) diff --git a/new-luxc/test/test/luxc/lang/synthesis/function.lux b/new-luxc/test/test/luxc/lang/synthesis/function.lux new file mode 100644 index 000000000..f364536cb --- /dev/null +++ b/new-luxc/test/test/luxc/lang/synthesis/function.lux @@ -0,0 +1,150 @@ +(;module: + lux + (lux [io] + (control [monad #+ do] + pipe) + (data [product] + [maybe] + [number] + text/format + (coll [list "list/" Functor Fold] + [dict #+ Dict] + [set])) + (meta [code]) + ["r" math/random "r/" Monad] + test) + (luxc (lang ["la" analysis] + ["ls" synthesis] + (synthesis [";S" expression]) + [";L" variable #+ Variable])) + (.. common)) + +(def: gen-function//constant + (r;Random [Nat la;Analysis la;Analysis]) + (r;rec + (function [gen-function//constant] + (do r;Monad + [function? r;bool] + (if function? + (do @ + [[num-args outputA subA] gen-function//constant] + (wrap [(n.inc num-args) + outputA + (` ("lux function" [] (~ subA)))])) + (do @ + [outputA gen-primitive] + (wrap [+0 outputA outputA]))))))) + +(def: (pick scope-size) + (-> Nat (r;Random Nat)) + (|> r;nat (:: r;Monad map (n.% scope-size)))) + +(def: gen-function//captured + (r;Random [Nat Int la;Analysis]) + (do r;Monad + [num-locals (|> r;nat (:: @ map (|>. (n.% +100) (n.max +10)))) + #let [indices (list;n.range +0 (n.dec num-locals)) + absolute-env (list/map variableL;local indices) + relative-env (list/map variableL;captured indices)] + [total-args prediction bodyA] (: (r;Random [Nat Int la;Analysis]) + (loop [num-args +1 + global-env relative-env] + (let [env-size (list;size global-env) + resolver (list/fold (function [[idx var] resolver] + (dict;put idx var resolver)) + (: (Dict Nat Int) + (dict;new number;Hash)) + (list;zip2 (list;n.range +0 (n.dec env-size)) + global-env))] + (do @ + [nest? r;bool] + (if nest? + (do @ + [num-picks (:: @ map (n.max +1) (pick (n.inc env-size))) + picks (|> (r;set number;Hash num-picks (pick env-size)) + (:: @ map set;to-list)) + [total-args prediction bodyA] (recur (n.inc num-args) + (list/map (function [pick] (maybe;assume (list;nth pick global-env))) + picks))] + (wrap [total-args prediction (` ("lux function" [(~@ (list/map (|>. variableL;captured code;int) picks))] + (~ bodyA)))])) + (do @ + [chosen (pick (list;size global-env))] + (wrap [num-args + (maybe;assume (dict;get chosen resolver)) + (la;var (variableL;captured chosen))])))))))] + (wrap [total-args prediction (` ("lux function" + [(~@ (list/map code;int absolute-env))] + (~ bodyA)))]) + )) + +(def: gen-function//local + (r;Random [Nat Int la;Analysis]) + (loop [num-args +0 + nest? true] + (if nest? + (do r;Monad + [nest?' r;bool + [total-args prediction bodyA] (recur (n.inc num-args) nest?')] + (wrap [total-args prediction (` ("lux function" [] (~ bodyA)))])) + (do r;Monad + [chosen (|> r;nat (:: @ map (|>. (n.% +100) (n.max +2))))] + (wrap [num-args + (|> chosen (n.+ (n.dec num-args)) nat-to-int) + (la;var (variableL;local chosen))]))))) + +(context: "Function definition." + (<| (times +100) + (do @ + [[args1 prediction1 function1] gen-function//constant + [args2 prediction2 function2] gen-function//captured + [args3 prediction3 function3] gen-function//local] + ($_ seq + (test "Nested functions will get folded together." + (|> (expressionS;synthesize function1) + (case> (^ [_ (#;Form (list [_ (#;Text "lux function")] [_ (#;Nat args)] [_ (#;Tuple captured)] output))]) + (and (n.= args1 args) + (corresponds? prediction1 output)) + + _ + (n.= +0 args1)))) + (test "Folded functions provide direct access to captured variables." + (|> (expressionS;synthesize function2) + (case> (^ [_ (#;Form (list [_ (#;Text "lux function")] [_ (#;Nat args)] [_ (#;Tuple captured)] + [_ (#;Form (list [_ (#;Int output)]))]))]) + (and (n.= args2 args) + (i.= prediction2 output)) + + _ + false))) + (test "Folded functions properly offset local variables." + (|> (expressionS;synthesize function3) + (case> (^ [_ (#;Form (list [_ (#;Text "lux function")] [_ (#;Nat args)] [_ (#;Tuple captured)] + [_ (#;Form (list [_ (#;Int output)]))]))]) + (and (n.= args3 args) + (i.= prediction3 output)) + + _ + false))) + )))) + +(context: "Function application." + (<| (times +100) + (do @ + [num-args (|> r;nat (:: @ map (|>. (n.% +10) (n.max +1)))) + funcA gen-primitive + argsA (r;list num-args gen-primitive)] + ($_ seq + (test "Can synthesize function application." + (|> (expressionS;synthesize (la;apply argsA funcA)) + (case> (^ [_ (#;Form (list& [_ (#;Text "lux call")] funcS argsS))]) + (and (corresponds? funcA funcS) + (list;every? (product;uncurry corresponds?) + (list;zip2 argsA argsS))) + + _ + false))) + (test "Function application on no arguments just synthesizes to the function itself." + (|> (expressionS;synthesize (la;apply (list) funcA)) + (corresponds? funcA))) + )))) diff --git a/new-luxc/test/test/luxc/lang/synthesis/loop.lux b/new-luxc/test/test/luxc/lang/synthesis/loop.lux new file mode 100644 index 000000000..90b303857 --- /dev/null +++ b/new-luxc/test/test/luxc/lang/synthesis/loop.lux @@ -0,0 +1,159 @@ +(;module: + lux + (lux [io] + (control [monad #+ do]) + (data [bool "bool/" Eq] + [number] + (coll [list "list/" Functor Fold] + ["s" set]) + text/format) + (meta [code]) + ["r" math/random "r/" Monad] + test) + (luxc (lang ["la" analysis] + ["ls" synthesis] + (synthesis [";S" expression] + [";S" loop]))) + (.. common)) + +(def: (does-recursion? arity exprS) + (-> ls;Arity ls;Synthesis Bool) + (loop [exprS exprS] + (case exprS + (^ [_ (#;Form (list [_ (#;Text "lux case")] inputS pathS))]) + (loop [pathS pathS] + (case pathS + (^ [_ (#;Form (list [_ (#;Text "lux case alt")] leftS rightS))]) + (or (recur leftS) + (recur rightS)) + + (^ [_ (#;Form (list [_ (#;Text "lux case seq")] leftS rightS))]) + (recur rightS) + + (^ [_ (#;Form (list [_ (#;Text "lux case exec")] bodyS))]) + (does-recursion? arity bodyS) + + _ + false)) + + (^ [_ (#;Form (list& [_ (#;Text "lux recur")] argsS))]) + (n.= arity (list;size argsS)) + + (^ [_ (#;Form (list [_ (#;Text "lux let")] register inputS bodyS))]) + (recur bodyS) + + (^ [_ (#;Form (list [_ (#;Text "lux if")] inputS thenS elseS))]) + (or (recur thenS) + (recur elseS)) + + _ + false + ))) + +(def: (gen-body arity output) + (-> Nat la;Analysis (r;Random la;Analysis)) + (r;either (r;either (r/wrap output) + (do r;Monad + [inputA (|> r;nat (:: @ map code;nat)) + num-cases (|> r;nat (:: @ map (|>. (n.% +10) (n.max +1)))) + tests (|> (r;set number;Hash num-cases r;nat) + (:: @ map (|>. s;to-list (list/map code;nat)))) + #let [bad-bodies (list;repeat num-cases (' []))] + good-body (gen-body arity output) + where-to-set (|> r;nat (:: @ map (n.% num-cases))) + #let [bodies (list;concat (list (list;take where-to-set bad-bodies) + (list good-body) + (list;drop (n.inc where-to-set) bad-bodies)))]] + (wrap (` ("lux case" (~ inputA) + (~ (code;record (list;zip2 tests bodies)))))))) + (r;either (do r;Monad + [valueS r;bool + output' (gen-body (n.inc arity) output)] + (wrap (` ("lux case" (~ (code;bool valueS)) + {("lux case bind" (~ (code;nat arity))) (~ output')})))) + (do r;Monad + [valueS r;bool + then|else r;bool + output' (gen-body arity output) + #let [thenA (if then|else output' (' [])) + elseA (if (not then|else) output' (' []))]] + (wrap (` ("lux case" (~ (code;bool valueS)) + {(~ (code;bool then|else)) (~ thenA) + (~ (code;bool (not then|else))) (~ elseA)}))))) + )) + +(def: (make-function arity body) + (-> ls;Arity la;Analysis la;Analysis) + (case arity + +0 body + _ (` ("lux function" [] (~ (make-function (n.dec arity) body)))))) + +(def: gen-recursion + (r;Random [Bool Nat la;Analysis]) + (do r;Monad + [arity (|> r;nat (:: @ map (|>. (n.% +10) (n.max +1)))) + recur? r;bool + outputS (if recur? + (wrap (la;apply (list;repeat arity (' [])) (la;var 0))) + (do @ + [plus-or-minus? r;bool + how-much (|> r;nat (:: @ map (|>. (n.% arity) (n.max +1)))) + #let [shift (if plus-or-minus? n.+ n.-)]] + (wrap (la;apply (list;repeat (shift how-much arity) (' [])) (la;var 0))))) + bodyS (gen-body arity outputS)] + (wrap [recur? arity (make-function arity bodyS)]))) + +(def: gen-loop + (r;Random [Bool Nat la;Analysis]) + (do r;Monad + [arity (|> r;nat (:: @ map (|>. (n.% +10) (n.max +1)))) + recur? r;bool + self-ref? r;bool + #let [selfA (la;var 0) + argA (if self-ref? selfA (' []))] + outputS (if recur? + (wrap (la;apply (list;repeat arity argA) selfA)) + (do @ + [plus-or-minus? r;bool + how-much (|> r;nat (:: @ map (|>. (n.% arity) (n.max +1)))) + #let [shift (if plus-or-minus? n.+ n.-)]] + (wrap (la;apply (list;repeat (shift how-much arity) (' [])) selfA)))) + bodyS (gen-body arity outputS)] + (wrap [(and recur? (not self-ref?)) + arity + (make-function arity bodyS)]))) + +(context: "Recursion." + (<| (times +100) + (do @ + [[prediction arity analysis] gen-recursion] + ($_ seq + (test "Can accurately identify (and then reify) tail recursion." + (case (expressionS;synthesize analysis) + (^ [_ (#;Form (list [_ (#;Text "lux function")] [_ (#;Nat _arity)] [_ (#;Tuple _env)] _body))]) + (|> _body + (does-recursion? arity) + (bool/= prediction) + (and (n.= arity _arity))) + + _ + false)))))) + +(context: "Loop." + (<| (times +100) + (do @ + [[prediction arity analysis] gen-recursion] + ($_ seq + (test "Can reify loops." + (case (expressionS;synthesize (la;apply (list;repeat arity (' [])) analysis)) + (^ [_ (#;Form (list [_ (#;Text "lux loop")] [_ (#;Nat in_register)] [_ (#;Tuple _inits)] _body))]) + (and (n.= arity (list;size _inits)) + (not (loopS;contains-self-reference? _body))) + + (^ [_ (#;Form (list& [_ (#;Text "lux call")] + [_ (#;Form (list [_ (#;Text "lux function")] _arity _env _bodyS))] + argsS))]) + (loopS;contains-self-reference? _bodyS) + + _ + false)))))) diff --git a/new-luxc/test/test/luxc/lang/synthesis/primitive.lux b/new-luxc/test/test/luxc/lang/synthesis/primitive.lux new file mode 100644 index 000000000..d907a4c04 --- /dev/null +++ b/new-luxc/test/test/luxc/lang/synthesis/primitive.lux @@ -0,0 +1,45 @@ +(;module: + lux + (lux [io] + (control [monad #+ do] + pipe) + (data text/format) + (meta [code]) + ["r" math/random] + test) + (luxc (lang ["la" analysis] + ["ls" synthesis] + (synthesis [";S" expression])))) + +(context: "Primitives" + (<| (times +100) + (do @ + [%bool% r;bool + %nat% r;nat + %int% r;int + %deg% r;deg + %frac% r;frac + %text% (r;text +5)] + (`` ($_ seq + (test (format "Can synthesize unit.") + (|> (expressionS;synthesize (' [])) + (case> (^code []) + true + + _ + false))) + (~~ (do-template [ ] + [(test (format "Can synthesize " ".") + (|> (expressionS;synthesize ( )) + (case> [_ ( value)] + (is value) + + _ + false)))] + + ["bool" code;bool #;Bool %bool%] + ["nat" code;nat #;Nat %nat%] + ["int" code;int #;Int %int%] + ["deg" code;deg #;Deg %deg%] + ["frac" code;frac #;Frac %frac%] + ["text" code;text #;Text %text%]))))))) diff --git a/new-luxc/test/test/luxc/lang/synthesis/procedure.lux b/new-luxc/test/test/luxc/lang/synthesis/procedure.lux new file mode 100644 index 000000000..2263a1616 --- /dev/null +++ b/new-luxc/test/test/luxc/lang/synthesis/procedure.lux @@ -0,0 +1,32 @@ +(;module: + lux + (lux [io] + (control [monad #+ do] + pipe) + (data [text "text/" Eq] + [product] + (coll [list])) + ["r" math/random "r/" Monad] + test) + (luxc (lang ["la" analysis] + ["ls" synthesis] + (synthesis [";S" expression]))) + (.. common)) + +(context: "Procedures" + (<| (times +100) + (do @ + [num-args (|> r;nat (:: @ map (n.% +10))) + nameA (r;text +5) + argsA (r;list num-args gen-primitive)] + ($_ seq + (test "Can synthesize procedure calls." + (|> (expressionS;synthesize (la;procedure nameA argsA)) + (case> (^ [_ (#;Form (list& [_ (#;Text procedure)] argsS))]) + (and (text/= nameA procedure) + (list;every? (product;uncurry corresponds?) + (list;zip2 argsA argsS))) + + _ + false))) + )))) diff --git a/new-luxc/test/test/luxc/lang/synthesis/structure.lux b/new-luxc/test/test/luxc/lang/synthesis/structure.lux new file mode 100644 index 000000000..eab568bbe --- /dev/null +++ b/new-luxc/test/test/luxc/lang/synthesis/structure.lux @@ -0,0 +1,49 @@ +(;module: + lux + (lux [io] + (control [monad #+ do] + pipe) + (data [bool "B/" Eq] + [product] + (coll [list])) + ["r" math/random "r/" Monad] + test) + (luxc (lang ["la" analysis] + ["ls" synthesis] + (synthesis [";S" expression]))) + (.. common)) + +(context: "Variants" + (<| (times +100) + (do @ + [size (|> r;nat (:: @ map (|>. (n.% +10) (n.max +2)))) + tagA (|> r;nat (:: @ map (n.% size))) + memberA gen-primitive] + ($_ seq + (test "Can synthesize variants." + (|> (expressionS;synthesize (la;sum tagA size +0 memberA)) + (case> (^ [_ (#;Form (list [_ (#;Nat tagS)] [_ (#;Bool last?S)] memberS))]) + (and (n.= tagA tagS) + (B/= (n.= (n.dec size) tagA) + last?S) + (corresponds? memberA memberS)) + + _ + false))) + )))) + +(context: "Tuples" + (<| (times +100) + (do @ + [size (|> r;nat (:: @ map (|>. (n.% +10) (n.max +2)))) + membersA (r;list size gen-primitive)] + ($_ seq + (test "Can synthesize tuple." + (|> (expressionS;synthesize (la;product membersA)) + (case> [_ (#;Tuple membersS)] + (and (n.= size (list;size membersS)) + (list;every? (product;uncurry corresponds?) (list;zip2 membersA membersS))) + + _ + false))) + )))) diff --git a/new-luxc/test/test/luxc/synthesizer/case/special.lux b/new-luxc/test/test/luxc/synthesizer/case/special.lux deleted file mode 100644 index 30e64fc77..000000000 --- a/new-luxc/test/test/luxc/synthesizer/case/special.lux +++ /dev/null @@ -1,68 +0,0 @@ -(;module: - lux - (lux [io] - (control [monad #+ do] - pipe) - (meta [code]) - ["r" math/random "r/" Monad] - test) - (luxc (lang ["la" analysis] - ["ls" synthesis] - [";L" variable #+ Variable]) - [synthesizer]) - (../.. common)) - -(context: "Dummy variables." - (<| (times +100) - (do @ - [maskedA gen-primitive - temp (|> r;nat (:: @ map (n.% +100))) - #let [maskA (` ("lux case" (~ maskedA) - {("lux case bind" (~ (code;nat temp))) - (~ (la;var (variableL;local temp)))}))]] - (test "Dummy variables created to mask expressions get eliminated during synthesis." - (|> (synthesizer;synthesize maskA) - (corresponds? maskedA)))))) - -(context: "Let expressions." - (<| (times +100) - (do @ - [registerA r;nat - inputA gen-primitive - outputA gen-primitive - #let [letA (` ("lux case" (~ inputA) - {("lux case bind" (~ (code;nat registerA))) - (~ outputA)}))]] - (test "Can detect and reify simple 'let' expressions." - (|> (synthesizer;synthesize letA) - (case> (^ [_ (#;Form (list [_ (#;Text "lux let")] [_ (#;Nat registerS)] inputS outputS))]) - (and (n.= registerA registerS) - (corresponds? inputA inputS) - (corresponds? outputA outputS)) - - _ - false)))))) - -(context: "If expressions." - (<| (times +100) - (do @ - [then|else r;bool - inputA gen-primitive - thenA gen-primitive - elseA gen-primitive - #let [ifA (if then|else - (` ("lux case" (~ inputA) - {true (~ thenA) - false (~ elseA)})) - (` ("lux case" (~ inputA) - {false (~ elseA) - true (~ thenA)})))]] - (test "Can detect and reify simple 'if' expressions." - (|> (synthesizer;synthesize ifA) - (case> (^ [_ (#;Form (list [_ (#;Text "lux if")] inputS thenS elseS))]) - (and (corresponds? inputA inputS) - (corresponds? thenA thenS) - (corresponds? elseA elseS)) - - _ - false)))))) diff --git a/new-luxc/test/test/luxc/synthesizer/common.lux b/new-luxc/test/test/luxc/synthesizer/common.lux deleted file mode 100644 index a74c64402..000000000 --- a/new-luxc/test/test/luxc/synthesizer/common.lux +++ /dev/null @@ -1,37 +0,0 @@ -(;module: - lux - (lux (data [bool "bool/" Eq] - [text "text/" Eq]) - (meta [code]) - ["r" math/random "r/" Monad]) - (luxc (lang ["la" analysis] - ["ls" synthesis]))) - -(def: #export gen-primitive - (r;Random la;Analysis) - (r;either (r;either (r;either (r/wrap (' [])) - (r/map code;bool r;bool)) - (r;either (r/map code;nat r;nat) - (r/map code;int r;int))) - (r;either (r;either (r/map code;deg r;deg) - (r/map code;frac r;frac)) - (r/map code;text (r;text +5))))) - -(def: #export (corresponds? analysis synthesis) - (-> la;Analysis ls;Synthesis Bool) - (case [analysis synthesis] - (^ [(^code []) (^code [])]) - true - - (^template [ ] - [[_ ( valueA)] [_ ( valueS)]] - ( valueA valueS)) - ([#;Bool bool/=] - [#;Nat n.=] - [#;Int i.=] - [#;Deg d.=] - [#;Frac f.=] - [#;Text text/=]) - - _ - false)) diff --git a/new-luxc/test/test/luxc/synthesizer/function.lux b/new-luxc/test/test/luxc/synthesizer/function.lux deleted file mode 100644 index cab0da847..000000000 --- a/new-luxc/test/test/luxc/synthesizer/function.lux +++ /dev/null @@ -1,150 +0,0 @@ -(;module: - lux - (lux [io] - (control [monad #+ do] - pipe) - (data [product] - [maybe] - [number] - text/format - (coll [list "list/" Functor Fold] - [dict #+ Dict] - [set])) - (meta [code]) - ["r" math/random "r/" Monad] - test) - (luxc (lang ["la" analysis] - ["ls" synthesis] - [";L" variable #+ Variable]) - [synthesizer]) - (.. common)) - -(def: gen-function//constant - (r;Random [Nat la;Analysis la;Analysis]) - (r;rec - (function [gen-function//constant] - (do r;Monad - [function? r;bool] - (if function? - (do @ - [[num-args outputA subA] gen-function//constant] - (wrap [(n.inc num-args) - outputA - (` ("lux function" [] (~ subA)))])) - (do @ - [outputA gen-primitive] - (wrap [+0 outputA outputA]))))))) - -(def: (pick scope-size) - (-> Nat (r;Random Nat)) - (|> r;nat (:: r;Monad map (n.% scope-size)))) - -(def: gen-function//captured - (r;Random [Nat Int la;Analysis]) - (do r;Monad - [num-locals (|> r;nat (:: @ map (|>. (n.% +100) (n.max +10)))) - #let [indices (list;n.range +0 (n.dec num-locals)) - absolute-env (list/map variableL;local indices) - relative-env (list/map variableL;captured indices)] - [total-args prediction bodyA] (: (r;Random [Nat Int la;Analysis]) - (loop [num-args +1 - global-env relative-env] - (let [env-size (list;size global-env) - resolver (list/fold (function [[idx var] resolver] - (dict;put idx var resolver)) - (: (Dict Nat Int) - (dict;new number;Hash)) - (list;zip2 (list;n.range +0 (n.dec env-size)) - global-env))] - (do @ - [nest? r;bool] - (if nest? - (do @ - [num-picks (:: @ map (n.max +1) (pick (n.inc env-size))) - picks (|> (r;set number;Hash num-picks (pick env-size)) - (:: @ map set;to-list)) - [total-args prediction bodyA] (recur (n.inc num-args) - (list/map (function [pick] (maybe;assume (list;nth pick global-env))) - picks))] - (wrap [total-args prediction (` ("lux function" [(~@ (list/map (|>. variableL;captured code;int) picks))] - (~ bodyA)))])) - (do @ - [chosen (pick (list;size global-env))] - (wrap [num-args - (maybe;assume (dict;get chosen resolver)) - (la;var (variableL;captured chosen))])))))))] - (wrap [total-args prediction (` ("lux function" - [(~@ (list/map code;int absolute-env))] - (~ bodyA)))]) - )) - -(def: gen-function//local - (r;Random [Nat Int la;Analysis]) - (loop [num-args +0 - nest? true] - (if nest? - (do r;Monad - [nest?' r;bool - [total-args prediction bodyA] (recur (n.inc num-args) nest?')] - (wrap [total-args prediction (` ("lux function" [] (~ bodyA)))])) - (do r;Monad - [chosen (|> r;nat (:: @ map (|>. (n.% +100) (n.max +2))))] - (wrap [num-args - (|> chosen (n.+ (n.dec num-args)) nat-to-int) - (la;var (variableL;local chosen))]))))) - -(context: "Function definition." - (<| (times +100) - (do @ - [[args1 prediction1 function1] gen-function//constant - [args2 prediction2 function2] gen-function//captured - [args3 prediction3 function3] gen-function//local] - ($_ seq - (test "Nested functions will get folded together." - (|> (synthesizer;synthesize function1) - (case> (^ [_ (#;Form (list [_ (#;Text "lux function")] [_ (#;Nat args)] [_ (#;Tuple captured)] output))]) - (and (n.= args1 args) - (corresponds? prediction1 output)) - - _ - (n.= +0 args1)))) - (test "Folded functions provide direct access to captured variables." - (|> (synthesizer;synthesize function2) - (case> (^ [_ (#;Form (list [_ (#;Text "lux function")] [_ (#;Nat args)] [_ (#;Tuple captured)] - [_ (#;Form (list [_ (#;Int output)]))]))]) - (and (n.= args2 args) - (i.= prediction2 output)) - - _ - false))) - (test "Folded functions properly offset local variables." - (|> (synthesizer;synthesize function3) - (case> (^ [_ (#;Form (list [_ (#;Text "lux function")] [_ (#;Nat args)] [_ (#;Tuple captured)] - [_ (#;Form (list [_ (#;Int output)]))]))]) - (and (n.= args3 args) - (i.= prediction3 output)) - - _ - false))) - )))) - -(context: "Function application." - (<| (times +100) - (do @ - [num-args (|> r;nat (:: @ map (|>. (n.% +10) (n.max +1)))) - funcA gen-primitive - argsA (r;list num-args gen-primitive)] - ($_ seq - (test "Can synthesize function application." - (|> (synthesizer;synthesize (la;apply argsA funcA)) - (case> (^ [_ (#;Form (list& [_ (#;Text "lux call")] funcS argsS))]) - (and (corresponds? funcA funcS) - (list;every? (product;uncurry corresponds?) - (list;zip2 argsA argsS))) - - _ - false))) - (test "Function application on no arguments just synthesizes to the function itself." - (|> (synthesizer;synthesize (la;apply (list) funcA)) - (corresponds? funcA))) - )))) diff --git a/new-luxc/test/test/luxc/synthesizer/loop.lux b/new-luxc/test/test/luxc/synthesizer/loop.lux deleted file mode 100644 index fd8c95ce1..000000000 --- a/new-luxc/test/test/luxc/synthesizer/loop.lux +++ /dev/null @@ -1,159 +0,0 @@ -(;module: - lux - (lux [io] - (control [monad #+ do]) - (data [bool "bool/" Eq] - [number] - (coll [list "list/" Functor Fold] - ["s" set]) - text/format) - (meta [code]) - ["r" math/random "r/" Monad] - test) - (luxc (lang ["la" analysis] - ["ls" synthesis]) - [synthesizer] - (synthesizer ["&&;" loop])) - (.. common)) - -(def: (does-recursion? arity exprS) - (-> ls;Arity ls;Synthesis Bool) - (loop [exprS exprS] - (case exprS - (^ [_ (#;Form (list [_ (#;Text "lux case")] inputS pathS))]) - (loop [pathS pathS] - (case pathS - (^ [_ (#;Form (list [_ (#;Text "lux case alt")] leftS rightS))]) - (or (recur leftS) - (recur rightS)) - - (^ [_ (#;Form (list [_ (#;Text "lux case seq")] leftS rightS))]) - (recur rightS) - - (^ [_ (#;Form (list [_ (#;Text "lux case exec")] bodyS))]) - (does-recursion? arity bodyS) - - _ - false)) - - (^ [_ (#;Form (list& [_ (#;Text "lux recur")] argsS))]) - (n.= arity (list;size argsS)) - - (^ [_ (#;Form (list [_ (#;Text "lux let")] register inputS bodyS))]) - (recur bodyS) - - (^ [_ (#;Form (list [_ (#;Text "lux if")] inputS thenS elseS))]) - (or (recur thenS) - (recur elseS)) - - _ - false - ))) - -(def: (gen-body arity output) - (-> Nat la;Analysis (r;Random la;Analysis)) - (r;either (r;either (r/wrap output) - (do r;Monad - [inputA (|> r;nat (:: @ map code;nat)) - num-cases (|> r;nat (:: @ map (|>. (n.% +10) (n.max +1)))) - tests (|> (r;set number;Hash num-cases r;nat) - (:: @ map (|>. s;to-list (list/map code;nat)))) - #let [bad-bodies (list;repeat num-cases (' []))] - good-body (gen-body arity output) - where-to-set (|> r;nat (:: @ map (n.% num-cases))) - #let [bodies (list;concat (list (list;take where-to-set bad-bodies) - (list good-body) - (list;drop (n.inc where-to-set) bad-bodies)))]] - (wrap (` ("lux case" (~ inputA) - (~ (code;record (list;zip2 tests bodies)))))))) - (r;either (do r;Monad - [valueS r;bool - output' (gen-body (n.inc arity) output)] - (wrap (` ("lux case" (~ (code;bool valueS)) - {("lux case bind" (~ (code;nat arity))) (~ output')})))) - (do r;Monad - [valueS r;bool - then|else r;bool - output' (gen-body arity output) - #let [thenA (if then|else output' (' [])) - elseA (if (not then|else) output' (' []))]] - (wrap (` ("lux case" (~ (code;bool valueS)) - {(~ (code;bool then|else)) (~ thenA) - (~ (code;bool (not then|else))) (~ elseA)}))))) - )) - -(def: (make-function arity body) - (-> ls;Arity la;Analysis la;Analysis) - (case arity - +0 body - _ (` ("lux function" [] (~ (make-function (n.dec arity) body)))))) - -(def: gen-recursion - (r;Random [Bool Nat la;Analysis]) - (do r;Monad - [arity (|> r;nat (:: @ map (|>. (n.% +10) (n.max +1)))) - recur? r;bool - outputS (if recur? - (wrap (la;apply (list;repeat arity (' [])) (la;var 0))) - (do @ - [plus-or-minus? r;bool - how-much (|> r;nat (:: @ map (|>. (n.% arity) (n.max +1)))) - #let [shift (if plus-or-minus? n.+ n.-)]] - (wrap (la;apply (list;repeat (shift how-much arity) (' [])) (la;var 0))))) - bodyS (gen-body arity outputS)] - (wrap [recur? arity (make-function arity bodyS)]))) - -(def: gen-loop - (r;Random [Bool Nat la;Analysis]) - (do r;Monad - [arity (|> r;nat (:: @ map (|>. (n.% +10) (n.max +1)))) - recur? r;bool - self-ref? r;bool - #let [selfA (la;var 0) - argA (if self-ref? selfA (' []))] - outputS (if recur? - (wrap (la;apply (list;repeat arity argA) selfA)) - (do @ - [plus-or-minus? r;bool - how-much (|> r;nat (:: @ map (|>. (n.% arity) (n.max +1)))) - #let [shift (if plus-or-minus? n.+ n.-)]] - (wrap (la;apply (list;repeat (shift how-much arity) (' [])) selfA)))) - bodyS (gen-body arity outputS)] - (wrap [(and recur? (not self-ref?)) - arity - (make-function arity bodyS)]))) - -(context: "Recursion." - (<| (times +100) - (do @ - [[prediction arity analysis] gen-recursion] - ($_ seq - (test "Can accurately identify (and then reify) tail recursion." - (case (synthesizer;synthesize analysis) - (^ [_ (#;Form (list [_ (#;Text "lux function")] [_ (#;Nat _arity)] [_ (#;Tuple _env)] _body))]) - (|> _body - (does-recursion? arity) - (bool/= prediction) - (and (n.= arity _arity))) - - _ - false)))))) - -(context: "Loop." - (<| (times +100) - (do @ - [[prediction arity analysis] gen-recursion] - ($_ seq - (test "Can reify loops." - (case (synthesizer;synthesize (la;apply (list;repeat arity (' [])) analysis)) - (^ [_ (#;Form (list [_ (#;Text "lux loop")] [_ (#;Nat in_register)] [_ (#;Tuple _inits)] _body))]) - (and (n.= arity (list;size _inits)) - (not (&&loop;contains-self-reference? _body))) - - (^ [_ (#;Form (list& [_ (#;Text "lux call")] - [_ (#;Form (list [_ (#;Text "lux function")] _arity _env _bodyS))] - argsS))]) - (&&loop;contains-self-reference? _bodyS) - - _ - false)))))) diff --git a/new-luxc/test/test/luxc/synthesizer/primitive.lux b/new-luxc/test/test/luxc/synthesizer/primitive.lux deleted file mode 100644 index 2a1490193..000000000 --- a/new-luxc/test/test/luxc/synthesizer/primitive.lux +++ /dev/null @@ -1,45 +0,0 @@ -(;module: - lux - (lux [io] - (control [monad #+ do] - pipe) - (data text/format) - (meta [code]) - ["r" math/random] - test) - (luxc (lang ["la" analysis] - ["ls" synthesis]) - [synthesizer])) - -(context: "Primitives" - (<| (times +100) - (do @ - [%bool% r;bool - %nat% r;nat - %int% r;int - %deg% r;deg - %frac% r;frac - %text% (r;text +5)] - (`` ($_ seq - (test (format "Can synthesize unit.") - (|> (synthesizer;synthesize (' [])) - (case> (^code []) - true - - _ - false))) - (~~ (do-template [ ] - [(test (format "Can synthesize " ".") - (|> (synthesizer;synthesize ( )) - (case> [_ ( value)] - (is value) - - _ - false)))] - - ["bool" code;bool #;Bool %bool%] - ["nat" code;nat #;Nat %nat%] - ["int" code;int #;Int %int%] - ["deg" code;deg #;Deg %deg%] - ["frac" code;frac #;Frac %frac%] - ["text" code;text #;Text %text%]))))))) diff --git a/new-luxc/test/test/luxc/synthesizer/procedure.lux b/new-luxc/test/test/luxc/synthesizer/procedure.lux deleted file mode 100644 index c659c5e34..000000000 --- a/new-luxc/test/test/luxc/synthesizer/procedure.lux +++ /dev/null @@ -1,32 +0,0 @@ -(;module: - lux - (lux [io] - (control [monad #+ do] - pipe) - (data [text "text/" Eq] - [product] - (coll [list])) - ["r" math/random "r/" Monad] - test) - (luxc (lang ["la" analysis] - ["ls" synthesis]) - [synthesizer]) - (.. common)) - -(context: "Procedures" - (<| (times +100) - (do @ - [num-args (|> r;nat (:: @ map (n.% +10))) - nameA (r;text +5) - argsA (r;list num-args gen-primitive)] - ($_ seq - (test "Can synthesize procedure calls." - (|> (synthesizer;synthesize (la;procedure nameA argsA)) - (case> (^ [_ (#;Form (list& [_ (#;Text procedure)] argsS))]) - (and (text/= nameA procedure) - (list;every? (product;uncurry corresponds?) - (list;zip2 argsA argsS))) - - _ - false))) - )))) diff --git a/new-luxc/test/test/luxc/synthesizer/structure.lux b/new-luxc/test/test/luxc/synthesizer/structure.lux deleted file mode 100644 index 517f087d1..000000000 --- a/new-luxc/test/test/luxc/synthesizer/structure.lux +++ /dev/null @@ -1,49 +0,0 @@ -(;module: - lux - (lux [io] - (control [monad #+ do] - pipe) - (data [bool "B/" Eq] - [product] - (coll [list])) - ["r" math/random "r/" Monad] - test) - (luxc (lang ["la" analysis] - ["ls" synthesis]) - [synthesizer]) - (.. common)) - -(context: "Variants" - (<| (times +100) - (do @ - [size (|> r;nat (:: @ map (|>. (n.% +10) (n.max +2)))) - tagA (|> r;nat (:: @ map (n.% size))) - memberA gen-primitive] - ($_ seq - (test "Can synthesize variants." - (|> (synthesizer;synthesize (la;sum tagA size +0 memberA)) - (case> (^ [_ (#;Form (list [_ (#;Nat tagS)] [_ (#;Bool last?S)] memberS))]) - (and (n.= tagA tagS) - (B/= (n.= (n.dec size) tagA) - last?S) - (corresponds? memberA memberS)) - - _ - false))) - )))) - -(context: "Tuples" - (<| (times +100) - (do @ - [size (|> r;nat (:: @ map (|>. (n.% +10) (n.max +2)))) - membersA (r;list size gen-primitive)] - ($_ seq - (test "Can synthesize tuple." - (|> (synthesizer;synthesize (la;product membersA)) - (case> [_ (#;Tuple membersS)] - (and (n.= size (list;size membersS)) - (list;every? (product;uncurry corresponds?) (list;zip2 membersA membersS))) - - _ - false))) - )))) diff --git a/new-luxc/test/tests.lux b/new-luxc/test/tests.lux index f96d5bdfc..5ec79d1e5 100644 --- a/new-luxc/test/tests.lux +++ b/new-luxc/test/tests.lux @@ -13,13 +13,13 @@ ["_;A" function] ["_;A" type] (procedure ["_;A" common] - ["_;A" host]))) - (synthesizer ["_;S" primitive] - ["_;S" structure] - (case ["_;S" special]) - ["_;S" function] - ["_;S" procedure] - ["_;S" loop]) + ["_;A" host])) + (synthesis ["_;S" primitive] + ["_;S" structure] + (case ["_;S" special]) + ["_;S" function] + ["_;S" procedure] + ["_;S" loop])) (generator ["_;G" primitive] ["_;G" structure] ["_;G" case] -- cgit v1.2.3