2017-12-13 14:04:28 +01:00
|
|
|
(* This language is the untyped lambda-calculus, extended with recursive
|
|
|
|
lambda-abstractions, nonrecursive [let] bindings, integer literals and
|
|
|
|
integer arithmetic operations, and the primitive operation [print]. *)
|
|
|
|
|
|
|
|
(* This language is really the same language as [RawLambda], with the
|
|
|
|
following internal differences:
|
|
|
|
|
|
|
|
1. Instead of recursive [let] bindings, the language has recursive
|
|
|
|
lambda-abstractions. A [let rec] definition whose right-hand side is not
|
|
|
|
a lambda-abstraction is rejected during the translation of [RawLambda]
|
|
|
|
to [Lambda].
|
|
|
|
|
|
|
|
2. Variables are represented by atoms (instead of strings). A term with an
|
|
|
|
unbound variable is rejected during the translation of [RawLambda] to
|
|
|
|
[Lambda].
|
|
|
|
|
|
|
|
3. Terms are no longer annotated with places. *)
|
|
|
|
|
|
|
|
(* Variables are atoms. *)
|
|
|
|
|
|
|
|
type variable =
|
|
|
|
Atom.atom
|
|
|
|
|
|
|
|
(* Every lambda-abstraction is marked recursive or nonrecursive. Whereas a
|
|
|
|
nonrecursive lambda-abstraction [fun x -> t] binds one variable [x], a
|
|
|
|
recursive lambda-abstraction [fix f. fun x -> t] binds two variables [f]
|
|
|
|
and [x]. The variable [f] is a self-reference. *)
|
|
|
|
|
|
|
|
and self =
|
|
|
|
| Self of variable
|
|
|
|
| NoSelf
|
|
|
|
|
|
|
|
and binop = RawLambda.binop =
|
|
|
|
| OpAdd
|
|
|
|
| OpSub
|
|
|
|
| OpMul
|
|
|
|
| OpDiv
|
|
|
|
|
|
|
|
and term =
|
|
|
|
| Var of variable
|
|
|
|
| Lam of self * variable * term
|
|
|
|
| App of term * term
|
|
|
|
| Lit of int
|
|
|
|
| BinOp of term * binop * term
|
|
|
|
| Print of term
|
|
|
|
| Let of variable * term * term
|
2018-02-16 00:19:44 +01:00
|
|
|
| IfZero of term * term * term
|
2017-12-13 14:04:28 +01:00
|
|
|
|
|
|
|
[@@deriving show { with_path = false }]
|