Compare commits
6 commits
b00976d359
...
ca790364b6
Author | SHA1 | Date | |
---|---|---|---|
Théophile Bastian | ca790364b6 | ||
Théophile Bastian | faa31d90dd | ||
Théophile Bastian | 7c6e2e390e | ||
Théophile Bastian | 3141ce6fde | ||
Théophile Bastian | 2a65d41cd8 | ||
Théophile Bastian | 7bc7921fc3 |
|
@ -30,7 +30,7 @@ let rec cps_value (t: S.term) : T.value = match t with
|
|||
| S.Var v -> T.VVar v
|
||||
| S.Lit v -> T.VLit v
|
||||
| S.BinOp (l, op, r) -> T.VBinOp (cps_value l, op, cps_value r)
|
||||
| S.Let _ | S.Lam _ | S.App _ | S.Print _ -> raise NotValue
|
||||
| S.Let _ | S.Lam _ | S.App _ | S.Print _ | S.IfZero _ -> raise NotValue
|
||||
|
||||
let cps_value_as_term (t: S.term) (cont: T.variable): T.term =
|
||||
T.TailCall(T.vvar cont, [cps_value t])
|
||||
|
@ -69,6 +69,13 @@ let rec cps_term_inner (t: S.term) (cont: T.variable) (nameHint: string option)
|
|||
let curCont = freshBlockVar () in
|
||||
letCont curCont var (cps_term_inner next cont None) @@
|
||||
cps_term_inner value curCont (Some (Atom.hint var))
|
||||
| S.IfZero (expr, tIf, tElse) ->
|
||||
let curCont = freshBlockVar ()
|
||||
and exprVal = freshVar () in
|
||||
letCont curCont exprVal (T.IfZero(T.vvar exprVal,
|
||||
cps_term_inner tIf cont None,
|
||||
cps_term_inner tElse cont None)) @@
|
||||
cps_term_inner expr curCont None
|
||||
|
||||
let cps_term (t: S.term): T.term =
|
||||
(** Entry point. Transforms a [Lambda] term into a [Tail] term, applying a
|
||||
|
|
|
@ -49,6 +49,8 @@ let rec cook_term env { S.place; S.value } =
|
|||
T.Let (f, T.Lam (T.Self f, x, t1), t2)
|
||||
| S.Let (S.Recursive, _, { S.place; _ }, _) ->
|
||||
error place "the right-hand side of 'let rec' must be a lambda-abstraction"
|
||||
| S.IfZero (expr, tIf, tElse) ->
|
||||
T.IfZero (cook_term env expr, cook_term env tIf, cook_term env tElse)
|
||||
|
||||
let cook_term t =
|
||||
cook_term Env.empty t
|
||||
|
|
|
@ -86,6 +86,10 @@ let rec walk_term fs t =
|
|||
T.Branch(thisTag, freeVars, nBody) in
|
||||
let fs = add_func fs arity thisFunc in
|
||||
fs, T.LetBlo (var, T.Con(thisTag, T.vvars freeVars), nNext)
|
||||
| S.IfZero (value, tIf, tElse) ->
|
||||
let fs, tIf = walk_term fs tIf in
|
||||
let fs, tElse = walk_term fs tElse in
|
||||
fs, T.IfZero(value, tIf, tElse)
|
||||
|
||||
|
||||
let apply_of_arity name args branches =
|
||||
|
|
|
@ -228,6 +228,12 @@ let rec finish_term (t : S.term) : C.stmt =
|
|||
init_block x b1 @
|
||||
[ finish_term t2 ]
|
||||
)
|
||||
| S.IfZero (expr, tIf, tElse) ->
|
||||
T.IfElse (
|
||||
T.Op2(T.K.Eq, to_int @@ finish_value expr,
|
||||
T.Constant(T.K.Int32, "0")),
|
||||
finish_term tIf,
|
||||
finish_term tElse)
|
||||
| S.Swi (v, bs) ->
|
||||
T.Switch (
|
||||
read_tag v,
|
||||
|
|
|
@ -44,5 +44,6 @@ and term =
|
|||
| BinOp of term * binop * term
|
||||
| Print of term
|
||||
| Let of variable * term * term
|
||||
| IfZero of term * term * term
|
||||
|
||||
[@@deriving show { with_path = false }]
|
||||
|
|
|
@ -44,6 +44,12 @@ rule entry = parse
|
|||
{ PRINT }
|
||||
| "rec"
|
||||
{ REC }
|
||||
| "ifzero"
|
||||
{ IFZERO }
|
||||
| "then"
|
||||
{ THEN }
|
||||
| "else"
|
||||
{ ELSE }
|
||||
| "->"
|
||||
{ ARROW }
|
||||
| "="
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
%token<string> IDENT
|
||||
%token<int> INTLITERAL
|
||||
%token FUN IN LET PRINT REC
|
||||
%token IFZERO THEN ELSE
|
||||
%token ARROW EQ LPAREN RPAREN
|
||||
%token<RawLambda.binop> MULOP ADDOP
|
||||
%token EOF
|
||||
|
@ -67,6 +68,9 @@ any_term_:
|
|||
{ Lam (x, t) }
|
||||
| LET mode = recursive x = IDENT EQ t1 = any_term IN t2 = any_term
|
||||
{ Let (mode, x, t1, t2) }
|
||||
| IFZERO expr = any_term THEN tIf = any_term ELSE tElse = any_term
|
||||
{ IfZero (expr, tIf, tElse) }
|
||||
|
||||
|
||||
%inline any_term:
|
||||
t = placed(any_term_)
|
||||
|
|
|
@ -30,6 +30,7 @@ and term_ =
|
|||
| BinOp of term * binop * term
|
||||
| Print of term
|
||||
| Let of recursive * variable * term * term
|
||||
| IfZero of term * term * term
|
||||
|
||||
(* Every abstract syntax tree node of type [term] is annotated with a place,
|
||||
that is, a position in the source code. This allows us to produce a good
|
||||
|
|
|
@ -73,6 +73,7 @@ and term =
|
|||
| Print of value * term
|
||||
| LetVal of variable * value * term
|
||||
| LetBlo of variable * block * term
|
||||
| IfZero of value * term * term
|
||||
|
||||
[@@deriving show { with_path = false }]
|
||||
|
||||
|
@ -130,3 +131,7 @@ and fv_term (t : term) =
|
|||
union
|
||||
(fv_block b1)
|
||||
(remove x (fv_term t2))
|
||||
| IfZero (cond, tIf, tElse) ->
|
||||
union
|
||||
(fv_value cond)
|
||||
(union (fv_term tIf) (fv_term tElse))
|
||||
|
|
|
@ -40,6 +40,7 @@ and term =
|
|||
| Print of value * term
|
||||
| LetVal of variable * value * term
|
||||
| LetBlo of variable * block * term
|
||||
| IfZero of value * term * term
|
||||
| Swi of value * branch list
|
||||
|
||||
(* A branch [tag xs -> t] is labeled with an integer tag [tag], and is
|
||||
|
|
|
@ -21,6 +21,11 @@ and fmt_term fmt (t: S.term) = match t with
|
|||
| S.LetBlo (var, block, next) ->
|
||||
Format.fprintf fmt "@[<v 4>let %a = %a@] in@ %a"
|
||||
fmt_var var fmt_block block fmt_term next
|
||||
| S.IfZero (cond, tIf, tElse) ->
|
||||
Format.fprintf fmt "@[<v 4>ifzero %a then@ %a@]@ @[<v 4>else@ %a@]@ "
|
||||
fmt_val cond
|
||||
fmt_term tIf
|
||||
fmt_term tElse
|
||||
|
||||
let show term =
|
||||
Format.asprintf "@[<v 0>%a@]" fmt_term term
|
||||
|
|
|
@ -28,6 +28,11 @@ let rec fmt_term fmt (term: S.term) = match term with
|
|||
fmt_var name
|
||||
fmt_block block
|
||||
fmt_term next
|
||||
| S.IfZero (cond, tIf, tElse) ->
|
||||
Format.fprintf fmt "@[<v 4>ifzero %a then@ %a@]@ @[<v 4>else@ %a@]"
|
||||
fmt_val cond
|
||||
fmt_term tIf
|
||||
fmt_term tElse
|
||||
| S.Swi (value, branches) ->
|
||||
Format.fprintf fmt "@[<v 4>switch(%a)" fmt_val value ;
|
||||
List.iter
|
||||
|
|
2
src/tests/if_func.exp
Normal file
2
src/tests/if_func.exp
Normal file
|
@ -0,0 +1,2 @@
|
|||
1
|
||||
1
|
26
src/tests/if_func.lambda
Normal file
26
src/tests/if_func.lambda
Normal file
|
@ -0,0 +1,26 @@
|
|||
let i = fun x -> x in
|
||||
let k = fun x -> fun y -> x in
|
||||
let zero = fun f -> i in
|
||||
let one = fun f -> fun x -> f x in
|
||||
let plus = fun m -> fun n -> fun f -> fun x -> m f (n f x) in
|
||||
let succ = plus one in
|
||||
let mult = fun m -> fun n -> fun f -> m (n f) in
|
||||
let exp = fun m -> fun n -> n m in
|
||||
let two = succ one in
|
||||
let three = succ two in
|
||||
let six = mult two three in
|
||||
let seven = succ six in
|
||||
let twenty_one = mult three seven in
|
||||
let forty_two = mult two twenty_one in
|
||||
let convert = fun n -> n (fun x -> x + 1) 0 in
|
||||
|
||||
let nothing =
|
||||
ifzero convert forty_two then
|
||||
print 0
|
||||
else
|
||||
print 1
|
||||
in
|
||||
ifzero convert zero then
|
||||
print 1
|
||||
else
|
||||
print 0
|
2
src/tests/if_func_branch.exp
Normal file
2
src/tests/if_func_branch.exp
Normal file
|
@ -0,0 +1,2 @@
|
|||
1
|
||||
1
|
8
src/tests/if_func_branch.lambda
Normal file
8
src/tests/if_func_branch.lambda
Normal file
|
@ -0,0 +1,8 @@
|
|||
let succeed = fun x -> print 1 in
|
||||
let fail = fun x -> print 0 in
|
||||
|
||||
let true = fun x -> 0 in
|
||||
let false = fun x -> 1 in
|
||||
|
||||
let nothing = ifzero true 0 then succeed 0 else fail 0 in
|
||||
ifzero false 0 then fail 0 else succeed 0
|
1
src/tests/simple_if.exp
Normal file
1
src/tests/simple_if.exp
Normal file
|
@ -0,0 +1 @@
|
|||
1
|
1
src/tests/simple_if.lambda
Normal file
1
src/tests/simple_if.lambda
Normal file
|
@ -0,0 +1 @@
|
|||
ifzero 42 then print 0 else print 1
|
Loading…
Reference in a new issue