From 35dccbd3999a8c3bb1dc9e96e21b69a39f44fc6f Mon Sep 17 00:00:00 2001 From: Siraaj Khandkar Date: Tue, 18 Sep 2018 16:31:45 -0400 Subject: [PATCH] Check scope of break statements --- compiler/src/lib/tiger/tiger_env.ml | 20 ++++++++++++ compiler/src/lib/tiger/tiger_env.mli | 4 +++ compiler/src/lib/tiger/tiger_error.ml | 36 +++++++++++++++++++++ compiler/src/lib/tiger/tiger_error.mli | 2 ++ compiler/src/lib/tiger/tiger_semant.ml | 15 +++++++-- compiler/src/lib/tiger/tiger_symbol.ml | 24 +++++++++----- compiler/src/lib/tiger/tiger_symbol.mli | 6 ++++ compiler/src/lib/tiger/tiger_test_cases.ml | 24 ++++++++++++++ screenshots/tests-tail.jpg | Bin 6236 -> 3808 bytes 9 files changed, 120 insertions(+), 11 deletions(-) diff --git a/compiler/src/lib/tiger/tiger_env.ml b/compiler/src/lib/tiger/tiger_env.ml index f698f89..1e4cd1d 100644 --- a/compiler/src/lib/tiger/tiger_env.ml +++ b/compiler/src/lib/tiger/tiger_env.ml @@ -1,15 +1,18 @@ module Map = Tiger_map +module Sym = Tiger_symbol module Type = Tiger_env_type module Value = Tiger_env_value type t = { typs : Type.env ; vals : Value.env + ; loop : Sym.t option } let base = { typs = Type.built_in ; vals = Value.built_in + ; loop = None } let get_typ {typs; _} k = @@ -23,3 +26,20 @@ let set_typ t k v = let set_val t k v = {t with vals = Map.set t.vals ~k ~v} + +let loop_begin t = + let loop = Sym.new_of_string "loop" in + let t = {t with loop = Some loop} in + (loop, t) + +let loop_end t given = + match t.loop with + | None -> + assert false + | Some current when (not (Sym.is_equal current given)) -> + assert false + | Some _ -> + {t with loop = None} + +let loop_current {loop; _} = + loop diff --git a/compiler/src/lib/tiger/tiger_env.mli b/compiler/src/lib/tiger/tiger_env.mli index 91747e5..3338949 100644 --- a/compiler/src/lib/tiger/tiger_env.mli +++ b/compiler/src/lib/tiger/tiger_env.mli @@ -7,3 +7,7 @@ val get_val : t -> Tiger_symbol.t -> Tiger_env_value.t option val set_typ : t -> Tiger_symbol.t -> Tiger_env_type.t -> t val set_val : t -> Tiger_symbol.t -> Tiger_env_value.t -> t + +val loop_begin : t -> (Tiger_symbol.t * t) +val loop_end : t -> Tiger_symbol.t -> t +val loop_current : t -> Tiger_symbol.t option diff --git a/compiler/src/lib/tiger/tiger_error.ml b/compiler/src/lib/tiger/tiger_error.ml index 11b4b95..f2b3ae1 100644 --- a/compiler/src/lib/tiger/tiger_error.ml +++ b/compiler/src/lib/tiger/tiger_error.ml @@ -10,6 +10,7 @@ type t = ; to_id : Sym.t ; to_pos : Pos.t } + | Break_outside_loop of Pos.t | Invalid_syntax of Pos.t | Unknown_id of {id : Sym.t; pos : Pos.t} | Unknown_type of {ty_id : Sym.t; pos : Pos.t} @@ -80,6 +81,8 @@ let to_string = function | Invalid_syntax pos -> s "Invalid syntax in %s" (Pos.to_string pos) + | Break_outside_loop pos -> + s "Break statement is not within a loop. In %s" (Pos.to_string pos) | Cycle_in_type_decs {from_id; from_pos; to_id; to_pos} -> s ( "Circular type declaration between %S and %S." ^^"Locations: %S (in %s), %S (in %s).") @@ -167,6 +170,7 @@ let is_unknown_id t = match t with | Unknown_id _ -> true + | Break_outside_loop _ | Cycle_in_type_decs _ | Invalid_syntax _ | Unknown_type _ @@ -190,6 +194,7 @@ let is_unknown_type t = match t with | Unknown_type _ -> true + | Break_outside_loop _ | Cycle_in_type_decs _ | Unknown_id _ | Invalid_syntax _ @@ -213,6 +218,7 @@ let is_wrong_type t = match t with | Wrong_type _ -> true + | Break_outside_loop _ | Cycle_in_type_decs _ | Unknown_type _ | Unknown_id _ @@ -236,6 +242,7 @@ let is_wrong_number_of_args t = match t with | Wrong_number_of_args _ -> true + | Break_outside_loop _ | Cycle_in_type_decs _ | Wrong_type _ | Unknown_type _ @@ -259,6 +266,7 @@ let is_invalid_syntax t = match t with | Invalid_syntax _ -> true + | Break_outside_loop _ | Cycle_in_type_decs _ | Wrong_type _ | Unknown_type _ @@ -282,6 +290,7 @@ let is_not_a_record t = match t with | Exp_not_a_record _ -> true + | Break_outside_loop _ | Cycle_in_type_decs _ | Invalid_syntax _ | Wrong_type _ @@ -305,6 +314,7 @@ let is_not_an_array t = match t with | Exp_not_an_array _ -> true + | Break_outside_loop _ | Cycle_in_type_decs _ | Exp_not_a_record _ | Invalid_syntax _ @@ -328,6 +338,7 @@ let is_no_such_field_in_record t = match t with | No_such_field_in_record _ -> true + | Break_outside_loop _ | Cycle_in_type_decs _ | Exp_not_an_array _ | Exp_not_a_record _ @@ -351,6 +362,31 @@ let is_cycle_in_type_dec t = match t with | Cycle_in_type_decs _ -> true + | Break_outside_loop _ + | No_such_field_in_record _ + | Exp_not_an_array _ + | Exp_not_a_record _ + | Invalid_syntax _ + | Wrong_type _ + | Unknown_type _ + | Unknown_id _ + | Id_is_a_function _ + | Id_not_a_function _ + | Wrong_type_of_expression_in_var_dec _ + | Wrong_type_used_as_array _ + | Wrong_type_used_as_record _ + | Wrong_type_of_field_value _ + | Wrong_type_of_arg _ + | Wrong_number_of_args _ + | Invalid_operand_type _ + | Different_operand_types _ -> + false + +let is_break_outside_loop t = + match t with + | Break_outside_loop _ -> + true + | Cycle_in_type_decs _ | No_such_field_in_record _ | Exp_not_an_array _ | Exp_not_a_record _ diff --git a/compiler/src/lib/tiger/tiger_error.mli b/compiler/src/lib/tiger/tiger_error.mli index 73505b8..0344269 100644 --- a/compiler/src/lib/tiger/tiger_error.mli +++ b/compiler/src/lib/tiger/tiger_error.mli @@ -10,6 +10,7 @@ type t = ; to_id : Sym.t ; to_pos : Pos.t } + | Break_outside_loop of Pos.t | Invalid_syntax of Pos.t | Unknown_id of {id : Sym.t; pos : Pos.t} | Unknown_type of {ty_id : Sym.t; pos : Pos.t} @@ -85,3 +86,4 @@ val is_not_a_record : t -> bool val is_not_an_array : t -> bool val is_no_such_field_in_record : t -> bool val is_cycle_in_type_dec : t -> bool +val is_break_outside_loop : t -> bool diff --git a/compiler/src/lib/tiger/tiger_semant.ml b/compiler/src/lib/tiger/tiger_semant.ml index 6bb45fd..19e8c8b 100644 --- a/compiler/src/lib/tiger/tiger_semant.ml +++ b/compiler/src/lib/tiger/tiger_semant.ml @@ -192,16 +192,25 @@ end = struct | A.WhileExp {test; body; pos} -> (* test : must be int, because we have no bool *) check_int (trexp test) ~pos; - ignore (trexp body); (* Only care if a type-error is raised *) + let (loop, env) = Env.loop_begin env in + (* Only care if an error is raised *) + ignore (transExp ~env body); + ignore (Env.loop_end env loop); return_unit | A.ForExp {var; lo; hi; body; pos; escape=_} -> check_int (trexp lo) ~pos; check_int (trexp hi) ~pos; - (* Only care if a type-error is raised *) + let (loop, env) = Env.loop_begin env in let env = Env.set_val env var (Value.Var {ty = Type.Int}) in + (* Only care if an error is raised *) ignore (transExp ~env body); + ignore (Env.loop_end env loop); return_unit - | A.BreakExp _ -> + | A.BreakExp pos -> + (match Env.loop_current env with + | Some _ -> () + | None -> E.raise (E.Break_outside_loop pos) + ); return_unit | A.LetExp {decs; body; pos=_} -> (* (1) decs augment env *) diff --git a/compiler/src/lib/tiger/tiger_symbol.ml b/compiler/src/lib/tiger/tiger_symbol.ml index f1dc51a..b5d895b 100644 --- a/compiler/src/lib/tiger/tiger_symbol.ml +++ b/compiler/src/lib/tiger/tiger_symbol.ml @@ -5,22 +5,30 @@ type t = ; symbol : int } -let nextsym = ref 0 +let counter = ref 0 let symbols = H.create 16 +let next name = + incr counter; + let symbol = !counter in + {name; symbol} + +let new_of_string name = + let t = next name in + H.replace symbols ~key:t.name ~data:t.symbol; + t + let of_string name = match H.find_opt symbols name with - | Some symbol -> - {name; symbol} - | None -> - incr nextsym; - let symbol = !nextsym in - H.replace symbols ~key:name ~data:symbol; - {name; symbol} + | Some s -> {name; symbol=s} + | None -> new_of_string name let to_string {name; _} = name let is_equal {symbol=s1; _} {symbol=s2; _} = s1 = s2 + +let show {name; symbol} = + Printf.sprintf "Symbol[%S, %d]" name symbol diff --git a/compiler/src/lib/tiger/tiger_symbol.mli b/compiler/src/lib/tiger/tiger_symbol.mli index e5c560f..1dd5acc 100644 --- a/compiler/src/lib/tiger/tiger_symbol.mli +++ b/compiler/src/lib/tiger/tiger_symbol.mli @@ -1,7 +1,13 @@ type t +val new_of_string : string -> t + val of_string : string -> t val to_string : t -> string +(* Reversable. Returns original. *) + +val show : t -> string +(* Not-reversable. M-expression with name and symbol. *) val is_equal : t -> t -> bool diff --git a/compiler/src/lib/tiger/tiger_test_cases.ml b/compiler/src/lib/tiger/tiger_test_cases.ml index 082e02f..1ead5f5 100644 --- a/compiler/src/lib/tiger/tiger_test_cases.ml +++ b/compiler/src/lib/tiger/tiger_test_cases.ml @@ -120,6 +120,30 @@ let micro = " ~is_error_expected_semant:(Some Error.is_cycle_in_type_dec) ) + ; ( Test.case + "Break outside loop" + ~code: + "break" + ~is_error_expected_semant:(Some Error.is_break_outside_loop) + ) + ; ( Test.case + "Break within for loop" + ~code:"for i := 0 to 5 do (print(\"x\"); break)" + ) + ; ( Test.case + "Break after for loop" + ~code:"(for i := 0 to 5 do (print(\"x\"); break); break)" + ~is_error_expected_semant:(Some Error.is_break_outside_loop) + ) + ; ( Test.case + "Break within while loop" + ~code:"while 1 do (print(\"x\"); break)" + ) + ; ( Test.case + "Break after while loop" + ~code:"(while 1 do (print(\"x\"); break); break)" + ~is_error_expected_semant:(Some Error.is_break_outside_loop) + ) ] let book ~dir = diff --git a/screenshots/tests-tail.jpg b/screenshots/tests-tail.jpg index b0c72d7a268444762e9532bd72484dd7e00ffe80..10e7dbe4bf483dc7036323a105293506eded3259 100644 GIT binary patch literal 3808 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 literal 6236 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 -- 2.20.1