From 8e294a013ca6d5c20e0ce12bd078e6edb53f6423 Mon Sep 17 00:00:00 2001 From: Christian Rinderknecht Date: Thu, 14 Mar 2019 13:19:52 +0100 Subject: [PATCH] Added assignment of a value to a map binding: m.[i] := v. --- AST.ml | 47 +++++++++++++++++++++++++++++------------ AST.mli | 16 +++++++++++--- Parser.mly | 61 ++++++++++++++++++++++++++++++++++-------------------- Tests/a.li | 4 ++-- 4 files changed, 87 insertions(+), 41 deletions(-) diff --git a/AST.ml b/AST.ml index 0a4cbd4d6..0854f624d 100644 --- a/AST.ml +++ b/AST.ml @@ -321,7 +321,7 @@ and instruction = and single_instr = Cond of conditional reg | Match of match_instr reg -| Ass of ass_instr reg +| Ass of ass_instr | Loop of loop | ProcCall of fun_call | Null of kwd_null @@ -358,12 +358,22 @@ and case = { instr : instruction } -and ass_instr = { +and ass_instr = + VarAss of var_ass reg +| MapAss of map_ass reg + +and var_ass = { var : variable; ass : ass; expr : expr } +and map_ass = { + lookup : map_lookup reg; + ass : ass; + expr : expr +} + and loop = While of while_loop reg | For of for_loop @@ -380,7 +390,7 @@ and for_loop = and for_int = { kwd_for : kwd_for; - ass : ass_instr reg; + var_ass : var_ass reg; down : kwd_down option; kwd_to : kwd_to; bound : expr; @@ -644,7 +654,8 @@ and record_expr_to_region = function let instr_to_region = function Single Cond {region; _} | Single Match {region; _} -| Single Ass {region; _} +| Single Ass VarAss {region; _} +| Single Ass MapAss {region; _} | Single Loop While {region; _} | Single Loop For ForInt {region; _} | Single Loop For ForCollect {region; _} @@ -971,12 +982,22 @@ and print_case {value; _} = print_token arrow "->"; print_instruction instr -and print_ass_instr {value; _} = +and print_ass_instr = function + VarAss a -> print_var_ass a +| MapAss a -> print_map_ass a + +and print_var_ass {value; _} = let {var; ass; expr} = value in print_var var; print_token ass ":="; print_expr expr +and print_map_ass {value; _} = + let {lookup; ass; expr} = value in + print_map_lookup lookup; + print_token ass ":="; + print_expr expr + and print_loop = function While {value; _} -> print_while_loop value | For for_loop -> print_for_loop for_loop @@ -992,15 +1013,15 @@ and print_for_loop = function | ForCollect for_collect -> print_for_collect for_collect and print_for_int ({value; _} : for_int reg) = - let {kwd_for; ass; down; kwd_to; + let {kwd_for; var_ass; down; kwd_to; bound; step; block} = value in - print_token kwd_for "for"; - print_ass_instr ass; - print_down down; - print_token kwd_to "to"; - print_expr bound; - print_step step; - print_block block + print_token kwd_for "for"; + print_var_ass var_ass; + print_down down; + print_token kwd_to "to"; + print_expr bound; + print_step step; + print_block block and print_down = function Some kwd_down -> print_token kwd_down "down" diff --git a/AST.mli b/AST.mli index 586a1902c..ce6b045c1 100644 --- a/AST.mli +++ b/AST.mli @@ -305,7 +305,7 @@ and instruction = and single_instr = Cond of conditional reg | Match of match_instr reg -| Ass of ass_instr reg +| Ass of ass_instr | Loop of loop | ProcCall of fun_call | Null of kwd_null @@ -342,12 +342,22 @@ and case = { instr : instruction } -and ass_instr = { +and ass_instr = + VarAss of var_ass reg +| MapAss of map_ass reg + +and var_ass = { var : variable; ass : ass; expr : expr } +and map_ass = { + lookup : map_lookup reg; + ass : ass; + expr : expr +} + and loop = While of while_loop reg | For of for_loop @@ -364,7 +374,7 @@ and for_loop = and for_int = { kwd_for : kwd_for; - ass : ass_instr reg; + var_ass : var_ass reg; down : kwd_down option; kwd_to : kwd_to; bound : expr; diff --git a/Parser.mly b/Parser.mly index 264f712e1..0c976d484 100644 --- a/Parser.mly +++ b/Parser.mly @@ -347,10 +347,11 @@ after_instr: instr_or_end: End { - `End $1 } + `End $1 + } | instruction after_instr { let instrs, term, close = $2 in - `Some ($1, instrs, term, close) + `Some ($1, instrs, term, close) } local_decl: @@ -456,6 +457,16 @@ case: } ass: + var_ass { + VarAss $1 + } +| map_selection ASS expr { + let region = cover $1.region (expr_to_region $3) + and value = {lookup = $1; ass = $2; expr = $3} + in MapAss {region; value} + } + +var_ass: var ASS expr { let region = cover $1.region (expr_to_region $3) and value = {var = $1; ass = $2; expr = $3} @@ -477,12 +488,12 @@ while_loop: } for_loop: - For ass Down? To expr option(step_clause) block { + For var_ass Down? To expr option(step_clause) block { let region = cover $1 $7.region in let value = { kwd_for = $1; - ass = $2; + var_ass = $2; down = $3; kwd_to = $4; bound = $5; @@ -657,20 +668,22 @@ unary_expr: | core_expr { $1 } core_expr: - Int { ArithExpr (Int $1) } -| var { Var $1 } -| String { StringExpr (String $1) } -| Bytes { Bytes $1 } -| C_False { LogicExpr (BoolExpr (False $1)) } -| C_True { LogicExpr (BoolExpr (True $1)) } -| C_Unit { Unit $1 } -| tuple { Tuple $1 } -| list_expr { ListExpr (List $1) } -| empty_list { ListExpr (EmptyList $1) } -| set_expr { SetExpr (Set $1) } -| empty_set { SetExpr (EmptySet $1) } -| none_expr { ConstrExpr (NoneExpr $1) } -| fun_call { FunCall $1 } + Int { ArithExpr (Int $1) } +| var { Var $1 } +| String { StringExpr (String $1) } +| Bytes { Bytes $1 } +| C_False { LogicExpr (BoolExpr (False $1)) } +| C_True { LogicExpr (BoolExpr (True $1)) } +| C_Unit { Unit $1 } +| tuple { Tuple $1 } +| list_expr { ListExpr (List $1) } +| empty_list { ListExpr (EmptyList $1) } +| set_expr { SetExpr (Set $1) } +| empty_set { SetExpr (EmptySet $1) } +| none_expr { ConstrExpr (NoneExpr $1) } +| fun_call { FunCall $1 } +| map_selection { MapLookUp $1 } +| record_expr { RecordExpr $1 } | Constr arguments { let region = cover $1.region $2.region in ConstrExpr (ConstrApp {region; value = $1,$2}) @@ -679,15 +692,16 @@ core_expr: let region = cover $1 $2.region in ConstrExpr (SomeApp {region; value = $1,$2}) } -| map_name DOT brackets(expr) { + +map_selection: + map_name DOT brackets(expr) { let region = cover $1.region $3.region in let value = { map_name = $1; selector = $2; index = $3} - in MapLookUp {region; value} + in {region; value} } -| record_expr { RecordExpr $1 } record_expr: record_injection { RecordInj $1 } @@ -722,10 +736,11 @@ after_field: field_or_end: End { - `End $1 } + `End $1 + } | field_assignment after_field { let fields, term, close = $2 in - `Some ($1, fields, term, close) + `Some ($1, fields, term, close) } field_assignment: diff --git a/Tests/a.li b/Tests/a.li index f6e042032..18b153ab1 100644 --- a/Tests/a.li +++ b/Tests/a.li @@ -6,7 +6,6 @@ type w is K of (U of int) (*v * u*) storage s : w // Line comment type i is int; operations o : u; -const pi : int = 314159 const x : v = record @@ -18,7 +17,7 @@ const x : v = (* Block comment *) entrypoint g (const l : list (int)) is - + var m : map (int, string) := empty_map; var y : v := copy x with record bar = 7 end; function f (const x : int) : int is @@ -29,6 +28,7 @@ entrypoint g (const l : list (int)) is end with y * 2 begin + y.[4] := "hello"; match l with [] -> null | h#t -> q (h+2)