This commit is contained in:
Galfour 2019-03-20 17:06:12 +00:00
parent 1918bc00d1
commit a9f88e3ddf
4 changed files with 223 additions and 32 deletions

View File

@ -31,7 +31,7 @@ and named_type_expression = {
and te = type_expression
and ae = annotated_expression
and te_map = type_expression type_name_map
and e_map = expression name_map
and ae_map = annotated_expression name_map
and type_expression =
| Type_tuple of te list
@ -41,17 +41,25 @@ and type_expression =
| Type_constant of type_name * te list
and expression =
(* Base *)
| Literal of literal
| Constant of name * ae list (* For language constants, like (Cons hd tl) or (plus i j) *)
| Variable of name
| Tuple of ae list
| Constructor of name * ae list (* For user defined constructors *)
| Lambda of {
binder: name ;
input_type: type_expression ;
output_type: type_expression ;
result: ae ;
body: block ;
}
(* Tuple *)
| Tuple of ae list
| Tuple_accessor of ae * int (* Access n'th tuple's element *)
(* Sum *)
| Constructor of name * ae (* For user defined constructors *)
(* Record *)
| Record of ae_map
| Record_accessor of ae * string
and literal =
| Bool of bool
@ -64,7 +72,7 @@ and b = block
and instruction =
| Assignment of named_expression
| Matching of matching
| Matching of ae * matching
| Loop of ae * b
| Skip
| Fail of ae

View File

@ -28,7 +28,7 @@ and named_expression = {
and tv = type_value
and ae = annotated_expression
and tv_map = type_value type_name_map
and e_map = expression name_map
and ae_map = annotated_expression name_map
and type_value =
| Type_tuple of tv list
@ -37,21 +37,31 @@ and type_value =
| Type_constant of type_name * tv list
and expression =
(* Base *)
| Literal of literal
| Constant of name * ae list (* For language constants, like (Cons hd tl) or (plus i j) *)
| Variable of name
| Tuple of ae list
| Constructor of name * ae list (* For user defined constructors *)
| Lambda of {
binder: name ;
input_type: type_value ;
output_type: type_value ;
input_type: tv ;
output_type: tv ;
result: ae ;
body: block ;
}
(* Tuple *)
| Tuple of ae list
| Tuple_accessor of ae * int (* Access n'th tuple's element *)
(* Sum *)
| Constructor of name * ae (* For user defined constructors *)
(* Record *)
| Record of ae_map
| Record_accessor of ae * string
and literal =
| Bool of bool
| Number of int
| Int of int
| Nat of int
| String of string
| Bytes of bytes
@ -60,7 +70,7 @@ and b = block
and instruction =
| Assignment of named_expression
| Matching of matching
| Matching of ae * matching
| Loop of ae * b
| Skip
| Fail of ae
@ -127,11 +137,29 @@ let rec type_value_eq (ab: (type_value * type_value)) : unit result = match ab w
)
| _ -> simple_fail "Different kinds of types"
let merge_annotation (a:type_value option) (b:type_value option) : type_value option result =
let merge_annotation (a:type_value option) (b:type_value option) : type_value result =
match a, b with
| None, None -> ok None
| Some a, None -> ok (Some a)
| None, Some b -> ok (Some b)
| None, None -> simple_fail "no annotation"
| Some a, None -> ok a
| None, Some b -> ok b
| Some a, Some b ->
let%bind _ = type_value_eq (a, b) in
ok (Some a)
ok a
let t_bool : type_value = Type_constant ("bool", [])
let t_string : type_value = Type_constant ("string", [])
let t_int : type_value = Type_constant ("int", [])
let get_annotation (x:annotated_expression) = x.type_annotation
let get_t_tuple : type_value -> type_value list result = function
| Type_tuple lst -> ok lst
| _ -> simple_fail "not a tuple"
let get_t_sum : type_value -> type_value SMap.t result = function
| Type_sum m -> ok m
| _ -> simple_fail "not a sum"
let get_t_record : type_value -> type_value SMap.t result = function
| Type_record m -> ok m
| _ -> simple_fail "not a record"

View File

@ -1225,6 +1225,82 @@ module Run = struct
end
module Translate_new_AST = struct
module AST = Ast_typed
let list_of_map m = List.rev @@ Ligo_helpers.X_map.String.fold (fun _ v prev -> v :: prev) m []
let rec translate_type (t:AST.type_value) : type_value result =
match t with
| Type_constant ("bool", []) -> ok (`Base Bool)
| Type_constant ("int", []) -> ok (`Base Int)
| Type_constant ("string", []) -> ok (`Base String)
| Type_sum m ->
let node = Append_tree.of_list @@ list_of_map m in
let aux a b : type_value result =
let%bind a = a in
let%bind b = b in
ok (`Or (a, b))
in
Append_tree.fold_ne translate_type aux node
| Type_record m ->
let node = Append_tree.of_list @@ list_of_map m in
let aux a b : type_value result =
let%bind a = a in
let%bind b = b in
ok (`Pair (a, b))
in
Append_tree.fold_ne translate_type aux node
| Type_tuple lst ->
let node = Append_tree.of_list lst in
let aux a b : type_value result =
let%bind a = a in
let%bind b = b in
ok (`Pair (a, b))
in
Append_tree.fold_ne translate_type aux node
| _ -> simple_fail "todo"
let rec translate_block (b:AST.block) : block result =
bind_list @@ List.map translate_instruction b
and translate_instruction (i:AST.instruction) : statement result =
match i with
| Assignment {name;annotated_expression} ->
let%bind expression = translate_annotated_expression annotated_expression in
ok @@ Assignment (Variable (name, expression))
| Matching (expr, Match_bool {match_true ; match_false}) ->
let%bind expr' = translate_annotated_expression expr in
let%bind true_branch = translate_block match_true in
let%bind false_branch = translate_block match_false in
ok @@ Cond (expr', true_branch, false_branch)
| Loop (expr, body) ->
let%bind expr' = translate_annotated_expression expr in
let%bind body' = translate_block body in
ok @@ While (expr', body')
| _ -> simple_fail "todo"
and translate_annotated_expression (ae:AST.annotated_expression) : expression result =
let%bind tv = translate_type ae.type_annotation in
match ae.expression with
| Literal (Bool b) -> ok (Literal (`Bool b), tv)
| Literal (Number n) -> ok (Literal (`Int n), tv)
| Literal (String s) -> ok (Literal (`String s), tv)
| Variable name -> ok (Var name, tv)
| _ -> simple_fail "todo"
let translate_declaration (d:AST.declaration) : toplevel_statement result =
match d with
| Constant_declaration {name;annotated_expression} ->
let%bind expression = translate_annotated_expression annotated_expression in
ok @@ Variable (name, expression)
let translate_program (lst:AST.program) : program result =
bind_list @@ List.map translate_declaration lst
end
module Combinators = struct
let var x : expression' = Var x

View File

@ -6,20 +6,36 @@ module O = Ast_typed
module SMap = O.SMap
module Environment = struct
type t = unit
let empty : t = ()
type ele = O.type_value
let get (():t) (_s:string) : O.type_value option = None
let add (():t) (_s:string) (_tv:O.type_value) : t = ()
let get_type (():t) (_s:string) : O.type_value option = None
let add_type (():t) (_s:string) (_tv:O.type_value) : t = ()
type t = {
environment: (string * ele) list ;
type_environment: (string * ele) list ;
}
let empty : t = {
environment = [] ;
type_environment = [] ;
}
let get (e:t) (s:string) : ele option =
List.assoc_opt s e.environment
let get_constructor (e:t) (s:string) : (ele * ele) option =
let rec aux = function
| [] -> None
| (_, ((O.Type_sum m) as tv)) :: _ when SMap.mem s m -> Some (SMap.find s m, tv)
| _ :: tl -> aux tl
in
aux e.environment
let add (e:t) (s:string) (tv:ele) : t =
{e with environment = (s, tv) :: e.environment}
let get_type (e:t) (s:string) : ele option =
List.assoc_opt s e.type_environment
let add_type (e:t) (s:string) (tv:ele) : t =
{e with type_environment = (s, tv) :: e.type_environment}
end
type environment = Environment.t
type environment = unit
let empty : environment = ()
let rec type_program (p:I.program) : O.program result =
let aux (e, acc:(environment * O.declaration list)) (d:I.declaration) =
let%bind (e', d') = type_declaration e d in
@ -27,12 +43,18 @@ let rec type_program (p:I.program) : O.program result =
| None -> ok (e', acc)
| Some d' -> ok (e', d' :: acc)
in
let%bind (_, lst) = bind_fold_list aux (empty, []) p in
let%bind (_, lst) = bind_fold_list aux (Environment.empty, []) p in
ok @@ List.rev lst
and type_declaration _env : I.declaration -> (environment * O.declaration option) result = function
| Type_declaration _ -> simple_fail ""
| Constant_declaration _ -> simple_fail ""
and type_declaration env : I.declaration -> (environment * O.declaration option) result = function
| Type_declaration {type_name;type_expression} ->
let%bind tv = evaluate_type env type_expression in
let env' = Environment.add_type env type_name tv in
ok (env', None)
| Constant_declaration {name;annotated_expression} ->
let%bind ae' = type_annotated_expression env annotated_expression in
let env' = Environment.add env name ae'.type_annotation in
ok (env', Some (O.Constant_declaration {name;annotated_expression=ae'}))
and type_block (e:environment) (b:I.block) : O.block result =
let aux (e, acc:(environment * O.instruction list)) (i:I.instruction) =
@ -73,9 +95,10 @@ and type_instruction (e:environment) : I.instruction -> (environment * O.instruc
let e' = Environment.add e name annotated_expression.type_annotation in
ok (e', O.Assignment {name;annotated_expression})
)
| Matching m ->
| Matching (ex, m) ->
let%bind m' = type_match e m in
ok (e, O.Matching m')
let%bind ex' = type_annotated_expression e ex in
ok (e, O.Matching (ex', m'))
and type_match (e:environment) : I.matching -> O.matching result = function
| Match_bool {match_true ; match_false} ->
@ -129,10 +152,66 @@ and evaluate_type (e:environment) : I.type_expression -> O.type_value result = f
ok (O.Type_constant(cst, lst'))
and type_annotated_expression (e:environment) (ae:I.annotated_expression) : O.annotated_expression result =
let%bind tv_opt = match ae.type_annotation with
| None -> ok None
| Some s -> let%bind r = evaluate_type e s in ok (Some r) in
let check tv = O.merge_annotation (Some tv) tv_opt in
match ae.expression with
(* Basic *)
| Variable name ->
let%bind tv' =
trace_option (simple_error "var not in env")
@@ Environment.get e name in
ok O.{expression = Variable name ; type_annotation = tv'}
let%bind type_annotation = check tv' in
ok O.{expression = Variable name ; type_annotation}
| Literal (Bool b) ->
let%bind type_annotation = check O.t_bool in
ok O.{expression = Literal (Bool b) ; type_annotation }
| Literal (String s) ->
let%bind type_annotation = check O.t_string in
ok O.{expression = Literal (String s) ; type_annotation }
| Literal (Number n) ->
let%bind type_annotation = check O.t_int in
ok O.{expression = Literal (Int n) ; type_annotation }
(* Tuple *)
| Tuple lst ->
let%bind lst' = bind_list @@ List.map (type_annotated_expression e) lst in
let tv_lst = List.map O.get_annotation lst' in
let%bind type_annotation = check (O.Type_tuple tv_lst) in
ok O.{expression = Tuple lst' ; type_annotation }
| Tuple_accessor (tpl, ind) ->
let%bind tpl' = type_annotated_expression e tpl in
let%bind tpl_tv = O.get_t_tuple tpl'.type_annotation in
let%bind tv =
generic_try (simple_error "bad tuple index")
@@ (fun () -> List.nth tpl_tv ind) in
let%bind type_annotation = check tv in
ok O.{expression = O.Tuple_accessor (tpl', ind) ; type_annotation}
(* Sum *)
| Constructor (c, expr) ->
let%bind (c_tv, sum_tv) =
trace_option (simple_error "no such constructor")
@@ Environment.get_constructor e c in
let%bind expr' = type_annotated_expression e expr in
let%bind _assert = O.type_value_eq (expr'.type_annotation, c_tv) in
let%bind type_annotation = check sum_tv in
ok O.{expression = O.Constructor(c, expr') ; type_annotation }
(* Record *)
| Record m ->
let aux k expr prev =
let%bind prev' = prev in
let%bind expr' = type_annotated_expression e expr in
ok (SMap.add k expr' prev')
in
let%bind m' = SMap.fold aux m (ok SMap.empty) in
let%bind type_annotation = check @@ O.Type_record (SMap.map O.get_annotation m') in
ok O.{expression = O.Record m' ; type_annotation }
| Record_accessor (r, ind) ->
let%bind r' = type_annotated_expression e r in
let%bind r_tv = O.get_t_record r'.type_annotation in
let%bind tv =
generic_try (simple_error "bad record index")
@@ (fun () -> SMap.find ind r_tv) in
let%bind type_annotation = check tv in
ok O.{expression = O.Record_accessor (r', ind) ; type_annotation }
| _ -> simple_fail "default"