refactor: mini_c expression built and access through combinators
This commit is contained in:
parent
0521c3d3b7
commit
eaf749cbc5
@ -73,11 +73,13 @@ and expression' ppf (e:expression') = match e with
|
|||||||
| E_make_none _ -> fprintf ppf "none"
|
| E_make_none _ -> fprintf ppf "none"
|
||||||
| E_Cond (c, a, b) -> fprintf ppf "%a ? %a : %a" expression c expression a expression b
|
| E_Cond (c, a, b) -> fprintf ppf "%a ? %a : %a" expression c expression a expression b
|
||||||
|
|
||||||
and expression ppf (e' , _ , _) = expression' ppf e'
|
and expression : _ -> expression -> _ = fun ppf e ->
|
||||||
|
expression' ppf (Combinators.Expression.get_content e)
|
||||||
and expression_with_type = fun ppf (e' , t , _) ->
|
|
||||||
fprintf ppf "%a : %a" expression' e' type_ t
|
|
||||||
|
|
||||||
|
and expression_with_type : _ -> expression -> _ = fun ppf e ->
|
||||||
|
fprintf ppf "%a : %a"
|
||||||
|
expression' (Combinators.Expression.get_content e)
|
||||||
|
type_ (Combinators.Expression.get_type e)
|
||||||
|
|
||||||
and function_ ppf ({binder ; input ; output ; body ; result ; capture_type}:anon_function_content) =
|
and function_ ppf ({binder ; input ; output ; body ; result ; capture_type}:anon_function_content) =
|
||||||
fprintf ppf "fun[%s] (%s:%a) : %a %a return %a"
|
fprintf ppf "fun[%s] (%s:%a) : %a %a return %a"
|
||||||
|
@ -1,6 +1,30 @@
|
|||||||
open Trace
|
open Trace
|
||||||
open Types
|
open Types
|
||||||
|
|
||||||
|
module Expression = struct
|
||||||
|
type t' = expression'
|
||||||
|
type t = expression
|
||||||
|
|
||||||
|
let get_content : t -> t' = fun e -> e.content
|
||||||
|
let get_type : t -> type_value = fun e -> e.type_value
|
||||||
|
let get_environment : t -> environment = fun e -> e.environment
|
||||||
|
let is_toplevel : t -> bool = fun e -> e.is_toplevel
|
||||||
|
|
||||||
|
let make = fun ?(itl = false) e' t env -> {
|
||||||
|
content = e' ;
|
||||||
|
type_value = t ;
|
||||||
|
environment = env ;
|
||||||
|
is_toplevel = itl ;
|
||||||
|
}
|
||||||
|
|
||||||
|
let make_tpl = fun ?(itl = false) (e' , t , env) -> {
|
||||||
|
content = e' ;
|
||||||
|
type_value = t ;
|
||||||
|
environment = env ;
|
||||||
|
is_toplevel = itl ;
|
||||||
|
}
|
||||||
|
end
|
||||||
|
|
||||||
let get_bool (v:value) = match v with
|
let get_bool (v:value) = match v with
|
||||||
| D_bool b -> ok b
|
| D_bool b -> ok b
|
||||||
| _ -> simple_fail "not a bool"
|
| _ -> simple_fail "not a bool"
|
||||||
@ -93,64 +117,16 @@ let quote binder input output body result : anon_function =
|
|||||||
|
|
||||||
let basic_quote i o b : anon_function result =
|
let basic_quote i o b : anon_function result =
|
||||||
let%bind (_, e) = get_last_statement b in
|
let%bind (_, e) = get_last_statement b in
|
||||||
let r : expression = (E_variable "output", o, e.post_environment) in
|
let r : expression = Expression.make_tpl (E_variable "output", o, e.post_environment) in
|
||||||
ok @@ quote "input" i o b r
|
ok @@ quote "input" i o b r
|
||||||
|
|
||||||
let basic_int_quote b : anon_function result =
|
let basic_int_quote b : anon_function result =
|
||||||
basic_quote t_int t_int b
|
basic_quote t_int t_int b
|
||||||
|
|
||||||
let basic_int_quote_env : environment =
|
let e_int expr env : expression = Expression.make_tpl (expr, t_int, env)
|
||||||
let e = Compiler_environment.empty in
|
|
||||||
Compiler_environment.add ("input", t_int) e
|
|
||||||
|
|
||||||
let e_int expr env : expression = (expr, t_int, env)
|
|
||||||
let e_var_int name env : expression = e_int (E_variable name) env
|
let e_var_int name env : expression = e_int (E_variable name) env
|
||||||
|
|
||||||
let d_unit : value = D_unit
|
let d_unit : value = D_unit
|
||||||
|
|
||||||
let environment_wrap pre_environment post_environment = { pre_environment ; post_environment }
|
let environment_wrap pre_environment post_environment = { pre_environment ; post_environment }
|
||||||
let id_environment_wrap e = environment_wrap e e
|
let id_environment_wrap e = environment_wrap e e
|
||||||
|
|
||||||
let statement s' e : statement =
|
|
||||||
match s' with
|
|
||||||
| S_environment_extend -> s', environment_wrap e (Compiler_environment.extend e)
|
|
||||||
| S_environment_restrict -> s', environment_wrap e (Compiler_environment.restrict e)
|
|
||||||
| S_environment_add (name, tv) -> s', environment_wrap e (Compiler_environment.add (name, tv) e)
|
|
||||||
| S_cond _ -> s', id_environment_wrap e
|
|
||||||
| S_if_none _ -> s', id_environment_wrap e
|
|
||||||
| S_while _ -> s', id_environment_wrap e
|
|
||||||
| S_patch _ -> s', id_environment_wrap e
|
|
||||||
| S_declaration (name, (_, t, _)) -> s', environment_wrap e (Compiler_environment.add (name, t) e)
|
|
||||||
| S_assignment (name, (_, t, _)) -> s', environment_wrap e (Compiler_environment.add (name, t) e)
|
|
||||||
|
|
||||||
let block (statements:statement list) : block result =
|
|
||||||
match statements with
|
|
||||||
| [] -> simple_fail "no statements in block"
|
|
||||||
| lst ->
|
|
||||||
let first = List.hd lst in
|
|
||||||
let last = List.(nth lst (length lst - 1)) in
|
|
||||||
ok (lst, environment_wrap (snd first).pre_environment (snd last).post_environment)
|
|
||||||
|
|
||||||
let append_statement' : block -> statement' -> block = fun b s' ->
|
|
||||||
let b_wrap = snd b in
|
|
||||||
let s = statement s' b_wrap.post_environment in
|
|
||||||
let s_wrap = snd s in
|
|
||||||
let b_wrap' = { b_wrap with post_environment = s_wrap.post_environment } in
|
|
||||||
let b_content = fst b in
|
|
||||||
(b_content @ [s], b_wrap')
|
|
||||||
|
|
||||||
let prepend_statement : statement -> block -> block = fun s b ->
|
|
||||||
let s_wrap = snd s in
|
|
||||||
let b_wrap = snd b in
|
|
||||||
let b_wrap' = { b_wrap with pre_environment = s_wrap.pre_environment } in
|
|
||||||
let b_content = fst b in
|
|
||||||
(s :: b_content, b_wrap')
|
|
||||||
|
|
||||||
let statements (lst:(environment -> statement) list) e : statement list =
|
|
||||||
let rec aux lst e = match lst with
|
|
||||||
| [] -> []
|
|
||||||
| hd :: tl ->
|
|
||||||
let s = hd e in
|
|
||||||
s :: aux tl (snd s).post_environment
|
|
||||||
in
|
|
||||||
aux lst e
|
|
||||||
|
51
src/ligo/mini_c/combinators_smart.ml
Normal file
51
src/ligo/mini_c/combinators_smart.ml
Normal file
@ -0,0 +1,51 @@
|
|||||||
|
open Trace
|
||||||
|
open Types
|
||||||
|
open Combinators
|
||||||
|
|
||||||
|
let basic_int_quote_env : environment =
|
||||||
|
let e = Compiler_environment.empty in
|
||||||
|
Compiler_environment.add ("input", t_int) e
|
||||||
|
|
||||||
|
let statement s' env : statement =
|
||||||
|
match s' with
|
||||||
|
| S_environment_extend -> s', environment_wrap env (Compiler_environment.extend env)
|
||||||
|
| S_environment_restrict -> s', environment_wrap env (Compiler_environment.restrict env)
|
||||||
|
| S_environment_add (name, tv) -> s' , environment_wrap env (Compiler_environment.add (name , tv) env)
|
||||||
|
| S_cond _ -> s' , id_environment_wrap env
|
||||||
|
| S_if_none _ -> s' , id_environment_wrap env
|
||||||
|
| S_while _ -> s' , id_environment_wrap env
|
||||||
|
| S_patch _ -> s' , id_environment_wrap env
|
||||||
|
| S_declaration (name , e) -> s', environment_wrap env (Compiler_environment.add (name , (Expression.get_type e)) env)
|
||||||
|
| S_assignment (name , e) -> s', environment_wrap env (Compiler_environment.add (name , (Expression.get_type e)) env)
|
||||||
|
|
||||||
|
let block (statements:statement list) : block result =
|
||||||
|
match statements with
|
||||||
|
| [] -> simple_fail "no statements in block"
|
||||||
|
| lst ->
|
||||||
|
let first = List.hd lst in
|
||||||
|
let last = List.(nth lst (length lst - 1)) in
|
||||||
|
ok (lst, environment_wrap (snd first).pre_environment (snd last).post_environment)
|
||||||
|
|
||||||
|
let append_statement' : block -> statement' -> block = fun b s' ->
|
||||||
|
let b_wrap = snd b in
|
||||||
|
let s = statement s' b_wrap.post_environment in
|
||||||
|
let s_wrap = snd s in
|
||||||
|
let b_wrap' = { b_wrap with post_environment = s_wrap.post_environment } in
|
||||||
|
let b_content = fst b in
|
||||||
|
(b_content @ [s], b_wrap')
|
||||||
|
|
||||||
|
let prepend_statement : statement -> block -> block = fun s b ->
|
||||||
|
let s_wrap = snd s in
|
||||||
|
let b_wrap = snd b in
|
||||||
|
let b_wrap' = { b_wrap with pre_environment = s_wrap.pre_environment } in
|
||||||
|
let b_content = fst b in
|
||||||
|
(s :: b_content, b_wrap')
|
||||||
|
|
||||||
|
let statements (lst:(environment -> statement) list) e : statement list =
|
||||||
|
let rec aux lst e = match lst with
|
||||||
|
| [] -> []
|
||||||
|
| hd :: tl ->
|
||||||
|
let s = hd e in
|
||||||
|
s :: aux tl (snd s).post_environment
|
||||||
|
in
|
||||||
|
aux lst e
|
@ -55,8 +55,8 @@ let rec get_predicate : string -> expression list -> predicate result = fun s ls
|
|||||||
(* | "CONS" -> ok @@ simple_binary @@ seq [prim I_SWAP ; prim I_CONS] *)
|
(* | "CONS" -> ok @@ simple_binary @@ seq [prim I_SWAP ; prim I_CONS] *)
|
||||||
| "MAP_REMOVE" ->
|
| "MAP_REMOVE" ->
|
||||||
let%bind v = match lst with
|
let%bind v = match lst with
|
||||||
| [ _ ; (_, m, _) ] ->
|
| [ _ ; expr ] ->
|
||||||
let%bind (_, v) = Combinators.get_t_map m in
|
let%bind (_, v) = Combinators.(get_t_map (Expression.get_type expr)) in
|
||||||
ok v
|
ok v
|
||||||
| _ -> simple_fail "mini_c . MAP_REMOVE" in
|
| _ -> simple_fail "mini_c . MAP_REMOVE" in
|
||||||
let%bind v_ty = Compiler_type.type_ v in
|
let%bind v_ty = Compiler_type.type_ v in
|
||||||
@ -113,7 +113,8 @@ and translate_function ({capture;content}:anon_function) : michelson result =
|
|||||||
ok @@ d_pair capture_m body
|
ok @@ d_pair capture_m body
|
||||||
| _ -> simple_fail "compiling closure without capture"
|
| _ -> simple_fail "compiling closure without capture"
|
||||||
|
|
||||||
and translate_expression ((expr', ty, env) as expr:expression) : michelson result =
|
and translate_expression (expr:expression) : michelson result =
|
||||||
|
let (expr' , ty , env) = Combinators.Expression.(get_content expr , get_type expr , get_environment expr) in
|
||||||
let error_message () = Format.asprintf "%a" PP.expression expr in
|
let error_message () = Format.asprintf "%a" PP.expression expr in
|
||||||
|
|
||||||
let return code =
|
let return code =
|
||||||
@ -157,8 +158,8 @@ and translate_expression ((expr', ty, env) as expr:expression) : michelson resul
|
|||||||
prim ~children:[t;v] I_PUSH ;
|
prim ~children:[t;v] I_PUSH ;
|
||||||
prim I_PAIR ;
|
prim I_PAIR ;
|
||||||
]
|
]
|
||||||
| E_application((_, f_ty, _) as f, arg) -> (
|
| E_application(f, arg) -> (
|
||||||
match f_ty with
|
match Combinators.Expression.get_type f with
|
||||||
| T_function _ -> (
|
| T_function _ -> (
|
||||||
trace (simple_error "Compiling quote application") @@
|
trace (simple_error "Compiling quote application") @@
|
||||||
let%bind f = translate_expression f in
|
let%bind f = translate_expression f in
|
||||||
@ -259,22 +260,22 @@ and translate_expression ((expr', ty, env) as expr:expression) : michelson resul
|
|||||||
i_pair ;
|
i_pair ;
|
||||||
] in
|
] in
|
||||||
return code
|
return code
|
||||||
| Deep_capture small_env ->
|
| Deep_capture _small_env -> simple_fail "no deep capture expression yet"
|
||||||
(* Capture the variable bounds, assemble them. On call, append the input. *)
|
(* (\* Capture the variable bounds, assemble them. On call, append the input. *\)
|
||||||
let senv_type = Compiler_environment.Small.to_mini_c_type small_env in
|
* let senv_type = Compiler_environment.Small.to_mini_c_type small_env in
|
||||||
let%bind body = translate_closure_body anon senv_type in
|
* let%bind body = translate_closure_body anon senv_type in
|
||||||
let%bind capture = Environment.Small.to_mini_c_capture env small_env in
|
* let%bind capture = Environment.Small.to_mini_c_capture env small_env in
|
||||||
let%bind capture = translate_expression capture in
|
* let%bind capture = translate_expression capture in
|
||||||
let%bind input_type = Compiler_type.type_ anon.input in
|
* let%bind input_type = Compiler_type.type_ anon.input in
|
||||||
let%bind output_type = Compiler_type.type_ anon.output in
|
* let%bind output_type = Compiler_type.type_ anon.output in
|
||||||
let code = seq [
|
* let code = seq [
|
||||||
capture ;
|
* capture ;
|
||||||
i_unpair ;
|
* i_unpair ;
|
||||||
i_lambda input_type output_type body ;
|
* i_lambda input_type output_type body ;
|
||||||
i_piar ;
|
* i_piar ;
|
||||||
i_pair ;
|
* i_pair ;
|
||||||
] in
|
* ] in
|
||||||
return code
|
* return code *)
|
||||||
| Shallow_capture env ->
|
| Shallow_capture env ->
|
||||||
(* Capture the whole environment. *)
|
(* Capture the whole environment. *)
|
||||||
let env_type = Compiler_environment.to_mini_c_type env in
|
let env_type = Compiler_environment.to_mini_c_type env in
|
||||||
@ -330,7 +331,8 @@ and translate_statement ((s', w_env) as s:statement) : michelson result =
|
|||||||
simple_fail "not ready yet"
|
simple_fail "not ready yet"
|
||||||
(* | S_environment_add (name, tv) ->
|
(* | S_environment_add (name, tv) ->
|
||||||
* Environment.to_michelson_add (name, tv) w_env.pre_environment *)
|
* Environment.to_michelson_add (name, tv) w_env.pre_environment *)
|
||||||
| S_declaration (s, ((_, tv, _) as expr)) ->
|
| S_declaration (s, expr) ->
|
||||||
|
let tv = Combinators.Expression.get_type expr in
|
||||||
let%bind expr = translate_expression expr in
|
let%bind expr = translate_expression expr in
|
||||||
let%bind add = Environment.to_michelson_add (s, tv) w_env.pre_environment in
|
let%bind add = Environment.to_michelson_add (s, tv) w_env.pre_environment in
|
||||||
ok (seq [
|
ok (seq [
|
||||||
@ -382,7 +384,7 @@ and translate_statement ((s', w_env) as s:statement) : michelson result =
|
|||||||
seq [add ; some'] ;
|
seq [add ; some'] ;
|
||||||
] I_IF_NONE
|
] I_IF_NONE
|
||||||
])
|
])
|
||||||
| S_while ((_, _, _) as expr, block) ->
|
| S_while (expr, block) ->
|
||||||
let%bind expr = translate_expression expr in
|
let%bind expr = translate_expression expr in
|
||||||
let%bind block' = translate_regular_block block in
|
let%bind block' = translate_regular_block block in
|
||||||
let%bind restrict_block =
|
let%bind restrict_block =
|
||||||
@ -540,12 +542,12 @@ type compiled_program = {
|
|||||||
}
|
}
|
||||||
|
|
||||||
let translate_program (p:program) (entry:string) : compiled_program result =
|
let translate_program (p:program) (entry:string) : compiled_program result =
|
||||||
let is_main ((s, _):toplevel_statement) =
|
let is_main (((name , expr), _):toplevel_statement) =
|
||||||
match s with
|
match Combinators.Expression.(get_content expr , get_type expr)with
|
||||||
| name , (E_function f, T_function (_, _), _)
|
| (E_function f , T_function _)
|
||||||
when f.capture_type = No_capture && name = entry ->
|
when f.capture_type = No_capture && name = entry ->
|
||||||
Some f
|
Some f
|
||||||
| name , (E_literal (D_function {content ; capture = None}), T_function (_, _), _)
|
| (E_literal (D_function {content ; capture = None}) , T_function _)
|
||||||
when name = entry ->
|
when name = entry ->
|
||||||
Some content
|
Some content
|
||||||
| _ -> None
|
| _ -> None
|
||||||
|
@ -117,16 +117,16 @@ module Small = struct
|
|||||||
| Empty -> ok (dip i_drop)
|
| Empty -> ok (dip i_drop)
|
||||||
| Full x -> to_michelson_append' x
|
| Full x -> to_michelson_append' x
|
||||||
|
|
||||||
let rec to_mini_c_capture' env : _ -> expression result = function
|
(* let rec to_mini_c_capture' env : _ -> expression result = function
|
||||||
| Leaf (n, tv) -> ok (E_variable n, tv, env)
|
* | Leaf (n, tv) -> ok (E_variable n, tv, env)
|
||||||
| Node {a;b} ->
|
* | Node {a;b} ->
|
||||||
let%bind ((_, ty_a, _) as a) = to_mini_c_capture' env a in
|
* let%bind ((_, ty_a, _) as a) = to_mini_c_capture' env a in
|
||||||
let%bind ((_, ty_b, _) as b) = to_mini_c_capture' env b in
|
* let%bind ((_, ty_b, _) as b) = to_mini_c_capture' env b in
|
||||||
ok (E_constant ("PAIR", [a;b]), (T_pair(ty_a, ty_b) : type_value), env)
|
* ok (E_constant ("PAIR", [a;b]), (T_pair(ty_a, ty_b) : type_value), env)
|
||||||
|
*
|
||||||
let to_mini_c_capture env = function
|
* let to_mini_c_capture env = function
|
||||||
| Empty -> simple_fail "to_mini_c_capture"
|
* | Empty -> simple_fail "to_mini_c_capture"
|
||||||
| Full x -> to_mini_c_capture' env x
|
* | Full x -> to_mini_c_capture' env x *)
|
||||||
|
|
||||||
let rec to_mini_c_type' : _ -> type_value = function
|
let rec to_mini_c_type' : _ -> type_value = function
|
||||||
| Leaf (_, t) -> t
|
| Leaf (_, t) -> t
|
||||||
@ -183,9 +183,9 @@ let rec to_mini_c_type = function
|
|||||||
| [hd] -> Small.to_mini_c_type hd
|
| [hd] -> Small.to_mini_c_type hd
|
||||||
| Append_tree.Empty :: tl -> to_mini_c_type tl
|
| Append_tree.Empty :: tl -> to_mini_c_type tl
|
||||||
| hd :: tl -> T_pair(Small.to_mini_c_type hd, to_mini_c_type tl)
|
| hd :: tl -> T_pair(Small.to_mini_c_type hd, to_mini_c_type tl)
|
||||||
let to_mini_c_capture = function
|
(* let to_mini_c_capture = function
|
||||||
| [a] -> Small.to_mini_c_capture a
|
* | [a] -> Small.to_mini_c_capture a
|
||||||
| _ -> raise (Failure "Schema.Big.to_mini_c_capture")
|
* | _ -> raise (Failure "Schema.Big.to_mini_c_capture") *)
|
||||||
|
|
||||||
type path = [`Left | `Right] list
|
type path = [`Left | `Right] list
|
||||||
let pp_path : _ -> path -> unit =
|
let pp_path : _ -> path -> unit =
|
||||||
|
@ -8,5 +8,5 @@
|
|||||||
(preprocess
|
(preprocess
|
||||||
(pps ppx_let)
|
(pps ppx_let)
|
||||||
)
|
)
|
||||||
(flags (:standard -w +1..62-4-9-44-40-42-48@39@33 -open Tezos_utils ))
|
(flags (:standard -w +1..62-4-9-44-40-42-48-30@39@33 -open Tezos_utils ))
|
||||||
)
|
)
|
||||||
|
@ -1,7 +1,10 @@
|
|||||||
include Types
|
include Types
|
||||||
|
|
||||||
module PP = PP
|
module PP = PP
|
||||||
module Combinators = Combinators
|
module Combinators = struct
|
||||||
|
include Combinators
|
||||||
|
include Combinators_smart
|
||||||
|
end
|
||||||
module Environment = Compiler_environment
|
module Environment = Compiler_environment
|
||||||
module Compiler_type = Compiler_type
|
module Compiler_type = Compiler_type
|
||||||
module Compiler = Compiler
|
module Compiler = Compiler
|
||||||
|
@ -51,8 +51,8 @@ let run (program:program) (input:value) : value result =
|
|||||||
let%bind (result : value) = Uncompiler.translate_value ex_ty_value in
|
let%bind (result : value) = Uncompiler.translate_value ex_ty_value in
|
||||||
ok result
|
ok result
|
||||||
|
|
||||||
let expression_to_value ((e', _, _) as e:expression) : value result =
|
let expression_to_value (e:expression) : value result =
|
||||||
match e' with
|
match (Combinators.Expression.get_content e) with
|
||||||
| E_literal v -> ok v
|
| E_literal v -> ok v
|
||||||
| _ -> fail
|
| _ -> fail
|
||||||
@@ error (thunk "not a value")
|
@@ error (thunk "not a value")
|
||||||
|
@ -65,7 +65,12 @@ and expression' =
|
|||||||
| E_make_none of type_value
|
| E_make_none of type_value
|
||||||
| E_Cond of expression * expression * expression
|
| E_Cond of expression * expression * expression
|
||||||
|
|
||||||
and expression = expression' * type_value * environment (* Environment in which the expressions are evaluated *)
|
and expression = {
|
||||||
|
content : expression' ;
|
||||||
|
type_value : type_value ;
|
||||||
|
environment : environment ; (* Environment in which the expressions are evaluated *)
|
||||||
|
is_toplevel : bool ;
|
||||||
|
}
|
||||||
|
|
||||||
and assignment = var_name * expression
|
and assignment = var_name * expression
|
||||||
|
|
||||||
|
@ -118,8 +118,8 @@ and translate_instruction (env:Environment.t) (i:AST.instruction) : statement li
|
|||||||
let return ?(env' = env) x : statement list result = ok ([x, environment_wrap env env']) in
|
let return ?(env' = env) x : statement list result = ok ([x, environment_wrap env env']) in
|
||||||
match i with
|
match i with
|
||||||
| I_declaration {name;annotated_expression} ->
|
| I_declaration {name;annotated_expression} ->
|
||||||
let%bind (_, t, _) as expression = translate_annotated_expression env annotated_expression in
|
let%bind expression = translate_annotated_expression env annotated_expression in
|
||||||
let env' = Environment.add (name, t) env in
|
let env' = Environment.add (name, (Combinators.Expression.get_type expression)) env in
|
||||||
return ~env' (S_declaration (name, expression))
|
return ~env' (S_declaration (name, expression))
|
||||||
| I_assignment {name;annotated_expression} ->
|
| I_assignment {name;annotated_expression} ->
|
||||||
let%bind expression = translate_annotated_expression env annotated_expression in
|
let%bind expression = translate_annotated_expression env annotated_expression in
|
||||||
@ -179,62 +179,67 @@ and translate_instruction (env:Environment.t) (i:AST.instruction) : statement li
|
|||||||
| I_skip -> ok []
|
| I_skip -> ok []
|
||||||
| I_fail _ -> simple_fail "todo : fail"
|
| I_fail _ -> simple_fail "todo : fail"
|
||||||
|
|
||||||
|
and translate_literal : AST.literal -> value = fun l -> match l with
|
||||||
|
| Literal_bool b -> D_bool b
|
||||||
|
| Literal_int n -> D_int n
|
||||||
|
| Literal_nat n -> D_nat n
|
||||||
|
| Literal_bytes s -> D_bytes s
|
||||||
|
| Literal_string s -> D_string s
|
||||||
|
| Literal_unit -> D_unit
|
||||||
|
|
||||||
and translate_annotated_expression (env:Environment.t) (ae:AST.annotated_expression) : expression result =
|
and translate_annotated_expression (env:Environment.t) (ae:AST.annotated_expression) : expression result =
|
||||||
let%bind tv = translate_type ae.type_annotation in
|
let%bind tv = translate_type ae.type_annotation in
|
||||||
let return (expr, tv) = ok (expr, tv, env) in
|
let return ?(tv = tv) expr = ok @@ Combinators.Expression.make_tpl (expr, tv, env) in
|
||||||
let f = translate_annotated_expression env in
|
let f = translate_annotated_expression env in
|
||||||
match ae.expression with
|
match ae.expression with
|
||||||
| E_literal (Literal_bool b) -> ok (E_literal (D_bool b), tv, env)
|
| E_literal l -> return @@ E_literal (translate_literal l)
|
||||||
| E_literal (Literal_int n) -> ok (E_literal (D_int n), tv, env)
|
|
||||||
| E_literal (Literal_nat n) -> ok (E_literal (D_nat n), tv, env)
|
|
||||||
| E_literal (Literal_bytes s) -> ok (E_literal (D_bytes s), tv, env)
|
|
||||||
| E_literal (Literal_string s) -> ok (E_literal (D_string s), tv, env)
|
|
||||||
| E_literal Literal_unit -> ok (E_literal D_unit, tv, env)
|
|
||||||
| E_variable name ->
|
| E_variable name ->
|
||||||
let%bind tv =
|
let%bind tv =
|
||||||
trace_option (simple_error "transpiler: variable not in env") @@
|
trace_option (simple_error "transpiler: variable not in env") @@
|
||||||
Environment.get_opt env name in
|
Environment.get_opt env name in
|
||||||
ok (E_variable name, tv, env)
|
return ~tv @@ E_variable name
|
||||||
| E_application (a, b) ->
|
| E_application (a, b) ->
|
||||||
let%bind a = translate_annotated_expression env a in
|
let%bind a = translate_annotated_expression env a in
|
||||||
let%bind b = translate_annotated_expression env b in
|
let%bind b = translate_annotated_expression env b in
|
||||||
ok (E_application (a, b), tv, env)
|
return @@ E_application (a, b)
|
||||||
| E_constructor (m, param) ->
|
| E_constructor (m, param) ->
|
||||||
let%bind (param'_expr, param'_tv, _) = translate_annotated_expression env ae in
|
let%bind param' = translate_annotated_expression env ae in
|
||||||
|
let (param'_expr , param'_tv) = Combinators.Expression.(get_content param' , get_type param') in
|
||||||
let%bind map_tv = get_t_sum ae.type_annotation in
|
let%bind map_tv = get_t_sum ae.type_annotation in
|
||||||
let node_tv = Append_tree.of_list @@ kv_list_of_map map_tv in
|
let node_tv = Append_tree.of_list @@ kv_list_of_map map_tv in
|
||||||
let%bind ae' =
|
let leaf (k, tv) : (expression' option * type_value) result =
|
||||||
let leaf (k, tv) : (expression' option * type_value) result =
|
if k = m then (
|
||||||
if k = m then (
|
let%bind _ =
|
||||||
let%bind _ =
|
trace (simple_error "constructor parameter doesn't have expected type (shouldn't happen here)")
|
||||||
trace (simple_error "constructor parameter doesn't have expected type (shouldn't happen here)")
|
@@ AST.assert_type_value_eq (tv, param.type_annotation) in
|
||||||
@@ AST.assert_type_value_eq (tv, param.type_annotation) in
|
ok (Some (param'_expr), param'_tv)
|
||||||
ok (Some (param'_expr), param'_tv)
|
) else (
|
||||||
) else (
|
let%bind tv = translate_type tv in
|
||||||
let%bind tv = translate_type tv in
|
ok (None, tv)
|
||||||
ok (None, tv)
|
) in
|
||||||
) in
|
let node a b : (expression' option * type_value) result =
|
||||||
let node a b : (expression' option * type_value) result =
|
let%bind a = a in
|
||||||
let%bind a = a in
|
let%bind b = b in
|
||||||
let%bind b = b in
|
match (a, b) with
|
||||||
match (a, b) with
|
| (None, a), (None, b) -> ok (None, T_or (a, b))
|
||||||
| (None, a), (None, b) -> ok (None, T_or (a, b))
|
| (Some _, _), (Some _, _) -> simple_fail "several identical constructors in the same variant (shouldn't happen here)"
|
||||||
| (Some _, _), (Some _, _) -> simple_fail "several identical constructors in the same variant (shouldn't happen here)"
|
| (Some v, a), (None, b) -> ok (Some (E_constant ("LEFT", [Combinators.Expression.make_tpl (v, a, env)])), T_or (a, b))
|
||||||
| (Some v, a), (None, b) -> ok (Some (E_constant ("LEFT", [v, a, env])), T_or (a, b))
|
| (None, a), (Some v, b) -> ok (Some (E_constant ("RIGHT", [Combinators.Expression.make_tpl (v, b, env)])), T_or (a, b))
|
||||||
| (None, a), (Some v, b) -> ok (Some (E_constant ("RIGHT", [v, b, env])), T_or (a, b))
|
in
|
||||||
in
|
let%bind (ae_opt, tv) = Append_tree.fold_ne leaf node node_tv in
|
||||||
let%bind (ae_opt, tv) = Append_tree.fold_ne leaf node node_tv in
|
let%bind ae =
|
||||||
let%bind ae =
|
trace_option (simple_error "constructor doesn't exist in claimed type (shouldn't happen here)")
|
||||||
trace_option (simple_error "constructor doesn't exist in claimed type (shouldn't happen here)")
|
ae_opt in
|
||||||
ae_opt in
|
return ~tv ae
|
||||||
ok (ae, tv, env) in
|
|
||||||
ok ae'
|
|
||||||
| E_tuple lst ->
|
| E_tuple lst ->
|
||||||
let node = Append_tree.of_list lst in
|
let node = Append_tree.of_list lst in
|
||||||
let aux (a:expression result) (b:expression result) : expression result =
|
let aux (a:expression result) (b:expression result) : expression result =
|
||||||
let%bind (_, a_ty, _) as a = a in
|
let%bind a = a in
|
||||||
let%bind (_, b_ty, _) as b = b in
|
let%bind b = b in
|
||||||
ok (E_constant ("PAIR", [a; b]), T_pair(a_ty, b_ty), env)
|
let a_ty = Combinators.Expression.get_type a in
|
||||||
|
let b_ty = Combinators.Expression.get_type b in
|
||||||
|
let tv = T_pair (a_ty , b_ty) in
|
||||||
|
return ~tv @@ E_constant ("PAIR", [a; b])
|
||||||
in
|
in
|
||||||
Append_tree.fold_ne (translate_annotated_expression env) aux node
|
Append_tree.fold_ne (translate_annotated_expression env) aux node
|
||||||
| E_tuple_accessor (tpl, ind) ->
|
| E_tuple_accessor (tpl, ind) ->
|
||||||
@ -246,22 +251,31 @@ and translate_annotated_expression (env:Environment.t) (ae:AST.annotated_express
|
|||||||
let c = match lr with
|
let c = match lr with
|
||||||
| `Left -> "CAR"
|
| `Left -> "CAR"
|
||||||
| `Right -> "CDR" in
|
| `Right -> "CDR" in
|
||||||
E_constant (c, [pred]), ty, env in
|
Combinators.Expression.make_tpl (E_constant (c, [pred]) , ty , env) in
|
||||||
let%bind tpl' = translate_annotated_expression env tpl in
|
let%bind tpl' = translate_annotated_expression env tpl in
|
||||||
let expr = List.fold_left aux tpl' path in
|
let expr = List.fold_left aux tpl' path in
|
||||||
ok expr
|
ok expr
|
||||||
| E_record m ->
|
| E_record m ->
|
||||||
let node = Append_tree.of_list @@ list_of_map m in
|
let node = Append_tree.of_list @@ list_of_map m in
|
||||||
let aux a b : expression result =
|
let aux a b : expression result =
|
||||||
let%bind (_, a_ty, _) as a = a in
|
let%bind a = a in
|
||||||
let%bind (_, b_ty, _) as b = b in
|
let%bind b = b in
|
||||||
ok (E_constant ("PAIR", [a; b]), T_pair(a_ty, b_ty), env)
|
let a_ty = Combinators.Expression.get_type a in
|
||||||
|
let b_ty = Combinators.Expression.get_type b in
|
||||||
|
let tv = T_pair (a_ty , b_ty) in
|
||||||
|
return ~tv @@ E_constant ("PAIR", [a; b])
|
||||||
in
|
in
|
||||||
Append_tree.fold_ne (translate_annotated_expression env) aux node
|
Append_tree.fold_ne (translate_annotated_expression env) aux node
|
||||||
| E_record_accessor (record, property) ->
|
| E_record_accessor (record, property) ->
|
||||||
let%bind translation = translate_annotated_expression env record in
|
let%bind translation = translate_annotated_expression env record in
|
||||||
let%bind record_type_map =
|
let%bind record_type_map =
|
||||||
trace (simple_error (Format.asprintf "Accessing field of %a, that has type %a, which isn't a record" AST.PP.annotated_expression record AST.PP.type_value record.type_annotation)) @@
|
let error =
|
||||||
|
let title () =
|
||||||
|
Format.asprintf "Accessing field of %a, that has type %a, which isn't a record"
|
||||||
|
AST.PP.annotated_expression record AST.PP.type_value record.type_annotation in
|
||||||
|
let content () = "" in
|
||||||
|
error title content in
|
||||||
|
trace error @@
|
||||||
get_t_record record.type_annotation in
|
get_t_record record.type_annotation in
|
||||||
let node_tv = Append_tree.of_list @@ kv_list_of_map record_type_map in
|
let node_tv = Append_tree.of_list @@ kv_list_of_map record_type_map in
|
||||||
let leaf (key, _) : expression result =
|
let leaf (key, _) : expression result =
|
||||||
@ -272,13 +286,13 @@ and translate_annotated_expression (env:Environment.t) (ae:AST.annotated_express
|
|||||||
) in
|
) in
|
||||||
let node (a:expression result) b : expression result =
|
let node (a:expression result) b : expression result =
|
||||||
match%bind bind_lr (a, b) with
|
match%bind bind_lr (a, b) with
|
||||||
| `Left ((_, t, env) as ex) -> (
|
| `Left expr -> (
|
||||||
let%bind (a, _) = get_t_pair t in
|
let%bind (tv, _) = get_t_pair @@ Combinators.Expression.get_type expr in
|
||||||
ok (E_constant ("CAR", [ex]), a, env)
|
return ~tv @@ E_constant ("CAR", [expr])
|
||||||
)
|
)
|
||||||
| `Right ((_, t, env) as ex) -> (
|
| `Right expr -> (
|
||||||
let%bind (_, b) = get_t_pair t in
|
let%bind (_, tv) = get_t_pair @@ Combinators.Expression.get_type expr in
|
||||||
ok (E_constant ("CDR", [ex]), b, env)
|
return ~tv @@ E_constant ("CDR", [expr])
|
||||||
) in
|
) in
|
||||||
let%bind expr =
|
let%bind expr =
|
||||||
trace_strong (simple_error "bad key in record (shouldn't happen here)") @@
|
trace_strong (simple_error "bad key in record (shouldn't happen here)") @@
|
||||||
@ -289,16 +303,16 @@ and translate_annotated_expression (env:Environment.t) (ae:AST.annotated_express
|
|||||||
match name, lst with
|
match name, lst with
|
||||||
| "NONE", [] ->
|
| "NONE", [] ->
|
||||||
let%bind o = Mini_c.Combinators.get_t_option tv in
|
let%bind o = Mini_c.Combinators.get_t_option tv in
|
||||||
ok (E_make_none o, tv, env)
|
return @@ E_make_none o
|
||||||
| _ -> ok (E_constant (name, lst'), tv, env)
|
| _ -> return @@ E_constant (name, lst')
|
||||||
)
|
)
|
||||||
| E_lambda l -> translate_lambda env l
|
| E_lambda l -> translate_lambda env l
|
||||||
| E_list lst ->
|
| E_list lst ->
|
||||||
let%bind t = Mini_c.Combinators.get_t_list tv in
|
let%bind t = Mini_c.Combinators.get_t_list tv in
|
||||||
let%bind lst' = bind_map_list (translate_annotated_expression env) lst in
|
let%bind lst' = bind_map_list (translate_annotated_expression env) lst in
|
||||||
let aux : expression -> expression -> expression result = fun prev cur ->
|
let aux : expression -> expression -> expression result = fun prev cur ->
|
||||||
return (E_constant ("CONS", [cur ; prev]), tv) in
|
return @@ E_constant ("CONS", [cur ; prev]) in
|
||||||
let%bind (init : expression) = return (E_empty_list t, tv) in
|
let%bind (init : expression) = return @@ E_empty_list t in
|
||||||
bind_fold_list aux init lst'
|
bind_fold_list aux init lst'
|
||||||
| E_map m ->
|
| E_map m ->
|
||||||
let%bind (src, dst) = Mini_c.Combinators.get_t_map tv in
|
let%bind (src, dst) = Mini_c.Combinators.get_t_map tv in
|
||||||
@ -307,19 +321,19 @@ and translate_annotated_expression (env:Environment.t) (ae:AST.annotated_express
|
|||||||
let%bind (k', v') =
|
let%bind (k', v') =
|
||||||
let v' = e_a_some v in
|
let v' = e_a_some v in
|
||||||
bind_map_pair (translate_annotated_expression env) (k, v') in
|
bind_map_pair (translate_annotated_expression env) (k, v') in
|
||||||
return (E_constant ("UPDATE", [k' ; v' ; prev']), tv)
|
return @@ E_constant ("UPDATE", [k' ; v' ; prev'])
|
||||||
in
|
in
|
||||||
let init = return (E_empty_map (src, dst), tv) in
|
let init = return @@ E_empty_map (src, dst) in
|
||||||
List.fold_left aux init m
|
List.fold_left aux init m
|
||||||
| E_look_up dsi ->
|
| E_look_up dsi ->
|
||||||
let%bind (ds', i') = bind_map_pair f dsi in
|
let%bind (ds', i') = bind_map_pair f dsi in
|
||||||
return (E_constant ("GET", [i' ; ds']), tv)
|
return @@ E_constant ("GET", [i' ; ds'])
|
||||||
| E_matching (expr, m) -> (
|
| E_matching (expr, m) -> (
|
||||||
let%bind expr' = translate_annotated_expression env expr in
|
let%bind expr' = translate_annotated_expression env expr in
|
||||||
match m with
|
match m with
|
||||||
| AST.Match_bool {match_true ; match_false} ->
|
| AST.Match_bool {match_true ; match_false} ->
|
||||||
let%bind (t, f) = bind_map_pair (translate_annotated_expression env) (match_true, match_false) in
|
let%bind (t, f) = bind_map_pair (translate_annotated_expression env) (match_true, match_false) in
|
||||||
return (E_Cond (expr', t, f), tv)
|
return @@ E_Cond (expr', t, f)
|
||||||
| AST.Match_list _ | AST.Match_option _ | AST.Match_tuple (_, _) ->
|
| AST.Match_list _ | AST.Match_option _ | AST.Match_tuple (_, _) ->
|
||||||
simple_fail "only match bool exprs are translated yet"
|
simple_fail "only match bool exprs are translated yet"
|
||||||
)
|
)
|
||||||
@ -336,7 +350,7 @@ and translate_lambda_shallow : Mini_c.Environment.t -> AST.lambda -> Mini_c.expr
|
|||||||
let%bind output_type' = translate_type output_type in
|
let%bind output_type' = translate_type output_type in
|
||||||
let tv = Combinators.t_shallow_closure env input_type' output_type' in
|
let tv = Combinators.t_shallow_closure env input_type' output_type' in
|
||||||
let content = {binder;input=input_type';output=output_type';body;result;capture_type} in
|
let content = {binder;input=input_type';output=output_type';body;result;capture_type} in
|
||||||
ok (E_function content, tv, env)
|
ok @@ Combinators.Expression.make_tpl (E_function content, tv, env)
|
||||||
|
|
||||||
and translate_lambda env l =
|
and translate_lambda env l =
|
||||||
let { binder ; input_type ; output_type ; body ; result } : AST.lambda = l in
|
let { binder ; input_type ; output_type ; body ; result } : AST.lambda = l in
|
||||||
@ -359,7 +373,7 @@ and translate_lambda env l =
|
|||||||
let%bind output = translate_type output_type in
|
let%bind output = translate_type output_type in
|
||||||
let tv = Combinators.t_function input output in
|
let tv = Combinators.t_function input output in
|
||||||
let content = {binder;input;output;body=body';result=result';capture_type} in
|
let content = {binder;input;output;body=body';result=result';capture_type} in
|
||||||
ok (E_literal (D_function {capture=None;content}), tv, env)
|
ok @@ Combinators.Expression.make_tpl (E_literal (D_function {capture=None;content}), tv, env)
|
||||||
)
|
)
|
||||||
| _ -> (
|
| _ -> (
|
||||||
trace (simple_error "translate lambda shallow") @@
|
trace (simple_error "translate lambda shallow") @@
|
||||||
@ -369,7 +383,8 @@ and translate_lambda env l =
|
|||||||
let translate_declaration env (d:AST.declaration) : toplevel_statement result =
|
let translate_declaration env (d:AST.declaration) : toplevel_statement result =
|
||||||
match d with
|
match d with
|
||||||
| Declaration_constant {name;annotated_expression} ->
|
| Declaration_constant {name;annotated_expression} ->
|
||||||
let%bind ((_, tv, _) as expression) = translate_annotated_expression env annotated_expression in
|
let%bind expression = translate_annotated_expression env annotated_expression in
|
||||||
|
let tv = Combinators.Expression.get_type expression in
|
||||||
let env' = Environment.add (name, tv) env in
|
let env' = Environment.add (name, tv) env in
|
||||||
ok @@ ((name, expression), environment_wrap env env')
|
ok @@ ((name, expression), environment_wrap env env')
|
||||||
|
|
||||||
@ -383,8 +398,8 @@ let translate_program (lst:AST.program) : program result =
|
|||||||
ok statements
|
ok statements
|
||||||
|
|
||||||
let translate_main (l:AST.lambda) (_t:AST.type_value) : anon_function result =
|
let translate_main (l:AST.lambda) (_t:AST.type_value) : anon_function result =
|
||||||
let%bind (expr, _, _) = translate_lambda Environment.empty l in
|
let%bind expr = translate_lambda Environment.empty l in
|
||||||
match expr with
|
match Combinators.Expression.get_content expr with
|
||||||
| E_literal (D_function f) -> ok f
|
| E_literal (D_function f) -> ok f
|
||||||
| _ -> simple_fail "main is not a function"
|
| _ -> simple_fail "main is not a function"
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user