Skip to content

Commit b379119

Browse files
committed
[lec12] lab4 live code
1 parent 62f748c commit b379119

File tree

3 files changed

+198
-2
lines changed

3 files changed

+198
-2
lines changed

README.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -57,8 +57,8 @@ Material: plt = course book, dragon = Dragon book. Slides follow closely the plt
5757
| *Wed 04/12* | *23* | *Lab 2 deadline* | |
5858
| Thu 05/12 | 13-15 | Functional programming languages | [slides](plt-book/ipl-book/slides/7-slides-ipl-book.pdf), plt 7, dragon 6.5,7.3, [script](notes/cbn-cbv.html) |
5959
| Tue 10/12 | 13-15 | Type inference and polymorphism | plt 7.7-9, [script](notes/typing.html), [visualization tool](https://github.com/teach-plt/visualize-type-inference) |
60-
| Thu 12/12 **HC1** | 13-14 | Hands-on with Lab 4 (Haskell) | |
61-
| Thu 12/12 | 14-15 | Hands-on with Lab 4 (Java) | |
60+
| Thu 12/12 **HC1** | 13-14 | Hands-on with Lab 4 (Haskell) | [live code](live/2024/lab4/Interpreter.hs) |
61+
| Thu 12/12 | 14-15 | Hands-on with Lab 4 (Java) | [live code](live/2024/lab4/Interpreter.java) |
6262
| Tue 17/12 | 13-15 | Dependent types (Agda) | |
6363
| *Wed 18/12* | *23* | *Lab 3 deadline* | |
6464
| Thu 19/12 **SB-H5** | 13-15 | Preparing for the exam | |

live/2024/lab4/Interpreter.hs

Lines changed: 94 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,94 @@
1+
{-# OPTIONS_GHC -Wno-unused-imports #-} -- Turn off unused import warning off in stub
2+
{-# OPTIONS_GHC -Wno-unused-matches #-} -- Turn off unused binding warning off in stub
3+
4+
{-# LANGUAGE LambdaCase #-}
5+
6+
-- | Interpreter for lambda-calculus with if, +, -, <.
7+
--
8+
-- Strategy can be either call-by-value or call-by-name.
9+
10+
module Interpreter (interpret, Strategy(..)) where
11+
12+
import Control.Applicative
13+
import Control.Monad.Except
14+
import Control.Monad.Reader
15+
16+
import Data.Functor
17+
import Data.Map (Map)
18+
import qualified Data.Map as Map
19+
20+
import Fun.Abs
21+
import Fun.Print
22+
23+
-- | Evaluation strategy.
24+
25+
data Strategy
26+
= CallByName
27+
| CallByValue
28+
29+
-- | Error monad.
30+
31+
type Err = Except String
32+
33+
-- | Signature maps identifiers to closed expressions.
34+
35+
type Sig = Map Ident Exp
36+
37+
-- | Call-by-value environment maps identifiers to values.
38+
39+
type Env = Map Ident Val
40+
41+
-- | Values.
42+
43+
data Val
44+
= VInt Integer -- ^ Integer literal.
45+
| VFun Ident Exp Env -- ^ Function closure.
46+
47+
-- | Read-only data for the evaluator.
48+
49+
data EvDat = EvDat
50+
{ _strategy :: Strategy
51+
, _sig :: Sig
52+
}
53+
54+
-- | Entry point: Program computes a number.
55+
56+
interpret :: Strategy -> Program -> Err Integer
57+
interpret strategy (Prog defs (DMain mainExp)) = do
58+
-- Build Sig
59+
let sig = Map.fromList $ map (\ (DDef f xs e) -> (f, abstract xs e)) defs
60+
-- Evaluate main
61+
case runExcept (eval (EvDat strategy sig) Map.empty mainExp) of
62+
Left err -> throwError err
63+
Right v -> case v of
64+
VInt i -> return i
65+
VFun{} -> throwError $ "main returned a function, but should return an integer"
66+
67+
-- | @abstract [x1,...,xn] e = EAbs x1 $ ... $ EAbs xn e@.
68+
abstract :: [Ident] -> Exp -> Exp
69+
abstract xs e = foldr EAbs e xs
70+
71+
eval :: EvDat -> Env -> Exp -> Err Val
72+
eval dat env = \case
73+
EInt i -> return $ VInt i -- return :: Val -> Err Val
74+
EVar x -> lookupVar dat env x
75+
EAbs x e -> return $ VFun x e env
76+
EApp e1 e2 -> do
77+
v1 <- eval dat env e1
78+
v2 <- eval dat env e2
79+
case v1 of
80+
VFun x e env1 -> eval dat (Map.insert x v2 env1) e
81+
VInt{} -> throwError $ printTree e1 ++ " is not a function, but applied to " ++ printTree e2
82+
e -> nyi e
83+
84+
lookupVar :: EvDat -> Env -> Ident -> Err Val
85+
lookupVar dat env x =
86+
case Map.lookup x env of
87+
Just v -> return v
88+
Nothing ->
89+
case Map.lookup x (_sig dat) of
90+
Just e -> eval dat Map.empty e
91+
Nothing -> throwError $ "unbound identifier " ++ printTree x
92+
93+
nyi :: Print e => e -> Err a
94+
nyi e = throwError $ "not yet implemented: interpreting " ++ printTree e

live/2024/lab4/Interpreter.java

Lines changed: 102 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,102 @@
1+
import java.util.*;
2+
import fun.Absyn.*;
3+
import fun.PrettyPrinter;
4+
5+
public class Interpreter {
6+
7+
final Strategy strategy;
8+
9+
final Map<String,Exp> sig = new TreeMap<String,Exp>();
10+
11+
public Interpreter(Strategy strategy) {
12+
this.strategy = strategy;
13+
}
14+
15+
public void interpret(Program p) {
16+
switch(p) {
17+
case Prog prg -> {
18+
DMain main = (DMain)prg.main_;
19+
// Make sig from listdef_
20+
for (var d : prg.listdef_) {
21+
DDef dd = (DDef)d;
22+
Exp e = dd.exp_;
23+
// [x1,x2] e --> new EAbs(x1, new EAbs(x2, e))
24+
var xs = dd.listident_;
25+
Collections.reverse(xs);
26+
for (String x : xs) {
27+
e = new EAbs(x, e);
28+
}
29+
sig.put(dd.ident_, e);
30+
}
31+
32+
// Evaluate main_
33+
System.out.println(eval(new Env(), main.exp_).intValue());
34+
}
35+
default -> { throw new RuntimeException("Interpreter not implemented yet"); }
36+
}
37+
}
38+
39+
// Evaluate expressions
40+
41+
Value eval(Env env, Exp e) {
42+
switch(e) {
43+
case EInt p -> { return new VInt(p.integer_); }
44+
case EAbs p -> { return new VFun(p.ident_, p.exp_, env); }
45+
case EApp p -> {
46+
Value v1 = eval(env, p.exp_1);
47+
Value v2 = eval(env, p.exp_2);
48+
return v1.apply(v2);
49+
}
50+
case EVar p -> {
51+
String x = p.ident_;
52+
Value v = env.lookup(x);
53+
if (v == null) {
54+
Exp f = sig.get(x);
55+
if (f == null) throw new RuntimeException("unbound identifier " + x);
56+
return eval(new Env(), f);
57+
} else return v;
58+
}
59+
default -> { throw new RuntimeException("not yet implemented" + PrettyPrinter.print(e)); }
60+
}
61+
}
62+
63+
// Values
64+
65+
abstract class Value {
66+
abstract public Integer intValue();
67+
abstract public Value apply(Value arg);
68+
}
69+
70+
class VInt extends Value {
71+
final Integer i;
72+
VInt(Integer i) { this.i = i; }
73+
public Integer intValue() { return i; }
74+
public Value apply(Value arg) { throw new RuntimeException("cannot apply number"); }
75+
}
76+
77+
class VFun extends Value {
78+
final String x;
79+
final Exp body;
80+
final Env env;
81+
VFun (String x, Exp body, Env env) { this.x = x; this.body = body; this.env = env; }
82+
public Integer intValue() { throw new RuntimeException("function does not have intValue()"); }
83+
public Value apply (Value arg) { return eval(new Extend(x, arg, env), body); }
84+
}
85+
86+
// Environments
87+
88+
class Env {
89+
public Value lookup(String x) { return null; }
90+
}
91+
92+
class Extend extends Env {
93+
final String x;
94+
final Value v;
95+
final Env env;
96+
Extend(String x, Value v, Env env) { this.x = x; this.v = v; this.env = env; }
97+
public Value lookup(String x) {
98+
if (x.equals(this.x)) return v;
99+
else return env.lookup(x);
100+
}
101+
}
102+
}

0 commit comments

Comments
 (0)