|
|
|||||
|
|
Start of topic | Skip to actions
Staged IntepreterReviewLast few classes, we have already seen how to define "typed terms" in concoqtion, and how to write an intepreter for it. Today we are going to look at some implementation details.What we've got:
type (env, t) term =
| TInt of let env' in int : (env', Int) term
| TVarZ of let t', env' in unit: ((env', t')pair, t') term
| TVarS of let t, t'', env' in (env', t') term : ((env', t'') pair, t') term
| TApp of let env', t1, t2 in (env' , Arrow t1 t2) term * (env', t1) term : (env', t2) term
| TLam of let env', t', t'' in ((env' t') pair, t'') term: (env', Arrow t' t'') term
eval (e:(env, t) term) ctx:eval_env =
match e with
| Int i -> VInt i
| Var Z -> first env
| Var (S n) -> eval (Var n) (second env)
| Lam e -> VFun (fun v -> eval e (EPair (v, env))
| App e1 e2 -> | (unVFun (eval e1 env)) (eval e2 env)
First: define the index type in coq:coq Inductive ty: Set := | Int: ty | Fun: ty -> ty -> ty. Inductive ev: Set := | Empty: ev | Ext: ev -> ty -> ev. end;; Now we can define the typed term as follows:
type ('e:'(ev), 't:'(ty)) tterm =
| TInt of let 'e1:'(ev) in int: ('(e1), '(Int)) tterm
| TVarZero of let 'e1:'(ev) 't1:'(ty) in unit: ('(Ext e1 t1), '(t1)) tterm
| TValPlus of let 'e1:'(ev) 't1:'(ty) 't2:'(ty) in ('(e1), '(t1)) tterm: ('(Ext e1 t2), '(t1)) tterm
| TAbs of let 'e1:'(ev) 't1:'(ty) 't2:'(ty) in ('(Ext e1 t1), '(t2)) tterm: ('(e1), '(Fun t1 t2)) tterm
| TApp of let 'e1:'(ev) 't1:'(ty) 't2:'(ty) in
('(e1), '(Fun t1 t2)) tterm * ('(e1), '(t1)) tterm: ('(e1), '(t2)) tterm
;;
Intepreter with tagsRemember that the type of our interpreter should like this:
forall e1:'(ev). forall t1:'(ty). ('(e1). '(t1)) tterm -> '(e2) -> '(t2)
What is e2 and t2 here? How to get them from e1 and t1? We first consider evaluation where there is no variable, thus evaluation environment is not needes. For '(t2), we can try something like this:
type 't:'(ty) value =
| VInt of int: '(Int) value
| VFun of let 't1:'(ty) 't2:'(ty) in '(t1) value * '(t2) value: '(Fun t1 t2) value
;;
let rec t_eval.|e1:'(ev), t1:'(ty)| (exp:('(e1), '(t1)) tterm): '(t1) value =
match exp as ('e:'(ev), 't:'(ty)) tterm in '(t) value with
| TInt .|e1:'(ev)| (i) -> VInt (i)
| TApp .|e1:'(ev), t2:'(ty), t3:'(ty)| (e1, e2) ->
let v1 = t_eval .|'(e1), '(Fun t2 t3)| e1 in
let v2 = t_eval .|'(e1), '(t2)| e2 in (v1 v2)
;;
We get the following error report from concoqtion. What's the problem? How to solve it? This expression is not a function, it cannot be applied Here is a trick we can use, which comes from Emir:
coq
Definition codom (t:ty) : ty :=
match t with
| Int => Int
| Fun a b => b end.
Definition dom (t:ty) : ty :=
match t with
| Int => Int
| Fun a b => a end.
end
let apply .|arrow:'(ty)| (f:'(arrow) value) : ('(dom arrow) value) -> '(codom arrow) value =
match f as 't:'(ty) value in '(dom t) value -> '(codom t) value with
| VFun .|a:'(ty),b:'(ty)| f -> (fun x -> f x)
| _ -> assert false
Although working, it is not nice. What else we can do?
Write up a tagless intepreterAgain the type of our interpreter should like this:
forall e1:'(ev). forall t1:'(ty). ('(e1). '(t1)) tterm -> '(e2) -> '(t2)
A tagless intepreter focus on coq types instead of OCaml types, thus we need to think: What is e2 and t2 here? How to get them from e1 and t1? Following are Coq type definition of evalution environment and return types which helps in a tagless intepreter
coq
Fixpoint evalT (t:ty) : OCamlType :=
match t with
| Int => OCaml_int
| Fun dom cod => OCaml_Arr (evalT dom) (evalT cod)
Notation "A -*- B" :=
OCaml_Tuple (OCaml_Lst_cons A (OCaml_List_cons B OCaml_List_nil)).
Fixpoint evalEnv (e:ev) : OCamlType :=
match e with
| Empty => OCaml_unit
| Ext env t => (evalEnv env) -*- (evalT t)
end;;
Finish the intepreterNow, the intepreter should look like:
let rec t_eval .|e1:'(ev), t1:'(ty)| (exp:('(e1), '(t1)) tterm) (evalEnv:'(evalEnv e1)): '(evalT t) =
match exp as ('e:'(ev), 't:'(ty)) tterm in '(t2) with
| TInt i ->
| TVarZero .|e1:'(ev), t1:'(ty)| _ ->
| TVarPlus .|e2:'(ev), t1:'(ty), t2:'(ty)| v1 ->
| TAbs .|e2:'(ev), t1:'(ty), t2:'(ty)| body ->
| TApp .|e2:'(ev), t1:'(ty), t2:'(ty)| (rator, rand) ->
What to put after each ->? What's more(Homework)?
Topic Actions: Edit | Attach | Printable | Raw View | Backlinks: Web, All Webs | History: r1 | More topic actions
Webs: Main | TWiki | Africa | EmbeddedSystems | Gpce | Houston | International | K12 | MetaOCaml | MulticoreOCR | ProgrammingLanguages | RAP | RIDL | Sandbox | SpeechClub | Teaching | Texbot | WG211 Web Actions: |
||||
This work is licensed under a Creative Commons Attribution 2.5 License. Please follow our citation guidelines.