190 likes | 332 Views
Normalisation by Evaluation for SML.NET. Sam Lindley University of Edinburgh. Outline of the talk. SML.NET NBE for ml Implementing NBE for SML.NET Other normalisation algorithms Benchmarks Conclusions and Future work. Goals.
E N D
Normalisation by Evaluation for SML.NET Sam Lindley University of Edinburgh
Outline of the talk • SML.NET • NBE for ml • Implementing NBE for SML.NET • Other normalisation algorithms • Benchmarks • Conclusions and Future work
Goals • Use SML.NET frontend to generate large terms in order to evaluate the efficiency of NBE in a non-trivial setting • Apply NBE in the actual compiler
SML.NET • A whole program compiler • Uses the monadic intermediate language MIL • Does lots of rewriting • Rewriting is currently a bottleneck
SML.NET compilation ML Frontend MIL Rewriting Optimised MIL Backend .NET bytecode
Rewriting phases val opts = ["presimp ", "simp", "funscope", "arity", "simp", "eq", "simp", "mono", "simp", "units", "simp", "arity", "tailrec", "simp", "inline", "funscope", "simp", "floathoist", "case", "lastsimp"]
Computational metalanguage (ml) Types , := o | ! | T Terms (ml) M,N := c | x | x.M | M@N | hM,Ni | 1(M) | 2(M) | [M] | let x = M in N
ml rewrites (-rules) (x.M)@N Ã M{N/x} i(hM1,M2i) Ã Mi let x = [M] in N Ã N{M/x} (commuting-conversions) let y = (let x = M in N) in P Ã let x = M in let y = N in P (-expansions) M Ãx.M@x M Ãh1(M),2(M)i M Ã let x = M in [x]
Residualising semantics for ml « o ¬ = ml « ! ¬ = « ¬!« ¬ « T ¬ = (« ¬!ml) !ml « x ¬ = (x) « x.M ¬ = v.« M ¬ [x v] « M@N ¬ = « M ¬« N ¬ « [M] ¬ k = k « M ¬ « let x = M in N ¬ k= « M ¬(v.« N ¬[x v]k)
NBE for ml # : «¬!ml (‘reify’) #o e = e #! f = x . # (f ("x)) (x “fresh”) #T c = c (v . [#v]) ": ml!«¬ (‘reflect’) "o e = e "! e = v. "(e@(#v)) "T e = k . let x = e in k ("x) (x “fresh”) norm e = #« e ¬ «c¬ = " c
Some variations • Suppress expansions • -reduction instead of expansion • shift / reset instead of local continuations • State monad instead of continuations monad (either local or global)
Changes from ml to MIL • Church instead of Curry-typing • Distinction between values and computations • Arity raising • Debugging info • Effect annotations • Extra term constructors: polymorphism, sums, recursive types, exceptions, references, .NET interoperability, etc.
Adapting NBE for MIL (1) • Ignore ‘unknown’ subterms • Map unknown values to * and unknown computations to [*] • Define « * ¬ v = « * ¬, « 1(*) ¬ = « * ¬, etc. • Potentially wipes out a lot of the source term
Adapting NBE for MIL (2) • Treat unknown term constructors as uninterpreted constants • Reflect at the appropriate type • Necessary to include types in the semantics for -expansion
Spectrum of normalisation algorithms • Naïve algorithm • Naïve algorithm + environments • Go via wnf using environments + closures • NBE
Benchmarks (ms) unknown *
Benchmarks (ms) unknown uninterpreted constant
Future work / work in progress • Polymorphism • Evaluate different approaches to sums and recursive types • Exceptions • Effects • Target MIL instead of MIL • Incorporate NBE into the actual compiler
Conclusions • NBE is fast • Carefully optimised normalisers can sometimes be even faster (but start to look very much like NBE) • NBE is a useful implementation tool • NBE algorithms can be derived by program translation