This commit is contained in:
Michael Zhang 2018-02-16 05:22:07 -06:00
parent 41ecdc4097
commit 97971a1d0c
No known key found for this signature in database
GPG key ID: A1B65B603268116B
5 changed files with 79 additions and 17 deletions

View file

@ -1 +1,4 @@
# λ # λ
Based on Benjamin Pierce's _Types and Programming Languages_

View file

@ -3,24 +3,72 @@ open Lexing
open Parser open Parser
open Types open Types
exception EvaluationComplete
let rec string_of_term (t:term) = let rec string_of_term (t:term) =
match t with match t with
| TmAbs(x, t1) -> | TmAbs(x, t1) ->
"(\\" ^ (String.make 1 x) ^ "." ^ (string_of_term t1) ^ ")" "(\\" ^ x ^ "." ^ (string_of_term t1) ^ ")"
| TmApp(t1, t2) -> | TmApp(t1, t2) ->
"(" ^ (string_of_term t1) ^ (string_of_term t2) ^ ")" "(" ^ (string_of_term t1) ^ " " ^ (string_of_term t2) ^ ")"
| TmVar(x) -> | TmVar(x) -> x
String.make 1 x
(*
let termshift d t =
let rec walk c t =
match t with
| TmVar(x) -> if
let termsubsttop (s:term) (t:term) =
termshift (-1) (termsubst 0 (termshift 1 s) t)
let rec isval ctx t =
match t with
| TmAbs(_, _, _) -> true
| _ -> false
let rec helper ctx t =
match t with
| TmApp(TmAbs(x, t1), v2) when isval ctx v2 -> termsubsttop v2 t1
| _ -> EvaluationComplete
*)
let assign ctx (name, t) : context =
(name, t)::ctx
let rec lookup ctx name : term =
match ctx with
| [] -> raise (Failure ("unbound variable " ^ name))
| (n, t)::tail ->
if n = name then t else lookup tail name
let rec eval (ctx, t) =
let rec helper (ctx, t) =
match t with
| Assign(name, t') ->
let (ctx', r) = helper(ctx, t') in
(assign ctx (name, r), r)
| TmAbs(name, t') ->
let (ctx', v) = helper (ctx, t') in
(assign ctx (name, v), v)
| TmVar(name) ->
(ctx, lookup ctx name)
| _ -> raise EvaluationComplete
in try
let (ctx', t') = helper (ctx, t) in
eval (ctx', t')
with EvaluationComplete -> (ctx, t)
let _ = let _ =
try try
let rec loop ctx = let rec loop ctx =
print_string "> "; flush stdout; print_string "> "; flush stdout;
let lexbuf = Lexing.from_channel stdin in let lexbuf = Lexing.from_channel stdin in
let result = Parser.main Lexer.token lexbuf in let t = Parser.main Lexer.token lexbuf in
print_endline (string_of_term result); flush stdout; let (ctx', r) = eval (ctx, t) in
loop ctx in print_endline (string_of_term r); flush stdout;
loop ctx' in
loop [] loop []
with Lexer.Eof -> with Lexer.Eof ->
print_endline "error"; print_endline "^D";
exit 0 exit 0

View file

@ -6,7 +6,10 @@
rule token = parse rule token = parse
| ' ' | '\t' { token lexbuf } | ' ' | '\t' { token lexbuf }
| '\n' { EOL } | '\n' { EOL }
| '=' { Equal }
| '\\' { Lambda } | '\\' { Lambda }
| '(' { LParen }
| ')' { RParen }
| '.' { Dot } | '.' { Dot }
| ['a'-'z'] as c | ['A'-'Z'] as c { Ident(c) } | ['a'-'z' 'A'-'Z'] ['a'-'z' 'A'-'Z' '0'-'9' '_']* as s { Ident(s) }
| eof { raise Eof } | eof { raise Eof }

View file

@ -4,7 +4,10 @@
%token EOL %token EOL
%token Dot %token Dot
%token <char> Ident %token Equal
%token LParen
%token RParen
%token <string> Ident
%token Lambda %token Lambda
%start main %start main
@ -12,12 +15,16 @@
%% %%
main: main:
expr EOL { $1 } | assign EOL { $1 }
| expr EOL { $1 }
;
assign:
| Ident Equal expr { Types.Assign($1, $3) }
; ;
expr: expr:
| var { Types.TmVar($1) } | var { Types.TmVar($1) }
| Lambda var Dot expr { Types.TmAbs($2, $4) } | Lambda var Dot expr { Types.TmAbs($2, $4) }
| expr expr { Types.TmApp ($1, $2) } | LParen expr expr RParen { Types.TmApp ($2, $3) }
; ;
var: var:
Ident { $1 } Ident { $1 }

View file

@ -1,9 +1,10 @@
type var = string
type term = type term =
| TmVar of char | Assign of string * term
| TmAbs of char * term | TmVar of var
| TmAbs of var * term
| TmApp of term * term | TmApp of term * term
type binding = NameBind type context = (string * term) list
type context = (char * binding) list