nano: parsing and eval · eval - recursive let let x = e1 in e2 if e1 is not a function, how do we...
TRANSCRIPT
![Page 1: Nano: Parsing and Eval · Eval - Recursive let let x = e1 in e2 If e1 is not a function, how do we implement eval? Eval - Recursive let let x = e1 in e2 let y = 3 in (1 + y) ... sum](https://reader036.vdocument.in/reader036/viewer/2022071100/5fd931ec09f301358739fc2f/html5/thumbnails/1.jpg)
Nano: Parsing and EvalCSE 1302.25.19
![Page 2: Nano: Parsing and Eval · Eval - Recursive let let x = e1 in e2 If e1 is not a function, how do we implement eval? Eval - Recursive let let x = e1 in e2 let y = 3 in (1 + y) ... sum](https://reader036.vdocument.in/reader036/viewer/2022071100/5fd931ec09f301358739fc2f/html5/thumbnails/2.jpg)
Parsing - A simple languageAExp ::= Int | String | Plus AExp AExp | Minus AExp AExp | Mul AExp AExp | Div AExp AExp
![Page 3: Nano: Parsing and Eval · Eval - Recursive let let x = e1 in e2 If e1 is not a function, how do we implement eval? Eval - Recursive let let x = e1 in e2 let y = 3 in (1 + y) ... sum](https://reader036.vdocument.in/reader036/viewer/2022071100/5fd931ec09f301358739fc2f/html5/thumbnails/3.jpg)
Goal: String -> AST“12 + 2” -> Plus 12 2
“1 + (2 / “a”)” -> Plus 1 (Div 2 “a”)
“(3 / 4) * (2 / 5)” -> Times (Div 3 4) (Div 2 5)
![Page 4: Nano: Parsing and Eval · Eval - Recursive let let x = e1 in e2 If e1 is not a function, how do we implement eval? Eval - Recursive let let x = e1 in e2 let y = 3 in (1 + y) ... sum](https://reader036.vdocument.in/reader036/viewer/2022071100/5fd931ec09f301358739fc2f/html5/thumbnails/4.jpg)
String -> LEXER -> [Token] -> PARSER -> AST
Strategy
![Page 5: Nano: Parsing and Eval · Eval - Recursive let let x = e1 in e2 If e1 is not a function, how do we implement eval? Eval - Recursive let let x = e1 in e2 let y = 3 in (1 + y) ... sum](https://reader036.vdocument.in/reader036/viewer/2022071100/5fd931ec09f301358739fc2f/html5/thumbnails/5.jpg)
String -> LEXER -> [Token] -> PARSER -> AST
Alex: Generates a Lexer in Haskell from .x file
Happy: Generates a parser in Haskell from .y file
Strategy
![Page 6: Nano: Parsing and Eval · Eval - Recursive let let x = e1 in e2 If e1 is not a function, how do we implement eval? Eval - Recursive let let x = e1 in e2 let y = 3 in (1 + y) ... sum](https://reader036.vdocument.in/reader036/viewer/2022071100/5fd931ec09f301358739fc2f/html5/thumbnails/6.jpg)
Lexer :: String -> [Token]Convert list of Chars to a high-level representation of same information
[‘5’,’0’,’0’,’ ‘,’+’,’ ‘,’1’,’2’] -> [500, Plus, 12]
[‘1’,’ ‘,’+’,’ ‘,’(‘,’3’,’ ‘,’*’,’ ‘,’2’,’)’] -> [1, Plus, LParen, 3, Times, 2, RParen]
![Page 7: Nano: Parsing and Eval · Eval - Recursive let let x = e1 in e2 If e1 is not a function, how do we implement eval? Eval - Recursive let let x = e1 in e2 let y = 3 in (1 + y) ... sum](https://reader036.vdocument.in/reader036/viewer/2022071100/5fd931ec09f301358739fc2f/html5/thumbnails/7.jpg)
Parser :: [Token] -> AST[500,Plus,12] -> Plus 500 12
[1,Plus,LParen,3,Times,2,RParen] -> Plus 1 (Times 3 2)
![Page 8: Nano: Parsing and Eval · Eval - Recursive let let x = e1 in e2 If e1 is not a function, how do we implement eval? Eval - Recursive let let x = e1 in e2 let y = 3 in (1 + y) ... sum](https://reader036.vdocument.in/reader036/viewer/2022071100/5fd931ec09f301358739fc2f/html5/thumbnails/8.jpg)
Writing a LexerNeed to define mappings from sequences of characters to tokens
data Token = NUM AlexPosn Int | ID AlexPosn String | PLUS AlexPosn
….
![Page 9: Nano: Parsing and Eval · Eval - Recursive let let x = e1 in e2 If e1 is not a function, how do we implement eval? Eval - Recursive let let x = e1 in e2 let y = 3 in (1 + y) ... sum](https://reader036.vdocument.in/reader036/viewer/2022071100/5fd931ec09f301358739fc2f/html5/thumbnails/9.jpg)
Writing a Lexerdata Token = NUM AlexPosn Int | ID AlexPosn String | PLUS AlexPosn
….
Define rules of the form | <regexp> {haskell-expr}
When <regexp> is matched, we evaluate {haskell-expr} to generate a token
![Page 10: Nano: Parsing and Eval · Eval - Recursive let let x = e1 in e2 If e1 is not a function, how do we implement eval? Eval - Recursive let let x = e1 in e2 let y = 3 in (1 + y) ... sum](https://reader036.vdocument.in/reader036/viewer/2022071100/5fd931ec09f301358739fc2f/html5/thumbnails/10.jpg)
Writing a Lexerdata Token = NUM AlexPosn Int | ID AlexPosn String | PLUS AlexPosn
….
Define rules of the form | <regexp> {haskell-expr}
When <regexp> is matched, we evaluate {haskell-expr} to generate a token
Haskell-expr :: AlexPosn -> String -> Token
![Page 11: Nano: Parsing and Eval · Eval - Recursive let let x = e1 in e2 If e1 is not a function, how do we implement eval? Eval - Recursive let let x = e1 in e2 let y = 3 in (1 + y) ... sum](https://reader036.vdocument.in/reader036/viewer/2022071100/5fd931ec09f301358739fc2f/html5/thumbnails/11.jpg)
More lexingdata Token = NUM AlexPosn Int | ID AlexPosn String | PLUS AlexPosn
Declare a mapping from patterns to a corresponding Haskell expression that returns a Token:
[\+] { \p _ -> PLUS p }
$digit+ { \p s -> NUM p (read s) }
![Page 12: Nano: Parsing and Eval · Eval - Recursive let let x = e1 in e2 If e1 is not a function, how do we implement eval? Eval - Recursive let let x = e1 in e2 let y = 3 in (1 + y) ... sum](https://reader036.vdocument.in/reader036/viewer/2022071100/5fd931ec09f301358739fc2f/html5/thumbnails/12.jpg)
Writing regexeshttps://www.haskell.org/alex/doc/html/regexps.html
![Page 13: Nano: Parsing and Eval · Eval - Recursive let let x = e1 in e2 If e1 is not a function, how do we implement eval? Eval - Recursive let let x = e1 in e2 let y = 3 in (1 + y) ... sum](https://reader036.vdocument.in/reader036/viewer/2022071100/5fd931ec09f301358739fc2f/html5/thumbnails/13.jpg)
Parsing :: [Token] -> ASTHappy uses a Context-Free Grammar to define the tree structure
Terminal objects (leaf nodes of tree): TNUM and ID. Other token declarations simply map to values of the Token type. Tokens are re-defined
%tokentype { Token }
%token TNUM { NUM _ $$ } ID { ID _ $$ } '+' { PLUS _ } '-' { MINUS _ } '*' { MUL _ } ...
![Page 14: Nano: Parsing and Eval · Eval - Recursive let let x = e1 in e2 If e1 is not a function, how do we implement eval? Eval - Recursive let let x = e1 in e2 let y = 3 in (1 + y) ... sum](https://reader036.vdocument.in/reader036/viewer/2022071100/5fd931ec09f301358739fc2f/html5/thumbnails/14.jpg)
Parsing :: [Token] -> ASTNon-terminals describe internal nodes of AST:
Aexpr : BinExp { $1 } | TNUM { AConst $1 } | ID { AVar $1 } | '(' Aexpr ')' { $2 }
BinExp : Aexpr '*' Aexpr { AMul $1 $3 } | Aexpr '+' Aexpr { APlus $1 $3 } | Aexpr '-' Aexpr { AMinus $1 $3 } | Aexpr '/' Aexpr { ADiv $1 $3 }
![Page 15: Nano: Parsing and Eval · Eval - Recursive let let x = e1 in e2 If e1 is not a function, how do we implement eval? Eval - Recursive let let x = e1 in e2 let y = 3 in (1 + y) ... sum](https://reader036.vdocument.in/reader036/viewer/2022071100/5fd931ec09f301358739fc2f/html5/thumbnails/15.jpg)
Parsing :: [Token] -> ASTStructure of rules corresponds to recursive structure of type definitions:
Aexpr : BinExp | TNUM | ID | '(' Aexpr ')'
BinExp : Aexpr '*' Aexpr | Aexpr '+' Aexpr | Aexpr '-' Aexpr | Aexpr '/' Aexpr
data Aexpr = AConst Int | AVar String | APlus Aexpr Aexpr | AMinus Aexpr Aexpr | AMul Aexpr Aexpr | ADiv Aexpr Aexp
![Page 16: Nano: Parsing and Eval · Eval - Recursive let let x = e1 in e2 If e1 is not a function, how do we implement eval? Eval - Recursive let let x = e1 in e2 let y = 3 in (1 + y) ... sum](https://reader036.vdocument.in/reader036/viewer/2022071100/5fd931ec09f301358739fc2f/html5/thumbnails/16.jpg)
Parsing :: [Token] -> ASTThe hardest part of writing parsers is figuring out a recursive definition for the grammar.
![Page 17: Nano: Parsing and Eval · Eval - Recursive let let x = e1 in e2 If e1 is not a function, how do we implement eval? Eval - Recursive let let x = e1 in e2 let y = 3 in (1 + y) ... sum](https://reader036.vdocument.in/reader036/viewer/2022071100/5fd931ec09f301358739fc2f/html5/thumbnails/17.jpg)
A problem evalString [] “2 * 5 + 5” = 20
evalString [] “2 - 1 - 1” = 2
![Page 18: Nano: Parsing and Eval · Eval - Recursive let let x = e1 in e2 If e1 is not a function, how do we implement eval? Eval - Recursive let let x = e1 in e2 let y = 3 in (1 + y) ... sum](https://reader036.vdocument.in/reader036/viewer/2022071100/5fd931ec09f301358739fc2f/html5/thumbnails/18.jpg)
A problem evalString [] “2 * 5 + 5” = 20
Should be
(2 * 5) + 5
![Page 19: Nano: Parsing and Eval · Eval - Recursive let let x = e1 in e2 If e1 is not a function, how do we implement eval? Eval - Recursive let let x = e1 in e2 let y = 3 in (1 + y) ... sum](https://reader036.vdocument.in/reader036/viewer/2022071100/5fd931ec09f301358739fc2f/html5/thumbnails/19.jpg)
A problem evalString [] “2 * 5 + 5” = 20
Should be
(2 * 5) + 5 = 15
Can be parsed as
(2 * 5) + 5
OR
2 * (5 + 5)
![Page 20: Nano: Parsing and Eval · Eval - Recursive let let x = e1 in e2 If e1 is not a function, how do we implement eval? Eval - Recursive let let x = e1 in e2 let y = 3 in (1 + y) ... sum](https://reader036.vdocument.in/reader036/viewer/2022071100/5fd931ec09f301358739fc2f/html5/thumbnails/20.jpg)
A problem evalString [] “2 - 1 - 1” = 2
Should be
(2 - 1) - 1
![Page 21: Nano: Parsing and Eval · Eval - Recursive let let x = e1 in e2 If e1 is not a function, how do we implement eval? Eval - Recursive let let x = e1 in e2 let y = 3 in (1 + y) ... sum](https://reader036.vdocument.in/reader036/viewer/2022071100/5fd931ec09f301358739fc2f/html5/thumbnails/21.jpg)
A problem evalString [] “2 - 1 - 1” = 2
Should be
(2 - 1) - 1
Can be parsed as
(2 - 1) - 1
OR
2 - (1 - 1)
![Page 22: Nano: Parsing and Eval · Eval - Recursive let let x = e1 in e2 If e1 is not a function, how do we implement eval? Eval - Recursive let let x = e1 in e2 let y = 3 in (1 + y) ... sum](https://reader036.vdocument.in/reader036/viewer/2022071100/5fd931ec09f301358739fc2f/html5/thumbnails/22.jpg)
A problemWe want to indicate that * has higher precedence than +
We want to indicate that - is left-associative
![Page 23: Nano: Parsing and Eval · Eval - Recursive let let x = e1 in e2 If e1 is not a function, how do we implement eval? Eval - Recursive let let x = e1 in e2 let y = 3 in (1 + y) ... sum](https://reader036.vdocument.in/reader036/viewer/2022071100/5fd931ec09f301358739fc2f/html5/thumbnails/23.jpg)
A solutionAexpr : Aexpr '+' Aexpr2 | Aexpr '-' Aexpr2 | Aexpr2
Aexpr2 : Aexpr2 '*' Aexpr3 | Aexpr2 '/' Aexpr3 | Aexpr3
Aexpr3 : TNUM | ID | '(' Aexpr ')'
![Page 24: Nano: Parsing and Eval · Eval - Recursive let let x = e1 in e2 If e1 is not a function, how do we implement eval? Eval - Recursive let let x = e1 in e2 let y = 3 in (1 + y) ... sum](https://reader036.vdocument.in/reader036/viewer/2022071100/5fd931ec09f301358739fc2f/html5/thumbnails/24.jpg)
Why does this work?“2 * 5 + 5”
Parser first looks for + or -
_ + 5 -> Plus _ 5
![Page 25: Nano: Parsing and Eval · Eval - Recursive let let x = e1 in e2 If e1 is not a function, how do we implement eval? Eval - Recursive let let x = e1 in e2 let y = 3 in (1 + y) ... sum](https://reader036.vdocument.in/reader036/viewer/2022071100/5fd931ec09f301358739fc2f/html5/thumbnails/25.jpg)
Why does this work?“2 * 5 + 5”
There is now only ONE unique way to generate this string from our grammar
Start by applying the “+” rule:
_ + 5
Then apply the “*” rule:
(2 * 5) + 5
![Page 26: Nano: Parsing and Eval · Eval - Recursive let let x = e1 in e2 If e1 is not a function, how do we implement eval? Eval - Recursive let let x = e1 in e2 let y = 3 in (1 + y) ... sum](https://reader036.vdocument.in/reader036/viewer/2022071100/5fd931ec09f301358739fc2f/html5/thumbnails/26.jpg)
Why does this work?“2 - 1 - 1”
There is now only ONE unique way to generate this string from our grammar
Any expression with more than one subtraction operation must have the extra subtractions in the LEFT subtree of the AST:
(2 - 1) - 1 is valid, but 2 - (1 - 1) is not, since anything on the right side of a subtraction must be generated by the Aexpr2 rule.
![Page 27: Nano: Parsing and Eval · Eval - Recursive let let x = e1 in e2 If e1 is not a function, how do we implement eval? Eval - Recursive let let x = e1 in e2 let y = 3 in (1 + y) ... sum](https://reader036.vdocument.in/reader036/viewer/2022071100/5fd931ec09f301358739fc2f/html5/thumbnails/27.jpg)
Another solution%left '+' '-'%left '*' '/'
Tells parser generator that operators are left-associative
Operators declared on bottom have higher precedence
![Page 28: Nano: Parsing and Eval · Eval - Recursive let let x = e1 in e2 If e1 is not a function, how do we implement eval? Eval - Recursive let let x = e1 in e2 let y = 3 in (1 + y) ... sum](https://reader036.vdocument.in/reader036/viewer/2022071100/5fd931ec09f301358739fc2f/html5/thumbnails/28.jpg)
Another solution%left '+' '-'%left '*' '/'
Tells parser generator that operators are left-associative
Operators declared on bottom have higher precedence
![Page 29: Nano: Parsing and Eval · Eval - Recursive let let x = e1 in e2 If e1 is not a function, how do we implement eval? Eval - Recursive let let x = e1 in e2 let y = 3 in (1 + y) ... sum](https://reader036.vdocument.in/reader036/viewer/2022071100/5fd931ec09f301358739fc2f/html5/thumbnails/29.jpg)
Parsing :: [Token] -> AST We could have defined our parser grammar exactly like the datatype:
Aexpr : TNUM | ID | '(' Aexpr ')' | Aexpr '*' Aexpr | Aexpr '+' Aexpr | Aexpr '-' Aexpr | Aexpr '/' Aexpr
data Aexpr = AConst Int | AVar String | APlus Aexpr Aexpr | AMinus Aexpr Aexpr | AMul Aexpr Aexpr | ADiv Aexpr Aexp
![Page 30: Nano: Parsing and Eval · Eval - Recursive let let x = e1 in e2 If e1 is not a function, how do we implement eval? Eval - Recursive let let x = e1 in e2 let y = 3 in (1 + y) ... sum](https://reader036.vdocument.in/reader036/viewer/2022071100/5fd931ec09f301358739fc2f/html5/thumbnails/30.jpg)
Parsing :: [Token] -> ASTIt’s generally easier to reason about the grammar if split into subtrees (AND you can deal with operator precedence):
Aexpr : BinExp | TNUM | ID | '(' Aexpr ')'
BinExp : Aexpr '*' Aexpr | Aexpr '+' Aexpr | Aexpr '-' Aexpr | Aexpr '/' Aexpr
data Aexpr = AConst Int | AVar String | APlus Aexpr Aexpr | AMinus Aexpr Aexpr | AMul Aexpr Aexpr | ADiv Aexpr Aexp
![Page 31: Nano: Parsing and Eval · Eval - Recursive let let x = e1 in e2 If e1 is not a function, how do we implement eval? Eval - Recursive let let x = e1 in e2 let y = 3 in (1 + y) ... sum](https://reader036.vdocument.in/reader036/viewer/2022071100/5fd931ec09f301358739fc2f/html5/thumbnails/31.jpg)
Extending our parser and lexerWhat if we want to add boolean expressions to our language?
data AExpr = … | ITE BExpr AExpr AExpr
data BExpr = BTrue | BFalse | Eq AExpr AExpr
![Page 32: Nano: Parsing and Eval · Eval - Recursive let let x = e1 in e2 If e1 is not a function, how do we implement eval? Eval - Recursive let let x = e1 in e2 let y = 3 in (1 + y) ... sum](https://reader036.vdocument.in/reader036/viewer/2022071100/5fd931ec09f301358739fc2f/html5/thumbnails/32.jpg)
New tokens and matching regexes:data Token = … | TRUE AlexPosn | FALSE AlexPosn | BEQ AlexPosn | IF AlexPosn | THEN AlexPosn …
“==” { \p _ -> BEQ p }if { \p _ -> IF p }then { \p _ -> THEN p }...
![Page 33: Nano: Parsing and Eval · Eval - Recursive let let x = e1 in e2 If e1 is not a function, how do we implement eval? Eval - Recursive let let x = e1 in e2 let y = 3 in (1 + y) ... sum](https://reader036.vdocument.in/reader036/viewer/2022071100/5fd931ec09f301358739fc2f/html5/thumbnails/33.jpg)
Extend the grammarDeclare more tokens in the .x file
...then { THEN _ }else { ELSE _ }‘==’ {BEq _}...
![Page 34: Nano: Parsing and Eval · Eval - Recursive let let x = e1 in e2 If e1 is not a function, how do we implement eval? Eval - Recursive let let x = e1 in e2 let y = 3 in (1 + y) ... sum](https://reader036.vdocument.in/reader036/viewer/2022071100/5fd931ec09f301358739fc2f/html5/thumbnails/34.jpg)
Extend the grammarAexpr : BinExp { $1 } | TNUM { AConst $1 } | ID { AVar $1 } | '(' Aexpr ')' { $2 } | if BoolExp then Aexpr else Aexpr { ITE $2 $4 $6 }
BoolExp : true { BTrue } | false { BTrue } | Aexpr eq Aexpr { BEq $1 $3 }
Breaking the grammar up makes it easier to extend!
![Page 35: Nano: Parsing and Eval · Eval - Recursive let let x = e1 in e2 If e1 is not a function, how do we implement eval? Eval - Recursive let let x = e1 in e2 let y = 3 in (1 + y) ... sum](https://reader036.vdocument.in/reader036/viewer/2022071100/5fd931ec09f301358739fc2f/html5/thumbnails/35.jpg)
More detail on this example:https://github.com/cse130-sp18/arith
Alex docs: https://www.haskell.org/alex/doc/html/index.html
Happy docs: https://www.haskell.org/happy/
![Page 36: Nano: Parsing and Eval · Eval - Recursive let let x = e1 in e2 If e1 is not a function, how do we implement eval? Eval - Recursive let let x = e1 in e2 let y = 3 in (1 + y) ... sum](https://reader036.vdocument.in/reader036/viewer/2022071100/5fd931ec09f301358739fc2f/html5/thumbnails/36.jpg)
Eval - Recursive letlet x = e1 in e2
If e1 is not a function, how do we implement eval?
![Page 37: Nano: Parsing and Eval · Eval - Recursive let let x = e1 in e2 If e1 is not a function, how do we implement eval? Eval - Recursive let let x = e1 in e2 let y = 3 in (1 + y) ... sum](https://reader036.vdocument.in/reader036/viewer/2022071100/5fd931ec09f301358739fc2f/html5/thumbnails/37.jpg)
Eval - Recursive letlet x = e1 in e2
let y = 3 in (1 + y)
![Page 38: Nano: Parsing and Eval · Eval - Recursive let let x = e1 in e2 If e1 is not a function, how do we implement eval? Eval - Recursive let let x = e1 in e2 let y = 3 in (1 + y) ... sum](https://reader036.vdocument.in/reader036/viewer/2022071100/5fd931ec09f301358739fc2f/html5/thumbnails/38.jpg)
Eval - Recursive letlet x = e1 in e2
What happens if e1 IS a function?
![Page 39: Nano: Parsing and Eval · Eval - Recursive let let x = e1 in e2 If e1 is not a function, how do we implement eval? Eval - Recursive let let x = e1 in e2 let y = 3 in (1 + y) ... sum](https://reader036.vdocument.in/reader036/viewer/2022071100/5fd931ec09f301358739fc2f/html5/thumbnails/39.jpg)
Eval - Recursive letlet sum = \n -> if n <= 0 then 0 else n + sum (n - 1)
in sum 5
![Page 40: Nano: Parsing and Eval · Eval - Recursive let let x = e1 in e2 If e1 is not a function, how do we implement eval? Eval - Recursive let let x = e1 in e2 let y = 3 in (1 + y) ... sum](https://reader036.vdocument.in/reader036/viewer/2022071100/5fd931ec09f301358739fc2f/html5/thumbnails/40.jpg)
How do we evaluate this?let sum = \n -> if n <= 0 then 0 else n + sum (n - 1)
in sum 5
![Page 41: Nano: Parsing and Eval · Eval - Recursive let let x = e1 in e2 If e1 is not a function, how do we implement eval? Eval - Recursive let let x = e1 in e2 let y = 3 in (1 + y) ... sum](https://reader036.vdocument.in/reader036/viewer/2022071100/5fd931ec09f301358739fc2f/html5/thumbnails/41.jpg)
One approachlet sum = \n -> if n <= 0 then 0 else n + sum (n - 1)
in sum 5
Add sum (as a closure) to the context, evaluate sum 5
[“sum”, <[],\n -> if n <= 0 then 0 else n + sum (n - 1)>]
sum 5 = ??
![Page 42: Nano: Parsing and Eval · Eval - Recursive let let x = e1 in e2 If e1 is not a function, how do we implement eval? Eval - Recursive let let x = e1 in e2 let y = 3 in (1 + y) ... sum](https://reader036.vdocument.in/reader036/viewer/2022071100/5fd931ec09f301358739fc2f/html5/thumbnails/42.jpg)
One approachlet sum = \n -> if n <= 0 then 0 else n + sum (n - 1)
in sum 5
Add sum (as a closure) to the context, evaluate sum 5
[“sum”, <[], \n -> if n <= 0 then 0 else n + sum (n - 1)>]
sum 5 = (\n -> if n <= 0 then 0 else n + sum (n - 1)) 5
![Page 43: Nano: Parsing and Eval · Eval - Recursive let let x = e1 in e2 If e1 is not a function, how do we implement eval? Eval - Recursive let let x = e1 in e2 let y = 3 in (1 + y) ... sum](https://reader036.vdocument.in/reader036/viewer/2022071100/5fd931ec09f301358739fc2f/html5/thumbnails/43.jpg)
One approachlet sum = \n -> if n <= 0 then 0 else n + sum (n - 1)
in sum 5
Add sum (as a closure) to the context, evaluate sum 5
[“sum”, <[], \n -> if n <= 0 then 0 else n + sum (n - 1)>]
sum 5 = (\n -> if n <= 0 then 0 else n + sum (n - 1)) 5
![Page 44: Nano: Parsing and Eval · Eval - Recursive let let x = e1 in e2 If e1 is not a function, how do we implement eval? Eval - Recursive let let x = e1 in e2 let y = 3 in (1 + y) ... sum](https://reader036.vdocument.in/reader036/viewer/2022071100/5fd931ec09f301358739fc2f/html5/thumbnails/44.jpg)
One approachAdd sum (as a closure) to the context, evaluate sum 5
[“sum”, <[], \n -> if n <= 0 then 0 else n + sum (n - 1)>]
sum 5 = (\n -> if n <= 0 then 0 else n + sum (n - 1)) 5
Will this work?
![Page 45: Nano: Parsing and Eval · Eval - Recursive let let x = e1 in e2 If e1 is not a function, how do we implement eval? Eval - Recursive let let x = e1 in e2 let y = 3 in (1 + y) ... sum](https://reader036.vdocument.in/reader036/viewer/2022071100/5fd931ec09f301358739fc2f/html5/thumbnails/45.jpg)
One approachAdd sum (as a closure) to the context, evaluate sum 5
[“sum”, <[], \n -> if n <= 0 then 0 else n + sum (n - 1)>]
sum 5 = (\n -> if n <= 0 then 0 else n + sum (n - 1)) 5
Will this work?
![Page 46: Nano: Parsing and Eval · Eval - Recursive let let x = e1 in e2 If e1 is not a function, how do we implement eval? Eval - Recursive let let x = e1 in e2 let y = 3 in (1 + y) ... sum](https://reader036.vdocument.in/reader036/viewer/2022071100/5fd931ec09f301358739fc2f/html5/thumbnails/46.jpg)
One approachAdd sum (as a closure) to the context, evaluate sum 5
[“sum”, <[], \n -> if n <= 0 then 0 else n + sum (n - 1)>]
if 5 <= 0 then 0 else n + sum (5 - 1)
Will this work?
What happens when we make the recursive call?