whnf (f :@ a) = case whnf f of
- Closure f b -> whnf (instantiate1 a $ (b >>>= f ))
- --- heres the lambda one again, shouldn't happen though!
+ whnf (instantiate1 a $ (b >>>= f ))
+ --- heres the lambda one again,
+ ---shouldn't happen though!
Lambda b -> whnf (instantiate1 a b)
+ toplevelWHNF e = whnf $! ( e >>= id )
+ --- closes the toplevel environment, with closures!
* lets make our evaluator have its own little stack of contexts, have
every function only appear in tail position.
+* heres an idea : explicit stack
+ SMach (Exp a -> [StackMachine a] -> Exp a )
+# Heres its Eval (and apply)
+toplevelWHNF e = stackWHNF (e >>= id ) 
+stackApply e (SMach a : as ) = a e as
+stackWHNF:: Exp a -> [StackMachine a] -> Exp a
+stackWHNF (f @: a) ls = stackWHNF f (SMach ( \e ->
+ stackWHNF (instantiate1 a $ (b >>>= f ) )
+ f' -> stackApply (f' :@ a) ls ) : ls )
+stackWHNF e ls = stackApply e ls
+* thats what happs when you dont do Continuation Passing Style Transformation
+* because we do need a stack somewhere
+* whats the rough idea for CPS?
+# CPS transform in a page (an abuse of a beautiful topic)
+toCPStoplevel e = toCPS e TOP
+toCPS (e1 e2) k -> toCPS e1 \v1 -> toCPS e2 \v2-> v1 v2 k
+toCPS (lam x-> e) k = k (lam x k -> toCPS e k )
+toCPS (variable) k -> k v
+* when we don't augment K
+# Why Did I show you this?
+* Continuations makes stack Allocation explicit as a programmatic construct you can optimize
+* Closures tell us what values to persist in the heap / stack
+* the Closure part of a continuation tells us what values to save on the stack
+# Why did i tell you this?
+* CMM (C minus minus), the last IR before LLMV / Native code generation
+is CPSd, and Closure Converted
+* CMM is kinda C without a type system, or assembly with better syntax
+ - theres a C Minus Minus language too, but GHC has its own version
+# How do funcalls work at the CMM level?
+* GHC has its own calling convention to support tail calls efficiently.
+* Let me show you the x86_64 calling convention for ghc 7.6
+* Has 6 registers reserved for Words,
+* 3 registersfor Base , heap , stack pointers, plus stack limit pointer
+* 2 SIMD registers for Doubles
+* 4 SIMD registers for Floats
+* any more arguments are put on the Stack in order
+# What are those fixed registers?
+REG_R1-R6 rbx r14 rsi rdi r8 r9
+# LLVM has GHC calling convention included
+def CC_X86_64_GHC : CallingConv<[
+ // Promote i8/i16/i32 arguments to i64.
+ CCIfType<[i8, i16, i32], CCPromoteToType<i64>>,
+ // Pass in STG registers: Base, Sp, Hp, R1,
+ R2, R3, R4, R5, R6, SpLim
+ CCAssignToReg<[R13, RBP, R12, RBX,
+ R14, RSI, RDI, R8, R9, R15]>>,
+ // Pass in STG registers: F1, F2, F3, F4, D1, D2
+ CCIfType<[f32, f64, v16i8, v8i16, v4i32,
+ CCAssignToReg<[XMM1, XMM2, XMM3,
+#Why on earth would you use CMM instead of C or haskell?
+* Maybe you want to have multiple values AND interact with the RTS
+ - This is how many of the concurrency primops are implemented
+* You like writing assembly
+How does CMM compare with Haskell code, C using the FFI's,
+and C modified to use the GHC calling convention
+* I'll add these later :)