diff --git a/asllib/Interpreter.ml b/asllib/Interpreter.ml index 0680317ba..9fe686b85 100644 --- a/asllib/Interpreter.ml +++ b/asllib/Interpreter.ml @@ -372,10 +372,10 @@ module Make (B : Backend.S) (C : Config) = struct let rec eval_expr (env : env) (e : expr) : expr_eval_type = if false then Format.eprintf "@[<3>Eval@ @[%a@]@]@." PP.pp_expr e; match e.desc with - (* Begin EvalEvalLit *) - | E_Literal l -> return_normal (B.v_of_literal l, env) |: SemanticsRule.Lit + (* Begin EvalELit *) + | E_Literal l -> return_normal (B.v_of_literal l, env) |: SemanticsRule.ELit (* End *) - (* Begin EvalEvalATC *) + (* Begin EvalATC *) | E_ATC (e1, t) -> let** v, new_env = eval_expr env e1 in let* b = is_val_of_type e1 env v t in @@ -383,42 +383,37 @@ module Make (B : Backend.S) (C : Config) = struct else fatal_from e1 (Error.MismatchType (B.debug_value v, [ t.desc ]))) |: SemanticsRule.ATC (* End *) - | E_Var x -> ( - match IEnv.find x env with - (* Begin EvalEvalELocalVar *) + (* Begin EvalEVar *) + | E_Var x -> + (match IEnv.find x env with | Local v -> let* () = B.on_read_identifier x (IEnv.get_scope env) v in - return_normal (v, env) |: SemanticsRule.ELocalVar - (* End *) - (* Begin EvalEvalEGlobalVar *) + return_normal (v, env) | Global v -> let* () = B.on_read_identifier x (Scope_Global false) v in - return_normal (v, env) |: SemanticsRule.EGlobalVar - (* End *) - (* Begin EvalEvalEUndefIdent *) - | NotFound -> - fatal_from e @@ Error.UndefinedIdentifier x - |: SemanticsRule.EUndefIdent) + return_normal (v, env) + | NotFound -> fatal_from e @@ Error.UndefinedIdentifier x) + |: SemanticsRule.EVar (* End *) - (* Begin EvalEvalBinopAnd *) + (* Begin EvalBinopAnd *) | E_Binop (BAND, e1, e2) -> (* if e1 then e2 else false *) E_Cond (e1, e2, false') |> add_pos_from e |> eval_expr env |: SemanticsRule.BinopAnd (* End *) - (* Begin EvalEvalBinopOr *) + (* Begin EvalBinopOr *) | E_Binop (BOR, e1, e2) -> (* if e1 then true else e2 *) E_Cond (e1, true', e2) |> add_pos_from e |> eval_expr env |: SemanticsRule.BinopOr (* End *) - (* Begin EvalEvalBinopImpl *) + (* Begin EvalBinopImpl *) | E_Binop (IMPL, e1, e2) -> (* if e1 then e2 else true *) E_Cond (e1, e2, true') |> add_pos_from e |> eval_expr env |: SemanticsRule.BinopImpl (* End *) - (* Begin EvalEvalBinop *) + (* Begin EvalBinop *) | E_Binop (op, e1, e2) -> let*^ m1, env1 = eval_expr env e1 in let*^ m2, new_env = eval_expr env1 e2 in @@ -426,13 +421,13 @@ module Make (B : Backend.S) (C : Config) = struct let* v = B.binop op v1 v2 in return_normal (v, new_env) |: SemanticsRule.Binop (* End *) - (* Begin EvalEvalUnop *) + (* Begin EvalUnop *) | E_Unop (op, e1) -> let** v1, env1 = eval_expr env e1 in let* v = B.unop op v1 in return_normal (v, env1) |: SemanticsRule.Unop (* End *) - (* Begin EvalEvalECond *) + (* Begin EvalECond *) | E_Cond (e_cond, e1, e2) -> let*^ m_cond, env1 = eval_expr env e_cond in if is_simple_expr e1 && is_simple_expr e2 then @@ -447,7 +442,7 @@ module Make (B : Backend.S) (C : Config) = struct choice_with_branch_effect m_cond e_cond e1 e2 (eval_expr env1) |: SemanticsRule.ECond (* End *) - (* Begin EvalEvalESlice *) + (* Begin EvalESlice *) | E_Slice (e_bv, slices) -> let*^ m_bv, env1 = eval_expr env e_bv in let*^ m_positions, new_env = eval_slices env1 slices in @@ -455,7 +450,7 @@ module Make (B : Backend.S) (C : Config) = struct let* v = B.read_from_bitvector positions v_bv in return_normal (v, new_env) |: SemanticsRule.ESlice (* End *) - (* Begin EvalEvalECall *) + (* Begin EvalECall *) | E_Call (name, actual_args, params) -> let**| ms, new_env = eval_call (to_pos e) name env actual_args params in let* v = @@ -467,7 +462,7 @@ module Make (B : Backend.S) (C : Config) = struct in return_normal (v, new_env) |: SemanticsRule.ECall (* End *) - (* Begin EvalEvalEGetArray *) + (* Begin EvalEGetArray *) | E_GetArray (e_array, e_index) -> ( let*^ m_array, env1 = eval_expr env e_array in let*^ m_index, new_env = eval_expr env1 e_index in @@ -482,20 +477,20 @@ module Make (B : Backend.S) (C : Config) = struct let** v_tuple, new_env = eval_expr env e_tuple in let* v = B.get_index index v_tuple in return_normal (v, new_env) - (* Begin EvalEvalERecord *) + (* Begin EvalERecord *) | E_Record (_, e_fields) -> let names, fields = List.split e_fields in let** v_fields, new_env = eval_expr_list env fields in let* v = B.create_record (List.combine names v_fields) in return_normal (v, new_env) |: SemanticsRule.ERecord (* End *) - (* Begin EvalEvalEGetField *) + (* Begin EvalEGetField *) | E_GetField (e_record, field_name) -> let** v_record, new_env = eval_expr env e_record in let* v = B.get_field field_name v_record in return_normal (v, new_env) |: SemanticsRule.EGetBitField (* End *) - (* Begin EvalEvalEGetFields *) + (* Begin EvalEGetFields *) | E_GetFields (e_record, field_names) -> let** v_record, new_env = eval_expr env e_record in let* v_list = @@ -507,13 +502,13 @@ module Make (B : Backend.S) (C : Config) = struct let* v = B.concat_bitvectors v_list in return_normal (v, new_env) (* End *) - (* Begin EvalEvalEConcat *) + (* Begin EvalEConcat *) | E_Concat e_list -> let** v_list, new_env = eval_expr_list env e_list in let* v = B.concat_bitvectors v_list in return_normal (v, new_env) |: SemanticsRule.EConcat (* End *) - (* Begin EvalEvalETuple *) + (* Begin EvalETuple *) | E_Tuple e_list -> let** v_list, new_env = eval_expr_list env e_list in let* v = B.create_vector v_list in @@ -619,15 +614,13 @@ module Make (B : Backend.S) (C : Config) = struct | LE_Var x -> ( let* v = m in match IEnv.assign x v env with - (* Begin EvalLELocalVar *) + (* Begin EvalLEVar *) | Local env -> let* () = B.on_write_identifier x (IEnv.get_scope env) v in - return_normal env |: SemanticsRule.LELocalVar - (* End *) - (* Begin EvalLEGlobalVar *) + return_normal env |: SemanticsRule.LEVar | Global env -> let* () = B.on_write_identifier x (Scope_Global false) v in - return_normal env |: SemanticsRule.LEGlobalVar + return_normal env |: SemanticsRule.LEVar (* End *) | NotFound -> ( match ver with @@ -683,7 +676,7 @@ module Make (B : Backend.S) (C : Config) = struct (* End *) (* Begin EvalLEConcat *) | LE_Concat (les, Some widths) -> - let extract_one e_width (ms, e_start) = + let extract_slice e_width (ms, e_start) = let e_end = binop PLUS e_start e_width in let m' = let* v = m @@ -693,9 +686,10 @@ module Make (B : Backend.S) (C : Config) = struct in (m' :: ms, e_end) in - let ms, _ = List.fold_right extract_one widths ([], expr_of_int 0) in + let ms, _ = List.fold_right extract_slice widths ([], expr_of_int 0) in multi_assign V1 env les ms (* End *) + (* Begin EvalLESetFields *) | LE_SetFields (le_record, fields, slices) -> let () = if List.compare_lengths fields slices != 0 then @@ -711,6 +705,7 @@ module Make (B : Backend.S) (C : Config) = struct rm_record fields slices in eval_lexpr ver le_record env1 m2 |: SemanticsRule.LESetField + (* End *) | LE_Concat (_, None) -> let* () = let* v = m in @@ -740,41 +735,32 @@ module Make (B : Backend.S) (C : Config) = struct [slices]. *) and eval_slices env : slice list -> ((B.value * B.value) list * env) maybe_exception m = - let eval_one env = function - (* Begin EvalSliceSingle *) + (* Begin EvalSlice *) + let eval_slice env = function | Slice_Single e -> let** v_start, new_env = eval_expr env e in - return_normal ((v_start, one), new_env) |: SemanticsRule.SliceSingle - (* End *) - (* Begin EvalSliceLength *) + return_normal ((v_start, one), new_env) |: SemanticsRule.Slice | Slice_Length (e_start, e_length) -> let*^ m_start, env1 = eval_expr env e_start in let*^ m_length, new_env = eval_expr env1 e_length in let* v_start = m_start and* v_length = m_length in - return_normal ((v_start, v_length), new_env) - |: SemanticsRule.SliceLength - (* End *) - (* Begin EvalSliceRange *) + return_normal ((v_start, v_length), new_env) |: SemanticsRule.Slice | Slice_Range (e_top, e_start) -> let*^ m_top, env1 = eval_expr env e_top in let*^ m_start, new_env = eval_expr env1 e_start in let* v_top = m_top and* v_start = m_start in let* v_length = B.binop MINUS v_top v_start >>= B.binop PLUS one in - return_normal ((v_start, v_length), new_env) - |: SemanticsRule.SliceRange - (* End *) - (* Begin EvalSliceStar *) + return_normal ((v_start, v_length), new_env) |: SemanticsRule.Slice | Slice_Star (e_factor, e_length) -> let*^ m_factor, env1 = eval_expr env e_factor in let*^ m_length, new_env = eval_expr env1 e_length in let* v_factor = m_factor and* v_length = m_length in let* v_start = B.binop MUL v_factor v_length in - return_normal ((v_start, v_length), new_env) - |: SemanticsRule.SliceStar + return_normal ((v_start, v_length), new_env) |: SemanticsRule.Slice (* End *) in (* Begin EvalSlices *) - fold_par_list eval_one env |: SemanticsRule.Slices + fold_par_list eval_slice env |: SemanticsRule.Slices (* End *) (* Evaluation of Patterns *) @@ -864,12 +850,9 @@ module Make (B : Backend.S) (C : Config) = struct (* Begin EvalLDTyped *) | LDI_Typed (ldi1, _t), Some m -> eval_local_decl pos ldi1 env (Some m) |: SemanticsRule.LDTyped - (* End *) - (* Begin EvalLDUninitialisedTyped *) | LDI_Typed (ldi1, t), None -> let m = base_value env t in - eval_local_decl pos ldi1 env (Some m) - |: SemanticsRule.LDUninitialisedTyped + eval_local_decl pos ldi1 env (Some m) |: SemanticsRule.LDTyped (* End *) (* Begin EvalLDTuple *) | LDI_Tuple ldis, Some m -> @@ -917,7 +900,7 @@ module Make (B : Backend.S) (C : Config) = struct let**| new_env = eval_lexpr ver le env1 m in return_continue new_env |: SemanticsRule.SAssign (* End *) - (* Begin EvalSReturnSome *) + (* Begin EvalSReturn *) | S_Return (Some { desc = E_Tuple es; _ }) -> let**| ms, new_env = eval_expr_list_m env es in let scope = IEnv.get_scope new_env in @@ -928,17 +911,14 @@ module Make (B : Backend.S) (C : Config) = struct return (i + 1, v :: vs) in let*| _i, vs = List.fold_left folder (return (0, [])) ms in - return_return new_env (List.rev vs) |: SemanticsRule.SReturnSome - (* End *) - (* Begin EvalSReturnOne *) + return_return new_env (List.rev vs) |: SemanticsRule.SReturn | S_Return (Some e) -> let** v, env1 = eval_expr env e in let* () = B.on_write_identifier (return_identifier 0) (IEnv.get_scope env1) v in - return_return env1 [ v ] |: SemanticsRule.SReturnOne - (* Begin EvalSReturnNone *) - | S_Return None -> return_return env [] |: SemanticsRule.SReturnNone + return_return env1 [ v ] |: SemanticsRule.SReturn + | S_Return None -> return_return env [] |: SemanticsRule.SReturn (* End *) (* Begin EvalSSeq *) | S_Seq (s1, s2) -> @@ -999,36 +979,29 @@ module Make (B : Backend.S) (C : Config) = struct IEnv.remove_local index_name env4 |> return_continue |: SemanticsRule.SFor (* End *) - (* Begin EvalSThrowNone *) - | S_Throw None -> return (Throwing (None, env)) |: SemanticsRule.SThrowNone - (* End *) - (* Begin EvalSThrowSomeTyped *) + (* Begin EvalSThrow *) + | S_Throw None -> return (Throwing (None, env)) |: SemanticsRule.SThrow | S_Throw (Some (e, Some t)) -> let** v, new_env = eval_expr env e in let name = throw_identifier () and scope = Scope_Global false in let* () = B.on_write_identifier name scope v in return (Throwing (Some ((v, name, scope), t), new_env)) - |: SemanticsRule.SThrowSomeTyped - (* End *) - (* Begin EvalSThrowSome *) - | S_Throw (Some (_e, None)) -> - fatal_from s Error.TypeInferenceNeeded |: SemanticsRule.SThrowSome + |: SemanticsRule.SThrow + | S_Throw (Some (_e, None)) -> fatal_from s Error.TypeInferenceNeeded (* End *) (* Begin EvalSTry *) | S_Try (s1, catchers, otherwise_opt) -> let s_m = eval_block env s1 in eval_catchers env catchers otherwise_opt s_m |: SemanticsRule.STry (* End *) - (* Begin EvalSDeclSome *) + (* Begin EvalSDecl *) | S_Decl (_ldk, ldi, Some e) -> let*^ m, env1 = eval_expr env e in let**| new_env = eval_local_decl s ldi env1 (Some m) in - return_continue new_env |: SemanticsRule.SDeclSome - (* End *) - (* Begin EvalSDeclNone *) + return_continue new_env |: SemanticsRule.SDecl | S_Decl (_dlk, ldi, None) -> let**| new_env = eval_local_decl s ldi env None in - return_continue new_env |: SemanticsRule.SDeclNone + return_continue new_env |: SemanticsRule.SDecl (* End *) | S_Print { args; debug } -> let* vs = List.map (eval_expr_sef env) args |> sync_list in diff --git a/asllib/Parser.mly b/asllib/Parser.mly index 9f650ccdd..6430ca27d 100644 --- a/asllib/Parser.mly +++ b/asllib/Parser.mly @@ -367,8 +367,8 @@ let fields == braced(tclist(typed_identifier)) let fields_opt == { [] } | fields (* Slices *) -let nslices == bracketed(nclist(slice)) -let slices == bracketed( clist(slice)) +let named_slices == bracketed(nclist(slice)) +let slices == bracketed( clist(slice)) let slice == | ~=expr; < Slice_Single > | e1=expr; COLON; e2=expr; < Slice_Range > @@ -379,9 +379,9 @@ let slice == let bitfields_opt == loption(bitfields) let bitfields == braced(tclist(bitfield)) let bitfield == - | s=nslices ; x=IDENTIFIER ; { BitField_Simple (x, s) } - | s=nslices ; x=IDENTIFIER ; bf=bitfields ; { BitField_Nested (x, s, bf) } - | s=nslices ; x=IDENTIFIER ; ty=as_ty ; { BitField_Type (x, s, ty) } + | s=named_slices ; x=IDENTIFIER ; { BitField_Simple (x, s) } + | s=named_slices ; x=IDENTIFIER ; bf=bitfields ; { BitField_Nested (x, s, bf) } + | s=named_slices ; x=IDENTIFIER ; ty=as_ty ; { BitField_Type (x, s, ty) } (* Also called ty in grammar.bnf *) let ty := diff --git a/asllib/Typing.ml b/asllib/Typing.ml index b074fd777..8414b4063 100644 --- a/asllib/Typing.ml +++ b/asllib/Typing.ml @@ -381,6 +381,7 @@ module Annotate (C : ANNOTATE_CONFIG) : S = struct open Property (C) module Fn = FunctionRenaming (C) + (* Begin ShouldReduceToCall *) let should_reduce_to_call env name st = match IMap.find_opt name env.global.subprogram_renamings with | None -> false @@ -391,7 +392,10 @@ module Annotate (C : ANNOTATE_CONFIG) : S = struct | None -> assert false | Some func_sig -> func_sig.subprogram_type = st) set + |: TypingRule.ShouldReduceToCall + (* End *) + (* Begin DisjointSlicesToPositions *) let disjoint_slices_to_diet loc env slices = let eval env e = match reduce_constants env e with @@ -424,6 +428,8 @@ module Annotate (C : ANNOTATE_CONFIG) : S = struct else fatal_from loc Error.(OverlappingSlices slices) in List.fold_left (one_slice loc env) Diet.Int.empty slices + |: TypingRule.DisjointSlicesToPositions + (* End *) let check_disjoint_slices loc env slices = if List.length slices <= 1 then ok @@ -993,15 +999,21 @@ module Annotate (C : ANNOTATE_CONFIG) : S = struct | _ -> None (* End *) + (* Begin CheckPositionsInWidth *) let check_diet_in_width loc slices width diet () = - let x = Diet.Int.min_elt diet |> Diet.Int.Interval.x - and y = Diet.Int.max_elt diet |> Diet.Int.Interval.y in - if 0 <= x && y < width then () + let min_pos = Diet.Int.min_elt diet |> Diet.Int.Interval.x + and max_pos = Diet.Int.max_elt diet |> Diet.Int.Interval.y in + if 0 <= min_pos && max_pos < width then + () |: TypingRule.CheckPositionsInWidth else fatal_from loc (BadSlices (Error.Static, slices, width)) + (* End *) + (* Begin CheckSlicesInWidth *) let check_slices_in_width loc env width slices () = let diet = disjoint_slices_to_diet loc env slices in check_diet_in_width loc slices width diet () + |: TypingRule.CheckSlicesInWidth + (* End *) (* Begin TBitField *) let rec annotate_bitfield ~loc env width bitfield : bitfield = @@ -1100,14 +1112,12 @@ module Annotate (C : ANNOTATE_CONFIG) : S = struct | None -> let e' = annotate_static_integer ~loc env e in ArrayLength_Expr e') - | ArrayLength_Enum (s, i) -> ( - let t_s = T_Named s |> here in - match (Types.make_anonymous env t_s).desc with - | T_Enum li when List.length li = i -> index - | _ -> conflict loc [ T_Enum [] ] t_s) + | ArrayLength_Enum (_, _) -> + assert (* Enumerated indices only exist in the typed AST. *) + false in T_Array (index', t') |> here |: TypingRule.TArray - (* Begin TRecordExceptionDecl *) + (* Begin TStructuredDecl *) | (T_Record fields | T_Exception fields) when decl -> ( let+ () = match get_first_duplicate fst fields with @@ -1119,10 +1129,9 @@ module Annotate (C : ANNOTATE_CONFIG) : S = struct List.map (fun (x, ty) -> (x, annotate_type ~loc env ty)) fields in match ty.desc with - | T_Record _ -> - T_Record fields' |> here |: TypingRule.TRecordExceptionDecl + | T_Record _ -> T_Record fields' |> here |: TypingRule.TStructuredDecl | T_Exception _ -> - T_Exception fields' |> here |: TypingRule.TRecordExceptionDecl + T_Exception fields' |> here |: TypingRule.TStructuredDecl | _ -> assert false (* Begin TEnumDecl *)) | T_Enum li when decl -> @@ -1180,46 +1189,41 @@ module Annotate (C : ANNOTATE_CONFIG) : S = struct - Rule WZCS: The width of a bitslice must be any non-negative, statically evaluable integer expression (including zero). *) - let rec tr_one s = + (* Begin Slice *) + let rec annotate_slice s = let () = if false then Format.eprintf "Annotating slice %a@." PP.pp_slice_list [ s ] in match s with - (* Begin SliceSingle *) | Slice_Single i -> (* LRM R_GXKG: The notation b[i] is syntactic sugar for b[i +: 1]. *) - tr_one (Slice_Length (i, !$1)) |: TypingRule.SliceSingle - (* End *) - (* Begin SliceLength *) + annotate_slice (Slice_Length (i, !$1)) |: TypingRule.Slice | Slice_Length (offset, length) -> let t_offset, offset' = annotate_expr env offset and length' = annotate_static_constrained_integer ~loc:(to_pos length) env length in let+ () = check_structure_integer offset' env t_offset in - Slice_Length (offset', length') |: TypingRule.SliceLength - (* End *) - (* Begin SliceRange *) + Slice_Length (offset', length') |: TypingRule.Slice | Slice_Range (j, i) -> (* LRM R_GXKG: The notation b[j:i] is syntactic sugar for b[i +: j-i+1]. *) let pre_length = binop MINUS j i |> binop PLUS !$1 in - tr_one (Slice_Length (i, pre_length)) |: TypingRule.SliceRange - (* End *) - (* Begin SliceStar *) + annotate_slice (Slice_Length (i, pre_length)) |: TypingRule.Slice | Slice_Star (factor, pre_length) -> (* LRM R_GXQG: The notation b[i *: n] is syntactic sugar for b[i*n +: n] *) let pre_offset = binop MUL factor pre_length in - tr_one (Slice_Length (pre_offset, pre_length)) |: TypingRule.SliceStar + annotate_slice (Slice_Length (pre_offset, pre_length)) + |: TypingRule.Slice (* End *) in - List.map tr_one + List.map annotate_slice and annotate_pattern loc env t = function (* Begin PAll *) @@ -1525,6 +1529,7 @@ module Annotate (C : ANNOTATE_CONFIG) : S = struct else (ty', E_ATC (e'', ty_struct) |> here)) |: TypingRule.ATC (* End *) + (* Begin EVar *) | E_Var x -> ( let () = if false then Format.eprintf "Looking at %S.@." x in if should_reduce_to_call env x ST_EmptyGetter then @@ -1545,7 +1550,6 @@ module Annotate (C : ANNOTATE_CONFIG) : S = struct in try match IMap.find x env.local.storage_types with - (* Begin ELocalVar *) | ty, LDK_Constant -> let e = try @@ -1555,24 +1559,16 @@ module Annotate (C : ANNOTATE_CONFIG) : S = struct in (ty, e) | ty, _ -> (ty, e) |: TypingRule.ELocalVar - (* End *) with Not_found -> ( try match IMap.find x env.global.storage_types with - (* Begin EGlobalVarConstant *) | ty, GDK_Constant -> ( match IMap.find_opt x env.global.constant_values with | Some v -> (ty, E_Literal v |> here) |: TypingRule.EGlobalVarConstantVal - (* End *) - (* Begin EGlobalVarConstantNoVal *) | None -> (ty, e) |: TypingRule.EGlobalVarConstantNoVal) - (* End *) - (* Begin EGlobalVar *) | ty, _ -> (ty, e) |: TypingRule.EGlobalVar - (* End *) - (* Begin EUndefIdent *) with Not_found -> let () = if false then @@ -2260,6 +2256,7 @@ module Annotate (C : ANNOTATE_CONFIG) : S = struct let () = assert (ty = None) in (S_Call (new_name, new_args, new_eqs) |> here, env) |: TypingRule.SCall (* End *) + (* Begin SReturn *) | S_Return e_opt -> (* Rule NYWH: A return statement appearing in a setter or procedure must have no return value expression. *) @@ -2267,15 +2264,10 @@ module Annotate (C : ANNOTATE_CONFIG) : S = struct requires a return value expression that type-satisfies the return type of the subprogram. *) (match (env.local.return_type, e_opt) with - (* Begin SReturnOne *) | None, Some _ | Some _, None -> fatal_from loc (Error.BadReturnStmt env.local.return_type) - |: TypingRule.SReturnOne - (* End *) - (* Begin SReturnNone *) - | None, None -> (S_Return None |> here, env) |: TypingRule.SReturnNone - (* End *) - (* Begin SReturnSome *) + |: TypingRule.SReturn + | None, None -> (S_Return None |> here, env) |: TypingRule.SReturn | Some t, Some e -> let t_e', e' = annotate_expr env e in let () = @@ -2286,7 +2278,7 @@ module Annotate (C : ANNOTATE_CONFIG) : S = struct in let+ () = check_type_satisfies s env t_e' t in (S_Return (Some e') |> here, env)) - |: TypingRule.SReturnSome + |: TypingRule.SReturn (* End *) (* Begin SCond *) | S_Cond (e, s1, s2) -> @@ -2407,16 +2399,14 @@ module Annotate (C : ANNOTATE_CONFIG) : S = struct | (LDK_Constant | LDK_Let), None -> fatal_from s UnrespectedParserInvariant) (* End *) - (* Begin SThrowSome *) + (* Begin SThrow *) | S_Throw (Some (e, _)) -> let t_e, e' = annotate_expr env e in let+ () = check_structure_exception s env t_e in - (S_Throw (Some (e', Some t_e)) |> here, env) |: TypingRule.SThrowSome - (* End *) - (* Begin SThrowNone *) + (S_Throw (Some (e', Some t_e)) |> here, env) |: TypingRule.SThrow | S_Throw None -> (* TODO: verify that this is allowed? *) - (s, env) |: TypingRule.SThrowNone + (s, env) |: TypingRule.SThrow (* End *) (* Begin STry *) | S_Try (s', catchers, otherwise) -> @@ -2425,9 +2415,11 @@ module Annotate (C : ANNOTATE_CONFIG) : S = struct let catchers' = List.map (annotate_catcher loc env) catchers in (S_Try (s'', catchers', otherwise') |> here, env) |: TypingRule.STry (* End *) + (* Begin SPrint *) | S_Print { args; debug } -> let args' = List.map (fun e -> annotate_expr env e |> snd) args in (S_Print { args = args'; debug } |> here, env) |: TypingRule.SDebug + (* End *) (* Begin AnnotateLoopLimit *) and annotate_loop_limit ~loc env = function @@ -2438,22 +2430,20 @@ module Annotate (C : ANNOTATE_CONFIG) : S = struct Some limit' |: TypingRule.AnnotateLoopLimit (* End *) + (* Begin Catcher *) and annotate_catcher loc env (name_opt, ty, stmt) = let ty' = annotate_type ~loc env ty in let+ () = check_structure_exception ty' env ty' in let env' = match name_opt with - (* Begin CatcherNone *) - | None -> env |: TypingRule.CatcherNone - (* End *) - (* Begin CatcherSome *) + | None -> env | Some name -> let+ () = check_var_not_in_env stmt env name in - add_local name ty LDK_Let env |: TypingRule.CatcherSome - (* End *) + add_local name ty LDK_Let env in let new_stmt = try_annotate_block env' stmt in - (name_opt, ty, new_stmt) + (name_opt, ty, new_stmt) |: TypingRule.Catcher + (* End *) (* Begin Block *) and try_annotate_block env s = diff --git a/asllib/doc/ASLFormal.tex b/asllib/doc/ASLFormal.tex index 7f5a55507..465096794 100644 --- a/asllib/doc/ASLFormal.tex +++ b/asllib/doc/ASLFormal.tex @@ -1,10 +1,10 @@ -\part{Formal System \label{part:FormalSystem}} +\chapter{Formal System \label{chap:FormalSystem}} In this part, we define the mathematical concepts and notations used throughout. We start by defining general mathematical concepts and then describe how sets of rules formally define functions and relations. -\chapter{Mathematical Definitions and Notations} +\section{Mathematical Definitions and Notations} \hypertarget{def-triangleq}{} We use $\triangleq$ to define mathematical concepts. @@ -326,7 +326,7 @@ \subsection{OCaml-style Notations} \end{definition} %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -\chapter{Inference Rules} +\section{Inference Rules} %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% An \emph{inference rule} (rule, for short) is an implication between a set of logical assertions, called the \emph{premises} of the rule, @@ -886,5 +886,5 @@ \subsection{Generic Notations} \item The notation $\commonsuffixline$ serves as a visual aid to delimit a common suffix of premises shared by rule cases. \hypertarget{tododefine}{} -\item \textbf{Missing definition:} Red hyperlinks indicate items that are yet to be defined. +\item \tododefine{Missing:} Red hyperlinks indicate items that are yet to be defined. \end{itemize} diff --git a/asllib/doc/ASLReference.tex b/asllib/doc/ASLReference.tex index 9b55773b4..725ce509b 100644 --- a/asllib/doc/ASLReference.tex +++ b/asllib/doc/ASLReference.tex @@ -11,6 +11,7 @@ \input{ASLStaticEnvLines} \input{ASLASTUtilsLines} \input{ASLASTLines} +\newcommand{\definitiontests}{../tests/ASLDefinition.t/} \newcommand{\syntaxtests}{../tests/ASLSyntaxReference.t/} \newcommand{\typingtests}{../tests/ASLTypingReference.t/} \newcommand{\semanticstests}{../tests/ASLSemanticsReference.t/} @@ -34,10 +35,46 @@ \include{notice.tex} \include{disclaimer.tex} +% \input{ASLFormal.tex} +% \input{ASLSyntaxReference.tex} +% \input{ASLTypingReference.tex} +% \input{ASLSemanticsReference.tex} + +\input{introduction.tex} \input{ASLFormal.tex} -\input{ASLSyntaxReference.tex} -\input{ASLTypingReference.tex} -\input{ASLSemanticsReference.tex} +\input{LexicalStructure.tex} +\input{Syntax.tex} +\input{AbstractSyntax.tex} +\input{TypeChecking.tex} +\input{Semantics.tex} +% explain the order - going over the AST - graphic depiction of navigation map +\input{Literals.tex} +\input{PrimitiveOperations.tex} +\input{Types.tex} +\input{Bitfields.tex} +\input{Expressions.tex} +\input{PatternMatching.tex} +\input{Slicing.tex} +\input{AssignableExpressions.tex} +\input{LocalStorageDeclarations.tex} +\input{Statements.tex} +\input{BlockStatements.tex} +\input{CatchingExceptions.tex} +\input{SubprogramCalls.tex} + +\input{GlobalDeclarations.tex} +\input{GlobalStorageDeclarations.tex} +\input{TypeDeclarations.tex} +\input{SubprogramDeclarations.tex} +\input{Specifications.tex} + +\input{StaticEvaluation.tex} +\input{SymbolicSubsumptionTesting.tex} +\input{SymbolicEquivalenceTesting.tex} +\input{TypeSystemUtilities.tex} +\input{SemanticsUtilities.tex} +\input{ErrorCodes.tex} +\chapter{Standard Library} \bibliographystyle{plain} \bibliography{ASL} diff --git a/asllib/doc/ASLSemanticsReference.tex b/asllib/doc/ASLSemanticsReference.tex deleted file mode 100644 index 67fa37f4f..000000000 --- a/asllib/doc/ASLSemanticsReference.tex +++ /dev/null @@ -1,6630 +0,0 @@ -% \documentclass{book} -% \input{ASLmacros} - -% Increase indentation of sections in the table of contents -% to allow a space between the section numbers and their titles. -% \makeatletter -% \renewcommand{\l@section}{\@dottedtocline{1}{1.5em}{2.6em}} -% \makeatother -% \setcounter{tocdepth}{1} - -% \author{Arm Architecture Technology Group} -% \title{ASL Semantics Reference \\ -% DDI 0621} -% \begin{document} -% \maketitle - -% \tableofcontents{} - -% \include{notice.tex} - -% \include{disclaimer.tex} - -\part{ASL Semantics Reference \label{part:ASLSemanticsReference}} - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -\chapter{Introduction} -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - -The semantics of ASL define all valid behaviors of a given ASL specification. -More precisely, an ASL specification is first parsed into an \emph{abstract syntax tree}, -or AST, for short. Second, a type checker analyzes the \emph{untyped AST} to determine whether it -is well-typed and, if successful, returns a \emph{static environment} and a \emph{typed AST}. -Otherwise, it returns a type error. - -Tools such as interpreters, Verilog simulators, and verifiers can operate over the typed AST, based on the definition -of the semantics in this document, to test and analyze a given specification. - -\paragraph{Understanding the Semantics Formalization:} -We assume basic familiarity with the ASL language constructs. -The ASL semantics is defined in terms of its AST, -and as a consequence familiarity with the AST is required to understand the semantics. -The few components of the type system needed to understand the ASL semantics are explained in context. -The mathematical background needed to understand the mathematical formalization -of the ASL semantics appears in \partref{FormalSystem} and \chapref{semanticsbuildingblocks}. - -\section{When Do ASL Specifications Have Meaning \label{sec:MeaningfulASLSpecifications}} -The ASL semantics defined here assign meaning only to \emph{well-typed specifications}. -That is, specifications for which the type-checker produces a static environment rather than -a type error. -Specifications that are not well-typed have no defined semantics. -In the rest of this document, we assume well-typed specifications. - -ASL admits non-determinism, for example via the \texttt{UNKNOWN} expression. -This means that a given specification might have (potentially infinitely) many -\hyperlink{def-derivationtree}{derivation trees}. - -An ASL specification is \emph{terminating} when \underline{all} of its derivation trees are finite. - -Although ASL does not require specifications to terminate, the semantics defined in this -document assign meaning only to terminating specifications. -A future version of this document, will assign meaning to non-terminating specifications. - -\section{Basic Semantic Concepts} -The ASL semantics are given by relations between \emph{semantic configurations}, -or \hyperlink{def-configuration}{\emph{configurations}}~\cite{SemanticsWithApplicationsBook}, for short. -We refer to relations between semantic configurations as \emph{semantic relations}. -Configurations encapsulate information needed to transition into other configurations, such as: -\begin{itemize} - \item a \emph{dynamic environment}, which binds variables to values; - \item the typed AST node that needs to be evaluated; - \item a \emph{concurrent execution graph}, as per a given memory model; and - \item values resulting from evaluating expressions. -\end{itemize} -The semantic relations are constructively defined via \emph{semantic rules}. -These semantic rules are defined by induction over the typed AST. - -\paragraph{Execution:} -A valid execution of an ASL specification transitions from an \emph{initial configuration}, -which consists of the given specification and the standard library specification, to an output configuration -consisting of an output value and a concurrent execution graph. - -\paragraph{Primitive Subprograms:} -The semantics of ASL are parameterized by a set of primitive subprograms --- -subprograms whose implementation is not defined by ASL statements and whose effect on the dynamic environment -is defined externally. Critically, access to memory is given by primitive subprograms. - -We define two types of semantics --- \emph{sequential semantics} and \emph{concurrent semantics}. - -\paragraph{Concurrent Semantics:} -The concurrent semantics operate over concurrent execution graphs. -Intuitively, these graphs define Read Effects and Write Effects to variables and constraints over those effects. -Together with the constraints that define a given memory model (such as the ARM memory model~\cite{AlglaveDGHM21}), -these graphs axiomatically define -the valid interactions of shared variables of a given specification. - -\paragraph{Sequential Semantics:} -The sequential semantics correspond to executing an ASL specification in the context of a single thread -of execution; notice that ASL does not contain any concurrency constructs. -% -Technically, the sequential semantics are defined by omitting the concurrent execution graph components -from all configurations. - -\paragraph{Reading guide:} -The semantic rules are organized into chapters, which roughly group the rules -by their AST node type. The set of rules in each chapter is further split -according to additional syntactic and semantic predicates over the AST node. -For example, expressions are split into literal expressions, binary operation -expressions, etc. Each such subset of rules is named accordingly and appears -in a section with the same name. For example, the rule for literal expressions -is named SemanticsRule.Lit and defined in \secref{SemanticsRule.Lit}. - -Sometimes rules are split into cases. We then drop the SemanticsRule prefix -from each case, for succinctness. The same convention applies to helper rules. - -Each rule is presented using the following template: -\begin{itemize} -\item a Prose paragraph gives the rule in English, and corresponds, as much as possible, to the code of the reference implementation ASLRef given at - \href{https://github.com/herd/herdtools7//tree/master/asllib}{/herdtools7/asllib}; - - \item one or several Example paragraphs, which, as much as possible, are also given as regression tests in -\href{https://github.com/herd/herdtools7//tree/master/asllib/tests/ASLSemanticsReference.t}{/herdtools7/asllib/tests/ASLSemanticsReference.t}; - -\ifcode -\item a Code paragraph which gives a verbatim of the corresponding OCaml implementation in the interpreter of ASLRef -\href{https://github.com/herd/herdtools7//tree/master/asllib/Interpreter.ml}{/herdtools7/asllib/Interpreter.ml}; -\fi - -\item a Formal paragraph, which provides semantic rules that essentially give the same information as the Prose paragraph, for both -the sequential semantics and the concurrent semantics, in the form of concurrent execution graphs. -The latter enables defining, for each AArch64 instruction, -the Intrinsic dependencies used by the AArch64 memory model from the ASL code of the instruction~\cite[B2.3.2]{ArmARM}. - -\item Comments paragraphs, which provide additional details. -\end{itemize} - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -\chapter{Semantics Building Blocks} -\label{chap:semanticsbuildingblocks} -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -This chapter defines the mathematical types over which our semantics are defined. -An \hyperlink{eval-example}{example} of semantic evaluation appears at the end. - -\section{Semantic Configurations \label{sec:configurations}} - -In the remainder of this document, we use the term configurations to refer to semantic configurations. - -Configurations express intermediate states related by \emph{semantic relations}. -% -More precisely, semantic relations relate two distinct sets of configurations --- -\emph{input configurations} and \emph{output configurations}. -Input configurations consist of an environment and an AST node. -Output configurations consist of an output environment, values, -and concurrent execution graphs. -% -Configurations wrap together elements such as environments and AST nodes -and associate them with a \emph{configuration domain}. Input configuration domains -determine the semantic relation they pertain to, while output configuration -domains distinguish between conceptually different kinds of outputs, for example -ones where an exception was raised, ones when a dynamic error occurred, etc. - -We now explain the components over which configurations are defined: -\begin{itemize} - \item Static Environments, which consist of the information inferred - by the type-checker for the specification. - \item Dynamic Environments (\defref{dynamicenvironments}) associate \nativevalues\ to variables. - \item Concurrent Execution Graphs (\secref{concurrentexecutiongraphs}) track Read and Write Effects over variables. -\end{itemize} -\newpage -\hypertarget{def-dynamicenvs}{} -\begin{definition}[Dynamic Environments\label{def:dynamicenvironments}] -A \emph{sequential dynamic environment}, or \\ \emph{dynamic environment}, for short, is a structure which, -associates \nativevalues\ to variables. -Formally, a sequential environment $\denv \in \dynamicenvs$ is a pair consisting of a partial function -(see \defref{PartialFunction}) from global -variable names to their \nativevalue, and a partial function from local variable names to their -\nativevalues: -\[ -\begin{array}{rcl} - \dynamicenvs &\triangleq& \mathbb{G} \times \mathbb{L} \\ - \mathbb{G} &\triangleq& (\Identifiers \partialto \vals) \\ - \mathbb{L} &\triangleq& (\Identifiers \partialto \vals) \\ -\end{array} -\] -\end{definition} - -\paragraph{Static Environments} -A \emph{static environment} (see \secref{StaticEnvironments}) $\tenv \in \staticenvs$ (also referred to as a \emph{type environment}) -is produced by the type-checker from the untyped AST. - -We assume that the static environment supports the following functions: -\hypertarget{def-findfunc}{} -\hypertarget{def-typesatisfies}{} -\[ - \begin{array}{rcl} - \findfunc &:& \staticenvs \times \Identifiers \partialto \func\\ - \typesat &:& \staticenvs \times (\ty \times \ty) \rightarrow \{\True, \False\} - \end{array} -\] -The partial function $\findfunc$ returns the typed AST of the subprogram for a given identifier. -(Recall that ASL allows subprogram overloading so a name does not uniquely identify -a specific subprogram. -However, the type-checker renames each function uniquely so that it can be accessed based -on its name alone.) -% -The function $\typesat(\vt, \vs)$ returns true -if the type $\vt$ \emph{type-satisfies} the type $\vs$ -(see \secref{TypingRule.TypeSatisfaction}). -This is used in matching a raised exception to a corresponding catch clause. - -\hypertarget{def-envs}{} -\begin{definition}[Environments] -Environments pair static environments with dynamic environments: -$\envs = \staticenvs \times \dynamicenvs$. -\end{definition} -\hypertarget{def-env}{} -We write $\env \in \envs$ to range over environments. -% -From the perspective of the semantics, the static environment is immutable. -That is, all environments share the same static environment. - -\subsection{Concurrent Execution Graphs \label{sec:concurrentexecutiongraphs}} - -The concurrent semantics of an ASL specification utilize \emph{concurrent execution graphs} -(\emph{execution graphs}, for short), -which track the Read and Write Effects over variables, yielded by the sequential semantics, -and the \emph{ordering constraints} between those effects. -The graphs resulting from executing an ASL specification are converted into -\emph{candidate execution graphs}, which are introduced, defined, -and used in~\cite{AlglaveMT14,alglave2016syntax,AlglaveDGHM21}. - -\hypertarget{def-xgraphs}{} -Formally, an execution graph $\xgraph = (N^\xgraph, E^\xgraph, O^\xgraph) \in \XGraphs$ -is defined via a set of \emph{nodes} ($N^\xgraph$), a set of \emph{edges} ($E^\xgraph$), and a set of \emph{output nodes} ($O^\xgraph$): -\hypertarget{def-nodes}{} -\[ -\begin{array}{rcl} -\XGraphs &\triangleq& \pow{\Nodes} \times \pow{\Nodes \times \Nodes \times \Labels} \times \pow{\Nodes} \hypertarget{def-read}{}\hypertarget{def-write}{}\\ -\Nodes &\triangleq& \N \times \{ \Read, \Write \} \times \Identifiers \hypertarget{def-labels}{}\\ -\Labels &\triangleq& \{ \asldata, \aslctrl, \aslpo \} -\end{array} -\] - -Nodes represent unique Read and Write Effects. Formally, a node $(u,l,\id) \in \Nodes$ associates a unique instance counter $u$ -to an \emph{ordering label} $l$, which specifies whether it represents a Read Effect of a Write Effect to a variable named $\id$. -% -We say that en Effect \texttt{E1} is \emph{$l$-before} another Effect \texttt{E2}, for $l\in \Labels$ and a given execution graph -$g$, when $(\texttt{E1}, l, \texttt{E2}) \in E^g$. - -An edge represents an ordering constraint between two effects, which can be one of the following: -\hypertarget{def-asldata}{} -\begin{description} -\item[$\asldata$] Represents a \emph{data dependency}. -That is, when one effect hands over its data to another effect. -\hypertarget{def-aslctrl}{} -\item[$\aslctrl$] Represents a \emph{control dependency}. -That is, when a Read Effect to a variable determines the flow of control (e.g., which condition of a branch is taken), -which then leads to another Read/Write Effect. -\hypertarget{def-aslpo}{} -\item[$\aslpo$] Represents a \emph{program order}. -That is, when two Effects are generated by ASL constructs, which are separated by a semicolon in the text of the specification, -or appear in successive iterations of loop a unrolling. -% That is, when two effects are defined to be ordered according to the sequential semantics. -\end{description} - -An execution graph is \emph{well-formed} if all nodes have unique instance counters, edges connect graph nodes, -and the output nodes are contained in the set of nodes: -\[ - \begin{array}{rcl} - \forall n, n' \in N^\xgraph &.& n=(u,l,\id) \wedge n=(u',l',\id') \;\Rightarrow\; u \neq u' \\ - \forall e \in E^\xgraph &.& e=(n, n', l) \;\Rightarrow\; n, n' \in N^\xgraph \\ - & & O^\xgraph \subseteq N^\xgraph \enspace. - \end{array} -\] -\hypertarget{def-emptygraph}{} - -We denote the empty execution graph $\emptygraph \triangleq (\emptyset, \emptyset, \emptyset)$. -% -We define the following functions, which return an execution graph that represents a single Read/Write Effect to a variable \texttt{x}. -\hypertarget{def-writeeffect}{} -\hypertarget{def-readeffect}{} -\begin{definition}[Read/Write Effects] -\[ - \begin{array}{rclll} - \WriteEffect(\vx) &\triangleq& (\{n\}, \emptyset, \{n\}) & \text{where } n=(u, \Write, \vx), & u\in\N \text{ is fresh}\\ - \ReadEffect(\vx) &\triangleq& (\{n\}, \emptyset, \{n\}) & \text{where } n=(u, \Read, \vx), & u\in\N \text{ is fresh}\\ - \end{array} -\] -\end{definition} - -We also define two ways to compose execution graphs --- \emph{unordered composition} and -\emph{ordered composition with a given label}. - -\hypertarget{def-parallel}{} -\begin{definition}[Unordered Graph Composition] -Given two execution graphs $S_1 = (N_1, E_1, O_1)$ and $S_1 = (N_2, E_2, O_2)$ their unordered composition, -denoted $S_1 \parallelcomp S_2$ is defined as follows: -\[ - S_1 \parallelcomp S_2\triangleq (N_1 \cup N_2, E_1 \cup E_2, O_1 \cup O_2) \enspace. -\] -Intuitively, this composition conveys the fact that there are no ordering constraints between the effects -in the arguments graphs. -\end{definition} - -\hypertarget{def-ordered}{} -\begin{definition}[Ordered Graph Composition] -Given two execution graphs, \\ $S_1 = (N_1, E_1, O_1)$ and $S_1 = (N_2, E_2, O_2)$ and an ordering label $l$, -the ordered composition $\ordered{S_1}{l}{S_2}$ is defined as follows: -\[ - \ordered{S_1}{l}{S_2} \triangleq (N_1 \cup N_2,\ E_1 \cup E_2 \cup (O_1 \times \{l\} \times N_2),\ O_2) \enspace. -\] -Intuitively, this composition constrains the output effects of $S_1$ to appear before any effect of $S_2$ with respect -to the given ordering label. -\end{definition} - -\subsection{Kinds of Semantic Configurations \label{sec:KindsOfSemanticConfigurations}} - -Recall that the ASL semantics defines a relation between input configurations and output configurations -(\secref{configurations}). -Input configuration domains are unique to the semantic relation that employs them. -For that reason, we name semantic relations by the name of the corresponding input configuration domain. -For example, the semantic relation that employs input configurations with the domain $\texttt{eval\_expr}$ -is named $\texttt{eval\_expr}$. -% -We will often use the prefix \texttt{eval} for semantic relations with the intuition being that their input configurations -should be semantically evaluated, yielding an output configuration. - -ASL semantics mainly utilizes the following types of output configurations: -\begin{description} - \item[Normal Values.] \hypertarget{def-normal}{} - Configurations consisting of different combinations of values, - execution graphs, and environments, representing intermediate results - generated while evaluating statements: - \begin{itemize} - \item $\Normal(\vals \times \XGraphs)$, - \item $\Normal((\vals \times \XGraphs), \envs)$, - \item $\Normal(((\vals \times \vals)^* \times \XGraphs), \envs)$, - \item $\Normal(\XGraphs, \envs)$, - \item $\Normal((\vals^* \times \XGraphs), \envs)$, and - \item $\Normal((\vals\times\XGraphs)^*, \envs)$. - \end{itemize} - - \hypertarget{def-throwing}{} - \item[Exceptions.] Configurations in - \[ - \Throwing(\langle \valuereadfrom(\vals,\Identifiers) \times \ty\rangle \times \XGraphs, \envs) - \] - represent thrown exceptions. - \hypertarget{def-valuereadfrom}{} - - There are two flavors of exceptions: - exceptions without an exception value (as in \texttt{throw;}), and ones with an exception value, - an identifier to which the Read Effect is attributed, and an associated type. - The type $\valuereadfrom(\vals,\Identifiers)$ is a configuration nested inside an exception configuration. - The ASL semantics propagates these \emph{exceptional configurations} to the nearest catch clause that matches - them, and otherwise they are caught at the top-level and reported as errors (see dynamic errors below). - - \hypertarget{def-returning}{} - \item[Returned Values.] Configurations in $\Returning((\vals^* \times \XGraphs), \envs)$ - represent (tuples of) values being returned by the currently executing subprogram. - The ASL semantics propagates these \emph{early return configurations} to the respective call expression/statement. - - \hypertarget{def-continuing}{} - \item[In-flight Subprogram.] Configurations in $\Continuing(\XGraphs, \envs)$ - represent the fact that a subprogram has more statements to execute. - The ASL semantics treats these configurations as a signal to keep evaluating the remainder - of the subprogram currently being evaluated. -%where is this used? - - \hypertarget{def-error}{} - \item[Dynamic Errors.] Configurations in $\Error(\Strings)$ - represent dynamic errors (for example, division by zero). - The ASL semantics is set up such that when these \emph{error configurations} appear, - the evaluation of the entire specification terminates by outputting them. -\end{description} -Helper relations often have output configurations that are just tuples, without an associated configuration domain. - -We define the following shorthands for types of output configurations: -\hypertarget{def-tnormal}{} -\hypertarget{def-tcontinuing}{} -\hypertarget{def-tthrowing}{} -\hypertarget{def-treturning}{} -\hypertarget{def-terror}{} -\[ - \begin{array}{rcl} - \TNormal & \triangleq & \Normal(\vals, \XGraphs) \cup \Normal((\vals \times \XGraphs), \envs)\ \cup \\ - & & \Normal(((\vals \times \vals)^* \times \XGraphs), \envs) \cup \Normal(\XGraphs, \envs)\ \cup \\ - & & \Normal((\vals^* \times \XGraphs), \envs) \cup \Normal((\vals\times\XGraphs)^*, \envs)\\ - \TThrowing & \triangleq & \Throwing(\langle\vals \times \ty\rangle \times \XGraphs, \envs)\\ - \TContinuing & \triangleq & \Continuing(\XGraphs, \envs)\\ - \TReturning & \triangleq & \Returning((\vals^* \times \XGraphs), \envs)\\ - \TError & \triangleq & \Error(\texttt{})\\ - \end{array} -\] - -We will say that a semantic transition \emph{terminates}: -\begin{itemize} -\item \emph{normally} when the output configuration domain is -$\Normal$, -\item \emph{exceptionally} when the output configuration domain is -$\Throwing$, -\item \emph{erroneously} when the output configuration domain is -$\Error$, and -\item \emph{abnormally} when it either terminates exceptionally or -erroneously. -\end{itemize} - -We introduce the following shorthands for configurations where all variables -appearing are \hyperlink{def-freshvariables}{fresh}: -\begin{itemize} -\hypertarget{def-throwingconfig}{} -\item $\ThrowingConfig \triangleq \Throwing((\vv, \vg), \newenv)$. -\hypertarget{def-errorconfig}{} -\item $\ErrorConfig \triangleq \Error(\vs)$. -\hypertarget{def-returningconfig}{} -\item $\ReturningConfig \triangleq \Returning((\vvs,\newg), \newenv)$ -is an early return configuration. -\hypertarget{def-continuingconfig}{} -\item $\ContinuingConfig \triangleq \Continuing(\newg, \newenv)$. -\end{itemize} - -\subsection{Extracting and Substituting Elements of Configurations} - -\hypertarget{def-graphof}{} -\hypertarget{def-environof}{} -Given a configuration $C$, we define the graph component of the configuration, \\ -$\graphof{C}$, and the environment of the configuration, $\environof{C}$, as follows: -\[ -\begin{array}{lcc} - C & \graphof{C} & \environof{C}\\ - \hline - \Normal(\vv,\vg) & \vg & \text{undefined}\\ - \Normal((\vv,\vg), \env) & \vg & \env\\ - \Normal(([i=1..k: (\texttt{va}_i,\texttt{vb})],\vg), \env) & \vg & \env\\ - \Normal(\vg, \env) & \vg & \env\\ - \Normal([\vv_{1..k}], \vg) & \vg & \env\\ - \Normal([i=1..k: (\vv_i,\vg_i)], \env) & \text{undefined} & \env\\ - \Throwing((\valuereadfrom(\vx,\vv),\vg), \env) & \vg & \env\\ - \Returning(([\vv_{1..k}],\vg), \env) & \vg & \env\\ - \Continuing(\vg, \env) & \vg & \env\\ -\end{array} -\] - -\hypertarget{def-withgraph}{} -Given a configuration $C$, we define $\withgraph{C}{\vgp}$ to be a configuration -like $C$ where the graph component is substituted with $\vgp$: -\[ -\begin{array}{ll} - C & \withgraph{C}{\vgp}\\ - \hline - \Normal(\vv,\vg) & \Normal(\vv,\vgp)\\ - \Normal((\vv,\vg), \env) & \Normal((\vv,\vgp), \env)\\ - \Normal((i=1..k: (\texttt{va}_i,\texttt{vb}),\vg), \env) & \Normal((i=1..k: (\texttt{va}_i,\texttt{vb}),\vgp), \env)\\ - \Normal(\vg, \env) & \Normal(\vgp, \env)\\ - \Normal(i=1..k: \vv_i, \vg) & \Normal(i=1..k: \vv_i, \vgp)\\ - \Normal([i=1..k: (\vv_i,\vg_i)], \env) & \text{undefined}\\ - \Throwing((\valuereadfrom(\vx,\vv),\vg), \env) & \Throwing((\valuereadfrom(\vx,\vv),\vgp), \env)\\ - \Returning((i=1..k: \vv_i,\vg), \env) & \Returning((i=1..k: \vv_i,\vgp), \env)\\ - \Continuing(\vg, \env) & \Continuing(\vgp, \env)\\ -\end{array} -\] -\hypertarget{def-withenviron}{} -Similarly, we define the $\withenviron{C}{\envp}$ to be a configuration -like $C$ where the environment component, if one exists, is substituted with $\envp$: -\[ -\begin{array}{ll} - \textbf{Configuration} & \withenviron{C}{\envp}\\ - \hline - \Normal(\vv,\vg) & \text{undefined}\\ - \Normal((\vv,\vg), \env) & \Normal((\vv,\vg), \envp)\\ - \Normal((i=1..k: (\texttt{va}_i,\texttt{vb}),\vg), \env) & \Normal((i=1..k: (\texttt{va}_i,\texttt{vb}),\vg), \envp)\\ - \Normal(\vg, \env) & \Normal(\vg, \envp)\\ - \Normal(i=1..k: \vv_i, \vg) & \Normal(i=1..k: \vv_i, \vg)\\ - \Normal([i=1..k: (\vv_i,\vg_i)], \env) & \Normal([i=1..k: (\vv_i,\vg_i)], \envp)\\ - \Throwing((\valuereadfrom(\vx,\vv),\vg), \env) & \Throwing((\valuereadfrom(\vx,\vv),\vg), \envp)\\ - \Returning((i=1..k: \vv_i,\vg), \env) & \Returning((i=1..k: \vv_i,\vg), \envp)\\ - \Continuing(\vg, \env) & \Continuing(\vg, \envp)\\ -\end{array} -\] - -\section{Semantic Evaluation} -\hypertarget{def-evalrel}{} -\hypertarget{def-primitiverel}{} -The semantics of ASL is given by the relations\footnote{The reason that relations, rather than functions, are used is due to the -potential non-determinism in the primitive subprograms -and the non-determinism inherent in the \texttt{UNKNOWN} expression.} -\evalrel\ and \primitiverel. -The relation \evalrel\ is defined as the disjoint union of the relations defined in this document. -The relation \primitiverel\ provides the semantics of primitive subprograms and is not otherwise defined -constructively. - -\subsection{Natural Operational Semantics} -We define the ASL semantics in the style of \emph{natural operational semantics}~\cite{SemanticsWithApplicationsBook} -(also known as \emph{big step semantics}). -Natural operational semantics evaluates the AST inductively. -That is, it concludes transitions for configurations starting from -non-leaf AST nodes by concluding transitions from configurations starting from their children nodes. - -\subsubsection{No Undefined Behaviors} -When an input configuration does not satisfy any semantic rule, -there is no output configuration for it to transition to. We say that -the configuration is \emph{stuck} and the ASL semantics is undefined for that -input configuration. - -The ASL semantics is defined for well-typed ASL specifications -and gets stuck only in cases of non-terminating specifications -(due to non-terminating loops, or infinite recursion). -Otherwise, for every input configuration there is at least one rule that can be used to take a semantic transition. - -\hypertarget{eval-example}{} -\subsubsection{Evaluation Example} -\newcommand\elint[1]{\ELiteral(\lint(#1))} -The following example shows how to utilize the rules for expression literals and binary operator expressions -to derive a transition from an input configuration with the expression $(1+2)*(4+5)$, -given by the AST -\[ - \begin{array}{rl} - \EBinop(\MUL, &\overname{\EBinop(\PLUS, \overname{\elint{1}}{\veone}, \overname{\elint{2}}{\vetwo})}{\veonetwo}, \\ - &\overname{\EBinop(\PLUS, \overname{\elint{4}}{\vefour}, \overname{\elint{5}}{\vefive})}{\vefourfive}) - \end{array} -\] -to an output configuration with the value resulting from the calculation of the expression. - -We annotate subexpressions to allow referring to them. - -\hypertarget{def-emptyenv}{} -We write $\emptyenv$ to stand for a trivial environment (that is, one where all functions are empty). - -Notice that, we have dropped the execution graph component and simplified pairs of the form $(\vv,\vg)$, -where $\vv$ is a \nativevalue\ and $\vg$ is an execution graph, to just $\vv$. -This is because we are interested in demonstrating the sequential semantics (also, the execution graphs -in this case are all empty). - -The example shows (using references to the relevant rules on the right), how the expression for $1+2$ is evaluated -using the rule for literal expressions, the rule for binary operator (for addition), and the rules for binary expressions. -Similarly, the expression for $4+5$ is evaluated. -Finally, the transitions for both of the subexpressions are used as premises for the binary expression -rule, along with the rule for binary operator (for multiplication), to evaluate the entire expression. - -\begin{mathpar} - \inferrule*[right=\ref{sec:SemanticsRule.Binop}]{ - \inferrule*[right=\ref{sec:SemanticsRule.Lit}]{}{ \evalexpr{\emptyenv, \veone} \evalarrow \Normal(\nvint(1), \emptyenv) } \\\\ - \inferrule*[right=\ref{sec:SemanticsRule.Lit}]{}{ \evalexpr{\emptyenv, \vetwo} \evalarrow \Normal(\nvint(2), \emptyenv) } \\\\ - \inferrule*[right=\ref{sec:SemanticsRule.BinopValues}]{}{\binoprel(\PLUS, \nvint(1), \nvint(2)) \evalarrow \nvint(3)} - } - { - \evalexpr{ \emptyenv, \veonetwo } \evalarrow - \Normal(\nvint(3), \emptyenv) - } -\end{mathpar} - -\begin{mathpar} - \inferrule*[right=\ref{sec:SemanticsRule.Binop}]{ - \inferrule*[right=\ref{sec:SemanticsRule.Lit}]{}{ \evalexpr{\emptyenv, \vefour} \evalarrow \Normal(\nvint(4), \emptyenv) } \\\\ - \inferrule*[right=\ref{sec:SemanticsRule.Lit}]{}{ \evalexpr{\emptyenv, \vefive} \evalarrow \Normal(\nvint(5), \emptyenv) } \\\\ - \inferrule*[right=\ref{sec:SemanticsRule.BinopValues}]{}{\binoprel(\PLUS, \nvint(4), \nvint(5)) \evalarrow \nvint(9)} - } - { - \evalexpr{ \emptyenv, \vefourfive } \evalarrow - \Normal(\nvint(9), \emptyenv) - } -\end{mathpar} - -\begin{mathpar} - \inferrule*[right=\ref{sec:SemanticsRule.Binop}]{ - \evalexpr{ \emptyenv, \veonetwo } \evalarrow \Normal(\nvint(3), \emptyenv)\\ - \evalexpr{ \emptyenv, \vefourfive } \evalarrow \Normal(\nvint(9), \emptyenv)\\ - \inferrule*[right=\ref{sec:SemanticsRule.BinopValues}]{}{\binoprel(\MUL, \nvint(3), \nvint(9)) \evalarrow \nvint(27)} - } - { - \evalexpr{ \emptyenv, \EBinop(\MUL, \veonetwo, \vefourfive) } \evalarrow - \Normal(\nvint(27), \emptyenv) - } -\end{mathpar} - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -\chapter{Evaluation of Expressions \label{chap:eval_expr}} -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - -% \section{Informal Preamble} - -% \lrmcomment{This is related to Section 8.3:} - -% \subsection{Execution-time expressions} - -% \lrmcomment{This is related to \identi{XYKC}:} - -% Expressions in ASL are either execution-time expressions or non-execution-time -% expressions. - -% \lrmcomment{This is related to \identd{ZPMF}:} - -% An expression is an execution-time expression if either: -% \begin{itemize} -% \item it contains an execution-time storage element identifier -% \item it contains an execution-time function or getter invocation -% \end{itemize} - -% \subsection{Compile-time-constant expressions} - -% \lrmcomment{This is related to \identi{XSFY}:} - -% Expressions in ASL are either compile-time-constant expressions or -% non-compile-time-constant expressions. - -% \lrmcomment{This is related to \identd{XRBT}:} - -% An expression is a compile-time-constant expression if each one of its atomic expressions is one of: -% \begin{itemize} -% \item a literal constant -% \item a compile-time-constant storage element identifier -% \item an immutable storage element identifier with a compile-time-constant initializer expression. -% \item compile-time-constant function or getter invocations -% \end{itemize} -% \section{Formal Preamble} - -The relation -\hypertarget{def-evalexpr}{} -\[ - \evalexpr{\overname{\envs}{\env} \aslsep \overname{\expr}{\ve}} \;\aslrel\; - \Normal((\overname{\vals}{\vv} \times \overname{\XGraphs}{\vg}) \aslsep \overname{\envs}{\newenv}) \cup - \overname{\TThrowing}{\ThrowingConfig} \cup \overname{\TError}{\ErrorConfig} -\] -evaluates the expression $\ve$ in an environment $\env$ and one of the following applies: -\begin{itemize} - \item the evaluation terminates normally, returning a \nativevalue\ $\vv$, a concurrent execution graph $\vg$, - and a modified environment $\newenv$; - \item the evaluation terminates abnormally. -\end{itemize} - -The evaluation of an expression is specialized by the shape of the expression $\ve$, -and one of the following applies: -\begin{itemize} -\item SemanticsRule.Lit (see Section~\ref{sec:SemanticsRule.Lit}); -\item SemanticsRule.ELocalVar (see Section~\ref{sec:SemanticsRule.ELocalVar}) -\item SemanticsRule.EGlobalVar (see Section~\ref{sec:SemanticsRule.EGlobalVar}) -\item SemanticsRule.BinopAnd (see Section~\ref{sec:SemanticsRule.BinopAnd}) -\item SemanticsRule.BinopOr (see Section~\ref{sec:SemanticsRule.BinopOr}) -\item SemanticsRule.BinopImpl (see Section~\ref{sec:SemanticsRule.BinopImpl}) -\item SemanticsRule.Binop (see Section~\ref{sec:SemanticsRule.Binop}) -\item SemanticsRule.Unop (see Section~\ref{sec:SemanticsRule.Unop}) -\item SemanticsRule.ECond (see Section~\ref{sec:SemanticsRule.ECond}) -\item SemanticsRule.ESlice (see Section~\ref{sec:SemanticsRule.ESlice}) -\item SemanticsRule.ECall (see Section~\ref{sec:SemanticsRule.ECall}) -\item SemanticsRule.EGetArray (see Section~\ref{sec:SemanticsRule.EGetArray}) -\item SemanticsRule.ERecord (see Section~\ref{sec:SemanticsRule.ERecord}) -\item SemanticsRule.EGetField (see Section~\ref{sec:SemanticsRule.EGetField}) -\item SemanticsRule.EConcat (see Section~\ref{sec:SemanticsRule.EConcat}) -\item SemanticsRule.ETuple (see Section~\ref{sec:SemanticsRule.ETuple}) -\item SemanticsRule.EUnknown (see Section~\ref{sec:SemanticsRule.EUnknown}) -\item SemanticsRule.EPattern (see Section~\ref{sec:SemanticsRule.EPattern}) -\item SemanticsRule.ATC (see Section~\ref{sec:SemanticsRule.ATC}) -\end{itemize} - -We also define the following helper relations: -\begin{itemize} - \item SemanticsRule.EExprList (see Section~\ref{sec:SemanticsRule.EExprList}); - \item SemanticsRule.EExprListM (see Section~\ref{sec:SemanticsRule.EExprListM}); - \item SemanticsRule.ESideEffectFreeExpr (see Section~\ref{sec:SemanticsRule.ESideEffectFreeExpr}); -\end{itemize} - -\section{SemanticsRule.Lit \label{sec:SemanticsRule.Lit}} -\subsection{Prose} -All of the following apply: -\begin{itemize} -\item $\ve$ is the literal expression for $\vl$, that is, $\ELiteral(\vl)$ -\item $\vv$ is the \nativevalue\ corresponding to $\vl$; -\item $\vg$ is the empty graph, as literals do not yield any Read and Write Effects; -\item $\newenv$ is $\env$. -\end{itemize} - -\subsection{Example} -In the specification: -\VerbatimInput{../tests/ASLSemanticsReference.t/SemanticsRule.Lit.asl} -each of the expressions \texttt{3} evaluates to the \nativevalue\ $\nvint(3)$. - -\CodeSubsection{\EvalLitBegin}{\EvalLitEnd}{../Interpreter.ml} - -\subsection{Formally} -\begin{mathpar} -\inferrule{}{ - \evalexpr{\env, \overname{\ELiteral(\vl)}{\ve}} \evalarrow \Normal((\overname{\nvliteral{\vl}}{\vv},\overname{\emptygraph}{\vg}), \overname{\env}{\newenv}) -} -\end{mathpar} - -\isempty{\subsection{Comments}} - -\section{SemanticsRule.ELocalVar \label{sec:SemanticsRule.ELocalVar}} -\subsection{Prose} -All of the following apply: -\begin{itemize} - \item $\ve$ denotes a variable expression, $\EVar(\vx)$, - which is bound locally in $\env$; - \item $\vv$ is the value of $\vx$ in $\env$; - \item $\newenv$ is $\env$. - \item $\vg$ is the graph containing a single Read Effect for $\vx$. -\end{itemize} - -\subsection{Example} -In the specification: -\VerbatimInput{../tests/ASLSemanticsReference.t/SemanticsRule.ELocalVar.asl} -the evaluation of \texttt{x} within \texttt{assert x == 3;} uses SemanticsRule.ELocalVar. - -\CodeSubsection{\EvalELocalVarBegin}{\EvalELocalVarEnd}{../Interpreter.ml} - -\subsection{Formally} -\begin{mathpar} -\inferrule{ - \env \eqname (\Ignore, \denv)\\ - \vx \in \dom(L^\denv) -}{ - \evalexpr{\env, \EVar(\vx)} \evalarrow \Normal((\overname{L^\denv(\vx)}{\vv}, \overname{\ReadEffect(\vx)}{\vg}), \overname{\env}{\newenv}) -} -\end{mathpar} - -\subsection{Comments} -When there exists a global variable $\vx$, the type system -forbids having $\vx$ as a local variable. -This is enforced by TypingRule.LDVar in the Chapter ``Typing of Local Declarations'', -and -TypingRule.DeclareGlobalStorage and TypingRule.DeclareOneFunc, -both in the Chapter ``Typing of Global Declarations''. - -\section{SemanticsRule.EGlobalVar \label{sec:SemanticsRule.EGlobalVar}} -\subsection{Prose} -All of the following apply: -\begin{itemize} - \item $\ve$ denotes a variable expression, $\EVar(\vx)$, which is bound globally in $\env$; - \item $\vv$ is the value of $\vx$ in $\env$; - \item $\newenv$ is $\env$. - \item $\vg$ is the graph containing a single Read Effect for $\vx$. -\end{itemize} - -\subsection{Example} -In the specification: -\VerbatimInput{../tests/ASLSemanticsReference.t/SemanticsRule.EGlobalVar.asl} -the evaluation of~\texttt{global\_x} within~\texttt{assert global\_x == 3;} -uses the rule \\ SemanticsRule.EGlobalVar. - -\CodeSubsection{\EvalEGlobalVarBegin}{\EvalEGlobalVarEnd}{../Interpreter.ml} - -\subsection{Formally} -\begin{mathpar} -\inferrule{ - \env \eqname (\tenv, \denv)\\ - \vx \in \dom(G^\denv)\\ - \vv \eqdef G^\denv(\vx) \\ - \vg \eqdef \ReadEffect(\vx)\\ - \newenv \eqname \env -}{ - \evalexpr{\env, \EVar(\vx)} \evalarrow \Normal((\vv, \vg), \newenv) -} -\end{mathpar} - -\isempty{\subsection{Comments}} - -\section{SemanticsRule.BinopAnd \label{sec:SemanticsRule.BinopAnd}} -\subsection{Prose} -All of the following apply: -\begin{itemize} -\item $\ve$ denotes a conjunction over two expressions, - $\EBinop(\BAND, \veone, \vetwo)$; -\item $C$ is the result of the evaluation of the expression - \texttt{if e1 then e2 else false} (see \secref{SemanticsRule.ECond}). -\end{itemize} - -\subsection{Example} -\VerbatimInput{../tests/ASLSemanticsReference.t/SemanticsRule.EBinopAndFalse.asl} -the expression \texttt{FALSE \&\& fail()} evaluates to the value \texttt{FALSE}. Notice that the function \texttt{fail} is never called. - -\CodeSubsection{\EvalBinopAndBegin}{\EvalBinopAndEnd}{../Interpreter.ml} - -\subsection{Formally} -\begin{mathpar} - \inferrule{ - \falsep \eqdef \ELiteral(\lbool(\False))\\ - \evalexpr{\env, \ECond(\veone, \vetwo, \falsep)} \evalarrow C - } - { - \evalexpr{\env, \EBinop(\BAND, \veone, \vetwo)} \evalarrow C - } -\end{mathpar} - -\subsection{Comments} -The evaluation via the rule above ensures that $\veone$ is evaluated first and -only if it evaluates to $\True$ is $\vetwo$ evaluated. - -\lrmcomment{This is related to \identr{BKNT}: add table} - -\lrmcomment{This is related to \identr{XKGC}:} - -It is an error for an expression’s meaning to rely on evaluation order except -that conditional expressions, and uses of the boolean operators \texttt{\&\&}, -\texttt{||},\texttt{-->}, are guaranteed to evaluate from left to right. - -\lrmcomment{This is related to \identi{YMRT}:} - -An implementation could enforce this rule by performing a global analysis of -all functions to determine whether a function can throw an exception and the -set of global variables read and written by a function. - -\lrmcomment{This is related to \identi{QRXP}:} -Conditional expressions and the operations \texttt{\&\&}, \texttt{||}, -\texttt{-->} provide a short-circuit evaluation mechanism: - -\lrmcomment{This is related to the note under \identr{LRHD}:} -\begin{itemize} -\item the first operand of \texttt{if} is always evaluated but only one of the -remaining operands is evaluated; -\item if the first operand of \texttt{and\_bool} is $\False$, then the second operand is not evaluated; -\item if the first operand of \texttt{or\_bool} is $\True$, then the second operand is not evaluated; and, -\item if the first operand of \texttt{implies\_bool} is $\False$, then the -second operand is not evaluated. -\end{itemize} - -However, note that relying on this short-circuit evaluation can be confusing -for readers of ASL specifications and as a consequence it is recommended that -an if-statement is used to achieve the same effect. - -\section{SemanticsRule.BinopOr \label{sec:SemanticsRule.BinopOr}} -\subsection{Prose} -All of the following apply: -\begin{itemize} -\item $\ve$ denotes a disjunction of two expressions, $\EBinop(\BOR, \veone, \vetwo)$; -\item $C$ is the result of the evaluation of - \texttt{if e1 then true else e2} (see \secref{SemanticsRule.ECond}). -\end{itemize} - -\subsection{Example} -\VerbatimInput{../tests/ASLSemanticsReference.t/SemanticsRule.EBinopOrTrue.asl} -The expression \texttt{(0 == 1) || (1 == 1)} evaluates to the value \True. - -\CodeSubsection{\EvalBinopOrBegin}{\EvalBinopOrEnd}{../Interpreter.ml} - -\begin{mathpar} -\inferrule{ - \truep \eqdef \ELiteral(\lbool(\True))\\ - \evalexpr{\env, \ECond(\veone, \truep, \vetwo)} \evalarrow C -}{ -\evalexpr{\env, \EBinop(\BOR, \veone, \vetwo)} \evalarrow C -} -\end{mathpar} -The evaluation via the rule above ensures that $\veone$ is evaluated first and only if -it evaluates to $\False$, is $\vetwo$ evaluated. - -\subsection{Comments} -\lrmcomment{This is related to \identr{BKNT}: add table} - -\lrmcomment{This is related to \identr{XKGC}:} - -It is an error for an expression’s meaning to rely on -evaluation order except that conditional expressions, and uses of the boolean -operators \texttt{\&\&}, \texttt{||}, \texttt{-->}, are guaranteed to evaluate -from left to right. - -\lrmcomment{This is related to \identi{YMRT}:} - -An implementation could enforce this rule by performing a global analysis of -all functions to determine whether a function can throw an exception and the -set of global variables read and written by a function. - -\lrmcomment{This is related to \identi{QRXP}:} -Conditional expressions and the operations \texttt{\&\&}, \texttt{||}, -\texttt{-->} provide a short-circuit evaluation mechanism: - -\lrmcomment{This is related to the note under \identr{LRHD}:} -\begin{itemize} -\item the first operand of \texttt{if} is always evaluated but only one of the -remaining operands is evaluated; -\item if the first operand of \texttt{and\_bool} is $\False$, then the second operand is not evaluated; -\item if the first operand of \texttt{or\_bool} is $\True$, then the second operand is not evaluated; and, -\item if the first operand of \texttt{implies\_bool} is $\False$, then the -second operand is not evaluated. -\end{itemize} - -However, note that relying on this short-circuit evaluation can be confusing -for readers of ASL specifications and as a consequence it is recommended that -an if-statement is used to achieve the same effect. - -\section{SemanticsRule.BinopImpl \label{sec:SemanticsRule.BinopImpl}} -\subsection{Prose} -All of the following apply: -\begin{itemize} - \item $\ve$ denotes an implication over two expressions, $\EBinop(\IMPL, \veone, \vetwo)$; - \item $\ve$ is evaluated as \texttt{if e1 then e2 else true}. -\end{itemize} - -\subsection{Example} -\VerbatimInput{../tests/ASLSemanticsReference.t/SemanticsRule.EBinopImplExFalso.asl} -the expression \texttt{(0 == 1) --> (1 == 0)} evaluates to the value \True, according to the definition of implication. - - \CodeSubsection{\EvalBinopImplBegin}{\EvalBinopImplEnd}{../Interpreter.ml} - - \begin{mathpar} - \inferrule{ - \truep \eqdef \ELiteral(\lbool(\True))\\ - \evalexpr{\env, \ECond(\veone, \vetwo, \truep)} \evalarrow C - } - { - \evalexpr{\env, \EBinop(\IMPL, \veone, \vetwo)} \evalarrow C - } - \end{mathpar} - The evaluation via the rule above ensures that $\veone$ is evaluated first and only if - it evaluates to \True, is $\vetwo$ evaluated. - -\isempty{\subsection{Comments}} -\lrmcomment{This is related to \identr{BKNT}: add table} - -\lrmcomment{This is related to \identi{QRXP}:} -Conditional expressions and the operations \texttt{\&\&}, \texttt{||}, -\texttt{-->} provide a short-circuit evaluation mechanism: - -\lrmcomment{This is related to the note under \identr{LRHD}:} -\begin{itemize} -\item the first operand of \texttt{if} is always evaluated but only one of the -remaining operands is evaluated; -\item if the first operand of \texttt{and\_bool} is $\False$, then the second operand is not evaluated; -\item if the first operand of \texttt{or\_bool} is $\True$, then the second operand is not evaluated; and, -\item if the first operand of \texttt{implies\_bool} is $\False$, then the -second operand is not evaluated. -\end{itemize} - -However, note that relying on this short-circuit evaluation can be confusing -for readers of ASL specifications and as a consequence it is recommended that -an if-statement is used to achieve the same effect. - -\section{SemanticsRule.Binop \label{sec:SemanticsRule.Binop}} - -\subsection{Prose} -All of the following apply: -\begin{itemize} - \item $\ve$ denotes a Binary Operator $\op$ over two expressions, $\EBinop(\op, \veone, \vetwo)$; - \item the operator $\op$ is not one of $\BAND$, $\BOR$, or $\IMPL$. - These operators are handled by rules - SemanticsRule.BinopAnd (\secref{SemanticsRule.BinopAnd}), - SemanticsRule.BinopOr \\ (\secref{SemanticsRule.BinopOr}), and - SemanticsRule.BinopImpl (\secref{SemanticsRule.BinopImpl}); - \item the evaluation of the expression $\veone$ in $\env$ is the configuration \\ - $\Normal(\vmone, \envone)$\ProseOrAbnormal; - \item the evaluation of the expression $\vetwo$ in $\envone$ is the configuration \\ - $\Normal(\vmtwo, \newenv)$\ProseOrAbnormal; - \item $\vmone$ consists of the value $\vvone$ and the execution graph $\vgone$; - \item $\vmtwo$ consists of the value $\vvtwo$ and the execution graph $\vgtwo$; - \item applying the Binary Operator $\op$ to $\vvone$ and $\vvtwo$ results in $\vv$\ProseOrError; - \item $\vg$ is the parallel composition of $\vgone$ and $\vgtwo$. -\end{itemize} - -\subsection{Example} -In this specification: -\VerbatimInput{../tests/ASLSemanticsReference.t/SemanticsRule.EBinopPlusAssert.asl} -the expression \texttt{3 + 2} evaluates to the value \texttt{5}. - -\subsection{Example} -In the specification: -\VerbatimInput{../tests/ASLSemanticsReference.t/SemanticsRule.EBinopDIVBackendDefinedError.asl} -the expression \texttt{3 DIV 0} results in a type error. - -\CodeSubsection{\EvalBinopBegin}{\EvalBinopEnd}{../Interpreter.ml} - -\subsection{Formally} -\begin{mathpar} -\inferrule{\op \not\in \{\BAND, \BOR, \IMPL\}\\ - \evalexpr{ \env, \veone} \evalarrow \Normal(\vmone, \envone) \OrAbnormal \\\\ - \evalexpr{ \envone, \vetwo } \evalarrow \Normal(\vmtwo, \newenv) \OrAbnormal \\\\ - \vmone \eqname (\vvone, \vgone) \\ - \vmtwo \eqname (\vvtwo, \vgtwo) \\ - \binoprel(\op, \vvone, \vvtwo) \evalarrow \vv \OrDynError\\\\ - \vg \eqdef \vgone \parallelcomp \vgtwo -}{ - \evalexpr{ \env, \overname{\EBinop(\op, \veone, \vetwo)}{\ve} } \evalarrow - \Normal((\vv, \vg), \newenv) -} -\end{mathpar} - -The rule above applies to many binary operators, including $\EQOP$ (which is used for \texttt{<->} -as well as \texttt{==}). - -\subsection{Comments} -\lrmcomment{This is related to \identr{BKNT}: add table} - -\lrmcomment{This is related to \identr{XKGC}:} - -The semantics takes a semantic transition over the left subexpression before -the right subexpression. - -This is an arbitrary choice as the type-checker must ensure that either order -of evaluation of the operands yields the same result. - -In other words, it it is an error for an expression’s meaning to rely on -evaluation order except that conditional expressions, and uses of the boolean -operators \texttt{\&\&}, \texttt{||}, \texttt{-->}, are guaranteed to evaluate -from left to right. - -\lrmcomment{This is related to \identi{YMRT}:} - -An implementation could enforce this rule by performing a global analysis of -all functions to determine whether a function can throw an exception and the -set of global variables read and written by a function. - -\lrmcomment{This is related to \identi{QJTN}:} - -Notice that when one of the subexpressions terminates exceptionally, -the other expression must be side effect-free and non-throwing. - -In other words, for any function call \texttt{F (e1, ..., em)}, tuple -\texttt{(e1, ..., em)}, or operation \texttt{e1 op e2} (with the exception of -\texttt{\&\&}, \texttt{||} and \texttt{-->}), it is an error if the -subexpressions conflict with each other by: -\begin{itemize} -\item both writing to the same variable. -\item one writing to a variable and the other reading from that same variable -\item one writing to a variable and the other throwing an exception -\item both throwing exceptions -\end{itemize} - -\lrmcomment{This is related to \identi{GFZT}:} -These conditions are sufficient but not necessary to ensure that evaluation -order does not affect the result of an expression, including any side-effects. - -\section{SemanticsRule.Unop \label{sec:SemanticsRule.Unop}} -\subsection{Prose} -All of the following apply: -\begin{itemize} -\item $\ve$ denotes a unary operator $\op$ over an expression, $\EUnop(\op, \veone)$; -\item the evaluation of the expression $\veone$ in $\env$ yields \\ $\Normal((\vvone, \vg), \newenv)$\ProseOrAbnormal; -\item applying the unary operator $\op$ to $\vvone$ is $\vv$. -\end{itemize} - -\subsection{Example} -In the specification: -\VerbatimInput{../tests/ASLSemanticsReference.t/SemanticsRule.EUnopAssert.asl} -the expression \texttt{NOT '1010'} evaluates to the value \texttt{'0101'}. - -\CodeSubsection{\EvalUnopBegin}{\EvalUnopEnd}{../Interpreter.ml} - -\begin{mathpar} - \inferrule{ - \evalexpr{ \env, \veone} \evalarrow \Normal((\vvone,\vg), \newenv) \OrAbnormal\\\\ - \unoprel(\op, \vvone) \evalarrow \vv - } - { - \evalexpr{ \env, \EUnop(\op, \veone) } \evalarrow - \Normal((\vv, \vg), \newenv) - } - \end{mathpar} - -\isempty{\subsection{Comments}} - -\section{SemanticsRule.ECond \label{sec:SemanticsRule.ECond}} - -\subsection{Prose} -All of the following apply: -\begin{itemize} - \item $\ve$ denotes a conditional expression $\econd$ with two options $\veone$ and $\vetwo$, - that is, $\ECond(\econd, \veone, \vetwo)$; - \item the evaluation of the conditional expression $\econd$ in $\env$ yields \\ - $\Normal(\mcond, \envone)$\ProseOrAbnormal; - \item $\mcond$ consists of a native Boolean for $\vb$ and execution graph $\vgone$; - \item $\vep$ is $\veone$ if $\vb$ is $\True$ and $\vetwo$ otherwise; - \item the evaluation of $\vep$ in $\envone$ yields $\Normal((\vvtwo, \vgtwo), \newenv)$\ProseOrAbnormal; - \item $\vg$ is the parallel composition of $\vgone$ and $\vgtwo$. -\end{itemize} - - \subsection{Example} - In the specification: - \VerbatimInput{../tests/ASLSemanticsReference.t/SemanticsRule.ECondFalse.asl} - the expression \texttt{if FALSE then Return42() else 3} evaluates to the value \texttt{3}. - - \subsection{Example} - In the specification: - \VerbatimInput{../tests/ASLSemanticsReference.t/SemanticsRule.ECondUNKNOWN3or42.asl} -the expression \texttt{if UNKNOWN: boolean then 3 else Return42()} will -evaluate either \texttt{3} or \texttt{Return42()} depending on how -\texttt{UNKNOWN} is implemented. - - \CodeSubsection{\EvalECondBegin}{\EvalECondEnd}{../Interpreter.ml} - -\begin{mathpar} - \inferrule{ - \evalexpr{\env, \econd} \evalarrow \Normal(\mcond, \envone) \OrAbnormal\\\\ - \mcond \eqname (\nvbool(\vb), \vgone)\\ - \vep \eqdef \choice{\vb}{\veone}{\vetwo}\\\\ - \evalexpr{\envone, \vep} \evalarrow \Normal((\vv, \vgtwo), \newenv) \OrAbnormal\\\\ - \vg \eqdef \ordered{\vgone}{\aslctrl}{\vgtwo} - } - { - \evalexpr{\env, \overname{\ECond(\econd, \veone, \vetwo)}{\ve}} \evalarrow - \Normal((\vv, \vg), \newenv) - } -\end{mathpar} - -\subsection{Comments} -\lrmcomment{This is related to \identr{YCDB}:} - -A conditional expression evaluates to its \texttt{then} expression if the -condition expression evaluates to $\True$. If the condition expression -evaluates to $\False$ each \texttt{elsif} condition expression is evaluated -sequentially until an \texttt{elsif} condition expression evaluates to $\True$; -the conditional expression evaluates to the corresponding \texttt{elsif} -expression. If no \texttt{elsif} expression evaluates to $\True$ the -conditional expression evaluates to the \texttt{else} expression. - -\section{SemanticsRule.ESlice \label{sec:SemanticsRule.ESlice}} -\subsection{Prose} -All of the following apply: -\begin{itemize} -\item $\ve$ denotes a slicing expression, $\ESlice(\ebv, \slices)$; -\item the evaluation of $\ebv$ in $\env$ yields $\Normal(\mbv, \envone)$\ProseOrAbnormal; -\item the evaluation of $\slices$ in $\env$ yields $\Normal(\mpositions, \newenv)$\ProseOrAbnormal; -\item $\mpositions$ consists of $\positions$ --- all the indices that need to be added to the -resulting bitvector --- and the execution graph $\vgone$; -\item reading from $\vbv$ as a bitvector at the indices indicated by $\positions$ - (see \secref{SemanticsRule.ReadFromBitvector}) results in the bitvector $\vv$, - which concatenates all of the values from the indicates indices\ProseOrError; -\item $\vg$ is the parallel composition of $\vgone$ and $\vgtwo$. -\end{itemize} - -\subsection{Example} -In the specification: -\VerbatimInput{../tests/ASLSemanticsReference.t/SemanticsRule.ESlice.asl} -the expression \texttt{'11110000'[6:3]} evaluates to the value \texttt{'1110'}. - -\CodeSubsection{\EvalESliceBegin}{\EvalESliceEnd}{../Interpreter.ml} - -\subsection{Formally} -\begin{mathpar} -\inferrule{ - \evalexpr{\env, \ebv} \evalarrow \Normal(\mbv, \envone) \OrAbnormal\\\\ - \mbv \eqname (\vbv,\vgone) \\ - \evalslices{\envone, \slices} \evalarrow \Normal(\mpositions, \newenv) \OrAbnormal \\ - \mpositions \eqname (\positions, \vgtwo) \\ - \readfrombitvector(\vbv, \positions) \evalarrow \vv \OrDynError\\\\ - \vg \eqdef \vgone \parallelcomp \vgtwo -}{ - \evalexpr{\env, \ESlice(\ebv, \slices)} \evalarrow \Normal((\vv, \vg), \newenv) -} -\end{mathpar} - -\isempty{\subsection{Comments}} - -\section{SemanticsRule.ECall \label{sec:SemanticsRule.ECall}} -All of the following apply: -\begin{itemize} - \item $\ve$ denotes a subprogram call, $\ECall(\name, \actualargs, \params)$; - \item the evaluation of that subprogram call in $\env$ is either - $\Normal(\vms, \newenv)$\ProseOrAbnormal; - \item one of the following applies: - \begin{itemize} - \item all of the following apply (\textsc{single\_returned\_value}): - \begin{itemize} - \item $\vms$ consists of a single returned value $(\vv,\vg)$, - which goes into the output configuration $\Normal((\vv, \vg), \newenv)$. - \end{itemize} - - \item all of the following apply (\textsc{multiple\_returned\_values}): - \begin{itemize} - \item $\vms$ consists of a list of returned value $(\vv_i,\vg_i)$, for $i=1..k$; - \item $\vg$ is the parallel composition of $\vg_i$, for $i=1..k$; - \item $\vv$ is the \nativevalue\ vector of values $\vv_i$, for $i=1..k$; - \item the resulting configuration is $\Normal((\vv, \vg), \newenv)$. - \end{itemize} - \end{itemize} -\end{itemize} - - \subsection{Example} - In the specification: - \VerbatimInput{../tests/ASLSemanticsReference.t/SemanticsRule.ECall.asl} - the expression \texttt{Return42()} evaluates to the value \texttt{42} because the - subprogram \texttt{Return42()} is implemented to return the value \texttt{42}. - - \CodeSubsection{\EvalECallBegin}{\EvalECallEnd}{../Interpreter.ml} - -\subsection{Formally} -\begin{mathpar} - \inferrule[single\_returned\_value]{ - \evalcall{\env, \name, \actualargs, \params} \evalarrow \Normal(\vms, \newenv) \OrAbnormal\\ - \vms \eqname [(\vv, \vg)] - } - { - \evalexpr{\env, \ECall(\name, \actualargs, \params)} \evalarrow \Normal((\vv, \vg), \newenv) - } -\and -\inferrule[multiple\_returned\_values]{ - \evalcall{\env, \name, \actualargs, \params} \evalarrow \Normal(\vms, \newenv) \OrAbnormal\\ - \vms \eqname [i=1..k: (\vv_i, \vg_i)]\\ - \vg \eqdef \vg_1 \parallelcomp \ldots \parallelcomp \vg_k \\ - \vv \eqdef \nvvector{\vv_{1..k}} -} -{ - \evalexpr{\env, \ECall(\name, \actualargs, \params)} \evalarrow \Normal((\vv, \vg), \newenv) -} -\end{mathpar} - -\isempty{\subsection{Comments}} - -\section{SemanticsRule.EGetArray \label{sec:SemanticsRule.EGetArray}} - -\subsection{Prose} -All of the following apply: -\begin{itemize} - \item $\ve$ denotes an array access expression, $\EGetArray(\earray, \eindex)$; - \item the evaluation of $\earray$ in $\env$ is $\Normal(\marray, \envone)$\ProseOrAbnormal; - \item the evaluation of $\eindex$ in $\env$ is $\Normal(\mindex, \newenv)$\ProseOrAbnormal - \item $\marray$ consists of the native vector $\varray$ and execution graph $\vgone$; - \item $\mindex$ consists of the native integer $\vindex$ and execution graph $\vgtwo$; - \item $\vindex$ is the native integer for $\vi$; - \item evaluating the value at index $\vi$ of $\varray$ is $\vv$; - \item $\vg$ is the parallel composition of $\vgone$ and $\vgtwo$. -\end{itemize} - -\subsection{Example} -In the specification: -\VerbatimInput{../tests/ASLSemanticsReference.t/SemanticsRule.EGetArray.asl} -the expression \texttt{my\_array[2]} appearing in the assertion evaluates to the value \texttt{42} since the element -indexed by \texttt{2} in \texttt{my\_array} is \texttt{42}. - - \subsection{Example} - The specification: - \VerbatimInput{../tests/ASLSemanticsReference.t/SemanticsRule.EGetArrayTooSmall.asl} - results in a typing error since we are trying to access index \texttt{3} of an array - which has indexes \texttt{0}, \texttt{1} and \texttt{2} only. - - \CodeSubsection{\EvalEGetArrayBegin}{\EvalEGetArrayEnd}{../Interpreter.ml} - -\subsection{Formally} - \begin{mathpar} - \inferrule{ - \evalexpr{\env, \earray} \evalarrow \Normal(\marray, \envone) \OrAbnormal\\ - \evalexpr{\envone, \eindex} \evalarrow \Normal(\mindex, \newenv) \OrAbnormal\\ - \marray \eqname (\varray, \vgone)\\ - \mindex \eqname (\vindex, \vgtwo)\\ - \vindex \eqname \nvint(\vi)\\ - \getindex(\vi, \varray) \evalarrow \vv\\ - \vg \eqdef \vgone \parallelcomp \vgtwo\\ - } - { - \evalexpr{\env, \EGetArray(\earray, \eindex)} \evalarrow \Normal((\vv, \vg), \newenv) - } - \end{mathpar} - -\isempty{\subsection{Comments}} - -\section{SemanticsRule.ERecord \label{sec:SemanticsRule.ERecord}} -\subsection{Prose} -All of the following apply: -\begin{itemize} -\item $\ve$ denotes a record creation expression, $\ERecord(\names, \efields)$; -\item the names of the fields are $\id_{1..k}$; -\item the expressions associated with the fields are $\ve_{1..k}$; -\item evaluating the expressions of $\fields$ in order yields \\ - $\Normal((\vvfields,\vg), \newenv)$\ProseOrAbnormal; -\item $\vvfields$ is a list of \nativevalues\ $\vv_{1..k}$; -\item $\vv$ is the native record that maps $\id_i$ to $\vv_i$, for $i=1..k$. -\end{itemize} - -\subsection{Example} -In the specification: -\VerbatimInput{../tests/ASLSemanticsReference.t/SemanticsRule.ERecord.asl} -the expression \verb|MyRecordType{a=3, b=42}| evaluates to the native record value \\ -$\nvrecord{\va\mapsto\nvint(3), \vb\mapsto\nvint(42)}$. - -\CodeSubsection{\EvalERecordBegin}{\EvalERecordEnd}{../Interpreter.ml} - -\subsection{Formally} -\begin{mathpar} - \inferrule{ - \efields \eqname [i=1..k: (\id_i, \ve_i)]\\ - \names \eqdef \id_{1..k} \\ - \fields \eqdef \ve_{1..k} \\ - \evalexprlist{\env, \fields} \evalarrow \Normal((\vvfields,\vg), \newenv) \OrAbnormal\\ - \vvfields \eqname \vv_{1..k}\\ - \vv \eqdef \nvrecord{\{i=1..k: \id_i\mapsto \vv_i\}} - } - { - \evalexpr{\env, \ERecord(\Ignore, \efields)} \evalarrow \Normal((\vv, \vg), \newenv) - } -\end{mathpar} - -\isempty{\subsection{Comments}} - -\section{SemanticsRule.EGetField \label{sec:SemanticsRule.EGetField}} -\subsection{Prose} -All of the following apply: -\begin{itemize} -\item $\ve$ denotes a field access expression, $\EGetField(\erecord, \fieldname)$; -\item the evaluation of $\erecord$ in $\env$ is $\Normal((\vrecord, \vg), \newenv)$\ProseOrAbnormal; -\item $\vv$ is the value mapped by $\fieldname$ in the native record $\vrecord$. -\end{itemize} - - \subsection{Example} - In the specification: - \VerbatimInput{../tests/ASLSemanticsReference.t/SemanticsRule.ERecord.asl} - the expression \texttt{my\_record.a} evaluates to the value \texttt{3}. - - \CodeSubsection{\EvalEGetFieldBegin}{\EvalEGetFieldEnd}{../Interpreter.ml} - -\subsection{Formally} -\begin{mathpar} - \inferrule{ - \evalexpr{\env, \erecord} \evalarrow \Normal((\vrecord, \vg), \newenv) \OrAbnormal\\ - \getfield(\fieldname, \vrecord) \evalarrow \vv - } - { - \evalexpr{\env, \EGetField(\erecord, \fieldname)} \evalarrow \Normal((\vv, \vg), \newenv) - } -\end{mathpar} - -\isempty{\subsection{Comments}} - -\section{SemanticsRule.EConcat \label{sec:SemanticsRule.EConcat}} -\subsection{Prose} -All of the following apply: -\begin{itemize} -\item $\ve$ denotes a concatenation of bitvector expressions, $\EConcat(\elist)$; -\item the evaluation of $\elist$ in $\env$ is $\Normal((\vlist, \vg), \newenv)$\ProseOrAbnormal; -\item $\vv$ is the bitvector constructed from the concatenation of $\vlist$. -\end{itemize} - - \subsection{Example} - In the specification: - \VerbatimInput{../tests/ASLSemanticsReference.t/SemanticsRule.EConcat.asl} - the expression \texttt{['10', '11']} evaluates to the value \texttt{'1011'}. - - \subsection{Example} - In the specification: - \VerbatimInput{../tests/ASLSemanticsReference.t/SemanticsRule.EConcat2.asl} - the expression \texttt{['1111', '0000']} evaluates to the value \texttt{'11110000'}. - - \CodeSubsection{\EvalEConcatBegin}{\EvalEConcatEnd}{../Interpreter.ml} - -\subsection{Formally} -\begin{mathpar} - \inferrule{ - \evalexprlist{\env, \elist} \evalarrow \Normal((\vlist, \vg), \newenv) \OrAbnormal\\ - \concatbitvectors(\vlist) \evalarrow \vv - } - { - \evalexpr{\env, \EConcat(\elist)} \evalarrow \Normal((\vv, \vg), \newenv) - } -\end{mathpar} - -\subsection{Comments} -\lrmcomment{This is related to \identr{BRCM}:} - -Concatenation of multiple bitvectors is done using a comma separated list -surrounded with square brackets. - -\section{SemanticsRule.ETuple \label{sec:SemanticsRule.ETuple}} - \subsection{Prose} - All of the following apply: - \begin{itemize} - \item $\ve$ denotes a tuple expression, $\ETuple(\elist)$; - \item the evaluation of $\elist$ in $\env$ is $\Normal((\vlist, \vg), \newenv)$\ProseOrAbnormal; - \item $\vv$ is the native vector constructed from the values in $\vlist$. - \end{itemize} - - \subsection{Example} - In the specification: - \VerbatimInput{../tests/ASLSemanticsReference.t/SemanticsRule.ETuple.asl} - the expression \texttt{(3, Return42())} evaluates to the value \texttt{(3, 42)}. - - \CodeSubsection{\EvalETupleBegin}{\EvalETupleEnd}{../Interpreter.ml} - -\subsection{Formally} -\begin{mathpar} - \inferrule{ - \evalexprlist{\env, \elist} \evalarrow \Normal((\vlist, \vg), \newenv) \OrAbnormal\\ - \vv \eqdef \nvvector{\vlist} - } - { - \evalexpr{\env, \ETuple(\elist)} \evalarrow \Normal((\vv, \vg), \newenv) - } -\end{mathpar} - -\isempty{\subsection{Comments}} - -\section{SemanticsRule.EUnknown \label{sec:SemanticsRule.EUnknown}} -\begin{definition}[Domain of a Type] -The domain of a type $\vt$ in an environment $\env=(\tenv,\denv)$, -denoted by $\dynamicdomain(\tenv, \denv, \vt)$, is defined by the type system (see \secref{DynDomain}) -as the set of values that $\vt$ may store in $\env$. The reason that the dynamic environment is -needed to determine the domain is due to subprogram parameters, which constrain integer parameters to -a singleton value domain. -\end{definition} - -\subsection{Prose} -All of the following apply: -\begin{itemize} - \item $\ve$ denotes the \texttt{UNKNOWN} expression annotated with type $\vt$; - \item $\vv$ is an arbitrary value in the domain of $\vt$ in $\env$; - \item $\newenv$ is $\env$. - \item $\vg$ is the empty execution graph. -\end{itemize} - -\subsection{Example} -In the specification: -\VerbatimInput{../tests/ASLSemanticsReference.t/SemanticsRule.EUnknownInteger3.asl} -the expression \texttt{[UNKNOWN : integer]} evaluates to an integer value. - -\subsection{Example} -In the specification: -\VerbatimInput{../tests/ASLSemanticsReference.t/SemanticsRule.EUnknownIntegerRange3-42-3.asl} -the expression \verb|UNKNOWN : integer {3, 42}| evaluates to either $\nvint(3)$ or $\nvint(42)$. - -\CodeSubsection{\EvalEUnknownBegin}{\EvalEUnknownEnd}{../Interpreter.ml} - -\subsection{Formally} -\begin{mathpar} -\inferrule{\env \eqname (\tenv, \denv)\\ - \vv \in \dynamicdomain(\tenv, \env, \vt) -}{ - \evalexpr{\env, \overname{\EUnknown(\vt)}{\ve}} \evalarrow \Normal((\vv, \overname{\emptygraph}{\vg}), \overname{\env}{\newenv}) -} -\end{mathpar} -Notice that this rule introduces non-determinism. - -\subsection{Comments} -\lrmcomment{This is related to \identr{WLCH}:} - -The expression \texttt{UNKNOWN: ty} evaluates to an arbitrary value in the -domain of \texttt{ty}. - -\section{SemanticsRule.EPattern \label{sec:SemanticsRule.EPattern}} - \subsection{Prose} - All of the following apply: - \begin{itemize} - \item $\ve$ denotes a pattern expression, $\EPattern(\ve, \vp)$; - \item evaluating the expression $\ve$ in an environment $\env$ results in \\ - $\Normal((\vvone, \vgone), \newenv)$\ProseOrAbnormal; - \item evaluating whether the pattern $\vp$ matches the value $\vvone$ in $\env$ - results in $\Normal(\vv, \vgtwo)$ where is a native Boolean that determines - whether the is indeed a match; - \item $\vg$ is the ordered composition of $\vgone$ and $\vgtwo$ with the $\asldata$ edge. - \end{itemize} - - \subsection{Example} - In the specification: - \VerbatimInput{../tests/ASLSemanticsReference.t/SemanticsRule.EPatternFALSE.asl} - the expression \texttt{42 IN \{0..3, -4\}} evaluates to the value \texttt{FALSE}. - - \subsection{Example} - In the specification: - \VerbatimInput{../tests/ASLSemanticsReference.t/SemanticsRule.EPatternTRUE.asl} - the expression \texttt{42 IN \{0..3, 42\}} evaluates to \True. - - \CodeSubsection{\EvalEPatternBegin}{\EvalEPatternEnd}{../Interpreter.ml} - -\subsection{Formally} -\begin{mathpar} - \inferrule{ - \evalexpr{\env, \ve} \evalarrow \Normal((\vvone, \vgone), \newenv) \OrAbnormal\\ - \evalpattern{\env, \vvone, \vp} \evalarrow \Normal(\vv, \vgtwo)\\ - \vg \eqdef \ordered{\vgone}{\asldata}{\vgtwo} - } - { - \evalexpr{\env, \EPattern(\ve, \vp)} \evalarrow \Normal((\vv, \vg), \newenv) - } -\end{mathpar} - -\isempty{\subsection{Comments}} - -\section{SemanticsRule.ATC \label{sec:SemanticsRule.ATC}} -\lrmcomment{This is related to \identi{TCST}:} -The rule about domains in the definitions of subtype-satisfaction and -type-satisfaction means that it is illegal to use the unconstrained integer -where a constrained integer is expected. An asserting type conversion (ATC) can -be used to overcome this. - -\lrmcomment{This is related to \identi{CGRH}:} -An ATC allows code to explicitly mark places where uses of constrained types -would otherwise be a static type-checking error. The intent is to reduce the -incidence of unintended errors by making such uses fail type-checking unless -the asserting type conversion is provided. - -\lrmcomment{This is related to \identr{WZVX}:} -Note that ATCs are execution-time checks. An execution-time check is a -condition that is evaluated during the evaluation of an execution-time -initializer expression or subprogram. If the condition evaluates to $\False$ it -is a dynamic error. - - \subsection{Prose} - All of the following apply: - \begin{itemize} - \item $\ve$ denotes an asserted type conversion expression, $\EATC(\veone, \vt)$; - \item evaluating $\veone$ in $\env$ results in $\Normal((\vv, \vgone), \newenv)$\ProseOrAbnormal; - \item evaluating whether $\vv$ has type $\vt$ in $\env$ results in $(\vb, \vgtwo)$\ProseTerminateAs{\ErrorConfig}; - \item one of the following applies: - \begin{itemize} - \item all of the following apply (\textsc{okay}): - \begin{itemize} - \item $\vb$ is the native Boolean for \True; - \item $\vg$ is the ordered composition of $\vgone$ and $\vgtwo$ with the $\asldata$ edge. - \end{itemize} - \item all of the following apply (\textsc{error}): - \begin{itemize} - \item $\vb$ is the native Boolean for \True; - \item an asserted type conversion error is returned. - \end{itemize} - \end{itemize} - \end{itemize} - -\subsection{Example} -\VerbatimInput{../tests/ASLSemanticsReference.t/SemanticsRule.ATCValue.asl} - -\subsection{Example} -\VerbatimInput{../tests/ASLSemanticsReference.t/SemanticsRule.ATCError.asl} - -\subsection{Example} -\lrmcomment{This is related to \identr{YCPX}:} - -Dynamic error conditions only hold if the asserting type conversion is -evaluated. - -In the example below, the asserting type conversion on \texttt{y} is -not a dynamic error if the invocation of \texttt{f1} returns $\False$ when -evaluated: -\VerbatimInput{../tests/ASLSemanticsReference.t/SemanticsRule.ATCNotDynamicErrorIfFalse.asl} - -\subsection{Example} - -The following excerpts indicates several points where various static and -dynamic errors can occur: -\VerbatimInput{../tests/ASLSemanticsReference.t/SemanticsRule.ATCVariousErrors.asl} - -\CodeSubsection{\EvalATCBegin}{\EvalATCEnd}{../Interpreter.ml} - -\subsection{Formally} -\begin{mathpar} -\inferrule[okay]{ - \evalexpr{\env, \veone} \evalarrow \Normal((\vv, \vgone), \newenv) \OrAbnormal\\\\ - \isvaloftype(\env, \vv, \vt) \evalarrow (\vb, \vgtwo) \OrDynError\\\\ - \vb \eqname \nvbool(\True)\\ - \vg \eqdef \ordered{\vgone}{\asldata}{\vgtwo} -}{ - \evalexpr{\env, \EATC(\veone, \vt)} \evalarrow \Normal((\vv, \vg), \newenv) -} -\and -\inferrule[error]{ - \evalexpr{\env, \veone} \evalarrow \Normal((\vv, \Ignore), \Ignore)\\ - \neg\isvaloftype(\env, \vv, \vt) \evalarrow (\vb, \Ignore)\\ - \vb \eqname \nvbool(\False) -}{ - \evalexpr{\env, \EATC(\veone, \vt)} \evalarrow \ErrorVal{ATC\_TypeMismatch} -} -\end{mathpar} - -\isempty{\subsection{Comments}} - -\section{SemanticsRule.EExprList \label{sec:SemanticsRule.EExprList}} -\subsection{Prose} -The relation -\hypertarget{def-evalexprlist}{} -\[ - \evalexprlist{\overname{\envs}{\env} \aslsep \overname{\expr^*}{\vle}} \;\aslrel\; - \Normal((\overname{\vals^*}{\vv} \times \overname{\XGraphs}{\vg})\aslsep \overname{\envs}{\newenv}) \cup - \overname{\TThrowing}{\ThrowingConfig} \cup \overname{\TError}{\ErrorConfig} -\] -evaluates the list of expressions $\vle$ in left-to-right order in the initial environment $\env$ -and returns the resulting value $\vv$, the parallel composition of the execution graphs -generated from evaluating each expression, and the new environment $\newenv$. -If the evaluation of any expression terminates abnormally then the abnormal configuration is returned. - -\subsection{Formally} -\begin{mathpar} - \inferrule[empty]{} - { - \evalexprlist{\env, \emptylist} \evalarrow \Normal((\emptylist, \emptygraph), \env) - } -\and - \inferrule[nonempty]{ - \texttt{le} \eqname [\ve] \concat \vle1\\ - \evalexpr{\env, \ve} \evalarrow \Normal((\vvone, \vgone), \envone) \OrAbnormal\\ - \evalexprlist{\envone, \vle1} \evalarrow \Normal((\vvs, \vgtwo), \newenv) \OrAbnormal\\ - \vg \eqdef \vgone \parallelcomp \vgtwo \\ - \vv \eqdef [\vvone] \concat \vvs - } - { - \evalexprlist{\env, \vle} \evalarrow \Normal((\vv, \vg), \newenv) - } -\end{mathpar} - -\section{SemanticsRule.EExprListM \label{sec:SemanticsRule.EExprListM}} -The relation -\[ - \evalexprlistm(\overname{\envs}{\env} \aslsep \overname{\expr^*}{\vEs}) \;\aslrel\; - \Normal(\overname{(\vals\times\XGraphs)^* }{\vms} \aslsep \overname{\envs}{\newenv}) \cup - \overname{\TThrowing}{\ThrowingConfig} \cup \overname{\TError}{\ErrorConfig} -\] -evaluates a list of expressions $\vEs$ in left-to-right in the initial environment $\env$ -and returns the list of values associated with graphs $\vms$ and the new environment $\newenv$. -If the evaluation of any expression terminates abnormally then the abnormal configuration is returned. - -\subsection{Prose} -One of the following applies: -\begin{itemize} - \item All of the following apply (\textsc{empty}): - \begin{itemize} - \item $\vEs$ is an empty list; - \item $\vms$ is then empty list. - \end{itemize} - - \item All of the following apply (\textsc{non\_empty}): - \begin{itemize} - \item $\vEs$ is a list with \head\ $\ve$ and \tail\ $\vesone$; - \item evaluating $\ve$ in $\env$ yields $\Normal(\vmone, \envone)$\ProseOrAbnormal; - \item evaluating $\vesone$ in $\envone$ via $\evalexprlistm$ yields \\ - $\Normal(\vmsone, \newenv)$\ProseOrAbnormal; - \item the result is the normal configuration with the list consisting of $\vmone$ as its \head\ and $\vmsone$ - as its \tail\ and $\newenv$. - \end{itemize} -\end{itemize} - -\subsection{Formally} -\begin{mathpar} -\inferrule[empty]{} -{ - \evalexprlistm(\env, \overname{\emptylist}{\vEs}) \evalarrow \Normal(\overname{\emptylist}{\vms}, \overname{\env}{\newenv}) -} -\end{mathpar} - -\begin{mathpar} -\inferrule[non\_empty]{ - \vEs \eqname [\ve] \concat \vesone\\ - \evalexpr{\env, \ve} \evalarrow \Normal(\vmone, \envone) \OrAbnormal\\ - \evalexprlistm(\envone, \vesone) \evalarrow \Normal(\vmsone, \newenv) \OrAbnormal -}{ - \evalexprlistm(\env, \vEs) \evalarrow \Normal([\vmone]\concat\vmsone, \newenv) -} -\end{mathpar} - -\section{SemanticsRule.ESideEffectFreeExpr \label{sec:SemanticsRule.ESideEffectFreeExpr}} -\subsection{Prose} -The relation -\hypertarget{def-evalexprsef}{} -\[ - \evalexprsef{\overname{\envs}{\env} \aslsep \overname{\expr}{\ve}} \;\aslrel\; - \Normal(\overname{\vals}{\vv}\aslsep\overname{\XGraphs}{\vg}) \cup - \overname{\TError}{\ErrorConfig} -\] -specializes the expression evaluation relation for side-effect-free expressions -by omitting throwing configurations as possible output configurations. - -\subsection{Formally} -\begin{mathpar} - \inferrule{ - \evalexpr{\env, \ve} \evalarrow \Normal((\vv,\vg), \env) \OrDynError - } - { - \evalexprsef{\env, \ve} \evalarrow \Normal(\vv, \vg) - } -\end{mathpar} -Notice that the output configuration does not contain an environment, -since side-effect-free expressions do not modify the environment. - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -\chapter{Evaluation of Left-Hand Side Expressions \label{chap:eval_lexpr}} -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - -The relation -\hypertarget{def-evallexpr}{} -\[ - \evallexpr{\overname{\envs}{\env} \aslsep \overname{\lexpr}{\vle} \aslsep (\overname{\vals}{\vv} \times \overname{\XGraphs}{\vg})} \;\aslrel\; - \Normal(\overname{\XGraphs}{\newg},\overname{\envs}{\newenv}) \cup - \overname{\TThrowing}{\ThrowingConfig} \cup \overname{\TError}{\ErrorConfig} -\] -evaluates the assignment of a value $\vv$ -to the left-hand-side expression $\vle$ in an environment $\env$, -resulting in either a configuration $\Normal(\newg, \env)$ or an abnormal configuration. - -One of the following applies: -\begin{itemize} -\item SemanticsRule.LEDiscard (see Section~\ref{sec:SemanticsRule.LEDiscard}); -\item SemanticsRule.LELocalVar (see Section~\ref{sec:SemanticsRule.LELocalVar}); -\item SemanticsRule.LEGlobalVar (see Section~\ref{sec:SemanticsRule.LEGlobalVar}); -\item SemanticsRule.LESlice (see Section~\ref{sec:SemanticsRule.LESlice}); -\item SemanticsRule.LESetArray (see Section~\ref{sec:SemanticsRule.LESetArray}); -\item SemanticsRule.LESetField (see Section~\ref{sec:SemanticsRule.LESetField}); -\item SemanticsRule.LEDestructuring (see Section~\ref{sec:SemanticsRule.LEDestructuring}). -\end{itemize} - -We also define the helper rule SemanticsRule.LEMultiAssign (\ref{sec:SemanticsRuleLEMultiAssign}). - -\hypertarget{def-rexpr}{} -Some of the rules require viewing left-hand-side expressions as their corresponding right-hand side expressions. -The correspondence is defined by the function $\torexpr : \lexpr \rightarrow \expr$. -% -For example, \hyperlink{SemanticsRule.LESetField}{SemanticsRule.LESetField} -needs to evaluate the record subexpression $\rerecord$, which is a left-hand-side expression. -To achieve this, $\torexpr(\record)$ is used to obtain a right-hand-side expression, which then allows -using $\texttt{eval\_expr}$ to evaluate it. - -\paragraph{Naming Convention:} -In this chapter, variables containing $\vm$ range over $\vals\times\XGraphs$ -while variables where the $\vm$ is replaced with $\vv$ correspond to their value component. -For example, $\rmarray\eqname(\rvarray,\vgtwo)$ and $\mindex\eqname(\vindex, \vgone)$. - -\section{SemanticsRule.LEDiscard \label{sec:SemanticsRule.LEDiscard}} - \subsection{Prose} - All of the following apply: - \begin{itemize} - \item $\vle$ is a discarding expression, $\LEDiscard$; - \item $\newg$ is $\vg$; - \item $\newenv$ is $\env$. - \end{itemize} - - \subsection{Example} - In the specification: - \VerbatimInput{../tests/ASLSemanticsReference.t/SemanticsRule.LEDiscard.asl} - \texttt{- = 42;} does not affect the environment. - - \CodeSubsection{\EvalLEDiscardBegin}{\EvalLEDiscardEnd}{../Interpreter.ml} - -\subsection{Formally} - \begin{mathpar} - \inferrule{ - \newg\eqdef\vg\\ - \newenv\eqdef\env - } - { \evallexpr{\env, \LEDiscard, (\vv, \vg)} \evalarrow \Normal(\newg, \newenv) } - \end{mathpar} - -\isempty{\subsection{Comments}} - -\section{SemanticsRule.LELocalVar \label{sec:SemanticsRule.LELocalVar}} - \subsection{Prose} - All of the following apply: - \begin{itemize} - \item $\vle$ denotes a variable, $\LEVar(\vx)$; - \item $\vx$ is locally bound in $\env$; - \item $\newg$ is the ordered composition of $\vg$ and a Write Effect for $\vx$ with the $\asldata$ edge; - \item $\newenv$ is $\env$ where $\vx$ is bound to $\vv$ in the local component of the environment. - \end{itemize} - - \subsection{Example} - In the specification: - \VerbatimInput{../tests/ASLSemanticsReference.t/SemanticsRule.LELocalVar.asl} - SemanticsRule.LELocalVar is (only) used to assign the value $42$ to the left-hand-side expression - \texttt{x} within \texttt{x = 42;}. - - \CodeSubsection{\EvalLELocalVarBegin}{\EvalLELocalVarEnd}{../Interpreter.ml} - -\subsection{Formally} - \begin{mathpar} - \inferrule{ - \env \eqname (\tenv, \denv)\\ - \vx \in \dom(L^\denv)\\ - \newenv \eqdef (\tenv, (G^\denv, L^\denv[\vx \mapsto \vv]))\\ - \newg \eqdef \ordered{\vg}{\asldata}{\WriteEffect(\vx)} - } - { \evallexpr{\env, \LEVar(\vx), (\vv, \vg)} \evalarrow \Normal(\newg,\newenv) } - \end{mathpar} - -\isempty{\subsection{Comments}} - -\section{SemanticsRule.LEGlobalVar \label{sec:SemanticsRule.LEGlobalVar}} - \subsection{Prose} - All of the following apply: - \begin{itemize} - \item $\vle$ denotes a variable $\vx$, $\LEVar(\vx)$; - \item $\vx$ is globally bound in $\env$; - \item $\newg$ is the ordered composition of $\vg$ and a Write Effect for $\vx$ with the $\asldata$ edge; - \item $\newenv$ is $\env$ where $\vx$ is bound to $\vv$ in the global component of the environment. - \end{itemize} - - \subsection{Example} - In the specification: - \VerbatimInput{../tests/ASLSemanticsReference.t/SemanticsRule.LEGlobalVar.asl} - SemanticsRule.LEGlobalVar is (only) used to assign the value $42$ to the left-hand-side expression - \texttt{x} within \texttt{x = 42;}. - - \CodeSubsection{\EvalLEGlobalVarBegin}{\EvalLEGlobalVarEnd}{../Interpreter.ml} - -\subsection{Formally} - \begin{mathpar} - \inferrule{ - \env \eqname (\tenv, \denv)\\ - \vx \in \dom(G^\denv)\\ - \newenv \eqdef(\tenv, (G^\denv[\vx \mapsto \vv], L^\denv))\\ - \newg \eqdef \ordered{\vg}{\asldata}{\WriteEffect(\vx)} - } - { \evallexpr{\env, \LEVar(\vx), (\vv, \vg)} \evalarrow \Normal(\newg,\newenv) } - \end{mathpar} - -\isempty{\subsection{Comments}} - -\section{SemanticsRule.LESlice \label{sec:SemanticsRule.LESlice}} - \subsection{Prose} - All of the following apply: - \begin{itemize} - \item $\vle$ denotes a left-hand-side slicing expression, $\LESlice(\ebv, \slices)$; - \item evaluating the right-hand-side expression that corresponds to $\ebv$ - (given by applying $\torexpr$ to $\ebv$) in $\env$ - is $\Normal(\mbv,\envone)$\ProseOrAbnormal; - \item evaluating $\slices$ in $\envone$ is $\Normal(\mpositions, \envtwo)$\ProseOrAbnormal; - \item $\mpositions$ consists of the execution graph $\vgone$ and the list of indices $\positions$; - \item $\mbv$ consists of the native bitvector $\vbv$ and the execution graph $\vgtwo$; - \item writing to the bitvector $\vbv$ at indices $\positions$ using the values from $\vv$ - results in the updated native bitvector $\vvone$\ProseOrError; - \item $\vgthree$ is the parallel composition of $\vg$, $\vgone$, and $\vgtwo$; - \item $\newmbv$ is a pair consisting of $\vvone$ and the execution graph $\vgthree$; - \item the steps so far computed the updated bitvector, but have not assigned it to the - variable bound to the bitvector given by $\ebv$, which is achieved next. - Evaluating the left-hand-side expression $\ebv$ with - $\newmbv$ in an environment $\envtwo$ is the output configuration $C$, - \end{itemize} - -\subsection{Example} -In the specification: -\VerbatimInput{../tests/ASLSemanticsReference.t/SemanticsRule.LESlice.asl} -The assignment \texttt{x[3:0] = '0000'} binds \texttt{x} to $\nvbitvector(11110000)$ -via the rule SemanticsRule.LESlice.asl -in the environment where \texttt{x} is bound to $\nvbitvector(11111111)$. - -\CodeSubsection{\EvalLESliceBegin}{\EvalLESliceEnd}{../Interpreter.ml} - -\subsection{Formally} - \begin{mathpar} - \inferrule{ - \evalexpr{\env, \torexpr(\ebv)} \evalarrow \Normal(\mbv,\envone) \OrAbnormal\\ - \evalslices{\envone, \slices} \evalarrow \Normal(\mpositions, \envtwo) \OrAbnormal\\ - \mpositions \eqname (\positions, \vgone)\\ - \mbv \eqname (\vbv, \vgtwo)\\\\ - \writetobitvector(\positions, \vv, \vbv) \evalarrow \vvone \OrDynError\\\\ - \vgthree \eqdef \vg \parallelcomp \vgone \parallelcomp \vgtwo\\ - \newmbv \eqdef (\vvone, \vgthree)\\ - \evallexpr{\envtwo, \ebv, \newmbv} \evalarrow C - } - { \evallexpr{\envtwo, \LESlice(\ebv, \slices), (\vv, \vg)} \evalarrow C } - \end{mathpar} - -\subsection{Comments} -\lrmcomment{This is related to \identr{WHRS}:} - -If the declared type of a setter’s RHS argument has the structure of a -bitvector or a type with fields, then if a bitslice or field selection is -applied to a setter invocation, then the assignment to that bitslice is -implemented using the following Read-Modify-Write (RMW) behavior: -\begin{itemize} -\item invoking the getter of the same name as the setter, with the same actual -arguments as the setter invocation -\item performing the assignment to the bitslice or field of the result of the -getter invocation -\item invoking the setter to assign the resulting value -\end{itemize} - -\section{SemanticsRule.LESetArray \label{sec:SemanticsRule.LESetArray}} - \subsection{Prose} - All of the following apply: - \begin{itemize} - \item $\vle$ denotes an array update expression, $\LESetArray(\rearray, \eindex)$; - \item evaluating the right-hand-side expression corresponding to $\rearray$ in $\env$ - is \Normal(\rmarray, \envone)\ProseOrAbnormal; - \item evaluating $\eindex$ in $\envone$ is \Normal(\mindex, \envtwo)\ProseOrAbnormal; - \item $\mindex$ consists of the native integer $\vindex$ and the execution graph $\vgone$; - \item $\vindex$ is the native integer for $\vi$; - \item $\rmarray$ consists of the native vector $\rvarray$ and the execution graph $\vgtwo$; - \item setting the value $\vv$ at index $\vi$ of $\rvarray$ is the native vector $\vvone$; - \item $\vmone$ is the pair consisting of $\vvone$ and the parallel composition of $\vgone$ and $\vgtwo$; - \item the steps so far computed the updated array, but have not assigned it to the variable - bound to the array given by $\rearray$, which is achieved next. - Evaluating the left-hand-side expression $\rearray$ in an environment $\envtwo$ with $\vmone$ - is the output configuration $C$. - \end{itemize} - - \subsection{Example} - The specification: - \VerbatimInput{../tests/ASLSemanticsReference.t/SemanticsRule.LESetArray.asl} - binds the third element of \texttt{my\_array} to the value \texttt{53}. - - \CodeSubsection{\EvalLESetArrayBegin}{\EvalLESetArrayEnd}{../Interpreter.ml} - -\subsection{Formally} -\begin{mathpar} - \inferrule{ - \evalexpr{\env, \torexpr(\rearray)} \evalarrow \Normal(\rmarray, \envone) \OrAbnormal\\ - \evalexpr{\envone, \eindex} \evalarrow \Normal(\mindex, \envtwo) \OrAbnormal\\ - \mindex \eqname (\vindex, \vgone)\\ - \vindex \eqname \nvint(\vi)\\ - \rmarray \eqname (\rvarray, \vgtwo)\\ - \setindex(\vi, \vv, \rvarray) \evalarrow \vvone\\ - \vmone \eqdef (\vvone, \vgone \parallelcomp \vgtwo)\\ - \evallexpr{\envtwo, \rearray, \vmone} \evalarrow C - } - { \evallexpr{\env, \LESetArray(\rearray, \eindex), (\vv, \vg)} \evalarrow C } -\end{mathpar} - -\subsection{Comments} -\lrmcomment{This is related to \identr{WHRS}:} -If the declared type of a setter’s RHS argument has the structure of a -bitvector or a type with fields, then if a bitslice or field selection is -applied to a setter invocation, then the assignment to that bitslice is -implemented using the following Read-Modify-Write (RMW) behavior: -\begin{itemize} -\item invoking the getter of the same name as the setter, with the same actual -arguments as the setter invocation -\item performing the assignment to the bitslice or field of the result of the -getter invocation -\item invoking the setter to assign the resulting value -\end{itemize} - -We note that the index is guaranteed by the type-checker to be within the array bounds -via \secref{TypingRule.LESetArray}. - -\hypertarget{SemanticsRule.LESetField}{} -\section{SemanticsRule.LESetField \label{sec:SemanticsRule.LESetField}} - - \subsection{Prose} - All of the following apply: - \begin{itemize} - \item $\vle$ denotes a field update expression, $\LESetField(\rerecord, \fieldname)$; - \item evaluating the right-hand-side expression corresponding to $\rerecord$ - in $\env$ is $\Normal(\rmrecord, \envone)$\ProseOrAbnormal; - \item $\rmrecord$ is a pair consisting of the native record $\rvrecord$ and - the execution graph $\vgone$; - \item setting the field $\fieldname$ in the native record $\rvrecord$ to $\vv$ - is the updated native record $\vvone$; - \item $\vmone$ is the pair consisting of the native vector $\vvone$ and the - execution graph that is, the parallel composition of $\vg$ and $\vgone$; - \item the steps so far computed the updated record, but have not assigned it to - the variable holding the record given by $\record$, which is achieved next. - Evaluating the left-hand-side expression $\rerecord$ in an environment $\envone$ with $\vmone$ - is the output configuration $C$. - \end{itemize} - - \subsection{Example} - In the specification: - \VerbatimInput{../tests/ASLSemanticsReference.t/SemanticsRule.LESetField.asl} - \texttt{my\_record.a = 42;} binds \texttt{my\_record} to \texttt{\{a: 42, b: 100\}} in the environment where \texttt{my\_record} is bound to \texttt{\{a: 3, b: 100\}}. - - \CodeSubsection{\EvalLESetFieldBegin}{\EvalLESetFieldEnd}{../Interpreter.ml} - -\subsection{Formally} -\begin{mathpar} - \inferrule{ - \evalexpr{\env, \torexpr(\rerecord)} \evalarrow \Normal(\rmrecord, \envone) \OrAbnormal\\ - \rmrecord \eqname (\rvrecord, \vgone)\\ - \setfield(\fieldname, \vv, \rvrecord) \evalarrow \vvone\\ - \vmone \eqdef (\vvone, \vg \parallelcomp \vgone)\\ - \evallexpr{\env1, \rerecord, \vmone} \evalarrow C - } - { \evallexpr{\env, \LESetField(\rerecord, \fieldname), (\vv, \vg)} \evalarrow C } -\end{mathpar} - -\subsection{Comments} -We note that the type-checker guarantees that $\fieldname$ exists in the record given by $\record$ -via TypingRule.LESetStructuredField. - -\lrmcomment{This is related to \identr{WHRS}:} -If the declared type of a setter’s RHS argument has the structure of a -bitvector or a type with fields, then if a bitslice or field selection is -applied to a setter invocation, then the assignment to that bitslice is -implemented using the following Read-Modify-Write (RMW) behavior: -\begin{itemize} -\item invoking the getter of the same name as the setter, with the same actual -arguments as the setter invocation -\item performing the assignment to the bitslice or field of the result of the -getter invocation -\item invoking the setter to assign the resulting value -\end{itemize} - -\section{SemanticsRule.LEDestructuring \label{sec:SemanticsRule.LEDestructuring}} - \subsection{Prose} - All of the following apply: - \begin{itemize} - \item $\vle$ denotes a list of left-hand-side expressions, $\LEDestructuring(\vlelist)$; - \item $\vlelist$ is the list of expressions $\vle_{1..k}$; - \item getting the values from the native vector $\vv$ at each index $i=1..k$ - results in $\vv_{i=1..k}$; - \item $\nmonads$ is the list of pairs consisting of $\vv_i$ and $\vg$ for $i=1..k$; - \item evaluating the multi-assignment between $\vlelist$ and the list $\nmonads$ - in $\env$ achieves the effects of assigning each value to the respective - subexpressions, resulting in the output configuration $C$. - \end{itemize} - -\subsection{Example} -In the specification: -\VerbatimInput{../tests/ASLSemanticsReference.t/SemanticsRule.LEDestructuring.asl} -\texttt{(x, y) = (3, 42)} binds \texttt{x} to $\nvint(3)$ and \texttt{y} to -$\nvint(42)$ in the environment where \texttt{x} is bound to $\nvint(42)$ and \texttt{y} is bound to $\nvint(3)$. - -\CodeSubsection{\EvalLEDestructuringBegin}{\EvalLEDestructuringEnd}{../Interpreter.ml} - -\subsection{Formally} -\begin{mathpar} - \inferrule{ - \vlelist \eqname [\vle_{1..k}]\\ - i=1..k: \getindex(i, \vv) \evalarrow \vv_i\\ - \nmonads \eqdef [i=1..k: (\vv_i, \vg)]\\ - \evalmultiassignment{\env, \vlelist, \nmonads} \evalarrow C - } - { \evallexpr{\env, \LEDestructuring(\vlelist), (\vv, \vg)} \evalarrow C } -\end{mathpar} - -\isempty{\subsection{Comments}} - -\section{SemanticsRule.LEMultiAssign \label{sec:SemanticsRuleLEMultiAssign}} -\subsection{Prose} -The helper relation -\hypertarget{def-evalmultiassign}{} -\[ - \evalmultiassignment{\overname{\envs}{\env} \aslsep \overname{\expr^*}{\vlelist} \aslsep \overname{(\vals \times \XGraphs)^*}{\vmlist}} \;\aslrel\; - \Normal(\overname{\XGraphs}{\newg} \aslsep \overname{\envs}{\newenv}) \cup - \overname{\TThrowing}{\ThrowingConfig} \cup \overname{\TError}{\ErrorConfig} -\] -evaluates multi-assignments. -That is, the simultaneous assignment of the list of value-execution graph pairs $\vmlist$ -to the corresponding list of left-hand side expressions $\vlelist$, in the environment $\env$. -The result is either the execution graph $\vg$ and new environment $\newenv$ or an abnormal configuration. - -\subsection{Formally} -\begin{mathpar} - \inferrule[empty]{} - { - \evalmultiassignment{\env, \emptylist, \emptylist} \evalarrow \Normal(\emptygraph, \env) - } -\and -\inferrule[nonempty]{ - \vlelist \eqname [\vle] \concat \vlelistone\\ - \vmlist \eqname [\vm] \concat \vmlistone\\ - \evallexpr{\env, \vle, \vm} \evalarrow \Normal(\envone, \vgone) \OrAbnormal\\ - \evalmultiassignment{\envone, \vlelistone, \vmlistone} \evalarrow \Normal(\newenv, \vgtwo) \OrAbnormal\\ - \newg \eqdef \ordered{\vgone}{\aslpo}{\vgtwo} -} -{ - \evalmultiassignment{\env, \vlelist, \vmlist} \evalarrow \Normal(\newg, \newenv) -} -\end{mathpar} -Notice that this rule is only defined when the lists $\vlelist$ and $\vmlist$ have the same length. -To see this, notice that -to form a derivation tree, we must employ the \textsc{nonempty} case, which ensures both lists -have at least one element and shortens the lengths of both lists by one, -until both lists become empty -which is when the \textsc{empty} axiom case is used. - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -\chapter{Evaluation of Slices \label{chap:eval_slices}} -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - -The rule for evaluating a list of slices is -SemanticsRule.Slices (see \secref{SemanticsRule.Slices}). - -The relation for evaluating a single slice is -\hypertarget{def-evalslice}{} -\[ - \begin{array}{rl} - \evalslice{\overname{\envs}{\env} \aslsep \overname{\slice}{\vs}} \;\aslrel & - \Normal(((\overname{\tint}{\vstart} \times \overname{\tint}{\vlength}) \times \overname{\XGraphs}{\newg}), \overname{\envs}{\newenv})\ \cup \\ - & \overname{\Throwing}{\ThrowingConfig} \cup \overname{\TError}{\ErrorConfig} - \end{array} -\] - -where a single slice $\vs$ is evaluated in an environment $\env$ is, -resulting either in $\Normal(((\vstart, \vlength), \vg), \newenv)$ -or an error configuration, -and one of the following applies: -\begin{itemize} - \item SemanticsRule.SliceSingle (see \secref{SemanticsRule.SliceSingle}), - \item SemanticsRule.SliceLength (see \secref{SemanticsRule.SliceLength}), - \item SemanticsRule.SliceRange (see \secref{SemanticsRule.SliceRange}), - \item SemanticsRule.SliceStar (see \secref{SemanticsRule.SliceStar}). - \end{itemize} - -\section{SemanticsRule.Slices \label{sec:SemanticsRule.Slices}} -\subsection{Prose} -The relation -\hypertarget{def-evalslices}{} -\[ - \begin{array}{rl} - \evalslices{\overname{\envs}{\env} \aslsep \overname{\slice^*}{\slices}} \;\aslrel & - \Normal((\overname{(\vals \times \vals)^*}{\ranges} \times \overname{\XGraphs}{\newg}), \overname{\envs}{\newenv})\ \cup \\ - & \overname{\Throwing}{\ThrowingConfig} \cup \overname{\TError}{\ErrorConfig} - \end{array} -\] -evaluates a list of slices $\slices$ in an environment $\env$, resulting in either \\ -$\Normal((\ranges, \newg), \newenv)$ or an abnormal configuration. - -One of the following applies: -\begin{itemize} - \item All of the following apply (\textsc{empty}): - \begin{itemize} - \item the list of slices is empty; - \item $\ranges$ is the empty list; - \item $\newg$ is the empty graph; - \item $\newenv$ is $\env$; - \end{itemize} - - \item All of the following apply (\textsc{nonempty}): - \begin{itemize} - \item the list of slices has $\slice$ as the head and $\slicesone$ as the tail; - \item evaluating the slice $\vslice$ in $\env$ results in \\ - $\Normal((\range, \vgone), \envone)$\ProseOrAbnormal; - \item evaluating the tail list $\slicesone$ in $\envone$ results in \\ - $\Normal((\rangesone, \vgtwo), \newenv)$\ProseOrAbnormal; - \item $\ranges$ is the concatenation of $\range$ to $\rangesone$; - \item $\newg$ is the parallel composition of $\vgone$ and $\vgtwo$. - \end{itemize} -\end{itemize} - -\texttt{eval\_slices env slices} is the list of pairs \texttt{(start\_n, length\_n)} that -correspond to the start (included) and the length of each slice in -$\slices$. - -\CodeSubsection{\EvalSlicesBegin}{\EvalSlicesEnd}{../Interpreter.ml} - -\subsection{Formally} -\begin{mathpar} - \inferrule[empty]{} - { - \evalslices{\env, \emptylist} \evalarrow \Normal((\emptylist, \emptygraph), \env) - } - \and - \inferrule[nonempty]{ - \slices \eqname [\vslice] \concat \slicesone\\ - \evalslice{\env, \vslice} \evalarrow \Normal((\range, \vgone), \envone) \OrAbnormal\\ - \evalslices{\envone, \slicesone} \evalarrow \Normal((\rangesone, \vgtwo), \newenv) \OrAbnormal\\ - \ranges \eqdef [\range] \concat \rangesone\\ - \newg \eqdef \vgone \parallelcomp \vgtwo - } - { - \evalslices{\env, \slices} \evalarrow \Normal((\ranges, \newg), \newenv) - } -\end{mathpar} - -\isempty{\subsection{Comments}} - -\section{SemanticsRule.SliceSingle \label{sec:SemanticsRule.SliceSingle}} - \subsection{Prose} - All of the following apply: - \begin{itemize} - \item $\vs$ is a single value slicing expression, $\SliceSingle(\ve)$; - \item evaluating $\ve$ in $\env$ results in $\Normal((\vstart, \newg)$\newenv)\ProseOrAbnormal; - \item $\vlength$ is the integer value 1. - \end{itemize} - - \subsection{Example} - In the specification: - \VerbatimInput{../tests/ASLSemanticsReference.t/SemanticsRule.SliceSingle.asl} - the slice \texttt{[2]} evaluates to \texttt{(2, 1)}, i.\,e.\ the slice of - length 1 starting at index 2. - - \CodeSubsection{\EvalSliceSingleBegin}{\EvalSliceSingleEnd}{../Interpreter.ml} - -\subsection{Formally} -\begin{mathpar} - \inferrule{ - \evalexpr{\env, \ve} \evalarrow \Normal((\vstart, \newg), \newenv) \OrAbnormal\\ - \vlength \eqdef \nvint(1) - } - { - \evalslice{\env, \SliceSingle(\ve)} \evalarrow \Normal(((\vstart, \vlength), \newg), \newenv) - } -\end{mathpar} - -\isempty{\subsection{Comments}} - -\section{SemanticsRule.SliceLength \label{sec:SemanticsRule.SliceLength}} - \subsection{Prose} - All of the following apply: - \begin{itemize} - \item $\vs$ is the slice which starts at expression~$\estart$ with length~$\elength$, - that is, $\SliceLength(\estart, \elength)$; - \item evaluating $\estart$ in $\env$ is \Normal(\mstart, \envone)\ProseOrAbnormal; - \item evaluating $\elength$ in $\envone$ is \Normal(\mlength, \newenv)\ProseOrAbnormal; - \item $\mstart$ is a pair consisting of the native integer $\vstart$ and execution graph $\vgone$; - \item $\mlength$ is a pair consisting of the native integer $\vlength$ and execution graph $\vgtwo$; - \item $\newg$ is the parallel composition of $\vgone$ and $\vgtwo$. - \end{itemize} - - \subsection{Example} - In the specification: - \VerbatimInput{../tests/ASLSemanticsReference.t/SemanticsRule.SliceLength.asl} - \texttt{2+:3} evaluates to \texttt{(2, 3)}. - - \CodeSubsection{\EvalSliceLengthBegin}{\EvalSliceLengthEnd}{../Interpreter.ml} - -\subsection{Formally} -\begin{mathpar} - \inferrule{ - \evalexpr{\env, \estart} \evalarrow \Normal(\mstart, \envone) \OrAbnormal\\ - \evalexpr{\envone, \elength} \evalarrow \Normal(\mlength, \newenv) \OrAbnormal\\ - \mstart \eqname (\vstart, \vgone)\\ - \mlength \eqname (\vlength, \vgtwo)\\ - \newg \eqdef \vgone \parallelcomp \vgtwo - } - { - \evalslice{\env, \SliceLength(\estart, \elength)} \evalarrow \\ \Normal(((\vstart, \vlength), \newg), \newenv) - } -\end{mathpar} - -\isempty{\subsection{Comments}} - -\section{SemanticsRule.SliceRange \label{sec:SemanticsRule.SliceRange}} - \subsection{Prose} - All of the following apply: - \begin{itemize} - \item $\vs$ is the slice range between the - expressions $\estart$ and $\etop$, that is, \\ $\SliceRange(\etop, \estart)$; - \item evaluating $\etop$ in $\env$ is $\Normal(\mtop, \envone)$\ProseOrAbnormal; - \item $\mtop$ is a pair consisting of the native integer $\vvsubtop$ and execution graph $\vgone$; - \item evaluating $\estart$ in $\envone$ is $\Normal(\mstart, \newenv)$\ProseOrAbnormal; - \item $\mstart$ is a pair consisting of the native integer $\vstart$ and execution graph $\vgtwo$; - \item $\vlength$ is the integer value \texttt{(v\_top - v\_start) + 1}; - \item $\newg$ is the parallel composition of $\vgone$ and $\vgtwo$. - \end{itemize} - - \subsection{Example} - In the specification: - \VerbatimInput{../tests/ASLSemanticsReference.t/SemanticsRule.SliceRange.asl} - \texttt{4:2} evaluates to \texttt{(2, 3)}. - - \CodeSubsection{\EvalSliceRangeBegin}{\EvalSliceRangeEnd}{../Interpreter.ml} - -\subsection{Formally} -\begin{mathpar} - \inferrule{ - \evalexpr{\env, \etop} \evalarrow \Normal(\mtop, \envone) \OrAbnormal\\\\ - \mtop \eqname (\vvsubtop, \vgone)\\ - \evalexpr{\envone, \estart} \evalarrow \Normal(\mstart, \newenv) \OrAbnormal\\\\ - \mstart \eqname (\vstart, \vgtwo)\\ - \binoprel(\MINUS, \vvsubtop, \vstart) \evalarrow \vdiff\\ - \binoprel(\PLUS, \nvint(1), \vdiff) \evalarrow \vlength\\ - \newg \eqdef \vgone \parallelcomp \vgtwo - } - { - \evalslice{\env, \SliceRange(\etop, \estart)} \evalarrow \\ \Normal(((\vstart, \vlength), \newg), \newenv) - } -\end{mathpar} - -\isempty{\subsection{Comments}} - -\section{SemanticsRule.SliceStar \label{sec:SemanticsRule.SliceStar}} - \subsection{Prose} - All of the following apply: - \begin{itemize} - \item $\vs$ is the slice with factor given by the - expression $\efactor$ and length given by the - expression $\elength$, that is, $\SliceStar(\efactor, \elength)$; - \item evaluating $\efactor$ in $\env$ is $\Normal(\mfactor, \envone)$\ProseOrAbnormal; - \item $\mfactor$ is a pair consisting of the native integer $\vfactor$ and execution graph $\vgone$; - \item evaluating $\elength$ in $\env$ is $\Normal(\mlength, \newenv)$\ProseOrAbnormal; - \item $\mlength$ is a pair consisting of the native integer $\vlength$ and execution graph $\vgtwo$; - \item $\vstart$ is the native integer $\vfactor \times \vlength$; - \item $\newg$ is the parallel composition of $\vgone$ and $\vgtwo$. - \end{itemize} - - \subsection{Example} - In the specification: - \VerbatimInput{../tests/ASLSemanticsReference.t/SemanticsRule.SliceStar.asl} - \texttt{x[3*:2]} evaluates to \texttt{'11'}. - - \CodeSubsection{\EvalSliceStarBegin}{\EvalSliceStarEnd}{../Interpreter.ml} - -\subsection{Formally} -\begin{mathpar} - \inferrule{ - \evalexpr{\env, \efactor} \evalarrow \Normal(\mfactor, \envone) \OrAbnormal\\ - \mfactor \eqname (\vfactor, \vgone)\\ - \evalexpr{\envone, \elength} \evalarrow \Normal(\mlength, \newenv) \OrAbnormal\\ - \mlength \eqname (\vlength, \vgtwo)\\ - \binoprel(\MUL, \vfactor, \vlength) \evalarrow \vstart \\ - \newg \eqdef \vgone \parallelcomp \vgtwo - } - { - \evalslice{\env, \SliceStar(\efactor, \elength)} \evalarrow \\ \Normal(((\vstart, \vlength), \newg), \newenv) - } -\end{mathpar} - -\isempty{\subsection{Comments}} - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -\chapter{Evaluation of Patterns \label{chap:eval_pattern}} -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - -The relation -\hypertarget{def-evalpattern}{} -\[ - \evalpattern{\overname{\envs}{\env} \aslsep \overname{\vals}{\vv} \aslsep \overname{\pattern}{\vp}} \;\aslrel\; - \Normal(\overname{\tbool}{\vb}, \overname{\XGraphs}{\newg}) -\] -determines whether a value $\vv$ matches the pattern $\vp$ in an environment $\env$ -resulting in either $\Normal(\vb, \newg)$ or an abnormal configuration, -and one of the following applies: -\begin{itemize} -\item SemanticsRule.PAll (see \secref{SemanticsRule.PAll}) -\item SemanticsRule.PAny (see \secref{SemanticsRule.PAny}) -\item SemanticsRule.PGeq (see \secref{SemanticsRule.PGeq}) -\item SemanticsRule.PLeq (see \secref{SemanticsRule.PLeq}) -\item SemanticsRule.PNot (see \secref{SemanticsRule.PNot}) -\item SemanticsRule.PRange (see \secref{SemanticsRule.PRange}) -\item SemanticsRule.PSingle (see \secref{SemanticsRule.PSingle}) -\item SemanticsRule.PMask (see \secref{SemanticsRule.PMask}) -\item SemanticsRule.PTuple (see \secref{SemanticsRule.PTuple}) -\end{itemize} - -\section{SemanticsRule.PAll \label{sec:SemanticsRule.PAll}} - \subsection{Prose} - All of the following apply: - \begin{itemize} - \item $\vp$ is the pattern which matches everything, $\PatternAll$, and therefore - matches $\vv$; - \item $\vb$ is the native Boolean value \True; - \item $\newg$ is the empty graph. - \end{itemize} - - \subsection{Example} - \VerbatimInput{../tests/ASLSemanticsReference.t/SemanticsRule.PAll.asl} - - \CodeSubsection{\EvalPAllBegin}{\EvalPAllEnd}{../Interpreter.ml} - -\subsection{Formally} -\begin{mathpar} - \inferrule{} - { - \evalpattern{\env, \Ignore, \PatternAll} \evalarrow \Normal(\nvbool(\True), \emptygraph) - } -\end{mathpar} - -\isempty{\subsection{Comments}} - -\section{SemanticsRule.PAny \label{sec:SemanticsRule.PAny}} - \subsection{Prose} - All of the following apply: - \begin{itemize} - \item $\vp$ is a list of patterns, $\PatternAny(\vps)$; - \item $\vps$ is $\vp_{1..k}$; - \item evaluating each pattern $\vp_i$ in $\env$ results in $\Normal(\nvbool(\vb_i), \vg_i)$\ProseOrAbnormal; - \item $\vb$ is the native Boolean which is the disjunction of $\vb_i$, for $i=1..k$; - \item $\newg$ is the parallel composition of all execution graphs $\vg_i$, for $i=1..k$. - \end{itemize} - - \subsection{Example} - \VerbatimInput{../tests/ASLSemanticsReference.t/SemanticsRule.PAnyTRUE.asl} - - \subsection{Example} - \VerbatimInput{../tests/ASLSemanticsReference.t/SemanticsRule.PAnyFALSE.asl} - - \CodeSubsection{\EvalPAnyBegin}{\EvalPAnyEnd}{../Interpreter.ml} - -\subsection{Formally} -\begin{mathpar} - \inferrule{ - \vps \eqname \vp_{1..k}\\ - i=1..k : \evalpattern{\env, \vv, \vp_i} \evalarrow \Normal(\nvbool(\vb_i), \vg_i) \OrDynError\\\\ - \vb \eqdef \nvbool(\bigvee_{i=1..k} \vb_i)\\ - \newg \eqdef \vg_1 \parallelcomp \ldots \parallelcomp \vg_k - } - { - \evalpattern{\env, \vv, \PatternAny(\vps)} \evalarrow \Normal(\vb, \newg) - } -\end{mathpar} - -\isempty{\subsection{Comments}} - -\section{SemanticsRule.PGeq \label{sec:SemanticsRule.PGeq}} - \subsection{Prose} - All of the following apply: - \begin{itemize} - \item $\vp$ is the condition corresponding to being greater than or equal - than the side-effect-free expression $\ve$, $\PatternGeq(\ve)$; - \item the side-effect-free evaluation of $\ve$ is either - $\Normal(\vvone, \newg)$\ProseOrError; - \item $\vb$ is the Boolean value corresponding to whether $\vv$ - is greater than or equal to $\vvone$. - \end{itemize} - - \subsection{Example} - \VerbatimInput{../tests/ASLSemanticsReference.t/SemanticsRule.PGeqTRUE.asl} - - \subsection{Example} - \VerbatimInput{../tests/ASLSemanticsReference.t/SemanticsRule.PGeqFALSE.asl} - - \CodeSubsection{\EvalPGeqBegin}{\EvalPGeqEnd}{../Interpreter.ml} - -\subsection{Formally} -\begin{mathpar} - \inferrule{ - \evalexprsef{\env, \ve} \evalarrow \Normal(\vvone, \newg) \OrDynError\\\\ - \binoprel(\GEQ, \vv, \vvone) \evalarrow \vb - } - { - \evalpattern{\env, \vv, \PatternGeq(\ve)} \evalarrow \Normal(\vb, \newg) - } -\end{mathpar} - -\isempty{\subsection{Comments}} - -\section{SemanticsRule.PLeq \label{sec:SemanticsRule.PLeq}} - \subsection{Prose} - All of the following apply: - \begin{itemize} - \item $\vp$ is the condition corresponding to being less than or equal - to the side-effect-free expression $\ve$, $\PatternLeq(\ve)$; - \item the side-effect-free evaluation of $\ve$ is either - $\Normal(\vvone, \newg)$\ProseOrError; - \item $\vb$ is the Boolean value corresponding to whether $\vv$ - is less than or equal to $\vvone$. - \end{itemize} - - \subsection{Example} - \VerbatimInput{../tests/ASLSemanticsReference.t/SemanticsRule.PLeqTRUE.asl} - - \subsection{Example} - \VerbatimInput{../tests/ASLSemanticsReference.t/SemanticsRule.PLeqFALSE.asl} - - \CodeSubsection{\EvalPLeqBegin}{\EvalPLeqEnd}{../Interpreter.ml} - -\subsection{Formally} -\begin{mathpar} - \inferrule{ - \evalexprsef{\env, \ve} \evalarrow \Normal(\vvone, \newg) \OrDynError\\\\ - \binoprel(\LEQ, \vv, \vvone) \evalarrow \vb - } - { - \evalpattern{\env, \vv, \PatternLeq(\ve)} \evalarrow \Normal(\vb, \newg) - } -\end{mathpar} - -\isempty{\subsection{Comments}} - -\section{SemanticsRule.PNot \label{sec:SemanticsRule.PNot}} - \subsection{Prose} - All of the following apply: - \begin{itemize} - \item $\vp$ is a negation pattern, $\PatternNot(\vpone)$; - \item evaluating that pattern $\vpone$ in an environment $\env$ is \\ - $\Normal(\vbone, \newg)$\ProseOrError; - \item $\vb$ is the Boolean negation of $\vbone$. - \end{itemize} - - \subsection{Example} - \VerbatimInput{../tests/ASLSemanticsReference.t/SemanticsRule.PNotTRUE.asl} - - \subsection{Example} - \VerbatimInput{../tests/ASLSemanticsReference.t/SemanticsRule.PNotFALSE.asl} - - \CodeSubsection{\EvalPNotBegin}{\EvalPNotEnd}{../Interpreter.ml} - -\subsection{Formally} -\begin{mathpar} - \inferrule{ - \evalexprsef{\env, \vpone} \evalarrow \Normal(\vbone, \newg) \OrDynError\\\\ - \unoprel(\BNOT, \vbone) \evalarrow \vb - } - { - \evalpattern{\env, \vv, \PatternNot(\vpone)} \evalarrow \Normal(\vb, \newg) - } -\end{mathpar} - -\isempty{\subsection{Comments}} - -\section{SemanticsRule.PRange \label{sec:SemanticsRule.PRange}} - \subsection{Prose} - All of the following apply: - \begin{itemize} - \item $\vp$ is the condition corresponding to being greater than or equal - to $\veone$, and lesser or equal to $\vetwo$, that is, $\PatternRange(\veone, \vetwo)$; - \item $\veone$ and $\vetwo$ are side-effect-free expressions; - \item the side-effect-free evaluation of $\veone$ in $\env$ is $\Normal(\vvone, \vgone)$\ProseOrError; - \item the side-effect-free evaluation of $\vetwo$ in $\env$ is $\Normal(\vvtwo, \vgtwo)$\ProseOrError; - \item $\vbone$ is the Boolean value corresponding to whether - $\vv$ is greater than or equal to $\vvone$; - \item $\vbtwo$ is the Boolean value corresponding to whether - $\vv$ is less than or equal to $\vvtwo$; - \item $\vb$ is the Boolean conjunction of $\vbone$ and - $\vbtwo$; - \item $\newg$ is the parallel composition of $\vgone$ and $\vgtwo$. - \end{itemize} - - \subsection{Example} - \VerbatimInput{../tests/ASLSemanticsReference.t/SemanticsRule.PRangeTRUE.asl} - - \subsection{Example} - \VerbatimInput{../tests/ASLSemanticsReference.t/SemanticsRule.PRangeFALSE.asl} - - \CodeSubsection{\EvalPRangeBegin}{\EvalPRangeEnd}{../Interpreter.ml} - -\subsection{Formally} -\begin{mathpar} - \inferrule{ - \evalexprsef{\env, \veone} \evalarrow \Normal(\vvone, \vgone) \OrDynError\\\\ - \binoprel(\GEQ, \vv, \vvone) \evalarrow \vbone\\ - \evalexprsef{\env, \veone} \evalarrow \Normal(\vvtwo, \vgtwo) \OrDynError\\\\ - \binoprel(\LEQ, \vv, \vvtwo) \evalarrow \vbtwo\\ - \binoprel(\BAND, \vbone, \vbtwo) \evalarrow \vb\\ - \newg \eqdef \vgone \parallelcomp \vgtwo - } - { - \evalpattern{\env, \vv, \PatternRange(\veone, \vetwo)} \evalarrow \Normal(\vb, \newg) - } -\end{mathpar} - -\isempty{\subsection{Comments}} - -\section{SemanticsRule.PSingle \label{sec:SemanticsRule.PSingle}} - \subsection{Prose} - All of the following apply: - \begin{itemize} - \item $\vp$ is the condition corresponding to being equal to the - side-effect-free expression $\ve$, $\PatternSingle(\ve)$; - \item the side-effect-free evaluation of $\ve$ in - environment $\env$ is \\ $\Normal(\vvone, \newg)$\ProseOrError; - \item $\vb$ is the Boolean value corresponding to whether $\vv$ - is equal to $\vvone$. - \end{itemize} - - \subsection{Example} - \VerbatimInput{../tests/ASLSemanticsReference.t/SemanticsRule.PSingleTRUE.asl} - - \subsection{Example} - \VerbatimInput{../tests/ASLSemanticsReference.t/SemanticsRule.PSingleFALSE.asl} - - \CodeSubsection{\EvalPSingleBegin}{\EvalPSingleEnd}{../Interpreter.ml} - -\subsection{Formally} -\begin{mathpar} - \inferrule{ - \evalexprsef{\env, \veone} \evalarrow \Normal(\vvone, \newg) \OrDynError\\\\ - \binoprel(\EQOP, \vvone, \vvone) \evalarrow \vb - } - { - \evalpattern{\env, \vv, \PatternSingle(\ve)} \evalarrow \Normal(\vb, \newg) - } -\end{mathpar} - -\isempty{\subsection{Comments}} - -\section{SemanticsRule.PMask \label{sec:SemanticsRule.PMask}} - \subsection{Prose} - All of the following apply: - \begin{itemize} - \item $\vp$ is a mask pattern, $\PatternMask(\vm)$, - of length $n$ (with spaces removed); - \item $\vv$ is a native bitvector of bits $\vu_{1..n}$; - \item $\vb$ is the native Boolean formed from the conjunction of Boolean values for each $i$, - where the bit $\vu_i$ is checked for matching the mask character $\vm_i$; - \item $\newg$ is the empty graph. - \end{itemize} - - \subsection{Example} - \VerbatimInput{../tests/ASLSemanticsReference.t/SemanticsRule.PMaskTRUE.asl} - - \subsection{Example} - \VerbatimInput{../tests/ASLSemanticsReference.t/SemanticsRule.PMaskFALSE.asl} - - \CodeSubsection{\EvalPMaskBegin}{\EvalPMaskEnd}{../Interpreter.ml} - -\subsection{Formally} - \newcommand\maskmatch[0]{\text{mask\_match}} - The helper function $\maskmatch : \{0, 1, \vx\} \times \{0,1\} \rightarrow \Bool$, - checks whether a bit value (second operand) matches a mask value (first operand), - is defined by the following table: -\[ - \begin{array}{|c|c|c|c|} - \hline - \textbf{\maskmatch} & 0 & 1 & \vx\\ - \hline - 0 & \True & \False & \True\\ - \hline - 1 & \False & \True & \True\\ - \hline - \end{array} -\] - -\begin{mathpar} - \inferrule{ - \vm \eqname \vm_{1..n}\\ - \vv \eqname \nvbitvector(\vu_{1..n})\\ - \vb \eqdef \nvbool(\bigwedge_{i=1..n} \maskmatch(\vm_i, \vu_i)) - } - { - \evalpattern{\env, \vv, \PatternMask(\vm)} \evalarrow \Normal(\vb, \emptygraph) - } -\end{mathpar} - -\isempty{\subsection{Comments}} - -\section{SemanticsRule.PTuple \label{sec:SemanticsRule.PTuple}} - - \subsection{Prose} - All of the following apply: - \begin{itemize} - \item $\vp$ gives a list of patterns $\vps$ of length $k$, $\PatternTuple(\vps)$; - \item $\vv$ gives a tuple of values $\vvs$ of length $k$; - \item for all $1 \leq i \leq n$, $\vb_i$ is the evaluation result - of $\vp_i$ with respect to the value $\vv_i$ in - environment $\env$; - \item $\vbs$ is the list of all $\vb_i$ for $1 \leq i \leq k$; - \item $\vb$ is the conjunction of the Boolean values of $\vbs$. - \end{itemize} - - \subsection{Example} - \VerbatimInput{../tests/ASLSemanticsReference.t/SemanticsRule.PTupleTRUE.asl} - - \subsection{Example} - \VerbatimInput{../tests/ASLSemanticsReference.t/SemanticsRule.PTupleFALSE.asl} - - \CodeSubsection{\EvalPTupleBegin}{\EvalPTupleEnd}{../Interpreter.ml} - -\subsection{Formally} -\begin{mathpar} - \inferrule{ - \vps \eqname \vp_{1..k}\\ - i=1..k: \getindex(i, \vv) \evalarrow \vvs_i\\ - i=1..k: \evalpattern{\env, \vvs_i, \vp_i} \evalarrow \Normal(\nvbool(\vbs_i), \vg_i) \OrDynError\\\\ - \vres \eqdef \nvbool(\bigwedge_{i=1..k} \vbs_i)\\ - \vg \eqdef \vg_1 \parallelcomp \ldots \parallelcomp \vg_k - } - { - \evalpattern{\env, \vv, \PatternTuple(\vps)} \evalarrow \Normal(\vres, \emptygraph) - } -\end{mathpar} - -\isempty{\subsection{Comments}} - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -\chapter{Evaluation of Local Declarations \label{chap:eval_local_decl}} -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - -The relation -\hypertarget{def-evallocaldecl}{} -\[ - \evallocaldecl{ - \overname{\envs}{\env} \aslsep - \overname{\localdeclitem}{\ldi} \aslsep - \overname{\langle\overname{\vals}{\vv}\times\overname{\XGraphs}{\vgone}\rangle}{\minitopt} - } \;\aslrel\; - \Normal(\overname{\XGraphs}{\newg}, \overname{\envs}{\newenv}) -\] -evaluates a local declaration of one or more variables $\ldi$ in -$\env$ with an optional initialization value $\minitopt$. -That is, the right-hand side of the declaration, if it exists, -has already been evaluated, yielding $\minitopt$ (see, for example, SemanticsRule.SDeclSome in \secref{SemanticsRule.SDeclSome}). -Evaluation of the local variables $\ldi$ -in an environment $\env$ is either $\Normal(\vg, \newenv)$ -or an abnormal configuration and one of the following applies: -\begin{itemize} - \item SemanticsRule.LDDiscard (see \secref{SemanticsRule.LDDiscard}), - \item SemanticsRule.LDVar (see \secref{SemanticsRule.LDVar}), - \item SemanticsRule.LDTyped (see \secref{SemanticsRule.LDTyped}), - \item SemanticsRule.LDTuple (see \secref{SemanticsRule.LDTuple}), - \item SemanticsRule.LDUninitialisedTyped (see \secref{SemanticsRule.LDUninitialisedTyped}), -\end{itemize} - -Recall that ASL has three different categories of variable declarations --- -%Recall from where? -constants, mutable variables (declared via \texttt{var}), and immutable variables (declared via \texttt{let}). -From the perspective of evaluating the semantics of local declarations (and local declarations statements -in \chapref{eval_stmt}), they are all treated the same way. - -\section{SemanticsRule.LDDiscard \label{sec:SemanticsRule.LDDiscard}} -\subsection{Prose} -All of the following apply: -\begin{itemize} - \item $\ldi$ indicates that the initialization value will be discarded, - $\LDIDiscard$; - \item $\newg$ is the empty graph; - \item $\newenv$ is $\env$. -\end{itemize} - -\subsection{Example} -In the specification: -\VerbatimInput{../tests/ASLSemanticsReference.t/SemanticsRule.LDDiscard.asl} -\texttt{var - : integer;} does not modify the environment. - -\CodeSubsection{\EvalLDDiscardBegin}{\EvalLDDiscardEnd}{../Interpreter.ml} - -\subsection{Formally} -\begin{mathpar} -\inferrule{} -{ - \evallocaldecl{\env, \overname{\LDIDiscard}{\ldi}, \overname{\color{white}{\texttt{xx}\Ignore}\texttt{xx}}{\minitopt}} - \evalarrow \Normal(\overname{\emptygraph}{\newg}, \overname{\env}{\newenv}) -} -\end{mathpar} - -\isempty{\subsection{Comments}} - -\section{SemanticsRule.LDVar \label{sec:SemanticsRule.LDVar}} - \subsection{Prose} - All of the following apply: - \begin{itemize} - \item $\ldi$ is a variable declaration, $\LDIVar(\vx)$; - \item $\minitopt$ is $\vm$; - \item $\vm$ is a pair consisting of the value $\vv$ and execution graph $\vgone$; - \item declaring $\vx$ in $\env$ is $(\newenv, \vgtwo)$; - \item $\newg$ is the ordered composition of $\vgone$ and $\vgtwo$ with the $\asldata$ edge. - \end{itemize} - -\subsection{Example} -In the specification: -\VerbatimInput{../tests/ASLSemanticsReference.t/SemanticsRule.LDVar0.asl} -\texttt{var x = 3;} binds \texttt{x} to the evaluation of \texttt{3} in $\env$. - -\subsection{Example} -In the specification: -\VerbatimInput{../tests/ASLSemanticsReference.t/SemanticsRule.LDVar1.asl} -\texttt{var x : integer = 3;} binds \texttt{x} to the evaluation of -\texttt{3} in $\env$, without type consideration at runtime. - -\CodeSubsection{\EvalLDVarBegin}{\EvalLDVarEnd}{../Interpreter.ml} - -\subsection{Formally} -\begin{mathpar} - \inferrule{ - \vm \eqname (\vv, \vgone)\\ - \declarelocalidentifier(\env, \vx, \vv)\evalarrow(\newenv, \vgtwo)\\ - \newg \eqdef \ordered{\vgone}{\asldata}{\vgtwo} - } - { - \evallocaldecl{\env, \LDIVar(\vx), \langle \vm\rangle} \evalarrow \Normal(\newg, \newenv) - } -\end{mathpar} - -\isempty{\subsection{Comments}} - -\section{SemanticsRule.LDTyped \label{sec:SemanticsRule.LDTyped}} -\subsection{Prose} -All of the following apply: -\begin{itemize} - \item $\ldi$ is a typed declaration, $\LDITyped(\ldione, \vt)$; - \item $\minitopt$ is $\vm$; - \item the resulting configuration is obtained via the evaluation - of the local declaration $\ldione$ in $\env$ with $\minitopt$ as $\vm$, - that is, \\ $\evallocaldecl{\env, \ldi1, \langle \vm\rangle}$. -\end{itemize} - -\subsection{Example} -In the specification: -\VerbatimInput{../tests/ASLSemanticsReference.t/SemanticsRule.LDTyped.asl} -\texttt{var x : integer = 42;} binds \texttt{x} in $\env$ to $\nvint(42)$. - -\CodeSubsection{\EvalLDTypedBegin}{\EvalLDTypedEnd}{../Interpreter.ml} - -\subsection{Formally} -\begin{mathpar} -\inferrule{ - \evallocaldecl{\env, \ldi1, \langle \vm\rangle} \evalarrow C -}{ - \evallocaldecl{\env, \LDITyped(\ldi1, \Ignore), \langle \vm\rangle} \evalarrow C -} -\end{mathpar} - -\isempty{\subsection{Comments}} - -\section{SemanticsRule.LDTuple \label{sec:SemanticsRule.LDTuple}} - \subsection{Prose} - All of the following apply: - \begin{itemize} - \item $\ldi$ declares a list of local variables, $\LDITuple(\ldis)$; - \item $\minitopt$ is $\vm$; - \item $\vm$ is a pair consisting of the native vector $\vv$ and execution graph $\vg$; - \item $\ldis$ is a list of local declaration items $\ldi_{1..k}$; - \item the value at each index of $\vv$ is $\vv_i$, for $i=1..k$; - \item $\liv$ is the list of pairs $(\vv_i, \vg)$, for $i=1..k$; - \item the output configuration is obtained by declare each local declaration item $\ldi_i$ - with the corresponding value ($\minitopt$ component) $(\vv_i, \vg)$. - \end{itemize} - -\subsection{Example} -In the specification: -\VerbatimInput{../tests/ASLSemanticsReference.t/SemanticsRule.LDTuple.asl} -\texttt{var (x,y,z) = (1,2,3);} binds \texttt{x} to the evaluation of -\texttt{1}, \texttt{y} to the evaluation of \texttt{2}, and \texttt{z} to the -evaluation of \texttt{3}) in $\env$. - - \CodeSubsection{\EvalLDTupleBegin}{\EvalLDTupleEnd}{../Interpreter.ml} - -\newcommand\ldituplefolder[0]{\hyperlink{def-ldituplefolder}{\textfunc{ldi\_tuple\_folder}}} - -\subsection{Formally} -\hypertarget{def-ldituplefolder}{} -We first define the helper semantic relation -\[ - \ldituplefolder(\overname{\envs}{\env} \aslsep \overname{\localdeclitem^*}{\ldis} \aslsep \overname{(\vals \times \XGraphs)^*}{\liv}) \;\aslrel\; - \Normal(\overname{\XGraphs}{\vg} \aslsep \overname{\envs}{\newenv}) -\] -via the following rules: -\begin{mathpar} - \inferrule{} - { - \ldituplefolder(\env, \emptylist, \emptylist) \evalarrow \Normal(\emptygraph, \env) - } -\and - \inferrule{ - \ldis \eqname [\ldi] \concat \ldis'\\ - \liv \eqname [\vm] \concat \liv'\\ - \vm \eqname (\vv, \vgone)\\ - \evallocaldecl{\env, \ldi, \langle\vm\rangle} \evalarrow \Normal(\vgone, \envone)\\ - \ldituplefolder(\envone, \ldis', \liv') \evalarrow \Normal(\vgtwo, \newenv)\\ - \newg \eqdef \vgone \parallelcomp \vgtwo - } - { - \ldituplefolder(\env, \ldis, \liv) \evalarrow \Normal(\newg, \newenv) - } -\end{mathpar} - -We now use the helper rules to define the rule for local declaration item tuples: -\begin{mathpar} - \inferrule{ - \vm \eqname (\vv, \vg)\\ - \ldis \eqname \ldi_{1..k}\\ - i=1..k: \getindex(i, \vv) \evalarrow \vv_i\\ - \liv \eqname [i=1..k: (\vv_i, \vg)]\\ - \ldituplefolder(\env, \ldis, \liv) \evalarrow C - } - { - \evallocaldecl{\env, \LDITuple(\ldis), \langle \vm\rangle} \evalarrow C - } -\end{mathpar} - -\isempty{\subsection{Comments}} - -\section{SemanticsRule.LDUninitialisedTyped\label{sec:SemanticsRule.LDUninitialisedTyped}} -\subsection{Prose} -All of the following apply: -\begin{itemize} - \item $\ldi$ gives a local declaration with a type, but no initial value, $\LDITyped(\ldione, \vt)$; - \item $\minitopt$ is $\None$; - \item the base value of $\vt$ is $\vm$\ProseOrError; - \item evaluating the local declaration $\ldione$ with $\vm$ - as the $\minitopt$ component yields the output configuration. -\end{itemize} - -\subsection{Example} -In the specification: -\VerbatimInput{../tests/ASLSemanticsReference.t/SemanticsRule.LDUninitialisedTyped.asl} -\verb|var x : integer{3..43};| binds \texttt{x} in $\env$ to the base value of \verb|integer{3..43}|, -which is $\nvint(3)$. - -\CodeSubsection{\EvalLDUninitialisedTypedBegin}{\EvalLDUninitialisedTypedEnd}{../Interpreter.ml} - -\subsection{Formally} -\begin{mathpar} - \inferrule{ - \basevalue(\env, \vt) \evalarrow \vm \OrDynError\\\\ - \evallocaldecl{\env, \ldione, \langle \vm \rangle} \evalarrow C - } - { - \evallocaldecl{\env, \LDITyped(\ldione, \vt), \None} \evalarrow C - } -\end{mathpar} - -\isempty{\subsection{Comments}} - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -\chapter{Evaluation of Statements \label{chap:eval_stmt}} -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -% \lrmcomment{This is related to \identr{PTNG}:} - -% \section{Informal preamble} -% Statements consist of: -% \begin{itemize} -% \item Pass statements, which do nothing (see \secref{SemanticsRule.SPass}), -% \item Assignment statements (see \secref{SemanticsRule.SAssign} and \secref{SemanticsRule.SAssignCall}), -% \item Sequencing statements (see \secref{SemanticsRule.SSeq}), -% \item Return statements (see \secref{ReturnStatements}, \secref{SemanticsRule.SReturnNone}, \secref{SemanticsRule.SReturnOne}, and \secref{SemanticsRule.SReturnSome}), -% \item Procedure invocation statements (see \secref{SemanticsRule.SCall}), -% \item Case statements (see \secref{SemanticsRule.SCase}), -% \item Assertion statements (see \secref{SemanticsRule.SAssert}), -% \item Repetitive statements (see \secref{SemanticsRule.SWhile}, \secref{SemanticsRule.SRepeat}, \secref{SemanticsRule.SFor}), -% \item Throw statements, which throw exceptions (see \secref{SemanticsRule.SThrowNone} and \secref{SemanticsRule.SThrowSomeTyped}), -% \item Conditional statements (see \secref{SemanticsRule.SCond}), -% \item Exception handling (see \secref{SemanticsRule.STry}), -% \item Declarations of variables, let values and constants (see \secref{SemanticsRule.SDeclSome} and \secref{SemanticsRule.SDeclNone}). -% \end{itemize} - -% \section{Formal preamble} - -The relation -\hypertarget{def-evalstmt}{} -\[ - \evalstmt{\overname{\envs}{\env} \aslsep \overname{\stmt}{\vs}} \;\aslrel\; - \left( - \begin{array}{cl} - \overname{\TReturning}{\Returning((\vvs,\newg), \newenv)} & \cup\\ - \overname{\TContinuing}{\Continuing(\newg,\newenv)} & \cup\\ - \overname{\TThrowing}{\ThrowingConfig} & \cup \\ - \overname{\TError}{\ErrorConfig} & - \end{array} - \right) -\] -evaluates a statement $\vs$ in an environment $\env$, resulting in one of four types of configurations -(see more details in \secref{KindsOfSemanticConfigurations}): -\begin{itemize} - \item returning configurations with values $\vvs$, execution graph $\newg$, and a modified environment $\newenv$; - \item continuing configurations with an execution graph $\newg$ and modified environment $\newenv$; - \item throwing configurations; - \item error configurations. -\end{itemize} - -In evaluating a statement $\vs$, one of the following applies: -\begin{itemize} -\item SemanticsRule.SPass (see \secref{SemanticsRule.SPass}), -\item SemanticsRule.SAssign (see \secref{SemanticsRule.SAssign}), -\item SemanticsRule.SAssignCall (see \secref{SemanticsRule.SAssignCall}), -\item SemanticsRule.SReturnNone (see \secref{SemanticsRule.SReturnNone}), -\item SemanticsRule.SReturnOne (see \secref{SemanticsRule.SReturnOne}), -\item SemanticsRule.SReturnSome (see \secref{SemanticsRule.SReturnSome}), -\item SemanticsRule.SSeq (see \secref{SemanticsRule.SSeq}), -\item SemanticsRule.SCall (see \secref{SemanticsRule.SCall}), -\item SemanticsRule.SCond (see \secref{SemanticsRule.SCond}), -\item SemanticsRule.SCase (see \secref{SemanticsRule.SCase}), -\item SemanticsRule.SAssert (see \secref{SemanticsRule.SAssert}), -\item SemanticsRule.SWhile (see \secref{SemanticsRule.SWhile}), -\item SemanticsRule.SRepeat (see \secref{SemanticsRule.SRepeat}), -\item SemanticsRule.SFor (see \secref{SemanticsRule.SFor}), -\item SemanticsRule.SThrowNone (see \secref{SemanticsRule.SThrowNone}), -\item SemanticsRule.SThrowSomeTyped (see \secref{SemanticsRule.SThrowSomeTyped}), -\item SemanticsRule.STry (see \secref{SemanticsRule.STry}), -\item SemanticsRule.SDeclSome (see \secref{SemanticsRule.SDeclSome}), -\item SemanticsRule.SDeclNone (see \secref{SemanticsRule.SDeclNone}). -\end{itemize} - -\section{SemanticsRule.SPass \label{sec:SemanticsRule.SPass}} -\subsection{Syntax} - -\subsection{Example} -In the specification: -\VerbatimInput{../tests/ASLSemanticsReference.t/SemanticsRule.SPass.asl} -\texttt{pass;} does nothing. - -\subsection{Formally} -All of the following apply: -\begin{itemize} -\item $\vs$ is a \texttt{pass} statement, $\SPass$; -\item $\newg$ is the empty graph; -\item $\newenv$ is $\env$. -\end{itemize} - -\begin{mathpar} -\inferrule{}{ - \evalstmt{\env, \SPass} \evalarrow \Continuing(\overname{\emptygraph}{\newg}, \overname{\env}{\newenv}) -} -\end{mathpar} - -\isempty{\subsection{Comments}} - -\CodeSubsection{\EvalSPassBegin}{\EvalSPassEnd}{../Interpreter.ml} - -\section{SemanticsRule.SAssign \label{sec:SemanticsRule.SAssign}} -\subsection{Example} -In the specification: -\VerbatimInput{../tests/ASLSemanticsReference.t/SemanticsRule.SAssign.asl} -\texttt{x = 3;} binds \texttt{x} to $\nvint(3)$ in the environment where \texttt{x} is bound to -$\nvint(42)$, and $\newenv$ is such that \texttt{x} is bound to $\nvint(3)$. - -\subsection{Formally} -All of the following apply: -\begin{itemize} - \item $\vs$ is an assignment statement, $\SAssign(\vle, \vre)$; - \item $\vre$ is not a call expression; - \item evaluating the expression $\vre$ in $\env$ as per \chapref{eval_expr} is - $\Normal(\vm, \envone)$ (here, $\vm$ is a pair consisting of a value and an execution graph)\ProseOrAbnormal; - \item evaluating the left-hand-side expression $\vle$ with $\vm$ in $\envone$, - as per \chapref{eval_lexpr}, is $\Normal(\newg, \newenv)$\ProseOrAbnormal. -\end{itemize} - -\begin{mathpar} -\inferrule{ - \astlabel(\vre) \neq \ECall\\ - \evalexpr{\env, \vre} \evalarrow \Normal(\vm, \envone) \OrAbnormal\\ - \evallexpr{\envone, \vle, \vm} \evalarrow \Normal(\newg, \newenv) \OrAbnormal -}{ - \evalstmt{\env, \SAssign(\vle, \vre)} \evalarrow \Continuing(\newg, \newenv) -} -\end{mathpar} - -\subsection{Comments} -This rule covers all assignment statements, except the ones where the -right-hand side expression is a function call, which is covered by -SemanticsRule.SAssignCall (see \secref{SemanticsRule.SAssignCall}). Although -the sequential semantics of both statements is the same, -SemanticsRule.SAssignCall generates a different execution graph. - -Notice that this rule first produces a value for the right-hand side expression -and then completes the update via an appropriate rule for evaluating the -left-hand side expression, which in turn handles variables, tuples, bitvectors, -etc. - -\CodeSubsection{\EvalSAssignBegin}{\EvalSAssignEnd}{../Interpreter.ml} - -\section{SemanticsRule.SAssignCall \label{sec:SemanticsRule.SAssignCall}} - -\isempty{\subsection{Example}} - -\VerbatimInput{\semanticstests/SemanticsRule.SAssignCall.asl} -given that the function call \texttt{f(1)} returns a pair of values --- $\nvint(1)$ and $\nvint(2)$ -(each with its own associated execution graph), -the statement \texttt{(a,b) = f(1)} assigns the value $\nvint(1)$ to the mutable variable \texttt{a} -and the value $\nvint(2)$ to the mutable variable~\texttt{b}. - -\subsection{Formally} -All of the following apply: -\begin{itemize} - \item $\vs$ assigns a left-hand-side expression list from a subprogram call, \\ - $\SAssign(\LEDestructuring(\les),\ECall(\name, \args, \namedargs))$; - \item $\les$ is a list of left-hand-side expressions, each of which is either \\ a variable ($\LEVar(\Ignore)$) - or a discarded variable (\LEDiscard); - \item evaluating the subprogram call as per \chapref{eval_call} is - $\Normal(\vms, \envone)$\ProseOrAbnormal; - \item assigning each value in $\vms$ to the respective element of the tuple $\les$ is \\ - $\Normal(\vgtwo, \newg)$\ProseOrAbnormal. -\end{itemize} - -\hypertarget{def-lexprisvar}{} -We first define the syntactic predicate -\[ - \lexprisvar(\lexpr) \aslto \True -\] -which holds when a left-hand side expression -represents a variable: -\begin{mathpar} - \inferrule{}{ \lexprisvar(\LEVar(\Ignore)) \evalarrow \True} - \and - \inferrule{}{ \lexprisvar(\LEDiscard) \evalarrow \False} -\end{mathpar} - -We now define the evaluation of assigning from a subprogram call: -\begin{mathpar} -\inferrule{ - \vles \eqdef \vle_{1..k}\\ - i=1..k: \lexprisvar(\vle_i) \evalarrow \True\\ - \evalcall{\env, \name, \args, \namedargs} \evalarrow \Normal(\vms, \envone) \OrAbnormal\\\\ - \evalmultiassignment{\envone, \vles, \vms} \evalarrow \Normal(\newg, \newenv) \OrAbnormal -}{ - \evalstmt{\env, \SAssign(\LEDestructuring(\les),\ECall(\name, \args, \namedargs))} \\ - \evalarrow \Continuing(\newg, \newenv) -} -\end{mathpar} - -\isempty{\subsection{Comments}} - -\CodeSubsection{\EvalSAssignCallBegin}{\EvalSAssignCallEnd}{../Interpreter.ml} - -\section{Return statements \label{sec:ReturnStatements}} - -% \lrmcomment{This is related to \identd{HTPL}:} - -% A return statement returns the control flow to the caller of a subprogram. - -% \lrmcomment{This is related to \identr{PHNZ}:} - -% A return statement appearing in a getter or function requires a return value expression that type-satisfies the return type of the subprogram. - -% \lrmcomment{This is related to \identr{NYWH}:} - -% A return statement appearing in a setter or procedure must have no return value expression. - -\subsection{SemanticsRule.SReturnNone \label{sec:SemanticsRule.SReturnNone}} -\subsubsection{Example} -The specification: -\VerbatimInput{../tests/ASLSemanticsReference.t/SemanticsRule.SReturnNone.asl} -exits the current procedure. - -\subsubsection{Prose} -All of the following apply: -\begin{itemize} - \item $\vs$ is a \texttt{return} statement, $\SReturn(\None)$; - \item $\vvs$ is the empty list, $\emptylist$; - \item $\newg$ is the empty graph; - \item $\newenv$ is $\env$. -\end{itemize} - -\begin{mathpar} -\inferrule{} -{ - \evalstmt{\env, \SReturn(\None)} \evalarrow \Returning((\emptylist, \emptygraph), \env) -} -\end{mathpar} - -\isempty{\subsubsection{Comments}} - -\CodeSubsubsection{\SReturnNoneBegin}{\EvalSReturnNoneEnd}{../Interpreter.ml} - -\subsection{SemanticsRule.SReturnOne \label{sec:SemanticsRule.SReturnOne}} -\subsubsection{Example} -In the specification: -\VerbatimInput{../tests/ASLSemanticsReference.t/SemanticsRule.SReturnOne.asl} -\texttt{return 3;} exits the current subprogram with value \texttt{3}. - -\subsubsection{Prose} -All of the following apply: -\begin{itemize} - \item $\vs$ is a \texttt{return} statement; - \item $\vs$ is a \texttt{return} statement for a single expression, $\SReturn(\langle\ve\rangle)$; - \item evaluating $\ve$ in $\env$ is $\Normal((\vv, \vgone), \newenv)$\ProseOrAbnormal; - \item $\vvs$ is $[\vv]$; - \item $\vgtwo$ is the result of adding a Write Effect for a fresh identifier and the value $\vv$; - \item $\newg$ is the ordered composition of $\vgone$ and $\vgtwo$ with the $\asldata$ edge. -\end{itemize} - -\begin{mathpar} -\inferrule{ - \evalexpr{\env, \ve} \evalarrow \Normal((\vv, \vgone), \newenv) \OrAbnormal\\\\ - \wid \in \Identifiers\text{ is fresh}\\ - \writeidentifier(\wid, \vv) \evalarrow \vgtwo\\ - \newg \eqdef \ordered{\vgone}{\asldata}{\vgtwo} -}{ - \evalstmt{\env, \SReturn(\langle\ve\rangle)} \evalarrow \Returning(([\vv], \newg), \newenv) -} -\end{mathpar} - -\isempty{\subsubsection{Comments}} -\CodeSubsubsection{\SReturnOneBegin}{\EvalSReturnOneEnd}{../Interpreter.ml} - -\subsection{SemanticsRule.SReturnSome \label{sec:SemanticsRule.SReturnSome}} -\subsubsection{Example} -In the specification: -\VerbatimInput{../tests/ASLSemanticsReference.t/SemanticsRule.SReturnSome.asl} -\texttt{return (3, 42);} exits the current subprogram with value \texttt{(3, 42)}. - -\subsubsection{Prose} -All of the following apply: -\begin{itemize} - \item $\vs$ is a \texttt{return} statement for a list of expressions, $\SReturn(\langle\ETuple(\es)\rangle)$; - \item evaluating each expression in $\es$ separately as per \secref{SemanticsRule.EExprListM} - is \\ $\Normal(\ms, \newenv)$\ProseOrAbnormal; - \item writing the list of values in $\vms$ results in $(\vvs, \newg)$. -\end{itemize} - -\newcommand\writefolder[1]{\texttt{write\_folder}(#1)} - -We first define the helper relation -\[ - \writefolder{\overname{(\vals\times\XGraphs)^*}{\vms}} \aslrel (\overname{\vals^*}{\vvs}, \overname{\XGraphs}{\newg}) \enspace, -\] -which concatenates the input values in $\vms$ and generates an execution graph -by composing the graphs in $\vms$ with Write Effects for the respective values. - -\begin{mathpar} - \inferrule[empty]{}{ - \writefolder{\emptylist} \evalarrow (\emptylist, \emptygraph) - } - \and - \inferrule[nonempty]{ - \vms \eqname [\vm] \concat \vmsone\\ - \vm \eqdef (\vv, \vg)\\ - \wid \in \Identifiers\text{ is fresh}\\ - \writeidentifier(\wid, \vv) \evalarrow \vgone\\ - \writefolder{\vmsone, \vgone} \evalarrow (\vvsone, \vgtwo)\\ - \vvs \eqdef [\vv] \concat \vvsone\\ - \newg \eqdef \ordered{\vgone}{\asldata}{\vgtwo} - } - { - \writefolder{\vms} \evalarrow (\vvs, \ordered{\vg}{\aslpo}{\newg}) - } -\end{mathpar} - -We now use the helper relation \texttt{write\_folder} to define the rule for returning a tuple of values: -\begin{mathpar} - \inferrule{ - \evalexprlistm(\env, \es) \evalarrow \Normal(\ms, \newenv) \OrAbnormal\\ - \writefolder{\ms} \evalarrow (\vvs, \newg) - } - { - \evalstmt{\env, \SReturn(\langle\ETuple(\es)\rangle)} \evalarrow \Returning((\vvs, \newg), \newenv) - } -\end{mathpar} - -\isempty{\subsubsection{Comments}} - -\CodeSubsubsection{\SReturnSomeBegin}{\EvalSReturnSomeEnd}{../Interpreter.ml} - -\section{SemanticsRule.SSeq \label{sec:SemanticsRule.SSeq}} -\subsection{Example} -In the specification: -\VerbatimInput{../tests/ASLSemanticsReference.t/SemanticsRule.SSeq.asl} -\texttt{let x = 3; let y = x + 1} evaluates \texttt{let x = 3} then \texttt{let y = x + 1}. - -\subsection{Prose} -All of the following apply: -\begin{itemize} - \item $\vs$ is a \emph{sequencing statement} \texttt{s1; s2}, that is, $\SSeq(\vsone, \vstwo)$; - \item evaluating $\vsone$ in $\env$ is either $\Continuing(\vgone, \envone)$ in which case - the evaluation continues, - or a returning configuration ($\Returning((\vvs, \newg), \newenv)$)\ProseOrAbnormal; - \item evaluating $\vstwo$ in $\envone$ yields a non-abnormal configuration \\ - (either $\Normal$ or $\Continuing$) $C$\ProseOrAbnormal; - \item $\newg$ is the ordered composition of $\vgone$ and the execution graph of $C$ with the - $\aslpo$ edge; - \item $D$ is the configuration $C$ with the execution graph component replaced with $\newg$. -\end{itemize} - -\subsection{Formally} -\begin{mathpar} - \inferrule{ - \evalstmt{\env, \vsone} \evalarrow \Continuing(\vgone, \envone) \terminateas \ReturningConfig,\ThrowingConfig,\ErrorConfig\\ - \evalstmt{\envone, \vstwo} \evalarrow C \OrAbnormal\\ - \newg \eqdef \ordered{\vgone}{\aslpo}{\graphof{C}}\\ - D \eqdef \withgraph{C}{\newg} - } - { - \evalstmt{\env, \SSeq(\vsone, \vstwo)} \evalarrow D - } -\end{mathpar} - -\isempty{\subsection{Comments}} - -\CodeSubsection{\EvalSSeqBegin}{\EvalSSeqEnd}{../Interpreter.ml} - -\section{SemanticsRule.SCall \label{sec:SemanticsRule.SCall}} -% \lrmcomment{This is related to \identd{KCYT}:} -% A procedure invocation statement calls a procedure subprogram using the given -% actual arguments. The subprogram must not have a return type. - -\subsection{Example} -In the specification: -\VerbatimInput{../tests/ASLSemanticsReference.t/SemanticsRule.SCall.asl} -\texttt{Zeros(3)} evaluates to \texttt{'000'}. - -\subsection{Prose} -All of the following apply: -\begin{itemize} - \item $\vs$ is a call statement, $\SCall(\name, \args, \namedargs)$; - \item evaluating the subprogram call as per \chapref{eval_call} is - \\ $\Normal(\newg, \newenv)$\ProseOrAbnormal; - \item the result of the entire evaluation is $\Continuing(\newg, \newenv)$. -\end{itemize} - -\subsection{Formally} -\begin{mathpar} -\inferrule{ - \evalcall{\env, \name, \args, \namedargs} \evalarrow \Normal(\newg, \newenv) \OrAbnormal -}{ - \evalstmt{\env, \overname{\SCall(\name, \args, \namedargs)}{\vs}} \evalarrow \Continuing(\newg, \newenv) -} -\end{mathpar} - -\isempty{\subsection{Comments}} - -\CodeSubsection{\EvalSCallBegin}{\EvalSCallEnd}{../Interpreter.ml} - -\section{SemanticsRule.SCond \label{sec:SemanticsRule.SCond}} -% \subsection{Informally} - -% \lrmcomment{This is related to \identr{TMYS}:} -% Conditional statements select which block to execute by testing condition expressions sequentially until a $\True$ condition is found. - -% \lrmcomment{This is related to \identr{XSSL}:} -% If no $\True$ condition is found and there is an \texttt{else} block, the -% \texttt{else} block is executed. - -% \lrmcomment{This is related to \identr{KZTJ}:} -% If no $\True$ condition is found and there is no \texttt{else} block, no block is executed. - -% \subsection{Examples} -% The specification: -% \VerbatimInput{../tests/ASLSemanticsReference.t/SemanticsRule.SCond.asl} -% does not result in any Assertion Error. - -% The specification: -% \VerbatimInput{../tests/ASLSemanticsReference.t/SemanticsRule.SCond2.asl} - -% The specification: -% \VerbatimInput{../tests/ASLSemanticsReference.t/SemanticsRule.SCond3.asl} - -% The specification: -% \VerbatimInput{../tests/ASLSemanticsReference.t/SemanticsRule.SCond4.asl} - -\subsection{Prose} -All of the following apply: -\begin{itemize} -\item $\vs$ is a condition statement, $\SCond(\ve, \vsone, \vstwo)$; -\item evaluating $\ve$ in $\env$ is $\Normal((\vv, \vgone)$\ProseOrAbnormal; -\item $\vv$ is a native Boolean for $\vb$; -\item the statement $\vsp$ is $\vsone$ is $\vb$ is $\True$ and $\vstwo$ otherwise -(so that $\vsone$ will be evaluated if the condition evaluates to $\True$ and otherwise -$\vstwo$ will be evaluated); -\item evaluating $\vsp$ in $\envone$ as per \chapref{eval_block} is a non-abnormal configuration - (either $\Normal$ or $\Continuing$) $C$\ProseOrAbnormal; -\item $\vg$ is the ordered composition of $\vgone$ and the execution graph of the configuration $C$; -\item $D$ is the configuration $C$ with the execution graph component updated to be $\vg$. -\end{itemize} - -\subsection{Formally} -\begin{mathpar} -\inferrule{ - \evalexpr{\env, \ve} \evalarrow \Normal((\vv, \vgone), \envone) \OrAbnormal\\ - \vv \eqname \nvbool(\vb)\\ - \vsp \eqdef \choice{\vb}{\vsone}{\vstwo}\\ - \evalblock{\envone, \vsp} \evalarrow C \OrAbnormal\\\\ - \vg \eqdef \ordered{\vgone}{\aslctrl}{\graphof{C}}\\ - D \eqdef \withgraph{C}{\vg} -}{ - \evalstmt{\env, \overname{\SCond(\ve, \vsone, \vstwo)}{\vs}} \evalarrow D -} -\end{mathpar} - -\isempty{\subsection{Comments}} - -\CodeSubsection{\EvalSCondBegin}{\EvalSCondEnd}{../Interpreter.ml} - -\section{SemanticsRule.SCase \label{sec:SemanticsRule.SCase}} - -% \subsection{Syntax} - -\subsection{Example} -The specification: -\VerbatimInput{../tests/ASLSemanticsReference.t/SemanticsRule.SCase.asl} -uses the second \texttt{when} clause because \texttt{3} is less than \texttt{42}. - -\subsection{Prose} -Evaluation of the statement $\vs$ in an environment $\env$ is a configuration $C$, -and all of the following apply: -\begin{itemize} - \item $\vs$ is a case statement, $\SCase(\ve, \caselist)$; - \item desugaring $\vs$ gives a statement $\vsone$, which assigns $\ve$ to a fresh variable - and then matches its value against a list of patterns corresponding to $\caselist$ nested conditions. - In particular, this means that the cases are considered in order and only one of them is executed; - \item evaluating $\vsone$ in $\env$ results in the output configuration $C$. -\end{itemize} - -\subsection{Formally} -\hypertarget{def-casetoconds}{} -A case statement is syntactic sugar for a condition ladder where each -of the alternatives is a pattern. -That is, a statement of the form -\texttt{if e1 then s1; else if e2 then s2; else if e3 then s3; ... else pass;} - -We define the relation -\[ - \casetoconds(\expr, (\pattern \times \stmt)^*) \;\bigtimes\; \stmt -\] -which performs this AST-to-AST transformation, effectively desugaring -the case statement. - -\begin{mathpar} - \inferrule[var-empty]{} - { - \casetoconds(\EVar(\vx), \emptylist) \evalarrow \SPass - } - \and - \inferrule[var-non-empty]{ - \casetoconds(\EVar(\vx), \caselist) \evalarrow \caselist' - } - { - \casetoconds(\EVar(\vx), [(\vp, \vs)] \concat \caselist) \evalarrow \\ - \SCond(\EPattern(\EVar(\vx), \vp), \vs, \caselist') - } - \and - \inferrule[non-var]{ - \astlabel(\ve) \neq \EVar\\ - \vy \in \Identifiers \text{ is fresh}\\ - \vardecl \eqname \SDecl(\LDKLet, \LDITyped(\LDIVar(\vy), \TInt(\unconstrained)))\\ - \casetoconds(\EVar(\vy), \caselist) \evalarrow \casecond - } - { - \casetoconds(\ve, \caselist) \evalarrow - \SSeq(\vardecl, \casecond) - } -\end{mathpar} - -We now define the semantics of a case statement in terms of the desugared statement: -\begin{mathpar} - \inferrule{ - \casetoconds(\ve, \caselist) \evalarrow \vsone\\ - \evalstmt{\env, \vsone} \evalarrow C - } - { - \evalstmt{\env, \SCase(\ve, \caselist)} \evalarrow C - } -\end{mathpar} - -\isempty{\subsection{Comments}} - -\CodeSubsection{\EvalSCaseBegin}{\EvalSCaseEnd}{../Interpreter.ml} - -\section{SemanticsRule.SAssert \label{sec:SemanticsRule.SAssert}} - -% \lrmcomment{This is related to \identd{QJYV}:} -% An assertion statement takes an expression that is asserted by the -% specification to be $\True$ when the assertion statement is executed. - -% \lrmcomment{This is related to \identr{WZSL}:} -% If an assertion expression is $\False$ when the assertion statement is -% executed, it is a dynamic error. An implementation may throw an -% implementation-defined exception in this case, but is not required to. - -% \lrmcomment{This is related to \identr{WQRN}:} -% The expression in an assertion statement must be side-effect-free. - -\subsection{Prose} -All of the following apply: -\begin{itemize} - \item $\vs$ is an assertion statement, $\SAssert(\ve)$; - \item one of the following holds: - \begin{itemize} - \item all of the following hold (\textsc{okay}): - \begin{itemize} - \item evaluating $\ve$ in $\env$ is $\Normal((\vv, \newg), \newenv)$\ProseOrAbnormal; - \item $\vv$ is a native Boolean value for $\True$; - \item the resulting configuration is $\Continuing(\newg, \newenv)$. - \end{itemize} - - \item all of the following hold (\textsc{error}): - \begin{itemize} - \item evaluating $\ve$ in $\env$ is $\Normal((\vv, \newg), \newenv)$; - \item $\vv$ is a native Boolean value for $\False$; - \item an AssertionFailed error is returned. - \end{itemize} - \end{itemize} -\end{itemize} - -\subsection{Example} -In the specification: -\VerbatimInput{../tests/ASLSemanticsReference.t/SemanticsRule.SAssertOk.asl} -\texttt{assert (42 != 3);} ensures that \texttt{3} is not equal to \texttt{42}. - -\subsection{Example} -In the specification: -\VerbatimInput{../tests/ASLSemanticsReference.t/SemanticsRule.SAssertNo.asl} -\texttt{assert (42 == 3);} results in an \texttt{AssertionFailed} error. - -\CodeSubsection{\EvalSAssertBegin}{\EvalSAssertEnd}{../Interpreter.ml} - -\subsection{Formally} -\begin{mathpar} - \inferrule[okay]{ - \evalexpr{\env, \ve} \evalarrow \Normal((\vv, \newg), \newenv) \OrAbnormal\\\\ - \vv \eqname \nvbool(\True) - } - { - \evalstmt{\env, \SAssert(\ve)} \evalarrow \Continuing(\newg, \newenv) - } - \and - \inferrule[error]{ - \evalexpr{\env, \ve} \evalarrow \Normal((\vv, \Ignore), \Ignore)\\ - \vv \eqname \nvbool(\False) - } - { - \evalstmt{\env, \SAssert(\ve)} \evalarrow \ErrorVal{AssertionFailed} - } -\end{mathpar} - -\isempty{\subsection{Comments}} - -\section{SemanticsRule.SWhile \label{sec:SemanticsRule.SWhile}} - \subsection{Prose} - Evaluation of the statement $\vs$ in an environment $\env$ is - the output configuration $C$ and all of the following apply: - \begin{itemize} - \item $\vs$ is a \texttt{while} statement, $\SWhile(\ve, \Ignore, \vbody)$; - \item evaluating the loop as per \secref{SemanticsRule.Loop} in an environment $\env$, - with the arguments $\True$ (which conveys that this is a \texttt{while} statement), $\ve$, and $\vbody$ - results in $C$. - \end{itemize} - - \subsection{Example} - The specification: - \VerbatimInput{../tests/ASLSemanticsReference.t/SemanticsRule.SWhile.asl} - prints \texttt{0123}. - - \CodeSubsection{\EvalSWhileBegin}{\EvalSWhileEnd}{../Interpreter.ml} - -\subsection{Formally} -\begin{mathpar} -\inferrule{ - \evalloop{\env, \True, \ve, \vbody} \evalarrow C -}{ - \evalstmt{\env, \overname{\SWhile(\ve, \Ignore, \vbody)}{\vs}} \evalarrow C -} -\end{mathpar} - -\isempty{\subsection{Comments}} - -\section{SemanticsRule.SRepeat \label{sec:SemanticsRule.SRepeat}} -\subsection{Prose} -Evaluation of the statement $\vs$ in an environment $\env$ is -either \\ $\Returning((\vvs, \newg), \newenv)$ or an output configuration $D$ and all of the following apply: -\begin{itemize} -\item $\vs$ is a \texttt{repeat} statement, $\SRepeat(\ve, \vbody, \Ignore)$; -\item evaluating $\vbody$ in $\env$ as per \chapref{eval_block} - yields $\Continuing(\vgone, \envone)$\ProseTerminateAs{\ReturningConfig,\ThrowingConfig,\ErrorConfig}; -\item evaluating the loop as per \secref{SemanticsRule.Loop} in an environment $\envone$, - with the arguments $\False$ (which conveys that this is a \texttt{repeat} statement), $\ve$, and $\vbody$ - results in $C$; -\item $\vgtwo$ is the ordered composition of $\vgone$ and $\vgtwo$ with the $\aslpo$ edge; -\item the output configuration $D$ is the output configuration $C$ with its execution graph - substituted with $\vgtwo$. -\end{itemize} - -\subsection{Example} -The specification: -\VerbatimInput{../tests/ASLSemanticsReference.t/SemanticsRule.SRepeat.asl} -prints -\begin{Verbatim} - 0 - 1 - 2 - 3 -\end{Verbatim} - -\CodeSubsection{\EvalSRepeatBegin}{\EvalSRepeatEnd}{../Interpreter.ml} - -\subsection{Formally} -\begin{mathpar} -\inferrule{ - \evalblock{\env, \vbody} \evalarrow \Continuing(\vgone, \envone) \terminateas \ReturningConfig,\ThrowingConfig,\ErrorConfig\\\\ - \evalloop{\envone, \False, \ve, \vbody} \evalarrow C\\ - \vgtwo \eqdef \ordered{\vgone}{\aslpo}{\graphof{C}}\\ - D \eqdef \withgraph{C}{\vgtwo} -}{ - \evalstmt{\env, \overname{\SRepeat(\ve, \vbody, \Ignore)}{\vs}} \evalarrow D -} -\end{mathpar} - -\isempty{\subsection{Comments}} - -\section{SemanticsRule.SFor \label{sec:SemanticsRule.SFor}} -Evaluating a \texttt{for} statement involves introducing an index variable to the -environment. The type system ensures, via TypingRule.SFor, that the index variable -is not already declared in the scope of the subprogram containing the \texttt{for} -statement. - -\subsection{Prose} -All of the following apply: -\begin{itemize} -\item $\vs$ is a \texttt{for} statement, $\SFor\left\{\begin{array}{rcl} - \Forindexname &:& \vindexname\\ - \Forstarte &:& \vstarte\\ - \fordirection &:& \vdirection\\ - \Forende &:& \vende\\ - \Forbody &:& \vbody\\ - \Forlimit &:& \Ignore -\end{array}\right\}$; -\item evaluating the side-effect-free expression $\veone$ in $\env$ is either -$\Normal(\vvone, \vgone)$\ProseOrError; -\item evaluating the side-effect-free expression $\vetwo$ in $\env$ is either -$\Normal(\vvtwo, \vgtwo)$\ProseOrError; -\item declaring the local identifier $\vindexname$ in $\env$ with value $\vvone$ is $(\vgthree, \envone)$; -\item evaluating the \texttt{for} loop with arguments $(\vindexname, \veone, \dir, \vetwo, \vs)$ in $\envone$, -as per \secref{SemanticsRule.For} is $\Normal(\vgfour, \envtwo)$\ProseOrAbnormal; -\item removing the local $\vindexname$ from $\envtwo$ is $\envthree$; -\item $\newg$ is formed as follows: taking the parallel composition of $\vgone$ and $\vgtwo$, -then taking the ordered composition of the result with the $\asldata$ edge, -and finally taking the ordered composition of the result with the $\aslpo$ edges; -\item $\newenv$ is $\envthree$. -\item the result of the entire evaluation is $\Continuing(\newg, \newenv)$. -\end{itemize} - -\subsection{Example} -The specification: -\VerbatimInput{../tests/ASLSemanticsReference.t/SemanticsRule.SFor.asl} -prints -\begin{Verbatim} - 0 - 1 - 2 - 3 -\end{Verbatim} - - \CodeSubsection{\EvalSForBegin}{\EvalSForEnd}{../Interpreter.ml} - -\subsection{Formally} -Recall that the expressions for the \texttt{for} loop range are side-effect-free, -which is why they are evaluated via the rule for evaluating side-effect-free expressions. -\begin{mathpar} - \inferrule{ - \evalexprsef{\env, \vstarte} \evalarrow \Normal(\vstartv, \vgone) \terminateas \ErrorConfig\\ - \evalexprsef{\env, \vende} \evalarrow \Normal(\vendv, \vgtwo) \terminateas \ErrorConfig\\ - \declarelocalidentifier(\env, \vindexname, \vendv) \evalarrow (\vgthree,\envone)\\ - \evalfor{\envone, \vindexname, \vstartv, \dir, \vendv, \vbody} \evalarrow \Normal(\vgfour, \envtwo) \OrAbnormal\\ - \removelocal(\envtwo, \vindexname) \evalarrow \envthree\\ - \newg \eqdef \ordered{(\vgone \parallelcomp \vgtwo)}{\asldata}{ \ordered{\vgthree}{\aslpo}{\vgfour} }\\ - \newenv \eqdef \envthree - } - { - { - \begin{array}{r} - \evalstmt{\env, - \overname{ - \SFor\left\{\begin{array}{rcl} - \Forindexname &:& \vindexname\\ - \Forstarte &:& \vstarte\\ - \fordirection &:& \vdirection\\ - \Forende &:& \vende\\ - \Forbody &:& \vbody\\ - \Forlimit &:& \Ignore\\ - \end{array}\right\}}{\vs}} \evalarrow \\ \Continuing(\newg, \newenv) - \end{array} - } - } -\end{mathpar} - -\isempty{\subsection{Comments}} - -\section{SemanticsRule.SThrowNone \label{sec:SemanticsRule.SThrowNone}} - \subsection{Prose} - All of the following apply: - \begin{itemize} - \item $\vs$ is a \texttt{throw} statement that does not provide an expression, $\SThrow(\None)$; - \item $\newenv$ is $\env$; - \item $\vex$ is $\None$; - \item $\newg$ is the empty graph; - \item an exception is thrown with $\newenv$. - \end{itemize} - - \subsection{Example} - The specification: - \VerbatimInput{../tests/ASLSemanticsReference.t/SemanticsRule.SThrowNone.asl} - throws a \texttt{MyException} exception. - - \CodeSubsection{\EvalSThrowNoneBegin}{\EvalSThrowNoneEnd}{../Interpreter.ml} - -\subsection{Formally} -\begin{mathpar} - \inferrule{} - { - \evalstmt{\env, \SThrow(\None)} \evalarrow \Throwing((\None, \emptygraph), \env) - } -\end{mathpar} - -\isempty{\subsection{Comments}} - -\section{SemanticsRule.SThrowSomeTyped \label{sec:SemanticsRule.SThrowSomeTyped}} -\subsection{Prose} -All of the following apply: -\begin{itemize} - \item $\vs$ is a \texttt{throw} statement that provides an expression and a type, - $\SThrow(\langle(\ve, \vt)\rangle)$; - \item evaluating $\ve$ in $\env$ is $\Normal((\vv, \vgone), \newenv)$\ProseOrAbnormal; - \item $\name$ is a fresh identifier (which conceptually holds the exception value); - \item $\vgtwo$ is a Write Effect to $\name$; - \item $\newg$ is the ordered composition of $\vgone$ and $\vgtwo$ with the $\asldata$ edge; - \item $\vex$ consists of the exception value $\vv$, the name of the variable holding it --- - $\name$, and the type annotation for the exception --- $\vt$; - \item the result of the entire evaluation is $\Throwing((\vex, \newg), \env)$. -\end{itemize} - -\subsection{Example} -The specification: -\VerbatimInput{../tests/ASLSemanticsReference.t/SemanticsRule.SThrowSomeTyped.asl} -terminates successfully. That is, no dynamic error occurs. - -\CodeSubsection{\EvalSThrowSomeTypedBegin}{\EvalSThrowSomeTypedEnd}{../Interpreter.ml} - -\subsection{Formally} - \begin{mathpar} - \inferrule{ - \evalexpr{\env, \ve} \evalarrow \Normal((\vv, \vgone), \newenv) \OrAbnormal\\ - \name\in\Identifiers \text{ is fresh}\\ - \vgtwo \eqdef \WriteEffect(\name)\\ - \newg \eqdef \ordered{\vgone}{\asldata}{\vgtwo}\\ - \vex \eqdef \langle(\valuereadfrom(\vv, \name),\vt)\rangle - } - { - \evalstmt{\env, \SThrow(\langle(\ve, \vt)\rangle)} \evalarrow - \Throwing((\vex, \newg), \newenv) - } - \end{mathpar} - -\isempty{\subsection{Comments}} - -\section{SemanticsRule.STry \label{sec:SemanticsRule.STry}} - \subsection{Prose} - All of the following apply: - \begin{itemize} - \item $\vs$ is a \texttt{try} statement, $\STry(\vs, \catchers, \otherwiseopt)$; - \item evaluating $\vsone$ in $\env$ as per \chapref{eval_block} - is a non-abnormal (that is, either $\Normal$ or $\Continuing$) configuration $\sm$\ProseOrAbnormal; - \item evaluating $(\catchers, \otherwiseopt, \sm)$ as per \chapref{eval_catchers} - is $C$, which is the result of the entire evaluation. - \end{itemize} - - \subsection{Example} - The specification: - \VerbatimInput{../tests/ASLSemanticsReference.t/SemanticsRule.STry.asl} - does not result in any Assertion error, and the specification terminates with the exit code $0$. - - \CodeSubsection{\EvalSTryBegin}{\EvalSTryEnd}{../Interpreter.ml} - -\subsection{Formally} -\begin{mathpar} - \inferrule{ - \evalblock{\env, \vsone} \evalarrow \sm \OrAbnormal\\ - \evalcatchers{\env, \catchers, \otherwiseopt, \sm} \evalarrow C - } - { - \evalstmt{\env, \STry(\vsone, \catchers, \otherwiseopt)} \evalarrow C - } -\end{mathpar} - -\isempty{\subsection{Comments}} - -\section{SemanticsRule.SDeclSome \label{sec:SemanticsRule.SDeclSome}} - \subsection{Prose} - All of the following apply: - \begin{itemize} - \item $\vs$ is a declaration with an initial value, - $\SDecl(\text{ldk}, \ldi, \langle\ve\rangle)$; - \item evaluating $\ve$ in $\env$ is $\Normal(\vm, \envone)$\ProseOrAbnormal; - \item evaluating the local declaration $\ldi$ with $\langle\vm\rangle$ as the initializing - value in $\envone$ as per \chapref{eval_local_decl} is $\Normal(\newg, \newenv)$; - \item the result of the entire evaluation is $\Continuing(\newg, \newenv)$. - \end{itemize} - -\subsection{Example} -The specification: -\VerbatimInput{../tests/ASLSemanticsReference.t/SemanticsRule.SDeclSome.asl} -\texttt{let x = 3;} binds \texttt{x} to $\nvint(3)$ in the empty environment. - -\CodeSubsection{\EvalSDeclSomeBegin}{\EvalSDeclSomeEnd}{../Interpreter.ml} - -\subsection{Formally} -\begin{mathpar} - \inferrule{ - \evalexpr{\env, \ve} \evalarrow \Normal(\vm, \envone) \OrAbnormal\\ - \evallocaldecl{\envone, \ldi, \langle\vm\rangle} \evalarrow \Normal(\newg, \newenv)\\ - } - { - \evalstmt{\env, \SDecl(\Ignore, \ldi, \langle\ve\rangle)} \evalarrow \Continuing(\newg, \newenv) - } -\end{mathpar} - -\isempty{\subsection{Comments}} - -\section{SemanticsRule.SDeclNone \label{sec:SemanticsRule.SDeclNone}} - \subsection{Prose} - All of the following apply: - \begin{itemize} - \item $\vs$ is a declaration without an initial value, $\SDecl(\Ignore, \ldi, \None)$; - \item evaluating the local declaration $(\ldi, \None)$ as per \chapref{eval_local_decl} - is \\ $\Normal(\newg, \newenv)$; - \item the result of the entire evaluation is $\Continuing(\newg, \newenv)$. - \end{itemize} - - \subsection{Example} - In the specification: - \VerbatimInput{../tests/ASLSemanticsReference.t/SemanticsRule.SDeclNone.asl} - \texttt{var x : integer;} binds \texttt{x} in $\env$ to the base value of \texttt{integer}. - - \CodeSubsection{\EvalSDeclNoneBegin}{\EvalSDeclNoneEnd}{../Interpreter.ml} - -\subsection{Formally} -\begin{mathpar} - \inferrule{ - \evallocaldecl{\env, \vs, \ldi, \None} \evalarrow \Normal(\newg, \newenv)\\ - } - { - \evalstmt{\env, \SDecl(\Ignore, \ldi, \None)} \evalarrow \Continuing(\newg, \newenv) - } -\end{mathpar} - -\isempty{\subsection{Comments}} - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -\chapter{Evaluation of Blocks \label{chap:eval_block}} -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - -The relation -\hypertarget{def-evalblock}{} -\[ - \evalblock{\overname{\envs}{\env} \times \overname{\stmt}{\stm}} \;\aslrel\; - \overname{\TContinuing}{\Continuing(\newg, \newenv)} \cup - \overname{\TReturning}{\ReturningConfig} \cup - \overname{\TThrowing}{\ThrowingConfig} \cup - \overname{\TError}{\ErrorConfig} -\] -evaluates a statement $\stm$ as a \emph{block}. That is, $\stm$ is evaluated in a fresh local environment, -which drops back to the original local environment of $\env$ when the evaluation terminates. - -\section{SemanticsRule.Block \label{sec:SemanticsRule.Block}} - \subsection{Prose} - All of the following apply: - \begin{itemize} - \item $\blockenv$ is the environment $\env$ modified by replacing the local component - (of the inner dynamic environment) by an empty one; - \item evaluating $\stm$ in $\blockenv$, as per \chapref{eval_stmt}, - is \\ $\Continuing(\newg, \blockenvone)$\ProseTerminateAs{\ReturningConfig}; - \item $\newenv$ is formed from $\blockenvone$ after restoring the - variable bindings of $\env$ with the updated values of $\blockenv$. - The effect is that of discarding the bindings for variables declared inside $\stm$; - \item the result of the entire evaluation is $\Continuing(\newg, \newenv)$. - \end{itemize} - - \subsection{Example} - In the specification: - \VerbatimInput{\semanticstests/SemanticsRule.Block.asl} - the conditional statement \texttt{if TRUE then\ldots{} end;} defines a -block structure. Thus, the scope of the declaration \texttt{let y = 2;} is -limited to its declaring block---or the binding for \texttt{y} no longer exists -once the block is exited. As a consequence, the subsequent declaration -\texttt{let y = 1} is valid. By contrast, the assignment of the mutable -variable~\texttt{x} persists after block end. However, observe that \texttt{x} -is defined before the block and hence still exists after the block. - -\CodeSubsection{\EvalBlockBegin}{\EvalBlockEnd}{../Interpreter.ml} - -\subsection{Formally} -\begin{mathpar} -\inferrule{ - \env \eqname (\tenv,\denv)\\ - \blockenv \eqdef (\tenv, (G^\denv, \emptyfunc))\\ - \evalstmt{\blockenv, \stm} \evalarrow \Continuing(\newg, \blockenvone) \terminateas \ReturningConfig,\ThrowingConfig,\ErrorConfig\\\\ - \blockenvone\eqname(\tenv, \denvone)\\ - \newenv \eqdef(\tenv, (G^{\denvone}, \restrictfunc{L^{\denvone}}{{\dom(L^\denv)}})) -}{ - \evalblock{\env, \stm} \evalarrow \Continuing(\newg, \newenv) -} -\end{mathpar} - -That is, evaluating a block discards the bindings for variables declared inside $\stm$. - -\isempty{\subsection{Comments}} - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -\chapter{Evaluation of Loops \label{chap:eval_loops}} -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - -The evaluation of loop is a common part of the evaluation of multiple loop -statements. -% -For example, the semantic rule \emph{Loop} is used by the semantic rule -\emph{SWhile} at \secref{SemanticsRule.SWhile} and the semantic rule -\emph{SRepeat} at \secref{SemanticsRule.SRepeat}. -% -The semantic rule \emph{For} is only used by the semantic rule \emph{SFor} at -\secref{SemanticsRule.SFor}. - -\section{SemanticsRule.Loop \label{sec:SemanticsRule.Loop}} -The relation -\hypertarget{def-evalloop}{} -\[ - \evalloop{\overname{\envs}{\env} \aslsep \overname{\Bool}{\iswhile} \aslsep \overname{\expr}{\econd} \aslsep \overname{\stmt}{\vbody}} - \;\aslrel\; - \left( - \begin{array}{cl} - \Continuing(\overname{\XGraphs}{\newg} \aslsep \overname{\envs}{\newenv}) & \cup \\ - \overname{\TReturning}{\ReturningConfig} & \cup \\ - \overname{\TThrowing}{\ThrowingConfig} & \cup \\ - \overname{\TError}{\ErrorConfig} & - \end{array} - \right) -\] -evaluates $\vbody$ in $\env$ as long as $\econd$ holds when $\iswhile$ is $\True$ -or until $\econd$ holds when $\iswhile$ is $\False$. -The result is either the continuing configuration \\ $\Continuing(\newg,\newenv)$, -an early return configuration, or an abnormal configuration. - -\subsection{Prose} -One of the following applies: -\begin{itemize} -\item all of the following apply (\textsc{exit}): - \begin{itemize} - \item evaluating $\econd$ in $\env$ is $\Normal(\condm, \newenv)$\ProseOrAbnormal; - \item $\condm$ consists of a native Boolean for $\vb$ and an execution graph $\newg$; - \item $\vb$ is not equal to $\iswhile$; - \item the result of the entire evaluation is $\Continuing(\newg, \newenv)$ - and the loop is exited. - \end{itemize} -\item all of the following apply (\textsc{continue}): - \begin{itemize} - \item evaluating $\econd$ in $\env$ is $\Normal(\condm, \envone)$; - \item $\mcond$ consists of a native Boolean for $\vb$ and an execution graph $\vgone$; - \item $\vb$ is equal to $\iswhile$; - \item evaluating $\vbody$ in $\envone$ as per \chapref{eval_block} is either \\ - $\Continuing(\vgtwo, \envtwo)$\ProseTerminateAs{\ReturningConfig, \ThrowingConfig, \ErrorConfig}; - \item evaluating $(\iswhile, \econd, \vbody)$ in $\envtwo$ as a loop is \\ - $\Continuing(\vgthree, \newenv)$\ProseTerminateAs{\ReturningConfig, \ThrowingConfig, \ErrorConfig}; - \item $\newg$ is the ordered composition of $\vgone$ and $\vgtwo$ with the $\aslctrl$ label - and then the ordered composition of the result and $\vgthree$ with the $\aslpo$ edge; - \item the result of the entire evaluation is $\Continuing(\newg, \newenv)$. - \end{itemize} -\end{itemize} - - \subsection{Example} - The specification: - \VerbatimInput{../tests/ASLSemanticsReference.t/SemanticsRule.Loop.asl} - does not result in any Assertion Error and the specification terminates with exit - code $0$. - - \CodeSubsection{\EvalLoopBegin}{\EvalLoopEnd}{../Interpreter.ml} - - \subsection{Formally} -The premise $\vb \neq \iswhile$ is $\True$ in the case of a \texttt{while} loop -and the loop condition $\ve$ not holding, which is exactly when we want the -loop to exit. The opposite holds for a \texttt{repeat} loop. -The negation of the condition is used to decide whether to continue the loop iteration. - -\begin{mathpar} - \inferrule[exit]{ - \evalexpr{\env, \econd} \evalarrow \Normal(\condm, \newenv) \OrAbnormal\\ - \condm \eqname (\nvbool(\vb), \newg)\\ - \vb \neq \iswhile - } - { - \evalloop{\env, \iswhile, \econd, \vbody} \evalarrow \Continuing(\newg, \newenv) - } -\and - \inferrule[continue]{ - \evalexpr{\env, \econd} \evalarrow \Normal(\condm, \envone)\\ - \condm \eqname (\nvbool(\vb), \vgone)\\ - \vb = \iswhile\\ - \evalblock{\envone, \vbody} \evalarrow \Continuing(\vgtwo, \envtwo) \terminateas \ReturningConfig, \ThrowingConfig, \ErrorConfig\\ - \evalloop{\envtwo, \iswhile, \econd, \vbody} \evalarrow \Continuing(\vgthree, \newenv) \terminateas \ReturningConfig, \ThrowingConfig, \ErrorConfig\\ - \newg \eqdef \ordered{\ordered{\vgone}{\aslctrl}{\vgtwo}}{\aslpo}{\vgthree} - } - { - \evalloop{\env, \iswhile, \econd, \vbody} \evalarrow \Continuing(\newg, \newenv) - } -\end{mathpar} - -\isempty{\subsection{Comments}} - -\section{SemanticsRule.For \label{sec:SemanticsRule.For}} -The relation -\hypertarget{def-evalfor}{} -\[ - \evalfor{\overname{\envs}{\env} \aslsep \overname{\Identifiers}{\vindexname} \aslsep \overname{\tint}{\vstart} - \aslsep \overname{\{\UP, \DOWN\}}{\dir} \aslsep \overname{\tint}{\vend} \aslsep \overname{\stmt}{\vbody}} - \;\aslrel\; - \left( - \begin{array}{cl} - \overname{\TReturning}{\ReturningConfig} & \cup\\ - \overname{\TContinuing}{\ContinuingConfig} & \cup\\ - \overname{\TThrowing}{\ThrowingConfig} & \cup \\ - \overname{\TError}{\ErrorConfig} & - \end{array} - \right) -\] -evaluates the \texttt{for} loop with the index variable $\vindexname$ starting from the value -$\vstart$ going in the direction given by $\dir$ until the value given by $\vend$, -executing $\vbody$ on each iteration. -% -The evaluation utilizes two helper relations: $\evalforstep$ and $\evalforloop$. - -The helper relation -\[ - \evalforstep( - \overname{\envs}{\env}, - \overname{\Identifiers}{\vindexname}, - \overname{\tint}{\vstart}, - \overname{\{\UP,\DOWN\}}{\dir}) - \;\aslrel\; - ((\overname{\tint}{\vstep} \times \overname{\envs}{\newenv}) \times \overname{\XGraphs}{\newg}) -\] -either increments or decrements the index variable, -returning the new value of the index variable, the modified environment, -and the resulting execution graph. - -The helper relation -\[ - \evalforloop(\overname{ - \envs}{\env}, - \overname{\Identifiers}{\vindexname}, - \overname{\tint}{\vstart}, - \overname{\{\UP,\DOWN\}}{\dir}, - \overname{\tint}{\vend}, - \overname{\stmt}{\vbody}) \;\aslrel\; - \left( - \begin{array}{cl} - \overname{\TContinuing}{\Continuing(\newg, \newenv)} & \cup\\ - \overname{\TReturning}{\ReturningConfig} & \cup\\ - \overname{\TThrowing}{\ThrowingConfig} & \cup \\ - \overname{\TError}{\ErrorConfig} & - \end{array} - \right) -\] -executes one iteration of the loop body and then uses $\texttt{eval\_for}$ to execute the remaining -iterations. - -\subsection{Prose} -\subsubsection{Stepping the Index Variable} -All of the following apply: -\begin{itemize} - \item $\opfordir$ is either $\PLUS$ when $\dir$ is $\UP$ or $\MINUS$ when $\dir$ is $\DOWN$; - \item reading $\vstart$ into the identifier $\vindexname$ gives $\vgone$; - \item applying the binary operator $\opfordir$ to $\vstart$ and the native integer for $1$ is $\vstep$; - \item the execution graph for writing $\vstep$ into the identifier $\vindexname$ gives $\vgtwo$; - \item updating the local component of the dynamic environment of $\env$ by binding \\ $\vindexname$ to $\vstep$ - gives $\newenv$; - \item $\newg$ is the ordered composition of $\vgone$ and $\vgtwo$ with the $\asldata$ edge. -\end{itemize} - -\subsubsection{Running the Loop Body} -All of the following apply: -\begin{itemize} - \item evaluating $\vbody$ as a block statement (see \chapref{eval_block}) in $\env$ - is \\ $\Continuing(\vgone, \envone)$\ProseTerminateAs{\ReturningConfig, \ThrowingConfig, \ErrorConfig}; - \item stepping the index $\vindexname$ with $\vstart$ and the direction $\dir$ in $\envone$, - that is, $\evalforstep(\envone, \vindexname, \vstart, \dir)$ gives $((\vstep, \envtwo), \vgtwo)$; - \item evaluating the \texttt{for} loop with $(\vindexname, \vstep, \dir, \vend, \vbody)$ - in $\envtwo$ results in a continuing configuration $\Continuing(\vgthree, \newenv)$\ProseTerminateAs{\ReturningConfig, \ThrowingConfig, \ErrorConfig}; - \item $\newg$ is the ordered composition of $\vgone$, $\vgtwo$, and $\vgthree$ with the $\aslpo$ - edge. -\end{itemize} - -\subsubsection{Overall Evaluation} - -Evaluating $(\vindexname, \vstart, \dir, \vend, \vbody)$ in $\env$ is either -a continuing configuration $\Continuing(\newg, \newenv)$ or a returning configuration -(in case the body of the loop results in an early return) -or an abnormal configuration, -and All of the following apply: -\begin{itemize} - \item $\compfordir$ is either $\LT$ when $\dir$ is $\UP$ or $\GT$ when $\dir$ is $\DOWN$; - \item reading $\vstart$ into the identifier $\vindexname$ gives $\vgone$; - \item One of the following applies: - \begin{itemize} - \item All of the following apply (\textsc{return}): - \begin{itemize} - \item using $\compfordir$ to compare $\vend$ to $\vstart$ gives the native Boolean for $\True$; - \item $\newg$ is $\vgone$; - \item $\newenv$ is $\env$; - \item the result of the entire evaluation is $\Continuing(\newg, \newenv)$. - \end{itemize} - \item All of the following apply (\textsc{continue}): - \begin{itemize} - \item using $\compfordir$ to compare $\vend$ to $\vstart$ gives the native Boolean for $\False$; - \item evaluating the loop body via $\evalforloop$ with \\ $(\vindexname, \vstart, \dir, \vend, \vbody)$ - in $\env$ is \\ $\Continuing(\vgtwo, \newenv)$\ProseTerminateAs{\ReturningConfig, \ThrowingConfig, \ErrorConfig}; - \item $\newg$ is the ordered composition of $\vgone$ and $\vgtwo$ with the $\aslctrl$ label. - \end{itemize} - \end{itemize} -\end{itemize} - -\subsection{Example} -The specification: -\VerbatimInput{../tests/ASLSemanticsReference.t/SemanticsRule.For.asl} -does not result in any assertion error, and the specification terminates with exit-code $0$. - -\CodeSubsection{\EvalForBegin}{\EvalForEnd}{../Interpreter.ml} - -\subsection{Formally} - -Advancing the loop counter one step towards the end of its range is achieved via the following rule: -\begin{mathpar} - \inferrule{ - \opfordir \eqdef \choice{\dir = \UP}{\PLUS}{\MINUS}\\ - \readidentifier(\vindexname, \vstart) \evalarrow \vgone\\ - \binoprel(\opfordir, \vstart, \nvint(1)) \evalarrow \vstep\\ - \writeidentifier(\vindex, \vstep) \evalarrow \vgtwo\\ - \env \eqname (\tenv, \denv)\\ - \newenv \eqdef (\tenv, (G^\denv, L^\denv[\vindexname\mapsto\vstep]))\\ - \newg \eqdef \ordered{\vgone}{\asldata}{\vgtwo} - } - { - \evalforstep(\env, \vindexname, \vstart, \dir) \evalarrow ((\vstep, \newenv), \newg) - } -\end{mathpar} - -Running the loop body is achieved via the following rule: -\begin{mathpar} - \inferrule{ - \evalblock{\env, \vbody} \evalarrow \Continuing(\vgone, \envone) \terminateas \ReturningConfig, \ThrowingConfig, \ErrorConfig\\ - \evalforstep(\envone, \vindexname, \vstart, \dir) \evalarrow ((\vstep, \envtwo), \vgtwo)\\ - \evalfor{\envtwo, \vindexname, \vstep, \dir, \vend, \vbody} \evalarrow \Continuing(\vgthree, \newenv) \terminateas \ReturningConfig, \ThrowingConfig, \ErrorConfig\\ - \newg \eqdef \ordered{\ordered{\vgone}{\aslpo}{\vgtwo}}{\aslpo}{\vgthree} - } - { - \evalforloop(\env, \vindexname, \vstart, \dir, \vend, \vbody) \evalarrow \Continuing(\newg, \newenv) - } -\end{mathpar} - -Finally, the rules for evaluating a \texttt{for} loop utilize both $\evalforstep$ -and $\evalforloop$ (the latter in a mutually recursive manner): -\begin{mathpar} - \inferrule[return]{ - \compfordir \eqdef \choice{\dir = \UP}{\LT}{\GT}\\ - \readidentifier(\vindexname, \vstart) \evalarrow \vgone\\ - \binoprel(\compfordir, \vend, \vstart) \evalarrow \nvbool(\True)\\ - \newg \eqdef \vgone\\ - \newenv = \env - } - { - \evalfor{\env, \vindexname, \vstart, \dir, \vend, \vbody} \evalarrow \Continuing(\newg, \newenv) - } - \and - \inferrule[continue]{ - \compfordir \eqdef \choice{\dir = \UP}{\LT}{\GT}\\ - \readidentifier(\vindexname, \vstart) \evalarrow \vgone\\ - \binoprel(\compfordir, \vend, \vstart) \evalarrow \nvint(\False)\\ - \evalforloop(\env, \vindexname, \vstart, \dir, \vend, \vbody) \evalarrow \\ - \Continuing(\vgtwo, \newenv) \terminateas \ReturningConfig, \ThrowingConfig, \ErrorConfig\\\\ - \newg \eqdef \ordered{\vgone}{\aslctrl}{\vgtwo} - } - { - \evalfor{\env, \vindexname, \vstart, \dir, \vend, \vbody} \evalarrow \Continuing(\newg, \newenv) - } -\end{mathpar} - -% Intuitively, a \texttt{for}-loop \texttt{for $i$ = $e_1$ to $e_2$ do $S$} is syntactic sugar for -% \texttt{$i$ = $e_1$; while $i$ < $e_2$ do $S$; $i$=$i$+1 end}. -% Similarly, \texttt{for $i$ = $e_1$ downto $e_2$ do $S$} is syntactic sugar for -% \texttt{$i$ = $e_1$; while $i$ > $e_2$ do $S$; $i$=$i$-1 end}. The important difference between -% the statement involving the \texttt{while} loop and the original \texttt{for} loop is that the -% scope of the counter variable is restricted to the body of the \texttt{for}. Notice that this -% aspect is already handled by the rule for \SFor. - -% To reflect this, we constructs the following two ASTs for each of the cases for the direction of the loop: -% \[ -% \begin{array}{rcl} -% \texttt{Ei} &\triangleq& \EVar(\vindexname)\\ -% \texttt{plus\_one} &\triangleq& \SAssign(\texttt{Ei}, \EBinop(\texttt{"+"}, \texttt{Ei}, \texttt{E\_Lit}(\texttt{L\_Int}(1))))\\ -% \texttt{Up\_for\_body} &\triangleq& \SSeq(\vbody, \texttt{plus\_one})\\ -% \texttt{Up\_cond} &\triangleq& \EBinop(\LT, \texttt{Ei}, \vend)\\ -% \texttt{Up\_for} &\triangleq& \SSeq(\SAssign(\texttt{Ei}, \vstart), \SWhile(\texttt{Up\_cond}, \texttt{Up\_for\_body}))\\ -% \hline -% \texttt{minus\_one} &\triangleq& \SAssign(\texttt{Ei}, \EBinop(\texttt{"-"}, \texttt{Ei}, \texttt{E\_Lit}(\texttt{L\_Int}(1))))\\ -% \texttt{Down\_for\_body} &\triangleq& \SSeq(\vbody, \texttt{minus\_one})\\ -% \texttt{Down\_cond} &\triangleq& \EBinop(\GT, \texttt{Ei}, \vend)\\ -% \texttt{Down\_for} &\triangleq& \SSeq(\SAssign(\texttt{Ei}, \vstart), \SWhile(\texttt{Down\_cond}, \texttt{Down\_for\_body})) -% \end{array} -% \] - -% We now use the (desugared) ASTs to evaluate the statement: -% \begin{mathpar} -% \inferrule{ -% \evalstmt{\env, \texttt{Up\_for}} \evalarrow C -% } -% { -% \evalfor{\env, \vindexname, \vstart, \texttt{Up}, \vend, \vbody} \evalarrow C -% } -% \and -% \inferrule{ -% \evalstmt{\env, \texttt{Down\_for}} \evalarrow C -% } -% { -% \evalfor{\env, \vindexname, \vstart, \texttt{Down}, \vend, \vbody} \evalarrow C -% } -% \end{mathpar} - -\isempty{\subsection{Comments}} - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -\chapter{Evaluation of Catchers \label{chap:eval_catchers}} -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - -The semantic relation for evaluating catchers employs an argument -that is an output configuration. This argument corresponds to the result -of evaluating a \texttt{try} statement and its type is defined as follows: -\hypertarget{def-toutconfig}{} -\[ - \TOutConfig \triangleq \TNormal \cup \TThrowing \cup \TContinuing \cup \TReturning \enspace. -\] - -The relation -\hypertarget{def-evalcatchers}{} -\[ - \evalcatchers{\overname{\envs}{\env} \aslsep \overname{\catcher^*}{\catchers} \aslsep \overname{\langle\stmt\rangle}{\otherwiseopt} - \aslsep \overname{\TOutConfig}{\sm}} \;\aslrel\; - \left( - \begin{array}{cl} - \TReturning & \cup\\ - \TContinuing & \cup\\ - \TThrowing & \cup \\ - \TError & - \end{array} - \right) -\] -evaluates a list of \texttt{catch} clauses $\catchers$, an \texttt{otherwise} clause, -and a configuration $\sm$ resulting from the evaluation of the throwing expression, -in the environment $\env$. The result is either a continuation configuration, -an early return configuration, or an abnormal configuration. - -When the statement in a \texttt{try} block, which we will refer to as the try-block statement, -is evaluated, it may call a function that updates -the global environment. If evaluation of the \texttt{try} block raises an exception that is caught, -either by a \texttt{catch} clause or an \texttt{otherwise} clause, -the statement associated with that clause, which we will refer to as the clause statement, is evaluated. -It is important to evaluate the clause statement in an environment that includes any updates -to the global environment made by evaluating the try-block statement. -% -We demonstrate this with the following example. - -Consider the following specification: -\VerbatimInput{../tests/ASLSemanticsReference.t/EvalCatchers.asl} - -Here, the try-block statement consists of the single statement \texttt{update\_and\_throw();}. -Evaluating the call to \texttt{update\_and\_throw} employs an environment $\env$ where -\texttt{g} is bound to $0$. -Notice that the call to \texttt{update\_and\_throw} binds \texttt{g} to $1$ before raising an exception. -Therefore, evaluating the call to \texttt{update\_and\_throw} returns a configuration -of the form -$\Throwing(\Ignore, \envthrow)$ where $\envthrow$ binds \texttt{g} to $1$. -When the catch clause is evaluated the semantics takes the global environment from $\envthrow$ -to account for the update to \texttt{g} and the local environment from $\env$ to account for the -updates to the local environment in \texttt{main}, which binds \texttt{x} to $2$, and use this -environment to evaluate \texttt{print(x, g)}, resulting in the output \texttt{2 1}. - -One of the following applies: -\begin{itemize} -\item SemanticsRule.Catch (see \secref{SemanticsRule.Catch}), -\item SemanticsRule.CatchNamed (see \secref{SemanticsRule.CatchNamed}), -\item SemanticsRule.CatchOtherwise (see \secref{SemanticsRule.CatchOtherwise}), -\item SemanticsRule.CatchNone (see \secref{SemanticsRule.CatchNone}), -\item SemanticsRule.CatchNoThrow (see \secref{SemanticsRule.CatchNoThrow}). -\end{itemize} - -We also define two helper relations: -\begin{itemize} - \item SemanticsRule.FindCatcher (see \secref{SemanticsRule.FindCatcher}), - \item SemanticsRule.RethrowImplicit (see \secref{SemanticsRule.RethrowImplicit}). -\end{itemize} - -\section{SemanticsRule.Catch \label{sec:SemanticsRule.Catch}} -\subsection{Prose} -All of the following apply: -\begin{itemize} - \item $\sm$ is $\Throwing((\langle \valuereadfrom(\vv, \eid), \vvty \rangle, \sg), \envthrow)$; - \item $\env$ consists of the static environment $\tenv$ and dynamic environment $\denv$; - \item $\envthrow$ consists of the static environment $\tenv$ and dynamic environment \\ $\denvthrow$; - \item $\envone$ is defined by taking the static environment $\tenv$, the global component of the dynamic - environment from $\denvthrow$ and the local component of the dynamic environment from $\denv$; - \item finding the first catcher with the static environment $\tenv$, the exception type $\vvty$, - and the list of catchers $\catchers$ gives a catcher that does not declare a name ($\None$) and gives a statement $\vs$; - \item evaluating $\vs$ in $\envone$ as a block (\chapref{eval_block}) is not an error - configuration $C$\ProseOrError; - \item editing potential implicit throwing configurations via $\rethrowimplicit(\vv, \vvty, C)$ - gives the configuration $D$; - \item $\newg$ is the ordered composition of $\sg$ and the graph of $D$; - \item the result of the entire evaluation is $D$ with its graph substituted with $\newg$. -\end{itemize} - -\subsection{Example} -The specification: -\VerbatimInput{../tests/ASLSemanticsReference.t/SemanticsRule.Catch.asl} -terminates successfully. That is, no dynamic error occurs. - -\CodeSubsection{\EvalCatchBegin}{\EvalCatchEnd}{../Interpreter.ml} - -\subsection{Formally} -\begin{mathpar} -\inferrule{ - \sm \eqname \Throwing((\langle \valuereadfrom(\vv, \eid), \vvty \rangle, \sg), \envthrow)\\ - \env \eqname (\tenv, (G^\denv, L^\denv))\\ - \envthrow \eqname (\tenv, (G^{\denvthrow}, L^{\denvthrow}))\\ - \envone \eqdef (\tenv, (G^{\denvthrow}, L^{\denv}))\\ - \findcatcher(\tenv, \vvty, \catchers) \eqname \langle (\None, \Ignore, \vs) \rangle\\ - \evalblock{\envone, \vs} \evalarrow C \OrDynError\\\\ - D \eqdef \rethrowimplicit(\vv, \vvty, C)\\ - \newg \eqdef \ordered{\sg}{\aslpo}{\graphof{D}} -}{ - \evalcatchers{\env, \catchers, \otherwiseopt, \sm} \evalarrow \withgraph{D}{\newg} -} -\end{mathpar} - -\isempty{\subsection{Comments}} - -\section{SemanticsRule.CatchNamed \label{sec:SemanticsRule.CatchNamed}} - \subsection{Prose} - All of the following apply: - \begin{itemize} - \item $\sm$ is $\Throwing((\langle \valuereadfrom(\vv, \eid), \vvty \rangle, \sg), \envthrow)$; - \item $\env$ consists of the static environment $\tenv$ and dynamic environment $\denv$; - \item $\envthrow$ consists of the static environment $\tenv$ and dynamic environment \\ $\denvthrow$; - \item $\envone$ is defined by taking the static environment $\tenv$, the global component of the dynamic - environment from $\denvthrow$ and the local component of the dynamic environment from $\denv$; - \item finding the first catcher with the static environment $\tenv$, the exception type $\vvty$, - and the list of catchers $\catchers$ gives a catcher that declares the name $\name$ and gives a statement $\vs$; - \item $\vgone$ is the execution graph resulting from reading $\vv$ into the identifier $\eid$; - \item declaring a local identifier $\name$ with $(\veone, \vgone)$ in $\envone$ gives $(\envtwo, \vgtwo)$; - \item evaluating $\vs$ in $\envtwo$ as a block (\chapref{eval_block}) is not an error - configuration $C$\ProseOrError; - \item $\envthree$ is the environment of the configuration $C$; - \item removing the binding for $\name$ from the local component of the dynamic environment in $\envthree$ - gives $\envfour$; - \item substituting the environment of $C$ with $\envfour$ gives $D$; - \item editing potential implicit throwing configurations via $\rethrowimplicit(\vv, \vvty, D)$ - gives the configuration $E$; - \item $\newg$ is the ordered composition of $\sg$, $\vgone$, $\vgtwo$, and the graph of $E$, - with the $\aslpo$ edges; - \item the result of the entire evaluation is $E$ with its graph substituted with $\newg$. - \end{itemize} - - \subsection{Example} - The specification: - \VerbatimInput{../tests/ASLSemanticsReference.t/SemanticsRule.CatchNamed.asl} - prints \texttt{My exception with my message}. - - \CodeSubsection{\EvalCatchNamedBegin}{\EvalCatchNamedEnd}{../Interpreter.ml} - -\subsection{Formally} -\begin{mathpar} - \inferrule{ - \sm \eqname \Throwing((\langle \valuereadfrom(\vv, \eid), \vvty \rangle, \sg), \envthrow)\\ - \env \eqname (\tenv, (G^\denv, L^\denv))\\ - \envthrow \eqname (\tenv, (G^{\denvthrow}, L^{\denvthrow}))\\ - \envone \eqdef (\tenv, (G^{\denvthrow}, L^{\denv}))\\ - \findcatcher(\tenv, \vvty, \catchers) \eqname \langle (\langle\name\rangle, \Ignore, \vs) \rangle\\ - \vgone \eqdef \readidentifier(\eid, \vv)\\ - \declarelocalidentifierm(\envone, \name, (\veone, \vgone)) \evalarrow (\envtwo, \vgtwo)\\ - \evalblock{\envtwo, \vs} \evalarrow C \OrDynError\\\\ - \envthree \eqdef \environof{C}\\ - \removelocal(\envthree, \name) \evalarrow \envfour\\ - D \eqdef \withenviron{C}{\envfour}\\ - E \eqdef \rethrowimplicit(\vv, \vvty, D)\\ - \newg \eqdef \ordered{\sg}{\aslpo}{ \ordered{\ordered{\vgone}{\aslpo}{\vgtwo}}{\aslpo}{\graphof{E}} } - } - { - \evalcatchers{\env, \catchers, \otherwiseopt, \sm} \evalarrow \withgraph{E}{\newg} - } -\end{mathpar} - -\isempty{\subsection{Comments}} - -\section{SemanticsRule.CatchOtherwise \label{sec:SemanticsRule.CatchOtherwise}} - \subsection{Prose} - All of the following apply: - \begin{itemize} - \item $\sm$ is $\Throwing((\langle \valuereadfrom(\vv, \eid), \vvty \rangle, \sg), \envthrow)$; - \item $\env$ consists of the static environment $\tenv$ and dynamic environment $\denv$; - \item $\envthrow$ consists of the static environment $\tenv$ and dynamic environment \\ $\denvthrow$; - \item $\envone$ is defined by taking the static environment $\tenv$, the global component of the dynamic - environment from $\denvthrow$ and the local component of the dynamic environment from $\denv$; - \item finding the first catcher with the static environment $\tenv$, the exception type $\vvty$, - and the list of catchers $\catchers$ gives a catcher that declares the name $\name$ and gives $\None$ - (that is, neither of the \texttt{catch} clauses matches the raised exception); - \item evaluating the \texttt{otherwise} statement $\vs$ in $\envtwo$ as a block (\chapref{eval_block}) - is not an error configuration $C$\ProseOrError; - \item editing potential implicit throwing configurations via $\rethrowimplicit(\vv, \vvty, C)$ - gives the configuration $D$; - \item $\newg$ is the ordered composition of $\sg$ and the graph of $D$, - with the $\aslpo$ edge; - \item the result of the entire evaluation is $D$ with its graph substituted with $\newg$. - \end{itemize} - - \subsection{Example} - The specification: - \VerbatimInput{../tests/ASLSemanticsReference.t/SemanticsRule.CatchOtherwise.asl} - prints \texttt{Otherwise}. - - \CodeSubsection{\EvalCatchOtherwiseBegin}{\EvalCatchOtherwiseEnd}{../Interpreter.ml} - -\subsection{Formally} - \begin{mathpar} - \inferrule{ - \sm \eqname \Throwing((\langle \valuereadfrom(\vv, \eid), \vvty \rangle, \sg), \envthrow)\\ - \env \eqname (\tenv, (G^\denv, L^\denv))\\ - \envthrow \eqname (\tenv, (G^{\denvthrow}, L^{\denvthrow}))\\ - \envone \eqdef (\tenv, (G^{\denvthrow}, L^{\denv}))\\ - \findcatcher(\tenv, \vvty, \catchers) = \None\\ - \evalblock{\envone, \vs} \evalarrow C \OrDynError\\\\ - D \eqdef \rethrowimplicit(\vv, \vvty, C)\\ - \vg \eqdef \ordered{\sg}{\aslpo}{\graphof{D}} - } - { - \evalcatchers{\env, \catchers, \langle\vs\rangle, \sm} \evalarrow \withgraph{D}{\vg} - } -\end{mathpar} - -\isempty{\subsection{Comments}} - -\section{SemanticsRule.CatchNone \label{sec:SemanticsRule.CatchNone}} - \subsection{Prose} - All of the following apply: - \begin{itemize} - \item $\sm$ is $\Throwing((\langle \valuereadfrom(\vv, \eid), \vvty \rangle, \sg), \envthrow)$; - \item $\env$ consists of the static environment $\tenv$ and dynamic environment $\denv$; - \item $\envthrow$ consists of the static environment $\tenv$ and dynamic environment \\ $\denvthrow$; - \item finding the first catcher with the static environment $\tenv$, the exception type $\vvty$, - and the list of catchers $\catchers$ gives a catcher that declares the name $\name$ and gives $\None$ - (that is, neither of the \texttt{catch} clauses matches the raised exception); - \item since there no \texttt{otherwise} clause, the result is $\sm$. - \end{itemize} - - \subsection{Example} - The specification: - \VerbatimInput{../tests/ASLSemanticsReference.t/SemanticsRule.CatchNone.asl} - does not print anything. - - \CodeSubsection{\EvalCatchNoneBegin}{\EvalCatchNoneEnd}{../Interpreter.ml} - -\subsection{Formally} - \begin{mathpar} - \inferrule{ - \sm \eqname \Throwing((\langle \valuereadfrom(\vv, \eid), \vvty \rangle, \sg), \envthrow)\\ - \env \eqname (\tenv, \denv)\\ - \findcatcher(\tenv, \vvty, \catchers) = \None - } - { - \evalcatchers{\env, \catchers, \None, \sm} \evalarrow \sm - } -\end{mathpar} - -\isempty{\subsection{Comments}} - -\section{SemanticsRule.CatchNoThrow \label{sec:SemanticsRule.CatchNoThrow}} - \subsection{Prose} - all of the following apply: - \begin{itemize} - \item One of the following holds: - \begin{itemize} - \item (\textsc{implicit\_throw}) $\sm$ is $\Throwing((\None, \sg), \envthrow)$ (that is, an implicit throw); - \item (\textsc{non\_throwing}) $\sm$ is a normal configuration (that is, the domain of $\sm$ is $\Normal$); - \end{itemize} - \item the result is $\sm$. - \end{itemize} - - \subsection{Example} - The specification: - \VerbatimInput{../tests/ASLSemanticsReference.t/SemanticsRule.CatchNoThrow.asl} - prints \texttt{No exception raised}. - -\CodeSubsection{\EvalCatchNoThrowBegin}{\EvalCatchNoThrowEnd}{../Interpreter.ml} - -\subsection{Formally} - \begin{mathpar} - \inferrule[implicit\_throw]{ - \sm \eqname \Throwing((\None, \sg), \envthrow) - } - { - \evalcatchers{\env, \catchers, \Ignore, \sm} \evalarrow \sm - } - \and - \inferrule[non\_throwing]{ - \configdomain{\sm} = \Normal - } - { - \evalcatchers{\env, \catchers, \Ignore, \sm} \evalarrow \sm - } -\end{mathpar} - -\isempty{\subsection{Comments}} - -\section{SemanticsRule.FindCatcher \label{sec:SemanticsRule.FindCatcher}} - -\hypertarget{def-findcatcher}{} -The (recursively-defined) helper relation -\[ - \findcatcher(\overname{\staticenvs}{\tenv} \aslsep \overname{\ty}{\vvty}, \overname{\catcher^*}{\catchers}) - \;\aslrel\; \langle \catcher \rangle \enspace, -\] -returns the first catcher clause in $\catchers$ that matches the type $\vvty$ (as a singleton set), or an empty set ($\None$), -by invoking $\typesat$ with the static environment $\tenv$. - -\subsection{Prose} -One of the following applies: -\begin{itemize} - \item All of the following apply (\textsc{empty}): - \begin{itemize} - \item $\catchers$ is an empty list; - \item the result is $\None$. - \end{itemize} - - \item All of the following apply (\textsc{match}): - \begin{itemize} - \item $\catchers$ has $\vc$ as its head and $\catchersone$ as its tail; - \item $\vc$ consists of $(\nameopt, \ety, \vs)$; - \item $\vvty$ type-satisfies $\ety$ in the static environment $\tenv$; - \item the result is the singleton set for $\vc$. - \end{itemize} - - \item All of the following apply (\textsc{no\_match}): - \begin{itemize} - \item $\catchers$ has $\vc$ as its head and $\catchersone$ as its tail; - \item $\vc$ consists of $(\nameopt, \ety, \vs)$; - \item $\vvty$ does not type-satisfy $\ety$ in the static environment $\tenv$; - \item the result of finding a catcher for $\vvty$ with the type environment $\tenv$ in the tail list $\catchersone$ - is $d$; - \item the result is $d$. - \end{itemize} -\end{itemize} - -\CodeSubsection{\EvalFindCatcherBegin}{\EvalFindCatcherEnd}{../Interpreter.ml} - -\subsection{Formally} -\begin{mathpar} - \inferrule[empty]{}{\findcatcher(\tenv, \vvty, \emptylist) \evalarrow \None} -\and -\inferrule[match]{ - \catchers \eqname [\vc] \concat \catchersone\\ - \vc \eqname (\nameopt, \ety, \vs) \\ - \typesat(\tenv, \vvty, \ety) -} -{ - \findcatcher(\tenv, \vvty, \catchers) \evalarrow \langle\vc\rangle -} -\and -\inferrule[no\_match]{ - \catchers \eqname [\vc] \concat \catchersone\\ - \vc \eqname (\nameopt, \ety, \vs) \\ - \neg\typesat(\tenv, \vvty, \ety)\\ - d \eqdef \findcatcher(\tenv, \vvty, \catchersone) -} -{ - \findcatcher(\tenv, \vvty, \catchers) \evalarrow d -} -\end{mathpar} - -\subsection{Comments} -\lrmcomment{This is related to \identr{SPNM}:} -When the \texttt{catch} of a \texttt{try} statement is executed, then the -thrown exception is caught by the first catcher in that \texttt{catch} which it -type-satisfies or the \texttt{otherwise\_opt} in that catch if it exists. - -\section{SemanticsRule.RethrowImplicit \label{sec:SemanticsRule.RethrowImplicit}} - -The helper relation -\hypertarget{def-rethrowimplicit}{} -\[ - \rethrowimplicit(\overname{\valuereadfrom(\vals,\Identifiers)}{\vv} \aslsep \overname{\ty}{\vvty} \aslsep \overname{\TOutConfig}{\vres}) \;\aslrel\; \TOutConfig -\] - -changes \emph{implicit throwing configurations} into \emph{explicit throwing configurations}. -That is, configurations of the form $\Throwing((\None, \vg), \envthrowone))$. - -$\rethrowimplicit$ leaves non-throwing configurations, and \emph{explicit throwing configurations}, -which have the form $\Throwing(\langle(\valuereadfrom(\vv', \eid), \vvty')\rangle, \vg)$, as is. -Implicit throwing configurations are changed by substituting the optional $\valuereadfrom$ configuration-exception type -pair with $\vv$ and $\vvty$, respectively. - -\subsection{Prose} -One of the following applies: -\begin{itemize} - \item All of the following apply (\textsc{implicit\_throwing}): - \begin{itemize} - \item $\vres$ is $\Throwing((\None, \vg), \envthrowone)$, which is an implicit throwing configuration; - \item the result is $\Throwing((\langle(\vv, \vvty)\rangle, \vg), \envthrowone)$. - \end{itemize} - - \item All of the following apply (\textsc{explicit\_throwing}): - \begin{itemize} - \item $\vres$ is $\Throwing(\langle(\vv', \vvty')\rangle, \vg)$, which is an explicit throwing configuration - (due to $(\vv', \vvty')$); - \item the result is $\Throwing((\langle(\vv', \vvty')\rangle, \vg), \envthrowone)$. \\ - That is, the same throwing configuration is returned. - \end{itemize} - - \item All of the following apply (\textsc{non\_throwing}): - \begin{itemize} - \item the configuration, $C$, domain is non-throwing; - \item the result is $C$. - \end{itemize} -\end{itemize} - -\CodeSubsection{\EvalRethrowImplicitBegin}{\EvalRethrowImplicitEnd}{../Interpreter.ml} - -\subsection{Formally} -\begin{mathpar} - \inferrule[implicit\_throwing]{} - { - \rethrowimplicit(\vv, \vvty, \Throwing((\None, \vg), \envthrowone)) \evalarrow \\ - \Throwing((\langle(\valuereadfrom(\vv, \eid), \vvty)\rangle, \vg), \envthrowone) - } -\and -\inferrule[explicit\_throwing]{} -{ - \rethrowimplicit(\vv, \vvty, \Throwing((\langle(\vv', \vvty')\rangle, \vg), \envthrowone)) \evalarrow \\ - \Throwing((\langle(\vv', \vvty')\rangle, \vg), \envthrowone) -} -\and -\inferrule[non\_throwing]{ - \configdomain{C} \neq \Throwing -} -{ - \rethrowimplicit(\Ignore, \Ignore, C, \Ignore) \evalarrow C -} -\end{mathpar} - -\subsection{Comments} -\lrmcomment{This is related to \identr{GVKS}:} -An expressionless \texttt{throw} statement causes the exception which the -currently executing catcher caught to be thrown. - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -\chapter{Evaluation of Subprograms \label{chap:eval_call}} -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - -% \section{Informal Preamble} - -% \lrmcomment{This is related to the preamble of Section 8.2:} - -% An ASL specification describes behavior in terms of the execution of a single -% thread of control. Executing a function or procedure may modify global state -% and can result in one of the following situations: -% \begin{itemize} -% \item The function/procedure returns successfully (i.e., without throwing an -% ASL exception or detecting a dynamic error). In this case, the result is a -% possibly modified global state and, for functions, a return value. -% \item The function/procedure throws an ASL exception. In this case, the result -% is a possibly modified global state and an exception object (that could be -% caught by the caller in a try-catch block, if desired). -% \item The function/procedure detects a dynamic error condition. This indicates -% an error in the specification and the global state and any other behavior is -% meaningless. -% \item The function/procedure enters an infinite loop. This indicates an error -% in the specification and the global state and any other behavior is -% meaningless. -% \end{itemize} - -% Note that Arm’s implementation of ASL also supports some builtin functions for -% printing to the console, etc. These internal extensions are not used in Arm’s -% published specifications but could be added to the description of the -% semantics. - -% \subsection{Execution-time subprograms} - -% \lrmcomment{This is related to Section 8.2.1:} - -% \lrmcomment{This is related to \identi{NXJR}:} - -% Subprogram declarations in ASL are either execution-time subprogram -% declarations or non-execution-time subprogram declarations. - -% \lrmcomment{This is related to \identd{CSFT}:} - -% A subprogram declaration is an execution-time declaration if it makes use of -% any of the following: -% \begin{itemize} -% \item an execution-time storage element -% \item an execution-time expression -% \item an execution-time subprogram invocation -% \end{itemize} - -% \lrmcomment{This is related to \identi{HYBT}:} - -% Subprogram invocations are also either execution-time or non-execution-time invocations. - -% \lrmcomment{This is related to \identd{CCTY}:} - -% A subprogram invocation is an execution-time invocation if the invoked -% subprogram has an execution-time declaration or if the invocation contains any -% of the following: -% \begin{itemize} -% \item an execution-time storage element -% \item an execution-time expression -% \item a bitvector whose width is an execution-time expression -% \end{itemize} - -% \lrmcomment{This is related to \identi{LYKD}:} - -% This means that an execution-time subprogram declaration shall only have -% execution-time invocations. - -% \subsection{Compile-time-constant subprograms} - -% \lrmcomment{This is related to \identi{ZPWM}:} - -% Subprogram declarations in ASL are either compile-time-constant subprogram declarations or non-compile-time- constant subprogram declarations. - -% \lrmcomment{This is related to \identd{KCKX}:} - -% A subprogram declaration is a compile-time-constant declaration if all of the following are true: -% \begin{itemize} -% \item the subprogram is side-effect-free -% \item all assignments in the subprogram are to the subprogram’s local -% variables -% \item all expressions in the subprogram are compile-time-constant -% expressions -% \item any subprogram invocations made in the subprogram are -% compile-time-constant subprogram invocations -% \end{itemize} - -% \lrmcomment{This is related to \identi{NTYZ}:} - -% Standard (built-in) functions, as defined in the ASL standard library, are -% generally compile-time-constant, unless otherwise stated. - -% \lrmcomment{This is related to \identi{MSZT}:} - -% Subprogram invocations are also either compile-time-constant subprogram -% invocations or non-compile-time-constant subprogram invocations. - -% \lrmcomment{This is related to \identd{QNHM}:} - -% A subprogram invocation is a compile-time-constant invocation if all the -% following hold: -% \begin{itemize} -% \item the invoked subprogram is a compile-time-constant subprogram -% \item all of the actual arguments are compile-time-constant expressions -% \item all actual arguments which are bitvectors were declared with a constant -% expression width -% \end{itemize} - -% Note: - -% Subprogram declarations or invocations may be both non-compile-time-constant -% and non-execution-time. - -% For example, storage elements declared with config are non-execution-time and -% non-compile-time-constant so any use of them in a function or procedure -% declaration or invocation renders it non-compile-time-constant, but does not -% cause it to be execution-time. - -% Subprogram declarations or invocations may not be both compile-time-constant -% and execution-time since if the conditions for execution-time are met then -% the conditions for compile-time-constant cannot be met, and vice versa. - -% \section{Formal Preamble} - -The relation -\hypertarget{def-evalcall}{} -\[ - \begin{array}{c} - \evalcall{\overname{\envs}{\env} \aslsep - \overbracket{\Identifiers}^{\texttt{name}} \aslsep - \overbracket{\expr^*}^{\texttt{args}} \aslsep - \overbracket{(\overname{\Identifiers}{\id_i}\times\overname{\expr}{\ve_i})^*}^{\texttt{named\_args}}} \;\aslrel\; \\ - \Normal(\overbracket{(\vals\times\XGraphs)^*}^{\vmstwo}, \overname{\envs}{\newenv}) \cup - \overname{\TThrowing}{\ThrowingConfig} \cup \overname{\TError}{\ErrorConfig} - \end{array} -\] -evaluates a call to the subprogram named $\name$ in the environment $\env$, -with the argument expressions -$\args$, and the parameter expressions $\namedargs$. -The evaluation results in either a list of returned values, each one associated -with an execution graph, and a new environment; -or an abnormal configuration. - -The evaluation first evaluates the expressions corresponding to the arguments -and parameters and then passes their values in a resulting configuration -to the helper relation \texttt{eval\_subprogram}. - -The relation -\hypertarget{def-evalsubprogram}{} -\[ - \begin{array}{c} - \evalsubprogram{\overname{\envs}{\env} \aslsep - \overname{\Identifiers}{\name} \aslsep - \overname{(\vals \times \XGraphs)^*}{\actualargs} \aslsep - \overname{(\Identifiers\times\vals)^*}{\params}} \aslrel \\ - \Normal(\overname{(\vals^* \aslsep \XGraphs)}{\vvs}, \overname{\envs}{\newenv}) \cup - \overname{\TThrowing}{\ThrowingConfig} \cup - \overname{\TError}{\ErrorConfig} - \end{array} -\] -evaluates the subprogram named $\name$ in the environment $\env$, with -$\actualargs$ the list of actual arguments, and $\params$ the -list of arguments deduced by type equality. -The result is either a normal configuration or an abnormal configuration. -In the case of a normal configuration, it consists of a list of pairs -with a value and an identifier, and a new environment $\newenv$. -The values represent values returned by the subprogram call and the -identifiers are used in generating execution graph constraints for the -returned values. - -The main subprogram call relation is given by -SemanticsRule.Call (see \secref{SemanticsRule.Call}). -% -The different types of subprogram calls are evaluated via one of the following rules: -\begin{itemize} -\item SemanticsRule.FPrimitive (see \secref{SemanticsRule.FPrimitive}) -\item SemanticsRule.FCall (see \secref{SemanticsRule.FCall}) -\end{itemize} - -We also define the following helper rules: -\begin{itemize} - \item SemanticsRule.ReadValueFrom (see \secref{SemanticsRule.ReadValueFrom}) - \item SemanticsRule.WriteRetVals (see \secref{SemanticsRule.WriteRetVals}) - \item SemanticsRule.AssignArgs (see \secref{SemanticsRule.AssignArgs}) - \item SemanticsRule.AssignNamedArgs (see \secref{SemanticsRule.AssignNamedArgs}) - \item SemanticsRule.MatchFuncRes (see \secref{SemanticsRule.MatchFuncRes}) -\end{itemize} - -\section{SemanticsRule.Call \label{sec:SemanticsRule.Call}} -\subsection{Prose} -All of the following apply: -\begin{itemize} - \item $\namedargs$ is a list of identifier-expression pairs $(\id_i, \ve_i)$, for $i=1..k$; - \item $\names$ is the list of identifiers in $\namedargs$; - \item $\nargsone$ is the list of argument expressions in $\namedargs$; - \item evaluating each expression in $\args$ separately in $\env$ as per \secref{SemanticsRule.EExprListM} - is \\ $\Normal(\vargs, \envone)$\ProseOrAbnormal; - \item evaluating each expression in $\nargs$ separately in $\envone$ as per \secref{SemanticsRule.EExprListM} - is \\ $\Normal(\nargstwo, \envtwo)$\ProseOrAbnormal; - \item $\nargstwo$ is the list of value-execution graph pairs $\vm_i$, for $i=1..k$; - \item $\nargsthree$ is the list of pairs $(\id_i, \vm_i)$, for $i=1..k$ (this is the format needed - for \texttt{eval\_subprogram}); - \item $\envtwo$ consists of the static environment $\tenv$ and the dynamic environment $\denvtwo$; - \item the environment $\envtwo'$ is defined as the environment - consisting of the static environment $\tenv$ and the dynamic environment with the global component - of $\denvtwo$ and an empty local component (intuitively, this is because the called subprogram does not have access - to the local environment of the caller); - \item evaluating the subprogram named $\name$ with arguments $\vvargs$ and parameters $\nargsthree$ in - $\denvtwo'$ is $\Normal(\vms, (\vglobal, \Ignore))$ (that is, we ignore the local environment - of the callee)\ProseOrAbnormal; - \item the list $\vms$ consists of value-identifier pairs $(\vv_j, \rid_j)$, for $i=1..n$; - \item applying the helper relation $\readvaluefrom$ to each $(\vv_j, \rid_j)$ - results in $\vmstwo_j$, for $i=1..n$; - \item $\vmstwo$ is defined as the list of $\vmstwo_j$, for $i=1..n$; - \item $\newenv$ consists of the static environment $\tenv$ and the dynamic environment consisting - of $\vglobal$ as the global component and the local component of $\denvtwo$ (that is, we restore - the local environment to that of the caller and drop the local environment of the callee). - \item the entire evaluation results in $\Normal(\vmstwo, \newenv)$. -\end{itemize} - -\CodeSubsection{\EvalCallBegin}{\EvalCallEnd}{../Interpreter.ml} - -\subsection{Formally} -\begin{mathpar} -\inferrule{ - \namedargs \eqname [i=1..k: (\id_i, \ve_i)]\\ - \names \eqdef [i=1..k: \id_i]\\ - \nargsone \eqdef [i=1..k: \ve_i]\\ - \evalexprlistm(\env, \args) \evalarrow \Normal(\vvargs, \envone)\OrAbnormal\\ - \evalexprlistm(\envone, \nargs1) \evalarrow \Normal(\nargstwo, \envtwo)\OrAbnormal\\ - \nargstwo \eqname [i=1..k: \vm_i]\\ - \nargsthree \eqdef [i=1...k: (\id_i, \vm_i)]\\ - \envtwo \eqname (\tenv, \denvtwo)\\ - \envtwo' \eqdef (\tenv,(G^\denvtwo,\emptyfunc))\\\\ - \evalsubprogram{\envtwo', \name, \vvargs, \nargsthree} \evalarrow \Normal(\vms, (\vglobal, \Ignore)) \OrAbnormal\\\\ - \vms \eqname [j=1..n: (\vv_j, \rid_j)]\\ - j=1..n: \readvaluefrom(\vv_j, \rid_j) \evalarrow \vmstwo_j\\ - \vmstwo \eqdef [j=1..n: \vmstwo_j]\\ - \newenv \eqdef (\tenv, (\vglobal, L^{\denvtwo})) -}{ - \evalcall{\env, \name, \args, \namedargs} \evalarrow \Normal(\vmstwo, \newenv) -} -\end{mathpar} - -\isempty{\subsection{Comments}} - -\section{SemanticsRule.FPrimitive \label{sec:SemanticsRule.FPrimitive}} -\subsection{Prose} -All of the following apply: -\begin{itemize} - \item $\env$ consists of the static environment $\tenv$ and the dynamic environment with $\genv$ as its - global component and an empty local component; - \item finding the function named $\name$ in the static environment $\tenv$ gives a $\func$ AST node - with the body field \SBPrimitive; - \item evaluating the primitive subprogram $\name$ with the actual arguments $\actualargs$ - is $\Normal(\vms, \vgone)$\ProseOrError; - \item writing the returned values $\vms$ as per \secref{SemanticsRule.WriteRetVals} gives $\vvsm$; - \item $\vvsm$ is a pair consisting of the list of values $\vvs$ and execution graph $\vgtwo$; - \item $\newg$ is the ordered composition of $\vgone$ and $\vgtwo$ with the $\asldata$ label; - \item $\newenv$ is the environment with $\tenv$ as its static environment component - and the dynamic environment consisting of $\genv$ as its global component and an empty local component; - \item the result of the entire evaluation is $\Normal((\vvs, \newg), \newenv)$. -\end{itemize} - -\subsection{Example} -In the specification: -\VerbatimInput{../tests/ASLSemanticsReference.t/SemanticsRule.FPrimitive.asl} -\texttt{print ("Hello, world!");} calls the primitive \texttt{print} on the evaluation of \texttt{"Hello, world!"}. - -\CodeSubsection{\EvalFPrimitiveBegin}{\EvalFPrimitiveEnd}{../Interpreter.ml} - -\subsection{Formally} -The following rule utilizes the transition relation -\hypertarget{def-evalprimitive}{} -\[ - \evalprimitive{\overname{\Identifiers}{\name} \aslsep \overname{(\vals\times\XGraphs)^*}{\actualargs}} \bigtimes - \Normal(\overname{(\vals\times\XGraphs)^*}{\vms} \aslsep \overname{\XGraphs}{\vgone}) \cup \overname{\TError}{\ErrorConfig} \enspace, -\] -which parameterizes the ASL semantics and allows evaluating primitive subprograms. -That is, it is not a part of $\evalarrow$ but rather a separate transition relation denoted $\evalprimitivearrow$. - -\begin{mathpar} -\inferrule{ - \env \eqname (\tenv, (\genv, \emptyfunc))\\ - \findfunc(\tenv, \name) = \{ \body = \SBPrimitive \ldots \}\\ - \evalprimitive{\name, \actualargs} \evalprimitivearrow \Normal(\vms, \vgone) \OrDynError\\\\ - \writeretvals(\vms) \evalarrow \vvsm\\ - \vvsm \eqname (\vvs, \vgtwo)\\ - \newg \eqdef \ordered{\vgone}{\asldata}{\vgtwo}\\ - \newenv \eqdef (\tenv, (\genv, \emptyfunc)) -}{ - \evalsubprogram{\env, \name, \actualargs, \params} \evalarrow \Normal((\vvs, \newg), \newenv) -} -\end{mathpar} - -\isempty{\subsection{Comments}} - -\section{SemanticsRule.FCall \label{sec:SemanticsRule.FCall}} -\subsection{Prose} -All of the following apply: -\begin{itemize} - \item $\env$ consists of the static environment $\tenv$ and the dynamic environment with the global - component $\genv$ and an empty local component; - \item finding the function named $\name$ in $\tenv$ gives the AST $\func$ node with body - $\SBASL(\vbody)$ and arguments $\argdecls$; - \item $\envone$ is the environment consisting of the static environment $\tenv$ and the dynamic1 - environment consisting of the dynamic component from $\denv$ and an empty local component; - \item assigning the actual arguments with $((\envone, \emptygraph), \argdecls, \actualargs)$ - as per \secref{SemanticsRule.AssignArgs} gives $(\envtwo, vgtwo)$ make sure that each - formal argument in $\argdecls$ is - locally bound to the corresponding actual argument in $\actualargs$; - \item declaring and assigning the parameter values with $((\envtwo, \vgtwo), \params)$ - as per \secref{SemanticsRule.AssignNamedArgs} gives $(\envthree, \vgthree)$; - \item evaluating the body of the subprogram $\vbody$ as a statement in in $\envthree$ - is $\vres$\ProseOrAbnormal; - \item matching the result $\vres$ to obtain a normal configuration as per \secref{SemanticsRule.MatchFuncRes} - gives $C$; - \item $\newg$ is the ordered composition of $\vgtwo$ and $\vgthree$ with the $\aslpo$ edge; - \item the result is $C$ with its graph substituted for $\newg$. -\end{itemize} - -\subsection{Example} -The specification: -\VerbatimInput{../tests/ASLSemanticsReference.t/SemanticsRule.FCall.asl} -calls the function \texttt{foo} and the procedure \texttt{bar}. - -\CodeSubsection{\EvalFCallBegin}{\EvalFCallEnd}{../Interpreter.ml} - -\subsection{Formally} -\begin{mathpar} -\inferrule{ - \env \eqname (\tenv, \denv)\\ - \findfunc(\tenv, \name) \eqname \{ \body: \SBASL(\vbody), \args: \argdecls, \ldots \}\\ - \envone \eqdef (\tenv, (G^\denv, \emptyfunc))\\ - \assignargs((\envone, \emptygraph), \argdecls, \actualargs) \evalarrow (\envtwo, \vgtwo)\\ - \assignnamedargs((\envtwo, \vgtwo), \params) \evalarrow (\envthree, \vgthree)\\ - \evalstmt{\envthree, \vbody} \evalarrow \vres \OrAbnormal\\ - \matchfuncres(\vres) \evalarrow C\\ - \newg \eqdef \ordered{\vgtwo}{\aslpo}{\vgthree}\\ -}{ - \evalsubprogram{\env, \name, \actualargs, \params} \evalarrow \withgraph{C}{\newg} -} -\end{mathpar} - -\subsection{Comments} -\lrmcomment{This is related to \identr{DFWZ}:} -It is not an error for execution of a procedure or setter to end without a -return statement. - -\section{SemanticsRule.ReadValueFrom \label{sec:SemanticsRule.ReadValueFrom}} -\hypertarget{def-readvaluefrom}{} -The helper relation -\[ - \readvaluefrom(\vals \aslsep \Identifiers) \;\aslrel\; (\vals \times \XGraphs) -\] -generates an execution graph for reading the given value to a variable given -by the identifier, and pairs it with the given value. - -\subsection{Prose} -All of the following apply: -\begin{itemize} - \item reading the value $\vv$ into the variable named $\id$ gives $\newg$; - \item the result is $(\vv, \newg)$. -\end{itemize} - -\CodeSubsection{\EvalReadValueFromBegin}{\EvalReadValueFromEnd}{../Interpreter.ml} - -\subsection{Formally} -\begin{mathpar} -\inferrule{ - \readidentifier(\vv, \id) \evalarrow \newg -}{ - \readvaluefrom(\vv, \id) \evalarrow (\vv, \newg) -} -\end{mathpar} - -\isempty{\subsection{Comments}} - -\section{SemanticsRule.WriteRetVals \label{sec:SemanticsRule.WriteRetVals}} -\hypertarget{def-writeretvals}{} -The relation -\[ - \writeretvals(\overname{(\overname{\overname{\vals}{\vv}\times\overname{\XGraphs}{\vgone}}{\vm})^*}{\vvsm}) \;\aslrel\; - (\overname{\vals^*}{\vvs}\times\overname{\XGraphs}{\newg}) \enspace. -\] -generates Write Effects for the values -returned by the evaluation of a primitive subprogram: - -\subsection{Prose} - one of the following applies: - \begin{itemize} - \item All of the following apply (\textsc{empty}): - \begin{itemize} - \item the list of value-execution graphs $\vvsm$ is empty; - \item the result is a pair consisting of an empty list and an empty graph. - \end{itemize} - - \item All of the following apply (\textsc{non\_empty}): - \begin{itemize} - \item the list of value-execution graphs $\vvsm$ has $\vm$ as its head and $\vvsmone$ as its tail; - \item $\vx$ is a fresh identifier; - \item $\vm$ consists of the value $\vv$ and execution graph $\vgone$; - \item the execution graph $\vgtwo$ is generating by writing the value $\vv$ for the variable named $\vx$; - \item writing the returned values in $\vvsmone$ gives $(\vvsone, \vgthree)$; - \item $\vs$ is defined as the list with $\vv$ as its head and $\vvsone$ as its tail; - \item $\newg$ is defined by first taking the ordered composition of $\vgone$ and $\vgtwo$ with the $\asldata$ edge - and then composing the resulting execution graph in parallel with $\vgthree$; - \item the result of the entire evaluation is $(\vvs, \newg)$. - \end{itemize} -\end{itemize} - -%% Annotating the OCaml code is problematic, since the code for this rule is inside the code -%% for FPrimitive. One option is to factor it out into a separate function. -% -% \CodeSubsection{\EvalWriteRetValsBegin}{\EvalWriteRetValsEnd}{../Interpreter.ml} - -\subsection{Formally} - \begin{mathpar} - \inferrule[empty]{} - { - \writeretvals(\emptylist) \evalarrow (\emptylist, \emptygraph) - } - \and - \inferrule[non\_empty]{ - \vvsm \eqname [\vm] \concat \vvsmone\\ - \vx \in \Identifiers \text{ is fresh}\\ - \vm \eqname (\vv, \vgone)\\ - \writeidentifier(\vx, \vv) \evalarrow \vgtwo\\ - \writeretvals(\vvsmone) \evalarrow (\vvsone, \vgthree)\\ - \vvs \eqdef [\vv] \concat \vvsone\\ - \newg \eqdef (\ordered{\vgone}{\asldata}{\vgtwo}) \parallelcomp \vgthree - } - { - \writeretvals(\vvsm) \evalarrow (\vvs, \newg) - } - \end{mathpar} - -\isempty{\subsection{Comments}} - -\section{SemanticsRule.AssignArgs \label{sec:SemanticsRule.AssignArgs}} -The helper relation -\hypertarget{def-assignargs}{} -\[ - \assignargs((\overname{\envs}{\env}\times\overname{\XGraphs}{\vgone})\aslsep \overname{(\Identifiers\times\ty)^*}{\texttt{arg\_decls}} - \aslsep \overname{(\vals\times\XGraphs)^*} {\texttt{actual\_args}}) \;\aslrel\; - (\overname{\envs}{\newenv} \times \overname{\XGraphs}{\newg}) -\] -assigns the values of (the actual) arguments to the -formal variables of a given subprogram. - -\subsection{Prose} -One of the following applies: -\begin{itemize} - \item All of the following apply (\textsc{empty}): - \begin{itemize} - \item both $\argdecls$ and $\actualargs$ are empty lists; - \item the result is $(\env, \vgone)$. - \end{itemize} - - \item All of the following apply (\textsc{non\_empty}): - \begin{itemize} - \item $\argdecls$ has $(\vx, \Ignore)$ as its head and $\argdecls$ as its tail, - and $\actualargs$ has $\vm$ as its head and $\actualargs$ as its tail; - \item declaring the local identifier $\vx$ with $\vm$ in $\env$ as per \secref{SemanticsRule.DeclareLocalIdentifierMM} - gives \\ $(\envone, \vgtwo)$. - \item assigning the remaining lists $\argdecls$ and $\actualargs$ with the environment $\envone$ and the ordered - composition of $\vgone$ and $\vgtwo$ with the $\aslpo$ edge gives $(\newenv, \newg)$. - \item the entire result of the evaluation is $(\newenv, \newg)$. - \end{itemize} -\end{itemize} - -\subsection{Formally} - \begin{mathpar} - \inferrule[empty]{} - { - \assignargs((\env, \vgone), \emptylist, \emptylist) \evalarrow (\env, \vgone) - } - \and - \inferrule[non\_empty]{ - \declarelocalidentifiermm(\env, \vx, \vm) \evalarrow (\envone, \vgtwo)\\ - \assignargs((\envone, \ordered{\vgone}{\aslpo}{\vgtwo}), \argdecls, \actualargs) \evalarrow (\newenv, \vg) - } - { - \assignargs((\env, \vgone), [(\vx, \Ignore)] \concat \argdecls, [\vm] \concat \actualargs) \evalarrow (\newenv, \vg) - } - \end{mathpar} - -\isempty{\subsection{Comments}} - -\section{SemanticsRule.AssignNamedArgs \label{sec:SemanticsRule.AssignNamedArgs}} -The helper relation -\hypertarget{def-assignnamedargs}{} -\[ - \begin{array}{c} - \assignnamedargs((\overname{\envs}{\env}\times\overname{\XGraphs}{\vgone}) \aslsep - \overname{(\overname{\Identifiers}{\vx}\times\overname{(\vals\times\XGraphs)}{\vm})^*}{\params}) \;\aslrel\; - (\overname{\envs}{\newenv}\times\overname{\XGraphs}{\newg}) - \end{array} -\] -assigns values to the variables that correspond -to the parameters of a given subprogram. - -\subsection{Prose} -One of the following applies: -\begin{itemize} - \item All of the following apply (\textsc{empty}): - \begin{itemize} - \item $\params$ is an empty list; - \item the result is $\env, \vgone$; - \end{itemize} - - \item All of the following apply (\textsc{declared}): - \begin{itemize} - \item $\params$ has $(\vx,\vm)$ as its head and $\paramsone$ as its tail; - \item $\env$ consists of the static environment $\tenv$ and dynamic environment $\denv$; - \item $\vx$ is bound to a value in $\denv$; - \item $\vacc$ is defined as $(\env,\vgone)$; - \item assigning the named args with $\vacc$ and $\paramsone$ gives $(\newenv, \vgtwo)$; - \item $\newg$ is the ordered composition of $\vgone$ and $\vgtwo$ with the $\aslpo$ edge. - \item the result is $(\newenv, \newg)$. - \end{itemize} - - \item All of the following apply (\textsc{not\_declared}): - \begin{itemize} - \item $\params$ has $(\vx,\vm)$ as its head and $\paramsone$ as its tail; - \item $\env$ consists of the static environment $\tenv$ and dynamic environment $\denv$; - \item $\vx$ is not bound to a value in $\denv$; - \item declaring the local identifier $\vx$ with $\vm$ in $\env$, as per \secref{SemanticsRule.DeclareLocalIdentifierM}, - gives $(\envone, \vgtwo)$; - \item $\vacc$ is defined as $(\envone,\vgtwo)$; - \item assigning the named args with $\vacc$ and $\paramsone$ gives $(\newenv, \vgthree)$; - \item $\newg$ is the ordered composition of $\vgone$, $\vgtwo$, and $\vgthree$ with the $\aslpo$ edge. - \item the result is $(\newenv, \newg)$. - \end{itemize} -\end{itemize} - -\subsection{Formally} -\newcommand\isbound[0]{\hyperlink{def-isbound}{\texttt{is\_bound}}} -\hypertarget{def-isbound}{} -We use the helper predicate -\[ -\isbound(\denv, \vx) \triangleq G^\denv(\vx) \neq \bot \vee L^\denv(\vx) \neq \bot -\] -to test whether the variable $\vx$ is bound in the dynamic environment $\denv$. - -\begin{mathpar} - \inferrule[empty]{} - { - \assignnamedargs((\env, \vgone), \emptylist) \evalarrow (\env, \vgone) - } - \and - \inferrule[declared]{ - \params \eqname [(\vx, \vm)] \concat \paramsone\\ - \env \eqname (\tenv, \denv)\\ - \isbound(\denv,\vx)\\ - \vacc \eqdef (\env, \vgone) \\ - \assignnamedargs(\vacc, \paramsone) \evalarrow (\newenv, \vgtwo)\\ - \newg \eqdef \ordered{\vgone}{\aslpo}{\vgtwo} - } - { - \assignnamedargs((\env, \vgone), \params) \evalarrow (\newenv, \newg) - } - \and - \inferrule[not\_declared]{ - \params \eqname [(\vx, \vm)] \concat \paramsone\\ - \env \eqname (\tenv, \denv)\\ - \neg\isbound(\denv,\vx)\\ - \declarelocalidentifierm(\env, \vx, \vm) \evalarrow (\envone, \vgtwo)\\ - \vacc \eqdef (\envone, \vgtwo) \\ - \assignnamedargs(\vacc, \paramsone) \evalarrow (\newenv, \vgthree)\\ - \newg \eqdef \ordered{\ordered{\vgone}{\aslpo}{\vgtwo}}{\aslpo}{\vgthree} - } - { - \assignnamedargs((\env, \vgone), \params) \evalarrow (\newenv, \newg) - } -\end{mathpar} - -\isempty{\subsection{Comments}} - -\section{SemanticsRule.MatchFuncRes \label{sec:SemanticsRule.MatchFuncRes}} -The helper relation -\hypertarget{def-matchfuncres}{} -\[ - \matchfuncres(\TContinuing \cup \TReturning) \;\aslrel\; - \Normal(((\Identifiers\times\vals)^*\times\XGraphs)\aslsep\envs) -\] -converts normal and throwing configurations -into corresponding normal configurations that can be returned by a subprogram evaluation. - -\subsection{Prose} -One of the following applies: -\begin{itemize} - \item All of the following apply (\textsc{continuing}): - \begin{itemize} - \item the given configuration is $\Continuing(\vg, \env)$. This happens when, - for example, the subprogram called is either a setter or a procedure; - \item the result is $\Normal((\emptylist, \vg), \env)$. - \end{itemize} - - \item All of the following apply (\textsc{returning}): - \begin{itemize} - \item the given configuration is $\Returning(\xs, \retenv)$, which is the case of a function; - \item $\xs$ is the list $\vv_i$, for $i=1..k$; - \item define the list of fresh identifiers $\id_i$, for $i=1..k$; - \item define $\vvs$ to be $(\vv_i, \id_i)$, for $i=1..k$; - \item the result is $\Normal((\vvs, \emptygraph), \retenv)$. - \end{itemize} -\end{itemize} - -\subsection{Formally} -\begin{mathpar} - \inferrule[continuing]{} - { - \matchfuncres(\Continuing(\vg, \env)) \evalarrow \Normal((\emptylist, \vg), \env) - } - \and - \inferrule[returning]{ - \xs \eqname [i=1..k: \vv_i]\\ - i=1..k: \id_i \in \Identifiers\text{ is fresh}\\ - \vvs \eqdef [i=1..k: (\vv_i, \id_i)] - } - { - \matchfuncres(\Returning(\xs, \retenv)) \evalarrow \Normal((\vvs, \emptygraph), \retenv) - } -\end{mathpar} - - -\isempty{\subsection{Comments}} - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -\chapter{Evaluation of Specifications \label{chap:eval_spec}} -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -The rule SemanticsRule.TopLevel (see \secref{SemanticsRule.TopLevel}) -evaluates entire specifications with the help of the following rules: -\begin{itemize} - \item SemanticsRule.EvalGlobals (see \secref{SemanticsRule.EvalGlobals}); - \item SemanticsRule.BuildGlobalEnv (see \secref{SemanticsRule.BuildGlobalEnv}). -\end{itemize} - -\section{SemanticsRule.TopLevel \label{sec:SemanticsRule.TopLevel}} -The relation -\hypertarget{def-evalspec}{} -\[ - \evalspec{\overname{\spec}{\parsedast}, \overname{\spec}{\parsedstd}} \;\aslrel\; - ((\overname{\vals}{\vv}\times \overname{\XGraphs}{\vg}) \cup \overname{\TError}{\ErrorConfig}) -\] -evaluates the \texttt{main} function in a given specification and standard library. - -The function $\typecheckast$ (see \secref{TypingRule.TypeCheckAST}) -takes an initial typing environment and a untyped AST and returns a corresponding typed AST and typing -environment. - -\subsection{Prose} - All of the following apply: - \begin{itemize} - \item the AST for the parsed specification, $\parsedspec$, and AST for the parsed standard library, - $\parsedstd$, are concatenated to give $\parsedast$; - \item applying the type-checker to $\parsedast$ with an empty static environment yields - $(\typedspec, \tenv)$; - \item populating the environment with the declarations of the global storage elements - is $(\env, \vgone)$\ProseOrError; - \item One of the following applies: - \begin{itemize} - \item All of the following apply (\textsc{normal}): - \begin{itemize} - \item evaluating the subprogram \texttt{main} with an empty list of actual arguments and empty list of parameters - in $\env$ is $\Normal([(\vv, \vgtwo)], \Ignore)$\ProseOrError; - \item $\newg$ is the ordered composition of $\vgone$ and $\vgtwo$ with the $\aslpo$ edge; - \item the result of the entire evaluation is $(\vv, \newg)$. - \end{itemize} - - \item All of the following apply (\textsc{throwing}): - \begin{itemize} - \item evaluating the subprogram \texttt{main} with an empty list of actual arguments and empty list of parameters - in $\env$ is $\Throwing(\texttt{v\_opt}, \Ignore)$, which is an uncaught exception; - \item the result of the entire evaluation is an error indicating that an exception was not caught. - \end{itemize} - \end{itemize} - \end{itemize} - - \subsection{Example} - - \CodeSubsection{\EvalTopLevelBegin}{\EvalTopLevelEnd}{../Interpreter.ml} - -\subsection{Formally} -\begin{mathpar} -\inferrule[normal]{ - \parsedast \eqdef \parsedspec \concat \parsedstd\\ - \typecheckast(\emptytenv, \parsedast) \typearrow (\typedspec,\tenv)\\ - \buildgenv(\typedspec, (\tenv, (\emptyfunc, \emptyfunc))) \evalarrow (\env, \vgone) \OrDynError\\\\ - \evalsubprogram{\env, \texttt{"main"}, \emptylist, \emptylist} \evalarrow \Normal([(\vv, \vgtwo)], \Ignore) \OrDynError\\\\ - \newg \eqdef \ordered{\vgone}{\aslpo}{\vgtwo} -} -{ - \evalspec{\parsedast, \parsedstd} \evalarrow (\vv, \newg) -} -\end{mathpar} - -\begin{mathpar} -\inferrule[throwing]{ - \parsedast \eqdef \parsedspec \concat \parsedstd\\ - \typecheckast(\emptytenv, \parsedast) \typearrow (\typedspec,\tenv)\\ - \buildgenv(\typedspec, (\tenv, (\emptyfunc, \emptyfunc))) \evalarrow (\env, \vgone)\\ - \evalsubprogram{\env, \texttt{"main"}, \emptylist, \emptylist} \evalarrow \Throwing(\texttt{v\_opt}, \Ignore) -} -{ - \evalspec{\parsedspec, \parsedstd} \evalarrow \ErrorVal{UncaughtException} -} -\end{mathpar} -Notice that when the type-checker fails due to a type error in the given specification, -the corresponding premise in the rule above does not hold, and the semantics -is undefined. Indeed, the ASL semantics is only defined for well-typed specifications. - -\isempty{\subsection{Comments}} - -\section{SemanticsRule.EvalGlobals \label{sec:SemanticsRule.EvalGlobals}} -The relation -\hypertarget{def-evalglobals}{} -\[ - \evalglobals(\overname{\decl^*}{\vdecls}, (\overname{\overname{\envs}{\env} \times \overname{\XGraphs}{\vgone}}{\envm})) - \;\aslrel\; \overname{(\envs \times \XGraphs)}{C} \cup \overname{\TError}{\ErrorConfig} -\] -updates the input environment and execution graph by initializing the global storage declarations, -either from their initializing expression or from the base value defined for their type as per \secref{SemanticsRule.BaseValue}. - -\subsection{Prose} -One of the following applies: -\begin{itemize} - \item All of the following apply (\textsc{empty}): - \begin{itemize} - \item there are no declarations of global variables; - \item the result is $\envm$. - \end{itemize} - - \item All of the following apply (\textsc{with\_initial\_value}): - \begin{itemize} - \item $\vdecls$ has $\vd$ as its head and $\vdecls'$ as its tail; - \item $d$ is the AST node for declaring a global storage element with initial value $\ve$, - name $\name$, and type $\vt$; - \item $\envm$ is the environment-execution graph pair $(\env, \vgone)$; - \item evaluating the side-effect-free expression $\ve$ in $\env$ as per \secref{SemanticsRule.ESideEffectFreeExpr} \\ - is $(\vv, \vgtwo)$\ProseOrError; - \item declaring the global $\name$ with value $\vv$ in $\env$ gives $\envtwo$; - \item evaluating the remaining global declarations $\vdecls'$ with the environment $\envtwo$ and the execution graph - that is the ordered composition of $\vgone$ and $\vgtwo$ with the $\aslpo$ label gives $C$; - \item the result of the entire evaluation is $C$. - \end{itemize} - - \item All of the following apply (\textsc{no\_initial\_value}): - \begin{itemize} - \item $\vdecls$ has $\vd$ as its head and $\vdecls'$ as its tail; - \item $d$ is the AST node for declaring a global storage element with no initial value, - name $\name$, and type $\vt$; - \item $\envm$ is the environment-execution graph pair $(\env, \vgone)$; - \item the base value of type $\vt$ in $\env$ is $(\vv, \vgtwo)$\ProseOrError; - \item declaring the global $\name$ with value $\vv$ in $\env$ gives $\envtwo$; - \item evaluating the remaining global declarations $\vdecls'$ with the environment $\envtwo$ and the execution graph - that is the ordered composition of $\vgone$ and $\vgtwo$ with the $\aslpo$ label gives $C$; - \item the result of the entire evaluation is $C$. - \end{itemize} -\end{itemize} -\subsection{Example} - -% \CodeSubsection{\EvalEvalGlobalsBegin}{\EvalEvalGlobalsEnd}{../Interpreter.ml} - -\subsection{Formally} -\begin{mathpar} - \inferrule[empty]{ - \vdecls \eqname \emptylist - } - { - \evalglobals(\vdecls, \envm) \evalarrow \envm - } - \and - \inferrule[with\_initial\_value]{ - \vdecls \eqname [\vd] \concat \vdecls'\\ - \vd \eqname \texttt{D\_GlobalStorage}(\{ \text{initial\_value}=\langle\ve\rangle, \text{name}:\name, \text{ty}:\vt, \ldots \})\\ - \envm \eqname (\env, \vgone)\\ - \evalexprsef{\env, \ve} \evalarrow (\vv, \vgtwo) \OrDynError\\\\ - \declareglobal(\name, \vv, \env) \evalarrow \envtwo\\ - \evalglobals(\vdecls', (\envtwo, \ordered{\vgone}{\aslpo}{ \vgtwo })) \evalarrow C - } - { - \evalglobals(\vdecls, \envm) \evalarrow C - } - \and - \inferrule[no\_initial\_value]{ - \vdecls \eqname [\vd] \concat \vdecls'\\ - \vd \eqname \texttt{D\_GlobalStorage}(\{ \text{initial\_value}:\None, \text{name}:\name, \text{ty}:\vt, \ldots \})\\ - \envm \eqname (\env, \vgone)\\ - \basevalue(\env, \vt) \evalarrow (\vv, \vgtwo) \OrDynError\\\\ - \declareglobal(\name, \vv, \env) \evalarrow \envtwo\\ - \evalglobals(\vdecls', (\envtwo, \ordered{\vgone}{\aslpo}{ \vgtwo })) \evalarrow C - } - { - \evalglobals(\vdecls, \envm) \evalarrow C - } -\end{mathpar} - -\isempty{\subsection{Comments}} - -\section{SemanticsRule.BuildGlobalEnv \label{sec:SemanticsRule.BuildGlobalEnv}} -The helper relation -\hypertarget{def-buildgenv}{} -\[ - \buildgenv(\overname{\envs}{\env}, \overname{\spec}{\typedspec}) \;\aslrel\; - (\overname{\envs}{\newenv}\times\overname{\XGraphs}{\newg}) \cup \overname{\TError}{\ErrorConfig} -\] -populates the environment and output execution graph with the global -storage declarations. -This works by traversing the global storage declarations in \emph{dependency order} -and updating the environment accordingly. By dependency order, we mean that if -a declaration $b$ refers to an identifier declared in $a$ then $a$ is evaluated -before $b$. - -\subsection{Prose} -All of the following apply: -\begin{itemize} - \item sorting the declarations of the global storage elements in topological order with respect to the dependency order - gives $\vdecls$; - \item evaluating the global storage declarations in $\vdecls$ in $\env$ with the empty execution graph - is $(\newenv, \newg)$\ProseOrError. - \item the result of the entire evaluation is $(\newenv, \newg)$. -\end{itemize} -\subsection{Example} - -\CodeSubsection{\EvalBuildGlobalEnvBegin}{\EvalBuildGlobalEnvEnd}{../Interpreter.ml} - -\subsection{Formally} -\hypertarget{def-topologicaldecls}{} -The helper relation $\topologicaldecls(\overname{\decl^*}{\parsedspec}, \overname{\decl^*}{\parsedstd})$ -accepts a specification and returns the subset of global storage declarations ordered by -dependency order. - -\begin{mathpar} - \inferrule{ - \topologicaldecls(\typedspec) \evalarrow \vdecls\\ - \evalglobals(\vdecls, (\env, \emptygraph)) \evalarrow (\newenv, \newg) \OrDynError - } - { - \buildgenv(\env, \typedspec) \evalarrow (\newenv, \newg) - } -\end{mathpar} - -\isempty{\subsection{Comments}} - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -\chapter{Basic Utility Relations \label{chap:utility}} -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - -In this chapter, we define helper relations for operating on \nativevalues, -environments, and operations involving values and types. -% -In this chapter rules are presented without examples and the corresponding code. - -We now define the following relations: -\begin{itemize} - \item SemanticsRule.RemoveLocal \secref{SemanticsRule.RemoveLocal}; - \item SemanticsRule.ReadIdentifier \secref{SemanticsRule.ReadIdentifier}; - \item SemanticsRule.WriteIdentifier \secref{SemanticsRule.WriteIdentifier}; - \item SemanticsRule.CreateBitvector \secref{SemanticsRule.CreateBitvector}; - \item SemanticsRule.ConcatBitvectors \secref{SemanticsRule.ConcatBitvectors}; - \item SemanticsRule.ReadFromBitvector \secref{SemanticsRule.ReadFromBitvector}; - \item SemanticsRule.WriteToBitvector \secref{SemanticsRule.WriteToBitvector}; - \item SemanticsRule.GetIndex \secref{SemanticsRule.GetIndex}; - \item SemanticsRule.SetIndex \secref{SemanticsRule.SetIndex}; - \item SemanticsRule.GetField \secref{SemanticsRule.GetField}; - \item SemanticsRule.SetField \secref{SemanticsRule.SetField}; - \item SemanticsRule.DeclareLocalIdentifier \secref{SemanticsRule.DeclareLocalIdentifier}; - \item SemanticsRule.DeclareLocalIdentifierM\secref{SemanticsRule.DeclareLocalIdentifierM}; - \item SemanticsRule.DeclareLocalIdentifierMM \secref{SemanticsRule.DeclareLocalIdentifierMM}; - \item SemanticsRule.DeclareGlobal \secref{SemanticsRule.DeclareGlobal}; - \item SemanticsRule.BaseValue \secref{SemanticsRule.BaseValue}; -\end{itemize} - -\section{SemanticsRule.RemoveLocal \label{sec:SemanticsRule.RemoveLocal}} -\subsection{Prose} -The relation -\hypertarget{def-removelocal}{} -\[ - \removelocal(\overname{\envs}{\env} \aslsep \overname{\Identifiers}{\name}) \;\aslrel\; \overname{\envs}{\newenv} -\] -removes the binding of the identifier $\name$ from the local storage of the environment $\env$. - -Removal of the identifier $\name$ from the local storage of the environment $\env$ -is the environment $\newenv$ and all of the following apply: -\begin{itemize} - \item $\env$ consists of the static environment $\tenv$ and dynamic environment $\denv$; - \item $\newenv$ consists of the static environment $\tenv$ and the dynamic environment - with the same global component as $\denv$ --- $G^\denv$, and local component $L^\denv$, - with the identifier $\name$ removed from its domain. -\end{itemize} - -\subsection{Formally} -(Recall that $[\name\mapsto\bot]$ means that $\name$ is not in the domain of the resulting function.) -\begin{mathpar} - \inferrule{ - \env \eqname (\tenv, (G^\denv, L^\denv))\\ - \newenv \eqdef (\tenv, (G^\denv, L^\denv[\name \mapsto \bot])) - } - { - \removelocal(\env, \name) \evalarrow \newenv - } -\end{mathpar} - -\section{SemanticsRule.ReadIdentifier \label{sec:SemanticsRule.ReadIdentifier}} -\subsection{Prose} -The relation -\hypertarget{def-readidentifier}{} -\[ - \readidentifier(\overname{\Identifiers}{\name}\aslsep\overname{\vals}{\vv}) \;\aslrel\; (\overname{\vals}{\vv} \times \XGraphs) -\] -reads a value $\vv$ into a storage element given by an identifier $\name$. -The result is the value and an execution graph containing a single Read Effect, -which denoting reading from $\name$. - -\subsection{Formally} -\begin{mathpar} - \inferrule{} - { - \readidentifier(\name, \vv) \evalarrow (\vv, \ReadEffect(\name)) - } -\end{mathpar} - -\section{SemanticsRule.WriteIdentifier \label{sec:SemanticsRule.WriteIdentifier}} -\subsection{Prose} -The relation -\hypertarget{def-writeidentifier}{} -\[ - \writeidentifier(\overname{\Identifiers}{\name}\aslsep\overname{\vals}{\vv}) \;\aslrel\; \XGraphs -\] -writes the value $\vv$ into a storage element given by an identifier $\name$. -The result is an execution graph containing a single Write Effect, -which denotes writing into $\name$. - -\subsection{Formally} -\begin{mathpar} - \inferrule{} - { - \writeidentifier(\name, \vv) \evalarrow \WriteEffect(\name) - } -\end{mathpar} - -\section{SemanticsRule.CreateBitvector \label{sec:SemanticsRule.CreateBitvector}} -\subsection{Prose} -The relation -\[ - \createbitvector(\overname{\vals^*}{\vvs}) \;\aslrel\; \tbitvector -\] -creates a native vector value bitvector from a sequence of values $\vvs$. - -\subsection{Formally} -\begin{mathpar} - \inferrule{} - { - \createbitvector(\vvs) \evalarrow \nvbitvector{\vvs} - } -\end{mathpar} - -\section{SemanticsRule.ConcatBitvectors \label{sec:SemanticsRule.ConcatBitvectors}} -\subsection{Prose} -The relation -\[ - \concatbitvectors(\overname{\tbitvector^*}{\vvs}) \;\aslrel\; \tbitvector -\] -transforms a (possibly empty) list of bitvector \nativevalues\ $\vvs$ into a single bitvector. - -\subsection{Formally} -\begin{mathpar} - \inferrule[ConcatBitvector.Empty]{} - { - \concatbitvectors(\emptylist) \evalarrow \nvbitvector(\emptylist) - } - \and - \inferrule[ConcatBitvector.NonEmpty]{ - \vvs \eqname [\vv] \concat \vvs'\\ - \vv\eqname\nvbitvector(\bv)\\ - \concatbitvectors(\vvs') \evalarrow \nvbitvector(\bv')\\ - \vres \eqdef \bv \concat \bv' - } - { - \concatbitvectors(\vvs) \evalarrow \nvbitvector(\vres) - } -\end{mathpar} - -\section{SemanticsRule.ReadFromBitvector \label{sec:SemanticsRule.ReadFromBitvector}} -\hypertarget{def-readfrombitvector}{} -The relation -\[ - \readfrombitvector(\overname{\tbitvector}{\bv} \aslsep \overname{(\tint\times\tint)^*}{\slices}) \;\aslrel\; - \overname{\tbitvector}{\vv} \cup \overname{\TError}{\ErrorConfig} -\] -reads from a bitvector $\bv$, or an integer seen as a bitvector, the indices specified by the list of slices $\slices$, -thereby concatenating their values. - -\subsection{Prose} -One of the following applies: -\begin{itemize} - \item all indices are in range for $\bv$ and the returned bitvector consists of the concatenated bits specified - by the slices. - \item there exists an out-of-range index and an error is returned. -\end{itemize} - -\subsection{Formally} -We start by introducing a few helper relations. - -\hypertarget{def-positioninrange}{} -The predicate $\positioninrange(\vs, \vl, n)$ checks whether the indices starting at index $\vs$ and -up to $\vs + \vl$, inclusive, would refer to actual indices of a bitvector of length $n$: -\[ - \positioninrange(\vs, \vl, \vn) \triangleq (\vs \geq 0) \land (\vl \geq 0) \land (\vs + \vl < \vn) \enspace. -\] - -The relation -\hypertarget{def-slicestopositions}{} -\[ - \slicestopositions(\overname{\N}{\vn} \aslsep \overname{(\overname{\tint}{\vs_i}\times\overname{\tint}{\vl_i})^+}{\slices}) \;\aslrel\; - (\overname{\N^*}{\positions} \cup\ \TError) -\] -returns the list of positions (indices) specified by the slices $\slices$, -unless an index would be out of range for a bitvector of length $\vn$, in which case it returns an error configuration. - -\begin{mathpar} - \inferrule[SlicesToPositionsOutOfRange]{ - \slices \eqname [i=1..k: (\nvint(\vs_i), \nvint(\vl_i))]\\ - j \in 1..k: \neg\positioninrange(\vs_j, \vl_j, \vn) - } - { - \slicestopositions(\vn, \slices) \evalarrow \ErrorVal{Slice\_PositionOutOfRange} - } - \and - \inferrule[SlicesToPositionsInRange]{ - \slices \eqname [i=1..k: (\nvint(\vs_i), \nvint(\vl_i))]\\ - i=1..k: \positioninrange(\vs_i, \vl_i, \vn)\\ - \positions \eqdef [\vs_1,\ldots,\vs_1+\vl_1] \concat \ldots \concat [\vs_k,\ldots,\vs_k+\vl_k]\\ - } - { - \slicestopositions(\vn, \slices) \evalarrow \positions - } -\end{mathpar} - -\hypertarget{def-asbitvector}{} -The function $\asbitvector : (\tbitvector\cup\tint) \rightarrow \{0,1\}^*$ transforms \nativevalue\ integers and \nativevalue\ bitvectors into -a sequence of binary values: -\begin{mathpar} - \inferrule[AsBitvectorBitvector]{} - { - \asbitvector(\nvbitvector(\bv)) \evalarrow \bv - } - \and - \inferrule[AsBitvectorInt]{ - \bv \eqdef \text{ two's complement representation of }n - } - { - \asbitvector(\nvint(n)) \evalarrow \bv - } -\end{mathpar} - -Finally, the rules below distinguish between empty bitvectors and non-empty bitvectors. -\begin{mathpar} - \inferrule[ReadFromBitvector.Empty]{} - { - \readfrombitvector(\bv, \emptylist) \evalarrow \nvbitvector(\emptylist) - } - \and - \inferrule[ReadFromBitvector.NonEmpty]{ - \asbitvector(\bv) \eqdef \vb_n \ldots \vb_1\\ - \slicestopositions(n, \slices) \evalarrow [j_{1..m}] \OrDynError\\\\ - \vv \eqdef \nvbitvector(\vb_{j_m + 1}\ldots\vb_{j_1 + 1}) - } - { - \readfrombitvector(\bv, \slices) \evalarrow \vv - } -\end{mathpar} -Notice that the bits of a bitvector go from the least significant bit being on the right to the most significant bit being on the left, -which is reflected by how the rules list the bits. -The effect of placing the bits in sequence is that of concatenating the results -from all of the given slices. -Also notice that bitvector bits are numbered from 1 and onwards, which is why we add 1 to the indices specified -by the slices when accessing a bit. - -\section{SemanticsRule.WriteToBitvector \label{sec:SemanticsRule.WriteToBitvector}} -\subsection{Prose} -The relation -\[ - \writetobitvector(\overname{(\tint\times\tint)^*}{\slices} \aslsep \overname{\tbitvector}{\src} \aslsep \overname{\tbitvector}{\dst}) - \;\bigtimes\; \overname{\tbitvector}{\vv} \cup \overname{\TError}{\ErrorConfig} -\] -overwrites the bits of $\dst$ at the positions given by $\slices$ with the bits of $\src$ -and one of the following applies: -\begin{itemize} - \item all positions specified by $\slices$ are within range for $\dst$ and the modified version - of $\dst$ with the bits of $\src$ at the specified positions is returned; - \item there exists a position in $\slices$ that is not in range for $\dst$ and an error is returned. -\end{itemize} - -\subsection{Formally} -\begin{mathpar} - \inferrule[WriteToBitvector.Empty]{} - { - \writetobitvector(\emptylist, \nvbitvector(\emptylist), \nvbitvector(\emptylist)) \evalarrow \nvbitvector(\emptylist) - } - \and - \inferrule[WriteToBitvector.NonEmpty]{ - \vs_n \ldots \vs_1 \eqdef \asbitvector(\src)\\ - \vd_n \ldots \vd_1 \eqdef \asbitvector(\dst)\\ - \slicestopositions(n, \slices) \evalarrow \positions \OrDynError\\\\ - {\mathit{bit} = \lambda i \in 1..n.\left\{ \begin{array}{ll} - \vs_i & i \in \positions\\ - \vd_i & \text{otherwise} - \end{array} \right.}\\ - \vv\eqdef\nvbitvector(\mathit{bit}(n-1)\ldots \mathit{bit}(0))\\ - } - { - \writetobitvector(\slices, \src, \dst) \evalarrow \vv - } -\end{mathpar} - -\section{SemanticsRule.GetIndex \label{sec:SemanticsRule.GetIndex}} -\subsection{Prose} -The relation -\hypertarget{def-getindex}{} -\[ - \getindex(\overname{\N}{\vi} \aslsep \overname{\tvector}{\vvec}) \;\aslrel\; \overname{\tvector}{\vv_{\vi}} -\] -reads the value $\vv_i$ from the vector of values $\vvec$ at the index $\vi$. - -\subsection{Formally} -\begin{mathpar} - \inferrule{ - \vvec \eqname \vv_{0..k}\\ - \vi \leq k\\ - } - { - \getindex(\vi, \vvec) \evalarrow \vv_{\vi} - } -\end{mathpar} -Notice that there is no rule to handle the case where the index is out of range --- -this is guaranteed by the type-checker not to happen. Specifically, -\begin{itemize} - \item \texttt{TypingRule.EGetArray} ensures that an index is within the bounds of the array - being accessed via a check that the type of the index satisfies the type of the array size. - \item Typing rules \texttt{TypingRule.LEDestructuring}, \texttt{TypingRule.PTuple}, - and \\ \texttt{TypingRule.LDTuple} use the same index sequences for the tuples - involved and the corresponding lists of expressions. -\end{itemize} -If the rules listed above do not hold the type checker fails. - -\section{SemanticsRule.SetIndex \label{sec:SemanticsRule.SetIndex}} -\subsection{Prose} -The relation -\hypertarget{def-setindex}{} -\[ - \setindex(\overname{\N}{\vi} \aslsep \overname{\vals}{\vv} \aslsep \overname{\tvector}{\vvec}) \;\aslrel\; \overname{\tvector}{\vres} -\] -overwrites the value at the given index $\vi$ in a vector of values $\vvec$ with the new value $\vv$. - -\subsection{Formally} -\begin{mathpar} - \inferrule{ - \vvec \eqname \vu_{0..k}\\ - \vi \leq k\\ - \vres \eqname \vw_{0..k}\\ - \vv \eqdef \vw_{\vi} \\ - j \in \{0..k\} \setminus \{\vi\}.\ \vw_{j} = \vu_j\\ - } - { - \setindex(\vi, \vv, \vvec) \evalarrow \vres - } -\end{mathpar} -Similar to $\getindex$, there is no need to handle the out-of-range index case. - -\section{SemanticsRule.GetField \label{sec:SemanticsRule.GetField}} -\subsection{Prose} -The relation -\hypertarget{def-getfield}{} -\[ - \getfield(\overname{\Identifiers}{\name} \aslsep \overname{\trecord}{\record}) \;\aslrel\; \vals -\] -retrieves the value corresponding to the field name $\name$ from the record value $\record$. - -\subsection{Formally} -\begin{mathpar} - \inferrule{ - \record \eqname \nvrecord{\fieldmap} - } - { - \getfield(\name, \record) \evalarrow \fieldmap(\name) - } -\end{mathpar} -The type-checker ensures, via TypingRule.EGetRecordField, that the field $\name$ exists in $\record$. - -\section{SemanticsRule.SetField \label{sec:SemanticsRule.SetField}} -\subsection{Prose} -The relation -\hypertarget{def-setfield}{} -\[ - \setfield(\overname{\Identifiers}{\name} \aslsep \overname{\vals}{\vv} \aslsep \overname{\trecord}{\record}) \;\aslrel\; \trecord -\] -overwrites the value corresponding to the field name $\name$ in the record value $\record$ with the value $\vv$. - -\subsection{Formally} -\begin{mathpar} - \inferrule{ - \record \eqname \nvrecord{\fieldmap}\\ - \fieldmap' \eqdef \fieldmap[\name\mapsto\vv] - } - { - \setfield(\name, \vv, \record) \evalarrow \nvrecord{\fieldmap'} - } -\end{mathpar} -The type-checker ensures that the field $\name$ exists in $\record$. - -\section{SemanticsRule.DeclareLocalIdentifier \label{sec:SemanticsRule.DeclareLocalIdentifier}} -\subsection{Prose} -The relation -\hypertarget{def-declarelocalidentifier}{} -\[ - \declarelocalidentifier(\overname{\envs}{\env} \aslsep \overname{\Identifiers}{\name} \aslsep \overname{\vals}{\vv}) \;\aslrel\; - (\overname{\envs}{\newenv}\times\overname{\XGraphs}{\vg}) -\] -associates $\vv$ to $\name$ as a local storage element in the environment $\env$ and -returns the updated environment $\newenv$ with the execution graph consisting of a Write Effect to $\name$. - -\subsection{Formally} -\begin{mathpar} - \inferrule{ - \vg \eqdef \WriteEffect(\name)\\ - \env \eqname (\tenv, (G^\denv, L^\denv))\\ - \newenv \eqdef (\tenv, (G^\denv, L^\denv[\name\mapsto \vv])) - } - { \declarelocalidentifier(\env, \name, \vv) \evalarrow (\newenv, \vg) } -\end{mathpar} - -\section{SemanticsRule.DeclareLocalIdentifierM \label{sec:SemanticsRule.DeclareLocalIdentifierM}} -\subsection{Prose} -\hypertarget{def-declarelocalidentifierm}{} -The relation -\[ - \declarelocalidentifierm(\overname{\envs}{\env} \aslsep - \overname{\Identifiers}{\vx} \aslsep - \overname{(\overname{\vals}{\vv}\times\overname{\XGraphs}{\vg})}{\vm}) \;\aslrel\; - (\overname{\envs}{\newenv} \times \overname{\XGraphs}{\newg}) -\] -declares the local identifier $\vx$ in the environment $\env$, in the context -of the value-graph pair $(\vv, \vg)$, and all of the following apply: -\begin{itemize} - \item \newenv\ is the environment $\env$ modified to declare the variable $\vx$ as a local storage element; - \item $\vgone$ is the execution graph resulting from the declaration of $\vx$; - \item $\vgtwo$ is the execution graph resulting from the ordered composition of $\vg$ and $\vgone$ - with the $\asldata$ edge. -\end{itemize} - -\subsection{Formally} -\begin{mathpar} - \inferrule{ - \vm \eqname (\vv, \vg)\\ - \declarelocalidentifier(\env, \vx, \vv) \evalarrow (\newenv, \vgone)\\ - \newg \eqdef \ordered{\vg}{\asldata}{\vgone} - } - { - \declarelocalidentifierm(\env, \vx, \vm) \evalarrow (\newenv, \newg) - } -\end{mathpar} - -\section{SemanticsRule.DeclareLocalIdentifierMM \label{sec:SemanticsRule.DeclareLocalIdentifierMM}} -\subsection{Prose} -\hypertarget{def-declarelocalidentifermm}{} -The relation -\[ - \declarelocalidentifiermm(\overname{\envs}{\env} \aslsep - \overname{\Identifiers}{\vx} \aslsep - \overname{(\overname{\vals}{\vv}\times\overname{\XGraphs}{\vg})}{\vm}) \;\aslrel\; - (\overname{\envs}{\newenv} \times \overname{\XGraphs}{\vgtwo}) -\] -declares the local identifier $\vx$ in the environment $\env$, -in the context of the value-graph pair $(\vv, \vg)$, -and all of the following apply: -\begin{itemize} - \item \newenv\ is the environment $\env$ modified to declare the variable $\vx$ as a local storage element; - \item $\vgone$ is the execution graph resulting from the declaration of $\vx$; - \item $\vgtwo$ is the execution graph resulting from the ordered composition of $\vg$ and $\vgone$ - with the $\aslpo$ edge. -\end{itemize} - -\subsection{Formally} -\begin{mathpar} - \inferrule{ - \declarelocalidentifierm(\env, \vm) \evalarrow (\newenv, \vgone)\\ - \vgtwo \eqdef \ordered{\vg}{\aslpo}{\vgone} - } - { - \declarelocalidentifiermm(\env, \vx, \vm) \evalarrow (\newenv, \vgtwo) - } -\end{mathpar} - -\section{SemanticsRule.DeclareGlobal \label{sec:SemanticsRule.DeclareGlobal}} -\subsection{Prose} -The relation -\hypertarget{def-declareglobal}{} -\[ - \declareglobal(\overname{\Identifiers}{\name} \aslsep \overname{\vals}{\vv} \aslsep \overname{\envs}{\env}) \;\aslrel\; \overname{\envs}{\newenv} -\] -updates the environment $\env$ by mapping $\name$ to $\vv$ as a global storage element. - -\subsection{Formally} -\begin{mathpar} - \inferrule{ - \env \eqname (\tenv, (G^\denv, L^\denv))\\ - \newenv \eqdef (\tenv, (G^\denv[\name\mapsto \vv], L^\denv)) - } - { \declareglobal(\name, \vv, \env) \evalarrow \newenv } -\end{mathpar} - -\section{SemanticsRule.BaseValue \label{sec:SemanticsRule.BaseValue}} -The relation -\hypertarget{def-basevalue}{} -\[ - \basevalue(\overname{(\overname{\staticenvs}{\tenv} \times \overname{\dynamicenvs}{\denv})}{\env} \aslsep \overname{\ty}{\vt}) \;\aslrel\; - (\overname{\vals}{\vv} \times \overname{\XGraphs}{\vg}) \cup \overname{\TError}{\ErrorConfig} -\] -returns the \emph{base value} of a type. -The result is an error configuration if a dynamic error is detected. - -\hypertarget{def-tstruct}{} -\paragraph{Type Structure} To obtain the base value of a type, we first obtain its \emph{structure}, using the function -\[ - \tstruct(\overname{\staticenvs}{\tenv} \aslsep \overname{\ty}{\tty}) \aslto \overname{\ty}{\vt} \cup \overname{\TTypeError}{\TypeErrorConfig} -\] -\hypertarget{def-typeerrorconfig}{} -where $\TypeErrorConfig$ stands for a type error. - -The structure of a type is the type that can hold the same set of values, but does not itself -contain any other type names. -This is essentially done by recursively replacing type names by their definition -(see \secref{TypingRule.structure}). -% -Since we assume the specification is well-typed (\secref{MeaningfulASLSpecifications}), -$\tstruct$ returns a valid type. - -\subsection{Prose} -The base value of the type $\vt$ in the environment $\env$ is $\vv$, -as well as the execution graph $\vg$ that results -from evaluating any of the side-effect-free expressions appearing in $\vt$, -or an error, and one of the following applies: -\begin{itemize} - \item all of the following apply (\textsc{boolean}): - \begin{itemize} - \item the structure of $\vt$ is the Boolean type; - \item $\vv$ is the native Boolean "true" value; - \item $\vg$ is the empty graph. - \end{itemize} - - \item all of the following apply (\textsc{real}): - \begin{itemize} - \item the structure of $\vt$ is the real type; - \item $\vv$ is the native real value $0$; - \item $\vg$ is the empty graph. - \end{itemize} - - \item all of the following apply (\textsc{string}): - \begin{itemize} - \item the structure of $\vt$ is the string type; - \item $\vv$ is the \nativevalue\ for the empty string; - \item $\vg$ is the empty graph. - \end{itemize} - - \item all of the following apply (\textsc{bitvector}): - \begin{itemize} - \item the structure of $\vt$ is the bitvector with the length expression $\ve$;; - \item evaluating the side-effect-free expression $\ve$ results in the \nativevalue\ $\length$ - and execution graph $\vg$\ProseOrError; - \item $\vv$ is the bitvector of length $\length$ where all bits are $0$. - \end{itemize} - - \item all of the following apply (\textsc{enum}): - \begin{itemize} - \item the structure of $\vt$ is the enumeration type where the first identifier is $\id_1$; - \item $\vl$ is the literal associated with $\id_1$ in the static environment; - \item $\vv$ is the \nativevalue\ literal for $\vl$; - \item $\vg$ is the empty graph. - \end{itemize} - - \item all of the following apply (\textsc{unconstrained\_integer}): - \begin{itemize} - \item the structure of $\vt$ is that of the unconstrained integer; - \item $\vv$ is the \nativevalue\ integer $0$; - \item $\vg$ is the empty graph. - \end{itemize} - - \item all of the following apply (\textsc{well\_constrained\_integer}): - \begin{itemize} - \item the structure of $\vt$ is that of the well-constrained integer where the first constraint - is exact with the expression $\ve$; - \item $(\vv, \vg)$ is the result of evaluating the side-effect-free expression $\ve$. - \end{itemize} - - \item all of the following apply (\textsc{record}): - \begin{itemize} - \item the structure of $\vt$ is that of a record or an exception; - \item the base value of each field is obtained, and if any of the base values results in an error - then the entire rule short-circuits with that error; - \item $\vv$ is the \nativevalue\ record where each identifier in the record is mapped to its - respective base value; - \item $\vg$ is the parallel composition of the graphs resulting from the base value evaluation - of all the fields. - \end{itemize} - - \item all of the following apply (\textsc{tuple}): - \begin{itemize} - \item the structure of $\vt$ is that of a tuple of types; - \item the base value of each type in the tuple is obtained, and if any of the base values results in an error - then the entire rule short-circuits with that error; - \item $\vv$ is the \nativevalue\ vector consisting of the base values in the order of the corresponding types - of the tuple; - \item $\vg$ is the parallel composition of the graphs resulting from the base value evaluation - of all the tuple types. - \end{itemize} - - \item all of the following apply (\textsc{array\_length\_global\_constant}): - \begin{itemize} - \item the structure of $\vt$ is that of an array with length expression $\elength$ and element type $\vvty$; - \item $\elength$ is the value of a declared constant; - \item $\elength$ is a variable expression with the variable name $\vx$; - \item the constant value for $\vx$ in the static environment is the literal integer for $n$; - \item the base value of $\vvty$ in $\env$ is $(\velem, \vg)$\ProseOrError; - \item $\vv$ is the \nativevalue\ vector of length $n$ where each element is $\velem$; - \end{itemize} - - \item all of the following apply (\textsc{array\_length\_expression}): - \begin{itemize} - \item the structure of $\vt$ is that of an array with length expression $\elength$ and element type $\vvty$; - \item $\elength$ is not the value of a declared constant; - \item the base value of $\vvty$ in $\env$ is $(\velem, \vg)$\ProseOrError; - \item evaluating the side-effect-free expression $\elength$ in the environment $\env$ - results in $(\vlength, \vgtwo)$\ProseOrError; - \item $\vlength$ is the \nativevalue\ integer for $n$; - \item $\vv$ is the \nativevalue\ vector of length $n$ where each element is $\velem$; - \item $\vg$ is the ordered composition of $\vgone$ and $\vgtwo$ with the $\asldata$ edge. - \end{itemize} -\end{itemize} - -\subsection{Formally} -Evaluating the inner expressions of the type $\vt$ is done via the relation\\ -$\evalexprsef$~\ref{sec:SemanticsRule.ESideEffectFreeExpr}. -If evaluating an inner expression results in an error, there is no base value and an error configuration is returned. - -\begin{mathpar} -\inferrule[bool]{ - \tstruct(\tenv, \vt) \typearrow \TBool -}{ - \basevalue((\tenv, \denv), \vt) \evalarrow (\overname{\nvbool(\True)}{\vv}, \overname{\emptygraph}{\vg}) -} -\and -\inferrule[real]{ - \tstruct(\tenv, \vt) \typearrow \TReal -}{ - \basevalue((\tenv, \denv), \vt) \evalarrow (\overname{\nvreal(0)}{\vv}, \overname{\emptygraph}{\vg}) -} -\and -\inferrule[string]{ - \tstruct(\tenv, \vt) \typearrow \TString -}{ - \basevalue((\tenv, \denv), \vt) \evalarrow (\overname{\nvliteral{\lstring(\emptylist)}}{\vv}, \overname{\emptygraph}{\vg}) -} -\end{mathpar} - -The base value of a bitvector is a bitvector \nativevalue\ consisting of a sequence of zeros -of the length specified by the type (\ve). If the length is $0$, the bitvector consists of an -empty sequence: -\begin{mathpar} -\inferrule[bitvector]{ - \env \eqname (\tenv, \denv)\\ - \tstruct(\tenv, \vt) \typearrow \TBits(\ve, \Ignore)\\ - \evalexprsef{\env, \ve} \evalarrow (\nvint(\length), \vg) \OrDynError -}{ - \basevalue(\env, \vt) \evalarrow (\overname{\nvbitvector(\overbrace{0\ldots 0}^{\length})}{\vv}, \vg) -} -\end{mathpar} - -\hypertarget{def-constantvalues}{} -The base value of an enumeration is obtained from its first declared literal. -Accessing this literal is done via the \constantvalues map in the -global component of the static environment: -\begin{mathpar} -\inferrule[enum]{ - \tstruct(\vt) \typearrow \TEnum(\id_{1..k})\\ - \env \eqname (\tenv, \denv)\\ - \tenv \eqname (G^\tenv, L^\tenv)\\ - G^\tenv.\constantvalues(\id_1) \eqname \vl -}{ - \basevalue(\env, \vt) \evalarrow (\overname{\nvliteral{\vl}}{\vv}, \overname{\emptygraph}{\vg}) -} -\end{mathpar} - -\begin{mathpar} -\inferrule[integer\_unconstrained]{ - \tstruct(\tenv, \vt) \typearrow \TInt(\unconstrained) -}{ - \basevalue((\tenv, \denv), \vt) \evalarrow (\overname{\nvint(0)}{\vv}, \overname{\emptygraph}{\vg}) -} -\and -\inferrule[integer\_constraint\_exact]{ - \env \eqname (\tenv, \denv)\\ - \tstruct(\tenv, \vt) \typearrow \TInt(\wellconstrained([\constraintexact(\ve)] \concat \Ignore))\\ - \evalexprsef{\env, \ve} \evalarrow C -}{ - \basevalue(\env, \vt) \evalarrow C -} -\and -\and -\inferrule[integer\_constraint\_range]{ - \env \eqname (\tenv, \denv)\\ - \tstruct(\tenv, \vt) \typearrow \TInt(\wellconstrained([\constraintrange(\ve, \Ignore)] \concat \Ignore))\\ - \evalexprsef{\env, \ve} \evalarrow C -}{ - \basevalue(\env, \vt) \evalarrow C -} -\end{mathpar} - -\begin{mathpar} -\inferrule[record]{ - \env \eqname (\tenv, \denv)\\ - \tstruct(\tenv, \vt) \typearrow L([i=1..k: (\id_i, \vt_i)])\\ - L \in \{\TRecord, \TException\}\\ - i=1..k: \basevalue(\env, \vt_i) \evalarrow (\vv_i, \vg_i) \OrDynError -}{ - \basevalue(\env, \vt) \evalarrow - (\overname{\nvrecord{\{i=1..k: \id_i\mapsto \vv_i\}}}{\vv}, \overname{\vg_1 \parallelcomp \ldots \parallelcomp \vg_k}{\vg}) -} -\end{mathpar} - -\begin{mathpar} -\inferrule[tuple]{ - \env \eqname (\tenv, \denv)\\ - \tstruct(\tenv, \vt) \typearrow \TTuple([i=1..k: \vt_i])\\ - i=1..k: \basevalue(\env, \vt_i) \evalarrow (\vv_i, \vg_i) \OrDynError -}{ - \basevalue(\env, \vt) \evalarrow (\overname{\nvvector{\vv_{1..k}}}{\vv}, \overname{\vg_1 \parallelcomp \ldots \parallelcomp \vg_k}{\vg}) -} -\end{mathpar} - -\newcommand\isconstant[0]{\hyperlink{def-isconstant}{\texttt{is\_contant}}} -\hypertarget{def-isconstant}{} -The predicate $\isconstant$ checks whether the expression $\ve$ is a variable -declared as a constant. -\begin{mathpar} -\inferrule[NotEVar]{ - \env \eqname (\tenv, \denv)\\ - \tenv \eqname (G^\tenv, L^\tenv)\\ - \astlabel(\ve) \neq \EVar -}{ - \isconstant(\env, \ve) \rightarrow \False -} -\and -\inferrule[EVar]{ - \env \eqname (\tenv, \denv)\\ - \tenv \eqname (G^\tenv, L^\tenv)\\ - \astlabel(\ve) = \EVar\\ - \ve\eqname\EVar(\vx)\\ - \vb \eqdef G^\tenv.\constantvalues(\vx) \neq \bot -}{ - \isconstant(\env, \ve) \rightarrow \vb -} -\end{mathpar} - -\begin{mathpar} -\inferrule[array\_length\_global\_constant]{ - \env \eqname (\tenv, \denv)\\ - \tstruct(\tenv, \vt) \typearrow \TArray(\elength, \vvty)\\ - \basevalue(\env, \vvty) \evalarrow (\velem, \vg) \OrDynError\\\\ - \isconstant(\env, \elength) \rightarrow \True\\ - \elength \eqname \EVar(\vx)\\ - \env \eqname (\tenv, \denv)\\ - \tenv \eqname (G^\tenv, L^\tenv)\\ - G^\tenv.\constantvalues(\vx) \eqname \lint(n) -}{ - \basevalue(\env, \vt) \evalarrow (\overname{\nvvector{i=1..n: \velem}}{\vv}, \vg) -} -\and -\inferrule[array\_length\_expression]{ - \env \eqname (\tenv, \denv)\\ - \tstruct(\tenv, \vt) \typearrow \TArray(\elength, \vvty)\\ - \basevalue(\env, \vvty) \evalarrow (\velem, \vgone) \OrDynError\\\\ - \isconstant(\elength) \rightarrow \False\\ - \evalexprsef{\env, \elength} \evalarrow (\vlength, \vgtwo) \OrDynError\\\\ - \vlength \eqname \nvint(n) -}{ - \basevalue(\env, \vt) \evalarrow (\overname{\nvvector{i=1..n: \velem}}{\vv}, \overname{\ordered{\vgone}{\asldata}{\vgtwo}}{\vg}) -} -\end{mathpar} - -\section{SemanticsRule.IsValOfType} -\subsection{Prose} -\hypertarget{def-isvaloftype}{} -The relation -\[ - \isvaloftype(\overname{\envs}{\env} \aslsep \overname{\vals}{\vv} \aslsep \overname{\ty}{\vt}) \;\aslrel\; - (\overname{\Bool}{\vb} \times \overname{\XGraphs}{\vg}) \cup \overname{\TError}{\ErrorConfig} -\] -checks whether the value $\vv$ can be stored in a variable of type $\vt$ in the environment $\env$, -resulting in a Boolean value $\vb$ and execution graph $\vg$ or a dynamic error. - -This relation is used in the context of a asserted type conversion, -which means the type-checker rule TypingRule.ATC was already applied, -thus filtering cases where the type inferred for the converted expression -does not type-satisfy $\vt$. The semantics takes this into account and -only returns \False\ in cases where dynamic information is required. - -One of the following applies: -\begin{itemize} - \item All of the following apply (\textsc{basic}): - \begin{itemize} - \item $\vt$ has the structure of a Boolean, a real, a string, or an enumeration; - \item $\vb$ is \True; - \item $\vg$ is the empty graph. - \end{itemize} - - \item All of the following apply (\textsc{int\_unconstrained}): - \begin{itemize} - \item $\vt$ has the structure of the unconstrained integer; - \item $\vb$ is \True; - \item $\vg$ is the empty graph. - \end{itemize} - - \item All of the following apply (\textsc{int\_wellconstrained}): - \begin{itemize} - \item $\vt$ has the structure of a well-constrained integer with constraints $\vc_{1..k}$; - \item $\vv$ is the \nativevalue\ integer for $n$; - \item the evaluation of every constraint $\vc_i$ with $n$ in environment $\env$ - yields a Boolean value $\vb_i$ and an execution graph $\vg_i$\ProseOrError; - \item $\vb$ is the Boolean disjunction of all Boolean values $\vb_i$, for $i=1..k$; - \item $\vg$ is the parallel composition of all execution graphs $\vg_i$, for $i=1..k$; - \end{itemize} - - \item All of the following apply (\textsc{record}): - \begin{itemize} - \item $\vt$ has the structure of a record or an exception, with a list of field names - $\id_i$, for $i=1..k$, associated with types $\vt_i$, for $i=1..k$; - \item the value of every field $\id_i$ in $\vv$ is $\vu_i$, for $i=1..k$, - \item the evaluation of $\isvaloftype$ for every value $\vu_i$ - and corresponding type $\vt_i$, for $i=1..k$, - results in a Boolean $\vb_i$ and execution graph $\vg_i$\ProseOrError; - \item $\vb$ is the Boolean conjunction of all Boolean values $\vb_i$, for $i=1..k$; - \item $\vg$ is the parallel composition of all execution graphs $\vg_i$, for $i=1..k$; - of the constraints. - \end{itemize} - - \item All of the following apply (\textsc{tuple}): - \begin{itemize} - \item $\vt$ has the structure of a tuple with types $\vt_i$, for $i=1..k$; - \item the value at every index $i=1..k$ of $\vv$ is $\vu_i$, for $i=1..k$, - \item the evaluation of $\isvaloftype$ for every value $\vu_i$ - and corresponding type $\vt_i$, for $i=1..k$, - results in a Boolean $\vb_i$ and execution graph $\vg_i$\ProseOrError; - \item $\vb$ is the Boolean conjunction of all Boolean values $\vb_i$, for $i=1..k$; - \item $\vg$ is the parallel composition of all execution graphs $\vg_i$, for $i=1..k$; - of the constraints. - \end{itemize} - - \item All of the following apply (\textsc{array}): - \begin{itemize} - \item $\vt$ has the structure of an array with length expression $\vt$ - and element type $\vtone$; - \item evaluating the side-effect-free expression $\ve$ in environment $\env$ - results in the \nativevalue\ integer for $k$ and execution graph $\vg$; - \item obtaining the values at indices $i=1..k$ from $\vv$ result in $\vv_i$; - \item evaluating $\isvaloftype$ for $\vv_i$ and $\vtone$, for $i=1..k$, - all result in Boolean values $\vb_i$ and execution graphs $\vg_i$\ProseOrError; - \item $\vb$ is the Boolean conjunction of all Boolean values $\vb_i$, for $i=1..k$; - \item $\vg$ is the parallel composition of all execution graphs $\vg_i$, for $i=1..k$; - of the constraints. - \end{itemize} -\end{itemize} - -% \CodeSubsection{\EvalValOfTypeBegin}{\EvalValOfTypeEnd}{../Interpreter.ml} - -\hypertarget{def-astlabel}{} -\subsection{Formally} -\begin{mathpar} -\inferrule[Basic (bool, real, string, enum)]{ - \astlabel(\tstruct(\env, \vt)) \in \{\TBool, \TReal, \TString, \TEnum\}\\ - \vg \eqdef \emptygraph -}{ - \isvaloftype(\env, \vv, \vt) \evalarrow (\True, \vg) -} -\end{mathpar} - -\begin{mathpar} -\inferrule[int\_unconstrained]{ - \tstruct(\env, \vt) \eqname \TInt(\unconstrained)\\ - \vg \eqdef \emptygraph -}{ - \isvaloftype(\env, \vv, \vt) \evalarrow (\True, \vg) -} -\end{mathpar} - -\hypertarget{def-integerconstraintsatisfied}{} -To handle \emph{well-constrained integers} (integers with a non-empty list of constraints), -we introduce the helper relation -\[ - \integerconstraintsatisfied(\overname{\envs}{\env} \aslsep \overname{\intconstraint}{\vc} \aslsep \overname{\Z}{n}) \;\aslrel\; - (\overname{\Bool}{\vb} \times \overname{\XGraphs}{\vg}) -\] -which checks whether the integer value $n$ \emph{meets the constraint} $\vc$ -(that is, whether $n$ is within the range of values defined by $\vc$) in the environment $\env$ -and returns a Boolean answer $\vb$ and the execution graph $\vg$ resulting from evaluating -the expressions appearing in $\vc$: -\begin{mathpar} -\inferrule[Constraint\_Exact\_Sat]{ - \evalexprsef{\env, \ve} \evalarrow (\nvint(m), \vg) \OrDynError\\\\ - \vb \eqdef m = n -} -{ - \integerconstraintsatisfied(\env, \constraintexact(\ve), n) \evalarrow (\vb, \vg) -} -\and -\inferrule[Constraint\_Range\_Sat]{ - \evalexprsef{\env, \veone} \evalarrow (\nvint(a), \vgone) \OrDynError\\\\ - \evalexprsef{\env, \vetwo} \evalarrow (\nvint(b), \vgtwo) \OrDynError\\\\ - \vb \eqdef \choice{a \leq n \wedge n \leq b}{\True}{\False}\\ - \vg \eqdef \vgone \parallelcomp \vgtwo -} -{ - \integerconstraintsatisfied(\env, \constraintrange(\veone, \vetwo), n) \evalarrow (\vb, \vg) -} -\end{mathpar} - -Finally, we can check whether an integer value satisfies any of the constraints: -\begin{mathpar} - \inferrule[int\_wellconstrained]{ - \tstruct(\env, \vt) \eqname \TInt(\wellconstrained(\vc_{1..k}))\\ - \vv \eqname \nvint(n)\\ - i=1..k: \integerconstraintsatisfied(\env, \vc_i, n) \evalarrow (\vb_i, \vg_i) \OrDynError\\\\ - \vb \eqdef \bigvee_{i=1}^k \vb_i\\ - \vg \eqdef \parallel_{i=1}^k \vg_i - } - { - \isvaloftype(\env, \vv, \vt) \evalarrow (\vb, \vg) - } -\end{mathpar} - -\begin{mathpar} - \inferrule[record]{ - \tstruct(\env, \vt) \eqname L(i=1..k: \id_i\mapsto \vt_i)\\ - L \in \{\TRecord, \TException\}\\ - i=1..k: \getfield(\id_i, \vv) \evalarrow \vu_i\\ - i=1..k: \isvaloftype(\env, \vu_i, \vt_i) \evalarrow (\vb_i, \vg_i) \OrDynError\\\\ - \vb \eqdef \bigwedge_{i=1}^k \vb_i \\ - \vg \eqdef \parallel_{i=1}^k \vg_i - } - { - \isvaloftype(\env, \vv, \vt) \evalarrow (\vb, \vg) - } -\end{mathpar} - -\begin{mathpar} - \inferrule[tuple]{ - \tstruct(\env, \vt) \eqname \TTuple(i=1..k: \vt_i)\\ - i=1..k: \getindex(i, \vv) \evalarrow \vu_i\\ - i=1..k: \isvaloftype(\env, \vu_i, \vt_i) \evalarrow (\vb_i, \vg_i) \OrDynError\\\\ - \vb \eqdef \bigwedge_{i=1}^k \vb_i \\ - \vg \eqdef \parallel_{i=1}^k \vg_i - } - { - \isvaloftype(\env, \vv, \vt) \evalarrow (\vb, \vg) - } -\end{mathpar} - -\begin{mathpar} - \inferrule[array]{ - \tstruct(\env, \vt) \eqname \TArray(\ve, \vtone)\\ - \evalexprsef{\env, \ve} \evalarrow (\nvint(k), \vg)\\ - i=1..k: \getindex(i, \vv) \evalarrow \vv_i\\ - i=1..k: \isvaloftype(\env, \vv_i, \vtone) \evalarrow (\vb_i, \vg_i) \OrDynError\\\\ - \vb \eqdef \bigwedge_{i=1}^k \vb_i \\ - \vg \eqdef \parallel_{i=1}^k \vg_i - } - { - \isvaloftype(\env, \vv, \vt) \evalarrow (\vb, \vg) - } -\end{mathpar} - -Notice that these rules cover all types, including named types ($\TNamed$), -since $\tstruct$ replaces named types by their type definitions. -% -Underconstrained integers (integers with an empty set of constraints) -cannot appear as a type, since ASL syntax does not allow the following: -\begin{itemize} -\item Declaring an underconstrained integer as a variable, -\item Declaring an alias to an underconstrained integer type, and -\item Declaring an underconstrained integer in a compound type. -\end{itemize} - -\section{SemanticsRule.UnopValues \label{sec:SemanticsRule.UnopValues}} -\hypertarget{def-unoprel}{} -The function -\[ - \unoprel(\overname{\unop}{\op} \aslsep \overname{\vals}{\vv}) \aslto \overname{\vals}{\vw} -\] -evaluates a unary operator $\op$ over a \nativevalue\ $\vv$ and returns the \nativevalue\ $\vw$. - -The evaluation is defined in terms of the static evaluation function -$\unopliterals$. - -\subsection{Prose} -One of the following applies: -\begin{itemize} - \item All of the following apply (\textsc{negate\_int}): - \begin{itemize} - \item $\op$ is $\NEG$ and $\vv$ is a literal integer for $n$; - \item statically evaluating $\NEG$ on the literal integer for $n$ yields the - literal integer for $m$; - \item $\vw$ is the native integer value for $m$. - \end{itemize} - - \item All of the following apply (\textsc{negate\_real}): - \begin{itemize} - \item $\op$ is $\NEG$ and $\vv$ is a literal real for $p$; - \item statically evaluating $\NEG$ on the literal real for $n$ yields the - literal real for $q$; - \item $\vw$ is the native real value for $q$. - \end{itemize} - - \item All of the following apply (\textsc{not\_bool}): - \begin{itemize} - \item $\op$ is $\BNOT$ and $\vv$ is a literal Boolean for $b$; - \item statically evaluating $\BNOT$ on the literal Boolean for $b$ yields the - literal real for $c$; - \item $\vw$ is the native Boolean value for $c$. - \end{itemize} - - \item All of the following apply (\textsc{not\_bits}): - \begin{itemize} - \item $\op$ is $\NOT$ and $\vv$ is a literal bitvector for $\bits$; - \item statically evaluating $\NOT$ on the literal bitvector for $\bits$ yields the - literal bitvector for $c$; - \item $\vw$ is the native bitvector value for $c$. - \end{itemize} -\end{itemize} - -\subsection{Formally} -\begin{mathpar} -\inferrule[negate\_int]{ - \unopliterals(\NEG, \lint(n)) \typearrow \lint(m) -}{ - \unoprel(\overname{\NEG}{\op}, \overname{\nvint(n)}{\vv}) \evalarrow \overname{\nvint(m)}{\vw} -} -\and -\inferrule[negate\_real]{ - \unopliterals(\NEG, \lreal(p)) \typearrow \lreal(q) -}{ - \unoprel(\overname{\NEG}{\op}, \overname{\nvreal(p)}{\vv}) \evalarrow \overname{\nvreal(q)}{\vw} -} -\and -\inferrule[not\_bool]{ - \unopliterals(\BNOT, \lbool(b)) \typearrow \lreal(c) -}{ - \unoprel(\overname{\BNOT}{\op}, \overname{\nvbool(b)}{\vv}) \evalarrow \overname{\nvbool(c)}{\vw} -} -\and -\inferrule[not\_bits]{ - \unopliterals(\NOT, \lbitvector(\bits)) \typearrow \lbitvector(c) -}{ - \unoprel(\overname{\NOT}{\op}, \overname{\nvbitvector(\bits)}{\vv}) \evalarrow \overname{\nvbitvector(c)}{\vw} -} -\end{mathpar} - -\section{SemanticsRule.BinopValues \label{sec:SemanticsRule.BinopValues}} -\hypertarget{def-binoprel}{} -The function -\[ - \binoprel(\overname{\binop}{\op} \aslsep \overname{\vals}{\vvone} \aslsep \overname{\vals}{\vvtwo}) - \aslto \overname{\vals}{\vr} \cup \TError -\] -evaluates a binary operator $\op$ over a pair of \nativevalues\ --- $\vvone$ and $\vvtwo$ --- and returns the -\nativevalue\ $\vw$ or an error. - -The evaluation is defined in terms of the static evaluation function -$\binopliterals$. - -\subsection{Prose} -One of the following applies: -\begin{itemize} - \item All of the following apply (\textsc{int\_arith}): - \begin{itemize} - \item $\vvone$ is a literal integer for $a$; - \item $\vvtwo$ is a literal integer for $b$; - \item statically evaluating $\op$ on $\vvone$ and $\vvtwo$ yields the literal integer for $c$; - \item $\vr$ is the native integer value for $c$. - \end{itemize} - - \item All of the following apply (\textsc{int\_rel}): - \begin{itemize} - \item $\vvone$ is a literal integer for $a$; - \item $\vvtwo$ is a literal integer for $b$; - \item statically evaluating $\op$ on $\vvone$ and $\vvtwo$ yields the literal Boolean for $c$; - \item $\vr$ is the native Boolean value for $c$. - \end{itemize} - - \item All of the following apply (\textsc{int\_error}): - \begin{itemize} - \item $\vvone$ is a literal integer for $a$; - \item $\vvtwo$ is a literal integer for $b$; - \item statically evaluating $\op$ on $\vvone$ and $\vvtwo$ yields a type error with message $m$; - \item the result is a dynamic error with message $m$. - \end{itemize} - - \item All of the following apply (\textsc{bool\_okay}): - \begin{itemize} - \item $\vvone$ is a literal Boolean for $a$; - \item $\vvtwo$ is a literal Boolean for $b$; - \item statically evaluating $\op$ on $\vvone$ and $\vvtwo$ yields the literal Boolean for $c$; - \item $\vr$ is the native Boolean value for $c$. - \end{itemize} - - \item All of the following apply (\textsc{bool\_error}): - \begin{itemize} - \item $\vvone$ is a literal Boolean for $a$; - \item $\vvtwo$ is a literal Boolean for $b$; - \item statically evaluating $\op$ on $\vvone$ and $\vvtwo$ yields a type error with message $m$; - \item the result is a dynamic error with message $m$. - \end{itemize} - - \item All of the following apply (\textsc{real\_arith\_okay}): - \begin{itemize} - \item $\vvone$ is a literal real for $a$; - \item $\vvtwo$ is a literal real for $b$; - \item statically evaluating $\op$ on $\vvone$ and $\vvtwo$ yields the literal real for $c$; - \item $\vr$ is the native real value for $c$. - \end{itemize} - - \item All of the following apply (\textsc{real\_rel\_okay}): - \begin{itemize} - \item $\vvone$ is a literal real for $a$; - \item $\vvtwo$ is a literal real for $b$; - \item statically evaluating $\op$ on $\vvone$ and $\vvtwo$ yields the literal Boolean for $c$; - \item $\vr$ is the native Boolean value for $c$. - \end{itemize} - - \item All of the following apply (\textsc{real\_rel\_error}): - \begin{itemize} - \item $\vvone$ is a literal real for $a$; - \item $\vvtwo$ is a literal real for $b$; - \item statically evaluating $\op$ on $\vvone$ and $\vvtwo$ yields a type error with message $m$; - \item the result is a dynamic error with message $m$. - \end{itemize} - - \item All of the following apply (\textsc{bitvector\_rel\_okay}): - \begin{itemize} - \item $\vvone$ is a literal bitvector for $a$; - \item $\vvtwo$ is a literal bitvector for $b$; - \item statically evaluating $\op$ on $\vvone$ and $\vvtwo$ yields the literal Boolean for $c$; - \item $\vr$ is the native Boolean value for $c$. - \end{itemize} - - \item All of the following apply (\textsc{bitvector\_rel\_error}): - \begin{itemize} - \item $\vvone$ is a literal bitvector for $a$; - \item $\vvtwo$ is a literal bitvector for $b$; - \item statically evaluating $\op$ on $\vvone$ and $\vvtwo$ yields a type error with message $m$; - \item the result is a dynamic error with message $m$. - \end{itemize} - - \item All of the following apply (\textsc{bitvector\_bits\_okay}): - \begin{itemize} - \item $\vvone$ is a literal bitvector for $a$; - \item $\vvtwo$ is a literal bitvector for $b$; - \item statically evaluating $\op$ on $\vvone$ and $\vvtwo$ yields the literal bitvector for $c$; - \item $\vr$ is the native bitvector value for $c$. - \end{itemize} - - \item All of the following apply (\textsc{bitvector\_bits\_error}): - \begin{itemize} - \item $\vvone$ is a literal bitvector for $a$; - \item $\vvtwo$ is a literal bitvector for $b$; - \item statically evaluating $\op$ on $\vvone$ and $\vvtwo$ yields a type error with message $m$; - \item the result is a dynamic error with message $m$. - \end{itemize} -\end{itemize} - -\subsection{Formally} - -\begin{mathpar} -\inferrule[int\_arith]{ - \binopliterals(\op, \lint(a), \lint(b)) \typearrow \lint(c) -}{ - \binoprel(\op, \overname{\nvint(a)}{\vvone}, \overname{\nvint(b)}{\vvtwo}) \evalarrow \overname{\nvint(c)}{\vr} -} -\and -\inferrule[int\_rel]{ - \binopliterals(\op, \lint(a), \lint(b)) \typearrow \lbool(c) -}{ - \binoprel(\op, \overname{\nvint(a)}{\vvone}, \overname{\nvint(b)}{\vvtwo}) \evalarrow \overname{\nvbool(c)}{\vr} -} -\and -\inferrule[int\_error]{ - \binopliterals(\op, \lint(a), \lint(b)) \typearrow \TypeError(m) -}{ - \binoprel(\op, \overname{\nvint(a)}{\vvone}, \overname{\nvint(b)}{\vvtwo}) \evalarrow \Error(m) -} -\end{mathpar} - -\begin{mathpar} -\inferrule[bool\_okay]{ - \binopliterals(\op, \lbool(a), \lbool(b)) \typearrow \lbool(c) -}{ - \binoprel(\op, \overname{\nvbool(a)}{\vvone}, \overname{\nvbool(b)}{\vvtwo}) \evalarrow \overname{\nvbool(c)}{\vr} -} -\and -\inferrule[bool\_error]{ - \binopliterals(\op, \lbool(a), \lbool(b)) \typearrow \TypeError(m) -}{ - \binoprel(\op, \overname{\nvbool(a)}{\vvone}, \overname{\nvbool(b)}{\vvtwo}) \evalarrow \Error(m) -} -\end{mathpar} - -\begin{mathpar} -\inferrule[real\_arith\_okay]{ - \binopliterals(\op, \lreal(a), \lreal(b)) \typearrow \lreal(c) -}{ - \binoprel(\op, \overname{\nvreal(a)}{\vvone}, \overname{\nvreal(b)}{\vvtwo}) \evalarrow \overname{\nvreal(c)}{\vr} -} -\and -\inferrule[real\_arith\_error]{ - \binopliterals(\op, \lreal(a), \lreal(b)) \typearrow \TypeError(m) -}{ - \binoprel(\op, \overname{\nvreal(a)}{\vvone}, \overname{\nvreal(b)}{\vvtwo}) \evalarrow \Error(m) -} -\end{mathpar} - -\begin{mathpar} -\inferrule[real\_rel\_okay]{ - \binopliterals(\op, \lreal(a), \lreal(b)) \typearrow \lbool(c) -}{ - \binoprel(\op, \overname{\nvreal(a)}{\vvone}, \overname{\nvreal(b)}{\vvtwo}) \evalarrow \overname{\nvbool(c)}{\vr} -} -\and -\inferrule[real\_rel\_error]{ - \binopliterals(\op, \lreal(a), \lreal(b)) \typearrow \TypeError(m) -}{ - \binoprel(\op, \overname{\nvreal(a)}{\vvone}, \overname{\nvreal(b)}{\vvtwo}) \evalarrow \Error(m) -} -\end{mathpar} - -\begin{mathpar} -\inferrule[bitvector\_rel\_okay]{ - \binopliterals(\op, \nvbitvector(a), \nvbitvector(b)) \typearrow \lbool(c) -}{ - \binoprel(\op, \overname{\lbitvector(a)}{\vvone}, \overname{\lbitvector(b)}{\vvtwo}) \evalarrow \overname{\nvbool(c)}{\vr} -} -\and -\inferrule[bitvector\_rel\_error]{ - \binopliterals(\op, \lbitvector(a), \lbitvector(b)) \typearrow \TypeError(m) -}{ - \binoprel(\op, \overname{\lbitvector(a)}{\vvone}, \overname{\lbitvector(b)}{\vvtwo}) \evalarrow \Error(m) -} -\and -\inferrule[bitvector\_bits\_okay]{ - \binopliterals(\op, \lbitvector(a), \lbitvector(b)) \typearrow \lbitvector(c) -}{ - \binoprel(\op, \overname{\lbitvector(a)}{\vvone}, \overname{\lbitvector(b)}{\vvtwo}) \evalarrow \overname{\nvbitvector(c)}{\vr} -} -\and -\inferrule[bitvector\_bits\_error]{ - \binopliterals(\op, \lbitvector(a), \lbitvector(b)) \typearrow \TypeError(m) -}{ - \binoprel(\op, \overname{\lbitvector(a)}{\vvone}, \overname{\lbitvector(b)}{\vvtwo}) \evalarrow \Error(m) -} -\end{mathpar} - -% \bibliographystyle{plain} -% \bibliography{ASL} -% \end{document} diff --git a/asllib/doc/ASLSyntaxReference.tex b/asllib/doc/ASLSyntaxReference.tex deleted file mode 100644 index 0c6127287..000000000 --- a/asllib/doc/ASLSyntaxReference.tex +++ /dev/null @@ -1,4609 +0,0 @@ -%\documentclass{book} -%\input{ASLmacros} - -\part{ASL Syntax Reference} - -% \author{Arm Architecture Technology Group} -% \title{ASL Syntax Reference \\ -% DDI 0620} -% \begin{document} -% \maketitle - -% \tableofcontents{} - -% \include{notice.tex} - -% \include{disclaimer.tex} - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -\chapter{Introduction} -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -This part defines how an ASL specification, given as text, can be transformed into an \emph{abstract syntax tree}, -which is a tree-like data structure. This transformation occurs in three stages: - -\begin{description} - \item[Lexical Analysis] The text is first transformed into a list of \emph{tokens}. - This stage is defined in \chapref{lexicalanalysis}; - \item[Parsing] The list of tokens is transformed into a \emph{parse tree}. - This stage is defined in \chapref{parsing}; - \item[Abstraction] The parse tree is transformed into an abstract syntax tree. This is a conceptual stage. In actuality, - the parsing stage transforms the list of tokens directly into an abstract syntax tree. However, it is useful to - distinguish between the parsing state and the abstraction stage. - ASL abstract syntax trees are defined in \chapref{ASLAbstractSyntax}. - This stage is defined in \chapref{BuildingAbstractSyntaxTrees}. -\end{description} - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -\chapter{ASL Lexical Definition \label{chap:lexicalanalysis}} -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -This chapter defines the various elements of an ASL specification text in a high-level way -and then formalizes the lexical analysis as a function that takes a text and returns -a list of \emph{tokens} or a lexical error. - -\section{ASL Specification Text} -An ASL specification is a string --- a list of ASCII characters --- consisting of a \emph{content text} -followed by an \emph{end-of-file}. -The content text is a list of -ASCII characters that have the decimal encoding of 32 through 126 (inclusive), -which includes the space character (decimal encoding 32), -as well as -carriage return (decimal encoding 13) and line feed (decimal encoding 10). -\hypertarget{def-eof}{} -The end of file character is denote by $\eof$. -The content text does not contain an end-of-file character. - -In particular, it is an error to use a tab character in ASL specification text (decimal encoding 9). - -\section{Lexical Regular Expressions} - -\hypertarget{def-regex}{} -Table~\ref{ta:LexicalRegularExpressions} defines the regular expressions $\RegExp$ used to define -\emph{lexemes} --- substrings of the ASL specification text that are used to form \emph{tokens}. - -\begin{table} -\caption{Lexical Regular Expressions \label{ta:LexicalRegularExpressions}} -\begin{center} -\begin{tabular}{ll} -\hline -\textbf{RegExp} & \textbf{Matches}\\ -\hline -$\underbracket{\texttt{a\_string}}$ & Any character in \texttt{a\_string}\\ -$\square$ & The space character (decimal 32)\\ -\ascii{a} & The ASCII with decimal 'a'\\ -\ascii{a-b} & The ASCII range between decimals 'a' and 'b'\\ -(\texttt{$A$}) & $A$\\ -$A$ $B$ & $A$ followed by $B$\\ -\texttt{$A$ | $B$} & A or B\\ -\texttt{$A$ - $B$} & $A$ but not $B$\\ -$A*$ & Zero or more repetitions of A\\ -$A+$ & One or more repetitions of A\\ -%\texttt{["a\_string"]} & Any character in \texttt{a\_string}\\ -\texttt{"a\_string"} & The string \texttt{a\_string} verbatim\\ -\texttt{<}r\texttt{>} & The lexical regular expression defined for \texttt{<}r\texttt{>}\\ -\hline -\end{tabular} -\end{center} -\end{table} - -Let $\REasciichar$ stand for any ASCII character: -\hypertarget{def-reasciichar}{} -\begin{center} -\begin{tabular}{rcl} -$\REasciichar$ &$\triangleq$& \ascii{0-255} -\end{tabular} -\end{center} - -Let $\REchar$ stand for an ASCII character that may appear in the content text: -\hypertarget{def-rechar}{} -\begin{center} -\begin{tabular}{rcl} -$\REchar$ &$\triangleq$& \ascii{10} \texttt{|} \ascii{13} \texttt{|} \ascii{32-126}\\ -\end{tabular} -\end{center} - -\hypertarget{def-lang}{} -The notation $\Lang(e)$ stands for \emph{formal language} of a regular expression $e$. -That is, the set of strings that match that regular expression. - -\section{Whitespace} -Comments, newlines and space characters are treated as whitespace. - -\section{Comments} -ASL supports comments in the style of C++: -\begin{itemize} -\item Single-line comments: the text from \text{//} until the end of the line -is a comment (\ascii{10} is the line feed character \verb|\n|). -\item Multi-line comments: the text between \texttt{/*} and \texttt{*/} is a comment. -\end{itemize} -Comments do not nest and the two styles of comments do not interact with each other. - -\hypertarget{def-recomment}{} -\begin{center} -\begin{tabular}{rcl} -$\RElinecomment$ &$\triangleq$& \texttt{"//"} (\REchar\ \texttt{-} \ascii{10})* \texttt{|} \texttt{"/*"} \REchar* \texttt{"*/"}\\ -\end{tabular} -\end{center} - -\section{Integer Literals} -Integers are written either in decimal using one or more of the characters \texttt{0-9} and underscore, or in hexadecimal -using \texttt{0x} at the start followed by the characters \texttt{0-9, a-f, A-F} and underscore. An integer literal cannot start with -an underscore. - -This is formalized by the following lexical regular expression: -\hypertarget{def-redigit}{} -\hypertarget{def-reintlit}{} -\hypertarget{def-rehexlit}{} -\begin{center} -\begin{tabular}{rcl} -$\REdigit$ &$\triangleq$& \anycharacter{\texttt{0123456789}}\\ -$\REintlit$ &$\triangleq$& \texttt{\REdigit\ ($\square$ | \REdigit)*}\\ -$\REhexlit$ &$\triangleq$& \anycharacter{\texttt{0x}} (\REdigit\ \texttt{|} \anycharacter{\texttt{abcdefABCDEF}}) (\Underscore\ \texttt{|} \REdigit\ \texttt{|} \anycharacter{\texttt{abcdefABCDEF}})* -\end{tabular} -\end{center} - -\section{Real Number Literals} -Real numbers are written in decimal and consist of one or more decimal digits, a decimal point and one -or more decimal digits. Underscores can be added between digits to aid readability - -Underscores in numbers are not significant, and their only purpose is to separate groups of digits to make constants -such as \texttt{0xefff\_fffe}, \texttt{1\_000\_000} or \texttt{3.141\_592\_654} easier to read, - -\hypertarget{def-reallit}{} -This is formalized by the following lexical regular expression: -\begin{center} -\begin{tabular}{rcl} -$\REreallit$ &$\triangleq$& \texttt{\REdigit\ (\Underscore\ | \REdigit)* '.' \REdigit\ (\Underscore\ | \REdigit)*} -\end{tabular} -\end{center} - -\section{Boolean Literals} -Boolean literals are written using \texttt{TRUE} or \texttt{FALSE}. - -\section{Bitvector Literals} -Constant bit-vectors are written using 1, 0 and spaces surrounded by single-quotes. -\hypertarget{def-rebitvectorlit}{} -\begin{center} -\begin{tabular}{rcl} -$\REbitvectorlit$ &$\triangleq$& \anycharacter{\texttt{'}} (\anycharacter{\texttt{01}\square})* \anycharacter{\texttt{'}} -\end{tabular} -\end{center} - -The spaces in a bitvector are not significant and are only used to improve readability. -For example, \texttt{'1111 1111 1111 1111'} is the same as \texttt{'1111111111111111'}. - -\section{Bitmasks} -Constant bitmasks are written using \texttt{1}, \texttt{0}, \texttt{x} and spaces surrounded by single-quotes. -The \texttt{x} represents a don’t care character. - -\hypertarget{def-rebitmasklit}{} -\begin{center} -\begin{tabular}{rcl} -$\REbitmasklit$ &$\triangleq$& \anycharacter{\texttt{'}} (\anycharacter{\texttt{01x}\square})* \anycharacter{\texttt{'}} -\end{tabular} -\end{center} - -The spaces in a constant bitmask are not significant and are only used to improve readability. - -\section{String Literals} - -String literals consist of printable characters surrounded by double quotes. -They are used to create string values, which are strings of zero or more characters, -where a character is a printable ASCII character, -tab (ASCII code \texttt{10}), -newline (ASCII code \texttt{10}), -the backslash character (ASCII code \texttt{92}), -and double-quote character (ASCII code \texttt{34}). -Unprintable characters (tabs and newlines) are not permitted in string literals, -so they are represented by treating the backslash character \textbackslash, as an escape character. -Note therefore that string literals cannot span multiple source lines. - -The escape sequences allowed in string literals appear in Table~\ref{ta:SscapeSeuqnces}. -\begin{table} -\caption{Escape Sequences in String Literals\label{ta:SscapeSeuqnces}} -\begin{center} -\begin{tabular}{ll} -\hline -\textbf{Escape sequence} & \textbf{Meaning}\\ -\hline -\verb|\n| & The newline, ASCII code \texttt{10}\\ -\verb|\t| & The tab, ASCII code \texttt{9}\\ -\verb|\\| & The backslash character, \verb|\|, ASCII code \texttt{92}\\ -\verb|\"| & The double-quote character, \texttt{"}, ASCII code \texttt{34}\\ -\hline -\end{tabular} -\end{center} -\end{table} - -\hypertarget{def-restringlit}{} -\hypertarget{def-restrchar}{} -\begin{center} -\begin{tabular}{rcl} -$\REstrchar$ &$\triangleq$& \ascii{32-126}\\ -$\REstringlit$ &$\triangleq$& \anycharacter{\texttt{"}} ( ($\REstrchar$ \texttt{-} $\underbracket{\texttt{"}\ \backslash\ }$) $|$ ($\underbracket{\backslash\ }$ $\underbracket{\texttt{" n t }\backslash\ }$) )* \anycharacter{\texttt{"}} -\end{tabular} -\end{center} - -\section{Identifiers} -Identifiers start with a letter or underscore and continue with zero or more letters, underscores or digits. -Identifiers are case sensitive. To improve readability, it is recommended to avoid the use of identifiers that differ -only by the case of some characters. - -By convention, identifiers that begin with double-underscore are reserved for use in the implementation and should -not be used in specifications. - -\hypertarget{def-reletter}{} -\hypertarget{def-reidentifier}{} -\begin{center} -\begin{tabular}{rcl} -$\REletter$ &$\triangleq$& \texttt{'a-z' $|$ 'A-Z'}\\ -$\REidentifier$ &$\triangleq$& \texttt{($\REletter$ $|$ $\underbracket{\texttt{ \_ } }$) ($\REletter$ $|$ $\underbracket{\texttt{ \_ } }$ $|$ $\REdigit$)*}\\ -\end{tabular} -\end{center} - -% An enumeration literal is also classed as a literal constant, but is syntactically an identifier. - -Tuple element selectors are classed as identifiers. That is, in cases like \texttt{(1, 2).item0}, -the selector \texttt{item0} is classed as an identifier. -\lrmcomment{This is related to \identiTSXL} - -\section{Lexical Analysis} -Lexical analysis, which is also referred to as \emph{scanning}, is defined via the function -\hypertarget{def-aslscan}{} -\[ -\aslscan : \LexSpec \times \REasciichar^* \aslto (\Token^* \cup \{\LexicalError\}) -\] -\hypertarget{def-lexicalerrorresult}{} -which takes a \emph{lexical specification} (explained soon), an ASL specification string -(where characters are simply numbers representing ASCII characters) -and returns a sequence of tokens (tokens are defined below) or a \emph{lexical error} $\LexicalError$. - -Tokens have one of two forms: -\begin{description} - \item[Value-carrying] Tokens that carry value have the form $L(v)$ where $L$ is a token label, - signifying the meaning of the token, and $v$ is a value carried by the token, - which is used to construct the respective Abstract Syntax Tree nodes. - \item[Valueless] Tokens that do not carry values have the form $L$ where $L$ is a token label. -\end{description} - -\hypertarget{def-token}{} -The set of tokens used for the lexical analysis of ASL strings is defined below. -\[ -\begin{array}{rcll} -\Token &\triangleq& \{\ \Tintlit(n) \;|\; n\in\Z\ \} & \cup\\ - & & \{\ \Treallit(q) \;|\; q\in\Q\ \} & \cup\\ - & & \{\ \Tstringlit(s) \;|\; s\in \Lang(\REstringlit) \} & \cup\\ - & & \{\ \Tstringchar(c) \;|\; c \in \Lang(\REchar) \} & \cup\\ - & & \{\ \Tstringend \} & \cup\\ - & & \{\ \Tbitvectorlit(b) \;|\; b\in\{0,1\}^*\ \} & \cup\\ - & & \{\ \Tmasklit(m) \;|\; m\in\{0,1,x\}^*\ \} & \cup\\ - & & \{\ \Tboollit(\True), \Tboollit(\False)\ \} & \cup \\ - & & \{\ \Tidentifier(\id) \;|\; \id\in \Lang(\REidentifier)\ \} & \cup \\ - & & \{\ \Tlexeme(s) \;|\; s\in\Strings\ \} & \cup \\ - & & \{\ \Twhitespace, \Teof, \Terror\ \} & -\end{array} -\] - -\hypertarget{def-tintlit}{} -\begin{itemize} - \item Tokens of the form $\Tintlit(n)$ represent integer literals; \hypertarget{def-treallit}{} - \item Tokens of the form $\Treallit(q)$ represent real literals; \hypertarget{def-tstringlit}{} - \item Tokens of the form $\Tstringlit(s)$ represent string literals; - \hypertarget{def-tstringchar}{} - \item Tokens of the form $\Tstringchar(c)$ represent a single character in a string literal; - \hypertarget{def-tstringend}{} - \item The token $\Tstringend$ represents the closing quotes of a string literal; - \hypertarget{def-tbitvectorlit}{} - \item Tokens of the form $\Tbitvectorlit(b)$ represent bitvector literals; \hypertarget{def-tmasklit} - \item Tokens of the form $\Tmasklit(m)$ represent constant bitmasks; \hypertarget{def-tboollit}{} - \item Tokens of the form $\Tboollit(b)$ represent Boolean literals; \hypertarget{def-tidentifier}{} - \hypertarget{def-tidentifier}{} - \item Tokens of the form $\Tidentifier(i)$ represent identifiers; \hypertarget{def-tlexeme}{} - \item Tokens with the label $\Tlexeme$ are ones where the value $s$ is simply the \emph{lexeme} for that token. - That is, the substring representing that token. Later we will refer to such token by simply quoting - the lexeme of the token and dropping the label, for brevity. For example, instead of $\Tlexeme(\texttt{for})$, - we will write $\Tfor$. \hypertarget{def-twhitespace}{} - \item The valueless token $\Twhitespace$ represents white spaces; \hypertarget{def-terror}{} - \item The valueless token $\Terror$ represents an illegal lexeme such as the use of a reserved keyword; - \hypertarget{def-teof}{} - \item The valueless token $\Teof$ represents $\eof$. -\end{itemize} - -\hypertarget{def-lexspec}{} -\begin{definition}[Lexical Specification] -A \emph{lexical specification} consists of a list of pairs $[(r_1,a_1),\ldots,(r_k,a_k)] \in \LexSpec$ -where each pair $(r_i,a_i)$ consists of a lexical regular expression $r_i$ -and a \emph{lexeme action} $a_i : \Strings\times\Strings \aslto \Token^*$. -\end{definition} - -The function -\[ -\remaxmatch : \overname{\RegExp}{e} \times \overname{\Strings}{s} \aslto (\overname{\Strings}{s_1} \times \overname{\Strings}{s_2}) \cup \{\bot\} -\] -returns the \emph{longest} match of a regular expression $e$ for a prefix of a string $s$. -More precisely: -$\remaxmatch(e, s) = (s_1,s_2)$ means that $s_1\in\Lang(e)$ and $s = s_1 \concat s_2$. -If no match exists, it is indicated by returning $\bot$. - -The function $\maxmatches : \overname{\LexSpec}{R} \times \overname{\Strings}{s} \aslto \overname{\LexSpec}{R'}$ -returns the sublist of $R$ consisting of pairs whose maximal matches for $s$ are equal. Importantly, the result sublist $R'$ maintains -the order of pairs in $R$. If all expressions in $R$ do not match (that is $\remaxmatch$ returns $\bot$ for all pairs in $R$), then $R'$ is the empty list. - -The function $\aslscan$ is constructively defined via the following inference rules: - -\begin{mathpar} -\inferrule[no\_match]{ - \maxmatches(R, s) = \emptylist -}{ - \aslscan(R, s) \scanarrow \LexicalError -} -\end{mathpar} - -\begin{mathpar} -\inferrule[token]{ - \maxmatches(R, s) = [(e_1,a_1),\ldots,(e_n,a_n)]\\ - \remaxmatch(s, e_1) = (s_1, s_2)\\ - a_1(s_1, s_2) \scanarrow \ts \terminateas \LexicalError -}{ - \aslscan(R, s) \scanarrow \ts -} -\end{mathpar} - -This form of scanning is referred to as ``Maximal Munch'' in Compiler Theory -and is the most common form of scanning. -See ``Compilers: Principles, Techniques, and Tools''~\cite{ASU86} for more details. - -While Maximal Munch is a useful policy for scanning of most tokens, -it does not work well for string literals and multi-line comments, which require -identifying the respective tokens via shortest match. -% -For this purpose, most lexical analyzers split the analysis into separate ``states'' --- -one for keywords, symbols, single-line comments, and identifiers, one for string literals, -and one for multi-line comments. The lexical analyzers switches between the states as -needed, and analyzing string literals involves concatenating the individual characters -of the string literal into a single token. - -Lexical analysis of ASL follows this approach by defining three specifications: -\begin{itemize} - \item $\spectoken$: For keywords, symbols, single-line comments, and identifiers; - \item $\speccomment$: For multi-line comments; - \item $\specstring$: For string literals. -\end{itemize} - -Additionally, lexical analysis of string literals carries the extra state --- -the string characters encountered along the way. - -We now define each of the lexical specifications and related lexeme actions. - -Each lexical specification is depicted by a table where the order of elements -of a specification corresponds to the order of rows in the table. - -\subsection{Scanning Regular Tokens} -To scan keywords, symbols, single-line comments, and identifiers, -we define the following lexeme actions: - -\hypertarget{def-actiondiscard}{} -\begin{itemize} -\item -The lexeme action -\[ -\actiondiscard(s_1, s_2) \triangleq \aslscan(\spectoken, s_2) -\] -discards the string $s_1$ and continues scanning $s_2$ with $\spectoken$. -This is used for whitespace. - -\item -\hypertarget{def-actiontoken}{} -The lexeme action -\[ -\begin{array}{l} -\actiontoken(f) \triangleq \lambda (s_1,s_2). \\ -\wrappedline\ -\begin{cases} - \LexicalError & \text{if }f(s_1) = \Terror \text{ or}\\ - & \aslscan(\spectoken, s_2) = \Terror\\ - [f(s_1)] \concat \aslscan(\spectoken, s_2) & \text{else} -\end{cases} -\end{array} -\] - -is parameterized by a function $f$ that converts strings into corresponding tokens. -It applies $f$ to convert $s_1$ into a token and then continues scanning $s_2$ with \\ -$\spectoken$. -If at any point a lexical error is encountered, the entire result is a lexical error. - -\item -\hypertarget{def-actionstartstring}{} -The lexeme action -\[ -\actionstartstring(s_1, s_2) \triangleq \scanstring(\emptylist, s_2) -\] -switches to scanning literal strings via $\scanstring$. - -\item The lexeme action -\hypertarget{def-actionstartcomment}{} -\[ -\actionstartcomment(s_1, s_2) \triangleq \aslscan(\speccomment, s_2) -\] -switches to scanning multi-line comments by changing the lexical specification -to $\speccomment$. - -\hypertarget{def-decimaltolit}{} -\item The function $\decimaltolit(s)$ returns $\Tintlit(n)$ where $n$ is the integer represented by $s$ -by decimal representation. -\hypertarget{def-hextolit}{} -\item The function $\hextolit(s)$ returns $\Tintlit(n)$ where $n$ is the integer represented by $s$ -by hexadecimal representation. -\hypertarget{def-realtolit}{} -\item The function $\realtolit(s)$ returns $\Treallit(q)$ where $q$ is the real value represented by $s$ -by floating point representation. -\hypertarget{def-strtolit}{} -\item The function $\strtolit(s)$ returns $\Tstringlit(s')$ where $s'$ is the string value represented by $s$. -\hypertarget{def-bitstolit}{} -\item The function $\bitstolit(s)$ returns $\Tbitvectorlit(b)$ where $b$ is the sequence of bits -given by $s$. -\hypertarget{def-masktolit}{} -\item The function $\masktolit(s)$ returns $\Tmasklit(m)$ where $m$ is the bitmask given by $s$. -\hypertarget{def-falsetolit}{} -\item The function $\falsetolit(s)$ returns $\Tboollit(\False)$ ($s$ is ensured to be \texttt{FALSE}). -\hypertarget{def-truetolit}{} -\item The function $\truetolit(s)$ returns $\Tboollit(\True)$ ($s$ is ensured to be \texttt{TRUE}). -\hypertarget{def-tokenid}{} -\item The function $\tokenid(s)$ returns $\Tlexeme(s)$. -\hypertarget{def-lexicalerror}{} -\item The function $\lexicalerror$ returns $\Terror$. -\hypertarget{def-toidentifier}{} -\item The function $\toidentifier(s)$ returns $\Tidentifier(s)$. -\hypertarget{def-eoftoken}{} -\item The lexeme action -\[ -\eoftoken(s_1, s_2) \triangleq \begin{cases} - \emptylist & s_2 = \emptylist\\ - \LexicalError & \text{else} -\end{cases} -\] -checks whether $\eof$ is not followed by more characters and returns a lexical error otherwise. -\end{itemize} - -\hypertarget{def-spectoken}{} -The lexical specification $\spectoken$ is given by the following four tables. -Splitting the lexical specification into four tables is done for presentation purposes --- -the ordering between the entries is induced by the order between the tables -and the order of entries in each table. -% -When several regular expressions are listed in a row, it means that they are all associated with the same -token function. - -\begin{center} -\begin{tabular}{ll} -\textbf{Lexical Regular Expressions} & \textbf{Lexeme Action}\\ -\hline -(\ascii{10} $|$ \ascii{13} $|$ \ascii{32})+ & $\discard$ \\ -$\texttt{"/*"}$ & $\actionstartcomment$ \\ -$\underbracket{\texttt{"}}$ & $\actionstartstring$ \\ -$\REintlit$ & $\actiontoken(\decimaltolit)$ \\ -$\REhexlit$ & $\actiontoken(\hextolit)$ \\ -$\REreallit$ & $\actiontoken(\realtolit)$ \\ -$\REstringlit$ & $\actiontoken(\strtolit)$ \\ -$\REbitvectorlit$ & $\actiontoken(\bitstolit)$ \\ -$\REbitmasklit$ & $\actiontoken(\masktolit)$ \\ -\texttt{'!'}, \texttt{','}, \texttt{'<'}, \texttt{">>"}, \texttt{"\&\&"}, \texttt{"-->"}, \texttt{"<<"} & $\actiontoken(\tokenid)$ \\ -\texttt{']'}, \texttt{')'}, \texttt{".."}, \texttt{'='}, \texttt{'\{'}, \texttt{"!="}, \texttt{'-'}, \texttt{"<->"} & $\actiontoken(\tokenid)$ \\ -\texttt{'['}, \texttt{'('}, \texttt{'.'}, \texttt{"<="}, \texttt{'\textasciicircum'}, \texttt{'*'}, \texttt{'/'} & $\actiontoken(\tokenid)$ \\ -\texttt{"=="}, \texttt{"||"}, \texttt{'+'}, \texttt{':'}, \texttt{"=>"}, & $\actiontoken(\tokenid)$ \\ -\texttt{'\}'}, \texttt{"++"}, \texttt{'>'}, \texttt{"+:"}, \texttt{"*:"}, \texttt{';'}, \texttt{">="} & $\actiontoken(\tokenid)$ \\ -\texttt{"@looplimit"} & $\actiontoken(\tokenid)$ \\ -\hline -\end{tabular} -\end{center} - -\begin{center} -\begin{tabular}{ll} -\textbf{Lexical Regular Expressions} & \textbf{Lexeme Action}\\ -\hline -\texttt{"AND"}, \texttt{"array"}, \texttt{"as"}, \texttt{"assert"}, & $\actiontoken(\tokenid)$ \\ -\texttt{"begin"}, \texttt{"bit"}, \texttt{"bits"}, \texttt{"boolean"} & $\actiontoken(\tokenid)$ \\ -\texttt{"case"}, \texttt{"catch"}, \texttt{"config"}, \texttt{"constant"} & $\actiontoken(\tokenid)$ \\ -\texttt{"DIV"}, \texttt{"DIVRM"}, \texttt{"do"},\texttt{"downto"} & $\actiontoken(\tokenid)$ \\ -\texttt{"else"}, \texttt{"elsif"}, \texttt{"end"}, \texttt{"enumeration"} & $\actiontoken(\tokenid)$ \\ -\texttt{"XOR"} & $\actiontoken(\tokenid)$ \\ -\texttt{"exception"} & $\actiontoken(\tokenid)$ \\ -\texttt{"FALSE"} & $\actiontoken(\falsetolit)$ \\ -\texttt{"for"}, \texttt{"func"} & $\actiontoken(\tokenid)$ \\ -\texttt{"getter"} & $\actiontoken(\tokenid)$ \\ -\texttt{"if"}, \texttt{"IN"}, \texttt{"integer"} & $\actiontoken(\tokenid)$ \\ -\texttt{"let"} & $\actiontoken(\tokenid)$ \\ -%"limit"} & LIMIT \\ -\texttt{"MOD"} & $\actiontoken(\tokenid)$ \\ -\texttt{"NOT"} & $\actiontoken(\tokenid)$ \\ -\texttt{"of"}, \texttt{"OR"}, \texttt{"otherwise"} & $\actiontoken(\tokenid)$ \\ -\texttt{"pass"}, \texttt{"pragma"}, \texttt{"print"} & $\actiontoken(\tokenid)$ \\ -\texttt{"real"}, \texttt{"record"}, \texttt{"repeat"}, \texttt{"return"} & $\actiontoken(\tokenid)$ \\ -\texttt{"setter"}, \texttt{"string"}, \texttt{"subtypes"} & $\actiontoken(\tokenid)$ \\ -\texttt{"then"}, \texttt{"throw"}, \texttt{"to"}, \texttt{"try"} & $\actiontoken(\tokenid)$ \\ -\texttt{"TRUE"} & $\actiontoken(\truetolit)$ \\ -\texttt{"type"} & $\actiontoken(\tokenid)$ \\ -\texttt{"UNKNOWN"}, \texttt{"until"} & $\actiontoken(\tokenid)$ \\ -\texttt{"var"} & $\actiontoken(\tokenid)$ \\ -\texttt{"when"}, \texttt{"where"}, \texttt{"while"}, \texttt{"with"} & $\actiontoken(\tokenid)$ \\ -\hline -\end{tabular} -\end{center} - -The following list represents keywords that are reserved for future use. -\begin{center} -\begin{tabular}{ll} -\textbf{Lexical Regular Expressions} & \textbf{Lexeme Action}\\ -\hline -\texttt{"SAMPLE"}, \texttt{"UNSTABLE"} & $\lexicalerror$ \\ -\texttt{"\_"}, \texttt{"access"}, \texttt{"advice"}, \texttt{"after"} & $\lexicalerror$ \\ -\texttt{"any"}, \texttt{"aspect"} & $\lexicalerror$ \\ -\texttt{"assume"}, \texttt{"assumes"}, \texttt{"before"} & $\lexicalerror$ \\ -\texttt{"call"}, \texttt{"cast"} & $\lexicalerror$ \\ -\texttt{"class"}, \texttt{"dict"} & $\lexicalerror$ \\ -\texttt{"endcase"}, \texttt{"endcatch"}, \texttt{"endclass"} & $\lexicalerror$ \\ -\texttt{"endevent"}, \texttt{"endfor"}, \texttt{"endfunc"}, \texttt{"endgetter"} & $\lexicalerror$ \\ -\texttt{"endif"}, \texttt{"endmodule"}, \texttt{"endnamespace"}, \texttt{"endpackage"} & $\lexicalerror$ \\ -\texttt{"endproperty"}, \texttt{"endrule"}, \texttt{"endsetter"}, \texttt{"endtemplate"} & $\lexicalerror$ \\ -\texttt{"endtry"}, \texttt{"endwhile"}, \texttt{"entry"} & $\lexicalerror$ \\ -\texttt{"event"}, \texttt{"export"}, \texttt{"expression"} & $\lexicalerror$ \\ -\texttt{"extends"}, \texttt{"extern"}, \texttt{"feature"} & $\lexicalerror$ \\ -\texttt{"get"}, \texttt{"gives"} & $\lexicalerror$ \\ -\texttt{"iff"}, \texttt{"implies"}, \texttt{"import"} & $\lexicalerror$ \\ -\texttt{"intersect"}, \texttt{"intrinsic"} & $\lexicalerror$ \\ -\texttt{"invariant"}, \texttt{"is"}, \texttt{"list"} & $\lexicalerror$ \\ -\texttt{"map"}, \texttt{"module"}, \texttt{"namespace"}, \texttt{"newevent"} & $\lexicalerror$ \\ -\texttt{"newmap"}, \texttt{"original"} & $\lexicalerror$ \\ -\texttt{"package"}, \texttt{"parallel"} & $\lexicalerror$ \\ -\texttt{"pointcut"}, \texttt{"port"}, \texttt{"private"} & $\lexicalerror$ \\ -\texttt{"profile"}, \texttt{"property"}, \texttt{"protected"}, \texttt{"public"} & $\lexicalerror$ \\ -\texttt{"replace"} & $\lexicalerror$ \\ -\texttt{"requires"}, \texttt{"rethrow"}, \texttt{"rule"} & $\lexicalerror$ \\ -\texttt{"set"}, \texttt{"shared"}, \texttt{"signal"} & $\lexicalerror$ \\ -\texttt{"statements"}, \texttt{"template"} & $\lexicalerror$ \\ -\texttt{"typeof"}, \texttt{"union"} & $\lexicalerror$ \\ -\texttt{"using"}, \texttt{"watch"} & $\lexicalerror$ \\ -\texttt{"ztype"} & $\lexicalerror$ \\ -% "pattern" -\hline -\end{tabular} -\end{center} - -\begin{center} -\begin{tabular}{ll} -\textbf{Lexical Regular Expression} & \textbf{Lexeme Action}\\ -\hline -$\REidentifier$ & $\actiontoken(\toidentifier)$ \\ -$\eof$ & $\eoftoken$ \\ -\hline -\end{tabular} -\end{center} - -\subsection{Scanning Strings} -\hypertarget{def-scanstring}{} -To scan string literals, we define the following specialized scanning function. -The function -\[ -\scanstring : \overname{\REasciichar^*}{\buff} \times \overname{\REasciichar^*}{s} \aslto (\Token^* \cup \{\LexicalError\}) -\] -scans string with the $\specstring$ specification while building the final string literal in $\buff$. -It is defined via the following rules: -\begin{mathpar} -\inferrule[no\_match]{ - \maxmatches(\specstring, s) = \emptylist -}{ - \scanstring(\buff, s) \scanarrow \LexicalError -} -\end{mathpar} - -\begin{mathpar} -\inferrule[char]{ - \maxmatches(R, s) = [(e_1,a_1),\ldots,(e_n,a_n)]\\ - \remaxmatch(s, e_1) = (s_1, s_2)\\ - a_1(s_1, s_2) = \Tstringchar(t)\\ - \scanstring(\buff \concat t, s_2) \scanarrow \tstwo \terminateas \LexicalError -}{ - \scanstring(\buff, s) \scanarrow \tstwo -} -\end{mathpar} - -\begin{mathpar} -\inferrule[end]{ - \maxmatches(R, s) = [(e_1,a_1),\ldots,(e_n,a_n)]\\ - \remaxmatch(s, e_1) = (s_1, s_2)\\ - a_1(s_1, s_2) = \Tstringend\\ - \aslscan(\spectoken, s_2) \scanarrow \tstwo \terminateas \LexicalError -}{ - \scanstring(\buff, s) \scanarrow [\Tstringlit(\buff)] \concat \tstwo -} -\end{mathpar} - -We also employ the following lexeme actions: -\begin{itemize} -\item -\hypertarget{def-stringchar}{} -The lexeme action -\[ -\stringchar(s_1, s_2) \triangleq \Tstringchar(s_1) -\] -returns $s_1$, which is always a single character, as a $\Tstringchar$ -token, which is added to the characters that make up the final string -literal. - -\item -\hypertarget{def-stringescape}{} -The lexeme action -\[ -\stringescape(s_1, s_2) \triangleq \begin{cases} - \Tstringchar(10) & s_1 = \texttt{\textbackslash\;\;n}\\ - \Tstringchar(9) & s_1 = \texttt{\textbackslash\;\;t}\\ - \Tstringchar(34) & s_1 = \texttt{\textbackslash\;\;"}\\ - \Tstringchar(92) & s_1 = \texttt{\textbackslash\;\;\textbackslash}\\ -\end{cases} -\] -returns the ASCII character for the corresponding escape string, in decimal encoding, -as a $\Tstringchar$ token, which is added to the characters that make up the final string -literal. - -\item -\hypertarget{def-stringfinish}{} -The lexeme action -\[ -\stringfinish(s_1, s_2) \triangleq \Tstringend -\] -signals that the string literal has ended, which makes $\scanstring$ -switch to scanning via $\aslscan$ and $\spectoken$. -\end{itemize} - -\hypertarget{def-specstring}{} -The lexical specification for string literals --- $\specstring$ --- is given by the following table: - -\begin{center} -\begin{tabular}{ll} -\textbf{Lexical Regular Expression} & \textbf{Lexeme Action}\\ -\hline -$\underbracket{\backslash\ }$ \anycharacter{{\color{white}\backslash}\texttt{n }} & $\stringescape$\\ -$\underbracket{\backslash\ }$ \anycharacter{{\color{white}\backslash}\texttt{t }} & $\stringescape$\\ -$\underbracket{\backslash\ }$ \anycharacter{{\color{white}\backslash}\texttt{" }} & $\stringescape$\\ -$\underbracket{\backslash\ }$ \anycharacter{\ \backslash\ } & $\stringescape$ \\ -\anycharacter{{\color{white}\backslash}\texttt{" }} & $\stringfinish$\\ -$\REchar$ & $\stringchar$\\ -\hline -\end{tabular} -\end{center} - -\subsection{Scanning Multi-line Comments} -The lexeme action -\hypertarget{def-discardcommentchar}{} -\[ -\discardcommentchar(s_1, s_2) \triangleq \aslscan(\spectoken, s_2) -\] -discards the string $s_1$ (which is always a single character) and continues scanning $s_2$ with $\speccomment$. -This is the same as $\discard$, except that $s_2$ is scanned with $\speccomment$ instead of $\spectoken$. - -\hypertarget{def-speccomment}{} -The lexical specification for multi-line comments --- $\speccomment$ --- is given by the table below. -% -Notice that here, $\actiondiscard$ below is used to discard the closing of the multi-line comment and to switch -to scanning with $\spectoken$. - -\begin{center} -\begin{tabular}{ll} -\textbf{Lexical Regular Expression} & \textbf{Lexeme Action}\\ -\hline -\texttt{"*/"} & $\actiondiscard$ \\ -$\REchar$ & $\discardcommentchar$ \\ -\hline -\end{tabular} -\end{center} - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -\chapter{ASL Concrete Syntax \label{chap:parsing}} -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - -This chapter defines the grammar of ASL. The grammar is presented via two extensions -to context-free grammars --- \emph{inlined derivations} and \emph{parametric productions}, -inspired by the Menhir Parser Generator~\cite{MenhirManual} for the OCaml language. -Those extensions can be viewed as macros over context-free grammars, which can be -expanded to yield a standard context-free grammar. - -Our definition of the grammar and description of the parsing mechanism heavily relies -on the theory of parsing via LR(1) grammars and LR(1) parser generators. -% -See ``Compilers: Principles, Techniques, and Tools''~\cite{ASU86} for a detailed -definition of LR(1) grammars and parser construction. - -The expanded context-free grammar is an LR(1) grammar, modulo shift-reduce -conflicts that are resolved via appropriate precedence definitions. -That is, given a list of token, returned from $\aslscan$, it is possible to apply -an LR(1) parser to obtain a parse tree if the list of tokens is in the formal language -of the grammar and return a parse error otherwise. - -The outline of this chapter is as follows: -\begin{itemize} - \item Definition of inlined derivations (see \secref{InlinedDerivations}) - \item Definition of parametric productions (see \secref{ParametricProductions}) - \item ASL Parametric Productions (see \secref{ASLParametricProductions}) - \item Definition of the ASL grammar (see \secref{ASLGrammar}) - \item Definition of parse trees (see \secref{ParseTrees}) - \item Definition of priority and associativity of operators (see \secref{PriorityAndAssociativity}) -\end{itemize} - -\section{Inlined Derivations \label{sec:InlinedDerivations}} -Context-free grammars consist of a list of \emph{derivations} $N \derives S^*$ -where $N$ is a non-terminal symbol and $S$ is a list of non-terminal symbols and terminal symbols, -which correspond to tokens. -We refer to a list of such symbols as a \emph{sentence}. -A special form of a sentence is the \emph{empty sentence}, written $\emptysentence$. - -As commonly done, we aggregate all derivations associated with the same non-terminal symbol -by writing $N \derives R_1 \;|\; \ldots \;|\; R_k$. -We refer to the right-hand-side sentences $R_{1..k}$ as the \emph{alternatives} of $N$. - -Our grammar contains another form of derivation --- \emph{inlined derivation} --- -written as $N \derivesinline R_1 \;|\; \ldots \;|\; R_k$. -Expanding an inlined derivation consists of replacing each instance of $N$ -in a right-hand-side sentence of a derivation with each of $R_{1..k}$, thereby -creating $k$ variations of it (and removing $N \derivesinline R_1 \;|\; \ldots \;|\; R_k$ -from the set of derivations). - -For example, consider the derivation -\begin{flalign*} -\Nexpr \derives\ & \Nexpr \parsesep \Nbinop \parsesep \Nexpr & -\end{flalign*} -coupled with the derivation -\begin{flalign*} -\Nbinop \derives\ & \Tand \;|\; \Tband \;|\; \Tbor \;|\; \Tbeq \;|\; \Tdiv \;|\; \Tdivrm \;|\; \Txor \;|\; \Teqop \;|\; \Tneq &\\ - |\ & \Tgt \;|\; \Tgeq \;|\; \Timpl \;|\; \Tlt \;|\; \Tleq \;|\; \Tplus \;|\; \Tminus \;|\; \Tmod \;|\; \Tmul &\\ - |\ & \Tor \;|\; \Trdiv \;|\; \Tshl \;|\; \Tshr \;|\; \Tpow \;|\; \Tconcat -\end{flalign*} - -A grammar containing these two derivations results in shift-reduce conflicts. -Resolving these conflicts is done by associating priority levels to each of the binary operators -and creating a version of the first derivation for each binary operator: -\begin{flalign*} -\Nexpr \derives\ & \Nexpr \parsesep \Tand \parsesep \Nexpr & \\ - |\ & \Nexpr \parsesep \Tband \parsesep \Nexpr & \\ - |\ & \Nexpr \parsesep \Tbor \parsesep \Nexpr & \\ - \ldots \\ - |\ & \Nexpr \parsesep \Tconcat \parsesep \Nexpr & -\end{flalign*} - -By defining the derivations of $\Nbinop$ as inlined, we achieve the same effect more compactly: -\begin{flalign*} -\Nbinop \derivesinline\ & \Tand \;|\; \Tband \;|\; \Tbor \;|\; \Tbeq \;|\; \Tdiv \;|\; \Tdivrm \;|\; \Txor \;|\; \Teqop \;|\; \Tneq &\\ - |\ & \Tgt \;|\; \Tgeq \;|\; \Timpl \;|\; \Tlt \;|\; \Tleq \;|\; \Tplus \;|\; \Tminus \;|\; \Tmod \;|\; \Tmul &\\ - |\ & \Tor \;|\; \Trdiv \;|\; \Tshl \;|\; \Tshr \;|\; \Tpow \;|\; \Tconcat -\end{flalign*} - -Barring mutually-recursive derivations involving inlined derivations, it is possible to expand -all inlined derivations to obtain a context-free grammar without any inlined derivations. - -\section{Parametric Productions \label{sec:ParametricProductions}} -A parametric production has the form -$N(p_{1..m}) \derives R_1 \;|\; \ldots \;|\; R_k$ -where $p_{1..m}$ are place holders for grammar symbols and may appear in any of the alternatives $R_{1..k}$. -We refer to $N(p_{1..m})$ as a \emph{parametric non-terminal}. - -\newcommand\uniquesymb[1]{\textsf{unique}(#1)} -Given sentences $S_{1..m}$, we can expand $N(p_{1..m}) \derives R_1 \;|\; \ldots \;|\; R_k$ -by creating a unique symbols for $N(p_{1..m})$, denoted as $\uniquesymb{N(S_{1..m})}$, defining the -derivations -\[ - \uniquesymb{N(S_{1..m})} \derives R_1[S_1/p_1,\ldots,S_m/p_m] \;|\; \ldots \;|\; R_k[S_1/p_1,\ldots,S_m/p_m] -\] -where for each $i= 1..k$, $R_i[S_1/p_1,\ldots,S_m/p_m]$ means replacing each instance of $p_j$ with $S_j$, for each $j=1..m$. -Then, each instance of $S_{1..m}$ in the grammar is replaced by $\uniquesymb{N(S_{1..m})}$. -If all instances of a parametric non-terminal are expanded this way, we can remove the derivations of the parametric -non-terminal altogether. - -We note that a parametric production can be either a normal derivation or an inlined derivation. - -For example, the derivation for a list of ASL global declarations is as follows: -\begin{flalign*} -\Nast \derives\ & \maybeemptylist{\Ndecl} & -\end{flalign*} -It is defined via the parametric production for possibly-empty lists: -\begin{flalign*} -\maybeemptylist{x} \derives\ & \emptysentence \;|\; x \parsesep \maybeemptylist{x} &\\ -\end{flalign*} - -\newcommand\Ndecllist[0]{\nonterminal{decl\_list}} -Expanding $\maybeemptylist{\Ndecl}$ produces the following derivations for a new unique symbol. -That is, a symbol that does not appear anywhere else in the grammar. -In this example we will choose $\uniquesymb{\maybeemptylist{\Ndecl}}$ the be the symbol $\Ndecllist$. -The result of the expansion is then: -\begin{flalign*} -\Ndecllist \derives\ & \emptysentence \;|\; \Ndecl \parsesep \Ndecllist &\\ -\end{flalign*} -The new symbol is substituted anywhere $\maybeemptylist{\Ndecl}$ appears in the original grammar, -which results in the following derivation replacing the original derivation for $\Nast$: -\begin{flalign*} -\Nast \derives\ & \Ndecllist & -\end{flalign*} - -% For example, -% \[ -% \option{x} \derives \emptysentence \;|\; x -% \] -% is useful for compactly defining derivations where part of a sentence may or may not appear. - -% Suppose we have -% \[ -% B \derives a \parsesep \option{A \parsesep b} -% \] -% then expanding the instance $\option{A, b}$ produces -% \[ -% \uniquesymb{\option{A \parsesep b}} \derives \emptysentence \;|\; A \parsesep b -% \] -% since $x[A \parsesep b/x]$ yields $A \parsesep b$ and $\emptysentence[A \parsesep b/x]$ yields $\emptysentence$, -% and the derivations for $B$ are replaced by -% \[ -% B \derives a \parsesep \uniquesymb{\option{A \parsesep b}} -% \] - -Expanding all instances of parametric productions results in a grammar without any parametric productions. - -\section{ASL Parametric Productions \label{sec:ASLParametricProductions}} -We define the following parametric productions for various types of lists and optional productions. - -\paragraph{Optional Symbol} -\hypertarget{def-option}{} -\begin{flalign*} -\option{x} \derives\ & \emptysentence \;|\; x &\\ -\end{flalign*} - -\paragraph{Possibly-empty List} -\hypertarget{def-maybeemptylist}{} -\begin{flalign*} -\maybeemptylist{x} \derives\ & \emptysentence \;|\; x \parsesep \maybeemptylist{x} &\\ -\end{flalign*} - -\paragraph{Non-empty List} -\hypertarget{def-nonemptylist}{} -\begin{flalign*} -\nonemptylist{x} \derives\ & x \;|\; x \parsesep \nonemptylist{x}&\\ -\end{flalign*} - -\paragraph{Non-empty Comma-separated List} -\hypertarget{def-nclist}{} -\begin{flalign*} -\NClist{x} \derives\ & x \;|\; x \parsesep \Tcomma \parsesep \NClist{x} &\\ -\end{flalign*} - -\paragraph{Possibly-empty Comma-separated List} -\hypertarget{def-clist}{} -\begin{flalign*} -\Clist{x} \derivesinline\ & \emptysentence \;|\; \NClist{x} &\\ -\end{flalign*} - -\paragraph{Comma-separated List With At Least Two Elements} -\hypertarget{def-clisttwo}{} -\begin{flalign*} -\Clisttwo{x} \derivesinline\ & x \parsesep \Tcomma \parsesep \NClist{x} &\\ -\end{flalign*} - -\paragraph{Possibly-empty Parenthesized, Comma-separated List} -\hypertarget{def-plist}{} -\begin{flalign*} -\Plist{x} \derivesinline\ & \Tlpar \parsesep \Clist{x} \parsesep \Trpar &\\ -\end{flalign*} - -\paragraph{Parenthesized Comma-separated List With At Least Two Elements} -\hypertarget{def-plisttwo}{} -\begin{flalign*} -\Plisttwo{x} \derivesinline\ & \Tlpar \parsesep x \parsesep \Tcomma \parsesep \NClist{x} \parsesep \Trpar &\\ -\end{flalign*} - -\paragraph{Non-empty Comma-separated Trailing List} -\hypertarget{def-tclist}{} -\begin{flalign*} -\NTClist{x} \derives\ & x \parsesep \option{\Tcomma} &\\ - |\ & x \parsesep \Tcomma \parsesep \NTClist{x} -\end{flalign*} - -\paragraph{Comma-separated Trailing List} -\hypertarget{def-tclist}{} -\begin{flalign*} -\TClist{x} \derivesinline\ & \option{\NTClist{x}} &\\ -\end{flalign*} - -\section{ASL Grammar \label{sec:ASLGrammar}} -We now present the list of derivations for the ASL Grammar where the start non-terminal is $\Nast$. -% -The derivations allow certain parse trees where lists may have invalid sizes. -Those parse trees must be rejected in a later phase. - -Notice that two of the derivations (for $\Nexprpattern$ and for $\Nexpr$) end with \\ -$\precedence{\Tunops}$. -This is a precedence annotation, which is not part of the right-hand-side sentence, and is explained in \secref{PriorityAndAssociativity} -and can be ignored upon first reading. - -For brevity, tokens are presented via their label only, dropping their associated value. -For example, instead of $\Tidentifier(\id)$, we simply write $\Tidentifier$. - -\hypertarget{def-nast}{} -\begin{flalign*} -\Nast \derives\ & \productionname{ast}{ast}\ \maybeemptylist{\Ndecl} & -\end{flalign*} - -\hypertarget{def-ndecl}{} -\hypertarget{def-funcdecl}{} -\begin{flalign*} -\Ndecl \derivesinline\ & \productionname{funcdecl}{func\_decl}\ \Tfunc \parsesep \Tidentifier \parsesep \Nparamsopt \parsesep \Nfuncargs \parsesep \Nreturntype \parsesep \Nfuncbody & -\hypertarget{def-proceduredecl}{}\\ -|\ & \productionname{proceduredecl}{procedure\_decl}\ \Tfunc \parsesep \Tidentifier \parsesep \Nparamsopt \parsesep \Nfuncargs \parsesep \Nfuncbody & -\hypertarget{def-getter}{}\\ -|\ & \productionname{getter}{getter}\ \Tgetter \parsesep \Tidentifier \parsesep \Nparamsopt \parsesep \Naccessargs \parsesep \Nreturntype \parsesep \Nfuncbody& -\hypertarget{def-noarggetter}{}\\ -|\ & \productionname{noarggetter}{no\_arg\_getter}\ \Tgetter \parsesep \Tidentifier \parsesep \Nreturntype \parsesep \Nfuncbody & -\hypertarget{def-setter}{}\\ -|\ & \productionname{setter}{setter}\ \Tsetter \parsesep \Tidentifier \parsesep \Nparamsopt \parsesep \Naccessargs \parsesep \Teq \parsesep \Ntypedidentifier & \\ - & \wrappedline\ \parsesep \Nfuncbody & -\hypertarget{def-noargsetter}{}\\ -|\ & \productionname{noargsetter}{no\_arg\_setter}\ \Tsetter \parsesep \Tidentifier \parsesep \Teq \parsesep \Ntypedidentifier \parsesep \Nfuncbody& -\hypertarget{def-typedecl}{}\\ -|\ & \productionname{typedecl}{type\_decl}\ \Ttype \parsesep \Tidentifier \parsesep \Tof \parsesep \Ntydecl \parsesep \Nsubtypeopt \parsesep \Tsemicolon& -\hypertarget{def-subtypedecl}{}\\ -|\ & \productionname{subtypedecl}{subtype\_decl}\ \Ttype \parsesep \Tidentifier \parsesep \Nsubtype \parsesep \Tsemicolon& -\hypertarget{def-globalstorage}{}\\ -|\ & \productionname{globalstorage}{global\_storage}\ \Nstoragekeyword \parsesep \Nignoredoridentifier \parsesep \option{\Tcolon \parsesep \Nty} \parsesep \Teq \parsesep &\\ - & \wrappedline\ \Nexpr \parsesep \Tsemicolon & -\hypertarget{def-globaluninitvar}{}\\ -|\ & \productionname{globaluninitvar}{global\_uninit\_var}\ \Tvar \parsesep \Nignoredoridentifier \parsesep \Tcolon \parsesep \Nty \parsesep \Tsemicolon& -\hypertarget{def-globalpragma}{}\\ -|\ & \productionname{globalpragma}{global\_pragma}\ \Tpragma \parsesep \Tidentifier \parsesep \Clist{\Nexpr} \parsesep \Tsemicolon& -\end{flalign*} - -\hypertarget{def-nsubtype}{} -\begin{flalign*} -\Nsubtype \derivesinline\ & \Tsubtypes \parsesep \Tidentifier \parsesep \Twith \parsesep \Nfields &\\ - |\ & \Tsubtypes \parsesep \Tidentifier &\\ -\end{flalign*} - -\hypertarget{def-nsubtypeopt}{} -\begin{flalign*} -\Nsubtypeopt \derivesinline\ & \option{\Nsubtype} & -\end{flalign*} - -\hypertarget{def-ntypedidentifier}{} -\begin{flalign*} -\Ntypedidentifier \derivesinline\ & \Tidentifier \parsesep \Nasty & -\end{flalign*} - -\hypertarget{def-nopttypeidentifier}{} -\begin{flalign*} -\Nopttypedidentifier \derivesinline\ & \Tidentifier \parsesep \option{\Nasty} & -\end{flalign*} - -\hypertarget{def-nasty}{} -\begin{flalign*} -\Nasty \derivesinline\ & \Tcolon \parsesep \Nty & -\end{flalign*} - -\hypertarget{def-nreturntype}{} -\begin{flalign*} -\Nreturntype \derivesinline\ & \Tarrow \parsesep \Nty & -\end{flalign*} - -\hypertarget{def-nparamsopt}{} -\begin{flalign*} -\Nparamsopt \derivesinline\ & \emptysentence &\\ - |\ & \Tlbrace \parsesep \Clist{\Nopttypedidentifier} \parsesep \Trbrace & -\end{flalign*} - -\hypertarget{def-naccessargs}{} -\begin{flalign*} -\Naccessargs \derivesinline\ & \Tlbracket \parsesep \Clist{\Ntypedidentifier} \parsesep \Trbracket & -\end{flalign*} - -\hypertarget{def-nfuncargs}{} -\begin{flalign*} -\Nfuncargs \derivesinline\ & \Tlpar \parsesep \Clist{\Ntypedidentifier} \parsesep \Trpar & -\end{flalign*} - -\hypertarget{def-nmaybeemptystmtlist}{} -\begin{flalign*} -\Nmaybeemptystmtlist \derivesinline\ & \emptysentence \;|\; \Nstmtlist & -\end{flalign*} - -\hypertarget{def-nfuncbody}{} -\begin{flalign*} -\Nfuncbody \derivesinline\ & \Tbegin \parsesep \Nmaybeemptystmtlist \parsesep \Tend & -\end{flalign*} - -\hypertarget{def-nignoredoridentifier}{} -\begin{flalign*} -\Nignoredoridentifier \derivesinline\ & \Tminus \;|\; \Tidentifier & -\end{flalign*} - -\vspace*{-\baselineskip} -\paragraph{Parsing note:} $\Tvar$ is not derived by $\Nlocaldeclkeyword$ to avoid an LR(1) conflict. -\hypertarget{def-nlocaldeclkeyword}{} -\begin{flalign*} -\Nlocaldeclkeyword \derivesinline\ & \Tlet \;|\; \Tconstant& -\end{flalign*} - -\hypertarget{def-nstoragekeyword}{} -\begin{flalign*} -\Nstoragekeyword \derivesinline\ & \Tlet \;|\; \Tconstant \;|\; \Tvar \;|\; \Tconfig& -\end{flalign*} - -\hypertarget{def-ndirection}{} -\begin{flalign*} -\Ndirection \derivesinline\ & \Tto \;|\; \Tdownto & -\end{flalign*} - -\hypertarget{def-nalt}{} -\begin{flalign*} -\Nalt \derivesinline\ & \Twhen \parsesep \Npatternlist \parsesep \option{\Twhere \parsesep \Nexpr} \parsesep \Tarrow \parsesep \Nstmtlist &\\ -|\ & \Totherwise \parsesep \Nstmtlist & -\end{flalign*} - -\hypertarget{def-notherwiseopt}{} -\begin{flalign*} -\Notherwiseopt \derives\ & \option{\Totherwise \parsesep \Tarrow \parsesep \Nstmtlist} & -\end{flalign*} - -\hypertarget{def-ncatcher}{} -\begin{flalign*} -\Ncatcher \derivesinline\ & \Twhen \parsesep \Tidentifier \parsesep \Tcolon \parsesep \Nty \parsesep \Tarrow \parsesep \Nstmtlist &\\ - |\ & \Twhen \parsesep \Nty \parsesep \Tarrow \parsesep \Nstmtlist &\\ -\end{flalign*} - -\hypertarget{def-nstmt}{} -\begin{flalign*} -\Nstmt \derivesinline\ & \Tif \parsesep \Nexpr \parsesep \Tthen \parsesep \Nstmtlist \parsesep \Nselse \parsesep \Tend &\\ -|\ & \Tcase \parsesep \Nexpr \parsesep \Tof \parsesep \nonemptylist{\Nalt} \parsesep \Tend &\\ -|\ & \Twhile \parsesep \Nexpr \parsesep \Tdo \parsesep \Nstmtlist \parsesep \Tend &\\ -|\ & \Tlooplimit \parsesep \Tlpar \parsesep \Nexpr \parsesep \Trpar \parsesep \Twhile \parsesep \Nexpr \parsesep \Tdo \parsesep \Nstmtlist \parsesep \Tend &\\ -|\ & \Tfor \parsesep \Tidentifier \parsesep \Teq \parsesep \Nexpr \parsesep \Ndirection \parsesep - \Nexpr \parsesep \Tdo \parsesep \Nstmtlist \parsesep \Tend &\\ -|\ & \Ttry \parsesep \Nstmtlist \parsesep \Tcatch \parsesep \nonemptylist{\Ncatcher} \parsesep \Notherwiseopt \parsesep \Tend &\\ -|\ & \Tpass \parsesep \Tsemicolon &\\ -|\ & \Treturn \parsesep \option{\Nexpr} \parsesep \Tsemicolon &\\ -|\ & \Tidentifier \parsesep \Plist{\Nexpr} \parsesep \Tsemicolon &\\ -|\ & \Tassert \parsesep \Nexpr \parsesep \Tsemicolon &\\ -|\ & \Nlocaldeclkeyword \parsesep \Ndeclitem \parsesep \Teq \parsesep \Nexpr \parsesep \Tsemicolon &\\ -|\ & \Nlexpr \parsesep \Teq \parsesep \Nexpr \parsesep \Tsemicolon &\\ -|\ & \Tvar \parsesep \Ndeclitem \parsesep \option{\Teq \parsesep \Nexpr} \parsesep \Tsemicolon &\\ -|\ & \Tvar \parsesep \Clisttwo{\Tidentifier} \parsesep \Tcolon \parsesep \Nty \parsesep \Tsemicolon &\\ -|\ & \Tprint \parsesep \Plist{\Nexpr} \parsesep \Tsemicolon &\\ -%|\ & \Tdebug \parsesep \Plist{\Nexpr} \parsesep \Tsemicolon &\\ -|\ & \Trepeat \parsesep \Nstmtlist \parsesep \Tuntil \parsesep \Nexpr \parsesep \Tsemicolon &\\ -|\ & \Tlooplimit \parsesep \Tlpar \parsesep \Nexpr \parsesep \Trpar \parsesep \Trepeat \parsesep \Nstmtlist \parsesep \Tuntil \parsesep \Nexpr \parsesep \Tsemicolon &\\ -|\ & \Tthrow \parsesep \Nexpr \parsesep \Tsemicolon &\\ -|\ & \Tthrow \parsesep \Tsemicolon &\\ -|\ & \Tpragma \parsesep \Tidentifier \parsesep \Clist{\Nexpr} \parsesep \Tsemicolon & -\end{flalign*} - -\hypertarget{def-nstmtlist}{} -\begin{flalign*} -\Nstmtlist \derivesinline\ & \nonemptylist{\Nstmt} & -\end{flalign*} - -\hypertarget{def-nselse}{} -\begin{flalign*} -\Nselse \derives\ & \Telseif \parsesep \Nexpr \parsesep \Tthen \parsesep \Nstmtlist \parsesep \Nselse &\\ -|\ & \Tpass &\\ -|\ & \Telse \parsesep \Nstmtlist & -\end{flalign*} - -\hypertarget{def-nlexpr}{} -\begin{flalign*} -\Nlexpr \derivesinline\ & \Nlexpratom &\\ -|\ & \Tminus &\\ -|\ & \Tlpar \parsesep \NClist{\Nlexpr} \parsesep \Trpar & -\end{flalign*} - -\hypertarget{def-nlexpratom}{} -\begin{flalign*} -\Nlexpratom \derives\ & \Tidentifier &\\ -|\ & \Nlexpratom \parsesep \Nslices &\\ -|\ & \Nlexpratom \parsesep \Tdot \parsesep \Tidentifier{\field} &\\ -|\ & \Nlexpratom \parsesep \Tdot \parsesep \Tlbracket \parsesep \Clist{{\Tidentifier}} \parsesep \Trbracket &\\ -|\ & \Tlbracket \parsesep \NClist{{\Nlexpratom}} \parsesep \Trbracket & -\end{flalign*} - -A $\Ndeclitem$ is another kind of left-hand-side expression, -which appears only in declarations. It cannot have setter calls or set record fields, -it must declare a new variable. -\hypertarget{def-ndeclitem}{} -\begin{flalign*} -\Ndeclitem \derives\ & \Nuntypeddeclitem \parsesep \Nasty&\\ -|\ & \Nuntypeddeclitem & -\end{flalign*} - -\hypertarget{def-nuntypeddeclitem}{} -\begin{flalign*} -\Nuntypeddeclitem \derivesinline\ & \Tidentifier &\\ -|\ & \Tminus &\\ -|\ & \Plisttwo{\Ndeclitem} & -\end{flalign*} - -\hypertarget{def-nintconstraints}{} -\begin{flalign*} -\Nintconstraints \derivesinline\ & \Tlbrace \parsesep \NClist{\Nintconstraint} \parsesep \Trbrace & -\end{flalign*} - -\hypertarget{def-nintconstraintsopt}{} -\begin{flalign*} -\Nintconstraintsopt \derivesinline\ & \Nintconstraints \;|\; \emptysentence & -\end{flalign*} - -\hypertarget{def-nintconstraint}{} -\begin{flalign*} -\Nintconstraint \derivesinline\ & \Nexpr &\\ -|\ & \Nexpr \parsesep \Tslicing \parsesep \Nexpr & -\end{flalign*} - -Pattern expressions ($\Nexprpattern$), given by the following derivations, is similar to regular expressions ($\Nexpr$), -except they do not derive tuples, which are the last derivation for $\Nexpr$. - -\hypertarget{def-nexprpattern}{} -\begin{flalign*} -\Nexprpattern \derives\ & \Nvalue &\\ - |\ & \Tidentifier &\\ - |\ & \Nexprpattern \parsesep \Nbinop \parsesep \Nexpr &\\ - |\ & \Nunop \parsesep \Nexpr & \precedence{\Tunops}\\ - |\ & \Tif \parsesep \Nexpr \parsesep \Tthen \parsesep \Nexpr \parsesep \Neelse &\\ - |\ & \Tidentifier \parsesep \Plist{\Nexpr} &\\ - |\ & \Nexprpattern \parsesep \Nslices &\\ - |\ & \Nexprpattern \parsesep \Tdot \parsesep \Tidentifier&\\ - |\ & \Nexprpattern \parsesep \Tdot \parsesep \Tlbracket \parsesep \NClist{\Tidentifier} \parsesep \Trbracket &\\ - |\ & \Tlbracket \parsesep \NClist{\Nexpr} \parsesep \Trbracket &\\ - |\ & \Nexprpattern \parsesep \Tas \parsesep \Nty &\\ - |\ & \Nexprpattern \parsesep \Tas \parsesep \Nintconstraints &\\ - |\ & \Nexprpattern \parsesep \Tin \parsesep \Npatternset &\\ - |\ & \Nexprpattern \parsesep \Tin \parsesep \Tmasklit &\\ - |\ & \Tunknown \parsesep \Tcolon \parsesep \Nty &\\ - |\ & \Tidentifier \parsesep \Tlbrace \parsesep \Clist{\Nfieldassign} \parsesep \Trbrace &\\ - |\ & \Tlpar \parsesep \Nexprpattern \parsesep \Trpar & -\end{flalign*} - -\hypertarget{def-npatternset}{} -\begin{flalign*} -\Npatternset \derivesinline\ & \Tbnot \parsesep \Tlbrace \parsesep \Npatternlist \parsesep \Trbrace &\\ - |\ & \Tlbrace \parsesep \Npatternlist \parsesep \Trbrace & -\end{flalign*} - -\hypertarget{def-npatternlist}{} -\begin{flalign*} -\Npatternlist \derivesinline\ & \NClist{\Npattern} & -\end{flalign*} - -\hypertarget{def-npattern}{} -\begin{flalign*} -\Npattern \derives\ & \Nexprpattern &\\ - |\ & \Nexprpattern \parsesep \Tslicing \parsesep \Nexpr &\\ - |\ & \Tminus &\\ - |\ & \Tleq \parsesep \Nexpr &\\ - |\ & \Tgeq \parsesep \Nexpr &\\ - |\ & \Tmasklit &\\ - |\ & \Plisttwo{\Npattern} &\\ - |\ & \Npatternset & -\end{flalign*} - -\hypertarget{def-nfields}{} -\begin{flalign*} -\Nfields \derivesinline\ & \Tlbrace \parsesep \TClist{\Ntypedidentifier} \parsesep \Trbrace & -\end{flalign*} - -\hypertarget{def-nfieldsopt}{} -\begin{flalign*} -\Nfieldsopt \derivesinline\ & \Nfields \;|\; \emptysentence & -\end{flalign*} - -\hypertarget{def-nnslices}{} -\begin{flalign*} -\Nnslices \derivesinline\ & \Tlbracket \parsesep \NClist{\Nslice} \parsesep \Trbracket & -\end{flalign*} - -\hypertarget{def-nslices}{} -\begin{flalign*} -\Nslices \derivesinline\ & \Tlbracket \parsesep \Clist{\Nslice} \parsesep \Trbracket & -\end{flalign*} - -\hypertarget{def-nslice}{} -\begin{flalign*} -\Nslice \derivesinline\ & \Nexpr &\\ - |\ & \Nexpr \parsesep \Tcolon \parsesep \Nexpr &\\ - |\ & \Nexpr \parsesep \Tpluscolon \parsesep \Nexpr &\\ - |\ & \Nexpr \parsesep \Tstarcolon \parsesep \Nexpr & -\end{flalign*} - -\hypertarget{def-nbitfields}{} -\begin{flalign*} -\Nbitfields \derivesinline\ & \Tlbrace \parsesep \TClist{\Nbitfield} \parsesep \Trbrace & -\end{flalign*} - -\hypertarget{def-nbitfield}{} -\begin{flalign*} -\Nbitfield \derivesinline\ & \Nnslices \parsesep \Tidentifier &\\ - |\ & \Nnslices \parsesep \Tidentifier \parsesep \Nbitfields &\\ - |\ & \Nnslices \parsesep \Tidentifier \parsesep \Tcolon \parsesep \Nty & -\end{flalign*} - -\hypertarget{def-nty}{} -\begin{flalign*} -\Nty \derives\ & \Tinteger \parsesep \option{\Nintconstraints} &\\ - |\ & \Treal &\\ - |\ & \Tboolean &\\ - |\ & \Tstring &\\ - |\ & \Tbit &\\ - |\ & \Tbits \parsesep \Tlpar \parsesep \Nexpr \parsesep \Trpar \parsesep \maybeemptylist{\Nbitfields} &\\ - |\ & \Plist{\Nty} &\\ - |\ & \Tidentifier &\\ - |\ & \Tarray \parsesep \Tlbracket \parsesep \Nexpr \parsesep \Trbracket \parsesep \Tof \parsesep \Nty & -\end{flalign*} - -\hypertarget{def-ntydecl}{} -\begin{flalign*} -\Ntydecl \derives\ & \Nty &\\ - |\ & \Tenumeration \parsesep \Tlbrace \parsesep \NTClist{\Tidentifier} \parsesep \Trbrace &\\ - |\ & \Trecord \parsesep \Nfieldsopt &\\ - |\ & \Texception \parsesep \Nfieldsopt & -\end{flalign*} - -\hypertarget{def-nfieldassign}{} -\begin{flalign*} -\Nfieldassign \derivesinline\ & \Tidentifier \parsesep \Teq \parsesep \Nexpr & -\end{flalign*} - -\hypertarget{def-neelse}{} -\begin{flalign*} -\Neelse \derives\ & \Telse \parsesep \Nexpr &\\ - |\ & \Telseif \parsesep \Nexpr \parsesep \Tthen \parsesep \Nexpr \parsesep \Neelse & -\end{flalign*} - -\hypertarget{def-nexpr}{} -\begin{flalign*} -\Nexpr \derives\ & \Nvalue &\\ - |\ & \Tidentifier &\\ - |\ & \Nexpr \parsesep \Nbinop \parsesep \Nexpr &\\ - |\ & \Nunop \parsesep \Nexpr & \precedence{\Tunops}\\ - |\ & \Tif \parsesep \Nexpr \parsesep \Tthen \parsesep \Nexpr \parsesep \Neelse &\\ - |\ & \Tidentifier \parsesep \Plist{\Nexpr} &\\ - |\ & \Nexpr \parsesep \Nslices &\\ - |\ & \Nexpr \parsesep \Tdot \parsesep \Tidentifier&\\ - |\ & \Nexpr \parsesep \Tdot \parsesep \Tlbracket \parsesep \NClist{\Tidentifier} \parsesep \Trbracket &\\ - |\ & \Tlbracket \parsesep \NClist{\Nexpr} \parsesep \Trbracket &\\ - |\ & \Nexpr \parsesep \Tas \parsesep \Nty &\\ - |\ & \Nexpr \parsesep \Tas \parsesep \Nintconstraints &\\ - |\ & \Nexpr \parsesep \Tin \parsesep \Npatternset &\\ - |\ & \Nexpr \parsesep \Tin \parsesep \Tmasklit &\\ - |\ & \Tunknown \parsesep \Tcolon \parsesep \Nty &\\ - |\ & \Tidentifier \parsesep \Tlbrace \parsesep \Clist{\Nfieldassign} \parsesep \Trbrace &\\ - |\ & \Tlpar \parsesep \Nexpr \parsesep \Trpar &\\ - |\ & \Plisttwo{\Nexpr} & -\end{flalign*} - -\hypertarget{def-nvalue}{} -\begin{flalign*} -\Nvalue \derivesinline\ & \Tintlit &\\ - |\ & \Tboollit &\\ - |\ & \Treallit &\\ - |\ & \Tbitvectorlit &\\ - |\ & \Tstringlit & -\end{flalign*} - -\hypertarget{def-nunop}{} -\begin{flalign*} -\Nunop \derivesinline\ & \Tbnot \;|\; \Tminus \;|\; \Tnot & -\end{flalign*} - -\hypertarget{def-nbinop}{} -\begin{flalign*} -\Nbinop \derivesinline\ & \Tand \;|\; \Tband \;|\; \Tbor \;|\; \Tbeq \;|\; \Tdiv \;|\; \Tdivrm \;|\; \Txor \;|\; \Teqop \;|\; \Tneq &\\ - |\ & \Tgt \;|\; \Tgeq \;|\; \Timpl \;|\; \Tlt \;|\; \Tleq \;|\; \Tplus \;|\; \Tminus \;|\; \Tmod \;|\; \Tmul &\\ - |\ & \Tor \;|\; \Trdiv \;|\; \Tshl \;|\; \Tshr \;|\; \Tpow \;|\; \Tconcat -\end{flalign*} - -\section{Parse Trees \label{sec:ParseTrees}} -We now define \emph{parse trees} for the ASL expanded grammar. Those are later used for build Abstract Syntax Trees. - -\begin{definition}[Parse Trees] -A \emph{parse tree} has one of the following forms: -\begin{itemize} - \item A \emph{token node}, given by the token itself, for example, $\Tlexeme(\Tarrow)$ and $\Tidentifier(\id)$; - \item \hypertarget{def-epsilonnode}{} $\epsilonnode$, which represents the empty sentence --- $\emptysentence$. - \item A \emph{non-terminal node} of the form $N(n_{1..k})$ where $N$ is a non-terminal symbol, - which is said to label the node, - and $n_{1..k}$ are its children parse nodes, - for example, - $\Ndecl(\Tfunc, \Tidentifier(\id), \Nparamsopt, \Nfuncargs, \Nfuncbody)$ - is labeled by $\Ndecl$ and has five children nodes. -\end{itemize} -\end{definition} -(In the literature, parse trees are also referred to as \emph{derivation trees}.) - -\begin{definition}[Well-formed Parse Trees] -A parse tree is \emph{well-formed} if its root is labelled by the start non-terminal ($\Nast$ for ASL) -and each non-terminal node $N(n_{1..k})$ corresponds to a grammar derivation -$N \derives l_{1..k}$ where $l_i$ is the label of node $n_i$ if it is a non-terminal node and $n_i$ -itself when it is a token. -A non-terminal node $N(\epsilonnode)$ is well-formed if the grammar includes a derivation -$N \derives \emptysentence$. -\end{definition} - -\hypertarget{def-yield}{} -\begin{definition}[Parse Tree Yield] -The \emph{\yield} of a parse tree is the list of tokens -given by an in-order walk of the tree: -\[ -\yield(n) \triangleq \begin{cases} - [t] & n \text{ is a token }t\\ - \emptylist & n = \epsilonnode\\ - \yield(n_1) \concat \ldots \concat \yield(n_k) & n = N(n_{1..k})\\ -\end{cases} -\] -\end{definition} - -\hypertarget{def-parsenode}{} -We denote the set of well-formed parse trees for a non-terminal symbol $S$ by $\parsenode{S}$. - -\hypertarget{def-aslparse}{} -A parser is a function -\[ -\aslparse : (\Token^* \setminus \{\Terror\}) \aslto \parsenode{\Nast} \cup \{\ParseError\} -\] -\hypertarget{def-parseerror}{} -where $\ParseError$ stands for a \emph{parse error}. -If $\aslparse(\ts) = n$ then $\yield(n)=\ts$ -and if $\aslparse(\ts) = \ParseError$ then there is no well-formed tree -$n$ such that $\yield(n)=\ts$. -(Notice that we do not define a parser if $\ts$ is lexically illegal.) - -The \emph{language of a grammar} $G$ is defined as follows: -\[ -\Lang(G) = \{\yield(n) \;|\; n \text{ is a well-formed parse tree for }G\} \enspace. -\] - -\section{Priority and Associativity \label{sec:PriorityAndAssociativity}} -A context-free grammar $G$ is \emph{ambiguous} if there can be more than one parse tree for a given list of tokens -$\ts \in \Lang(G)$. -Indeed the expanded ASL grammar is ambiguous, for example, due to its definition of binary operation expressions. -To allow assigning a unique parse tree to each sequence of tokens in the language of the ASL grammar, -we utilize the standard technique of associating priority levels to productions and using them to resolve -any shift-reduce conflicts in the LR(1) parser associated with our grammar (our grammar does not have any -reduce-reduce conflicts). - -The priority of a grammar derivation is defined as the priority of its rightmost token. -Derivations that do not contain tokens do not require a priority as they do not induce shift-reduce conflicts. - -The table below assigns priorities to tokens in increasing order, starting from the lowest priority (for $\Telse$) -to the highest priority (for $\Tdot$). -When a shift-reduce conflict arises during the LR(1) grammar construction -it resolve in favor of the action (shift or reduce) associated with the derivation that has the higher priority. -If two derivations have the same priority due to them both having the same rightmost token, -the conflict is resolved based on the associativity associated with the token below: -reduce for $\leftassoc$, shift for $\rightassoc$, and a parsing error for $\nonassoc$. - -The two rules involving a unary minus operation are not assigned the priority level of $\Tminus$, -but rather then the priority level $\Tunops$, as denoted by the notation \\ -$\precedence{\Tunops}$ -appearing to their right. This is a standard way of dealing with a unary minus operation -in many programming languages, which involves defining an artificial token $\Tunops$, -which is never returned by the scanner. - -\begin{center} -\begin{tabular}{ll} -\textbf{Terminals} & \textbf{Associativity}\\ -\hline -\Telse & \nonassoc\\ -\Tbor, \Tband, \Timpl, \Tbeq, \Tas & \leftassoc\\ -\Teqop, \Tneq & \leftassoc\\ -\Tgt, \Tgeq, \Tlt, \Tleq & \nonassoc\\ -\Tplus, \Tminus, \Tor, \Txor, \Tand & \leftassoc\\ -\Tmul, \Tdiv, \Tdivrm, \Trdiv, \Tmod, \Tshl, \Tshr & \leftassoc\\ -\Tpow, \Tconcat & \leftassoc\\ -$\Tunops$ & \nonassoc\\ -\Tin & \nonassoc\\ -\Tdot, \Tlbracket & \leftassoc -\end{tabular} -\end{center} - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -\chapter{ASL Abstract Syntax \label{chap:ASLAbstractSyntax}} -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -An abstract syntax is a form of context-free grammar over structured trees. -Compilers and interpreters typically start by parsing the text of a program and producing an abstract syntax tree (AST, for short), -and then continue to operate over that tree. -% -The reason for this is that abstract syntax trees abstract away details that are irrelevant to the semantics of the program, -such as punctuation and scoping syntax, which are useful for readability and parsing. - -Technically, there are two abstract syntaxes: -an \emph{untyped abstract syntax} and a \emph{typed abstract syntax}. -The first syntax results from parsing the text of an ASL specification. -The type checker checks whether the untyped AST is valid and if so produces -a typed AST where some nodes in the untyped AST have been transformed to -more explicit representation. For example, the untyped AST may contain -what looks like a slicing expression, which turns out to be a call to a getter. -The typed AST represents that call directly, making it simpler for an interpreter -to evaluate that expression. - -\paragraph{Outline} -The outline of this chapter is as follows, -We first define the type of Abstract Syntax Trees used by ASL (\secref{ASLAbstractSyntaxTrees}). -We then define the notations for defining the AST grammar used by ASL (\secref{ASLAbstractSyntaxGrammar}) -Finally, we define the AST grammar rules for the different ASL constructs along with examples: -\begin{itemize} - \item Identifiers (\secref{Identifiers}) - \item Literal values (\secref{ASTLiterals}) - \item Basic Operations (\secref{BasicOperations}) - \item Expressions (\secref{Expressions}) - \item Patterns (\secref{Patterns}) - \item Slices (\secref{Slices}) - \item Types (\secref{Types}) - \item Constraints (\secref{Constraints}) - \item Bit Fields (\secref{BitFields}) - \item Array Indices (\secref{ArrayIndices}) - \item Fields and Typed Identifiers (\secref{FieldsAndTypedIdentifiers}) - \item Left-hand Side Expressions (\secref{LeftHandSideExpressions}) - \item Local Declarations (\secref{LocalDeclarations}) - \item Statements (\secref{Statements}) - \item Case Alternatives (\secref{CaseAlternatives}) - \item Exception Catchers (\secref{ExceptionCatchers}) - \item Subprograms (\secref{Subprograms}) - \item Global Declarations (\secref{GlobalDeclarations}) - \item Specifications (\secref{Specifications}) -\end{itemize} - -\section{ASL Abstract Syntax Trees \label{sec:ASLAbstractSyntaxTrees}} - -In an ASL abstract syntax tree, a node is one the following data types: -\begin{description} -\item[Token Node.] A lexical token, denoted as in the lexical description of ASL; -\item[Label Node.] A label -\item[Unlabelled Tuple Node.] A tuple of children nodes, denoted as $(n_1,\ldots,n_k)$; -\item[Labelled Tuple Node.] A tuple labelled~$L$, denoted as~$L(n_1,\ldots,n_k)$; -\item[List Node.] A list of~$0$ or more children nodes, denoted as~$\emptylist$ - when the list is empty and~$[n_1,\ldots,n_k]$ for non-empty lists; -\item[Optional.] An optional node stands for a list of 0 or 1 occurrences of a sub-node $n$. We denote an empty optional by $\langle\rangle$ and the non-empty optional by $\langle n \rangle$; -\item[Record Node.] A record node, denoted as $\{\text{name}_1 : n_1,\ldots,\text{name}_k : n_k\}$, where \\ - $\text{name}_1 \ldots \text{name}_k$ are names, which associates names with corresponding nodes. -\end{description} - -\newpage - -\section{ASL Abstract Syntax Grammar \label{sec:ASLAbstractSyntaxGrammar}} - -An abstract syntax is defined in terms of derivation rules containing variables (also referred to as non-terminals). -% -A \emph{derivation rule} has the form $v \derives \textit{rhs}$ where $v$ is a non-terminal variable and \textit{rhs} is a \emph{node type}. We write $n$, $n_1,\ldots,n_k$ to denote node types. -% -Node types are defined recursively as follows: -\begin{description} -\item[Non-terminal.] A non-terminal variable; -\item[Terminal.] A lexical token $t$ or a label $L$; -\item[Unlabelled Tuple.] A tuple of node types, denoted as~$(n_1,\ldots,n_k)$; -\item[Labelled Tuple.] A tuple labelled~$L$, denoted as~$L(n_1,\ldots,n_k)$; -\item[List.] A list node type, denoted as $n^{*}$; -\item[Optional.] An optional node type, denoted as $n?$; -\item[Record.] A record, denoted as $\{\text{name}_1 : n_1,\ldots,\text{name}_k : n_k\}$ where $\text{name}_i$, which associates names with corresponding node types. -\end{description} - -\newpage - -An abstract syntax consists of a set of derivation rules and a start non-terminal. - -\newcommand\ASTComment[1]{//\quad\textit{#1}\ } - -\section{ASL Untyped Abstract Syntax} - -The abstract syntax of ASL is given in terms of the derivation rules below and the start non-terminal $\specification$. -% -Some extra details are given by using the notation $\overname{\textit{symbol}}{\text{detail}}$. - -\subsection{Identifiers \label{sec:Identifiers}} -\hypertarget{ast-identifier}{} -Identifiers in the AST, denoted $\identifier$ are simply strings representing ASL identifiers. -Those are obtained directly from the values of identifier tokens, $\Tidentifier(s)$. - -\subsection{Literal Values \label{sec:ASTLiterals}} -The following rules correspond to literal values of the following ASL data types: -integers, Booleans, real numbers, bitvectors, and strings. - -\begin{flalign*} -\literal \derives\ & \lint(\overname{n}{\Z}) -& \hypertarget{ast-lbool}{} -\\ - |\ & \lbool(\overname{b}{\{\True, \False\}}) - & \hypertarget{ast-lreal}{} -\\ - |\ & \lreal(\overname{q}{\Q}) - & \hypertarget{ast-lbitvector}{} -\\ - |\ & \lbitvector(\overname{B}{B \in \{0, 1\}^*}) - & \hypertarget{ast-lstring}{} -\\ - |\ & \lstring(\overname{S}{S \in \{C \;|\; \texttt{"$C$"}\ \in\ \Strings\}}) & -\end{flalign*} - -\subsection{Basic Operations \label{sec:BasicOperations}} -The following rules correspond to unary operations and binary operations that can be applied to expressions. - -\hypertarget{ast-unop}{} \hypertarget{ast-bnot}{} \hypertarget{ast-neg}{} \hypertarget{ast-not}{} -\begin{flalign*} -\unop \derives\ & \overname{\BNOT}{\texttt{"!"}} \;|\; \overname{\NEG}{\texttt{"-"}} \;|\; \overname{\NOT}{\texttt{"NOT"}} -& \hypertarget{ast-binop}{} \hypertarget{ast-bor}{} \hypertarget{ast-impl}{} \hypertarget{ast-beq}{} \hypertarget{ast-band}{} -\\ -\binop \derives\ & \overname{\BAND}{\texttt{"\&\&"}} \;|\; \overname{\BOR}{\texttt{"||"}} \;|\; \overname{\IMPL}{\texttt{"-->"}} - \;|\; \overname{\BEQ}{\texttt{"<->"}} - & \hypertarget{ast-eqop}{} \hypertarget{ast-neq}{} \hypertarget{ast-gt}{} \hypertarget{ast-geq}{} \hypertarget{ast-lt}{} \hypertarget{ast-leq}{} -\\ - |\ & \overname{\EQOP}{\texttt{"=="}} \;|\; \overname{\NEQ}{\texttt{"!="}} \;|\; \overname{\GT}{\texttt{"<"}} - \;|\; \overname{\GEQ}{\texttt{">="}} \;|\; \overname{\LT}{\texttt{"<"}} \;|\; \overname{\LEQ}{\texttt{"<="}} - & \hypertarget{ast-plus}{} \hypertarget{ast-minus}{} \hypertarget{ast-or}{} \hypertarget{ast-xor}{} \hypertarget{ast-and}{} -\\ - |\ & \overname{\PLUS}{\texttt{"+"}} \;|\; \overname{\MINUS}{\texttt{"-"}} \;|\; \overname{\OR}{\texttt{"OR"}} - \;|\; \overname{\XOR}{\texttt{"XOR"}} \;|\; \overname{\AND}{\texttt{"AND"}} - & \hypertarget{ast-mul}{} \hypertarget{ast-div}{} \hypertarget{ast-divrm}{} \hypertarget{ast-mod}{} \hypertarget{ast-shl}{} \hypertarget{ast-shr}{} -\\ - |\ & \overname{\MUL}{\texttt{"*"}} \;|\; \overname{\DIV}{\texttt{"DIV"}} \;|\; \overname{\DIVRM}{\texttt{"DIVRM"}} - \;|\; \overname{\MOD}{\texttt{"MOD"}} \;|\; \overname{\SHL}{\texttt{"<<"}} \;|\; \overname{\SHR}{\texttt{">>"}} - & \hypertarget{ast-rdiv}{} \hypertarget{ast-pow}{} -\\ - |\ & \overname{\RDIV}{\texttt{"/"}} \;|\; \overname{\POW}{\texttt{"\^{}"}} - & \hypertarget{ast-literal}{} \hypertarget{ast-lint}{} -\end{flalign*} - -\subsection{Expressions \label{sec:Expressions}} -The following rules correspond to various types of expressions: -literal expressions, variable expressions, typing assertions, binary operation expressions, unary operation expressions, -call expressions, slicing expressions, conditional expressions, single-field access expressions, multiple-field access expressions, -record and exception construction expressions, concatenation expressions, tuple expressions, unknown-value expressions, -and pattern matching expressions. - -\hypertarget{ast-expr}{} \hypertarget{ast-eliteral}{} -\begin{flalign*} -\expr \derives\ & \ELiteral(\literal) -& \hypertarget{ast-evar}{} \hypertarget{ast-identifier}{}\\ - |\ & \EVar(\overtext{\identifier}{variable name}) - &\hypertarget{ast-eatc}{}\\ - |\ & \overtext{\EATC}{Type assertion}(\expr, \overtext{\ty}{asserted type}) - &\hypertarget{ast-ebinop}{}\\ - |\ & \EBinop(\binop, \expr, \expr) - &\hypertarget{ast-eunop}{}\\ - |\ & \EUnop(\unop, \expr) - &\hypertarget{ast-ecall}{}\\ - |\ & \ECall(\overtext{\identifier}{subprogram name}, \overtext{\expr^{*}}{actual arguments}) - &\hypertarget{ast-eslice}{}\\ - |\ & \ESlice(\expr, \slice^{*}) - &\hypertarget{ast-econd}{}\\ - |\ & \ECond(\overtext{\expr}{condition}, \overtext{\expr}{then}, \overtext{\expr}{else}) - &\hypertarget{ast-egetfield}{}\\ - |\ & \EGetField(\overtext{\expr}{record}, \overtext{\identifier}{field name}) - &\hypertarget{ast-egetfields}{}\\ - |\ & \EGetFields(\overtext{\expr}{record}, \overtext{\identifier^{*}}{field names}) - &\hypertarget{ast-erecord}{}\\ - |\ & \ERecord(\overtext{\ty}{record type}, \overtext{(\identifier, \expr)^{*}}{field initializers}) - &\hypertarget{ast-econcat}{}\\ - |\ & \EConcat(\expr^{+}) - &\hypertarget{ast-etuple}{}\\ - |\ & \ETuple(\expr^{+}) - &\hypertarget{ast-eunknown}{}\\ - |\ & \EUnknown(\ty) - &\hypertarget{ast-epattern}{}\\ - |\ & \EPattern(\expr, \pattern) -\end{flalign*} - -\figref{expr1} and \figref{expr2} exemplify the different kinds of expressions, -as indicated by respective comments. -\begin{figure} -\CodeExample{\syntaxtests/expr1.asl} -\caption{Examples of expressions \label{fi:expr1}} -\end{figure} - -\begin{figure} -\CodeExample{\syntaxtests/expr2.asl} -\caption{Examples of expressions \label{fi:expr2}} -\end{figure} - -\begin{itemize} - \item $\EVar(\vx)$ represents variables (\texttt{E\_Var 1}) - as well as getters declared without a list of arguments (\texttt{E\_Var 2}). - - \item $\EATC(\ve, \vt)$ represents typing assertions. For example: \texttt{x as integer}. - Here $\ve$ corresponds to \texttt{x} and $\vt$ corresponds to \texttt{integer}. - - \item $\ESlice(\ve, \vslices)$ represents slices of bitvectors (\texttt{E\_Slice 1}), - slices of integers \\ - (\texttt{E\_Slice 2}), - calls to getters (\texttt{E\_Slice 3} and \texttt{E\_Slice 4}), - and access to array elements (\texttt{E\_Slice 5}). - - \item $\EGetField(\ve, \id)$ represents an access to a record (\texttt{E\_GetField 1}) - or exception field - as well as an access to a tuple component (\texttt{E\_GetField 2}). - - \item $\EGetFields(\ve, \ids)$ represents an access to multiple record fields (\texttt{E\_GetFields 1}). -\end{itemize} - -\subsection{Patterns \label{sec:Patterns}} - -\hypertarget{ast-pattern}{} \hypertarget{ast-patternall}{} -\begin{flalign*} -\pattern \derives\ & \PatternAll - & \hypertarget{ast-patternany}{}\\ - |\ & \PatternAny(\pattern^{*}) - & \hypertarget{ast-patterngeq}{}\\ - |\ & \PatternGeq(\expr) - & \hypertarget{ast-patternleq}{}\\ - |\ & \PatternLeq(\expr) - & \hypertarget{ast-patternmask}{}\\ - |\ & \PatternMask(\overtext{\{0,1,x\}^*}{mask constant}) - & \hypertarget{ast-patternnot}{}\\ - |\ & \PatternNot(\pattern) - & \hypertarget{ast-patternrange}{}\\ - |\ & \PatternRange(\overtext{\expr}{lower}, \overtext{\expr}{upper}) - & \hypertarget{ast-patternsingle}{}\\ - |\ & \PatternSingle(\expr) - & \hypertarget{ast-patterntuple}{}\\ - |\ & \PatternTuple(\pattern^{*}) & -\end{flalign*} - -\subsection{Slices \label{sec:Slices}} - -\hypertarget{ast-slice}{} \hypertarget{ast-slicesingle}{} -\begin{flalign*} -% &&\ASTComment{Indexes an array or a bitvector.}\\ -% &&\ASTComment{All positions mentioned below are inclusive}\\ -\slice \derives\ & \SliceSingle(\overname{\expr}{\vi}) - & \hypertarget{ast-slicerange}{}\\ - % & & \ASTComment{the slice of length \texttt{1} at position \vi.}\\ - |\ & \SliceRange(\overname{\expr}{\vj}, \overname{\expr}{\vi}) - & \hypertarget{ast-slicelength}{}\\ - % & & \ASTComment{the slice from \vi\ to \texttt{j - 1}.}\\ - |\ & \SliceLength(\overname{\expr}{\vi}, \overname{\expr}{\vn}) - & \hypertarget{ast-slicestar}{}\\ - % & & \ASTComment{the slice starting at \vi\ of length \vn.}\\ - |\ & \SliceStar(\overname{\expr}{\vi}, \overname{\expr}{\vn}) & - % & & \ASTComment{the slice starting at \texttt{i*n} of length \vn} -\end{flalign*} - -\subsection{Types \label{sec:Types}} - -\hypertarget{ast-ty}{} \hypertarget{ast-tint}{} -\begin{flalign*} -\ty \derives\ & \TInt(\intconstraints) -\hypertarget{ast-treal}{}\\ - |\ & \TReal - & \hypertarget{ast-tstring}{}\\ - |\ & \TString - & \hypertarget{ast-tbool}{}\\ - |\ & \TBool - & \hypertarget{ast-tbits}{}\\ - |\ & \TBits(\overtext{\expr}{width}, \bitfield^{*}) - & \hypertarget{ast-tenum}{}\\ - |\ & \TEnum(\overtext{\identifier^{*}}{labels}) - & \hypertarget{ast-ttuple}{}\\ - |\ & \TTuple(\ty^{*}) - & \hypertarget{ast-tarray}{}\\ - |\ & \TArray(\arrayindex, \ty) - & \hypertarget{ast-trecord}{}\\ - |\ & \TRecord(\Field^{*}) - & \hypertarget{ast-texception}{}\\ - |\ & \TException(\Field^{*}) - & \hypertarget{ast-tnamed}{}\\ - |\ & \TNamed(\overtext{\identifier}{type name}) & -% & & & \ASTComment{This is related to \identi{LDNP}} -\end{flalign*} - -\subsection{Constraints \label{sec:Constraints}} - -\hypertarget{ast-intconstraints}{} \hypertarget{ast-unconstrained}{} -\begin{flalign*} - % & & \ASTComment{Constraints that may be assigned to integer types.} \\ - \intconstraints \derives\ & \unconstrained - % & & \ASTComment{The unconstrained integer type.} - & \hypertarget{ast-wellconstrained}{}\\ - |\ & \wellconstrained(\intconstraint^{+}) - % & & \ASTComment{An integer type with explicit constraints.} - & \hypertarget{ast-parameterized}{}\\ - |\ & \parameterized(\overtext{\identifier}{parameter}) & - % & & \ASTComment{Implicitly constrained integer from function declaration.} \\ - % & & \ASTComment{Attributes are:} \\ - % & & \ASTComment{- a unique integer identifier and the variable} \\ - % & & \ASTComment{- the type was implicitly constructed from.} \\ -\end{flalign*} - -\hypertarget{ast-intconstraint}{} \hypertarget{ast-constraintexact}{} -\begin{flalign*} -% & & \ASTComment{A constraint on an integer part.}\\ -\intconstraint \derives\ & \ConstraintExact(\expr) - % & & \ASTComment{A single value, given by a statically evaluable expression.} - & \hypertarget{ast-constraintrange}{}\\ - |\ & \ConstraintRange(\expr, \expr)& - % & & \ASTComment{An interval between two statically evaluable expression.}\\ -\end{flalign*} - -\subsection{Bit Fields \label{sec:BitFields}} - -\hypertarget{ast-bitfield}{} \hypertarget{ast-bitfieldsimple}{} -\begin{flalign*} -% & & \ASTComment{Represent static slices on a given bitvector type.}\\ -\bitfield \derives\ & \BitFieldSimple(\identifier, \slice^{*}) - % & & \ASTComment{A name and its corresponding slice.} - & \hypertarget{ast-bitfieldnested}{}\\ - |\ & \BitFieldNested(\identifier, \slice^{*}, \bitfield^{*}) - % & & \ASTComment{A name, its corresponding slice and some nested bitfields.} - & \hypertarget{ast-bitfieldtype}{}\\ - |\ & \BitFieldType(\identifier, \slice^{*}, \ty) & - % & & \ASTComment{A name, its corresponding slice, and the type of the bitfield.}\\ -\end{flalign*} - -\subsection{Array Indices \label{sec:ArrayIndices}} - -\hypertarget{ast-arrayindex}{} \hypertarget{ast-arraylengthexpr}{} -The type of array indices is given by the following AST type: -\begin{flalign*} -\arrayindex \derives\ & \ArrayLengthExpr(\overtext{\expr}{array length}) & -\end{flalign*} - -% \[ -% \begin{array}{rcl} -% & & \ASTComment{The type of indexes for an array.} \\ -% \hline -% \arrayindex & \derives -% & \ArrayLengthExpr(\overtext{\expr}{array length}) -% \hypertarget{ast-arraylengthenum}{}\\ -% &|& \ArrayLengthEnum(\overtext{\identifier}{name of enumeration}, \overtext{\Z}{length}) \\ -% \end{array} -% \] - -\subsection{Fields and Typed Identifiers \label{sec:FieldsAndTypedIdentifiers}} - -The following rule corresponds to a field of a record-like structure: -\hypertarget{ast-field}{} -\begin{flalign*} -\Field \derives\ & (\identifier, \ty) & \hypertarget{ast-typedidentifier}{} -\end{flalign*} - -The following rule corresponds to an identifier with its associated type: -\hypertarget{ast-typedidentifier}{} -\begin{flalign*} -\typedidentifier \derives\ & (\identifier, \ty) & -\end{flalign*} - -\subsection{Left-hand Side Expressions \label{sec:LeftHandSideExpressions}} - -The following rules define the types of left-hand side of assignments: -\hypertarget{ast-lexpr}{} \hypertarget{ast-lediscard}{} -\begin{flalign*} -\lexpr \derives\ & \overtext{\LEDiscard}{\texttt{"-"}} &\\ - |\ & \LEVar(\identifier) & \hypertarget{ast-leslice}{}\\ - |\ & \LESlice(\lexpr, \slice^*) & \hypertarget{ast-lesetarray}{}\\ - |\ & \LESetArray(\lexpr, \expr) & \hypertarget{ast-lesetfield}{}\\ - |\ & \LESetField(\lexpr, \identifier) & \hypertarget{ast-lesetfields}{}\\ - |\ & \LESetFields(\lexpr, \identifier^*) & \hypertarget{ast-ledestructuring}{}\\ - |\ & \LEDestructuring(\lexpr^*) & \hypertarget{ast-leconcat}{}\\ - |\ & \LEConcat(\lexpr^+) &\\ -\end{flalign*} - -$\LEConcat(\texttt{les})$ represents the left-hand-side list of expressions for simultaneous assignments. - -\subsection{Local Declarations \label{sec:LocalDeclarations}} - -\hypertarget{ast-localdeclkeyword}{} \hypertarget{ast-ldkvar}{} \hypertarget{ast-ldkconstant}{} \hypertarget{ast-ldklet}{} -\begin{flalign*} -\localdeclkeyword \derives\ & \LDKVar \;|\; \LDKConstant \;|\; \LDKLet & -\end{flalign*} - -A local declaration item is the left-hand side of a declaration statements. -In the following example of a declaration statement: -\begin{verbatim} -let (x, -, z): (integer, integer, integer {0..32}) = (2, 3, 4); -\end{verbatim} -the local declaration item is -\Verb|(x, -, z): (integer, integer, integer {0..32})|. - -\hypertarget{ast-localdeclitem}{} \hypertarget{ast-ldidiscard}{} -\begin{flalign*} -\localdeclitem \derives\ & \LDIDiscard - % & & \ASTComment{The ignored local declaration item, for example used in: \Verb!let - = 42;!.} - & \hypertarget{ast-ldivar}{}\\ - |\ & \LDIVar(\identifier) - % & & \ASTComment{\texttt{LDI\_Var x} is the variable declaration of the variable \texttt{x}, used for example in:}\\ - % & & \ASTComment{\texttt{let x = 42;}.} - & \hypertarget{ast-ldituple}{}\\ - |\ & \LDITuple(\localdeclitem^*) - % & & \ASTComment{\texttt{LDI\_Tuple ldis} is the tuple declarations of the items in \texttt{ldis},}\\ - % & & \ASTComment{used for example in: \texttt{let (x, y, -, z) = (1, 2, 3, 4);}}\\ - % & & \ASTComment{Note that a the list here must be at least 2 items long.} - & \hypertarget{ast-ldityped}{}\\ - |\ & \LDITyped(\localdeclitem, \ty) & - % & & \ASTComment{\texttt{LDI\_Typed (ldi, t)} declares the item \texttt{ldi} with type \texttt{t}, used for example in:} \\ - % & & \ASTComment{\texttt{let x: integer = 4;}} -\end{flalign*} - -\subsection{Statements \label{sec:Statements}} - -\hypertarget{ast-fordirection}{} \hypertarget{ast-up}{} \hypertarget{ast-down}{} -\begin{flalign*} -\fordirection \derives\ & \UP \;|\; \DOWN &\\ -\hypertarget{ast-stmt}{} \hypertarget{ast-spass}{}\\ -\stmt \derives\ & \SPass -\hypertarget{ast-sseq}{} &\\ - |\ & \SSeq(\stmt, \stmt) - \hypertarget{ast-sdecl}{} &\\ - |\ & \SDecl(\localdeclkeyword, \localdeclitem, \expr?) - \hypertarget{ast-sassign}{} &\\ - |\ & \SAssign(\lexpr, \expr) - \hypertarget{ast-scall}{} &\\ - |\ & \SCall(\overtext{\identifier}{subprogram name}, \overtext{\expr^{*}}{actual arguments}) - \hypertarget{ast-sreturn}{} &\\ - |\ & \SReturn(\expr?) - \hypertarget{ast-scond}{} &\\ - |\ & \SCond(\expr, \stmt, \stmt) - \hypertarget{ast-scase}{} &\\ - |\ & \SCase(\expr, \casealt^*) - \hypertarget{ast-sassert}{} &\\ - |\ & \SAssert(\expr) - \hypertarget{ast-sfor}{} &\\ - |\ & \SFor\left\{ - \begin{array}{rcl} - \Forindexname &:& \identifier,\\ - \Forstarte &:& \expr,\\ - \Fordir &:& \fordirection,\\ - \Forende &:& \expr,\\ - \Forbody &:& \stmt,\\ - \Forlimit &:& \expr? - \end{array} - \right\} - \hypertarget{ast-swhile}{} &\\ - |\ & \SWhile(\overtext{\expr}{condition}, \overtext{\expr?}{loop limit}, \overtext{\stmt}{loop body}) - \hypertarget{ast-srepeat}{} &\\ - |\ & \SRepeat(\overtext{\stmt}{loop body}, \overtext{\expr}{condition}, \overtext{\expr?}{loop limit}) - \hypertarget{ast-sthrow}{} &\\ - & \ASTComment{The option represents an implicit throw: \texttt{throw;}.}\\ - |\ & \SThrow(\expr?) &\\ - \hypertarget{ast-stry}{} &\\ - |\ & \STry(\stmt, \catcher^*, \overtext{\stmt?}{otherwise}) - \hypertarget{ast-sprint}{} &\\ - |\ & \SPrint(\overtext{\expr^*}{args}, \overtext{\Bool}{debug}) -\end{flalign*} - -\subsection{Case Alternatives \label{sec:CaseAlternatives}} - -\hypertarget{ast-casealt}{} -\begin{flalign*} -\casealt \derives\ & \{ \CasePattern : \pattern, \CaseWhere : \expr?, \CaseStmt : \stmt \} & -\end{flalign*} - -\subsection{Exception Catchers \label{sec:ExceptionCatchers}} -\hypertarget{ast-catcher}{} -\begin{flalign*} -\catcher \derives\ & (\overtext{\identifier?}{exception to match}, \overtext{\ty}{guard type}, \overtext{\stmt}{statement to execute on match}) & -\end{flalign*} - -\subsection{Subprograms \label{sec:Subprograms}} -\hypertarget{ast-subprogramtype}{} \hypertarget{ast-stprocedure}{} \hypertarget{ast-stfunction}{} -\begin{flalign*} -\subprogramtype \derives\ & \STProcedure \;|\; \STFunction -\hypertarget{ast-stgetter}{} \hypertarget{ast-stemptygetter}{} &\\ - |\ & \STGetter \;|\; \STEmptyGetter - \hypertarget{ast-stsetter}{} \hypertarget{ast-stemptysetter}{} &\\ - |\ & \STSetter \;|\; \STEmptySetter & -\end{flalign*} - -\hypertarget{ast-subprogrambody}{} \hypertarget{ast-sbasl}{} -\begin{flalign*} -\subprogrambody \derives\ & \SBASL(\stmt) \hypertarget{ast-sbprimitive}{} \;|\; \SBPrimitive & -\end{flalign*} - -\hypertarget{ast-func}{} -\begin{flalign*} -\func \derives\ & -{ -\left\{ - \begin{array}{rcl} - \funcname &:& \Strings, \\ - \funcparameters &:& (\identifier, \ty?)^*,\\ - \funcargs &:& \typedidentifier^*,\\ - \funcbody &:& \subprogrambody,\\ - \funcreturntype &:& \ty?,\\ - \funcsubprogramtype &:& \subprogramtype -\end{array} -\right\} -} & -\end{flalign*} - -\subsection{Global Declarations \label{sec:GlobalDeclarations}} -Declaration keyword for global storage elements: -\hypertarget{ast-globaldeclkeyword}{} \hypertarget{ast-gdkconstant}{} \hypertarget{ast-gdkconfig}{} \hypertarget{ast-gdklet}{} \hypertarget{ast-gdkvar}{} -\begin{flalign*} -\globaldeclkeyword \derives\ & \GDKConstant \;|\; \GDKConfig \;|\; \GDKLet \;|\; \GDKVar & -\end{flalign*} - -\hypertarget{ast-globaldecl}{} -\begin{flalign*} -\globaldecl \derives\ & -{\left\{ - \begin{array}{rcl} - \GDkeyword &:& \globaldeclkeyword, \\ - \GDname &:& \identifier,\\ - \GDty &:& \ty?,\\ - \GDinitialvalue &:& \expr? - \end{array} - \right\} - } & -\end{flalign*} - -\hypertarget{ast-decl}{} -\hypertarget{ast-dfunc}{} -\begin{flalign*} -\decl \derives\ & \DFunc(\func) & \hypertarget{ast-dglobalstorage}{}\\ - |\ & \DGlobalStorage(\globaldecl) & \hypertarget{ast-dtypedecl}{}\\ - |\ & \DTypeDecl(\identifier, \ty, (\identifier, \overtext{\Field^*}{with fields})?) & -\end{flalign*} - -\subsection{Specifications \label{sec:Specifications}} -\hypertarget{ast-specification}{} -\begin{flalign*} -\specification \derives\ & \decl^* & -\end{flalign*} - -\section{ASL Typed Abstract Syntax} - -The derivation rules for the typed abstract syntax are the same as the rules for the untyped abstract syntax, -except for the following differences. - -The rules for expressions have the extra derivation rule: -\hypertarget{ast-egetarray}{} -\begin{flalign*} -\expr \derives\ & \EGetArray(\overtext{\expr}{base}, \overtext{\expr}{index}) & -\end{flalign*} - -The AST node for call expressions includes an extra component that explicitly associates expressions -with parameters: -\begin{flalign*} -\expr \derives\ & \ECall(\overtext{\identifier}{subprogram name}, \overtext{\expr^{*}}{actual arguments}, \overtext{(\identifier, \expr)^{*}}{parameters with initializers}) & -\end{flalign*} - -The AST node for a left-hand-side tuple of expressions contains a second component, which is a type annotation: -\begin{flalign*} -\lexpr \derives\ & \LEConcat(\lexpr^+, \Tintlit^+?) & -\end{flalign*} - -The rules for statements refine the throw statement by annotating it with -the type of the thrown exception. -\begin{flalign*} -\stmt \derives\ & \SThrow((\expr, \overtext{\ty}{exception type})?) & -\end{flalign*} - -Similar to expressions, the AST node for call statements includes an extra component that explicitly associates expressions -with parameters: -\begin{flalign*} -\stmt \derives\ & \SCall(\overtext{\identifier}{subprogram name}, \overtext{\expr^{*}}{actual arguments}, \overtext{(\identifier, \expr)^{*}}{parameters with initializers}) & -\end{flalign*} - -The rules for slices is replaced by the following: -\begin{flalign*} -\slice \derives\ & \SliceLength(\expr, \expr) & -\end{flalign*} -This reflects the fact that all other slicing constructs are syntactic sugar -for \SliceLength. - -The following extra rule enables expressing array indices based on enumeration: -\hypertarget{ast-arraylengthenum}{} -\begin{flalign*} -\arrayindex \derives\ & \ArrayLengthEnum(\overtext{\identifier}{name of enumeration}, \overtext{\Z}{length}) & -\end{flalign*} - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -\chapter{Building Abstract Syntax Trees \label{chap:BuildingAbstractSyntaxTrees}} -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -This chapter define how to transform a parse tree into the corresponding AST -via recursively traversing the parse tree and applying a \emph{builder} function -for each non-terminal node. - -(Some of the builders are relations due to non-determinism induced by naming global variables -for assignments whose left-hand-side variable is discarded ($\Tminus$).) - -For each non-terminal $N \derives R_1 \;|\; \ldots R_k$, we define a builder function -$\textsf{build\_}N $ which takes a parse tree $\parsenode{N}$ and returns the corresponding -AST. The builder function is defined in terms of one inference rule per alternative $R_i$. -The input for the builder for an alternative $R = S_{1..m}$ is a parse node -$N(S_{1..m})$. To allow the builder to refer to the children nodes of $N$, -we use the notation $\namednode{n_i}{S_i}$, which names the child node $S_i$ as $n_i$. - -\section{Example} -Consider the derivation for while loops: -\[ -\Nstmt \derives \Twhile \parsesep \Nexpr \parsesep \Tdo \parsesep \Nstmtlist \parsesep \Tend -\] - -The parse node for a while statement has the form -\[ -\Nstmt(\Twhile, \namednode{\ve}{\Nexpr}, \Tdo, \namednode{\vstmtlist}{\Nstmtlist}, \Tend) -\] -where $\ve$ names the node representing the condition of the loop and $\vstmtlist$ names -the list of statements that form the body of the loop. - -To build the corresponding AST, we employ the builder function $\buildstmt$, since -the non-terminal labelling the parse node is $\Nstmt$. - -We also employ the following rule: -\begin{mathpar} -\inferrule{ - \buildexpr(\ve) \astarrow \astversion{\ve}\\ - \buildstmtlist(\vstmtlist) \astarrow \astversion{\vstmtlist} -}{ -{ -\begin{array}{r} - \buildstmt(\Nstmt(\Twhile, \namednode{\ve}{\Nexpr}, \Tdo, \namednode{\vstmtlist}{\Nstmtlist}, \Tend)) - \astarrow\\ - \SWhile(\astversion{\ve}, \None, \astversion{\vstmtlist}) -\end{array} -} -} -\end{mathpar} -That is, we apply the $\buildexpr$ to transform the condition parse node $\ve$ into the corresponding AST node, -we apply $\buildstmtlist$ to transform the parse node $\vstmtlist$ for the body of the list into the corresponding AST node, -and finally return the AST node for \texttt{while} loops --- $\SWhile$ --- with the two nodes as its children. - -\section{Abbreviated Rule Notation} -Notice that there is only one instance of $\Nexpr$ and one instance of $\Nstmtlist$ in this production. -This is very common and we therefore use the following shorthand notation for such cases, as explained next. - -In a non-terminal $N$ appears only once in the right-hand-side of a derivation, -we use the name $\texttt{N}$ to name the corresponding child parse node. -For example, $\namednode{\vexpr}{\Nexpr}$ and $\namednode{\vstmtlist}{\Nstmtlist}$. -In such cases, we always have the premise $\textsf{build\_}N(\texttt{N}) \astarrow \astversion{N}$ -to obtain the corresponding AST node. -We therefore make this premise implicit, by dropping it entirely and using $\astof{N}$ to mean that -the parse node $N$ is named $\texttt{N}$, the premise $\textsf{build\_}N(\texttt{N}) \astarrow \astversion{N}$ -is considered part of the rule and $\astversion{N}$ itself stands for $\astversion{N}$. - -In our example, this results in the abbreviated rule notation -\begin{mathpar} -\inferrule{}{ -{ -\begin{array}{r} - \buildstmt(\Nstmt(\Twhile, \punnode{\Nexpr}, \Tdo, \punnode{\Nstmtlist}, \Tend)) - \astarrow\\ - \SWhile(\astof{\vexpr}, \None, \astof{\vstmtlist}) - \end{array} -} -} -\end{mathpar} - -\section{AST Builder Functions and Relations} -We define the following rules for transforming the various non-terminal parse nodes into -the corresponding AST nodes: -\begin{itemize} - \item SyntaxRule.AST (see \secref{SyntaxRule.AST}) - \item SyntaxRule.GlobalDecl (see \secref{SyntaxRule.GlobalDecl}) - \item SyntaxRule.Subtype (see \secref{SyntaxRule.Subtype}) - \item SyntaxRule.Subtypeopt (see \secref{SyntaxRule.Subtypeopt}) - \item SyntaxRule.TypedIdentifier (see \secref{SyntaxRule.TypedIdentifier}) - \item SyntaxRule.OptTypedIdentifier (see \secref{SyntaxRule.OptTypedIdentifier}) - \item SyntaxRule.ReturnType (see \secref{SyntaxRule.ReturnType}) - \item SyntaxRule.ParamsOpt (see \secref{SyntaxRule.ParamsOpt}) - \item SyntaxRule.AccessArgs (see \secref{SyntaxRule.AccessArgs}) - \item SyntaxRule.FuncArgs (see \secref{SyntaxRule.FuncArgs}) - \item SyntaxRule.MaybeEmptyStmtList (see \secref{SyntaxRule.MaybeEmptyStmtList}) - \item SyntaxRule.FuncBody (see \secref{SyntaxRule.FuncBody}) - \item SyntaxRule.IgnoredOrIdentifier (see \secref{SyntaxRule.IgnoredOrIdentifier}) - \item SyntaxRule.LocalDeclKeyword (see \secref{SyntaxRule.LocalDeclKeyword}) - \item SyntaxRule.StorageKeyword (see \secref{SyntaxRule.StorageKeyword}) - \item SyntaxRule.Direction (see \secref{SyntaxRule.Direction}) - \item SyntaxRule.Alt (see \secref{SyntaxRule.Alt}) - \item SyntaxRule.OtherwiseOpt (see \secref{SyntaxRule.OtherwiseOpt}) - \item SyntaxRule.Catcher (see \secref{SyntaxRule.Catcher}) - \item SyntaxRule.Stmt (see \secref{SyntaxRule.Stmt}) - \item SyntaxRule.StmtList (see \secref{SyntaxRule.StmtList}) - \item SyntaxRule.SElse (see \secref{SyntaxRule.SElse}) - \item SyntaxRule.LExpr (see \secref{SyntaxRule.LExpr}) - \item SyntaxRule.LExprAtom (see \secref{SyntaxRule.LExprAtom}) - \item SyntaxRule.DeclItem (see \secref{SyntaxRule.DeclItem}) - \item SyntaxRule.UntypedDeclItem (see \secref{SyntaxRule.UntypedDeclItem}) - \item SyntaxRule.IntConstraints (see \secref{SyntaxRule.IntConstraints}) - \item SyntaxRule.IntConstraintsopt (see \secref{SyntaxRule.IntConstraintsopt}) - \item SyntaxRule.IntConstraint (see \secref{SyntaxRule.IntConstraint}) - \item SyntaxRule.ExprPattern (see \secref{SyntaxRule.ExprPattern}) - \item SyntaxRule.PatternSet (see \secref{SyntaxRule.PatternSet}) - \item SyntaxRule.PatternList (see \secref{SyntaxRule.PatternList}) - \item SyntaxRule.Pattern (see \secref{SyntaxRule.Pattern}) - \item SyntaxRule.Fields (see \secref{SyntaxRule.Fields}) - \item SyntaxRule.FieldsOpt (see \secref{SyntaxRule.FieldsOpt}) - \item SyntaxRule.NSlices (see \secref{SyntaxRule.NSlices}) - \item SyntaxRule.Slices (see \secref{SyntaxRule.Slices}) - \item SyntaxRule.Slice (see \secref{SyntaxRule.Slice}) - \item SyntaxRule.Bitfields (see \secref{SyntaxRule.Bitfields}) - \item SyntaxRule.Bitfield (see \secref{SyntaxRule.Bitfield}) - \item SyntaxRule.Ty (see \secref{SyntaxRule.Ty}) - \item SyntaxRule.TyDecl (see \secref{SyntaxRule.TyDecl}) - \item SyntaxRule.FieldAssign (see \secref{SyntaxRule.FieldAssign}) - \item SyntaxRule.EElse (see \secref{SyntaxRule.EElse}) - \item SyntaxRule.Expr (see \secref{SyntaxRule.Expr}) - \item SyntaxRule.Value (see \secref{SyntaxRule.Value}) - \item SyntaxRule.Unop (see \secref{SyntaxRule.Unop}) - \item SyntaxRule.Binop (see \secref{SyntaxRule.Binop}) -\end{itemize} - -We also define the following helper functions: -\begin{itemize} -\item SyntaxRule.StmtFromList (see \secref{SyntaxRule.StmtFromList}) -\item SyntaxRule.SequenceStmts (see \secref{SyntaxRule.SequenceStmts}) -\end{itemize} - -\section{SyntaxRule.AST \label{sec:SyntaxRule.AST}} -\hypertarget{build-ast}{} -The relation -\[ - \buildast : \overname{\parsenode{\Nast}}{\vparsednode} \;\aslrel\; \overname{\specification}{\vastnode} -\] -transforms an $\Nast$ node $\vparsednode$ into an AST specification node $\vastnode$. - -Notice that we define some builders as relations rather than functions. This is due to the non-determinism -in creating identifiers for auxiliary variables that stand in for instances of \texttt{-} on the left-hand-side -of assignments and declarations. -For example, \texttt{- = 5;} will effectively create some auxiliary variable, which will result in -an AST node such as $\SAssign(\EVar(\texttt{aux-1}), \ELiteral(\lint(5)))$. -Recall that hyphens are not legal characters in ASL identifiers, which avoids potential clashes with -user-supplied identifiers. An implementation is free however to choose other naming schemes that -avoid name clashes, for example, by employing counters. - -\begin{mathpar} -\inferrule[ast]{ - \buildlist[\builddecl](\vdecls) \astarrow \vadecls -}{ - \buildast(\overname{\Nast(\namednode{\vdecls}{\maybeemptylist{\Ndecl}})}{\vparsednode}) \astarrow \overname{\vadecls}{\vastnode} -} -\end{mathpar} - -\section{SyntaxRule.GlobalDecl \label{sec:SyntaxRule.GlobalDecl}} -\hypertarget{build-decl}{} -The relation -\[ - \builddecl : \overname{\parsenode{\Ndecl}}{\vparsednode} \;\aslrel\; \overname{\decl}{\vastnode} -\] -transforms a parse node $\vparsednode$ into an AST node $\vastnode$. - - -\hypertarget{build-funcdecl}{} -\begin{mathpar} -\inferrule[func\_decl]{}{ - \builddecl( - \overname{\Ndecl( - \Tfunc, \Tidentifier(\name), \punnode{\Nparamsopt}, \punnode{\Nfuncargs}, \punnode{\Nreturntype}, \punnode{\Nfuncbody} - )}{\vparsednode}) - \astarrow \\ - { - \overname{ - \DFunc\left(\left\{ - \begin{array}{rcl} - \funcname &:& \name,\\ - \funcparameters &:& \astof{\vparamsopt},\\ - \funcargs &:& \astof{\vfuncargs},\\ - \funcbody &:& \SBASL(\astof{\vfuncbody}),\\ - \funcreturntype &:& \langle \astof{\vreturntype} \rangle,\\ - \funcsubprogramtype &:& \STFunction - \end{array} - \right\}\right)}{\vastnode} - } -} -\end{mathpar} - -\hypertarget{build-procedureecl}{} -\begin{mathpar} -\inferrule[procedure\_decl]{}{ - \builddecl( - \overname{\Ndecl(\Tfunc, \Tidentifier(\name), \punnode{\Nparamsopt}, \punnode{\Nfuncargs}, \punnode{\Nfuncbody})}{\vparsednode} - ) - \astarrow \\ - { - \overname{ - \DFunc\left(\left\{ - \begin{array}{rcl} - \funcname &:& \name,\\ - \funcparameters &:& \astof{\vparamsopt},\\ - \funcargs &:& \astof{\vfuncargs},\\ - \funcbody &:& \SBASL(\astof{\vfuncbody}),\\ - \funcreturntype &:& \None,\\ - \funcsubprogramtype &:& \STProcedure - \end{array} - \right\}\right) - }{\vastnode} - } -} -\end{mathpar} - -\hypertarget{build-getter}{} -\begin{mathpar} -\inferrule[getter]{}{ - { - \begin{array}{r} - \builddecl\left(\overname{\Ndecl\left( - \begin{array}{l} - \Tgetter, \Tidentifier(\name), \punnode{\Nparamsopt}, \punnode{\Naccessargs}, \\ - \wrappedline\ \punnode{\Nreturntype}, \punnode{\Nfuncbody} - \end{array} - \right)}{\vparsednode}\right) - \astarrow \\ - \overname{ - \DFunc\left(\left\{ - \begin{array}{rcl} - \funcname &:& \name,\\ - \funcparameters &:& \astof{\vparamsopt},\\ - \funcargs &:& \astof{\vaccessargs},\\ - \funcbody &:& \SBASL(\astof{\vfuncbody}),\\ - \funcreturntype &:& \langle \astof{\vreturntype}\rangle,\\ - \funcsubprogramtype &:& \STGetter - \end{array} - \right\}\right) - }{\vastnode} - \end{array} - } -} -\end{mathpar} - -\hypertarget{build-noarggetter}{} -\begin{mathpar} -\inferrule[no\_arg\_getter]{}{ - \builddecl(\overname{\Ndecl(\Tgetter, \Tidentifier(\name), \punnode{\Nreturntype}, \punnode{\Nfuncbody})}{\vparsednode}) - \astarrow \\ - { - \overname{ - \DFunc\left(\left\{ - \begin{array}{rcl} - \funcname &:& \name,\\ - \funcparameters &:& \emptylist,\\ - \funcargs &:& \emptylist,\\ - \funcbody &:& \SBASL(\astof{\vfuncbody}),\\ - \funcreturntype &:& \langle \astof{\vreturntype}\rangle,\\ - \funcsubprogramtype &:& \STEmptyGetter - \end{array} - \right\}\right) - }{\vastnode} - } -} -\end{mathpar} - -\hypertarget{build-setter}{} -\begin{mathpar} -\inferrule[setter]{}{ - { - \builddecl\left(\overname{\Ndecl\left( - \begin{array}{r} - \Tsetter, \Tidentifier(\name), \punnode{\Nparamsopt}, \punnode{\Naccessargs}, \Teq, \\ - \wrappedline\ \namednode{\vv}{\Ntypedidentifier}, \punnode{\Nfuncbody} - \end{array} - \right)}{\vparsednode}\right) - } \astarrow - \\ - { - \overname{ - \DFunc\left(\left\{ - \begin{array}{rcl} - \funcname &:& \name,\\ - \funcparameters &:& \astof{\vparamsopt},\\ - \funcargs &:& [\vv] \concat \astof{\vaccessargs},\\ - \funcbody &:& \SBASL(\astof{\vfuncbody}),\\ - \funcreturntype &:& \None,\\ - \funcsubprogramtype &:& \STSetter - \end{array} - \right\}\right) - }{\vastnode} - } -} -\end{mathpar} - -\hypertarget{build-noargsetter}{} -\begin{mathpar} -\inferrule[no\_arg\_setter]{}{ - \builddecl(\overname{\Ndecl(\Tsetter, \Tidentifier(\name), \Teq, \namednode{\vv}{\Ntypedidentifier}, \punnode{\Nfuncbody})}{\vparsednode}) - \astarrow \\ - { - \overname{ - \DFunc\left(\left\{ - \begin{array}{rcl} - \funcname &:& \name,\\ - \funcparameters &:& \emptylist,\\ - \funcargs &:& [\vv],\\ - \funcbody &:& \SBASL(\astof{\vfuncbody}),\\ - \funcreturntype &:& \None,\\ - \funcsubprogramtype &:& \STEmptySetter - \end{array} - \right\}\right) - }{\vastnode} - } -} -\end{mathpar} - -\hypertarget{build-typedecl}{} -\begin{mathpar} -\inferrule[type\_decl]{} -{ - { - \begin{array}{c} - \builddecl(\overname{\Ndecl(\Ttype, \Tidentifier(\vx), \Tof, \punnode{\Ntydecl}, \Nsubtypeopt, \Tsemicolon)}{\vparsednode}) - \astarrow \\ - \overname{\DTypeDecl(\vx, \astof{\vt}, \astof{\vsubtypeopt})}{\vastnode} - \end{array} - } -} -\end{mathpar} - -\hypertarget{build-subtypedecl}{} -\begin{mathpar} -\inferrule[subtype\_decl]{ - \buildsubtype(\vsubtype) \astarrow \vs\\ - \vs \eqname (\name, \vfields) -}{ - { - \begin{array}{c} - \builddecl(\overname{\Ndecl(\Ttype, \Tidentifier(\vx), \Tof, \punnode{\Nsubtype}, \Tsemicolon)}{\vparsednode}) - \astarrow \\ - \overname{\DTypeDecl(\vx, \TNamed(\name), \langle(\name, \vfields)\rangle)}{\vastnode} - \end{array} - } -} -\end{mathpar} - -\hypertarget{build-globalstorage}{} -\begin{mathpar} -\inferrule[global\_storage]{ - \buildstoragekeyword(\keyword) \astarrow \astof{\keyword}\\ - \buildoption[\buildasty](\tty) \astarrow \ttyp\\ - \buildexpr(\vinitialvalue) \typearrow \astof{\vinitialvalue} -} -{ - { - \builddecl\left(\overname{\Ndecl\left( - \begin{array}{r} - \namednode{\vkeyword}{\Nstoragekeyword}, \namednode{\name}{\Nignoredoridentifier}, \\ - \wrappedline\ \namednode{\tty}{\option{\Nasty}}, \Teq, \namednode{\vinitialvalue}{\Nexpr}, \Tsemicolon - \end{array} - \right)}{\vparsednode}\right) - } \astarrow \\ - { - \overname{ - \DGlobalStorage\left(\left\{ - \begin{array}{rcl} - \GDkeyword &:& \astof{\vkeyword},\\ - \GDname &:& \astof{\name},\\ - \GDty &:& \ttyp,\\ - \GDinitialvalue &:& \astof{\vinitialvalue} - \end{array} - \right\}\right) - }{\vastnode} - } -} -\end{mathpar} - -\hypertarget{build-globaluninitvar}{} -\begin{mathpar} -\inferrule[global\_uninit\_var]{ - \buildignoredoridentifier(\cname) \astarrow \name -} -{ - { - \begin{array}{r} - \builddecl(\overname{\Ndecl(\Tvar, \namednode{\cname}{\Nignoredoridentifier}, \Nasty, \Tsemicolon)}{\vparsednode}) \astarrow - \end{array} - } \\ - \overname{\DGlobalStorage(\{\GDkeyword: \GDKVar, \GDname: \name, \GDty: \langle\astof{\Nasty}\rangle, \GDinitialvalue: \None\})}{\vastnode} -} -\end{mathpar} - -\hypertarget{build-globalpragma}{} -\begin{mathpar} -\inferrule[global\_pragma]{} -{ - \builddecl(\overname{\Ndecl(\Tpragma, \Tidentifier(\vx), \Clist{\Nexpr}, \Tsemicolon)}{\vparsednode}) \astarrow \overname{\tododefine{pragma\_node}}{\vastnode} -} -\end{mathpar} - -\section{SyntaxRule.Subtype \label{sec:SyntaxRule.Subtype}} -\hypertarget{build-subtype}{} -The function -\[ - \buildsubtype(\overname{\parsenode{\Nsubtype}}{\vparsednode}) \aslto \overname{(\identifier \times (\identifier\times \ty)^*)}{\vastnode} -\] -transforms a parse node $\vparsednode$ into an AST node $\vastnode$. - -\hypertarget{build-subtype}{} -\begin{mathpar} -\inferrule[with\_fields]{}{ - { - \begin{array}{r} - \buildsubtype(\overname{\Nsubtype( - \Tsubtypes, \Tidentifier(\id), \Twith, \punnode{\Nfields} - )}{\vparsednode}) - \astarrow \\ - \overname{(\id, \astof{\vfields})}{\vastnode} - \end{array} - } -} -\end{mathpar} - -\begin{mathpar} - \inferrule[no\_fields]{}{ - \buildsubtype(\overname{\Nsubtype( - \Tsubtypes, \Tidentifier(\id))}{\vparsednode}) - \astarrow - \overname{(\id, \emptylist)}{\vastnode} -} -\end{mathpar} - -\section{SyntaxRule.Subtypeopt \label{sec:SyntaxRule.Subtypeopt}} -\hypertarget{build-subtypeopt}{} -The function -\[ - \buildsubtypeopt(\overname{\parsenode{\Nsubtypeopt}}{\vparsednode}) \aslto - \overname{\langle(\identifier \times \langle (\identifier\times \ty)^* \rangle)\rangle}{\vastnode} -\] -transforms a parse node $\vparsednode$ into an AST node $\vastnode$. - -\begin{mathpar} -\inferrule[subtype\_opt]{ - \buildoption[\Nsubtype](\vsubtypeopt) \astarrow \vastnode -}{ - \buildsubtypeopt(\overname{\Nsubtypeopt(\namednode{\vsubtypeopt}{\option{\Nsubtype}})}{\vparsednode}) \astarrow \vastnode -} -\end{mathpar} - -\section{SyntaxRule.TypedIdentifier \label{sec:SyntaxRule.TypedIdentifier}} -\hypertarget{build-typedidentifier}{} -The function -\[ -\buildtypedidentifier(\overname{\parsenode{\Ntypedidentifier}}{\vparsednode}) \aslto \overname{(\identifier \times \ty)}{\vastnode} -\] -transforms a parse node $\vparsednode$ into an AST node $\vastnode$. - -\begin{mathpar} -\inferrule{}{ - \buildtypedidentifier(\overname{\Ntypedidentifier(\Tidentifier(\id), \punnode{\Nasty})}{\vparsednode}) \astarrow \overname{(\id,\astof{\vasty})}{\vastnode} -} -\end{mathpar} - -\section{SyntaxRule.OptTypedIdentifier \label{sec:SyntaxRule.OptTypedIdentifier}} -\hypertarget{build-opttypedidentifier}{} -The function -\[ -\buildopttypedidentifier(\overname{\parsenode{\Nopttypedidentifier}}{\vparsednode}) \aslto \overname{(\identifier \times \langle\ty\rangle)}{\vastnode} -\] -transforms a parse node $\vparsednode$ into an AST node $\vastnode$. - -\begin{mathpar} -\inferrule{ - \buildoption[\Nasty](\vastyopt) \astarrow \astversion{\vastyopt} -}{ - { - \begin{array}{r} - \buildopttypedidentifier(\overname{\Ntypedidentifier(\Tidentifier(\id), \namednode{\vastyopt}{\option{\Nasty}})}{\vparsednode}) \astarrow \\ - \overname{(\id, \astversion{\vastyopt})}{\vastnode} - \end{array} - } -} -\end{mathpar} - -\section{SyntaxRule.ReturnType \label{sec:SyntaxRule.ReturnType}} -\hypertarget{build-returntype}{} -The function -\[ -\buildreturntype(\overname{\parsenode{\Nreturntype}}{\vparsednode}) \aslto \overname{\ty}{\vastnode} -\] -transforms a parse node $\vparsednode$ into an AST node $\vastnode$. - -\begin{mathpar} -\inferrule{}{ - \buildreturntype(\overname{\Nreturntype(\Tarrow, \punnode{\Nty})}{\vparsednode}) \astarrow - \overname{\astof{\tty}}{\vastnode} -} -\end{mathpar} - -\section{SyntaxRule.ParamsOpt \label{sec:SyntaxRule.ParamsOpt}} -\hypertarget{build-paramsopt}{} -The function -\[ -\buildparamsopt(\overname{\parsenode{\Nparamsopt}}{\vparsednode}) \aslto - \overname{(\identifier\times\langle\ty\rangle)^*}{\vastnode} -\] -transforms a parse node $\vparsednode$ into an AST node $\vastnode$. - -\begin{mathpar} -\inferrule[empty]{}{ - \buildparamsopt(\overname{\Nparamsopt(\epsilonnode)}{\vparsednode}) \astarrow - \overname{\emptylist}{\vastnode} -} -\end{mathpar} - -\begin{mathpar} -\inferrule[non\_empty]{ - \buildclist[\Nopttypedidentifier](\ids) \astarrow \astversion{\ids} -}{ - \buildparamsopt(\overname{\Nparamsopt(\Tlbrace, \namednode{\ids}{\Clist{\Nopttypedidentifier}}, \Trbrace)}{\vparsednode}) \astarrow - \overname{\astversion{\ids}}{\vastnode} -} -\end{mathpar} - -\section{SyntaxRule.AccessArgs \label{sec:SyntaxRule.AccessArgs}} -\hypertarget{build-accessargs}{} -The function -\[ -\buildaccessargs(\overname{\parsenode{\Naccessargs}}{\vparsednode}) \aslto - \overname{(\identifier\times\ty)^*}{\vastnode} -\] -transforms a parse node $\vparsednode$ into an AST node $\vastnode$. - -\begin{mathpar} -\inferrule{ - \buildclist[\Ntypedidentifier](\ids) \astarrow \astversion{\ids} -}{ - \buildaccessargs(\overname{\Naccessargs(\Tlbracket, \namednode{\ids}{\Clist{\Ntypedidentifier}}, \Trbracket)}{\vparsednode}) \astarrow - \overname{\astversion{\ids}}{\vastnode} -} -\end{mathpar} - -\section{SyntaxRule.FuncArgs \label{sec:SyntaxRule.FuncArgs}} -\hypertarget{build-funcargs}{} -The function -\[ -\buildfuncargs(\overname{\parsenode{\Nfuncargs}}{\vparsednode}) \aslto - \overname{(\identifier\times\ty)^*}{\vastnode} -\] -transforms a parse node $\vparsednode$ into an AST node $\vastnode$. - -\begin{mathpar} -\inferrule{ - \buildclist[\Ntypedidentifier](\ids) \astarrow \astversion{\ids} -}{ - \buildfuncargs(\overname{\Nfuncargs(\Tlpar, \namednode{\ids}{\Clist{\Ntypedidentifier}}, \Trpar)}{\vparsednode}) \astarrow - \overname{\astversion{\ids}}{\vastnode} -} -\end{mathpar} - -\section{SyntaxRule.MaybeEmptyStmtList \label{sec:SyntaxRule.MaybeEmptyStmtList}} -\hypertarget{build-maybeemptystmtlist}{} -The function -\[ -\buildmaybeemptystmtlist(\overname{\parsenode{\Nmaybeemptystmtlist}}{\vparsednode}) \aslto - \overname{\stmt}{\vastnode} -\] -transforms a parse node $\vparsednode$ into an AST node $\vastnode$. - -\begin{mathpar} -\inferrule[empty]{}{ - \buildmaybeemptystmtlist(\overname{\Nmaybeemptystmtlist(\epsilonnode)}{\vparsednode}) \astarrow - \overname{\SPass}{\vastnode} -} -\end{mathpar} - -\begin{mathpar} -\inferrule[non\_empty]{}{ - \buildmaybeemptystmtlist(\overname{\Nmaybeemptystmtlist(\Nstmtlist)}{\vparsednode}) \astarrow - \overname{\astof{\vstmtlist}}{\vastnode} -} -\end{mathpar} - -\section{SyntaxRule.FuncBody \label{sec:SyntaxRule.FuncBody}} -\hypertarget{build-funcbody}{} -The function -\[ -\buildfuncargs(\overname{\parsenode{\Nfuncbody}}{\vparsednode}) \aslto - \overname{\stmt}{\vastnode} -\] -transforms a parse node $\vparsednode$ into an AST node $\vastnode$. - -\begin{mathpar} -\inferrule{}{ - { - \begin{array}{r} - \buildfuncbody(\overname{\Nfuncbody(\Tbegin, \namednode{\vstmts}{\Nmaybeemptystmtlist}, \Tend)}{\vparsednode}) \astarrow \\ - \overname{\astof{\vmaybeemptystmtlist}}{\vastnode} - \end{array} - } -} -\end{mathpar} - -\section{SyntaxRule.IgnoredOrIdentifier \label{sec:SyntaxRule.IgnoredOrIdentifier}} -\hypertarget{build-ignoredoridentifier}{} -The relation -\[ -\buildfuncargs(\overname{\parsenode{\Nignoredoridentifier}}{\vparsednode}) \;\aslrel\; - \overname{\identifier}{\vastnode} -\] -transforms a parse node $\vparsednode$ into an AST node $\vastnode$. - -\begin{mathpar} -\inferrule[discard]{ - \id \in \identifier \text{ is fresh} -}{ - \buildignoredoridentifier(\overname{\Nignoredoridentifier(\Tminus)}{\vparsednode}) \astarrow - \overname{\id}{\vastnode} -} -\end{mathpar} - -\begin{mathpar} -\inferrule[id]{}{ - \buildignoredoridentifier(\overname{\Nignoredoridentifier(\Tidentifier(\id))}{\vparsednode}) \astarrow - \overname{\id}{\vastnode} -} -\end{mathpar} - -\section{SyntaxRule.LocalDeclKeyword \label{sec:SyntaxRule.LocalDeclKeyword}} -\hypertarget{build-localdeclkeyword}{} -The function -\[ -\buildlocaldeclkeyword(\overname{\parsenode{\Nlocaldeclkeyword}}{\vparsednode}) \;\aslto\; - \overname{\localdeclkeyword}{\vastnode} -\] -transforms a parse node $\vparsednode$ into an AST node $\vastnode$. - -\begin{mathpar} -\inferrule[let]{}{ - \buildlocaldeclkeyword(\overname{\Nlocaldeclkeyword(\Tlet)}{\vparsednode}) \astarrow \overname{\LDKLet}{\vastnode} -} -\end{mathpar} - -\begin{mathpar} -\inferrule[constant]{}{ - \buildlocaldeclkeyword(\overname{\Nlocaldeclkeyword(\Tconstant)}{\vparsednode}) \astarrow \overname{\LDKConstant}{\vastnode} -} -\end{mathpar} - -\section{SyntaxRule.StorageKeyword \label{sec:SyntaxRule.StorageKeyword}} -\hypertarget{build-storagekeyword}{} -The function -\[ -\buildstoragekeyword(\overname{\parsenode{\Nstoragekeyword}}{\vparsednode}) \;\aslto\; - \overname{\globaldeclkeyword}{\vastnode} -\] -transforms a parse node $\vparsednode$ into an AST node $\vastnode$. - -\begin{mathpar} -\inferrule[let]{}{ - \buildstoragekeyword(\overname{\Nstoragekeyword(\Tlet)}{\vparsednode}) \astarrow \overname{\GDKLet}{\vastnode} -} -\end{mathpar} - -\begin{mathpar} -\inferrule[constant]{}{ - \buildstoragekeyword(\overname{\Nstoragekeyword(\Tconstant)}{\vparsednode}) \astarrow \overname{\GDKConstant}{\vastnode} -} -\end{mathpar} - -\begin{mathpar} -\inferrule[var]{}{ - \buildstoragekeyword(\overname{\Nstoragekeyword(\Tvar)}{\vparsednode}) \astarrow \overname{\GDKVar}{\vastnode} -} -\end{mathpar} - -\begin{mathpar} -\inferrule[config]{}{ - \buildstoragekeyword(\overname{\Nstoragekeyword(\Tconfig)}{\vparsednode}) \astarrow \overname{\GDKConfig}{\vastnode} -} -\end{mathpar} - -\section{SyntaxRule.Direction \label{sec:SyntaxRule.Direction}} -\hypertarget{build-direction}{} -The function -\[ -\builddirection(\overname{\parsenode{\Ndirection}}{\vparsednode}) \;\aslto\; \overname{\fordirection}{\vastnode} -\] -transforms a parse node $\vparsednode$ into an AST node $\vastnode$. - -\begin{mathpar} -\inferrule[to]{}{ - \builddirection(\overname{\Ndirection(\Tto)}{\vparsednode}) \astarrow \overname{\UP}{\vastnode} -} -\end{mathpar} - -\begin{mathpar} -\inferrule[downto]{}{ - \builddirection(\overname{\Ndirection(\Tdownto)}{\vparsednode}) \astarrow \overname{\DOWN}{\vastnode} -} -\end{mathpar} - -\section{SyntaxRule.Alt \label{sec:SyntaxRule.Alt}} -\hypertarget{build-alt}{} -The function -\[ -\buildalt(\overname{\parsenode{\Nalt}}{\vparsednode}) \;\aslto\; \overname{\casealt}{\vastnode} -\] -transforms a parse node $\vparsednode$ into an AST node $\vastnode$. - -\begin{mathpar} -\inferrule[when]{ - \buildoption[\buildexpr](\vwhereopt) \astarrow \vwhereast -}{ - { - \begin{array}{r} - \buildalt\left(\overname{\Nalt\left( - \begin{array}{l} - \Twhen, \punnode{\Npatternlist}, \\ - \wrappedline\ \namednode{\vwhereopt}{\option{\Twhere, \Nexpr}}, \Tarrow, \\ - \wrappedline\ \namednode{\vstmts}{\Nstmtlist} - \end{array} - \right)}{\vparsednode}\right) - \astarrow \\ - \overname{\casealt(\CasePattern: \astof{\vpatternlist}, \CaseWhere: \vwhereast, \CaseStmt: \astof{\vstmtlist})}{\vastnode} - \end{array} - } -} -\end{mathpar} - -\begin{mathpar} -\inferrule[otherwise]{}{ - { - \begin{array}{r} - \buildalt(\overname{\Nalt(\Totherwise, \namednode{\vstmts}{\Nstmtlist})}{\vparsednode}) - \astarrow \\ - \overname{\casealt(\CasePattern: \PatternAll, \CaseWhere: \None, \CaseStmt: \astof{\vstmtlist})}{\vastnode} - \end{array} - } -} -\end{mathpar} - -\section{SyntaxRule.OtherwiseOpt \label{sec:SyntaxRule.OtherwiseOpt}} -\hypertarget{build-otherwiseopt}{} -The function -\[ -\buildotherwiseopt(\overname{\parsenode{\Notherwiseopt}}{\vparsednode}) \;\aslto\; \overname{\stmt?}{\vastnode} -\] -transforms a parse node $\vparsednode$ into an AST node $\vastnode$. - -\begin{mathpar} -\inferrule{ - \buildoption[\buildstmtlist] (\vv)\astarrow \vastnode -}{ - { - \begin{array}{r} - \buildotherwiseopt(\overname{\Notherwiseopt(\namednode{\vv}{\option{\Totherwise, \Tarrow, \Nstmtlist}})}{\vparsednode}) - \astarrow \\ - \vastnode - \end{array} - } -} -\end{mathpar} - -\section{SyntaxRule.Catcher \label{sec:SyntaxRule.Catcher}} -\hypertarget{build-catcher}{} -The function -\[ -\buildcatcher(\overname{\parsenode{\Ncatcher}}{\vparsednode}) \;\aslto\; \overname{\catcher}{\vastnode} -\] -transforms a parse node $\vparsednode$ into an AST node $\vastnode$. - -\begin{mathpar} -\inferrule[named]{}{ - { - \begin{array}{r} - \buildcatcher(\overname{\Ncatcher(\Twhen, \Tidentifier(\id), \Tcolon, \Nty, \Tarrow, \Nstmtlist)}{\vparsednode}) - \astarrow \\ - \overname{(\langle\id\rangle, \astof{\tty}, \astof{\vstmtlist})}{\vastnode} - \end{array} - } -} -\end{mathpar} - -\begin{mathpar} -\inferrule[unnamed]{}{ - { - \begin{array}{r} - \buildcatcher(\overname{\Ncatcher(\Twhen, \Nty, \Tarrow, \Nstmtlist)}{\vparsednode}) - \astarrow \\ - \overname{(\None, \astof{\tty}, \astof{\vstmtlist})}{\vastnode} - \end{array} - } -} -\end{mathpar} - -\section{SyntaxRule.Stmt \label{sec:SyntaxRule.Stmt}} -\hypertarget{build-stmt}{} -The function -\[ -\buildstmt(\overname{\parsenode{\Nstmt}}{\vparsednode}) \;\aslto\; \overname{\stmt}{\vastnode} -\] -transforms a parse node $\vparsednode$ into an AST node $\vastnode$. - - -\begin{mathpar} -\inferrule[if]{}{ - { - \begin{array}{r} - \buildstmt(\overname{\Nstmt(\Tif, \punnode{\Nexpr}, \Tthen, \punnode{\Nstmtlist}, \punnode{\Nselse}, \Tend)}{\vparsednode}) - \astarrow \\ - \overname{\SCond(\astof{\vexpr}, \astof{\vstmtlist}, \astof{\velse})}{\vastnode} - \end{array} - } -} -\end{mathpar} - -\begin{mathpar} -\inferrule[case]{ - \buildlist[\Nalt](\valtlist) \astarrow \valtlistast -}{ - { - \begin{array}{r} - \buildstmt(\overname{\Nstmt(\Tcase, \punnode{\Nexpr}, \Tof, \namednode{\valtlist}{\nonemptylist{\Nalt}}, \Tend)}{\vparsednode}) - \astarrow \\ - \overname{\SCase(\astof{\vexpr}, \valtlistast)}{\vastnode} - \end{array} - } -} -\end{mathpar} - -\begin{mathpar} -\inferrule[while]{}{ - { - \begin{array}{r} - \buildstmt(\overname{\Nstmt(\Twhile, \punnode{\Nexpr}, \Tdo, \punnode{\Nstmtlist}, \Tend)}{\vparsednode}) - \astarrow\\ - \overname{\SWhile(\astof{\vexpr}, \None, \astof{\vstmtlist})}{\vastnode} -\end{array} -} -} -\end{mathpar} - -\begin{mathpar} -\inferrule[looplimit\_while]{ - \buildexpr(\vlimitexpr) \astarrow \astversion{\vlimitexpr} -}{ - { - \begin{array}{r} - \buildstmt\left(\overname{\Nstmt\left( - \begin{array}{r} - \Tlooplimit, \Tlpar, \namednode{\vlimitexpr}{\Nexpr}, \Trpar, \Twhile, \\ - \wrappedline\ \punnode{\Nexpr}, \Tdo, \punnode{\Nstmtlist}, \Tend - \end{array} - \right)}{\vparsednode}\right) - \astarrow\\ - \overname{\SWhile(\astof{\vexpr}, \langle\astversion{\vlimitexpr}\rangle, \astof{\vstmtlist})}{\vastnode} -\end{array} -} -} -\end{mathpar} - -\begin{mathpar} -\inferrule[for]{ - \buildexpr(\vstarte) \astarrow \astversion{\vstarte}\\ - \buildexpr(\vende) \astarrow \astversion{\vende}\\ -}{ - { - \begin{array}{r} - \buildstmt\left(\overname{\Nstmt\left( - \begin{array}{l} - \Tfor, \Tidentifier(\vindexname), \Teq, \namednode{\vstarte}{\Nexpr}, \Ndirection, \\ - \wrappedline\ \namednode{\vende}{\Nexpr}, \Tdo, \punnode{\Nstmtlist}, \Tend - \end{array} - \right)}{\vparsednode}\right) - \astarrow \\ - \overname{ - \SFor\left(\left\{ - \begin{array}{rcl} - \Forindexname &:& \vindexname\\ - \Forstarte &:& \astversion{\vstarte}\\ - \Forende &:& \astversion{\vende}\\ - \Forbody &:& \astof{\vstmtlist}\\ - \Forlimit &:& \None\\ - \end{array} - \right\}\right) - }{\vastnode} - \end{array} - } -} -\end{mathpar} - -\begin{mathpar} -\inferrule[try]{ - \buildlist[\Ncatcher] \astarrow \astversion{\vcatcherlist} -}{ - { - \begin{array}{r} - \buildstmt\left(\overname{\Nstmt\left( - \begin{array}{r} - \Ttry, \Nstmtlist, \Tcatch, \\ - \wrappedline\ \namednode{\vcatcherlist}{\nonemptylist{\Ncatcher}}, \\ - \wrappedline\ \Notherwiseopt, \Tend - \end{array} - \right)}{\vparsednode}\right) - \astarrow \\ - \overname{\STry(\astof{\vstmtlist}, \astversion{\vcatcherlist}, \astof{\votherwiseopt})}{\vastnode} -\end{array} -} -} -\end{mathpar} - -\begin{mathpar} -\inferrule[pass]{}{ - \buildstmt(\overname{\Nstmt(\Tpass, \Tsemicolon)}{\vparsednode}) - \astarrow - \overname{\SPass}{\vastnode} -} -\end{mathpar} - -\begin{mathpar} -\inferrule[return]{ - \buildoption[\Nexpr](\vexpr) \astarrow \astversion{\vexpr} -}{ - \buildstmt(\overname{\Nstmt(\Treturn, \namednode{\vexpr}{\option{\Nexpr}}, \Tsemicolon)}{\vparsednode}) - \astarrow - \overname{\SReturn(\astversion{\vexpr})}{\vastnode} -} -\end{mathpar} - -\begin{mathpar} -\inferrule[call]{ - \buildplist[\Nexpr](\vargs) \astarrow \astversion{\vargs} -}{ - \buildstmt(\overname{\Nstmt(\Tidentifier(\vx), \namednode{\vargs}{\Plist{\Nexpr}}, \Tsemicolon)}{\vparsednode}) - \astarrow - \overname{\SCall(\vx, \astversion{\vargs})}{\vastnode} -} -\end{mathpar} - -\begin{mathpar} -\inferrule[assert]{}{ - \buildstmt(\overname{\Nstmt(\Tassert, \Nexpr, \Tsemicolon)}{\vparsednode}) - \astarrow - \overname{\SAssert(\astof{\vexpr})}{\vastnode} -} -\end{mathpar} - -\begin{mathpar} -\inferrule[decl]{}{ - { - \begin{array}{r} - \buildstmt(\overname{\Nstmt(\Nlocaldeclkeyword, \Ndeclitem, \Teq, \punnode{\Nexpr}, \Tsemicolon)}{\vparsednode}) - \astarrow\\ - \overname{\SDecl(\astof{\vlocaldeclkeyword}, \astof{\vdeclitem}, \langle\astof{\vexpr}\rangle)}{\vastnode} - \end{array} - } -} -\end{mathpar} - -\begin{mathpar} -\inferrule[assignment]{}{ - \buildstmt(\overname{\Nstmt(\punnode{\Nlexpr}, \Teq, \punnode{\Nexpr}, \Tsemicolon)}{\vparsednode}) - \astarrow - \overname{\SAssign(\astof{\vlexpr}, \astof{\vexpr})}{\vastnode} -} -\end{mathpar} - -\begin{mathpar} -\inferrule[var\_decl]{ - \buildoption[\buildexpr](\ve) \astarrow \astversion{\ve} -}{ - { - \begin{array}{r} - \buildstmt(\overname{\Nstmt(\Tvar, \Ndeclitem, \namednode{\ve}{\option{\Teq, \Nexpr}}, \Tsemicolon)}{\vparsednode}) - \astarrow \\ - \overname{\SDecl(\LDKVar, \astof{\vdeclitem}, \astversion{\ve})}{\vastnode} -\end{array} -} -} -\end{mathpar} - -\begin{mathpar} -\inferrule[multi\_var\_decl]{ - \buildclist[\buildidentity](\vids) \astarrow \astversion{\vids}\\ - \vstmts \eqdef [\vx\in\astversion{\vids}: \SDecl(\LDKVar, \vx, \astof{\tty})]\\ - \stmtfromlist(\vstmts) \astarrow \vastnode -}{ - \buildstmt(\overname{\Nstmt(\Tvar, \namednode{\vids}{\Clisttwo{\Tidentifier}}, \Tcolon, \punnode{\Nty}, \Tsemicolon)}{\vparsednode}) - \astarrow - \vastnode -} -\end{mathpar} - -\begin{mathpar} -\inferrule[print]{ - \buildplist[\Nexpr](\vargs) \astarrow \astversion{\vargs} -}{ - \buildstmt(\overname{\Nstmt(\Tprint, \namednode{\vargs}{\Plist{\Nexpr}}, \Tsemicolon)}{\vparsednode}) - \astarrow - \overname{\SPrint(\astversion{\vargs})}{\vastnode} -} -\end{mathpar} - -\begin{mathpar} -\inferrule[repeat]{}{ - { - \begin{array}{r} - \buildstmt(\overname{\Nstmt(\Trepeat, \Nstmtlist, \Tuntil, \Nexpr, \Tsemicolon)}{\vparsednode}) - \astarrow\\ - \overname{\SRepeat(\astof{\vstmtlist}, \astof{\vexpr}, \None)}{\vastnode} - \end{array} - } -} -\end{mathpar} - -\begin{mathpar} -\inferrule[looplimit\_repeat]{ - \buildexpr(\vlimitexpr) \astarrow \astversion{\vlimitexpr} -}{ - { - \begin{array}{r} - \buildstmt\left(\overname{\Nstmt\left( - \begin{array}{r} - \Tlooplimit, \Tlpar, \namednode{\vlimitexpr}{\Nexpr}, \Trpar, \Trepeat, \\ - \wrappedline\ \Nstmtlist, \Tuntil, \Nexpr, \Tsemicolon - \end{array} - \right)}{\vparsednode}\right) - \astarrow\\ - \overname{\SRepeat(\astof{\vstmtlist}, \astof{\vexpr}, \langle\astversion{\vlimitexpr}\rangle)}{\vastnode} - \end{array} - } -} -\end{mathpar} - -\begin{mathpar} -\inferrule[throw\_some]{}{ - \buildstmt(\overname{\Nstmt(\Tthrow, \Nexpr, \Tsemicolon)}{\vparsednode}) - \astarrow - \overname{\SThrow(\langle\astof{\vexpr}\rangle)}{\vastnode} -} -\end{mathpar} - -\begin{mathpar} -\inferrule[throw\_none]{}{ - \buildstmt(\overname{\Nstmt(\Tthrow, \Tsemicolon)}{\vparsednode}) - \astarrow - \overname{\SThrow(\None)}{\vastnode} -} -\end{mathpar} - -\begin{mathpar} -\inferrule[pragma]{}{ - \buildstmt(\overname{\Nstmt(\Tpragma, \Tidentifier, \Clist{\Nexpr}, \Tsemicolon)}{\vparsednode}) - \astarrow - \overname{\tododefine{pragma\_node}}{\vastnode} -} -\end{mathpar} - -\section{SyntaxRule.StmtList \label{sec:SyntaxRule.StmtList}} -\hypertarget{build-stmtlist}{} -The function -\[ - \buildstmtlist(\overname{\parsenode{\Nstmtlist}}{\vparsednode}) \;\aslto\; \overname{\stmt}{\vastnode} -\] -transforms a parse node $\vparsednode$ into an AST node $\vastnode$. - -\begin{mathpar} -\inferrule{ - \buildlist[\Nstmt](\vstmts) \astarrow \vstmtlist\\ - \stmtfromlist(\vstmtlist) \astarrow \vastnode -}{ - \buildstmtlist(\Nstmtlist(\namednode{\vstmts}{\nonemptylist{\Nstmt}})) \astarrow \vastnode -} -\end{mathpar} - -\section{SyntaxRule.SElse \label{sec:SyntaxRule.SElse}} -\hypertarget{build-selse}{} -The function -\[ - \buildselse(\overname{\parsenode{\Nselse}}{\vparsednode}) \;\aslto\; \overname{\stmt}{\vastnode} -\] -transforms a parse node $\vparsednode$ into an AST node $\vastnode$. - -\begin{mathpar} -\inferrule[elseif]{}{ - { - \begin{array}{r} - \buildselse(\Nselse(\Telseif, \Nexpr, \Twhen, \Nstmtlist, \Nselse)) \astarrow \\ - \overname{\SCond(\astof{\vexpr}, \astof{\vstmtlist}, \astof{\vselse})}{\vastnode} - \end{array} - } -} -\end{mathpar} - -\begin{mathpar} -\inferrule[pass]{}{ - \buildselse(\Nselse(\Tpass)) \astarrow \overname{\SPass}{\vastnode} -} -\end{mathpar} - -\begin{mathpar} -\inferrule[else]{}{ - \buildselse(\Nselse(\Telse, \punnode{\Nstmtlist})) \astarrow \overname{\astof{\vstmtlist}}{\vastnode} -} -\end{mathpar} - -\section{SyntaxRule.LExpr \label{sec:SyntaxRule.LExpr}} -\hypertarget{build-lexpr}{} -The function -\[ - \buildlexpr(\overname{\parsenode{\Nlexpr}}{\vparsednode}) \;\aslto\; \overname{\lexpr}{\vastnode} -\] -transforms a parse node $\vparsednode$ into an AST node $\vastnode$. - -\begin{mathpar} -\inferrule[lexpr\_atom]{}{ - \buildlexpr(\Nlexpr(\punnode{\Nlexpratom})) \astarrow \overname{\astof{\vlexpratom}}{\vastnode} -} -\end{mathpar} - -\begin{mathpar} -\inferrule[discard]{}{ - \buildlexpr(\Nlexpr(\Tminus)) \astarrow \overname{\LEDiscard}{\vastnode} -} -\end{mathpar} - -\begin{mathpar} -\inferrule[multi\_lexpr]{ - \buildclist[\Nlexpr](\vlexprs) \astarrow \vlexprasts -}{ - \buildlexpr(\Nlexpr(\Tlpar, \namednode{\vlexprs}{\NClist{\Nlexpr}}, \Trpar)) \astarrow - \overname{\LEDestructuring(\vlexprasts)}{\vastnode} -} -\end{mathpar} - -\section{SyntaxRule.LExprAtom \label{sec:SyntaxRule.LExprAtom}} -\hypertarget{build-lexpratom}{} -The function -\[ - \buildlexpratom(\overname{\parsenode{\Nlexpratom}}{\vparsednode}) \;\aslto\; \overname{\lexpr}{\vastnode} -\] -transforms a parse node $\vparsednode$ into an AST node $\vastnode$. - -\begin{mathpar} -\inferrule[var]{}{ - \buildlexpratom(\Nlexpr(\Tidentifier(\id))) \astarrow - \overname{\LEVar(\id)}{\vastnode} -} -\end{mathpar} - -\begin{mathpar} -\inferrule[slice]{}{ - \buildlexpratom(\Nlexpr(\punnode{\Nlexpratom}, \punnode{\Nslices})) \astarrow - \overname{\LESlice(\astof{\vlexpratom}, \astof{\vslices})}{\vastnode} -} -\end{mathpar} - -\begin{mathpar} -\inferrule[set\_field]{}{ - \buildlexpratom(\Nlexpr(\punnode{\Nlexpratom}, \Tdot, \Tidentifier(\id))) \astarrow - \overname{\LESetField(\astof{\vlexpratom}, \id)}{\vastnode} -} -\end{mathpar} - -\begin{mathpar} -\inferrule[set\_fields]{ - \buildclist[\buildidentity](\vfields) \astarrow \vfieldasts -}{ - { - \begin{array}{r} - \buildlexpratom(\Nlexpr(\punnode{\Nlexpratom}, \Tdot, \Tlbracket, \namednode{\vfields}{\Clist{\Tidentifier}}, \Trbracket)) \astarrow\\ - \overname{\LESetFields(\astof{\vlexpratom}, \vfieldasts)}{\vastnode} - \end{array} - } -} -\end{mathpar} - -\begin{mathpar} -\inferrule[concat]{ - \buildclist[\buildlexpratom](\vlexprs) \astarrow \vlexprasts -}{ - { - \begin{array}{r} - \buildlexpratom(\Nlexpr(\Tlbracket, \namednode{\vlexprs}{\NClist{{\Nlexpratom}}}, \Trbracket)) \astarrow\\ - \overname{\LEConcat(\vlexprasts)}{\vastnode} - \end{array} - } -} -\end{mathpar} - -\section{SyntaxRule.DeclItem \label{sec:SyntaxRule.DeclItem}} -\hypertarget{build-declitem}{} -The function -\[ - \builddeclitem(\overname{\parsenode{\Ndeclitem}}{\vparsednode}) \;\aslto\; \overname{\localdeclitem}{\vastnode} -\] -transforms a parse node $\vparsednode$ into an AST node $\vastnode$. - -\begin{mathpar} -\inferrule[typed]{}{ - { - \begin{array}{r} - \builddeclitem(\Ndeclitem(\punnode{\Nuntypeddeclitem}, \punnode{\Nasty})) \astarrow \\ - \overname{\LDITyped(\astof{\vuntypedlocaldeclitem}, \astof{\vasty})}{\vastnode} - \end{array} - } -} -\end{mathpar} - -\begin{mathpar} -\inferrule[untyped]{}{ - \builddeclitem(\Ndeclitem(\punnode{\Nuntypeddeclitem})) \astarrow - \overname{\astof{\vuntypedlocaldeclitem}}{\vastnode} -} -\end{mathpar} - -\section{SyntaxRule.UntypedDeclItem \label{sec:SyntaxRule.UntypedDeclItem}} -\hypertarget{build-untypeddeclitem}{} -The function -\[ - \builduntypeddeclitem(\overname{\parsenode{\Nuntypeddeclitem}}{\vparsednode}) \;\aslto\; \overname{\localdeclitem}{\vastnode} -\] -transforms a parse node $\vparsednode$ into an AST node $\vastnode$. - -\begin{mathpar} -\inferrule[var]{}{ - \builduntypeddeclitem(\Nuntypeddeclitem(\Tidentifier(\id))) \astarrow - \overname{\LDIVar(\id)}{\vastnode} -} -\end{mathpar} - -\begin{mathpar} -\inferrule[discard]{}{ - \builduntypeddeclitem(\Nuntypeddeclitem(\Tminus)) \astarrow - \overname{\LDIDiscard}{\vastnode} -} -\end{mathpar} - -\begin{mathpar} -\inferrule[tuple]{ - \buildclist[\builddeclitem](\vdeclitems) \astarrow \vdeclitemasts -}{ - { - \begin{array}{r} - \builduntypeddeclitem(\Nuntypeddeclitem(\namednode{\vdeclitems}{\Plisttwo{\Ndeclitem}})) \astarrow \\ - \overname{\LDITuple(\vdeclitemasts)}{\vastnode} - \end{array} - } -} -\end{mathpar} - -\section{SyntaxRule.IntConstraints \label{sec:SyntaxRule.IntConstraints}} -\hypertarget{build-intconstraints}{} -The function -\[ - \buildintconstraints(\overname{\parsenode{\Nintconstraints}}{\vparsednode}) \;\aslto\; \overname{\intconstraints}{\vastnode} -\] -transforms a parse node $\vparsednode$ into an AST node $\vastnode$. - -\begin{mathpar} -\inferrule{ - \buildclist[\buildintconstraint](\vconstraintasts) \astarrow \vconstraintasts -}{ - { - \begin{array}{r} - \buildintconstraints(\Nintconstraints(\Tlbrace, \namednode{\vconstraints}{\NClist{\Nintconstraint}}, \Trbrace)) \astarrow\\ - \overname{\wellconstrained(\vconstraintasts)}{\vastnode} - \end{array} - } -} -\end{mathpar} - -\section{SyntaxRule.IntConstraintsopt \label{sec:SyntaxRule.IntConstraintsopt}} -\hypertarget{build-intconstraintsopt}{} -The function -\[ - \buildintconstraintsopt(\overname{\parsenode{\Nintconstraintsopt}}{\vparsednode}) \;\aslto\; \overname{\intconstraints}{\vastnode} -\] -transforms a parse node $\vparsednode$ into an AST node $\vastnode$. - -\begin{mathpar} -\inferrule[constrained]{}{ - { - \begin{array}{r} - \buildintconstraintsopt(\Nintconstraintsopt(\punnode{\Nintconstraints})) \astarrow \\ - \overname{\astof{\vintconstraints}}{\vastnode} - \end{array} - } -} -\end{mathpar} - -\begin{mathpar} -\inferrule[unconstrained]{}{ - \buildintconstraintsopt(\Nintconstraintsopt(\emptysentence)) \astarrow - \overname{\unconstrained}{\vastnode} -} -\end{mathpar} - -\section{SyntaxRule.IntConstraint \label{sec:SyntaxRule.IntConstraint}} -\hypertarget{build-intconstraint}{} -The function -\[ - \buildintconstraint(\overname{\parsenode{\Nintconstraint}}{\vparsednode}) \;\aslto\; \overname{\intconstraint}{\vastnode} -\] -transforms a parse node $\vparsednode$ into an AST node $\vastnode$. - -\begin{mathpar} -\inferrule[exact]{}{ - \buildintconstraint(\Nintconstraint(\punnode{\Nexpr})) \astarrow - \overname{\ConstraintExact(\astof{\vexpr})}{\vastnode} -} -\end{mathpar} - -\begin{mathpar} -\inferrule[range]{ - \buildexpr(\vfromexpr) \astarrow \astversion{\vfromexpr}\\ - \buildexpr(\vtoexpr) \astarrow \astversion{\vtoexpr}\\ -}{ - { - \begin{array}{r} - \buildintconstraint(\Nintconstraint(\namednode{\vfromexpr}{\Nexpr}, \Tslicing, \namednode{\vtoexpr}{\Nexpr})) \astarrow\\ - \overname{\ConstraintRange(\astversion{\vfromexpr}, \astversion{\vtoexpr})}{\vastnode} - \end{array} - } -} -\end{mathpar} - -\section{SyntaxRule.ExprPattern \label{sec:SyntaxRule.ExprPattern}} -\hypertarget{build-exprpattern}{} -The function -\[ - \buildexprpattern(\overname{\parsenode{\Nexprpattern}}{\vparsednode}) \;\aslto\; \overname{\expr}{\vastnode} -\] -transforms a parse node $\vparsednode$ into an AST node $\vastnode$. - -\begin{mathpar} -\inferrule[literal]{}{ - \buildexprpattern(\Nexprpattern(\punnode{\Nvalue})) \astarrow - \overname{\ELiteral(\astof{\vvalue})}{\vastnode} -} -\end{mathpar} - -\begin{mathpar} - \inferrule[var]{}{ - \buildexprpattern(\Nexprpattern(\Tidentifier(\id))) \astarrow - \overname{\EVar(\id)}{\vastnode} -} -\end{mathpar} - -\begin{mathpar} - \inferrule[binop]{}{ - { - \begin{array}{r} - \buildexprpattern(\Nexprpattern(\punnode{\Nexprpattern}, \punnode{\Nbinop}, \punnode{\Nexpr})) \astarrow\\ - \overname{\EBinop(\astof{\vexprpattern}, \astof{\vbinop}, \astof{\vexpr})}{\vastnode} - \end{array} - } -} -\end{mathpar} - -\begin{mathpar} - \inferrule[unop]{}{ - \buildexprpattern(\Nexprpattern(\punnode{\Nunop}, \punnode{\Nexpr})) \astarrow - \overname{\EUnop(\astof{\vunop}, \astof{\vexpr})}{\vastnode} -} -\end{mathpar} - -\begin{mathpar} - \inferrule[cond]{ - \buildexpr(\vcondexpr) \astarrow \astversion{\vcondexpr}\\ - \buildexpr(\vthenexpr) \astarrow \astversion{\vthenexpr} - }{ - { - \begin{array}{r} - \buildexprpattern\left(\Nexprpattern\left( - \begin{array}{l} - \Tif, \namednode{\vcondexpr}{\Nexpr}, \Tthen, \\ - \wrappedline\ \namednode{\vthenexpr}{\Nexpr}, \punnode{\Neelse} - \end{array} - \right)\right) \astarrow\\ - \overname{\ECond(\astversion{\vcondexpr}, \astversion{\vthenexpr}, \astof{\veelse})}{\vastnode} - \end{array} - } -} -\end{mathpar} - -\begin{mathpar} - \inferrule[call]{ - \buildplist[\buildexpr](\vargs) \astarrow \vexprasts - }{ - \buildexprpattern(\Nexprpattern(\Tidentifier(\id), \namednode{\vargs}{\Plist{\Nexpr}})) \astarrow - \overname{\ECall(\id, \vexprasts)}{\vastnode} -} -\end{mathpar} - -\begin{mathpar} - \inferrule[slice]{}{ - { - \begin{array}{r} - \buildexprpattern(\Nexprpattern(\punnode{\Nexprpattern}, \punnode{\Nslice})) \astarrow\\ - \overname{\ESlice(\astof{\vexprpattern}, \astof{\vslice})}{\vastnode} - \end{array} - } -} -\end{mathpar} - -\begin{mathpar} - \inferrule[get\_field]{}{ - \buildexprpattern(\Nexprpattern(\Nexprpattern, \Tdot, \Tidentifier(\id))) \astarrow - \overname{\EGetField(\astof{\vexpr}, \id)}{\vastnode} -} -\end{mathpar} - -\begin{mathpar} - \inferrule[get\_fields]{ - \buildclist[\buildidentity](\vids) \astarrow \vidasts - }{ - { - \begin{array}{r} - \buildexprpattern(\Nexprpattern(\punnode{\Nexprpattern}, \Tdot, \Tlbracket, \namednode{\vids}{\NClist{\Tidentifier}}, \Trbracket)) \astarrow\\ - \overname{\EGetFields(\astof{\vexprpattern}, \vidasts)}{\vastnode} - \end{array} - } -} -\end{mathpar} - -\begin{mathpar} - \inferrule[concat]{ - \buildclist[\buildexpr](\vexprs) \astarrow \vexprasts - }{ - \buildexprpattern(\Nexprpattern(\Tlbracket, \namednode{\vexprs}{\NClist{\Nexpr}}, \Trbracket)) \astarrow - \overname{\EConcat(\vexprasts)}{\vastnode} -} -\end{mathpar} - -\begin{mathpar} - \inferrule[atc]{}{ - { - \begin{array}{r} - \buildexprpattern(\Nexprpattern(\punnode{\Nexprpattern}, \Tas, \punnode{\Nty})) \astarrow\\ - \overname{\EATC(\astof{\vexprpattern}, \astof{\tty})}{\vastnode} - \end{array} - } -} -\end{mathpar} - -\begin{mathpar} - \inferrule[atc\_int\_constraints]{}{ - { - \begin{array}{r} - \buildexprpattern(\Nexprpattern(\punnode{\Nexprpattern}, \Tas, \punnode{\Nintconstraints})) \astarrow\\ - \overname{\EATC(\astof{\vexprpattern}, \TInt(\astof{\vintconstraints}))}{\vastnode} -\end{array} -} -} -\end{mathpar} - -\begin{mathpar} - \inferrule[pattern\_set]{}{ - { - \begin{array}{r} - \buildexprpattern(\Nexprpattern(\punnode{\Nexprpattern}, \Tin, \punnode{\Npatternset})) \astarrow\\ - \overname{\EPattern(\astof{\vexprpattern}, \astof{\vpatternset})}{\vastnode} -\end{array} -} -} -\end{mathpar} - -\begin{mathpar} - \inferrule[pattern\_mask]{}{ - { - \begin{array}{r} - \buildexprpattern(\Nexprpattern(\punnode{\Nexprpattern}, \Tin, \Tmasklit(\vm))) \astarrow\\ - \overname{\EPattern(\astof{\vexprpattern}, \PatternMask(\vm))}{\vastnode} -\end{array} -} -} -\end{mathpar} - -\begin{mathpar} - \inferrule[unknown]{}{ - \buildexprpattern(\Nexprpattern(\Tunknown, \Tcolon, \punnode{\Nty})) \astarrow - \overname{\EUnknown(\astof{\tty})}{\vastnode} -} -\end{mathpar} - -\begin{mathpar} - \inferrule[record]{ - \buildclist[\buildfieldassign](\vfieldassigns) \astarrow \vfieldassignasts - }{ - { - \begin{array}{r} - \buildexprpattern\left(\Nexprpattern\left( - \begin{array}{l} - \Tidentifier(\vt), \Tlbrace, \\ - \wrappedline\ \namednode{\vfieldassigns}{\Clist{\Nfieldassign}}, \\ - \wrappedline\ \Trbrace - \end{array} - \right)\right) \\ - \astarrow\ \overname{\ERecord(\TNamed(\vt), \vfieldassignasts)}{\vastnode} -\end{array} -} -} -\end{mathpar} - -\begin{mathpar} - \inferrule[sub\_expr]{}{ - \buildexprpattern(\Nexprpattern(\Tlpar, \punnode{\Nexprpattern}, \Trpar)) \astarrow - \overname{\astof{\vexprpattern}}{\vastnode} -} -\end{mathpar} - -\section{SyntaxRule.PatternSet \label{sec:SyntaxRule.PatternSet}} -\hypertarget{build-patternset}{} -The function -\[ - \buildpatternset(\overname{\parsenode{\Npatternset}}{\vparsednode}) \;\aslto\; \overname{\pattern}{\vastnode} -\] -transforms a parse node $\vparsednode$ into an AST node $\vastnode$. - -\begin{mathpar} -\inferrule[not]{}{ - { - \begin{array}{r} - \buildpatternset(\Npatternset(\Tbnot, \Tlbrace, \punnode{\Npatternlist}, \Trbrace)) \astarrow\\ - \overname{\PatternNot(\astof{\vpatternlist})}{\vastnode} - \end{array} - } -} -\end{mathpar} - -\begin{mathpar} -\inferrule[list]{}{ - \buildpatternset(\Npatternset(\Tlbrace, \punnode{\Npatternlist}, \Trbrace)) \astarrow - \overname{\astof{\vpatternlist}}{\vastnode} -} -\end{mathpar} - -\section{SyntaxRule.PatternList \label{sec:SyntaxRule.PatternList}} -\hypertarget{build-patternlist}{} -The function -\[ - \buildpatternlist(\overname{\parsenode{\Npatternlist}}{\vparsednode}) \;\aslto\; \overname{\pattern}{\vastnode} -\] -transforms a parse node $\vparsednode$ into an AST node $\vastnode$. - -\begin{mathpar} -\inferrule{ - \buildclist[\buildpattern](\vpatterns) \astarrow \vpatternasts -}{ - { - \begin{array}{r} - \buildpatternlist(\Npatternlist(\namednode{\vpatterns}{\NClist{\Npattern}})) \astarrow\\ - \overname{\PatternAny(\vpatternasts)}{\vastnode} - \end{array} - } -} -\end{mathpar} - -\section{SyntaxRule.Pattern \label{sec:SyntaxRule.Pattern}} -\hypertarget{build-pattern}{} -The function -\[ - \buildpattern(\overname{\parsenode{\Npattern}}{\vparsednode}) \;\aslto\; \overname{\pattern}{\vastnode} -\] -transforms a parse node $\vparsednode$ into an AST node $\vastnode$. - -\begin{mathpar} -\inferrule[single]{}{ - \buildpattern(\Npattern(\punnode{\Nexprpattern})) \astarrow - \overname{\PatternSingle(\astof{\vexprpattern})}{\vastnode} -} -\end{mathpar} - -\begin{mathpar} -\inferrule[range]{}{ - { - \begin{array}{r} - \buildpattern(\Npattern(\punnode{\Nexprpattern}, \Tslicing, \punnode{\Nexpr})) \astarrow\\ - \overname{\PatternRange(\astof{\vexprpattern}, \astof{\vexpr})}{\vastnode} - \end{array} - } -} -\end{mathpar} - -\begin{mathpar} -\inferrule[all]{}{ - \buildpattern(\Npattern(\Tminus)) \astarrow - \overname{\PatternAll}{\vastnode} -} -\end{mathpar} - -\begin{mathpar} -\inferrule[leq]{}{ - \buildpattern(\Npattern(\Tleq, \punnode{\Nexpr})) \astarrow - \overname{\PatternLeq(\astof{\vexpr})}{\vastnode} -} -\end{mathpar} - -\begin{mathpar} -\inferrule[geq]{}{ - \buildpattern(\Npattern(\Tgeq, \punnode{\Nexpr})) \astarrow - \overname{\PatternGeq(\astof{\vexpr})}{\vastnode} -} -\end{mathpar} - -\begin{mathpar} -\inferrule[mask]{}{ - \buildpattern(\Npattern(\Tmasklit(\vm))) \astarrow - \overname{\PatternMask(\vm)}{\vastnode} -} -\end{mathpar} - -\begin{mathpar} -\inferrule[tuple]{ - \buildplist[\buildpattern](\vpatterns) \astarrow \vpatternasts -}{ - \buildpattern(\Npattern(\namednode{\vpatterns}{\Plisttwo{\Npattern}})) \astarrow - \overname{\PatternTuple(\vpatternasts)}{\vastnode} -} -\end{mathpar} - -\begin{mathpar} -\inferrule[set]{}{ - \buildpattern(\Npattern(\punnode{\Npatternset})) \astarrow - \overname{\astof{\vpatternset}}{\vastnode} -} -\end{mathpar} - -\section{SyntaxRule.Fields \label{sec:SyntaxRule.Fields}} -\hypertarget{build-fields}{} -The function -\[ - \buildfields(\overname{\parsenode{\Nfields}}{\vparsednode}) \;\aslto\; \overname{\Field^*}{\vastnode} -\] -transforms a parse node $\vparsednode$ into an AST node $\vastnode$. - -\begin{mathpar} -\inferrule{ - \buildtclist[\buildtypedidentifier](\vfields) \astarrow \vfieldasts -}{ - \buildfields(\Nfields(\Tlbrace, \namednode{\vfields}{\TClist{\Ntypedidentifier}}, \Trbrace)) \astarrow - \overname{\vfieldasts}{\vastnode} -} -\end{mathpar} - -\section{SyntaxRule.FieldsOpt \label{sec:SyntaxRule.FieldsOpt}} -\hypertarget{build-fieldsopt}{} -The function -\[ - \buildfieldsopt(\overname{\parsenode{\Nfieldsopt}}{\vparsednode}) \;\aslto\; \overname{\Field^*}{\vastnode} -\] -transforms a parse node $\vparsednode$ into an AST node $\vastnode$. - -\begin{mathpar} -\inferrule[fields]{}{ - \buildfieldsopt(\Nfieldsopt(\punnode{\Nfields})) \astarrow - \overname{\astof{\vfields}}{\vastnode} -} -\end{mathpar} - -\begin{mathpar} -\inferrule[empty]{}{ - \buildfieldsopt(\Nfieldsopt(\emptysentence)) \astarrow - \overname{\emptylist}{\vastnode} -} -\end{mathpar} - -\section{SyntaxRule.NSlices \label{sec:SyntaxRule.NSlices}} -\hypertarget{build-nslices}{} -The function -\[ - \buildnslices(\overname{\parsenode{\Nnslices}}{\vparsednode}) \;\aslto\; \overname{\slice^+}{\vastnode} -\] -transforms a parse node $\vparsednode$ into an AST node $\vastnode$. - -\begin{mathpar} -\inferrule{ - \buildclist[\buildslice](\vslices) \astarrow \vsliceasts -}{ - \buildnslices(\Nnslices(\Tlbracket, \namednode{\vslices}{\NClist{\Nslice}}, \Trbracket)) \astarrow - \overname{\vsliceasts}{\vastnode} -} -\end{mathpar} - -\section{SyntaxRule.Slices \label{sec:SyntaxRule.Slices}} -\hypertarget{build-slices}{} -The function -\[ - \buildslices(\overname{\parsenode{\Nslices}}{\vparsednode}) \;\aslto\; \overname{\slice^*}{\vastnode} -\] -transforms a parse node $\vparsednode$ into an AST node $\vastnode$. - -\begin{mathpar} -\inferrule{ - \buildclist[\buildslice](\vslices) \astarrow \vsliceasts -}{ - \buildslices(\Nslices(\Tlbracket, \namednode{\vslices}{\Clist{\Nslice}}, \Trbracket)) \astarrow - \overname{\vsliceasts}{\vastnode} -} -\end{mathpar} - -\section{SyntaxRule.Slice \label{sec:SyntaxRule.Slice}} -\hypertarget{build-slice}{} -The function -\[ - \buildslice(\overname{\parsenode{\Nslice}}{\vparsednode}) \;\aslto\; \overname{\slice}{\vastnode} -\] -transforms a parse node $\vparsednode$ into an AST node $\vastnode$. - -\begin{mathpar} -\inferrule[single]{}{ - \buildslices(\Nslice(\punnode{\Nexpr})) \astarrow - \overname{\SliceSingle(\astof{\vexpr})}{\vastnode} -} -\end{mathpar} - -\begin{mathpar} -\inferrule[range]{ - \buildexpr(\veone) \astarrow \astversion{\veone}\\ - \buildexpr(\vetwo) \astarrow \astversion{\vetwo} -}{ - \buildslices(\Nslice(\namednode{\veone}{\Nexpr}, \Tcolon, \namednode{\vetwo}{\Nexpr})) \astarrow - \overname{\SliceRange(\astversion{\veone}, \astversion{\vetwo})}{\vastnode} -} -\end{mathpar} - -\begin{mathpar} -\inferrule[length]{ - \buildexpr(\veone) \astarrow \astversion{\veone}\\ - \buildexpr(\vetwo) \astarrow \astversion{\vetwo} -}{ - \buildslices(\Nslice(\namednode{\veone}{\Nexpr}, \Tpluscolon, \namednode{\vetwo}{\Nexpr})) \astarrow - \overname{\SliceLength(\astversion{\veone}, \astversion{\vetwo})}{\vastnode} -} -\end{mathpar} - -\begin{mathpar} -\inferrule[star]{ - \buildexpr(\veone) \astarrow \astversion{\veone}\\ - \buildexpr(\vetwo) \astarrow \astversion{\vetwo} -}{ - \buildslices(\Nslice(\namednode{\veone}{\Nexpr}, \Tstarcolon, \namednode{\vetwo}{\Nexpr})) \astarrow - \overname{\SliceStar(\astversion{\veone}, \astversion{\vetwo})}{\vastnode} -} -\end{mathpar} - -\section{SyntaxRule.Bitfields \label{sec:SyntaxRule.Bitfields}} -\hypertarget{build-bitfields}{} -The function -\[ - \buildbitfields(\overname{\parsenode{\Nbitfields}}{\vparsednode}) \;\aslto\; \overname{\bitfield^*}{\vastnode} -\] -transforms a parse node $\vparsednode$ into an AST node $\vastnode$. - -\begin{mathpar} -\inferrule{ - \buildtclist[\buildbitfield](\vbitfields) \astarrow \vbitfieldasts -}{ - \buildbitfields(\Nbitfields(\Tlbrace, \namednode{\vbitfields}{\TClist{\Nbitfield}}, \Trbrace)) \astarrow - \overname{\vbitfieldasts}{\vastnode} -} -\end{mathpar} - -\section{SyntaxRule.Bitfield \label{sec:SyntaxRule.Bitfield}} -\hypertarget{build-bitfield}{} -The function -\[ - \buildbitfield(\overname{\parsenode{\Nbitfield}}{\vparsednode}) \;\aslto\; \overname{\bitfield}{\vastnode} -\] -transforms a parse node $\vparsednode$ into an AST node $\vastnode$. - -\begin{mathpar} -\inferrule[simple]{}{ - \buildbitfields(\Nbitfield(\punnode{\Nnslices}, \Tidentifier(\vx))) \astarrow - \overname{\BitFieldSimple(\vx, \astof{\vslices})}{\vastnode} -} -\end{mathpar} - -\begin{mathpar} -\inferrule[nested]{}{ - { - \begin{array}{r} - \buildbitfields(\Nbitfield(\punnode{\Nnslices}, \Tidentifier(\vx), \punnode{\Nbitfields})) \astarrow\\ - \overname{\BitFieldNested(\vx, \astof{\vslices}, \astof{\vbitfields})}{\vastnode} - \end{array} - } -} -\end{mathpar} - -\begin{mathpar} -\inferrule[type]{}{ - \buildbitfields(\Nbitfield(\punnode{\Nnslices}, \Tidentifier(\vx), \Tcolon, \punnode{\Nty})) \astarrow - \overname{\BitFieldType(\vx, \astof{\vslices}, \astof{\tty})}{\vastnode} -} -\end{mathpar} - -\section{SyntaxRule.Ty \label{sec:SyntaxRule.Ty}} -\hypertarget{build-ty}{} -The function -\[ - \buildty(\overname{\parsenode{\Nty}}{\vparsednode}) \;\aslto\; \overname{\ty}{\vastnode} -\] -transforms a parse node $\vparsednode$ into an AST node $\vastnode$. - -\begin{mathpar} -\inferrule[integer]{}{ - \buildty(\Nty(\Tinteger, \punnode{\Nintconstraintsopt})) \astarrow - \overname{\TInt(\astof{\vintconstraintsopt})}{\vastnode} -} -\end{mathpar} - -\begin{mathpar} -\inferrule[real]{}{ - \buildty(\Nty(\Treal)) \astarrow - \overname{\TReal}{\vastnode} -} -\end{mathpar} - -\begin{mathpar} -\inferrule[boolean]{}{ - \buildty(\Nty(\Tboolean)) \astarrow - \overname{\TBool}{\vastnode} -} -\end{mathpar} - -\begin{mathpar} -\inferrule[string]{}{ - \buildty(\Nty(\Tstring)) \astarrow - \overname{\TString}{\vastnode} -} -\end{mathpar} - -\begin{mathpar} -\inferrule[bit]{}{ - \buildty(\Nty(\Tbit)) \astarrow - \overname{\TBits(\ELiteral(\lint(1)), \emptylist)}{\vastnode} -} -\end{mathpar} - -\begin{mathpar} -\inferrule[bits]{ - \buildlist[\buildbitfield](\vbitfields) \astarrow \vbitfieldasts -}{ - { - \begin{array}{r} - \buildty(\Nty(\Tbits, \Tlpar, \punnode{\Nexpr}, \Trpar, \namednode{\vbitfields}{\maybeemptylist{\Nbitfields}})) \astarrow\\ - \overname{\TBits(\astof{\vexpr}, \vbitfieldasts)}{\vastnode} - \end{array} - } -} -\end{mathpar} - -\begin{mathpar} -\inferrule[tuple]{ - \buildplist[\buildty](\vtypes) \astarrow \vtypeasts -}{ - \buildty(\Nty(\namednode{\vtypes}{\Plist{\Nty}})) \astarrow - \overname{\TTuple(\vtypeasts)}{\vastnode} -} -\end{mathpar} - -\begin{mathpar} -\inferrule[named]{}{ - \buildty(\Nty(\Tidentifier(\id))) \astarrow - \overname{\TNamed(\id)}{\vastnode} -} -\end{mathpar} - -\begin{mathpar} -\inferrule[array]{}{ - \buildty(\Nty(\Tarray, \Tlbracket, \punnode{\Nexpr}, \Trbracket, \Tof, \punnode{\Nty})) \astarrow - \overname{\TArray(\ArrayLengthExpr(\astof{\vexpr}), \astof{\tty})}{\vastnode} -} -\end{mathpar} - -\section{SyntaxRule.TyDecl \label{sec:SyntaxRule.TyDecl}} -\hypertarget{build-tydecl}{} -The function -\[ - \buildtydecl(\overname{\parsenode{\Ntydecl}}{\vparsednode}) \;\aslto\; \overname{\ty}{\vastnode} -\] -transforms a parse node $\vparsednode$ into an AST node $\vastnode$. - -\begin{mathpar} -\inferrule[ty]{}{ - \buildtydecl(\Ntydecl(\punnode{\Nty})) \astarrow - \overname{\astof{\tty}}{\vastnode} -} -\end{mathpar} - -\begin{mathpar} -\inferrule[enumeration]{ - \buildtclist[\buildidentity](\vids) \astarrow \vidasts -}{ - { - \begin{array}{r} - \buildtydecl(\Ntydecl(\Tenumeration, \Tlbrace, \namednode{\vids}{\NTClist{\Tidentifier}}, \Trbrace)) \astarrow\\ - \overname{\TEnum(\vidasts)}{\vastnode} -\end{array} - } -} -\end{mathpar} - -\begin{mathpar} -\inferrule[record]{}{ - \buildtydecl(\Ntydecl(\Trecord, \punnode{\Nfieldsopt})) \astarrow - \overname{\TRecord(\astof{\vfieldsopt})}{\vastnode} -} -\end{mathpar} - -\begin{mathpar} -\inferrule[exception]{}{ - \buildtydecl(\Ntydecl(\Texception, \punnode{\Nfieldsopt})) \astarrow - \overname{\TException(\astof{\vfieldsopt})}{\vastnode} -} -\end{mathpar} - -\section{SyntaxRule.FieldAssign \label{sec:SyntaxRule.FieldAssign}} -\hypertarget{build-fieldassign}{} -The function -\[ - \buildfieldassign(\overname{\parsenode{\Nfieldassign}}{\vparsednode}) \;\aslto\; \overname{(\identifier\times\expr)}{\vastnode} -\] -transforms a parse node $\vparsednode$ into an AST node $\vastnode$. - -\begin{mathpar} -\inferrule{}{ - \buildfieldassign(\Nfieldassign(\Tidentifier(\id), \Teq, \punnode{\Nexpr})) \astarrow - \overname{(\id, \astof{\vexpr})}{\vastnode} -} -\end{mathpar} - -\section{SyntaxRule.EElse \label{sec:SyntaxRule.EElse}} -\hypertarget{build-eelse}{} -The function -\[ - \buildeelse(\overname{\parsenode{\Nfieldassign}}{\vparsednode}) \;\aslto\; \overname{\expr}{\vastnode} -\] -transforms a parse node $\vparsednode$ into an AST node $\vastnode$. - -\begin{mathpar} -\inferrule[else]{}{ - \buildeelse(\Neelse(\Telse, \punnode{\Nexpr})) \astarrow - \overname{\astof{\vexpr}}{\vastnode} -} -\end{mathpar} - -\begin{mathpar} -\inferrule[else\_if]{ - \buildexpr(\vcondexpr) \astarrow \astversion{\vcondexpr}\\ - \buildexpr(\vthenexpr) \astarrow \astversion{\vthenexpr} -}{ - { - \begin{array}{r} - \buildeelse\left(\Neelse\left( - \begin{array}{l} - \Telseif, \namednode{\vcondexpr}{\Nexpr}, \\ - \wrappedline\ \Tthen, \namednode{\vthenexpr}{\Nexpr}, \punnode{\Neelse} - \end{array} - \right)\right) \astarrow\\ - \overname{\ECond(\astversion{\vcondexpr}, \astversion{\vthenexpr}, \astof{\veelse})}{\vastnode} -\end{array} - } -} -\end{mathpar} - -\section{SyntaxRule.Expr \label{sec:SyntaxRule.Expr}} -\hypertarget{build-expr}{} -The function -\[ - \buildexpr(\overname{\parsenode{\Nexpr}}{\vparsednode}) \;\aslto\; \overname{\expr}{\vastnode} -\] -transforms a parse node $\vparsednode$ into an AST node $\vastnode$. - -\begin{mathpar} -\inferrule[literal]{}{ - \buildexpr(\overname{\Nexpr(\punnode{\Nvalue})}{\vparsednode}) \astarrow - \overname{\ELiteral(\astof{\vvalue})}{\vastnode} -} -\end{mathpar} - -\begin{mathpar} - \inferrule[var]{}{ - \buildexpr(\overname{\Nexpr(\Tidentifier(\id))}{\vparsednode}) \astarrow - \overname{\EVar(\id)}{\vastnode} -} -\end{mathpar} - -\begin{mathpar} - \inferrule[binop]{ - \buildexpr(\veone) \astarrow \astversion{\veone}\\ - \buildexpr(\vetwo) \astarrow \astversion{\vetwo} - }{ - { - \begin{array}{r} - \buildexpr(\overname{\Nexpr(\namednode{\veone}{\Nexpr}, \punnode{\Nbinop}, \namednode{\vetwo}{\Nexpr})}{\vparsednode}) \astarrow\\ - \overname{\EBinop(\astversion{\veone}, \astof{\vbinop}, \astversion{\vetwo})}{\vastnode} - \end{array} - } -} -\end{mathpar} - -\begin{mathpar} - \inferrule[unop]{}{ - \buildexpr(\overname{\Nexpr(\punnode{\Nunop}, \punnode{\Nexpr})}{\vparsednode}) \astarrow - \overname{\EUnop(\astof{\vunop}, \astof{\vexpr})}{\vastnode} -} -\end{mathpar} - -\begin{mathpar} - \inferrule[cond]{ - \buildexpr(\vcondexpr) \astarrow \astversion{\vcondexpr}\\ - \buildexpr(\vthenexpr) \astarrow \astversion{\vthenexpr} - }{ - { - \begin{array}{r} - \buildexpr\left(\overname{\Nexpr\left( - \begin{array}{l} - \Tif, \namednode{\vcondexpr}{\Nexpr}, \Tthen, \\ - \wrappedline\ \namednode{\vthenexpr}{\Nexpr}, \punnode{\Neelse} - \end{array} - \right)}{\vparsednode}\right) \astarrow\\ - \overname{\ECond(\astversion{\vcondexpr}, \astversion{\vthenexpr}, \astof{\veelse})}{\vastnode} - \end{array} - } -} -\end{mathpar} - -\begin{mathpar} - \inferrule[call]{ - \buildplist[\buildexpr](\vargs) \astarrow \vexprasts - }{ - \buildexpr(\overname{\Nexpr(\Tidentifier(\id), \namednode{\vargs}{\Plist{\Nexpr}})}{\vparsednode}) \astarrow - \overname{\ECall(\id, \vexprasts)}{\vastnode} -} -\end{mathpar} - -\begin{mathpar} - \inferrule[slice]{}{ - { - \begin{array}{r} - \buildexpr(\overname{\Nexpr(\punnode{\Nexpr}, \punnode{\Nslice})}{\vparsednode}) \astarrow\\ - \overname{\ESlice(\astof{\vexpr}, \astof{\vslice})}{\vastnode} - \end{array} - } -} -\end{mathpar} - -\begin{mathpar} - \inferrule[get\_field]{}{ - \buildexpr(\overname{\Nexpr(\Nexpr, \Tdot, \Tidentifier(\id))}{\vparsednode}) \astarrow - \overname{\EGetField(\astof{\vexpr}, \id)}{\vastnode} -} -\end{mathpar} - -\begin{mathpar} - \inferrule[get\_fields]{ - \buildclist[\buildidentity](\vids) \astarrow \vidasts - }{ - { - \begin{array}{r} - \buildexpr(\overname{\Nexpr(\punnode{\Nexpr}, \Tdot, \Tlbracket, \namednode{\vids}{\NClist{\Tidentifier}}, \Trbracket)}{\vparsednode}) \astarrow\\ - \overname{\EGetFields(\astof{\vexpr}, \vidasts)}{\vastnode} - \end{array} - } -} -\end{mathpar} - -\begin{mathpar} - \inferrule[concat]{ - \buildclist[\buildexpr](\vexprs) \astarrow \vexprasts - }{ - \buildexpr(\overname{\Nexpr(\Tlbracket, \namednode{\vexprs}{\NClist{\Nexpr}}, \Trbracket)}{\vparsednode}) \astarrow - \overname{\EConcat(\vexprasts)}{\vastnode} -} -\end{mathpar} - -\begin{mathpar} - \inferrule[atc]{}{ - { - \begin{array}{r} - \buildexpr(\overname{\Nexpr(\punnode{\Nexpr}, \Tas, \punnode{\Nty})}{\vparsednode}) \astarrow\\ - \overname{\EATC(\astof{\vexpr}, \astof{\tty})}{\vastnode} - \end{array} - } -} -\end{mathpar} - -\begin{mathpar} - \inferrule[atc\_int\_constraints]{}{ - { - \begin{array}{r} - \buildexpr(\overname{\Nexpr(\punnode{\Nexpr}, \Tas, \punnode{\Nintconstraints})}{\vparsednode}) \astarrow\\ - \overname{\EATC(\astof{\vexpr}, \TInt(\astof{\vintconstraints}))}{\vastnode} -\end{array} -} -} -\end{mathpar} - -\begin{mathpar} - \inferrule[pattern\_set]{}{ - { - \begin{array}{r} - \buildexpr(\overname{\Nexpr(\punnode{\Nexpr}, \Tin, \punnode{\Npatternset})}{\vparsednode}) \astarrow\\ - \overname{\EPattern(\astof{\vexpr}, \astof{\vpatternset})}{\vastnode} -\end{array} -} -} -\end{mathpar} - -\begin{mathpar} - \inferrule[pattern\_mask]{}{ - { - \begin{array}{r} - \buildexpr(\overname{\Nexpr(\punnode{\Nexpr}, \Tin, \Tmasklit(\vm))}{\vparsednode}) \astarrow\\ - \overname{\EPattern(\astof{\vexpr}, \PatternMask(\vm))}{\vastnode} -\end{array} -} -} -\end{mathpar} - -\begin{mathpar} - \inferrule[unknown]{}{ - \buildexpr(\overname{\Nexpr(\Tunknown, \Tcolon, \punnode{\Nty})}{\vparsednode}) \astarrow - \overname{\EUnknown(\astof{\tty})}{\vastnode} -} -\end{mathpar} - -\begin{mathpar} - \inferrule[record]{ - \buildclist[\buildfieldassign](\vfieldassigns) \astarrow \vfieldassignasts - }{ - { - \begin{array}{r} - \buildexpr\left(\overname{\Nexpr\left( - \begin{array}{l} - \Tidentifier(\vt), \Tlbrace, \\ - \wrappedline\ \namednode{\vfieldassigns}{\Clist{\Nfieldassign}}, \\ - \wrappedline\ \Trbrace - \end{array} - \right)}{\vparsednode}\right) \\ - \astarrow\ \overname{\ERecord(\TNamed(\vt), \vfieldassignasts)}{\vastnode} -\end{array} -} -} -\end{mathpar} - -\begin{mathpar} - \inferrule[sub\_expr]{}{ - \buildexpr(\overname{\Nexpr(\Tlpar, \punnode{\Nexpr}, \Trpar)}{\vparsednode}) \astarrow - \overname{\astof{\vexpr}}{\vastnode} -} -\end{mathpar} - -\begin{mathpar} - \inferrule[tuple]{ - \buildplist[\buildexpr](\vexprs) \astarrow \vexprasts - }{ - \buildexpr(\overname{\Nexpr(\namednode{\vexprs}{\Plisttwo{\Nexpr}})}{\vparsednode}) \astarrow - \overname{\ETuple(\vexprasts)}{\vastnode} -} -\end{mathpar} - -\section{SyntaxRule.Value \label{sec:SyntaxRule.Value}} -\hypertarget{build-value}{} -The function -\[ - \buildvalue(\overname{\parsenode{\Nvalue}}{\vparsednode}) \;\aslto\; \overname{\literal}{\vastnode} -\] -transforms a parse node $\vparsednode$ into an AST node $\vastnode$. - -\begin{mathpar} -\inferrule[integer]{}{ - \buildvalue(\Nvalue(\Tintlit(\vi))) \astarrow - \overname{\lint(\vi)}{\vastnode} -} -\end{mathpar} - -\begin{mathpar} -\inferrule[boolean]{}{ - \buildvalue(\Nvalue(\Tboollit(\vb))) \astarrow - \overname{\lbool(\vb)}{\vastnode} -} -\end{mathpar} - -\begin{mathpar} -\inferrule[real]{}{ - \buildvalue(\Nvalue(\Treallit(\vr))) \astarrow - \overname{\lreal(\vr)}{\vastnode} -} -\end{mathpar} - -\begin{mathpar} -\inferrule[bitvector]{}{ - \buildvalue(\Nvalue(\Tbitvectorlit(\vb))) \astarrow - \overname{\lbitvector(\vb)}{\vastnode} -} -\end{mathpar} - -\begin{mathpar} -\inferrule[string]{}{ - \buildvalue(\Nvalue(\Tstringlit(\vs))) \astarrow - \overname{\lstring(\vs)}{\vastnode} -} -\end{mathpar} - -\section{SyntaxRule.Unop \label{sec:SyntaxRule.Unop}} -\hypertarget{build-unop}{} -The function -\[ - \buildunop(\overname{\parsenode{\Nunop}}{\vparsednode}) \;\aslto\; \overname{\unop}{\vastnode} -\] -transforms a parse node $\vparsednode$ into an AST node $\vastnode$. - -\begin{mathpar} -\inferrule[bnot]{}{ - \buildunop(\Nunop(\Tbnot)) \astarrow \overname{\BNOT}{\vastnode} -} -\end{mathpar} - -\begin{mathpar} -\inferrule[neg]{}{ - \buildunop(\Nunop(\Tminus)) \astarrow \overname{\NEG}{\vastnode} -} -\end{mathpar} - -\begin{mathpar} -\inferrule[not]{}{ - \buildunop(\Nunop(\Tnot)) \astarrow \overname{\NOT}{\vastnode} -} -\end{mathpar} - -\section{SyntaxRule.Binop \label{sec:SyntaxRule.Binop}} -\hypertarget{build-binop}{} -The function -\[ - \buildbinop(\overname{\parsenode{\Nbinop}}{\vparsednode}) \;\aslto\; \overname{\binop}{\vastnode} -\] -transforms a parse node $\vparsednode$ into an AST node $\vastnode$. - -\begin{mathpar} -\inferrule[]{}{ - \buildbinop(\Nbinop(\Tand)) \astarrow \overname{\AND}{\vastnode} -} -\end{mathpar} - -\begin{mathpar} -\inferrule[]{}{ - \buildbinop(\Nbinop(\Tband)) \astarrow \overname{\BAND}{\vastnode} -} -\end{mathpar} - -\begin{mathpar} -\inferrule[]{}{ - \buildbinop(\Nbinop(\Tbor)) \astarrow \overname{\BOR}{\vastnode} -} -\end{mathpar} - -\begin{mathpar} -\inferrule[]{}{ - \buildbinop(\Nbinop(\Tbeq)) \astarrow \overname{\EQOP}{\vastnode} -} -\end{mathpar} - -\begin{mathpar} -\inferrule[]{}{ - \buildbinop(\Nbinop(\Tdiv)) \astarrow \overname{\DIV}{\vastnode} -} -\end{mathpar} - -\begin{mathpar} -\inferrule[]{}{ - \buildbinop(\Nbinop(\Tdivrm)) \astarrow \overname{\DIVRM}{\vastnode} -} -\end{mathpar} - -\begin{mathpar} -\inferrule[]{}{ - \buildbinop(\Nbinop(\Txor)) \astarrow \overname{\XOR}{\vastnode} -} -\end{mathpar} - -\begin{mathpar} -\inferrule[]{}{ - \buildbinop(\Nbinop(\Teqop)) \astarrow \overname{\EQOP}{\vastnode} -} -\end{mathpar} - -\begin{mathpar} -\inferrule[]{}{ - \buildbinop(\Nbinop(\Tneq)) \astarrow \overname{\NEQ}{\vastnode} -} -\end{mathpar} - -\begin{mathpar} -\inferrule[]{}{ - \buildbinop(\Nbinop(\Tgt)) \astarrow \overname{\GT}{\vastnode} -} -\end{mathpar} - -\begin{mathpar} -\inferrule[]{}{ - \buildbinop(\Nbinop(\Tgeq)) \astarrow \overname{\GEQ}{\vastnode} -} -\end{mathpar} - -\begin{mathpar} -\inferrule[]{}{ - \buildbinop(\Nbinop(\Timpl)) \astarrow \overname{\IMPL}{\vastnode} -} -\end{mathpar} - -\begin{mathpar} -\inferrule[]{}{ - \buildbinop(\Nbinop(\Tlt)) \astarrow \overname{\LT}{\vastnode} -} -\end{mathpar} - -\begin{mathpar} -\inferrule[]{}{ - \buildbinop(\Nbinop(\Tleq)) \astarrow \overname{\LEQ}{\vastnode} -} -\end{mathpar} - -\begin{mathpar} -\inferrule[]{}{ - \buildbinop(\Nbinop(\Tplus)) \astarrow \overname{\PLUS}{\vastnode} -} -\end{mathpar} - -\begin{mathpar} -\inferrule[]{}{ - \buildbinop(\Nbinop(\Tminus)) \astarrow \overname{\MINUS}{\vastnode} -} -\end{mathpar} - -\begin{mathpar} -\inferrule[]{}{ - \buildbinop(\Nbinop(\Tmod)) \astarrow \overname{\MOD}{\vastnode} -} -\end{mathpar} - -\begin{mathpar} -\inferrule[]{}{ - \buildbinop(\Nbinop(\Tmul)) \astarrow \overname{\MUL}{\vastnode} -} -\end{mathpar} - -\begin{mathpar} -\inferrule[]{}{ - \buildbinop(\Nbinop(\Tor)) \astarrow \overname{\OR}{\vastnode} -} -\end{mathpar} - -\begin{mathpar} -\inferrule[]{}{ - \buildbinop(\Nbinop(\Trdiv)) \astarrow \overname{\RDIV}{\vastnode} -} -\end{mathpar} - -\begin{mathpar} -\inferrule[]{}{ - \buildbinop(\Nbinop(\Tshl)) \astarrow \overname{\SHL}{\vastnode} -} -\end{mathpar} - -\begin{mathpar} -\inferrule[]{}{ - \buildbinop(\Nbinop(\Tshr)) \astarrow \overname{\SHR}{\vastnode} -} -\end{mathpar} - -\begin{mathpar} -\inferrule[]{}{ - \buildbinop(\Nbinop(\Tpow)) \astarrow \overname{\POW}{\vastnode} -} -\end{mathpar} - -\begin{mathpar} -\inferrule[]{}{ - \buildbinop(\Nbinop(\Tconcat)) \astarrow \overname{\tododefine{CONCAT}}{\vastnode} -} -\end{mathpar} - -\section{SyntaxRule.StmtFromList \label{sec:SyntaxRule.StmtFromList}} -\hypertarget{def-stmtfromlist}{} -The function -\[ -\stmtfromlist(\overname{\stmt^*}{\vstmts}) \aslto \overname{\stmt}{\news} -\] -builds a statement $\news$ from a possibly-empty list of statements $\vstmts$. - -\begin{mathpar} -\inferrule[empty]{ -}{ - \stmtfromlist(\overname{\emptylist}{\vstmts}) \astarrow \overname{\SPass}{\news} -} -\and -\inferrule[non\_empty]{ - \stmtfromlist(\vstmtsone) \astarrow \vsone\\ - \sequencestmts(\vs, \vsone) \astarrow \news -}{ - \stmtfromlist(\overname{[\vs] \concat \vstmtsone}{\vstmts}) \astarrow \news -} -\end{mathpar} - -\section{SyntaxRule.SequenceStmts \label{sec:SyntaxRule.SequenceStmts}} -\hypertarget{def-sequencestmts}{} -The function -\[ -\sequencestmts(\overname{\stmt}{\vsone}, \overname{\stmt}{\vstwo}) \aslto \overname{\stmt}{\news} -\] -Combines the statement $\vsone$ with $\vstwo$ into the statement $\news$, while filtering away -instances of $\SPass$. - -\begin{mathpar} -\inferrule[s1\_spass]{}{ - \sequencestmts(\overname{\SPass}{\vsone}, \vstwo) \astarrow \overname{\vstwo}{\news} -} -\and -\inferrule[s2\_spass]{ - \vsone \neq \SPass -}{ - \sequencestmts(\vsone, \overname{\SPass}{\vstwo}) \astarrow \overname{\vsone}{\news} -} -\and -\inferrule[no\_spass]{ - \vsone \neq \SPass\\ - \vstwo \neq \SPass -}{ - \sequencestmts(\vsone, \vstwo) \astarrow \overname{\SSeq(\vsone, \vstwo)}{\news} -} -\end{mathpar} - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -\chapter{Building Macro Productions} -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -This chapter defines builder relations for the -subset of macro productions in \secref{ParametricProductions} -that are not inlined: -\begin{itemize} - \item SyntaxRule.List (see \secref{SyntaxRule.List}) - \item SyntaxRule.CList (see \secref{SyntaxRule.CList}) - \item SyntaxRule.NTCList (see \secref{SyntaxRule.NTCList}) - \item SyntaxRule.Option (see \secref{SyntaxRule.Option}) -\end{itemize} - -We also define SyntaxRule.Identity (see \secref{SyntaxRule.Identity}), -which can be used in conjunction with the rules above in application -to terminals. - -\section{SyntaxRule.List \label{sec:SyntaxRule.List}} -\hypertarget{build-list}{} -The meta relation -\[ -\buildlist[b](\overname{N}{\vsyms}) \;\aslrel\; \overname{A}{\vsymasts} -\] -which is parameterized by an AST building relation $b : E \aslrel A$, -takes a parse node that represents a possibly-empty list of $E$ values --- $\vsyms$ --- and returns the result of applying $b$ -to each of them --- $\vsymasts$. - -\begin{mathpar} -\inferrule[empty]{}{ - \buildlist[b](\overname{\emptysentence}{\vsyms}) \astarrow \overname{\emptylist}{\vsymasts} -} -\end{mathpar} - -\begin{mathpar} -\inferrule[non\_empty]{ - b(\vv) \astarrow \astversion{\vv}\\ - \buildlist[b](\vsymsone) \astarrow \vsymastsone -}{ - \buildlist[b](\overname{ - \maybeemptylist{N}(\namednode{\vv}{E}, \namednode{\vsymsone}{\maybeemptylist{N}}) - }{\vsyms}) \astarrow - \overname{[\astversion{\vv}] \concat \vsymastsone}{\vsymasts} -} -\end{mathpar} - -\section{SyntaxRule.CList \label{sec:SyntaxRule.CList}} -\hypertarget{build-clist}{} -The meta relation -\[ -\buildclist[b](\overname{N}{\vsyms}) \;\aslrel\; \overname{A}{\vsymasts} -\] -which is parameterized by an AST building relation $b : E \aslrel A$, -takes a parse node that represents a possibly-empty comma-separated list of $E$ values --- $\vsyms$ --- and returns the result of applying $b$ -to each of them --- $\vsymasts$. - -\begin{mathpar} -\inferrule[empty]{}{ - \buildclist[b](\overname{\emptysentence}{\vsyms}) \astarrow \overname{\emptylist}{\vsymasts} -} -\end{mathpar} - -\begin{mathpar} -\inferrule[non\_empty]{ - b(\vv) \astarrow \astversion{\vv}\\ - \buildclist[b](\vsymsone) \astarrow \vsymastsone -}{ - \buildclist[b](\overname{ - \Clist{N}(\namednode{\vv}{E}, \Tcomma, \namednode{\vsymsone}{\NClist{N}}) - }{\vsyms}) \astarrow \overname{[\astversion{\vv}] \concat \vsymastsone}{\vsymasts} -} -\end{mathpar} - -\section{SyntaxRule.NTCList \label{sec:SyntaxRule.NTCList}} -\hypertarget{build-ntclist}{} -The meta relation -\[ -\buildntclist[b](\overname{N}{\vsyms}) \;\aslrel\; \overname{A}{\vsymasts} -\] -which is parameterized by an AST building relation $b : E \aslrel A$, -takes a parse node that represents a non-empty comma-separated trailing list of $E$ values --- $\vsyms$ --- and returns the result of applying $b$ -to each of them --- $\vsymasts$. - -\begin{mathpar} -\inferrule[empty]{ - b(\vv) \astarrow \astversion{\vv} -}{ - \buildntclist[b](\overname{\vv \parsesep \option{\Tcomma}}{\vsyms}) \astarrow \overname{[\astversion{\vv}]}{\vsymasts} -} -\end{mathpar} - -\begin{mathpar} -\inferrule[non\_empty]{ - b(\vv) \astarrow \astversion{\vv}\\ - \buildntclist[b](\vsymsone) \astarrow \vsymastsone -}{ - \buildntclist[b](\overname{\namednode{\vv}{E}, \Tcomma, \namednode{\vsymsone}{\NTClist{N}}}{\vsyms}) \astarrow \overname{[\astversion{\vv}] \concat \vsymastsone}{\vsymasts} -} -\end{mathpar} - -\section{SyntaxRule.Option \label{sec:SyntaxRule.Option}} -\hypertarget{build-option}{} -The meta relation -\[ -\buildoption[b](\overname{N}{\vsym}) \;\aslrel\; \overname{\langle A \rangle}{\vsymast} -\] -which is parameterized by an AST building relation $b : E \aslrel A$, -takes a parse node that represents an optional $E$ value --- $\vsym$ --- and returns the result of applying $b$ -to the value if it exists --- $\vsymasts$. - -\begin{mathpar} -\inferrule[none]{}{ - \buildoption[b](\overname{\emptysentence}{\vsym}) \astarrow \overname{\None}{\vsymast} -} -\end{mathpar} - -\begin{mathpar} -\inferrule[some]{ - b(\vv) \astarrow \astversion{\vv} -}{ - \buildoption[b](\overname{\namednode{\vv}{E}}{\vsym}) \astarrow \overname{\langle\astversion{\vv}\rangle}{\vsymast} -} -\end{mathpar} - -When this relation is applied to a sentence consisting of a prefix of terminals $t_{1..k}$, ending with a non-terminal $\vv$, -it ignore the terminals and returns the result for the non-terminal. -\begin{mathpar} -\inferrule[last]{ - \buildoption[b](\vv) \astarrow \vsymast -}{ - \buildoption[b](t_{1..k}, \namednode{\vv}{E}) \astarrow \vsymast -} -\end{mathpar} - -\section{SyntaxRule.Identity \label{sec:SyntaxRule.Identity}} -\hypertarget{build-identity}{} -The meta function -\[ -\buildidentity(\overname{T}{x}) \aslto \overname{T}{x} -\] -is the identity function, which can be used as an argument to meta functions such as $\buildlist$ when they are applied -to terminals. - -\begin{mathpar} -\inferrule{}{ - \buildidentity(x) \astarrow x -} -\end{mathpar} - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -\chapter{Correspondence Between Left-hand-side Expressions and Right-hand-side Expressions -\label{chap:LeftToRight}} -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - -The recursive function $\torexpr : \lexpr \rightarrow \expr$ transforms -left-hand-side expressions to corresponding right-hand-side expressions, -which is utilized both for the type system and semantics: -\[ -\begin{array}{lcl} - \textbf{Left hand side expression} & & \textbf{Right hand side expression}\\ - \hline - \torexpr(\LEVar(\vx)) &=& \EVar(\vx)\\ - \torexpr(\LESlice(\vle, \vargs)) &=& \ESlice(\torexpr(\vle), \vargs)\\ - \torexpr(\LESetArray(\vle, \ve)) &=& \EGetArray(\torexpr(\vle), \ve)\\ - \torexpr(\LESetField(\vle, \vx)) &=& \EGetField(\torexpr(\vle), \vx)\\ - \torexpr(\LESetFields(\vle, \vx)) &=& \EGetFields(\torexpr(\vle), \vx)\\ - \torexpr(\LEDiscard) &=& \EVar(\texttt{-})\\ - \torexpr(\LEDestructuring([\vle_{1..k}])) &=& \ETuple([i=1..k: \torexpr(\vle_i)])\\ - \torexpr(\LEConcat([\vle_{1..k}], \Ignore)) &=& \EConcat([i=1..k: \torexpr(\vle_i)])\\ -\end{array} -\] - -% \bibliographystyle{plain} -% \bibliography{ASL} -% \end{document} diff --git a/asllib/doc/ASLTypingReference.tex b/asllib/doc/ASLTypingReference.tex deleted file mode 100644 index 7ab6adeba..000000000 --- a/asllib/doc/ASLTypingReference.tex +++ /dev/null @@ -1,19921 +0,0 @@ -% \documentclass{book} -% \input{ASLmacros} -% \input{ASLTypingLines} -% \input{ASLTypeSatisfactionLines} -% \input{ASLStaticModelLines} -% \input{ASLStaticInterpreterLines} -% \input{ASLStaticEnvLines} -% \input{ASLASTUtilsLines} -% \input{ASLASTLines} -% \newcommand{\typingtests}{../tests/ASLTypingReference.t/} - -\newcommand\todocomment[1]{} - -% % Increase indentation of sections in the table of contents -% % to allow a space between the section numbers and their titles. -% \makeatletter -% \renewcommand{\l@section}{\@dottedtocline{1}{1.5em}{2.6em}} -% \makeatother -% \setcounter{tocdepth}{1} - -% \author{Arm Architecture Technology Group} -% \title{ASL Typing Reference \\ -% DDI 0622} -% \begin{document} -% \maketitle - -% \tableofcontents{} - -% \include{notice.tex} - -% \include{disclaimer.tex} - -\part{ASL Typing Reference} - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -\chapter{Introduction} -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - -The purpose of this document is to describe, in a formal and authoritative way, -which ASL specifications are considered \emph{well-typed}. -Whether a specification is well-typed is defined in terms of a \emph{type system}~\cite{TypeSystemsLucaCardelli}. -That is, a set of \emph{typing rules}. - -An ASL parser accepts an ASL specification and checks whether it is valid with respect to the syntax of ASL, -which is defined in \secref{ASLGrammar}. -If the specification is syntactically valid, the parser returns an \emph{abstract syntax tree} (AST, for short), -which represents the specification as a labelled structured tree. Otherwise, it returns a syntax error. -When an ASL specification is successfully parsed, we refer to the resulting AST as the \emph{untyped AST}. - -A \emph{type checker} is an implementation of the ASL type system, which accepts an untyped AST and applies the -rules of the type system to the untyped AST. If it is successful, the specification -is considered \emph{well-typed} and the result is a pair consisting of -a \emph{static environment} and a \emph{typed AST}, which are used in defining the ASL semantics (\partref{ASLSemanticsReference}). -Otherwise, the type checker returns a type error. - -\paragraph{Understanding the Typing Formalization:} -We assume basic familiarity with the ASL language. -The ASL type system is defined in terms of its AST, -and familiarity with the AST is \underline{required} to understand it. -The mathematical background needed to understand the mathematical formalization -of the ASL semantics appears in \partref{FormalSystem} and \chapref{typesystembuildingblocks}. - -\paragraph{Reading guide:} -The typing rules are organized into chapters, which roughly group the rules by their AST node type. -The set of rules in each chapter is further split according to additional syntactic and semantic -predicates over the AST node. -For example, an expression can be a literal, or a binary operator, amongst other -things. Each of those has its own evaluation rule: TypingRule.ELit in -\secref{TypingRule.ELit} and -Typing.Binop in \secref{TypingRule.Binop}, respectively. - -Each rule is presented using the following template: -\begin{itemize} -\item a Prose paragraph gives the rule in English, and corresponds as much as possible to the code of the reference implementation ASLRef given at -\href{https://github.com/herd/herdtools7//tree/master/asllib}{/herdtools7/asllib}; -\item one or several Example paragraphs, which as much as possible are also given as regression tests in -\href{https://github.com/herd/herdtools7//tree/master/asllib/tests/ASLTypingReference.t}{/herdtools7/asllib/tests/ASLTypingReference.t}; -\ifcode -\item a Code paragraph which gives a verbatim of the corresponding OCaml implementation in the type-checker of ASLRef -\href{https://github.com/herd/herdtools7//tree/master/asllib/Typing.ml}{/herdtools7/asllib/Typing.ml}; -\fi -\item Formal paragraphs which give formal definitions of the rule. -\item Comments paragraphs, which provide additional details. -\end{itemize} - -Note that rules use a specific language to define variables, deconstruct mathematical data types, -and assert equality. See \secref{FlavoursOfEqualityInRules} for details. - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -\chapter{Type System Building Blocks} -\label{chap:typesystembuildingblocks} -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -This chapter defines necessary mathematical types and concepts for the ASL system. - -Types are represented by ASTs derived from the non-terminal $\ty$. - -\section{Static Environments \label{sec:StaticEnvironments}} - -A \emph{static environment} (also called a \emph{type environment}) is what the typing rules operate over: -a structure, which amongst other things, associates types to variables. -Throughout this document, we will use the term environment for static environment, unless otherwise stated. -Intuitively, the typing of a -specification makes an initial environment evolve, with new types as given by the -variable declarations of the specification. - -\begin{definition} -\hypertarget{def-staticenvs}{} -Static environments, denoted as $\staticenvs$, are defined as follows (referring to symbols defined by the abstract syntax): -\[ -\begin{array}{rcl} -\staticenvs &\triangleq& \globalstaticenvs \times \localstaticenvs \hypertarget{def-globalstaticenvs}{}\\ -\globalstaticenvs &\triangleq& \declaredtypes \times \constantvalues \times \globalstoragetypes\\ - & & \times\ \subtypes \times \subprograms \times \subprogramrenamings \hypertarget{def-localstaticenvs}{}\\ -\localstaticenvs &\triangleq& \constantvalues \times \localstoragetypes \times \returntype\\ -\hline -\declaredtypes &\triangleq& \identifier \partialto \ty\\ -\constantvalues &\triangleq& \identifier \partialto \literal\\ -\globalstoragetypes &\triangleq& \identifier \partialto \ty \times \globaldeclkeyword\\ -\localstoragetypes &\triangleq& \identifier \partialto \ty \times \localdeclkeyword\\ -\subtypes &\triangleq& \identifier \partialto \identifier\\ -\subprograms &\triangleq& \identifier \partialto \func\\ -\subprogramrenamings &\triangleq& \identifier \rightarrow \pow{\Strings}\\ -\returntype &\triangleq& \langle \ty \rangle -\end{array} -\] -\end{definition} - -We use $\tenv$ and similar variable names (for example, $\tenvone$ and $\newtenv$) to range over static environments. - -A static environment $\tenv=(G^\tenv, L^\tenv)$ consists of two -distinct components: the global environment $G^\tenv \in \globalstaticenvs$ --- pertaining to AST nodes -appearing outside of a given subprogram, and the local environment -$L^\tenv \in \localstaticenvs$ --- pertaining to AST nodes appearing inside a given subprogram. -This separation allows us to type-check subprograms by using an empty local environment. - -The intuitive meaning of each component is as follows: -\begin{itemize} - \hypertarget{def-declaredtypes}{} - \item $\declaredtypes$ assigns types to their declared names; - \hypertarget{def-constantvalues}{} - \item $\constantvalues$ assigns literals to their declaring (constant) names; - \hypertarget{def-globalstoragetypes}{} - \item $\globalstoragetypes$ associates names of global storage elements to their inferred type - and how they were declared --- as constants, configuration variables, \texttt{let} variables, - or mutable variables; - \hypertarget{def-localstoragetypes}{} - \item $\localstoragetypes$ associates names of local storage elements to their inferred type - and how they were declared --- as variables, constants, or as \texttt{let} variables; - \hypertarget{def-subtypes}{} - \item $\subtypes$ associates type names to the names that their type subtypes; - \hypertarget{def-subprograms}{} - \item $\subprograms$ associates names of subprograms to the $\func$ AST node they were - declared with; - \hypertarget{def-subprogramrenamings}{} - \item $\subprogramrenamings$ associates names of subprograms to the set of overloading - subprograms --- $\func$ AST nodes that share the same name; - \hypertarget{def-returntype}{} - \item $\returntype$ contains the name of the type that a subprogram declares, if it is - a function or a getter. -\end{itemize} - -\hypertarget{def-emptytenv}{} -\begin{definition}[Empty Static Environment] - The \emph{empty static environment}, \\ denoted as $\emptytenv$, is defined as follows: - \[ - \emptytenv \triangleq \left( - \begin{array}{c} - \overname{ - (\overname{\emptyfunc}{\declaredtypes}, - \overname{\emptyfunc}{\constantvalues}, - \overname{\emptyfunc}{\globalstoragetypes}, - \overname{\emptyfunc}{\subtypes}, - \overname{\emptyfunc}{\subprograms}, - \overname{\emptyfunc}{\subprogramrenamings})}{G},\\ - \overname{ - ( - \overname{\emptyfunc}{\constantvalues}, - \overname{\emptyfunc}{\localstoragetypes}, - \overname{\None}{\returntype} - )}{L} - \enspace. - \end{array} - \right) - \] -\end{definition} - -The global environment and local environment consist of various components. -We use the notation $G^\tenv.m$ and $L^\tenv.m$ to access the $m$ component of a given environment. - -To update a function component $f$ (e.g., $\declaredtypes$) of a global or local environment $E$ -with a new mapping $x \mapsto v$, we use the notation $\tenv.f[x \mapsto v]$ to stand for $E[f \mapsto E.f[x \mapsto v]]$. - -\lrmcomment{This is related to \identd{JRXM} and \identi{ZTMQ}.} - -\section{Constrained Types} -\begin{itemize} - \item A \emph{constrained type} is a type whose definition is parameterized by an expression. - In ASL only integer types and bitvector types can be constrained. - \item A type which is not constrained is \emph{unconstrained}. - \item A constrained type with a non-empty constraint is \emph{well-constrained}. - \hypertarget{def-parameterizedintegertype} - \item A \emph{\parameterizedintegertype} is an implicit type of a subprogram parameter. - \end{itemize} -The widths of bitvector storage elements are constrained integers. - -\hypertarget{def-isunconstrainedinteger}{} -\hypertarget{def-isparameterizedinteger}{} -\hypertarget{def-iswellconstrainedinteger}{} -We use the following helper predicates to classify integer types: -\[ - \begin{array}{rcl} - \isunconstrainedinteger(\overname{\ty}{\vt}) &\aslto& \Bool\\ - \isparameterizedinteger(\overname{\ty}{\vt}) &\aslto& \Bool\\ - \iswellconstrainedinteger(\overname{\ty}{\vt}) &\aslto& \Bool - \end{array} -\] -Those are defined as follows: -\[ - \begin{array}{rcl} - \isunconstrainedinteger(\vt) &\triangleq& \vt = \TInt(c) \land \astlabel(c)=\unconstrained\\ - \isparameterizedinteger(\vt) &\triangleq& \vt = \TInt(c) \land \astlabel(c)=\parameterized\\ - \iswellconstrainedinteger(\vt) &\triangleq& \vt = \TInt(c) \land \astlabel(c)=\wellconstrained\\ -\end{array} -\] - -\isempty{\subsection{Comments}} -\lrmcomment{This is related to \identd{ZTPP}, \identr{WJYH}, \identr{HJPN}, \identr{CZTX}, \identr{TPHR}.} - -\section{ASL Type System} -\hypertarget{def-annotaterel}{} -The type system of ASL is given by the relation $\annotaterel$, which is defined as the disjoint union -of the functions and relations defined in this document. -The functions and relations in this document are defined, in turn, via type system rules. - -The output configurations of type assertions have two flavors: -\begin{description} - \item[Normal Outputs.] \hypertarget{def-normal-type-outputs}{} - Configurations are typically tuples with different combinations - of \emph{static environments}, types, and Boolean values. - - \hypertarget{def-typeerror}{} - \item[Type Errors.] Configurations in $\TypeError(\Strings)$ - represent type errors, for example, using an integer type as a condition expression, as in \verb|if 5 then 1 else 2|. - The ASL type system is designed such that when these \emph{type error configurations} appear, - the typing of the entire specification terminates by outputting them. -\end{description} - -We define the mathematical type of type error configurations -(which is needed to define the types of functions in the ASL type system) -as follows: -\hypertarget{def-ttypeerror}{} -\[ - \TTypeError \triangleq \{\TypeErrorVal{\vs} \;|\; \vs \in \Strings \} \enspace. -\] - -\hypertarget{def-typeerrorconfig}{} -and the shorthand $\TypeErrorConfig \triangleq \TypeError(\vs)$ for type error configurations. - -% \hypertarget{def-proseortypeerror}{} -% Specifically,\ProseOrTypeError\ means: ``or a type error configuration $\TypeErrorConfig$, which short-circuits the rule, -% making it transition into the type error configuration $\TypeErrorConfig$.''. -% -When several \hyperlink{def-caserules}{case rules} for the same function use the same short-circuiting transition assertion, -we do not repeat the\ProseOrTypeError, but rather include it only in the first rule. - -% \subsection*{Rule Example} -% The following rule is used to type a sequence of two statements: -% \[ -% \inferrule{ -% \annotatestmt{\tenv, \vs1} = (\newsone, \tenvone)\\ -% \annotatestmt{\tenvone, \vs2} = (\newstwo, \tenvtwo)\\ -% } -% { -% \annotatestmt{\tenv, \SSeq(\vsone, \vstwo)} = (\SSeq(\newsone, \newstwo), \tenvtwo) -% } -% \] -% The rule uses the annotation function $\annotatestmt{\cdot}$, which -% accepts an environment $\tenv$ and two statements and returns a new statement and a new environment. -% The function returns a new statement in order to implement certain code transformations, such as -% inlining setter functions. - -\section{Annotation} - -Typing a specification consists of annotating the root of its AST with the rules defined -in the remainder of this document. - -\paragraph{Shorthand Notations:} - -\hypertarget{def-unconstrainedinteger}{} -We use the shorthand notation $\unconstrainedinteger$ to denote the unconstrained integer type: $\TInt(\unconstrained)$. - -We employ the following abbreviations for various AST nodes: -\begin{center} -\begin{tabular}{ll} -\hline -\textbf{Abbreviation} & \textbf{Meaning} -\hypertarget{def-elint}{}\\ -\hline -$\ELInt{n}$ & literal integer expression: $\ELiteral(\lint(n))$ -\hypertarget{def-abbrevconstraintexact}{}\\ -$\AbbrevConstraintExact{\ve}$ & $\ConstraintExact(\ve)$ -\hypertarget{def-abbrevconstraintrange}{}\\ -$\AbbrevConstraintRange{\veone}{\vetwo}$ & $\ConstraintRange(\veone, \vetwo)$ \hypertarget{def-abbrevebinop}{}\\ -$\AbbrevEBinop{\op}{\veone}{\vetwo}$ & $\EBinop(\op, \veone, \vetwo)$ \hypertarget{def-abbrevtarraylengthexpr}{}\\ -$\AbbrevTArray{\vi}{\vt}$ & $\TArray(\ArrayLengthExpr(\vi), \vt)$ \hypertarget{def-abbrevtarray}{}\\ -$\AbbrevTArrayLengthExpr{\ve}{\vt}$ & $\TArray(\ArrayLengthExpr(\ve), \vt)$ \hypertarget{def-abbrevtarraylengthenum}{}\\ -$\AbbrevTArrayLengthEnum{\ve}{\vs}{\vt}$ & $\TArray(\ArrayLengthEnum(\ve, \vs), \vt)$\\ -\hline -\end{tabular} -\end{center} - -Note that throughout this document we use $\tty$ to denote a type variable, which should not be confused with the abstract syntax variable $\ty$. - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -\chapter{Domain of Values for Types\label{chap:DomainOfValuesForTypes}} -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -This chapter formalizes the concept of the set of values for a given type. -The formalism is given in the form of rules. -% -The chapter also defines the concept of checking whether the set of values -for one type is included in the set of values for another type. - -\hypertarget{def-vals}{} -\hypertarget{def-nativevalue}{} -\hypertarget{def-nativevalues}{} -\section{Native Values \label{sec:nativevalues}} - -Types define sets of values that variables can take when a specification is semantically evaluated. -To formalize this, we define the set of \emph{\nativevalues}, denoted $\vals$ -(\texttt{NV} stands for Native Value). - -\subsection{Prose} -The set of \nativevalues\ $\vals$ is the minimal set satisfying all of the following rules: -\begin{itemize} - \item \textsc{basis set}: if $\vv$ is a literal then $\nvliteral{\vv}$ is a \nativevalue; - \item \textsc{tuple values and array values}: if $\vl$ is a list of \nativevalues\ then $\nvvector{\vl}$ is a \nativevalue; - \item \textsc{record values}: if $\vr$ is a finite function from identifiers to \nativevalues\ then $\nvrecord{\vr}$ is a \nativevalue. -\end{itemize} - -\subsection{Formally} -\hypertarget{def-nvliteral}{} -\hypertarget{def-nvvector}{} -\hypertarget{def-nvrecord}{} -\begin{mathpar} - \inferrule[(Basis Set: Integers, Reals, Booleans, Strings, and Bitvectors)] - {\vv \in \literal} - { \nvliteral{\vv} \in \vals } - \and - \inferrule[(Tuple Values and Array Values)]{\vvl \in \vals^*} - { \nvvector{\vvl} \in \vals } - \and - \inferrule[(Record Values)] - {\vr : \Identifiers \rightarrowfin \vals} - { \nvrecord{\vr} \in \vals } -\end{mathpar} - -We define the following shorthands for \nativevalue\ literals: -\hypertarget{def-nvint}{} -\[ -\begin{array}{rcl} -\nvint(z) &\triangleq& \nvliteral{\lint(z)} \hypertarget{def-nvbool}{}\\ -\nvbool(b) &\triangleq& \nvliteral{\lbool(b)} \hypertarget{def-nvreal}{}\\ -\nvreal(r) &\triangleq& \nvliteral{\lreal(r)} \hypertarget{def-nvstring}{}\\ -\nvstring(s) &\triangleq& \nvliteral{\lstring(s)} \hypertarget{def-nvbitvector}{}\\ -\nvbitvector(v) &\triangleq& \nvliteral{\lbitvector(v)}\\ -\end{array} -\] - -We define the following types of \nativevalues: -\hypertarget{def-tint}{} -\[ -\begin{array}{rcl} - \tint &\triangleq& \{ \nvint(z) \;|\; z \in \Z\} \hypertarget{def-tbool}{}\\ - \tbool &\triangleq& \{ \nvbool(\True), \nvbool(\False) \} \hypertarget{def-treal}{}\\ - \treal &\triangleq& \{ \nvreal(r) \;|\; r \in \Q\} \hypertarget{def-tstring}{}\\ - \tstring &\triangleq& \{ \nvstring(s) \;|\; s \in \Strings\} \hypertarget{def-tbitvector}{}\\ - \tbitvector &\triangleq& \{ \nvbitvector(\textit{bits}) \;|\; \textit{bits} \in \{0,1\}^*\} \hypertarget{def-tvector}{}\\ - \tvector &\triangleq& \{ \nvvector{\textit{vals}} \;|\; \textit{vals} \in \vals^*\} \hypertarget{def-trecord}{}\\ - \trecord &\triangleq& \{ \nvrecord{\fieldmap} \;|\; \fieldmap \in \Identifiers\rightarrowfin\vals\}\\ -\end{array} -\] - -\section{Dynamic Domain of a Type\label{sec:DynDomain}} -\hypertarget{def-dyndomain}{} - -We now define the concept of a \emph{dynamic domain} of a type -and the \emph{static domain} of a type. -Intuitively, domains assign potentially infinite sets of \nativevalues\ to types. -Dynamic domains are used by the semantics to evaluate expressions of the form \texttt{UNKNOWN: t} -by choosing a single value from the dynamic domain of $\vt$. -Static domains are used to define subtype satisfaction in \secref{TypingRule.SubtypeSatisfaction}. - -\hypertarget{def-dynamicenvs}{} -The definition of a dynamic domain refers to \emph{dynamic environments}, denoted $\dynamicenvs$, -which assigns \nativevalues\ to identifiers. - -\hypertarget{def-envs}{} -We define \emph{environments} as pairs of static environments and dynamic environments: -$\envs \triangleq \staticenvs \times \dynamicenvs$. - -Formally, the partial function -\[ - \dynamicdomain : \overname{\envs}{\env} \times \overname{\ty}{\vt} - \partialto \overname{\pow{\vals}}{\vd} -\] -assigns the set of values that a type $\vt$ can hold in a given environment $\env$. -% -We say that $\dynamicdomain(\env, \vt)$ is the \emph{dynamic domain} of $\vt$ -in the environment $\env$. -% -The \emph{static domain} of a type is the set of values which storage elements of that type may hold -\underline{across all possible dynamic environments}. -% -The reason for this distinction is that the sets of values -of integer types, bitvector types, and array types can depend on the dynamic values of variables. - -Types that do not refer to variables whose values are only known dynamically have -a static domain that is equal to any of their dynamic domains. -In those cases, we simply refer to their \emph{domain}. - -Associating a set of values to a type is done by evaluating any expression appearing -in the type definitions. Evaluation is defined by the relation $\evalexprsef$. -which evaluates side-effect-free expressions and either returns -a configuration of the form $\Normal(\vv,\vg)$ or a dynamic error configuration $\ErrorConfig$. -In the first case, $\vv$ is a \nativevalue\ and $\vg$ -is an \emph{execution graph}. Execution graphs are related to the concurrent semantics -and can be ignored in the context of defining dynamic domains. -In the latter case (which can occur if, for example, an expression attempts to divide -\texttt{8} by \texttt{0}), a dynamic error configuration, for which we use the notation -$\ErrorConfig$, is returned. -% -The dynamic domain is empty in cases where evaluating side-effect-free expressions -results in a dynamic error. -% -The dynamic domain is undefined if the type $\vt$ is not well-typed in $\tenv$. -That is, if $\annotatetype{\tenv, \vt} \typearrow \TypeErrorConfig$. - -As part of the definition, we also associate dynamic domains to integer constraints -by overloading $\dynamicdomain$: -\[ - \dynamicdomain : \overname{\envs}{\env} \times \overname{\intconstraint}{\vc} - \partialto \overname{\pow{\vals}}{\vd} -\] - -\subsection{Prose} -For an environment $\env \in \envs$ and a type $\vt$, the domain is $\vd$ and one of the following applies: -\begin{itemize} - \item All of the following apply (\textsc{t\_bool}): - \begin{itemize} - \item $\vt$ is the Boolean type, $\TBool$; - \item $\vd$ is the set of native Boolean values, $\tbool$. - \end{itemize} - - \item All of the following apply (\textsc{t\_string}): - \begin{itemize} - \item $\vt$ is the string type, $\TString$; - \item $\vd$ is the set of all native string values, $\tstring$. - \end{itemize} - - \item All of the following apply (\textsc{t\_real}): - \begin{itemize} - \item $\vt$ is the real type, $\TReal$; - \item $\vd$ is the set of all native real values, $\treal$. - \end{itemize} - - \item All of the following apply (\textsc{t\_enumeration}): - \begin{itemize} - \item $\vt$ is the enumeration type with labels $\id_{1..k}$, that is $\TEnum(\id_{1..k})$; - \item $\vd$ is the set of all native integer values for $1..k$.\\ - \textbf{Why represent enumeration domains via integers:} - Conceptually, enumeration labels carry two pieces of information --- the identifiers themselves - and their position in the list of identifiers, which are used for accessing arrays. - For the purpose of type-checking, we use the identifiers, but for the purpose of the semantics - and the domain of values, only the positions are relevant. - \end{itemize} - - \item All of the following apply (\textsc{t\_int\_unconstrained}): - \begin{itemize} - \item $\vt$ is the unconstrained integer type, $\unconstrainedinteger$; - \item $\vd$ is the set of all native integer values, $\tint$. - \end{itemize} - - \item All of the following apply (\textsc{t\_int\_well\_constrained}): - \begin{itemize} - \item $\vt$ is the well-constrained integer type $\TInt(\wellconstrained(\vc_{1..k}))$; - \item $\vd$ is the union of the dynamic domains of each of the constraints $\vc_{1..k}$ in $\env$. - \end{itemize} - - \item All of the following apply (\textsc{constraint\_exact\_okay}): - \begin{itemize} - \item $\vc$ is a constraint consisting of a single side-effect-free expression $\ve$, that is, $\ConstraintExact(\ve)$; - \item evaluating $\ve$ in $\env$, results in a configuration with the native integer for $n$; - \item $\vd$ is the set containing the single native integer value for $n$. - \end{itemize} - - \item All of the following apply (\textsc{constraint\_exact\_dynamic\_error}): - \begin{itemize} - \item $\vc$ is a constraint consisting of a single side-effect-free expression $\ve$, that is, $\ConstraintExact(\ve)$; - \item evaluating $\ve$ in $\env$, results in a dynamic error configuration; - \item $\vd$ is the empty set. - \end{itemize} - - \item All of the following apply (\textsc{constraint\_range\_okay}): - \begin{itemize} - \item $\vc$ is a range constraint consisting of a two side-effect-free expressions $\veone$ and $\vetwo$, that is, $\ConstraintRange(\veone, \vetwo)$; - \item evaluating $\veone$ in $\env$, results in a configuration with the native integer for $a$; - \item evaluating $\vetwo$ in $\env$, results in a configuration with the native integer for $b$; - \item $\vd$ is the set containing all native integer values for integers greater or equal to $a$ and less than or equal to $b$. - \end{itemize} - - \item All of the following apply (\textsc{constraint\_range\_dynamic\_error1}): - \begin{itemize} - \item $\vc$ is a range constraint consisting of a two side-effect-free expressions $\veone$ and $\vetwo$, that is, $\ConstraintRange(\veone, \vetwo)$; - \item evaluating $\veone$ in $\env$, results in a dynamic error configuration; - \item $\vd$ is the empty set. - \end{itemize} - - \item All of the following apply (\textsc{constraint\_range\_dynamic\_error2}): - \begin{itemize} - \item $\vc$ is a range constraint consisting of a two side-effect-free expressions $\veone$ and $\vetwo$, that is, $\ConstraintRange(\veone, \vetwo)$; - \item evaluating $\veone$ in $\env$, results in a configuration with the native integer for $a$; - \item evaluating $\vetwo$ in $\env$, results in a dynamic error configuration; - \item $\vd$ is the empty set. - \end{itemize} - - \item All of the following apply (\textsc{t\_int\_parameterized}): - \begin{itemize} - \item $\vt$ is a \parameterizedintegertype\ for parameter $\id$, \\ $\TInt(\parameterized(\id))$; - \item the \nativevalue\ associated with $\id$ in the local dynamic environment is the native integer value for $n$; - \item $\vd$ is the set containing the single integer value for $n$. - \end{itemize} - - \item All of the following apply (\textsc{t\_bits\_dynamic\_error}): - \begin{itemize} - \item $\vt$ is a bitvector type with size expression $\ve$, $\TBits(\ve, \Ignore)$; - \item evaluating $\ve$ in $\env$, results in a dynamic error configuration; - \item $\vd$ is the empty set. - \end{itemize} - - \item All of the following apply (\textsc{t\_bits\_negative\_width\_error}): - \begin{itemize} - \item $\vt$ is a bitvector type with size expression $\ve$, $\TBits(\ve, \Ignore)$; - \item evaluating $\ve$ in $\env$, results in a configuration with the native integer for $k$; - \item $k$ is negative; - \item $\vd$ is the empty set. - \end{itemize} - - \item All of the following apply (\textsc{t\_bits\_empty}): - \begin{itemize} - \item $\vt$ is a bitvector type with size expression $\ve$, $\TBits(\ve, \Ignore)$; - \item evaluating $\ve$ in $\env$, results in a configuration with the native integer for $0$; - \item $\vd$ is the set containing the single \nativevalue\ for an empty bitvector. - \end{itemize} - - \item All of the following apply (\textsc{t\_bits\_non\_empty}): - \begin{itemize} - \item $\vt$ is a bitvector type with size expression $\ve$, $\TBits(\ve, \Ignore)$; - \item evaluating $\ve$ in $\env$, results in a configuration with the native integer for $k$; - \item $k$ is greater than $0$; - \item $\vd$ is the set containing all \nativevalues\ for bitvectors of size exactly $k$. - \end{itemize} - - \item All of the following apply (\textsc{t\_tuple}): - \begin{itemize} - \item $\vt$ is a tuple type over types $\vt_i$, for $i=1..k$, $\TTuple(\vt_{1..k})$; - \item the domain of each element $\vt_i$ is $D_i$, for $i=1..k$; - \item evaluating $\ve$ in $\env$, results in a configuration with the native integer for $k$; - \item $\vd$ is the set containing all native vectors of $k$ values, where the value at position $i$ - is from $D_i$. - \end{itemize} - - \item All of the following apply (\textsc{t\_array\_dynamic\_error}): - \begin{itemize} - \item $\vt$ is an array type with length expression $\ve$ and element type $\vt_i$, for $i=1..k$, $\TArray(\ve, \vtone)$; - \item evaluating $\ve$ in $\env$, results in a dynamic error configuration; - \item $\vd$ is the empty set. - \end{itemize} - - \item All of the following apply (\textsc{t\_array\_negative\_length\_error}): - \begin{itemize} - \item $\vt$ is an array type with length expression $\ve$ and element type $\vt_i$, for $i=1..k$, $\TArray(\ve, \vtone)$; - \item evaluating $\ve$ in $\env$, results in a configuration with the native integer for $k$; - \item $k$ is negative; - \item $\vd$ is the empty set. - \end{itemize} - - \item All of the following apply (\textsc{t\_array\_okay}): - \begin{itemize} - \item $\vt$ is an array type with length expression $\ve$ and element type $\vt_i$, for $i=1..k$, $\TArray(\ve, \vtone)$; - \item evaluating $\ve$ in $\env$, results in a configuration with the native integer for $k$; - \item $k$ is greater than or equal to $0$; - \item the domain of $\vtone$ is $D_\vtone$; - \item $\vd$ is the set containing all native vectors of $k$ values taken from $D_\vtone$. - \end{itemize} - - \item All of the following apply (\textsc{t\_structured}): - \begin{itemize} - \item $\vt$ is a \structuredtype\ with typed fields $(\id_i, \vt_i$, for $i=1..k$, that is $L([i=1..k: (\id_i,\vt_i))]$ - where $L\in\{\TRecord, \TException\}$; - \item the domain of each type $\vt_i$ is $D_i$, for $i=1..k$; - \item $\vd$ is the set containing all native records where $\id_i$ is mapped to a value taken from $D_i$. - \end{itemize} - - \item All of the following apply (\textsc{t\_named}): - \begin{itemize} - \item $\vt$ is a named type with name $\id$, $\TNamed(\id)$; - \item the type associated with $\id$ in $\tenv$ is $\tty$; - \item $\vd$ is the domain of $\tty$ in $\env$. - \end{itemize} -\end{itemize} - -\subsection{Formally} - -\begin{mathpar} -\inferrule[t\_bool]{}{ \dynamicdomain(\env, \overname{\TBool}{\vt}) = \overname{\tbool}{\vd} } -\and -\inferrule[t\_string]{}{ \dynamicdomain(\env, \overname{\TString}{\vt}) = \overname{\tstring}{\vd} } -\and -\inferrule[t\_real]{}{ \dynamicdomain(\env, \overname{\TReal}{\vt}) = \overname{\treal}{\vd} } -\and -\inferrule[t\_enumeration]{}{ - \dynamicdomain(\env, \overname{\TEnum(\id_{1..k})}{\vt}) = \overname{\{\nvint(1),\ldots,\nvint(k)\}}{\vd} -} -\end{mathpar} - -\begin{mathpar} - \inferrule[t\_int\_unconstrained]{}{ - \dynamicdomain(\env, \overname{\unconstrainedinteger}{\vt}) = \overname{\tint}{\vd} -} -\end{mathpar} - -\begin{mathpar} -\inferrule[t\_int\_well\_constrained]{}{ - \dynamicdomain(\env, \overname{\TInt(\wellconstrained(\vc_{1..k}))}{\vt}) = \overname{\bigcup_{i=1}^k \dynamicdomain(\env, \vc_i)}{\vd} -} -\end{mathpar} - -\begin{mathpar} -\inferrule[constraint\_exact\_okay]{ - \evalexprsef{\env, \ve} \evalarrow \Normal(\nvint(n), \Ignore) -}{ - \dynamicdomain(\env, \overname{\ConstraintExact(\ve)}{\vc}) = \overname{\{ \nvint(n) \}}{\vd} -} -\and -\inferrule[constraint\_exact\_dynamic\_error]{ - \evalexprsef{\env, \ve} \evalarrow \ErrorConfig -}{ - \dynamicdomain(\env, \overname{\ConstraintExact(\ve)}{\vc}) = \overname{\emptyset}{\vd} -} -\end{mathpar} - -\begin{mathpar} -\inferrule[constraint\_range\_okay]{ - \evalexprsef{\env, \veone} \evalarrow \Normal(\nvint(a), \Ignore)\\ - \evalexprsef{\env, \vetwo} \evalarrow \Normal(\nvint(b), \Ignore) -}{ - \dynamicdomain(\env, \overname{\ConstraintRange(\veone, \vetwo)}{\vc}) = \overname{\{ \nvint(n) \;|\; a \leq n \land n \leq b\}}{\vd} -} -\and -\inferrule[constraint\_range\_dynamic\_error1]{ - \evalexprsef{\env, \veone} \evalarrow \ErrorConfig -}{ - \dynamicdomain(\env, \overname{\ConstraintRange(\veone, \vetwo)}{\vc}) = \overname{\emptyset}{\vd} -} -\and -\inferrule[constraint\_range\_dynamic\_error2]{ - \evalexprsef{\env, \veone} \evalarrow \Normal(\Ignore, \Ignore)\\ - \evalexprsef{\env, \vetwo} \evalarrow \ErrorConfig -}{ - \dynamicdomain(\env, \overname{\ConstraintRange(\veone, \vetwo)}{\vc}) = \overname{\emptyset}{\vd} -} -\end{mathpar} - -The notation $L^\denv(\id)$ denotes the \nativevalue\ associated with the identifier $\id$ -in the \emph{local dynamic environment} of $\denv$. -\begin{mathpar} - \inferrule[t\_int\_parameterized]{ - L^\denv(\id) = \nvint(n) -}{ - \dynamicdomain(\env, \overname{\TInt(\parameterized(\id))}{\vt}) = \overname{\{ \nvint(n) \}}{\vd} -} -\end{mathpar} - -\begin{mathpar} -\inferrule[t\_bits\_dynamic\_error]{ - \evalexprsef{\env, \ve} \evalarrow \ErrorConfig -}{ - \dynamicdomain(\env, \overname{\TBits(\ve, \Ignore)}{\vt}) = \overname{\emptyset}{\vd} -} -\and -\inferrule[t\_bits\_negative\_width\_error]{ - \evalexprsef{\env, \ve} \evalarrow \Normal(\nvint(k), \Ignore)\\ - k < 0 -}{ - \dynamicdomain(\env, \overname{\TBits(\ve, \Ignore)}{\vt}) = \overname{\emptyset}{\vd} -} -\and -\inferrule[t\_bits\_empty]{ - \evalexprsef{\env, \ve} \evalarrow \Normal(\nvint(0), \Ignore) -}{ - \dynamicdomain(\env, \overname{\TBits(\ve, \Ignore)}{\vt}) = \overname{\{ \nvbitvector(\emptylist) \}}{\vd} -} -\and -\inferrule[t\_bits\_non\_empty]{ - \evalexprsef{\env, \ve} \evalarrow \Normal(\nvint(k), \Ignore)\\ - k > 0 -}{ - \dynamicdomain(\env, \overname{\TBits(\ve, \Ignore)}{\vt}) = \overname{\{ \nvbitvector(\vb_{1..k}) \;|\; \vb_1,\ldots,\vb_k \in \{0,1\} \}}{\vd} -} -\end{mathpar} - -\begin{mathpar} -\inferrule[t\_tuple]{ - i=1..k: \dynamicdomain(\env, \vt_i) = D_i -}{ - \dynamicdomain(\env, \overname{\TTuple(\vt_{1..k})}{\vt}) = - \overname{\{ \nvvector{\vv_{1..k}} \;|\; \vv_i \in D_i \}}{\vd} -} -\end{mathpar} - -\begin{mathpar} -\inferrule[t\_array\_dynamic\_error]{ - \evalexprsef{\env, \ve} \evalarrow \ErrorConfig -}{ - \dynamicdomain(\env, \overname{\TArray(\ve, \vtone)}{\vt}) = \overname{\emptyset}{\vd} -} -\and -\inferrule[t\_array\_negative\_length\_error]{ - \evalexprsef{\env, \ve} \evalarrow \Normal(\nvint(k), \Ignore)\\ - k < 0 -}{ - \dynamicdomain(\env, \overname{\TArray(\ve, \vtone)}{\vt}) = \overname{\emptyset}{\vd} -} -\and -\inferrule[t\_array\_okay]{ - \evalexprsef{\env, \ve} \evalarrow \Normal(\nvint(k), \Ignore)\\ - k \geq 0\\ - \dynamicdomain(\env, \vtone) = D_\vtone -}{ - \dynamicdomain(\env, \overname{\TArray(\ve, \vtone)}{\vt}) = - \overname{\{ \nvvector{\vv_{1..k}} \;|\; \vv_{1..k} \in D_{\vtone} \}}{\vd} -} -\end{mathpar} - -\begin{mathpar} -\inferrule[structured]{ - L \in \{\TRecord, \TException\}\\ - i=1..k: \dynamicdomain(\env, \vt_i) = D_i -}{ - \dynamicdomain(\env, \overname{L([i=1..k: (\id_i,\vt_i))]}{\vt}) = \\ - \overname{\{ \nvrecord{\{i=1..k: \id_i\mapsto \vv_i\}} \;|\; \vv_i \in D_i \}}{\vd} -} -\end{mathpar} - -\begin{mathpar} -\inferrule[t\_named]{ - G^\tenv.\declaredtypes(\id)=\tty -}{ - \dynamicdomain(\env, \overname{\TNamed(\id)}{\vt}) = \overname{\dynamicdomain(\env, \tty)}{\vd} -} -\end{mathpar} - -\subsection{Example} -The domain of \texttt{integer} is the infinite set of all integers. - -The domain of \verb|integer {2,16}| is the set $\{\nvint(2), \nvint(16)\}$. - -The domain of \verb|integer{1..3}| is the set $\{\nvint(1), \nvint(2), \nvint(3)\}$. - -The domain of \verb|integer{10..1}| is the empty set as there are no integers that are -both greater than $10$ and smaller than $1$. - -The domain of \texttt{bits(2)} is the set $\{\nvbitvector(00)$, $\nvbitvector(01),$ -$\nvbitvector(10)$, $\nvbitvector(11)\}$. - -The domain of \verb|enumeration {GREEN, ORANGE, RED}| is the set \\ -$\{\nvint(1), \nvint(2), \nvint(3)\}$ and so is the domain -of \\ -\verb|type TrafficLights of enumeration {GREEN, ORANGE, RED}|. - -The domain of \texttt{bits({2,16})} is the set containing native bitvectors of all 2-bit and all 16-bit binary sequences. - -The domain of \texttt{(integer, integer)} is the set containing all pairs of native integer values. - -The domain of \verb|record {a: integer; b: boolean}| contains all native records -that map \texttt{a} to a native integer value and \texttt{b} to a native Boolean value. - -The dynamic domain of a subprogram parameter \texttt{N: integer} is the (singleton) set containing -the native integer value $c$, -which is assigned to \texttt{N} by a given dynamic environment. The static domain of that parameter -is the infinite set of all native integer values. - -\lrmcomment{ -This is related to \identd{BMGM}, \identr{PHRL}, \identr{PZNR}, -\identr{RLQP}, \identr{LYDS}, \identr{SVDJ}, \identi{WLPJ}, \identr{FWMM}, -\identi{WPWL}, \identi{CDVY}, \identi{KFCR}, \identi{BBQR}, \identr{ZWGH}, -\identr{DKGQ}, \identr{DHZT}, \identi{HSWR}, \identd{YZBQ}. -} - -\section{Subsumption Testing \label{sec:subsumptiontesting}} -Whether an assignment statement is well-typed depends on whether the dynamic domain of the -right hand side type is contained in the dynamic domain of the left hand side type, -for any given dynamic environment -(see \secref{TypingRule.SubtypeSatisfaction} where this is checked). - -\begin{definition}[Subsumption] -For any given types $\vt$ and $\vs$ and static environment $\tenv$, -we say that $\vt$ \emph{subsumes} $\vs$ in $\tenv$, -if the following condition holds: -\hypertarget{def-subsumes}{} -\begin{equation} - \subsumes(\tenv, \vt, \vs) \triangleq \forall \denv\in\dynamicenvs.\ \dynamicdomain((\tenv, \denv), \vt) \supseteq \dynamicdomain((\tenv, \denv), \vs) \enspace. -\end{equation} -\end{definition} - -For example, consider the assignment -\begin{center} -\verb|var x : integer{1,2,3} = UNKNOWN : integer{1,2};| -\end{center} - -It is legal, since (in any static environment), the domain of \verb|integer{1,2,3}| -is \\ -$\{\nvint(1), \nvint(2), \nvint(3)\}$, which subsumes -the domain of \verb|integer{1,2}|, which is \\ $\{\nvint(1), \nvint(2)\}$. - -Since dynamic domains are potentially infinite, this requires \emph{symbolic reasoning}. -Furthermore, since any (statically evaluable) expressions may appear inside integer and bitvector -types, testing subsumption is undecidable. -We therefore approximate subsumption testing \emph{conservatively} via the predicate $\symsubsumes(\tenv, \vt, \vs)$. - -\hypertarget{def-soundsubsumptiontest}{} -\begin{definition}[Sound Subsumption Test] -A predicate -\[ - \symsubsumes(\overname{\staticenvs}{\tenv} \aslsep \overname{\ty}{\vt} \aslsep \overname{\ty}{\vs}) \aslto \Bool -\] -is \emph{sound} if the following condition holds: -\begin{equation} - \begin{array}{l} - \forall \vt,\vs\in\ty.\ \tenv\in\staticenvs. \\ - \;\;\;\; \symsubsumes(\tenv, \vt, \vs) \typearrow \True \;\Longrightarrow\; \subsumes(\tenv, \vt, \vs) \enspace. - \end{array} -\end{equation} -\end{definition} - -That is, if a sound subsumption test returns a positive answer, it means that -$\vt$ definitely \emph{subsumes} $\vs$ in the static environment $\tenv$. -This is referred to as a \emph{true positive}. -However, a negative answer means one of two things: -\begin{description} - \item[True Negative:] indeed, $\vt$ does not subsume $\vs$ in the static environment $\tenv$; or - \item[False Negative:] the symbolic reasoning is unable to decide. -\end{description} - -In other words, $\symsubsumes(\tenv, \vt, \vs)$ errs on the \emph{safe side} --- -it never answers $\True$ when the real answer is $\False$, which would (undesirably) -determine the following statement as well-typed: -\begin{center} - \verb|var x : integer{1,2} = UNKNOWN: integer;| -\end{center} - -A sound but trivial subsumption test is one that always returns $\False$. -However, that would make all assignments be considered as not well-typed. -Indeed, it has the maximal set of false negatives. -Reducing the set of false negatives requires stronger symbolic reasoning algorithms, -which inevitably leads to higher computational complexity. -% -The symbolic subsumption test in \chapref{symbolicsubsumptiontesting} -attempts to accept a large enough set of true positives, based on empirical trial and error, -while maintaining the computational complexity of the symbolic reasoning relatively low. -% -In particular, it serves as the definitive subsumption test that must be utilized -by any implementation of the ASL type system. - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -\chapter{Basic Type Attributes} -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - -This chapter defines some basic predicates for classifying types as well as -functions that inspect the structure of types: -\begin{itemize} - \item Builtin singular types (\secref{TypingRule.BuiltinSingularType}) - \item Builtin aggregate types (\secref{TypingRule.BuiltinAggregateType}) - \item Builtin types (\secref{TypingRule.BuiltinSingularOrAggregate}) - \item Named types (\secref{TypingRule.NamedType}) - \item Anonymous types (\secref{TypingRule.AnonymousType}) - \item Singular types (\secref{TypingRule.SingularType}) - \item Aggregate types (\secref{TypingRule.AggregateType}) - \item Non-primitive types (\secref{TypingRule.NonPrimitiveType}) - \item Primitive types (\secref{TypingRule.PrimitiveType}) - \item The structure of a type (\secref{TypingRule.structure}) - \item The underlying type of a type (\secref{anonymize}) - \item Checked constrained integers (\secref{TypingRule.CheckConstrainedInteger}) -\end{itemize} - -\section{TypingRule.BuiltinSingularType \label{sec:TypingRule.BuiltinSingularType}} -\hypertarget{def-isbuiltinsingular}{} -The predicate -\[ - \isbuiltinsingular(\overname{\ty}{\tty}) \;\aslto\; \Bool -\] -tests whether the type $\tty$ is a \emph{builtin singular type}. - -\subsection{Prose} -The \emph{builtin singular types} are: -\begin{itemize} -\item \texttt{integer}; -\item \texttt{real}; -\item \texttt{string}; -\item \texttt{boolean}; -\item \texttt{bits} (which also represents \texttt{bit}, as a special case); -\item \texttt{enumeration}. -\end{itemize} - -\subsection{Example} -In this example: -\VerbatimInput[firstline=3,lastline=8]{\typingtests/TypingRule.BuiltinSingularTypes.asl} - -Variables of builtin singular types \texttt{integer}, \texttt{real}, -\texttt{boolean}, \texttt{bits(4)}, \\ and~\texttt{bits(2)} are defined. - -\subsection{Example} -\VerbatimInput{\typingtests/TypingRule.EnumerationType.asl} -The builtin singular type \texttt{Color} consists in two constants -\texttt{RED}, and~\texttt{BLACK}. - -\CodeSubsection{\BuiltinSingularBegin}{\BuiltinSingularEnd}{../types.ml} - -\subsection{Formally} -\begin{mathpar} -\inferrule{ - \vb \eqdef \astlabel(\tty) \in \{\TReal, \TString, \TBool, \TBits, \TEnum, \TInt\} -}{ - \isbuiltinsingular(\tty) \typearrow \vb -} -\end{mathpar} - -\isempty{\subsection{Comments}} -\lrmcomment{This is related to \identd{PQCK} and \identd{NZWT}.} - -\section{TypingRule.BuiltinAggregateType \label{sec:TypingRule.BuiltinAggregateType}} -\hypertarget{def-isbuiltinaggregate}{} -The predicate -\[ - \isbuiltinaggregate(\overname{\ty}{\tty}) \;\aslto\; \Bool -\] -tests whether the type $\tty$ is a \emph{builtin aggregate type}. - -\subsection{Prose} -The builtin aggregate types are: -\begin{itemize} -\item tuple; -\item \texttt{array}; -\item \texttt{record}; -\item \texttt{exception}. -\end{itemize} - -\subsection{Example} -\VerbatimInput{\typingtests/TypingRule.BuiltinAggregateTypes.asl} -Type \texttt{Pair} is the type of integer and boolean pairs. - -Arrays are declared with indices that are either integer-typed -or enumeration-typed. In the example above, \texttt{T} is -declared as an array with an integer-typed index (as indicated -by the used of the integer-typed constant \texttt{3}) whereas -\texttt{PointArray} is declared with the index of -\texttt{Coord}, which is an enumeration type. - -Arrays declared with integer-typed indices can be accessed only by integers ranging from $0$ to -the size of the array minus $1$. In the example above, $\texttt{T}$ can be accessed with -one of $0$, $1$, and $2$. - -Arrays declared with an enumeration-typed index can only be accessed with labels from the corresponding -enumeration. In the example above, \texttt{PointArray} can only be accessed with one of the labels -\texttt{CX}, \texttt{CY}, and \texttt{CZ}. - -The (builtin aggregate) type \verb|{ x : real, y : real, z : real }| is a record type with three fields -\texttt{x}, \texttt{y} and \texttt{z}. - -\subsection{Example} -\VerbatimInput{\typingtests/TypingRule.BuiltinExceptionType.asl} -Two (builtin aggregate) exception types are defined: -\begin{itemize} -\item \verb|exception{}| (for \texttt{Not\_found}), which carries no value; and -\item \verb|exception { message:string }| (for \texttt{SyntaxException}), which carries a message. -\end{itemize} -Notice the similarity with record types and that the empty field list \verb|{}| can be -omitted in type declarations, as is the case for \texttt{Not\_found}. - -\CodeSubsection{\BuiltinAggregateBegin}{\BuiltinAggregateEnd}{../types.ml} - -\subsection{Formally} -\begin{mathpar} -\inferrule{ \vb \eqdef \astlabel(\tty) \in \{\TTuple, \TArray, \TRecord, \TException\} } -{ \isbuiltinaggregate(\tty) \typearrow \vb } -\end{mathpar} - -\isempty{\subsection{Comments}} -\lrmcomment{This is related to \identd{PQCK} and \identd{KNBD}.} - -\section{TypingRule.BuiltinSingularOrAggregate \label{sec:TypingRule.BuiltinSingularOrAggregate}} -\hypertarget{def-isbuiltin}{} -The predicate -\[ - \isbuiltin(\overname{\ty}{\tty}) \;\aslto\; \Bool -\] -tests whether the type $\tty$ is a \emph{builtin type}. - -\subsection{Prose} -$\tty$ is a builtin type and one of the following applies: -\begin{itemize} -\item $\tty$ is singular; -\item $\tty$ is builtin aggregate. -\end{itemize} - -\subsection{Example} -In the specification -\begin{verbatim} - type ticks of integer; -\end{verbatim} -the type \texttt{integer} is a builtin type but the type of \texttt{ticks} is not. - -\CodeSubsection{\BuiltinSingularOrAggregateBegin}{\BuiltinSingularOrAggregateEnd}{../types.ml} - -\subsection{Formally} -\begin{mathpar} - \inferrule{ - \isbuiltinsingular(\tty) \typearrow \vbone\\ - \isbuiltinaggregate(\tty) \typearrow \vbtwo - }{ - \isbuiltin(\tty) \typearrow \vbone \lor \vbtwo - } -\end{mathpar} - -\isempty{\subsection{Comments}} - -\section{TypingRule.NamedType \label{sec:TypingRule.NamedType} } -\hypertarget{def-isnamed}{} -The predicate -\[ - \isnamed(\overname{\ty}{\tty}) \;\aslto\; \Bool -\] -tests whether the type $\tty$ is a \emph{named type}. - -\subsection{Prose} -A named type is a type that is declared by using the \texttt{type of} syntax. - -\subsection{Example} -In the specification -\begin{verbatim} - type ticks of integer; -\end{verbatim} -\texttt{ticks} is a named type. - -\CodeSubsection{\NamedBegin}{\NamedEnd}{../types.ml} - -\subsection{Formally} -\begin{mathpar} -\inferrule{ - \vb \eqdef \astlabel(\tty) = \TNamed -}{ - \isnamed(\tty) \typearrow \vb -} -\end{mathpar} - -\isempty{\subsection{Comments}} -\lrmcomment{This is related to \identd{vmzx}.} - -\section{TypingRule.AnonymousType \label{sec:TypingRule.AnonymousType}} -\hypertarget{def-isanonymous}{} -The predicate -\[ - \isanonymous(\overname{\ty}{\tty}) \;\aslto\; \Bool -\] -tests whether the type $\tty$ is an \emph{anonymous type}. - -\subsection{Prose} -An anonymous type is a type that is not declared using the type syntax. - -\subsection{Example} -The tuple type \texttt{(integer, integer)} is an anonymous type. - -\CodeSubsection{\AnonymousBegin}{\AnonymousEnd}{../types.ml} - -\subsection{Formally} -\begin{mathpar} -\inferrule{ \vb \eqdef \astlabel(\tty) \neq \TNamed -} -{ - \isanonymous(\tty) \typearrow \vb -} -\end{mathpar} - -\isempty{\subsection{Comments}} -\lrmcomment{This is related to \identd{VMZX}.} - -\section{TypingRule.SingularType \label{sec:TypingRule.SingularType}} -\hypertarget{def-issingular}{} -The predicate -\[ - \issingular(\overname{\staticenvs}{\tenv} \aslsep \overname{\ty}{\tty}) \;\aslto\; - \overname{\Bool}{\vb} \cup \overname{\TTypeError}{\TypeErrorConfig} -\] -tests whether the type $\tty$ is a \emph{singular type} in the static environment $\tenv$. - -\subsection{Prose} -A type $\tty$ is singular if and only if all of the following apply: -\begin{itemize} - \item obtaining the \underlyingtype\ of $\tty$ in the environment $\tenv$ yields $\vtone$\ProseOrTypeError; - \item $\vtone$ is a builtin singular type. -\end{itemize} - -\subsection{Example} -In the following example, the types \texttt{A}, \texttt{B}, and \texttt{C} are all singular types: -\begin{verbatim} -type A of integer; -type B of A; -type C of B; -\end{verbatim} - -\CodeSubsection{\SingularBegin}{\SingularEnd}{../types.ml} - -\subsection{Formally} -\begin{mathpar} -\inferrule{ - \makeanonymous(\tenv, \tty) \typearrow \vtone \OrTypeError\\\\ - \isbuiltinsingular(\vtone) \typearrow \vb -}{ -\issingular(\tenv, \tty) \typearrow \vb -} -\end{mathpar} - -\isempty{\subsection{Comments}} -\lrmcomment{This is related to \identr{GVZK}.} - -\section{TypingRule.AggregateType \label{sec:TypingRule.AggregateType}} -\hypertarget{def-isbuiltinaggregate}{} -The predicate -\[ - \isaggregate(\overname{\staticenvs}{\tenv} \aslsep \overname{\ty}{\tty}) \;\aslto\; - \overname{\Bool}{\vb} \cup \overname{\TTypeError}{\TypeErrorConfig} -\] -tests whether the type $\tty$ is an \emph{aggregate type} in the static environment $\tenv$. - -\subsection{Prose} -A type $\tty$ is aggregate in an environment $\tenv$ if and only if all of the following apply: -\begin{itemize} - \item obtaining the \underlyingtype\ of $\tty$ in the environment $\tenv$ yields $\vtone$\ProseOrTypeError; - \item $\vtone$ is a builtin aggregate. -\end{itemize} - -\subsection{Example} -In the following example, the types \texttt{A}, \texttt{B}, and \texttt{C} are all aggregate types: -\begin{verbatim} -type A of (integer, integer); -type B of A; -type C of B; -\end{verbatim} - -\CodeSubsection{\AggregateBegin}{\AggregateEnd}{../types.ml} - -\subsection{Formally} -\begin{mathpar} -\inferrule{ - \makeanonymous(\tenv, \tty) \typearrow \vtone \OrTypeError\\\\ - \isbuiltinaggregate(\vtone) \typearrow \vb -}{ - \isaggregate(\tenv, \tty) \typearrow \vb -} -\end{mathpar} - -\isempty{\subsection{Comments}} -\lrmcomment{This is related to \identr{GVZK}.} - -\section{TypingRule.StructuredType \label{sec:TypingRule.StructuredType}} -\hypertarget{def-isstructured}{} -\hypertarget{def-structuredtype}{} -A \emph{\structuredtype} is any type that consists of a list of field identifiers -that denote individual storage elements. In ASL there are two such types --- record types and exception types. - -The predicate -\[ - \isstructured(\overname{\ty}{\tty}) \;\aslto\; \overname{\Bool}{\vb} -\] -tests whether the type $\tty$ is a \structuredtype\ and yields the result in $\vb$. - -\subsection{Prose} -The result $\vb$ is $\True$ if and only if $\tty$ is either a record type or an exception type, -which is determined via the AST label of $\tty$. - -\subsection{Example} -In the following example, the types \texttt{SyntaxException} and \texttt{PointRecord} -are each an example of a \structuredtype: -\begin{verbatim} -type SyntaxException of exception {message: string }; -type PointRecord of Record {x : real, y: real, z: real}; -\end{verbatim} - -\subsection{Formally} -\begin{mathpar} -\inferrule{}{ - \isstructured(\tty) \typearrow \overname{\astlabel(\tty) \in \{\TRecord, \TException\}}{\vb} -} -\end{mathpar} - -\isempty{\subsection{Comments}} -\lrmcomment{This is related to \identd{WGQS}, \identd{QXYC}.} - -\section{TypingRule.NonPrimitiveType \label{sec:TypingRule.NonPrimitiveType}} -\hypertarget{def-isnonprimitive}{} -The predicate -\[ - \isnonprimitive(\overname{\ty}{\tty}) \;\aslto\; \overname{\Bool}{\vb} -\] -tests whether the type $\tty$ is a \emph{non-primitive type}. - -\subsection{Prose} -One of the following applies: -\begin{itemize} - \item All of the following apply (\textsc{singular}): - \begin{itemize} - \item $\tty$ is a builtin singular type; - \item $\vb$ is $\False$. - \end{itemize} - \item All of the following apply (\textsc{named}): - \begin{itemize} - \item $\tty$ is a named type; - \item $\vb$ is $\True$. - \end{itemize} - \item All of the following apply (\textsc{tuple}): - \begin{itemize} - \item $\tty$ is a tuple type $\vli$; - \item $\vb$ is $\True$ if and only if there exists a non-primitive type in $\vli$. - \end{itemize} - \item All of the following apply (\textsc{array}): - \begin{itemize} - \item $\tty$ is an array of type $\tty'$ - \item $\vb$ is $\True$ if and only if $\tty'$ is non-primitive. - \end{itemize} - \item All of the following apply (\textsc{structured}): - \begin{itemize} - \item $\tty$ is a \structuredtype\ with fields $\fields$; - \item $\vb$ is $\True$ if and only if there exists a non-primitive type in $\fields$. - \end{itemize} -\end{itemize} - -\subsection{Example} -The following types are non-primitive: - -\begin{tabular}{ll} -\textbf{Type definition} & \textbf{Reason for being non-primitive}\\ -\hline -\texttt{type A of integer} & Named types are non-primitive\\ -\texttt{(integer, A)} & The second component, \texttt{A}, has non-primitive type\\ -\texttt{array[6] of A} & Element type \texttt{A} has a non-primitive type\\ -\verb|record { a : A }| & The field \texttt{a} has a non-primitive type -\end{tabular} - -\CodeSubsection{\NonPrimitiveBegin}{\NonPrimitiveEnd}{../types.ml} - -\subsection{Formally} -The cases \textsc{tuple} and \textsc{structured} below, use the notation $\vb_\vt$ to name -Boolean variables by using the types denoted by $\vt$ as a subscript. -\begin{mathpar} -\inferrule[singular]{ - \astlabel(\tty) \in \{\TReal, \TString, \TBool, \TBits, \TEnum, \TInt\} -}{ - \isnonprimitive(\tty) \typearrow \False -} -\end{mathpar} - -\begin{mathpar} -\inferrule[named]{\astlabel(\tty) = \TNamed}{\isnonprimitive(\tty) \typearrow \True} -\end{mathpar} - -\begin{mathpar} -\inferrule[tuple]{ - \vt \in \tys: \isnonprimitive(\vt) \typearrow \vb_{\vt}\\ - \vb \eqdef \bigvee_{\vt \in \tys} \vb_{\vt} -}{ - \isnonprimitive(\overname{\TTuple(\tys)}{\tty}) \typearrow \vb -} -\end{mathpar} - -\begin{mathpar} -\inferrule[array]{ - \isnonprimitive(\tty') \typearrow \vb -}{ - \isnonprimitive(\overname{\TArray(\Ignore, \tty')}{\tty}) \typearrow \vb -} -\end{mathpar} - -\begin{mathpar} -\inferrule[structured]{ - L \in \{\TRecord, \TException\}\\ - (\Ignore,\vt) \in \fields : \isnonprimitive(\vt) \typearrow \vb_\vt\\ - \vb \eqdef \bigvee_{\vt \in \vli} \vb_{\vt} -}{ - \isnonprimitive(\overname{L(\fields)}{\tty}) \typearrow \vb -} -\end{mathpar} - -\isempty{\subsection{Comments}} -\lrmcomment{This is related to \identd{GWXK}.} - -\section{TypingRule.PrimitiveType \label{sec:TypingRule.PrimitiveType}} -\hypertarget{def-isprimitive}{} -The predicate -\[ - \isprimitive(\overname{\ty}{\tty}) \;\aslto\; \Bool -\] -tests whether the type $\tty$ is a \emph{primitive type}. - -\subsection{Prose} -A type $\tty$ is primitive if it is not non-primitive. - -\subsection{Example} -The following types are primitive: - -\begin{tabular}{ll} -\textbf{Type definition} & \textbf{Reason for being primitive}\\ -\hline -\texttt{integer} & Integers are primitive\\ -\texttt{(integer, integer)} & All tuple elements are primitive\\ -\texttt{array[5] of integer} & The array element type is primitive\\ -\verb|record {ticks : integer}| & The single field \texttt{ticks} has a primitive type -\end{tabular} - -\CodeSubsection{\PrimitiveBegin}{\PrimitiveEnd}{../types.ml} - -\subsection{Formally} -\begin{mathpar} -\inferrule{ - \isnonprimitive(\tty) \typearrow \vb -}{ - \isprimitive(\tty) \typearrow \neg\vb -} -\end{mathpar} - -\isempty{\subsection{Comments}} -\lrmcomment{This is related to \identd{GWXK}.} - -\section{TypingRule.Structure\label{sec:TypingRule.structure}} -\hypertarget{def-structure}{} -The function -\[ - \tstruct(\overname{\staticenvs}{\tenv} \aslsep \overname{\ty}{\tty}) \aslto \overname{\ty}{\vt} \cup \overname{\TTypeError}{\TypeErrorConfig} -\] -assigns a type to its \hypertarget{def-tstruct}{\emph{\structure}}, which is the type formed by -recursively replacing named types by their type definition in the static environment $\tenv$. -If a named type is not associated with a declared type in $\tenv$, a type error is returned. - -TypingRule.Specification ensures the absence of circular type definitions, -which ensures that TypingRule.Structure terminates\footnote{In mathematical terms, -this ensures that TypingRule.Structure is a proper \emph{structural induction.}}. - -\subsection{Prose} -One of the following applies: -\begin{itemize} -\item All of the following apply (\textsc{named}): - \begin{itemize} - \item $\tty$ is a named type $\vx$; - \item obtaining the declared type associated with $\vx$ in the static environment $\tenv$ yields $\vtone$\ProseOrTypeError; - \item obtaining the structure of $\vtone$ static environment $\tenv$ yields $\vt$\ProseOrTypeError; - \end{itemize} -\item All of the following apply (\textsc{builtin\_singular}): - \begin{itemize} - \item $\tty$ is a builtin singular type; - \item $\vt$ is $\tty$. - \end{itemize} -\item All of the following apply (\textsc{tuple}): - \begin{itemize} - \item $\tty$ is a tuple type with list of types $\tys$; - \item the types in $\tys$ are indexed as $\vt_i$, for $i=1..k$; - \item obtaining the structure of each type $\vt_i$, for $i=1..k$, in $\tys$ in the static environment $\tenv$, - yields $\vtp_i$\ProseOrTypeError; - \item $\vt$ is a tuple type with the list of types $\vtp_i$, for $i=1..k$. - \end{itemize} -\item All of the following apply (\textsc{array}): - \begin{itemize} - \item $\tty$ is an array type of length $\ve$ with element type $\vt$; - \item obtaining the structure of $\vt$ yields $\vtone$\ProseOrTypeError; - \item $\vt$ is is an array type with of length $\ve$ with element type $\vtone$. - \end{itemize} -\item All of the following apply (\textsc{structured}): - \begin{itemize} - \item $\tty$ is a \structuredtype\ with fields $\fields$; - \item obtaining the structure for each type $\vt$ associated with field $\id$ yields a type $\vt_\id$\ProseOrTypeError; - \item $\vt$ is a record or an exception, in correspondence to $\tty$, with the list of pairs $(\id, \vt\_\id)$; - \end{itemize} -\end{itemize} - -\subsection{Example} -In this example: -\texttt{type T1 of integer;} is the named type \texttt{T1} -whose structure is \texttt{integer}. - -In this example: -\texttt{type T2 of (integer, T1);} -is the named type \texttt{T2} whose structure is (integer, integer). In this -example, \texttt{(integer, T1)} is non-primitive since it uses \texttt{T1}, which is builtin aggregate. - -In this example: -\texttt{var x: T1;} -the type of $\vx$ is the named (hence non-primitive) type \texttt{T1}, whose structure -is \texttt{integer}. - -In this example: -\texttt{var y: integer;} -the type of \texttt{y} is the anonymous primitive type \texttt{integer}. - -In this example: -\texttt{var z: (integer, T1);} -the type of \texttt{z} is the anonymous non-primitive type -\texttt{(integer, T1)} whose structure is \texttt{(integer, integer)}. - -\CodeSubsection{\StructureBegin}{\StructureEnd}{../types.ml} - -\subsection{Formally} -\begin{mathpar} -\inferrule[named]{ - \declaredtype(\tenv, \vx) \typearrow \vtone \OrTypeError\\\\ - \tstruct(\tenv, \vtone)\typearrow\vt \OrTypeError -}{ - \tstruct(\tenv, \TNamed(\vx)) \typearrow \vt -} -\and -\inferrule[builtin\_singular]{ - \isbuiltinsingular(\tty) \typearrow \True -}{ - \tstruct(\tenv, \tty) \typearrow \tty -} -\and -\inferrule[tuple]{ - \tys \eqname \vt_{1..k}\\ - i=1..k: \tstruct(\tenv, \vt_i) \typearrow \vtp_i \OrTypeError -}{ - \tstruct(\tenv, \TTuple(\tys)) \typearrow \TTuple(i=1..k: \vtp_i) -} -\and -\inferrule[array]{ - \tstruct(\tenv, \vt) \typearrow \vtone \OrTypeError -}{ - \tstruct(\tenv, \TArray(\ve, \vt)) \typearrow \TArray(\ve, \vtone) -} -\and -\inferrule[structured]{ - L \in \{\TRecord, \TException\}\\\\ - (\id,\vt) \in \fields : \tstruct(\tenv, \vt) \typearrow \vt_\id \OrTypeError -}{ - \tstruct(\tenv, L(\fields)) \typearrow - L([ (\id,\vt) \in \fields : (\id,\vt_\id) ]) -} -\end{mathpar} - -\isempty{\subsection{Comments}} -\lrmcomment{This is related to \identd{FXQV}.} - -\section{TypingRule.Anonymize \label{sec:anonymize}} -\hypertarget{def-makeanonymous}{} -\hypertarget{def-underlyingtype}{} -The function -\[ - \makeanonymous(\overname{\staticenvs}{\tenv} \aslsep \overname{\ty}{\tty}) \aslto \overname{\ty}{\vt} \cup \overname{\TTypeError}{\TypeErrorConfig} -\] -returns the \emph{\underlyingtype} --- $\vt$ --- of the type $\tty$ in the static environment $\tenv$ or a type error. -Intuitively, $\tty$ is the first non-named type that is used to define $\tty$. Unlike $\tstruct$, -$\makeanonymous$ replaces named types by their definition until the first non-named type is found but -does not recurse further. - -\subsection{Prose} -One of the following applies: -\begin{itemize} - \item All of the following apply (\textsc{named}): - \begin{itemize} - \item $\tty$ is a named type $\vx$; - \item obtaining the type declared for $\vx$ yields $\vtone$\ProseOrTypeError; - \item the \underlyingtype\ of $\vtone$ is $\vt$. - \end{itemize} - - \item All of the following apply (\textsc{non-named}): - \begin{itemize} - \item $\tty$ is not a named type $\vx$; - \item $\vt$ is $\tty$. - \end{itemize} -\end{itemize} - -\subsection{Example} -Consider the following example: -\begin{verbatim} -type T1 of integer; -type T2 of T1; -type T3 of (integer, T2); -\end{verbatim} - -The underlying types of \texttt{integer}, \texttt{T1}, and \texttt{T2} is \texttt{integer}. - -The underlying type of \texttt{(integer, T2)} and \texttt{T3} is -\texttt{(integer, T2)}. Notice how the underlying type does not replace -\texttt{T2} with its own underlying type, in contrast to the structure of -\texttt{T2}, which is \texttt{(integer, integer)}. - -\CodeSubsection{\AnonymizeBegin}{\AnonymizeEnd}{../types.ml} - -\subsection{Formally} -\begin{mathpar} -\inferrule[named]{ - \tty \eqname \TNamed(\vx) \\ - \declaredtype(\tenv, \vx) \typearrow \vtone \OrTypeError \\\\ - \makeanonymous(\tenv, \vtone) \typearrow \vt -}{ - \makeanonymous(\tenv, \tty) \typearrow \vt -} -\and -\inferrule[non-named]{ - \astlabel(\tty) \neq \TNamed -}{ - \makeanonymous(\tenv, \tty) \typearrow \tty -} -\end{mathpar} - -\isempty{\subsection{Comments}} - -\section{TypingRule.CheckConstrainedInteger \label{sec:TypingRule.CheckConstrainedInteger}} -\hypertarget{def-checkconstrainedinteger}{} -The function -\[ - \checkconstrainedinteger(\overname{\staticenvs}{\tenv} \aslsep \overname{\ty}{\tty}) \aslto \{\True\} \cup \overname{\TTypeError}{\TypeErrorConfig} -\] -checks whether the type $\vt$ is a \constrainedinteger. If so, the result is $\True$, otherwise a type error is returned. - -\subsection{Prose} -One of the following applies: -\begin{itemize} - \item All of the following apply (\textsc{well-constrained}): - \begin{itemize} - \item $\vt$ is a well-constrained integer; - \item the result is $\True$. - \end{itemize} - - \item All of the following apply (\textsc{parameterized}): - \begin{itemize} - \item $\vt$ is a \parameterizedintegertype; - \item the result is $\True$. - \end{itemize} - - \item All of the following apply (\textsc{unconstrained}): - \begin{itemize} - \item $\vt$ is an unconstrained integer; - \item the result is a type error indicating that a constrained integer type is expected. - \end{itemize} - - \item All of the following apply (\textsc{conflicting\_type}): - \begin{itemize} - \item $\vt$ is not an integer type; - \item the result is a type error indicating the type conflict. - \end{itemize} -\end{itemize} - -\isempty{\subsection{Example}} - -\CodeSubsection{\CheckConstrainedIntegerBegin}{\CheckConstrainedIntegerEnd}{../Typing.ml} - -\subsection{Formally} -\begin{mathpar} -\inferrule[well-constrained]{} -{ - \checkconstrainedinteger(\tenv, \TInt(\wellconstrained(\Ignore))) \typearrow \True -} -\and -\inferrule[parameterized]{} -{ - \checkconstrainedinteger(\tenv, \TInt(\parameterized(\Ignore))) \typearrow \True -} -\and -\inferrule[unconstrained]{} -{ - \checkconstrainedinteger(\tenv, \TInt(\unconstrained(\Ignore))) \typearrow \\ - \TypeErrorVal{ConstrainedIntegerExpected} -} -\and -\inferrule[conflicting\_type]{ - \astlabel(\vt) \neq \TInt -}{ - \checkconstrainedinteger(\tenv, \vt) \typearrow \TypeErrorVal{TypeConflict} -} -\end{mathpar} - -\isempty{\subsection{Comments}} - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -\chapter{Relations Over Types \label{chap:relationsovertypes}} -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - -We define the following relations over types and operators: -\begin{itemize} - \item Subtype (\secref{TypingRule.Subtype}) - \item Subtype Satisfaction (\secref{TypingRule.SubtypeSatisfaction}) - \item Type Satisfaction (\secref{TypingRule.TypeSatisfaction}) - \item Type Clash (\secref{TypingRule.TypeClash}) - \item Lowest Common Ancestor (\secref{TypingRule.LowestCommonAncestor}) - \item Checking adequacy of a unary operator for a type (\secref{TypingRule.CheckUnop}) - \item Checking adequacy of a binary operator for a pair of types (\secref{TypingRule.CheckBinop}) -\end{itemize} - -Finally, we define the following helper functions: -\begin{itemize} - \item TypingRule.AnnotateConstraintBinop (see \secref{TypingRule.AnnotateConstraintBinop}) - \item TypingRule.BinopFilterRhs (see \secref{TypingRule.BinopFilterRhs}) - \item TypingRule.RefineConstraintBySign (see \secref{TypingRule.RefineConstraintBySign}) - \item TypingRule.ReduceToZOpt (see \secref{TypingRule.ReduceToZOpt}) - \item TypingRule.RefineConstraints (see \secref{TypingRule.RefineConstraints}) - \item TypingRule.FilterReduceConstraintDiv (see \secref{TypingRule.FilterReduceConstraintDiv}) - \item TypingRule.GetLiteralDivOpt (see \secref{TypingRule.GetLiteralDivOpt}) - \item TypingRule.ExplodeIntervals (see \secref{TypingRule.ExplodeIntervals}) - \item TypingRule.ExplodeConstraint (see \secref{TypingRule.ExplodeConstraint}) - \item TypingRule.IntervalTooLarge (see \secref{TypingRule.IntervalTooLarge}) - \item TypingRule.BinopIsExploding (see \secref{TypingRule.BinopIsExploding}) -\end{itemize} - -We also define the helper rule TypingRule.FindNamedLCA (\secref{TypingRule.FindNamedLCA}). - -\section{TypingRule.Subtype\label{sec:TypingRule.Subtype}} -The \emph{subtype} relation is a partial order over \underline{named types}. -The \emph{supertype} is the inverse relation. That is, \tty\ is a supertype of \tsy\ if and only if \tsy\ is a subtype of \tty. - -\hypertarget{def-subtypesrel}{} -The predicate -\[ - \subtypesrel(\overname{\staticenvs}{\tenv} \aslsep \overname{\ty}{\vtone} \aslsep \overname{\ty}{\vttwo}) - \aslto \overname{\Bool}{\vb} -\] - -\subsection{Prose} -One of the following applies: -\begin{itemize} - \item all of the following apply (\textsc{reflexive}): - \begin{itemize} - \item $\vtone$ and $\vttwo$ are both the same named type; - \item $\vb$ is $\True$. - \end{itemize} - - \item all of the following apply (\textsc{transitive}): - \begin{itemize} - \item $\vtone$ is a named type with name $\idone$, that is $\TNamed(\idone)$; - \item $\vttwo$ is a named type with name $\idtwo$, that is $\TNamed(\idtwo)$, such that $\idone$ is different from $\idtwo$; - \item the global static environment maintains that $\idone$ is a subtype of $\idthree$; - \item testing whether the type named $\idthree$ is a subtype of $\vttwo$ in the static environment $\tenv$ - gives $\vb$. - \end{itemize} - - \item all of the following apply (\textsc{no\_supertype}): - \begin{itemize} - \item $\vtone$ is a named type with name $\idone$, that is $\TNamed(\idone)$; - \item $\vttwo$ is a named type with name $\idtwo$, that is $\TNamed(\idtwo)$, such that $\idone$ is different from $\idtwo$; - \item the global static environment maintains that $\idone$ does subtype any named type; - \item $\vb$ is $\False$. - \end{itemize} - - \item all of the following apply (\textsc{not\_named}): - \begin{itemize} - \item at least one of $\vtone$ and $\vttwo$ is not a named type; - \item $\vb$ is $\False$. - \end{itemize} -\end{itemize} -\subsection{Example} -In the following example \texttt{subInt} is a subtype of itself and of \texttt{superInt}: -\begin{verbatim} -type superInt of integer; -type subInt of integer subtypes superInt; -\end{verbatim} - -\CodeSubsection{\SubtypeBegin}{\SubtypeEnd}{../types.ml} - -\subsection{Formally} -\begin{mathpar} - \inferrule[reflexive]{}{ - \subtypesrel(\tenv, \TNamed(\id), \TNamed(\id)) \typearrow \True - } - \and - \inferrule[transitive]{ - \idone \neq \idtwo\\ - G^\tenv.\subtypes(\idone) = \idthree\\ - \subtypesrel(\tenv, \TNamed(\idthree), \vttwo) \typearrow \vb - }{ - \subtypesrel(\tenv, \TNamed(\idone), \TNamed(\idtwo)) \typearrow \vb - } - \and - \inferrule[no\_supertype]{ - \idone \neq \idtwo\\ - G^\tenv.\subtypes(\idone) = \bot - }{ - \subtypesrel(\tenv, \TNamed(\idone), \TNamed(\idtwo)) \typearrow \False - } - \and - \inferrule[not\_named]{ - (\astlabel(\vtone) \neq \TNamed \lor \astlabel(\vttwo) \neq \TNamed) - }{ - \subtypesrel(\tenv, \vtone, \vttwo) \typearrow \False - } -\end{mathpar} - -\isempty{\subsection{Comments}} -\lrmcomment{This is related to \identr{NXRX}, \identi{KGKS}, \identi{MTML}, \identi{JVRM}, \identi{CHMP}.} - -\section{TypingRule.SubtypeSatisfaction\label{sec:TypingRule.SubtypeSatisfaction}} -\hypertarget{def-subtypesat} -The predicate -\[ - \subtypesat(\overname{\staticenvs}{\tenv} \aslsep \overname{\ty}{\vt} \aslsep \overname{\ty}{\vs}) - \aslto \overname{\Bool}{\vb} \cup \overname{\TTypeError}{\TypeErrorConfig} -\] -tests whether a type $\vt$ \emph{subtype-satisfies} a type $\vs$ in environment $\tenv$, -returning the result $\vb$ or a type error, if one is detected. -The function assumes that both $\vt$ and $\vs$ are well-typed according to \chapref{typingoftypes}. - -\subsection{Prose} -One of the following applies: -\begin{itemize} -\item All of the following apply (\textsc{error1}): - \begin{itemize} - \item obtaining the \underlyingtype\ of $\vt$ gives a type error; - \item the rule results in a type error. - \end{itemize} - -\item All of the following apply (\textsc{error2}): - \begin{itemize} - \item obtaining the \underlyingtype\ of $\vt$ gives a type $\vttwo$; - \item obtaining the \underlyingtype\ of $\vs$ gives a type error; - \item the rule results in a type error. - \end{itemize} - -\item All of the following apply (\textsc{different\_labels}): - \begin{itemize} - \item the underlying types of $\vt$ and $\vs$ have different AST labels - (for example, \texttt{integer} and \texttt{real}); - \item $\vb$ is $\False$. - \end{itemize} - -\item All of the following apply (\textsc{simple}): - \begin{itemize} - \item the \underlyingtype\ of $\vt$, $\vttwo$, is either \texttt{real}, \texttt{string}, or \texttt{bool}; - \item the \underlyingtype\ of $\vs$, $\vstwo$, is either \texttt{real}, \texttt{string}, or \texttt{bool}; - \item $\vb$ is $\True$ if and only if both $\vttwo$ and $\vstwo$ have the same ASL label. - \end{itemize} - -\item All of the following apply (\textsc{t\_int}): - \begin{itemize} - \item the \underlyingtype\ of $\vt$, $\vttwo$, is an \texttt{integer} (any kind); - \item the \underlyingtype\ of $\vs$, $\vstwo$, is an \texttt{integer} (any kind); - \item determining whether $\vs$ subsumes $\vt$ in $\tenv$ via symbolic reasoning results in $\vb$. - \end{itemize} - -\item All of the following apply (\textsc{t\_enum}): - \begin{itemize} - \item the \underlyingtype\ of $\vt$ is an enumeration type with list of labels $\vlit$, that is, $\TEnum(\vlit)$; - \item the \underlyingtype\ of $\vs$ is is an enumeration type with list of labels $\vlis$, that is, $\TEnum(\vlis)$; - \item $\vb$ is $\True$ if and only if $\vlit$ is equal to $\vlis$. - \end{itemize} - -\item All of the following apply (\textsc{t\_bits}): - \begin{itemize} - \item the \underlyingtype\ of $\vs$ is a bitvector type with width $\ws$ and bit fields $\bfss$, that is $\TBits(\ws, \bfss)$; - \item the \underlyingtype\ of $\vt$ is a bitvector type with width $\wt$ and bit fields $\bfst$, that is $\TBits(\wt, \bfst)$; - \item determining whether the bit fields $\bfss$ are included in the bit fields $\bfst$ in $\tenv$ yields $\True$\ProseOrTypeError; - \item determining whether the \symbolicdomain{} of bitwidth $\ws$ subsumes the \symbolicdomain{} of bitwidth $\wt$ in $\tenv$ yields $\vb$. - \end{itemize} - -\item All of the following apply (\textsc{t\_array\_expr}): - \begin{itemize} - \item $\vs$ has the \underlyingtype\ of an array with index $\vlengths$ and element type $\vtys$, that is $\TArray(\vlengths, \vtys)$; - \item $\vt$ has the \underlyingtype\ of an array with index $\vlengtht$ and element type $\vtyt$, that is $\TArray(\vlengtht, \vtyt)$; - \item determining whether $\vtys$ and $\vtyt$ are equivalent in $\tenv$ is either $\True$ - or $\False$, which short-circuits the entire rule with $\vb=\False$; - \item either the AST labels of $\vlengths$ and $\vlengtht$ are the same or the rule short-circuits with $\vb=\False$; - \item $\vlengths$ is an array length expression with $\vlengthexprs$, that is \\ $\ArrayLengthExpr(\vlengthexprs)$; - \item $\vlengtht$ is an array length expression with $\vlengthexprt$, that is \\ $\ArrayLengthExpr(\vlengthexprt)$; - \item determining whether expressions $\vlengthexprs$ and $\vlengthexprt$ are equivalent gives $\vb$. - \end{itemize} - - \item All of the following apply (\textsc{t\_array\_enum}): - \begin{itemize} - \item $\vs$ has the \underlyingtype\ of an array with index $\vlengths$ and element type $\vtys$, that is $\TArray(\vlengths, \vtys)$; - \item $\vt$ has the \underlyingtype\ of an array with index $\vlengtht$ and element type $\vtyt$, that is $\TArray(\vlengtht, \vtyt)$; - \item determining whether $\vtys$ and $\vtyt$ are equivalent in $\tenv$ is either $\True$ - or $\False$, which short-circuits the entire rule with $\vb=\False$; - \item either the AST labels of $\vlengths$ and $\vlengtht$ are the same or the rule short-circuits with $\vb=\False$; - \item $\vlengths$ is an array with indices taken from the enumeration $\vnames$, that is $\ArrayLengthEnum(\vnames, \Ignore)$; - \item $\vlengtht$ is an array with indices taken from the enumeration $\vnamet$, that is $\ArrayLengthEnum(\vnamet, \Ignore)$; - \item $\vb$ is $\True$ if and only if $\vnames$ and $\vnamet$ are the same. - \end{itemize} - -\item All of the following apply (\textsc{t\_tuple}): - \begin{itemize} - \item $\vs$ has the \underlyingtype\ of a tuple with type list $\vlis$, that is $\TTuple(\vlis)$; - \item $\vt$ has the \underlyingtype\ of a tuple with type list $\vlit$, that is $\TTuple(\vlit)$; - \item equating the lengths of $\vlis$ and $\vlit$ is either $\True$ or $\False$, which short-circuits - the entire rule with $\vb=\False$; - \item checking at each index $\vi$ of the list $\vlis$ whether the type $\vlit[\vi]$ \typesatisfies\ the type $\vlis[\vi]$ - yields $\vb_\vi$\ProseOrTypeError; - \item $\vb$ is $\True$ if and only if all $\vb_\vi$ are $\True$; - \end{itemize} - -\item All of the following apply (\textsc{structured}): - \begin{itemize} - \item $\vs$ has the \underlyingtype\ $L(\vfieldss)$, which is a \structuredtype; - \item $\vt$ has the \underlyingtype\ $L(\vfieldst)$, which is a \structuredtype; - \item since both underlying types have the same AST label they are either both record types or both exception types; - \item $\vb$ is $\True$ if and only if for each field in $\vfieldss$ with type $\vtys$ - there exists a field in $\vfieldst$ with type $\vtyt$ such that both $\vtys$ and $\vtyt$ - are determined to be \typeequivalent\ in $\tenv$. - \end{itemize} -\end{itemize} - -\subsection{Formally} -\begin{mathpar} - \inferrule[error1]{ - \makeanonymous(\tenv, \vt) \typearrow \TypeErrorConfig - } - { - \subtypesat(\tenv, \vt, \vs) \typearrow \TypeErrorConfig - } - \and - \inferrule[error2]{ - \makeanonymous(\tenv, \vt) \typearrow \vttwo\\ - \makeanonymous(\tenv, \vs) \typearrow \TypeErrorConfig - } - { - \subtypesat(\tenv, \vt, \vs) \typearrow \TypeErrorConfig - } - \and - \inferrule[different\_labels]{ - \makeanonymous(\tenv, \vt) \typearrow \vttwo\\ - \makeanonymous(\tenv, \vs) \typearrow \vstwo\\ - \astlabel(\vttwo) \neq \astlabel(\vstwo) - } - { - \subtypesat(\tenv, \vt, \vs) \typearrow \False - } -\end{mathpar} - -\begin{mathpar} - \inferrule[simple]{ - \makeanonymous(\tenv, \vt) \typearrow \vttwo\\ - \makeanonymous(\tenv, \vs) \typearrow \vstwo\\ - \astlabel(\vttwo) \in \{\TInt, \TReal, \TString, \TBool\}\\ - \vb \eqdef \astlabel(\vstwo) = \astlabel(\vttwo) - }{ - \subtypesat(\tenv, \vt, \vs) \typearrow \vb - } -\end{mathpar} - -\begin{mathpar} -\inferrule[t\_int]{ - \makeanonymous(\tenv, \vt) \typearrow \vttwo\\ - \makeanonymous(\tenv, \vs) \typearrow \vstwo\\ - \vsstruct = \TInt(\vc)\\ - \symsubsumes(\tenv, \vsstruct, \vtstruct) \typearrow \vb -}{ - \subtypesat(\tenv, \vt, \vs) \typearrow \vb -} -\end{mathpar} - -\begin{mathpar} -\inferrule[t\_enum]{ - \makeanonymous(\tenv, \vt) \typearrow \TEnum(\vlit)\\ - \makeanonymous(\tenv, \vs) \typearrow \TEnum(\vlis)\\ - \vb \eqdef \vlit = \vlis -}{ - \subtypesat(\tenv, \vt, \vs) \typearrow \vb -} -\end{mathpar} - -\begin{mathpar} -\inferrule[t\_bits]{ - \makeanonymous(\tenv, \vs) \typearrow \TBits(\ws, \bfss)\\ - \makeanonymous(\tenv, \vt) \typearrow \TBits(\wt, \bfst)\\ - \bitfieldsincluded(\tenv, \bfss, \bfst) \typearrow \True \OrTypeError \\ - \symdomofwidth(\tenv, \ws) \typearrow \ds \\ - \symdomofwidth(\tenv, \wt) \typearrow \dt \\ - \symdomissubset(\tenv, \ds, \dt) \typearrow \vb -}{ - \subtypesat(\tenv, \vt, \vs) \typearrow \vb -} -\end{mathpar} - -\begin{mathpar} -\inferrule[t\_array\_expr]{ - \makeanonymous(\tenv, \vs) \typearrow \TArray(\vlengths,\vtys) \\ - \makeanonymous(\tenv, \vt) \typearrow \TArray(\vlengtht,\vtyt) \\ - \typeequal(\tenv, \vtys, \vtyt) \typearrow \True \terminateas \False\\ - \booltrans{\astlabel(\vlengths) = \astlabel(\vlengtht)} \booltransarrow \True \terminateas \False\\ - \vlengths \eqname \ArrayLengthExpr(\vlengthexprs)\\ - \vlengtht \eqname \ArrayLengthExpr(\vlengthexprt)\\ - \exprequal(\tenv, \vlengthexprs, \vlengthexprt) \typearrow \vb -}{ - \subtypesat(\tenv, \vt, \vs) \typearrow \vb -} -\and -\inferrule[t\_array\_enum]{ - \makeanonymous(\tenv, \vs) \typearrow \TArray(\vlengths,\vtys) \\ - \makeanonymous(\tenv, \vt) \typearrow \TArray(\vlengtht,\vtyt) \\ - \typeequal(\tenv, \vtys, \vtyt) \typearrow \True\\ - \booltrans{\astlabel(\vlengths) = \astlabel(\vlengtht)} \typearrow \True\\ - \vlengths \eqname \ArrayLengthEnum(\vnames, \Ignore)\\ - \vlengtht \eqname \ArrayLengthEnum(\vnamet, \Ignore)\\ - \vb \eqdef \vnames = \vnamet -}{ - \subtypesat(\tenv, \vt, \vs) \typearrow \vb -} -\end{mathpar} - -\begin{mathpar} -\inferrule[t\_tuple] -{ \makeanonymous(\tenv, \vs) \typearrow\TTuple(\vlis)\\ - \makeanonymous(\tenv, \vt) \typearrow\TTuple(\vlit)\\ - \equallength(\vlis, \vlit) \typearrow\True \terminateas \False\\ - \vi\in\listrange(\vlis): \typesat(\tenv, \vlit[\vi], \vlis[\vi]) \typearrow \vb_i \terminateas \TTypeError\\ - \vb \eqdef \bigwedge_{\vi=1}^k \vb_\vi -}{ - \subtypesat(\tenv, \vt, \vs) \typearrow \vb -} -\end{mathpar} - -\hypertarget{def-fieldnames}{} -For a list of typed fields $\fields$, we define the set of its field identifiers as: -\[ - \fieldnames(\fields) \triangleq \{ \id \;|\; (\id, \vt) \in \fields\} -\] -\hypertarget{def-fieldtype}{} -We define the type associated with the field name $\id$ in a list of typed fields $\fields$, -if there is a unique one, as follows: -\[ - \fieldtype(\fields, \id) \triangleq - \begin{cases} - \vt & \text{ if }\{ \vtp \;|\; (\id,\vtp) \in \fields\} = \{\vt\}\\ - \bot & \text{ otherwise} - \end{cases} -\] - -\begin{mathpar} -\inferrule[structured]{ - L \in \{\TRecord, \TException\}\\ - \makeanonymous(\tenv, \vs)\typearrow L(\vfieldss) \\ - \makeanonymous(\tenv, \vt)\typearrow L(\vfieldst) \\ - \vnamess \eqdef \fieldnames(\vfieldss)\\ - \vnamest \eqdef \fieldnames(\vfieldst)\\ - \booltrans{\vnamess \subseteq \vnamest} \booltransarrow \True \terminateas \False\\ - (\id,\vtys)\in\vfieldss: \typeequal(\tenv, \vtys, \fieldtype(\vfieldst, \id)) \typearrow \vb_\id\\ - \vb \eqdef \bigwedge_{\id \in \vnamess} \vb_\id -}{ - \subtypesat(\tenv, \vs, \vt) \typearrow \vb -} -\end{mathpar} - -\isempty{\subsection{Comments}} -\lrmcomment{This is related to \identd{TRVR}, \identi{SJDC}, \identi{MHYB}, \identi{TWTZ}, \identi{GYSK}, \identi{KXSD}, \identi{KNXJ}.} - -\isempty{\subsection{Example}} - -\CodeSubsection{\SubtypeSatisfactionBegin}{\SubtypeSatisfactionEnd}{../types.ml} - -\section{TypingRule.TypeSatisfaction \label{sec:TypingRule.TypeSatisfaction}} -\hypertarget{def-typesatisfies}{} -The predicate -\[ - \typesat(\overname{\staticenvs}{\tenv} \aslsep \overname{\ty}{\vt} \aslsep \overname{\ty}{\vs}) - \aslto \overname{\Bool}{\vb} \cup \overname{\TTypeError}{\TypeErrorConfig} -\] -tests whether a type $\vt$ \emph{\typesatisfies} a type $\vs$ in environment $\tenv$, -returning the result $\vb$ or a type error, if one is detected. - -\hypertarget{def-checktypesat}{} -We also define -\[ - \checktypesat(\overname{\staticenvs}{\tenv} \aslsep \overname{\ty}{\vt} \aslsep \overname{\ty}{\vs}) - \aslto \{\True\} \cup \overname{\TTypeError}{\TypeErrorConfig} -\] -which is the same as $\typesat$, but yields a type error when \\ $\typesat(\tenv, \vt, \vs)$ is $\False$. - -These functions assume that both $\vt$ and $\vs$ are well-typed according to \chapref{typingoftypes}. - -\subsection{Prose} -One of the following applies: - \begin{itemize} - \item All of the following apply (\textsc{subtypes}): - \begin{itemize} - \item $\vt$ subtypes $\vs$ in $\tenv$ ; - \item $\vb$ is $\True$. - \end{itemize} - - \item All of the following apply (\textsc{anonymous}): - \begin{itemize} - \item $\vt$ does not subtype $\vs$ in $\tenv$; - \item at least one of $\vt$ and $\vs$ is an anonymous type in $\tenv$; - \item determining whether $\vt$ \subtypesatisfies\ $\vs$ in $\tenv$ yields $\True$\ProseOrTypeError; - \item $\vb$ is $\True$. - \end{itemize} - - \item All of the following apply (\textsc{t\_bits}): - \begin{itemize} - \item $\vt$ does not subtype $\vs$ in $\tenv$; - \item determining whether $\vt$ is anonymous yields $\vbone$; - \item determining whether $\vs$ is anonymous yields $\vbtwo$; - \item determining whether $\vt$ \subtypesatisfies\ $\vs$ in $\tenv$ yields $\vbthree$; - \item $(\vbone \lor \vbtwo) \land \vbthree$ is $\False$; - \item $\vt$ is a bitvector type with width $\widtht$ and no bitfields; - \item obtaining the \structure\ of $\vs$ in $\tenv$ yields a bitvector type with width \\ - $\widths$\ProseOrTypeError; - \item determining whether $\widtht$ and $\widths$ are \bitwidthequivalent\ yields $\vb$. - \end{itemize} - - \item All of the following apply (\textsc{otherwise1}): - \begin{itemize} - \item $\vt$ does not subtype $\vs$ in $\tenv$; - \item determining whether $\vt$ is anonymous yields $\vbone$; - \item determining whether $\vs$ is anonymous yields $\vbtwo$; - \item determining whether $\vt$ \subtypesatisfies\ $\vs$ in $\tenv$ yields $\vbthree$; - \item $(\vbone \lor \vbtwo) \land \vbthree$ is $\False$; - \item obtaining the \structure\ of $\vs$ in $\tenv$ yields a $\vsstruct$\ProseOrTypeError; - \item at least one of $\vt$ and $\vsstruct$ is not a bitvector type; - \end{itemize} - - \item All of the following apply (\textsc{otherwise2}): - \begin{itemize} - \item $\vt$ does not subtype $\vs$ in $\tenv$; - \item determining whether $\vt$ is anonymous yields $\vbone$; - \item determining whether $\vs$ is anonymous yields $\vbtwo$; - \item determining whether $\vt$ \subtypesatisfies\ $\vs$ in $\tenv$ yields $\vbthree$; - \item $(\vbone \lor \vbtwo) \land \vbthree$ is $\False$; - \item obtaining the \structure\ of $\vs$ in $\tenv$ yields a $\vsstruct$\ProseOrTypeError; - \item both $\vt$ and $\vsstruct$ are bitvector types; - \item the bitvector type $\vt$ has a non-empty list of bitfields; - \item $\vb$ is $\False$; - \end{itemize} -\end{itemize} - -\subsection{Example} -In the specification: -\VerbatimInput{../tests/ASLTypingReference.t/TypingRule.TypeSatisfaction1.asl} -\texttt{var pair: pairT = (1, dataT1)} is legal since the right-hand-side has -anonymous, non-primitive type \texttt{(integer, T1)}. - -\subsection{Example} -In the specification: -\VerbatimInput{../tests/ASLTypingReference.t/TypingRule.TypeSatisfaction2.asl} -\texttt{pair = (1, dataAsInt);} is legal since the right-hand-side has anonymous, -primitive type \texttt{(integer, integer)}. - -\subsection{Example} -In the specification: -\VerbatimInput{../tests/ASLTypingReference.t/TypingRule.TypeSatisfaction3.asl} -\texttt{pair = (1, dataT2);} is illegal since the right-hand-side has anonymous, -non-primitive type \texttt{(integer, T2)} which does not subtype-satisfy named -type \texttt{pairT}. - -\CodeSubsection{\TypeSatisfactionBegin}{\TypeSatisfactionEnd}{../types.ml} - -\subsection{Formally} -\begin{mathpar} -\inferrule[subtypes]{ - \subtypesrel(\tenv, \vt, \vs) \typearrow \True -}{ - \typesat(\tenv, \vt, \vs) \typearrow \True -} -\end{mathpar} - -\begin{mathpar} -\inferrule[anonymous]{ - \subtypesrel(\tenv, \vt, \vs) \typearrow \False\\ - \isanonymous(\tenv, \vt) \typearrow \vbone\\ - \isanonymous(\tenv, \vs) \typearrow \vbtwo\\ - \vbone \lor \vbtwo\\ - \subtypesat(\tenv, \vt, \vs) \typearrow \True -}{ - \typesat(\tenv, \vt, \vs) \typearrow \True -} -\end{mathpar} - -\begin{mathpar} -\inferrule[t\_bits]{ - \subtypesrel(\tenv, \vt, \vs) \typearrow \False\\ - \isanonymous(\tenv, \vt) \typearrow \vbone\\ - \isanonymous(\tenv, \vs) \typearrow \vbtwo\\ - \subtypesat(\tenv, \vt, \vs) \typearrow \vbthree\\ - \neg((\vbone \lor \vbtwo) \land \vbthree)\\ - \vt \eqname \TBits(\widtht, \emptylist)\\ - \tstruct(\tenv, \vs) \typearrow \TBits(\widths, \Ignore) \OrTypeError\\\\ - \bitwidthequal(\tenv, \widtht, \widths) \typearrow \vb -}{ - \typesat(\tenv, \vt, \vs) \typearrow \vb -} -\end{mathpar} - -\begin{mathpar} -\inferrule[otherwise1]{ - \subtypesrel(\tenv, \vt, \vs) \typearrow \False\\ - \isanonymous(\tenv, \vt) \typearrow \vbone\\ - \isanonymous(\tenv, \vs) \typearrow \vbtwo\\ - \subtypesat(\tenv, \vt, \vs) \typearrow \vbthree\\ - \neg((\vbone \lor \vbtwo) \land \vbthree)\\ - \tstruct(\tenv, \vs) \typearrow \vsstruct\\ - \astlabel(\vt) \neq \TBits \lor \astlabel(\vsstruct) \neq \TBits -}{ - \typesat(\tenv, \vt, \vs) \typearrow \overname{\False}{\vb} -} -\end{mathpar} - -\begin{mathpar} -\inferrule[otherwise2]{ - \subtypesrel(\tenv, \vt, \vs) \typearrow \False\\ - \isanonymous(\tenv, \vt) \typearrow \vbone\\ - \isanonymous(\tenv, \vs) \typearrow \vbtwo\\ - \subtypesat(\tenv, \vt, \vs) \typearrow \vbthree\\ - \neg((\vbone \lor \vbtwo) \land \vbthree)\\ - \tstruct(\tenv, \vs) \typearrow \vsstruct\\ - \astlabel(\vt) = \TBits \land \astlabel(\vsstruct) = \TBits\\ - \vt \eqname \TBits(\widtht, \bitfields)\\ - \bitfields \neq \emptylist -}{ - \typesat(\tenv, \vt, \vs) \typearrow \overname{\False}{\vb} -} -\end{mathpar} - -The rules for the checked type-satisfy predicate are: -\begin{mathpar} -\inferrule[true]{ - \typesat(\tenv, \vt, \vs) \typearrow \True \OrTypeError\\ -}{ - \checktypesat(\tenv, \vt, \vs) \typearrow \True -} -\end{mathpar} - -\begin{mathpar} -\inferrule[error]{ - \typesat(\tenv, \vt, \vs) \typearrow \False -}{ - \checktypesat(\tenv, \vt, \vs) \typearrow \TypeErrorVal{TypeConflict} -} -\end{mathpar} - -\subsection{Comments} -Since the subtype relation is a partial order, it is reflexive. Therefore -every type $\vt$ is a subtype of itself, and as a consequence, every type $\vt$ -\typesatisfies\ itself. - -\lrmcomment{This is related to \identr{FMXK} and \identi{NLFD}.} - -\section{TypingRule.TypeClash\label{sec:TypingRule.TypeClash}} -\hypertarget{def-typeclashes}{} -The predicate -\[ - \typeclashes(\overname{\staticenvs}{\tenv} \aslsep \overname{\ty}{\vt} \aslsep \overname{\ty}{\vs}) - \aslto \overname{\Bool}{\vb} \cup \overname{\TTypeError}{\TypeErrorConfig} -\] -tests whether a type $\vt$ \emph{type-clashes} with a type $\vs$ in environment $\tenv$, -returning the result $\vb$ or a type error, if one is detected. - -\subsection{Prose} - One of the following applies: -\begin{itemize} - \item All of the following apply (\textsc{subtype}): - \begin{itemize} - \item either $\vs$ subtypes $\vt$ or $\vt$ subtypes $\vs$; - \item $\vb$ is $\True$. - \end{itemize} - - \item All of the following apply (\textsc{simple}): - \begin{itemize} - \item neither $\vs$ subtypes $\vt$ nor $\vt$ subtypes $\vs$; - \item obtaining the \structure\ of $\vt$ in $\tenv$ yields $\vtstruct$\ProseOrTypeError; - \item obtaining the \structure\ of $\vs$ in $\tenv$ yields $\vsstruct$\ProseOrTypeError; - \item both $\vtstruct$ and $\vsstruct$ are one of the following types: \\ \texttt{integer}, \texttt{real}, \texttt{string}; - \item $\vb$ is $\True$. - \end{itemize} - - \item All of the following apply (\textsc{t\_enum}): - \begin{itemize} - \item neither $\vs$ subtypes $\vt$ nor $\vt$ subtypes $\vs$; - \item obtaining the \structure\ of $\vt$ in $\tenv$ yields an enumeration type with labels $\vlit$; - \item obtaining the \structure\ of $\vs$ in $\tenv$ yields an enumeration type with labels $\vlis$; - \item $\vb$ is $\True$ if and only if $\vlis$ and $\vlit$ are equal. - \end{itemize} - - \item All of the following apply (\textsc{t\_array}): - \begin{itemize} - \item neither $\vs$ subtypes $\vt$ nor $\vt$ subtypes $\vs$; - \item obtaining the \structure\ of $\vt$ in $\tenv$ yields an array type with element type $\vtyt$; - \item obtaining the \structure\ of $\vs$ in $\tenv$ yields an array type with element type $\vtys$; - \item $\vb$ is $\True$ if and only if $\vtyt$ and $\vtys$ type-clash. - \end{itemize} - - \item All of the following apply (\textsc{t\_tuple}): - \begin{itemize} - \item neither $\vs$ subtypes $\vt$ nor $\vt$ subtypes $\vs$; - \item obtaining the \structure\ of $\vt$ in $\tenv$ yields a tuple type with element types $\vt_{1..k}$; - \item obtaining the \structure\ of $\vs$ in $\tenv$ yields a tuple type with element types $\vs_{1..n}$; - \item if $n \neq k$ the rule short-circuits with $\vb=\False$; - \item $\vb$ is $\True$ if and only if $\vt_i$ type-clashes with $\vs_i$, for all $i=1..k$. - \end{itemize} - - \item All of the following apply (\textsc{otherwise\_different\_labels}): - \begin{itemize} - \item neither $\vs$ subtypes $\vt$ nor $\vt$ subtypes $\vs$; - \item obtaining the \structure\ of $\vt$ in $\tenv$ yields $\vtstruct$; - \item obtaining the \structure\ of $\vs$ in $\tenv$ yields $\vsstruct$; - \item $\vsstruct$ and $\vtstruct$ have different AST labels; - \item $\vb$ is $\False$; - \end{itemize} - - \item All of the following apply (\textsc{otherwise\_structured}): - \begin{itemize} - \item neither $\vs$ subtypes $\vt$ nor $\vt$ subtypes $\vs$; - \item obtaining the \structure\ of $\vt$ in $\tenv$ yields $\vtstruct$; - \item obtaining the \structure\ of $\vs$ in $\tenv$ yields $\vsstruct$; - \item $\vsstruct$ and $\vtstruct$ have the same AST label; - \item $\vtstruct$ (and thus $\vsstruct$) is a \structuredtype; - \item $\vb$ is $\False$; - \end{itemize} -\end{itemize} - -\isempty{\subsection{Example}} - -\CodeSubsection{\TypeClashBegin}{\TypeClashEnd}{../types.ml} - -\subsection{Formally} -\begin{mathpar} -\inferrule[subtype]{ - (\subtypesrel(\tenv, \vs, \vt) \typearrow \True) \lor (\subtypesrel(\tenv, \vt, \vs) \typearrow \True) -}{ - \typeclashes(\tenv, \vt, \vs) \typearrow \overname{\True}{\vb} -} -\end{mathpar} - -\begin{mathpar} -\inferrule[simple]{ - \subtypesrel(\tenv, \vs, \vt) \typearrow \False\\ - \subtypesrel(\tenv, \vt, \vs) \typearrow \False\\\\ - \tstruct(\tenv, \vt) \typearrow \vtstruct \OrTypeError \\ - \tstruct(\tenv, \vs) \typearrow \vsstruct \OrTypeError \\ - \astlabel(\vtstruct)=\astlabel(\vsstruct)\\ - \astlabel(\vtstruct) \in \{\TInt, \TReal, \TString, \TBits\} -}{ - \typeclashes(\tenv, \vt, \vs) \typearrow \overname{\True}{\vb} -} -\end{mathpar} - -\begin{mathpar} -\inferrule[t\_enum]{ - \subtypesrel(\tenv, \vs, \vt) \typearrow \False\\ - \subtypesrel(\tenv, \vt, \vs) \typearrow \False\\\\ - \tstruct(\tenv, \vt) \typearrow \TEnum(\Ignore, \vlis) \\ - \tstruct(\tenv, \vs) \typearrow \TEnum(\Ignore, \vlit) -}{ - \typeclashes(\tenv, \vt, \vs) \typearrow \overname{\vlis = \vlit}{\vb} -} -\end{mathpar} - -\begin{mathpar} -\inferrule[t\_array]{ - \subtypesrel(\tenv, \vs, \vt) \typearrow \False\\ - \subtypesrel(\tenv, \vt, \vs) \typearrow \False\\\\ - \tstruct(\tenv, \vt) \typearrow \TArray(\Ignore, \vtyt) \\ - \tstruct(\tenv, \vs) \typearrow \TArray(\Ignore, \vtys) \\ - \typeclashes(\tenv, \vtyt, \vtys) \typearrow \vb -}{ - \typeclashes(\tenv, \vt, \vs) \typearrow \vb -} -\end{mathpar} - -\begin{mathpar} -\inferrule[t\_tuple]{ - \subtypesrel(\tenv, \vs, \vt) \typearrow \False\\ - \subtypesrel(\tenv, \vt, \vs) \typearrow \False\\\\ - \tstruct(\tenv, \vt) \typearrow \TTuple(\vt_{1..k}) \\ - \tstruct(\tenv, \vs) \typearrow \TTuple(\vs_{1..n}) \\ - \booltrans{n = k} \booltransarrow \True \terminateas \False\\ - i=1..k: \typeclashes(\tenv, \vt_i, \vs_i) \typearrow \vb_i\\ - \vb \eqdef \bigwedge_{\vi=1}^k \vb_i -}{ - \typeclashes(\tenv, \vt, \vs) \typearrow \vb -} -\end{mathpar} - -\begin{mathpar} -\inferrule[otherwise\_different\_labels]{ - \subtypesrel(\tenv, \vs, \vt) \typearrow \False\\ - \subtypesrel(\tenv, \vt, \vs) \typearrow \False\\\\ - \tstruct(\tenv, \vt) \typearrow \vtstruct \\ - \tstruct(\tenv, \vs) \typearrow \vsstruct \\ - \astlabel(\vtstruct) \neq \astlabel(\vsstruct) -}{ - \typeclashes(\tenv, \vt, \vs) \typearrow \overname{\False}{\vb} -} -\end{mathpar} - -\begin{mathpar} -\inferrule[otherwise\_structured]{ - \subtypesrel(\tenv, \vs, \vt) \typearrow \False\\ - \subtypesrel(\tenv, \vt, \vs) \typearrow \False\\\\ - \tstruct(\tenv, \vt) \typearrow \vtstruct \\ - \tstruct(\tenv, \vs) \typearrow \vsstruct \\ - \astlabel(\vtstruct) = \astlabel(\vsstruct)\\ - \vb \eqdef \astlabel(\vtstruct) \in \{\TRecord, \TException\}\\ -}{ - \typeclashes(\tenv, \vt, \vs) \typearrow \overname{\False}{\vb} -} -\end{mathpar} - -\subsection{Comments} -Note that if $\vt$ subtype-satisfies $\vs$ then $\vt$ and $\vs$ type-clash, but not the other -way around. - -Note that type-clashing is an equivalence relation. Therefore if $\vt$ -type-clashes with \texttt{A} and \texttt{B} then it is also the case that \texttt{A} and \texttt{B} type-clash. - -\lrmcomment{This is related to \identd{VPZZ}, \identi{PQCT} and \identi{WZKM}.} - -\section{TypingRule.LowestCommonAncestor \label{sec:TypingRule.LowestCommonAncestor}} -\hypertarget{def-lowestcommonancestor}{} -Annotating a conditional expression (see \secref{TypingRule.ECond}), -requires finding a single type that can be used to annotate the results of both subexpressions. -The function -\[ - \lca(\overname{\staticenvs}{\tenv} \aslsep \overname{\ty}{\vt} \aslsep \overname{\ty}{\vs}) - \aslto \overname{\ty}{\tty} \cup \overname{\TTypeError}{\TypeErrorConfig} -\] -returns the \emph{lowest common ancestor} of types $\vt$ and $\vs$ in $\tenv$ --- $\tty$. -The result is a type error if a lowest common ancestor does not exist or a type error is detected. - -\subsection{Prose} -One of the following applies: -\begin{itemize} - \item All of the following apply (\textsc{type\_equal}): - \begin{itemize} - \item $\vt$ is \typeequal\ to $\vs$ in $\tenv$; - \item $\tty$ is $\vs$ (can as well be $\vt$). - \end{itemize} - - \item All of the following apply: - \begin{itemize} - \item $\vt$ is not \typeequal\ to $\vs$ in $\tenv$ and one of the following applies: - - \item All of the following apply (\textsc{named\_subtype1}): - \begin{itemize} - \item $\vt$ is a named type with identifier $\namesubt$, that is, $\TNamed(\namesubt)$; - \item $\vs$ is a named type with identifier $\namesubs$, that is, $\TNamed(\namesubs)$; - \item there is no \namedlowestcommonancestor\ of $\namesubs$ and $\namesubt$ in $\tenv$; - \item obtaining the \underlyingtype\ of $\vs$ yields $\vanons$\ProseOrTypeError; - \item obtaining the \underlyingtype\ of $\vt$ yields $\vanont$\ProseOrTypeError; - \item obtaining the lowest common ancestor of $\vanons$ and $\vanont$ in $\tenv$ yields $\tty$\ProseOrTypeError. - \end{itemize} - - \item All of the following apply (\textsc{named\_subtype2}): - \begin{itemize} - \item $\vt$ is a named type with identifier $\namesubt$, that is, $\TNamed(\namesubt)$; - \item $\vs$ is a named type with identifier $\namesubs$, that is, $\TNamed(\namesubs)$; - \item the \namedlowestcommonancestor\ of $\namesubs$ and $\namesubt$ in $\tenv$ is \\ - $\name$\ProseOrTypeError; - \item $\tty$ is the named type with identifier $\name$, that is, $\TNamed(\name)$. - \end{itemize} - - \item All of the following apply (\textsc{one\_named1}): - \begin{itemize} - \item only one of $\vt$ or $\vs$ is a named type; - \item obtaining the \underlyingtype\ of $\vs$ yields $\vanons$\ProseOrTypeError; - \item obtaining the \underlyingtype\ of $\vt$ yields $\vanont$\ProseOrTypeError; - \item $\vanont$ is \typeequal\ to $\vanons$; - \item $\tty$ is $\vt$ if it is a named type (that is, $\astlabel(\vt)=\TNamed$), and $\vs$ otherwise. - \end{itemize} - - \item All of the following apply (\textsc{one\_named2}): - \begin{itemize} - \item only one of $\vt$ or $\vs$ is a named type; - \item obtaining the \underlyingtype\ of $\vs$ yields $\vanons$\ProseOrTypeError; - \item obtaining the \underlyingtype\ of $\vt$ yields $\vanont$\ProseOrTypeError; - \item $\vanont$ is not \typeequal\ to $\vanons$; - \item the lowest common ancestor of $\vanont$ and $\vanons$ in $\tenv$ is $\tty$\ProseOrTypeError. - \end{itemize} - - \item All of the following apply (\textsc{t\_int\_unconstrained}): - \begin{itemize} - \item both $\vt$ and $\vs$ are integer types; - \item at least one of $\vt$ or $\vs$ is an unconstrained integer type; - \item $\tty$ is the unconstrained integer type. - \end{itemize} - - \item All of the following apply (\textsc{t\_int\_parameterized}): - \begin{itemize} - \item neither $\vt$ nor $\vs$ are the unconstrained integer type; - \item one of $\vt$ and $\vs$ is a \parameterizedintegertype; - \item the \wellconstrainedversion\ of $\vt$ is $\vtone$; - \item the \wellconstrainedversion\ of $\vs$ is $\vsone$; - \item $\tty$ the lowest common ancestor of $\vtone$ and $\vsone$ in $\tenv$ is $\tty$\ProseOrTypeError. - \end{itemize} - - \item All of the following apply (\textsc{t\_int\_wellconstrained}): - \begin{itemize} - \item $\vt$ is a well-constrained integer type with constraints $\cst$; - \item $\vs$ is a well-constrained integer type with constraints $\css$; - \item $\tty$ is the well-constrained integer type with constraints $\cst \concat \css$. - \end{itemize} - - \item All of the following apply (\textsc{t\_bits}): - \begin{itemize} - \item $\vt$ is a bitvector type with with length expression $\vet$, that is, $\TBits(\vet, \Ignore)$; - \item $\vs$ is a bitvector type with with length expression $\ves$, that is, $\TBits(\ves, \Ignore)$; - \item applying $\typeequal$ to $\vt$ and $\vs$ in $\tenv$ yields $\False$; - \item applying $\exprequal$ to $\vet$ and $\ves$ in $\tenv$ yields $\vbequal$; - \item checking whether $\vbequal$ is $\True$ yields $\True$\ProseTerminateAs{\NoLCA}; - \item $\tty$ is a bitvector type with length expression $\vet$ and an empty bitfield list, that is, $\TBits(\vet, \emptylist)$. - \end{itemize} - - \item All of the following apply (\textsc{t\_array}): - \begin{itemize} - \item $\vt$ is an array type with width expression $\widtht$ and element type $\vtyt$; - \item $\vs$ is an array type with width expression $\widths$ and element type $\vtys$; - \item applying $\arraylengthequal$ to $\widtht$ and $\widths$ in $\tenv$ to equate the array lengths, - yields $\vbequallength$\ProseOrTypeError; - \item checking that $\vbequallength$ is $\True$ yields $\True$\ProseTerminateAs{\NoLCA}; - \item the lowest common ancestor of $\vtyt$ and $\vtys$ is $\vtone$\ProseOrTypeError; - \item $\tty$ is an array type with width expression $\widths$ and element type $\vtone$. - \end{itemize} - - \item All of the following apply (\textsc{t\_tuple}): - \begin{itemize} - \item $\vt$ is a tuple type with type list $\vlit$; - \item $\vs$ is a tuple type with type list $\vlis$; - \item checking whether $\vlit$ and $\vlis$ have the same number of elements yields $\True$ - or a type error, which short-circuits the entire rule (indicating that the number of elements in both tuples is expected - to be the same and thus there is no lowest common ancestor); - \item applying $\lca$ to $\vlit[\vi]$ and $\vlis[\vi]$ in $\tenv$, for every position of $\vlit$, - yields $\vt_\vi$\ProseOrTypeError; - \item define $\vli$ to be the list of types $\vt_\vi$, for every position of $\vlit$; - \item define $\tty$ as the tuple type with list of types $\vli$, that is, $\TTuple(\vli)$. - \end{itemize} - - \item All of the following apply (\textsc{error}): - \begin{itemize} - \item either the AST labels of $\vt$ and $\vs$ are different, or one of them is $\TEnum$, $\TRecord$, or $\TException$; - \item the result is a type error indicating the lack of a lowest common ancestor. - \end{itemize} - \end{itemize} -\end{itemize} - -\isempty{\subsection{Example}} - -\CodeSubsection{\LowestCommonAncestorBegin}{\LowestCommonAncestorEnd}{../types.ml} - -\subsection{Formally} -Since we do not impose a canonical representation on types (e.g., \verb|integer {1, 2}| is equivalence to \verb|integer {1..2}|), -the lowest common ancestor is not unique. -We define $\lca(\tenv, \vt, \vs)$ to be any type $\vtp$ that is \typeequivalent\ to the lowest common ancestor of $\vt$ and $\vs$. - -\begin{mathpar} -\inferrule[type\_equal]{ - \typeequal(\tenv, \vt, \vs) \typearrow \True -}{ - \lca(\tenv, \vt, \vs) \typearrow \overname{\vs}{\tty} -} -\end{mathpar} - -\begin{mathpar} -\inferrule[named\_subtype1]{ - \vt = \TNamed(\namesubs)\\ - \vs = \TNamed(\namesubt)\\ - \typeequal(\tenv, \vt, \vs) \typearrow \False\\ - \namedlca(\tenv, \namesubs, \namesubt) \typearrow \None \OrTypeError\\\\ - \makeanonymous(\tenv, \vs) \typearrow \vanons \OrTypeError\\\\ - \makeanonymous(\tenv, \vt) \typearrow \vanont \OrTypeError\\\\ - \lca(\tenv, \vanont, \vanons) \typearrow \tty \OrTypeError -}{ - \lca(\tenv, \vt, \vs) \typearrow \tty -} -\end{mathpar} - -\begin{mathpar} -\inferrule[named\_subtype2]{ - \vt = \TNamed(\namesubs)\\ - \vs = \TNamed(\namesubt)\\ - \typeequal(\tenv, \vt, \vs) \typearrow \False\\ - \namedlca(\tenv, \namesubs, \namesubt) \typearrow \langle\name\rangle \OrTypeError\\ -}{ - \lca(\tenv, \vt, \vs) \typearrow \overname{\TNamed(\name)}{\tty} -} -\end{mathpar} - -\begin{mathpar} -\inferrule[one\_named1]{ - \typeequal(\tenv, \vt, \vs) \typearrow \False\\ - (\astlabel(\vt) = \TNamed \lor \astlabel(\vs) = \TNamed)\\ - \astlabel(\vt) \neq \astlabel(\vs)\\ - \makeanonymous(\tenv, \vs) \typearrow \vanons \OrTypeError\\\\ - \makeanonymous(\tenv, \vt) \typearrow \vanont \OrTypeError\\\\ - \typeequal(\tenv, \vanont, \vanons) \typearrow \True\\ - \tty \eqdef \choice{\astlabel(\vt) = \TNamed}{\vt}{\vs} -}{ - \lca(\tenv, \vt, \vs) \typearrow \tty -} -\end{mathpar} - -\begin{mathpar} -\inferrule[one\_named2]{ - \typeequal(\tenv, \vt, \vs) \typearrow \False\\ - (\astlabel(\vt) = \TNamed \lor \astlabel(\vs) = \TNamed)\\ - \astlabel(\vt) \neq \astlabel(\vs)\\ - \makeanonymous(\tenv, \vs) \typearrow \vanons \OrTypeError\\\\ - \makeanonymous(\tenv, \vt) \typearrow \vanont \OrTypeError\\\\ - \typeequal(\tenv, \vanont, \vanons) \typearrow \False\\ - \lca(\tenv, \vanont, \vanons) \typearrow \tty \OrTypeError -}{ - \lca(\tenv, \vt, \vs) \typearrow \tty -} -\end{mathpar} - -\begin{mathpar} -\inferrule[t\_int\_unconstrained]{ - \typeequal(\tenv, \vt, \vs) \typearrow \False\\ - \astlabel(\vt) = \astlabel(\vs) = \TInt\\ - \isunconstrainedinteger(\vt) \lor \isunconstrainedinteger(\vs) -}{ - \lca(\tenv, \vt, \vs) \typearrow \overname{\unconstrainedinteger}{\tty} -} -\and -\inferrule[t\_int\_parameterized]{ - \typeequal(\tenv, \vt, \vs) \typearrow \False\\ - \astlabel(\vt) = \astlabel(\vs) = \TInt\\ - \neg\isunconstrainedinteger(\vt)\\ - \neg\isunconstrainedinteger(\vs)\\ - \isparameterizedinteger(\vt) \lor \isparameterizedinteger(\vs)\\ - \towellconstrained(\tenv, \vt) \typearrow \vtone\\ - \towellconstrained(\tenv, \vs) \typearrow \vsone\\ - \lca(\tenv, \vtone, \vsone) \typearrow \tty \OrTypeError -}{ - \lca(\tenv, \vt, \vs) \typearrow \tty -} -\and -\inferrule[t\_int\_wellconstrained] -{ - \typeequal(\tenv, \vt, \vs) \typearrow \False\\ - \vt \eqname \TInt(\wellconstrained(\cst))\\ - \vs \eqname \TInt(\wellconstrained(\css)) -}{ - \lca(\tenv, \vt, \vs) \typearrow \overname{\TInt(\wellconstrained(\cst \concat \css))}{\tty} -} -\end{mathpar} - -\begin{mathpar} -\inferrule[t\_bits]{ - \typeequal(\tenv, \vt, \vs) \typearrow \False\\ - \exprequal(\tenv, \vet, \ves) \typearrow \vbequal\\ - \checktrans{\vbequal}{\NoLCA} \checktransarrow \True \OrTypeError -}{ - \lca(\tenv, \overname{\TBits(\vet, \Ignore)}{\vt}, \overname{\TBits(\ves, \Ignore)}{\vs}) \typearrow \overname{\TBits(\vet, \emptylist)}{\tty} -} -\end{mathpar} - -\begin{mathpar} -\inferrule[t\_array]{ - \typeequal(\tenv, \vt, \vs) \typearrow \False\\ - \arraylengthequal(\tenv, \widtht, \widths) \typearrow \vbequallength \OrTypeError\\\\ - \checktrans{\vbequallength}{\NoLCA} \checktransarrow \True \OrTypeError\\\\ - \lca(\tenv, \vtyt, \vtys) \typearrow \vtone \OrTypeError -}{ - { - \begin{array}{r} - \lca(\tenv, \overname{\TArray(\widtht, \vtyt)}{\vt}, \overname{\TArray(\widths, \vtys)}{\vs}) \typearrow \\ - \overname{\TArray(\widtht, \vtone)}{\tty} - \end{array} - } -} -\end{mathpar} - -\begin{mathpar} -\inferrule[t\_tuple]{ - \typeequal(\tenv, \vt, \vs) \typearrow \False\\ - \equallength(\vlit, \vlis) \typearrow \vb\\ - \checktrans{\vb}{\NoLCA} \typearrow \True \OrTypeError\\\\ - { - \begin{array}{r} - \vi\in\listrange(\vlit): \lca(\tenv, \vlit[\vi], \vlis[\vi]) \typearrow \\ - \vt_\vi \OrTypeError - \end{array} - }\\ - \vli \eqdef [\vi\in\listrange(\vlit): \vt_\vi] -}{ - \lca(\tenv, \overname{\TTuple(\vlit)}{\vt}, \overname{\TTuple(\vlis)}{\vs}) \typearrow \overname{\TTuple(\vli)}{\tty} -} -\end{mathpar} - -\begin{mathpar} -\inferrule[error]{ - \typeequal(\tenv, \vt, \vs) \typearrow \False\\ - (\astlabel(\vt) \neq \astlabel(\vs)) \lor - \astlabel(\vt) \in \{\TEnum, \TRecord, \TException\} -}{ - \lca(\tenv, \vt, \vs) \typearrow \TypeErrorVal{\NoLCA} -} -\end{mathpar} - -\isempty{\subsection{Comments}} -\lrmcomment{This is related to \identr{YZHM}.} - -\section{TypingRule.CheckUnop \label{sec:TypingRule.CheckUnop}} -\hypertarget{def-checkunop}{} -The function -\[ - \CheckUnop(\overname{\staticenvs}{\tenv} \aslsep \overname{\unop}{\op} \aslsep \overname{\ty}{\vt}) - \aslto \overname{\ty}{\vs} \cup \overname{\TTypeError}{\TypeErrorConfig} -\] -determines the result type of applying a unary operator when the type of its operand is known. -Similarly, we determine the negation of integer constraints. -\ProseOtherwiseTypeError - -\subsection{Prose} -One of the following applies: -\begin{itemize} -\item All of the following apply (\textsc{bnot\_t\_bool}): - \begin{itemize} - \item $\op$ is $\BNOT$; - \item determining whether $\vt$ \typesatisfies\ $\TBool$ yields $\True$\ProseOrTypeError; - \item $\vs$ is $\TBool$; - \end{itemize} - -\item All of the following apply (\textsc{neg\_error}): -\begin{itemize} - \item $\op$ is $\NEG$; - \item determining whether $\vt$ \typesatisfies\ $\TReal$ yields $\False$\ProseOrTypeError; - \item determining whether $\vt$ \typesatisfies\ $\unconstrainedinteger$ yields $\False$\ProseOrTypeError; - \item the result is a type error indicating the $\NEG$ is appropriate only for \texttt{real} and \texttt{integer} types; -\end{itemize} - -\item All of the following apply (\textsc{neg\_t\_real}): -\begin{itemize} - \item $\op$ is $\NEG$; - \item determining whether $\vt$ \typesatisfies\ $\TReal$ yields $\True$; - \item $\vs$ is $\TReal$; -\end{itemize} - -\item All of the following apply (\textsc{neg\_t\_int\_unconstrained}): -\begin{itemize} - \item $\op$ is $\NEG$; - \item obtaining the \wellconstrainedstructure\ of $\vt$ yields $\unconstrainedinteger$\ProseOrTypeError; - \item $\vs$ is $\unconstrainedinteger$; -\end{itemize} - -\item All of the following apply (\textsc{neg\_t\_int\_well\_constrained}): -\begin{itemize} - \item $\op$ is $\NEG$; - \item obtaining the \wellconstrainedstructure\ of $\vt$ yields the well-constrained integer type with constraints $\vcs$\ProseOrTypeError; - \item negating the constraints in $\vcs$ (see $\negateconstraint$) yields $\vcsnew$; - \item $\vs$ is the well-constrained integer type with constraints $\vcsnew$, that is, \\ - $\TInt(\wellconstrained(\vcsnew))$; -\end{itemize} - -\item All of the following apply (\textsc{not\_t\_bits}): - \begin{itemize} - \item $\op$ is $\NOT$; - \item $\vt$ has the structure of a bitvector; - \item $\vs$ is $\vt$. - \end{itemize} -\end{itemize} - -\isempty{\subsection{Example}} - -\CodeSubsection{\CheckUnopBegin}{\CheckUnopEnd}{../Typing.ml} - -\subsection{Formally} -\begin{mathpar} -\inferrule[bnot\_t\_bool]{ - \checktypesat(\tenv, \vtone, \TBool) \typearrow \True \OrTypeError\\ -}{ - \CheckUnop(\tenv, \BNOT, \vtone) \typearrow \TBool -} -\end{mathpar} - -\hypertarget{def-negateconstraint}{} -We now define the helper function -\[ - \negateconstraint(\intconstraint) \aslto \intconstraint -\] -which takes an integer constraint and returns the constraint that corresponds to the negation of all -the values it represents: - -\begin{mathpar} -\inferrule{} -{ - \negateconstraint(\ConstraintExact(\ve)) \typearrow \ConstraintExact(\EUnop(\MINUS, \ve)) -} -\and -\inferrule{} -{ - \negateconstraint(\ConstraintRange(\vvtop, \vbot)) \typearrow \\ - \ConstraintRange(\EUnop(\MINUS, \vbot), \EUnop(\MINUS, \vvtop)) -} -\end{mathpar} - -\begin{mathpar} -\inferrule[neg\_error]{ - \typesat(\tenv, \vt, \unconstrainedinteger) \typearrow \False \OrTypeError\\\\ - \typesat(\tenv, \vt, \TReal) \typearrow \False \OrTypeError\\ -}{ - \CheckUnop(\tenv, \overname{\NEG}{\op}, \vt) \typearrow \TypeErrorVal{InappropriateTypeForNeg} -} -\end{mathpar} - -\begin{mathpar} -\inferrule[neg\_t\_real]{ - \typesat(\tenv, \vt, \TReal) \typearrow \True -}{ - \CheckUnop(\tenv, \overname{\NEG}{\op}, \vt) \typearrow \overname{\TReal}{\vs} -} -\end{mathpar} - -\begin{mathpar} -\inferrule[neg\_t\_int\_unconstrained]{ - \getwellconstrainedstructure(\tenv, \vt) \typearrow \unconstrainedinteger \OrTypeError -}{ - \CheckUnop(\tenv, \overname{\NEG}{\op}, \vt) \typearrow \overname{\unconstrainedinteger}{\vs} -} -\end{mathpar} - -\begin{mathpar} -\inferrule[neg\_t\_int\_well\_constrained]{ - \getwellconstrainedstructure(\tenv, \vt) \typearrow \TInt(\wellconstrained(\vcs))\\ - \vc \in \vcs: \negateconstraint(\vc) \typearrow \vneg_\vc\\ - \vcsnew \eqdef [\vc \in \vcs: \vneg_\vc] -}{ - \CheckUnop(\tenv, \overname{\NEG}{\op}, \vt) \typearrow \overname{\TInt(\wellconstrained(\vcsnew))}{\vs} -} -\end{mathpar} - -\begin{mathpar} -\inferrule[not\_t\_bits]{ - \checkstructurelabel(\tenv, \vt, \TBits) \typearrow \True \OrTypeError -}{ - \CheckUnop(\tenv, \overname{\NOT}{\op}, \vt) \typearrow \vt -} -\end{mathpar} - -\isempty{\subsection{Comments}} - -\section{TypingRule.CheckBinop \label{sec:TypingRule.CheckBinop}} -\hypertarget{def-checkbinop}{} -The function -\[ - \CheckBinop(\overname{\staticenvs}{\tenv} \aslsep \overname{\binop}{\op} \aslsep \overname{\ty}{\vtone} - \aslsep \overname{\ty}{\vttwo}) - \aslto \overname{\ty}{\vt} \cup \overname{\TTypeError}{\TypeErrorConfig} -\] -determines the result type $\vt$ of applying the binary operator $\op$ -to operands of type $\vtone$ and $\vttwo$ in the static environment $\tenv$. -\ProseOtherwiseTypeError - -\subsection{Prose} -One of the following applies: -\begin{itemize} - \item All of the following apply (\textsc{boolean}): - \begin{itemize} - \item $\op$ is $\AND$, $\OR$, $\EQOP$ or $\IMPL$; - \item determining whether $\vtone$ \typesatisfies\ $\TBool$ in $\tenv$ yields $\True$\ProseOrTypeError; - \item determining whether $\vttwo$ \typesatisfies\ $\TBool$ in $\tenv$ yields $\True$\ProseOrTypeError; - \item $\vt$ is $\TBool$. - \end{itemize} - - \item All of the following apply (\textsc{bits\_bool}): - \begin{itemize} - \item $\op$ is $\AND$, $\OR$, or $\XOR$; - \item checking whether $\vtone$ and $\vttwo$ have the \structure\ of bitvector types - of the same width in $\tenv$ yields $\True$\ProseOrTypeError; - \item the bitvector width of $\vtone$ in $\tenv$ is $\vw$; - \item $\vt$ is the bitvector type of width $\vw$ and empty list of bitfields, that is, \\ $\TBits(\vw, \emptylist)$. - \end{itemize} - - \item All of the following apply (\textsc{plus\_minus\_error}): - \begin{itemize} - \item $\op$ is $\PLUS$ or $\MINUS$; - \item obtaining the \structure\ of $\vtone$ in $\tenv$ is $\vtonestruct$\ProseOrTypeError; - \item $\vtonestruct$ is neither a bitvector type nor an integer type; - \item the result is a type error indicating that the type of $\vtone$ is inappropriate for $\op$. - \end{itemize} - - \item All of the following apply (\textsc{plus\_minus\_bits\_int}): - \begin{itemize} - \item $\op$ is $\PLUS$ or $\MINUS$; - \item obtaining the \structure\ of $\vtone$ in $\tenv$ is $\vtonestruct$\ProseOrTypeError; - \item $\vtonestruct$ is a bitvector type; - \item $\vttwo$ \typesatisfies\ the unconstrained integer type in $\tenv$; - \item obtaining the bitwidth of $\vtone$ in $\tenv$ yields $\vw$. - \item $\vt$ is the bitvector type of width $\vw$ and empty list of bitfields, that is, \\ $\TBits(\vw, \emptylist)$. - \end{itemize} - - \item All of the following apply (\textsc{plus\_minus\_bits\_bits}): - \begin{itemize} - \item $\op$ is $\PLUS$ or $\MINUS$; - \item obtaining the \structure\ of $\vtone$ in $\tenv$ is a bitvector of width $\veone$, that is,\\ $\TBits(\veone, \Ignore)$; - \item $\vttwo$ does not \typesatisfy\ the unconstrained integer type in $\tenv$ - \item obtaining the \structure\ of $\vttwo$ in $\tenv$ is $\vttwostruct$\ProseOrTypeError; - \item determining whether $\vttwostruct$ has a bitvector type yields $\True$\ProseOrTypeError; - \item $\vttwostruct$ is a bitvector of width $\vwtwo$, that is, $\TBits(\vwtwo, \Ignore)$; - \item determining whether $\vwone$ and $\vwtwo$ are equal bitwidths yields $\vb$; - \item $\vb$ is $\True$\ProseOrTypeError; - \item $\vt$ is the bitvector type of width $\vwone$ and empty list of bitfields, that is, \\ $\TBits(\vwone, \emptylist)$. - \end{itemize} - - \item All of the following apply (\textsc{eq\_neq\_error}): - \begin{itemize} - \item $\op$ is either $\EQOP$ or $\NEQ$; - \item the \underlyingtype\ of $\vtone$ in $\tenv$ is $\vtoneanon$\ProseOrTypeError; - \item the \underlyingtype\ of $\vttwo$ in $\tenv$ is $\vttwoanon$\ProseOrTypeError; - \item the AST labels of $\vtoneanon$ and $\vttwoanon$ are different or one of them is not in - $\{\TInt, \TReal, \TBool, \TBits, \TEnum\}$; - \item the result is a type error indicating that the types of $\vtone$ and $\vttwo$ are inappropriate for $\op$. - \end{itemize} - - \item All of the following apply (\textsc{eq\_neq\_bits}): - \begin{itemize} - \item $\op$ is either $\EQOP$ or $\NEQ$; - \item the \underlyingtype\ of $\vtone$ in $\tenv$ is $\vtoneanon$\ProseOrTypeError; - \item $\vtoneanon$ is a bitvector type; - \item the \underlyingtype\ of $\vttwo$ in $\tenv$ is $\vttwoanon$\ProseOrTypeError; - \item $\vttwoanon$ is a bitvector type; - \item checking whether the bitwidth of $\vtoneanon$ and $\vttwoanon$ is the same yields $\True$\ProseOrTypeError; - \item $\vt$ is $\TBool$. - \end{itemize} - - \item All of the following apply (\textsc{eq\_neq\_bool}): - \begin{itemize} - \item $\op$ is either $\EQOP$ or $\NEQ$; - \item the \underlyingtype\ of $\vtone$ in $\tenv$ is $\TBool$\ProseOrTypeError; - \item the \underlyingtype\ of $\vttwo$ in $\tenv$ is $\TBool$\ProseOrTypeError; - \item checking whether $\vtoneanon$ \typesatisfies\ $\TBool$ yields $\True$\ProseOrTypeError; - \item checking whether $\vttwoanon$ \typesatisfies\ $\TBool$ yields $\True$\ProseOrTypeError; - \item $\vt$ is $\TBool$. - \end{itemize} - - \item All of the following apply (\textsc{eq\_neq\_real}): - \begin{itemize} - \item $\op$ is either $\EQOP$ or $\NEQ$; - \item the \underlyingtype\ of $\vtone$ in $\tenv$ is $\TReal$\ProseOrTypeError; - \item the \underlyingtype\ of $\vttwo$ in $\tenv$ is $\TReal$\ProseOrTypeError; - \item checking whether $\vtoneanon$ \typesatisfies\ $\TBool$ yields $\True$\ProseOrTypeError; - \item checking whether $\vttwoanon$ \typesatisfies\ $\TBool$ yields $\True$\ProseOrTypeError; - \item $\vt$ is $\TBool$. - \end{itemize} - - \item All of the following apply (\textsc{eq\_neq\_string}): - \begin{itemize} - \item $\op$ is either $\EQOP$ or $\NEQ$; - \item the \underlyingtype\ of $\vtone$ in $\tenv$ is $\TString$\ProseOrTypeError; - \item the \underlyingtype\ of $\vttwo$ in $\tenv$ is $\TString$\ProseOrTypeError; - \item checking whether $\vtoneanon$ \typesatisfies\ $\TBool$ yields $\True$\ProseOrTypeError; - \item checking whether $\vttwoanon$ \typesatisfies\ $\TBool$ yields $\True$\ProseOrTypeError; - \item $\vt$ is $\TBool$. - \end{itemize} - - \item All of the following apply (\textsc{eq\_neq\_enum}): - \begin{itemize} - \item $\op$ is either $\EQOP$ or $\NEQ$; - \item the \underlyingtype\ of $\vtone$ in $\tenv$ is $\TEnum(\vlione)$\ProseOrTypeError; - \item the \underlyingtype\ of $\vttwo$ in $\tenv$ is $\TEnum(\vlitwo)$\ProseOrTypeError; - \item checking whether $\vlione$ is equal to $\vlitwo$ yields $\True$\ProseOrTypeError; - \item $\vt$ is $\TBool$. - \end{itemize} - - \item All of the following apply (\textsc{relational}): - \begin{itemize} - \item $\op$ is one of $\LT$, $\LEQ$, $\GT$, and $\GEQ$; - \item determining whether both $\vtone$ and $\vttwo$ \typesatisfy\ the unconstrained integer type in $\tenv$ - or both $\vtone$ and $\vttwo$ \typesatisfy\ the \texttt{real} type in $\tenv$ yields $\True$\ProseOrTypeError; - \item $\vt$ is $\TBool$. - \end{itemize} - - \item All of the following apply (\textsc{arith\_error}): - \begin{itemize} - \item obtaining the \structure\ of $\vtone$ in $\tenv$ yields $\vtonestruct$\ProseOrTypeError; - \item obtaining the \structure\ of $\vttwo$ in $\tenv$ yields $\vttwostruct$\ProseOrTypeError; - \item the operator and the AST labels of $\vtonestruct$ and $\vttwostruct$ do not match any of the rows in the following table: - - \begin{center} - \begin{tabular}{lll} - \op & $\astlabel(\vtonestruct)$ & $\astlabel(\vttwostruct)$\\ - \hline - \MUL & \TInt & \TInt\\ - \DIV & \TInt & \TInt\\ - \DIVRM & \TInt & \TInt\\ - \MOD & \TInt & \TInt\\ - \SHL & \TInt & \TInt\\ - \SHR & \TInt & \TInt\\ - \POW & \TInt & \TInt\\ - \PLUS & \TInt & \TInt\\ - \MINUS & \TInt & \TInt\\ - \PLUS & \TReal & \TReal\\ - \MINUS & \TReal & \TReal\\ - \MUL & \TReal & \TReal\\ - \RDIV & \TReal & \TReal\\ - \POW & \TReal & \TInt\\ - \end{tabular} - \end{center} - \item the result is a type error indicating that the types of $\vtone$ and $\vttwo$ are inappropriate for $\op$. - \end{itemize} - - \item All of the following apply (\textsc{arith\_t\_int\_unconstrained1}, \\ - \textsc{arith\_t\_int\_unconstrained2}): - \begin{itemize} - \item $\op$ is one of $\{\MUL, \DIV, \DIVRM, \MOD, \SHL, \SHR, \POW, \PLUS, \MINUS\}$; - \item the \wellconstrainedstructure\ of $\vtone$ or $\vttwo$ in $\tenv$ is that of the unconstrained integer type; - \item $\vt$ is the unconstrained integer type; - \end{itemize} - - \item All of the following apply (\textsc{arith\_t\_int\_wellconstrained}): - \begin{itemize} - \item $\op$ is one of $\{\MUL, \POW, \PLUS, \MINUS, \DIVRM, \DIV, \MOD, \SHL, \SHR\}$; - \item the \wellconstrainedstructure\ of $\vtone$ in $\tenv$ is that of a well-constrained integer type with - constraints $\vcsone$; - \item the \wellconstrainedstructure\ of $\vttwo$ in $\tenv$ is that of a well-constrained integer type with - constraints $\vcstwo$; - \item applying $\annotateconstraintbinop$ to $\op$, $\vcsone$, and $\vcstwo$ in $\tenv$ yields $\vcs$; - \item $\vt$ is the integer type with constraints $\vcs$; - \end{itemize} - - \item All of the following apply (\textsc{plus\_minus\_mul\_real}): - \begin{itemize} - \item $\op$ is one of $\{\PLUS, \MINUS, \MUL\}$; - \item obtaining the \structure\ of $\vtone$ in $\tenv$ yields $\TReal$; - \item obtaining the \structure\ of $\vttwo$ in $\tenv$ yields $\TReal$; - \item $\vt$ is $\TReal$. - \end{itemize} - - \item All of the following apply (\textsc{pow\_real\_int}): - \begin{itemize} - \item $\op$ is one of $\{\PLUS, \MINUS, \MUL\}$; - \item obtaining the \structure\ of $\vtone$ in $\tenv$ yields $\TReal$; - \item obtaining the \structure\ of $\vttwo$ in $\tenv$ yields an integer type; - \item $\vt$ is $\TReal$. - \end{itemize} - - \item All of the following apply (\textsc{rdiv}): - \begin{itemize} - \item $\op$ is one of $\{\RDIV\}$; - \item determining whether $\vtone$ \typesatisfies\ $\TReal$ yields $\True$\ProseOrTypeError; - \item determining whether $\vttwo$ \typesatisfies\ $\TReal$ yields $\True$\ProseOrTypeError; - \item $\vt$ is $\TReal$. - \end{itemize} -\end{itemize} - -\isempty{\subsection{Example}} - -\CodeSubsection{\CheckBinopBegin}{\CheckBinopEnd}{../Typing.ml} - -\subsection{Formally} -\begin{mathpar} -\inferrule[boolean]{ - \op \in \{\BAND, \BOR, \IMPL, \EQOP\}\\ - \checktypesat(\tenv, \vt1, \TBool) \typearrow \True \OrTypeError\\\\ - \checktypesat(\tenv, \vttwo, \TBool) \typearrow \True \OrTypeError -}{ - \CheckBinop(\tenv, \op, \vtone, \vttwo) \typearrow \overname{\TBool}{\vt} -} -\end{mathpar} - -\begin{mathpar} -\inferrule[bits\_bool]{ - \op \in \{\AND, \OR, \XOR\}\\ - \checkbitsequalwidth(\tenv, \vtone, \vttwo) \typearrow \True \OrTypeError\\\\ - \getbitvectorwidth(\tenv, \vtone) \typearrow \vw -}{ - \CheckBinop(\tenv, \op, \vtone, \vttwo) \typearrow \overname{\TBits(\vw, \emptylist)}{\vt} -} -\end{mathpar} - -\begin{mathpar} -\inferrule[plus\_minus\_error]{ - \op \in \{\PLUS, \MINUS\}\\ - \tstruct(\tenv, \vtone) \typearrow \vtonestruct \OrTypeError\\\\ - \astlabel(\vtonestruct) \not\in \{\TBits,\TInt\}\\ -}{ - \CheckBinop(\tenv, \op, \vtone, \vttwo) \typearrow \TypeErrorVal{\InvalidOperandTypesForBinop} -} -\and -\inferrule[plus\_minus\_bits\_int]{ - \op \in \{\PLUS, \MINUS\}\\ - \tstruct(\tenv, \vtone) \typearrow \vtonestruct \OrTypeError\\\\ - \astlabel(\vtonestruct) = \TBits\\ - \typesat(\tenv, \vttwo, \unconstrainedinteger) \typearrow \True\\ - \getbitvectorwidth(\tenv, \vtone) \typearrow \vw\\ -}{ - \CheckBinop(\tenv, \op, \vtone, \vttwo) \typearrow \overname{\TBits(\vw, \emptylist)}{\vt} -} -\and -\inferrule[plus\_minus\_bits\_bits]{ - \op \in \{\PLUS, \MINUS\}\\ - \tstruct(\tenv, \vtone) \typearrow \TBits(\vwone, \Ignore) \\ - \typesat(\tenv, \vttwo, \unconstrainedinteger) \typearrow \False\\ - \tstruct(\tenv, \vttwo) \typearrow \vttwostruct \OrTypeError\\\\ - \checktrans{\astlabel(\vttwostruct)=\TBits}{\ExpectedBitvectorType} \checktransarrow \True \OrTypeError\\\\ - \vttwostruct \eqname \TBits(\vwtwo, \Ignore)\\ - \bitwidthequal(\tenv, \vwone, \vwtwo) \typearrow \vb\\ - \checktrans{\vb}{DifferentBitwidths} \checktransarrow \True \OrTypeError -}{ - \CheckBinop(\tenv, \op, \vtone, \vttwo) \typearrow \overname{\TBits(\vwone, \emptylist)}{\vt} -} -\end{mathpar} - -\begin{mathpar} -\inferrule[eq\_neq\_error] -{ - \op \in \{\EQOP, \NEQ\}\\ - \makeanonymous(\tenv, \vtone) \typearrow \vtoneanon \OrTypeError\\\\ - \makeanonymous(\tenv, \vttwo) \typearrow \vttwoanon \OrTypeError\\\\ - { - \left(\begin{array}{ll} - \astlabel(\vtoneanon) \neq \astlabel(\vttwoanon) & \lor \\ - \astlabel(\vtoneanon) \not\in \{\TInt, \TReal, \TBool, \TBits, \TEnum\} & - \end{array}\right) - } -}{ - \CheckBinop(\tenv, \op, \vtone, \vttwo) \typearrow \TypeErrorVal{\InvalidOperandTypesForBinop} -} -\and -\inferrule[eq\_neq\_bits]{ - \op \in \{\EQOP, \NEQ\}\\ - \makeanonymous(\tenv, \vtone) \typearrow \vtoneanon \OrTypeError\\\\ - \makeanonymous(\tenv, \vttwo) \typearrow \vttwoanon \OrTypeError\\\\ - \astlabel(\vtoneanon) = \TBits\\ - \astlabel(\vttwoanon) = \TBits\\ - \checkbitsequalwidth(\tenv, \vtoneanon, \vttwoanon) \typearrow \True \OrTypeError -}{ - \CheckBinop(\tenv, \op, \vtone, \vttwo) \typearrow \overname{\TBool}{\vt} -} -\and -\inferrule[eq\_neq\_bool]{ - \op \in \{\EQOP, \NEQ\}\\ - \makeanonymous(\tenv, \vtone) \typearrow \vtoneanon \OrTypeError\\\\ - \makeanonymous(\tenv, \vttwo) \typearrow \vttwoanon \OrTypeError\\\\ - \checktypesat(\tenv, \vtoneanon, \TBool) \typearrow \True \OrTypeError\\\\ - \checktypesat(\tenv, \vttwoanon, \TBool) \typearrow \True \OrTypeError -}{ - \CheckBinop(\tenv, \op, \vtone, \vttwo) \typearrow \overname{\TBool}{\vt} -} -\and -\inferrule[eq\_neq\_real]{ - \op \in \{\EQOP, \NEQ\}\\ - \makeanonymous(\tenv, \vtone) \typearrow \vtoneanon \OrTypeError\\\\ - \makeanonymous(\tenv, \vttwo) \typearrow \vttwoanon \OrTypeError\\\\ - \checktypesat(\tenv, \vtoneanon, \TReal) \typearrow \True \OrTypeError\\\\ - \checktypesat(\tenv, \vttwoanon, \TReal) \typearrow \True \OrTypeError -}{ - \CheckBinop(\tenv, \op, \vtone, \vttwo) \typearrow \overname{\TBool}{\vt} -} -\and -\inferrule[eq\_neq\_string]{ - \op \in \{\EQOP, \NEQ\}\\ - \makeanonymous(\tenv, \vtone) \typearrow \vtoneanon \OrTypeError\\\\ - \makeanonymous(\tenv, \vttwo) \typearrow \vttwoanon \OrTypeError\\\\ - \checktypesat(\tenv, \vtoneanon, \TString) \typearrow \True \OrTypeError\\\\ - \checktypesat(\tenv, \vttwoanon, \TString) \typearrow \True \OrTypeError -}{ - \CheckBinop(\tenv, \op, \vtone, \vttwo) \typearrow \overname{\TBool}{\vt} -} -\and -\inferrule[eq\_neq\_enum]{ - \op \in \{\EQOP, \NEQ\}\\ - \makeanonymous(\tenv, \vtone) \typearrow \TEnum(\vlione)\\ - \makeanonymous(\tenv, \vttwo) \typearrow \TEnum(\vlitwo)\\ - \checktrans{\vlione = \vlitwo}{DifferentEnumLabels} \checktransarrow \True \OrTypeError -}{ - \CheckBinop(\tenv, \op, \vtone, \vttwo) \typearrow \overname{\TBool}{\vt} -} -\end{mathpar} - -\begin{mathpar} -\inferrule[relational]{ - \op \in \{\LT, \LEQ, \GT, \GEQ\}\\ - \typesat(\tenv, \vtone, \unconstrainedinteger) \typearrow \vbone \OrTypeError\\\\ - \typesat(\tenv, \vttwo, \unconstrainedinteger) \typearrow \vbtwo \OrTypeError\\\\ - \typesat(\tenv, \vtone, \TReal) \typearrow \vbthree \OrTypeError\\\\ - \typesat(\tenv, \vttwo, \TReal) \typearrow \vbfour \OrTypeError\\\\ - \checktrans{\vbone \land \vbtwo \lor \vbthree \land \vbfour}{\InvalidOperandTypesForBinop} \checktransarrow \True \OrTypeError -}{ - \CheckBinop(\tenv, \op, \vtone, \vttwo) \typearrow \overname{\TBool}{\vt} -} -\end{mathpar} - -\begin{mathpar} -\inferrule[arith\_error]{ - \tstruct(\tenv, \vtone) \typearrow \vtonestruct \OrTypeError\\\\ - \tstruct(\tenv, \vttwo) \typearrow \vttwostruct \OrTypeError\\\\ - (\op, \astlabel(\vtonestruct), \astlabel(\vttwostruct)) \not\in - { - \left\{ - \begin{array}{lclcl} - (\MUL &,& \TInt &,& \TInt)\\ - (\DIV &,& \TInt &,& \TInt)\\ - (\DIVRM &,& \TInt &,& \TInt)\\ - (\MOD &,& \TInt &,& \TInt)\\ - (\SHL &,& \TInt &,& \TInt)\\ - (\SHR &,& \TInt &,& \TInt)\\ - (\POW &,& \TInt &,& \TInt)\\ - (\PLUS &,& \TInt &,& \TInt)\\ - (\MINUS &,& \TInt &,& \TInt)\\ - (\PLUS &,& \TReal &,& \TReal)\\ - (\MINUS &,& \TReal &,& \TReal)\\ - (\MUL &,& \TReal &,& \TReal)\\ - (\RDIV &,& \TReal &,& \TReal)\\ - (\POW &,& \TReal &,& \TInt)\\ - \end{array} - \right\} - } -}{ - \CheckBinop(\tenv, \op, \vtone, \vttwo) \typearrow \TypeErrorVal{\InvalidOperandTypesForBinop} -} -\end{mathpar} - -The following two rules are not mutually exclusive, but both yield the same result when they are both active. -\begin{mathpar} -\inferrule[arith\_t\_int\_unconstrained1]{ - \op \in \{\MUL, \DIV, \DIVRM, \MOD, \SHL, \SHR, \POW, \PLUS, \MINUS\}\\ - \getwellconstrainedstructure(\tenv, \vtone) \typearrow \unconstrainedinteger\\ - \getwellconstrainedstructure(\tenv, \vttwo) \typearrow \TInt(\Ignore)\\ -}{ - \CheckBinop(\tenv, \op, \vtone, \vttwo) \typearrow \unconstrainedinteger -} -\and -\inferrule[arith\_t\_int\_unconstrained2]{ - \op \in \{\MUL, \DIV, \DIVRM, \MOD, \SHL, \SHR, \POW, \PLUS, \MINUS\}\\ - \getwellconstrainedstructure(\tenv, \vtone) \typearrow \TInt(\Ignore)\\ - \getwellconstrainedstructure(\tenv, \vttwo) \typearrow \unconstrainedinteger\\ -}{ - \CheckBinop(\tenv, \op, \vtone, \vttwo) \typearrow \unconstrainedinteger -} -\end{mathpar} - -\begin{mathpar} -\inferrule[arith\_t\_int\_wellconstrained]{ - \op \in \{\MUL, \POW, \PLUS, \MINUS, \DIVRM, \DIV, \MOD, \SHL, \SHR\}\\ - \getwellconstrainedstructure(\tenv, \vtone) \typearrow \TInt(\wellconstrained(\vcsone))\\ - \getwellconstrainedstructure(\tenv, \vttwo) \typearrow \TInt(\wellconstrained(\vcstwo))\\ - \annotateconstraintbinop(\tenv, \op, \vcsone, \vcstwo) \typearrow \vcs -}{ - \CheckBinop(\tenv, \op, \vtone, \vttwo) \typearrow \TInt(\vcs) -} -\end{mathpar} - -\begin{mathpar} -\inferrule[plus\_minus\_mul\_real]{ - \op \in \{\PLUS, \MINUS, \MUL\}\\ - \tstruct(\tenv, \vtone) \typearrow \TReal\\ - \tstruct(\tenv, \vttwo) \typearrow \TReal -}{ - \CheckBinop(\tenv, \op, \vtone, \vttwo) \typearrow \TReal -} -\end{mathpar} - -\begin{mathpar} -\inferrule[pow\_real\_int]{ - \tstruct(\tenv, \vtone) \typearrow \TReal\\ - \astlabel(\tstruct(\tenv, \vttwo)) \typearrow \TInt -}{ - \CheckBinop(\tenv, \POW, \vtone, \vttwo) \typearrow \TReal -} -\end{mathpar} - -\begin{mathpar} -\inferrule[rdiv]{ - \checktypesat(\tenv, \vtone, \TReal) \typearrow \True \OrTypeError\\\\ - \checktypesat(\tenv, \vttwo, \TReal) \typearrow \True \OrTypeError\\ -}{ - \CheckBinop(\tenv, \RDIV, \vtone, \vttwo) \typearrow \TReal -} -\end{mathpar} - -\isempty{\subsection{Comments}} -\lrmcomment{ - This is related to \identr{BKNT}, \identr{ZYWY}, \identr{BZKW}, - \identr{KFYS}, \identr{KXMR}, \identr{SQXN}, \identr{MRHT}, \identr{JGWF}, - \identr{TTGQ}, \identi{YHML}, \identi{YHRP}, \identi{VMZF}, \identi{YXSY}, - \identi{LGHJ}, \identi{RXLG}. -} - -\section{TypingRule.FindNamedLCA \label{sec:TypingRule.FindNamedLCA}} -\hypertarget{def-namedlowestcommonancestor}{} -The function -\[ - \namedlca(\overname{\staticenvs}{\tenv} \aslsep \overname{\ty}{\vt} \aslsep \overname{\ty}{\vs}) - \aslto \overname{\ty}{\tty} \cup \overname{\TTypeError}{\TypeErrorConfig} -\] -returns the lowest common named super type --- $\tty$ --- of the types $\vt$ and $\vs$ in $\tenv$. - -\newcommand\supers[0]{\texttt{supers}} -The helper function -\[ - \supers(\overname{\staticenvs}{\tenv} \aslsep \overname{\ty}{\vt}) - \aslto \pow{\ty} -\] -returns the set of \emph{named supertypes} given via the $\subtypes$ function of the global environment: -\[ - \supers(\tenv, \vt) \triangleq - \begin{cases} - \{\vt\} \cup \supers(\vs) & \text{ if }G^\tenv.\subtypes(\vt) = \vs\\ - \{\vt\} & \text{ otherwise } (\text{that is, }G^\tenv.\subtypes(\vt) = \bot)\\ - \end{cases} -\] - -\subsection{Prose} -One of the following holds: -\begin{itemize} - \item $\vtsupers$ is in the set of named supertypes of $\vt$; - \item All of the following hold (\textsc{found}): - \begin{itemize} - \item $\vs$ is in $\vtsupers$; - \item $\tty$ is $\vs$; - \end{itemize} - - \item All of the following hold (\textsc{super}): - \begin{itemize} - \item $\vs$ is not in $\vtsupers$; - \item $\vs$ has a named super type in $\tenv$ --- $\vsp$; - \item $\tty$ is the lowest common named supertype of $\vt$ and $\vsp$ in $\tenv$. - \end{itemize} - - \item All of the following hold (\textsc{none}): - \begin{itemize} - \item $\vs$ is not in $\vtsupers$; - \item $\vs$ has no named super type in $\tenv$; - \item $\tty$ is $\None$. - \end{itemize} -\end{itemize} - -\subsection{Formally} -\begin{mathpar} -\inferrule[found]{ - \supers(\tenv, \vt) \typearrow \vtsupers\\ - \vs \in \vtsupers -}{ - \namedlca(\tenv, \vt, \vs) \typearrow \vs -} -\and -\inferrule[super]{ - \supers(\tenv, \vt) \typearrow \vtsupers\\ - \vs \not\in \vtsupers\\ - G^\tenv.\subtypes(\vs) = \vsp\\ - \namedlca(\tenv, \vt, \vsp) \typearrow \tty -}{ - \namedlca(\tenv, \vt, \vs) \typearrow \tty -} -\and -\inferrule[none]{ - \supers(\tenv, \vt) \typearrow \vtsupers\\ - \vs \not\in \vtsupers\\ - G^\tenv.\subtypes(\vs) = \None -}{ - \namedlca(\tenv, \vt, \vs) \typearrow \None -} -\end{mathpar} - -\section{TypingRule.AnnotateConstraintBinop \label{sec:TypingRule.AnnotateConstraintBinop}} -\hypertarget{def-annotateconstraintbinop}{} -The function -\[ -\begin{array}{r} -\annotateconstraintbinop( - \overname{\staticenvs}{\tenv} \aslsep - \overname{\binop}{\op} \aslsep - \overname{\intconstraint^*}{\csone} \aslsep - \overname{\intconstraint^*}{\cstwo} -) \aslto \\ -\overname{\intconstraints}{\vics} -\cup \overname{\TTypeError}{\TypeErrorConfig} -\end{array} -\] -annotates the application of the binary operation $\op$ to the lists of integer constraints -$\csone$ and $\cstwo$, yielding an integer constraints element $\vics$. -\ProseOtherwiseTypeError\ - -The operator $\op$ is assumed to be only one of the operators in the following set: -$\{\SHL, \SHR, \POW, \MOD, \DIVRM, \MINUS, \MUL, \PLUS, \DIV\}$. - -Annotating the constraints involves applying symbolic reasoning and in particular filtering out values that -will definitely result in a dynamic error. - -\subsection{Prose} -All of the following apply: -\begin{itemize} - \item applying $\binopfilterrhs$ to $\op$ $\cstwo$ in $\tenv$, to filter out constraints that will definitely fail dynamically, yields $\cstwof$; - \item applying $\binopisexploding$ to $\op$ yields $\vbexploding$; - \item applying $\explodeintervals$ to $\csone$ in $\tenv$ yields $\csonee$; - \item applying $\explodeintervals$ to $\cstwo$ in $\tenv$ yields $\cstwo$; - \item define $(\csonearg, \cstwoarg)$ as $(\csonee, \cstwoe)$ if $\vbexploding$ is $\True$ and $(\csone, \cstwof)$, otherwise; - \item applying $\constraintbinop$ yo $\op$, $\csonearg$, and $\cstwoarg$ yields $\csvanilla$; - \item applying $\reduceconstraints$ to $\csvanilla$ in $\tenv$ yields $\cs$; - \item one of the following applies: - \begin{itemize} - \item All of the following apply (\textsc{div\_wellconstrained}): - \begin{itemize} - \item $\op$ is $\DIV$ and $\cs$ is a $\wellconstrained$ constraint; - \item view $\cs$ as $\wellconstrained(\cslist)$; - \item applying $\refineconstraints$ to $\filterreduceconstraintdiv$ and \\ - $\cslist$ yields $\cslistfiltered$; - \item applying $\reduceconstants$ to $\cslistfiltered$ yields $\vics$. - \end{itemize} - - \item All of the following apply (\textsc{else}): - \begin{itemize} - \item either $\op$ is not $\DIV$ or $\cs$ is not a $\wellconstrained$ constraint; - \item $\vics$ is $\cs$. - \end{itemize} - \end{itemize} -\end{itemize} - -\CodeSubsection{\AnnotateConstraintBinopBegin}{\AnnotateConstraintBinopEnd}{../Typing.ml} - -\subsection{Formally} -\begin{mathpar} -\inferrule[div\_wellconstrained]{ - \binopfilterrhs(\tenv, \op, \cstwo) \typearrow \cstwof\\ - \binopisexploding(\op) \typearrow \vbexploding\\ - \explodeintervals(\tenv, \csone) \typearrow \csonee\\ - \explodeintervals(\tenv, \cstwof) \typearrow \cstwoe\\ - (\csonearg, \cstwoarg) \eqdef \choice{\vbexploding}{(\csonee, \cstwoe)}{(\csone, \cstwof)}\\ - \constraintbinop(\op, \csonearg, \cstwoarg) \typearrow \csvanilla\\ - \reduceconstraints(\tenv, \csvanilla) \typearrow \cs\\\\ - \commonprefixline\\\\ - \op = \DIV \land \astlabel(\cs) = \wellconstrained\\ - \cs \eqname \wellconstrained(\cslist)\\ - { - \begin{array}{r} - \refineconstraints(\filterreduceconstraintdiv, \cslist) \typearrow \\ - \cslistfiltered - \end{array} - }\\ - \reduceconstraints(\cslistfiltered) \typearrow \vics -}{ - \annotateconstraintbinop(\tenv, \op, \csone, \cstwo) \typearrow \vics -} -\end{mathpar} - -\begin{mathpar} -\inferrule[else]{ - \binopfilterrhs(\tenv, \op, \cstwo) \typearrow \cstwof\\ - \binopisexploding(\op) \typearrow \vbexploding\\ - \explodeintervals(\tenv, \csone) \typearrow \csonee\\ - \explodeintervals(\tenv, \cstwof) \typearrow \cstwoe\\ - (\csonearg, \cstwoarg) \eqdef \choice{\vbexploding}{(\csonee, \cstwoe)}{(\csone, \cstwof)}\\ - \constraintbinop(\op, \csonearg, \cstwoarg) \typearrow \csvanilla\\ - \reduceconstraints(\tenv, \csvanilla) \typearrow \cs\\\\ - \commonprefixline\\\\ - \neg(\op = \DIV \land \astlabel(\cs) = \wellconstrained) -}{ - \annotateconstraintbinop(\tenv, \op, \csone, \cstwo) \typearrow \overname{\cs}{\vics} -} -\end{mathpar} - -\section{TypingRule.BinopFilterRhs \label{sec:TypingRule.BinopFilterRhs}} -\hypertarget{def-binopfilterrhs}{} -The function -\[ -\binopfilterrhs(\overname{\staticenvs}{\tenv} \aslsep \overname{\binop}{\op} \aslsep \overname{\intconstraint^*}{\cs}) -\aslto \overname{\intconstraint^*}{\newcs} -\] -\subsection{Prose} -One of the following applies: -\begin{itemize} - \item All of the following apply (\textsc{greater\_or\_equal}): - \begin{itemize} - \item $\op$ is one of $\SHL$, $\SHR$, and $\POW$; - \item define $\vf$ as the specialization of $\refineconstraintbysign$ for the predicate - $\lambda x.\ x \geq 0$, which is $\True$ if and only if the tested number if greater or equal to $0$; - \item refining the list of constraints $\cs$ with $\vp$ via $\refineconstraints$ yields $\newcs$; - \item checking whether $\newcs$ is empty yields $\True$\ProseTerminateAs{\BinaryOperationFailsAllConstraints}. - \end{itemize} - - \item All of the following apply (\textsc{greater\_than}): - \begin{itemize} - \item $\op$ is one of $\MOD$, $\DIV$, and $\DIVRM$; - \item define $\vf$ as the specialization of $\refineconstraintbysign$ for the predicate - $\lambda x.\ x > 0$, which is $\True$ if and only if the tested number if greater than $0$; - \item refining the list of constraints $\cs$ with $\vp$ via $\refineconstraints$ yields $\newcs$; - \item checking whether $\newcs$ is empty yields $\True$\ProseTerminateAs{\BinaryOperationFailsAllConstraints}. - \end{itemize} - - \item All of the following apply (\textsc{no\_filtering}): - \begin{itemize} - \item $\op$ is one of $\MINUS$, $\MUL$, and $\PLUS$; - \item $\newcs$ is $\cs$. - \end{itemize} -\end{itemize} - -\subsection{Formally} -\begin{mathpar} -\inferrule[greater\_or\_equal]{ - \op \in \{\SHL, \SHR, \POW\}\\\\ - \vf \eqdef \refineconstraintbysign(\tenv, \lambda x.\ x \geq 0, \vc)\\ - \refineconstraints(\cs, \vp) \typearrow \newcs\\ - \checktrans{\newcs \neq \emptylist}{\BinaryOperationFailsAllConstraints} \typearrow \True\OrTypeError -}{ - \binopfilterrhs(\tenv, \op, \cs) \typearrow \newcs -} -\end{mathpar} - -\begin{mathpar} -\inferrule[greater\_than]{ - \op \in \{\MOD, \DIV, \DIVRM\}\\\\ - \vf \eqdef \refineconstraintbysign(\tenv, \lambda x.\ x > 0, \vc)\\ - \refineconstraints(\cs, \vp) \typearrow \newcs\\ - \checktrans{\newcs \neq \emptylist}{\BinaryOperationFailsAllConstraints} \typearrow \True\OrTypeError -}{ - \binopfilterrhs(\tenv, \op, \cs) \typearrow \newcs -} -\end{mathpar} - -\begin{mathpar} -\inferrule[no\_filter]{ - \op \in \{\MINUS, \MUL, \PLUS\} -}{ - \binopfilterrhs(\tenv, \op, \cs) \typearrow \overname{\cs}{\newcs} -} -\end{mathpar} - -\section{TypingRule.RefineConstraintBySign \label{sec:TypingRule.RefineConstraintBySign}} -\hypertarget{def-refineconstraintbysign}{} -The function -\[ -\refineconstraintbysign(\overname{\staticenvs}{\tenv} \aslsep \overname{\Z\rightarrow \Bool}{\vp} \aslsep \overname{\intconstraint}{\vc}) -\aslto \overname{\langle\intconstraint\rangle}{\vcopt} -\] -takes a predicate $\vp$ that returns $\True$ based on the sign of its input. -The function conservatively refines the constraint $\vc$ in $\tenv$ by applying symbolic reasoning to yield a new constraint -(inside an optional) -that represents the values that satisfy the $\vc$ and for which $\vp$ holds. -In this context, conservatively means that the new constraint may represent a superset of the values that a more precise -reasoning may yield. -If the set of those values is empty the result is $\None$. - -\subsection{Prose} -One of the following applies: -\begin{itemize} - \item All of the following apply (\textsc{exact\_reduces\_to\_z}): - \begin{itemize} - \item $\vc$ is an exact constraint for the expression $\ve$, that is, $\ConstraintExact(\ve)$; - \item applying $\reducetozopt$ to $\ve$ in $\tenv$, in order to symbolically simplify $\ve$ to an integer, - yields $\langle\vz\rangle$; - \item $\vcopt$ is $\langle\vc\rangle$ if $\vp$ holds for $\vz$ and $\None$ otherwise. - \end{itemize} - - \item All of the following apply (\textsc{exact\_does\_not\_reduce\_to\_z}): - \begin{itemize} - \item $\vc$ is an exact constraint for the expression $\ve$, that is, $\ConstraintExact(\ve)$; - \item applying $\reducetozopt$ to $\ve$ in $\tenv$, in order to symbolically simplify $\ve$ to an integer, - yields $\None$; - \item $\vcopt$ is $\langle\vc\rangle$. - \end{itemize} - - \item All of the following apply (\textsc{range\_both\_reduce\_to\_z}): - \begin{itemize} - \item $\vc$ is a range constraint for the expressions $\veone$ and $\vetwo$, that is, \\ - $\ConstraintRange(\veone, \vetwo)$; - \item applying $\reducetozopt$ to $\veone$ in $\tenv$, in order to symbolically simplify $\veone$ to an integer, - yields $\langle\vzone\rangle$; - \item applying $\reducetozopt$ to $\vetwo$ in $\tenv$, in order to symbolically simplify $\vetwo$ to an integer, - yields $\langle\vztwo\rangle$; - \item One of the following applies (defining $\vcopt$): - \begin{itemize} - \item if $\vp$ is $\True$ for both $\vzone$ and $\vztwo$, define $\vcopt$ as $\langle\vc\rangle$; - \item if $\vp$ is $\False$ for $\vzone$ and $\True$ for $\vztwo$, define $\vcopt$ as the optional range constraint - where the bottom expression is the literal expression for $0$ if $\vp$ holds for $0$ and the literal expression for $1$ otherwise, - and the top expression is $\vetwo$; - \item if $\vp$ is $\True$ for $\vzone$ and $\False$ for $\vztwo$, define $\vcopt$ as the optional range constraint - where the bottom expression is $\veone$ and the top expression is the literal expression for $0$ if $\vp$ holds for $0$ - and the literal expression for $-1$ otherwise; - \item if $\vp$ is $\False$ for both $\vzone$ and $\vztwo$, define $\vcopt$ as $\None$. - \end{itemize} - \end{itemize} - - \item All of the following apply (\textsc{only\_e1\_reduces\_to\_z}): - \begin{itemize} - \item $\vc$ is a range constraint for the expressions $\veone$ and $\vetwo$, that is, \\ - $\ConstraintRange(\veone, \vetwo)$; - \item applying $\reducetozopt$ to $\veone$ in $\tenv$, in order to symbolically simplify $\veone$ to an integer, - yields $\langle\vzone\rangle$; - \item applying $\reducetozopt$ to $\vetwo$ in $\tenv$, in order to symbolically simplify $\vetwo$ to an integer, - yields $\None$; - \item One of the following applies (defining $\vcopt$): - \begin{itemize} - \item if $\vp$ is $\True$ for $\vzone$, define $\vcopt$ as $\langle\vc\rangle$; - \item if $\vp$ is $\False$ for $\vzone$, define $\vcopt$ as the optional range constraint with the bottom expression - as the literal expression for $0$ if $\vp$ holds for $0$ and the literal expression for $1$ otherwise, - and the top expression $\vetwo$. - \end{itemize} - \end{itemize} - - \item All of the following apply (\textsc{only\_e2\_reduces\_to\_z}): - \begin{itemize} - \item $\vc$ is a range constraint for the expressions $\veone$ and $\vetwo$, that is, \\ - $\ConstraintRange(\veone, \vetwo)$; - \item applying $\reducetozopt$ to $\veone$ in $\tenv$, in order to symbolically simplify $\veone$ to an integer, - yields $\None$; - \item applying $\reducetozopt$ to $\vetwo$ in $\tenv$, in order to symbolically simplify $\vetwo$ to an integer, - yields $\langle\vztwo\rangle$; - \item One of the following applies (defining $\vcopt$): - \begin{itemize} - \item if $\vp$ is $\True$ for $\vztwo$, define $\vcopt$ as $\langle\vc\rangle$; - \item if $\vp$ is $\False$ for $\vztwo$, define $\vcopt$ as the optional range constraint with the bottom expression - $\veone$ and the top expression the literal expression for $0$ if $\vp$ holds for $0$ and the literal expression for $-1$ otherwise. - \end{itemize} - \end{itemize} -\end{itemize} - -\subsection{Formally} -\begin{mathpar} -\inferrule[exact\_reduces\_to\_z]{ - \reducetozopt(\tenv, \ve) \typearrow \langle\vz\rangle\\ - \vcopt \eqdef \choice{\vp(\vz)}{\langle\vc\rangle}{\None} -}{ - \refineconstraintbysign(\tenv, \vp, \overname{\ConstraintExact(\ve)}{\vc}) \typearrow \vcopt -} -\end{mathpar} - -\begin{mathpar} -\inferrule[exact\_does\_not\_reduce\_to\_z]{ - \reducetozopt(\tenv, \ve) \typearrow \None -}{ - \refineconstraintbysign(\tenv, \vp, \overname{\ConstraintExact(\ve)}{\vc}) \typearrow \overname{\langle\vc\rangle}{\vcopt} -} -\end{mathpar} - -\begin{mathpar} -\inferrule[range\_both\_reduce\_to\_z]{ - \reducetozopt(\tenv, \veone) \typearrow \langle\vzone\rangle\\ - \reducetozopt(\tenv, \vetwo) \typearrow \langle\vztwo\rangle\\ - { - \begin{array}{c} - \vcopt \eqdef \\ \wrappedline\ \begin{cases} - \langle\vc\rangle& \text{if }\vp(\vzone) \land \vp(\vztwo)\\ - \langle\ConstraintRange(\choice{\vp(0)}{\ELInt{0}}{\ELInt{1}}, \vetwo)\rangle& \text{if }\neg\vp(\vzone) \land \vp(\vztwo)\\ - \langle\ConstraintRange(\veone, \choice{\vp(0)}{\ELInt{0}}{\ELInt{-1}})\rangle& \text{if }\vp(\vzone) \land \neg\vp(\vztwo)\\ - \None& \text{if }\neg\vp(\vzone) \land \neg\vp(\vztwo)\\ - \end{cases} -\end{array} - } -}{ - \refineconstraintbysign(\tenv, \vp, \overname{\ConstraintRange(\veone, \vetwo)}{\vc}) \typearrow \vcopt -} -\end{mathpar} - -\begin{mathpar} -\inferrule[only\_e1\_reduces\_to\_z]{ - \reducetozopt(\tenv, \veone) \typearrow \langle\vzone\rangle\\ - \reducetozopt(\tenv, \vetwo) \typearrow \None\\ - { - \begin{array}{c} - \vcopt \eqdef \\ \wrappedline\ \begin{cases} - \langle\vc\rangle& \text{if }\vp(\vzone)\\ - \langle\ConstraintRange(\choice{\vp(0)}{\ELInt{0}}{\ELInt{1}}, \vetwo)\rangle& \text{else}\\ - \end{cases} -\end{array} - } -}{ - \refineconstraintbysign(\tenv, \vp, \overname{\ConstraintRange(\veone, \vetwo)}{\vc}) \typearrow \vcopt -} -\end{mathpar} - -\begin{mathpar} -\inferrule[only\_e2\_reduces\_to\_z]{ - \reducetozopt(\tenv, \veone) \typearrow \None\\ - \reducetozopt(\tenv, \vetwo) \typearrow \langle\vztwo\rangle\\ - { - \begin{array}{c} - \vcopt \eqdef \\ \wrappedline\ \begin{cases} - \langle\vc\rangle& \text{if }\vp(\vztwo)\\ - \langle\ConstraintRange(\veone, \choice{\vp(0)}{\ELInt{0}}{\ELInt{-1}})\rangle& \text{else}\\ - \end{cases} -\end{array} - } -}{ - \refineconstraintbysign(\tenv, \vp, \overname{\ConstraintRange(\veone, \vetwo)}{\vc}) \typearrow \vcopt -} -\end{mathpar} - -\begin{mathpar} -\inferrule[none\_reduce\_to\_z]{ - \reducetozopt(\tenv, \veone) \typearrow \None\\ - \reducetozopt(\tenv, \vetwo) \typearrow \None -}{ - \refineconstraintbysign(\tenv, \vp, \overname{\ConstraintRange(\veone, \vetwo)}{\vc}) \typearrow \overname{\vc}{\vcopt} -} -\end{mathpar} - -\section{TypingRule.ReduceToZOpt \label{sec:TypingRule.ReduceToZOpt}} -\hypertarget{def-reducetozopt}{} -The function -\[ -\reducetozopt(\overname{\staticenvs}{\tenv} \aslsep \overname{\expr}{\ve}) -\aslto \overname{\langle\Z\rangle}{\vzopt} -\] -returns an integer inside an optional if $\ve$ can be symbolically simplified into an integer in $\tenv$ -and $\None$ otherwise. -The expression $\ve$ is assumed to appear in a constraint for a type that has been successfully annotated, -which means that applying $\normalize$ to it should not yield a type error. - -\subsection{Prose} -One of the following applies: -\begin{itemize} - \item All of the following apply (\textsc{normalizes\_to\_z}): - \begin{itemize} - \item symbolically simplifying $\ve$ in $\tenv$ via $\normalize$ yields a literal expression for the integer $\vz$; - \item define $\vzopt$ as $\langle\vz\rangle$. - \end{itemize} - - \item All of the following apply (\textsc{does\_not\_normalize\_to\_z}): - \begin{itemize} - \item symbolically simplifying $\ve$ in $\tenv$ via $\normalize$ yields an expression that is not an integer literal; - \item define $\vzopt$ as $\None$. - \end{itemize} -\end{itemize} - -\subsection{Formally} -\begin{mathpar} -\inferrule[normalizes\_to\_z]{ - \normalize(\tenv, \ve) \typearrow \ELInt{\vz} -}{ - \reducetozopt(\tenv, \ve) \typearrow \overname{\langle\vz\rangle}{\vzopt} -} -\end{mathpar} - -\begin{mathpar} -\inferrule[does\_not\_normalize\_to\_z]{ - \normalize(\tenv, \ve) \typearrow \vep\\ - \forall \vz\in\Z.\ \vep \neq \ELInt{\vz} -}{ - \reducetozopt(\tenv, \ve) \typearrow \overname{\None}{\vzopt} -} -\end{mathpar} - -\section{TypingRule.RefineConstraints \label{sec:TypingRule.RefineConstraints}} -\hypertarget{def-refineconstraints}{} -The function -\[ -\begin{array}{r} -\refineconstraints(\overname{\staticenvs}{\tenv} \aslsep \overname{\intconstraint\rightarrow\langle\intconstraint\rangle}{\vf} \aslsep \overname{\intconstraint^*}{\cs}) -\aslto \\ -\overname{\intconstraint^*}{\newcs} -\end{array} -\] -refines a list of constraints $\cs$ by applying the refinement function $\vf$ to each constraint and retaining the constraints -that do not refine to $\None$ in $\tenv$. The resulting list of constraints is given in $\newcs$. - -\subsection{Prose} -One of the following applies: -\begin{itemize} - \item All of the following apply (\textsc{empty}): - \begin{itemize} - \item $\cs$ is the empty list; - \item $\newcs$ is the empty list. - \end{itemize} - - \item All of the following apply (\textsc{non\_empty\_none}): - \begin{itemize} - \item $\cs$ is the list with $\vc$ as its \head\ and $\csone$ as its \tail; - \item applying $\vf$ to $\vc$ in $\tenv$ yields $\None$; - \item applying $\refineconstraints$ to $\vf$ and $\csone$ in $\tenv$ yields $\csonep$; - \item $\newcs$ is $\csonep$. - \end{itemize} - - \item All of the following apply (\textsc{non\_empty\_somee}): - \begin{itemize} - \item $\cs$ is the list with $\vc$ as its \head\ and $\csone$ as its \tail; - \item applying $\vf$ to $\vc$ in $\tenv$ yields $\langle\vcp\rangle$; - \item applying $\refineconstraints$ to $\vf$ and $\csone$ in $\tenv$ yields $\csonep$; - \item $\newcs$ is the list with $\vcp$ as its \head\ and $\csonep$ as its \tail. - \end{itemize} -\end{itemize} - -\subsection{Formally} -\begin{mathpar} -\inferrule[empty]{}{ - \refineconstraints(\tenv, \vf, \overname{\emptylist}{\cs}) \typearrow \overname{\emptylist}{\newcs} -} -\end{mathpar} - -\begin{mathpar} -\inferrule[non\_empty\_none]{ - \vf(\tenv, \vc) \typearrow \None\\ - \refineconstraints(\tenv, \vf, \csone) \typearrow \csonep\\ -}{ - \refineconstraints(\tenv, \vf, \overname{[\vc]\concat \csone}{\cs}) \typearrow \overname{\csonep}{\newcs} -} -\end{mathpar} - -\begin{mathpar} -\inferrule[non\_empty\_some]{ - \vf(\tenv, \vc) \typearrow \langle\vcp\rangle\\ - \refineconstraints(\tenv, \vf, \csone) \typearrow \csonep\\ -}{ - \refineconstraints(\tenv, \vf, \overname{[\vc]\concat \csone}{\cs}) \typearrow \overname{[\vcp] \concat \csonep}{\newcs} -} -\end{mathpar} - -\section{TypingRule.FilterReduceConstraintDiv \label{sec:TypingRule.FilterReduceConstraintDiv}} -\hypertarget{def-filterreduceconstraintdiv}{} -The function -\[ -\filterreduceconstraintdiv(\overname{\intconstraint}{\vc}) \aslto \overname{\langle\intconstraint\rangle}{\vcopt} -\] -returns $\None$ if $\vc$ is an exact constraint for a binary expression for dividing two integer literals -where the denominator does not divide the numerator and an optional containing $\vc$. -The result is returned in $\vcopt$. -This is used to conservatively test whether $\vc$ would always fail dynamically. - -\subsection{Prose} -If $\vc$ is an exact constraint for a binary expression for the division operation and two integer literal -expressions for the integers $\vzone$ and $\vztwo$ such that $\vztwo$ does not divide $\vzone$ then -$\vcopt$ is $\None$. Otherwise $\vcopt$ is $\langle\vc\rangle$. - -\subsection{Formally} -\begin{mathpar} -\inferrule[exact\_div\_literals]{ - \vc = \ConstraintExact(\ve)\\ - \getliteraldivopt(\ve) \typearrow \None -}{ - \filterreduceconstraintdiv(\tenv, \vc) \typearrow \overname{\langle\vc\rangle}{\vcopt} -} -\end{mathpar} - -\begin{mathpar} -\inferrule[exact\_not\_div\_literals]{ - \vc = \ConstraintExact(\ve)\\ - \getliteraldivopt(\ve) \typearrow \langle(\vzone, \vztwo)\rangle - \vcopt \eqdef \choice{\frac{\vzone}{\vztwo} \in \Z}{\langle\vc\rangle}{\None} -}{ - \filterreduceconstraintdiv(\tenv, \vc) \typearrow \vcopt -} -\end{mathpar} - -\begin{mathpar} -\inferrule[range]{ - \astlabel(\vc) = \ConstraintRange -}{ - \filterreduceconstraintdiv(\tenv, \vc) \typearrow \overname{\langle\vc\rangle}{\vcopt} -} -\end{mathpar} - -\section{TypingRule.GetLiteralDivOpt \label{sec:TypingRule.GetLiteralDivOpt}} -\hypertarget{def-getliteraldivopt}{} -The function -\[ -\getliteraldivopt(\overname{\expr}{\ve}) \aslto \overname{\langle\Z\cartimes\Z\rangle}{\rangeopt} -\] -matches the expression $\ve$ to a binary operation expression over the division operation and two literal integer expressions. -If $\ve$ matches this pattern the result $\rangeopt$ is an optional containing the pair of integers appearing in the operand -expressions. Otherwise, the result is $\None$. - -\subsection{Prose} -The value $\rangeopt$ is $\langle(\vzone, \vztwo)\rangle$ if $\ve$ is a binary operation expression over the division operation -and two literal integer expressions for the integers $\vzone$ and $\vztwo$ and $\None$ otherwise. - -\subsection{Formally} -\begin{mathpar} -\inferrule{ - \rangeopt \eqdef \choice{\ve = \EBinop(\DIV, \ELInt{\vzone}, \ELInt{\vztwo})}{\langle(\vzone, \vztwo)\rangle}{\None} -}{ - \getliteraldivopt(\ve) \typearrow \rangeopt -} -\end{mathpar} - -\section{TypingRule.ExplodeIntervals \label{sec:TypingRule.ExplodeIntervals}} -\hypertarget{def-explodeintervals}{} -The function -\[ -\explodeintervals(\overname{\staticenvs}{\tenv} \aslsep \overname{\intconstraint^*}{\cs}) -\aslto \overname{\intconstraint^*}{\newcs} -\] -applies $\explodedinterval$ to each constraint of $\cs$ in $\tenv$ and concatenates the resulting -list, yielding the result in $\newcs$. - -\subsection{Prose} -One of the following applies: -\begin{itemize} - \item All of the following apply (\textsc{empty}): - \begin{itemize} - \item $\cs$ is the empty list; - \item $\newcs$ is the empty list. - \end{itemize} - - \item All of the following apply (\textsc{non\_empty}): - \begin{itemize} - \item $\cs$ is the list with $\vc$ as its \head\ and $\csone$ as its \tail; - \item applying $\explodeconstraint$ to $\vc$ in $\tenv$ yields $\vcp$ (a list of constraints); - \item applying $\explodeintervals$ to $\csone$ in $\tenv$ yields $\csonep$; - \item $\newcs$ is the concatenation of $\vcp$ and $\csonep$. - \end{itemize} -\end{itemize} - -\subsection{Formally} -\begin{mathpar} -\inferrule[empty]{}{ - \explodeintervals(\tenv, \overname{\emptylist}{\cs}) \typearrow \overname{\emptylist}{\newcs} -} -\end{mathpar} - -\begin{mathpar} -\inferrule[non\_empty]{ - \explodeconstraint(\tenv, \vc) \typearrow \vcp\\ - \explodeintervals(\tenv, \csone) \typearrow \csonep\\ -}{ - \explodeintervals(\tenv, \overname{[\vc] \concat \csone}{\cs}) \typearrow \overname{\vcp \concat \csonep}{\newcs} -} -\end{mathpar} - -\section{TypingRule.ExplodeConstraint \label{sec:TypingRule.ExplodeConstraint}} -\hypertarget{def-explodeconstraint}{} -The function -\[ -\explodeconstraint(\overname{\staticenvs}{\tenv} \aslsep \overname{\intconstraint}{\vc}) -\aslto \overname{\intconstraint^*}{\vcs} -\] -expands the constraint $\vc$ into the equivalent list of exact constraints if -$\vc$ matches a n ascending range constraint that is not too large in $\tenv$ -and the singleton list for $\vc$ otherwise. - -\subsection{Prose} -One of the following applies: -\begin{itemize} - \item All of the following apply (\textsc{exact}): - \begin{itemize} - \item $\vc$ is an exact constraint; - \item $\vcs$ is the singleton list for $\vc$. - \end{itemize} - - \item All of the following apply (\textsc{range\_reduced}): - \begin{itemize} - \item $\vc$ is a range constraint for the expressions $\va$ and $\vb$; - \item applying $\reducetozopt$ to $\va$ in $\tenv$ yields $\langle\vza\rangle$; - \item applying $\reducetozopt$ to $\vb$ in $\tenv$ yields $\langle\vzb\rangle$; - \item define $\explodedinterval$ as the list of exact constraints for each integer literal in the range starting - at $\vza$ and ending at $\vzb$, inclusively, which is empty if $\vzb < \vza$; - \item applying $\intervaltoolarge$ to $\vza$ and $\vzb$ yields $\vbtoolarge$; - \item define $\vcs$ as the singleton list for $\vc$ if $\vbtoolarge$ is $\True$ and \\ - $\explodedinterval$ otherwise. - \end{itemize} - - \item All of the following apply (\textsc{range\_not\_reduced}): - \begin{itemize} - \item $\vc$ is a range constraint for the expressions $\va$ and $\vb$; - \item applying $\reducetozopt$ to $\va$ in $\tenv$ yields $\vzaopt$; - \item applying $\reducetozopt$ to $\vb$ in $\tenv$ yields $\vzbopt$; - \item at least one of $\vzaopt$ and $\vzbopt$ is $\None$; - \item $\vcs$ is the singleton list for $\vc$. - \end{itemize} -\end{itemize} - -\subsection{Formally} -\begin{mathpar} -\inferrule[exact]{ - \astlabel(\vc) = \ConstraintExact -}{ - \explodeconstraint(\tenv, \vc) \typearrow \overname{[\vc]}{\vcs} -} -\end{mathpar} - -\begin{mathpar} -\inferrule[range\_reduced]{ - \vc = \ConstraintRange(\va, \vb)\\ - \reducetozopt(\tenv, \va) \typearrow \langle\vza\rangle\\ - \reducetozopt(\tenv, \vb) \typearrow \langle\vzb\rangle\\ - \explodedinterval \eqdef [\vz \in \vza..\vzb: \ConstraintExact(\ELInt{\vz})]\\ - \intervaltoolarge(\vza, \vzb) \typearrow \vbtoolarge\\ - \vcs \eqdef \choice{\vbtoolarge}{[\vc]}{\explodedinterval} -}{ - \explodeconstraint(\tenv, \vc) \typearrow \vcs -} -\end{mathpar} - -\begin{mathpar} -\inferrule[range\_not\_reduced]{ - \vc = \ConstraintRange(\va, \vb)\\ - \reducetozopt(\tenv, \va) \typearrow \vzaopt\\ - \reducetozopt(\tenv, \vb) \typearrow \vzbopt\\ - \vzaopt = \None \lor \vzbopt = \None -}{ - \explodeconstraint(\tenv, \vc) \typearrow \overname{[\vc]}{\vcs} -} -\end{mathpar} - -\section{TypingRule.IntervalTooLarge \label{sec:TypingRule.IntervalTooLarge}} -\hypertarget{def-intervaltoolarge}{} -The function -\[ -\intervaltoolarge(\overname{\Z}{\vzone} \aslsep \overname{\Z}{\vztwo}) \aslto \overname{\Bool}{\vb} -\] -tests whether the set of numbers between $\vzone$ and $\vztwo$, inclusive, contains more than $2^{14}$ -integers, yielding the result in $\vb$. - -\subsection{Prose} -The value $\vb$ is $\True$ if and only if the absolute value of $\vzone-\vztwo$ is greater than $2^{14}$. - -\subsection{Formally} -\begin{mathpar} -\inferrule{}{ - \intervaltoolarge(\vzone, \vztwo) \typearrow \overname{|\vzone-\vztwo| > 2^{14}}{\vb} -} -\end{mathpar} - -\section{TypingRule.BinopIsExploding \label{sec:TypingRule.BinopIsExploding}} -\hypertarget{def-binopisexploding}{} -The function -\[ -\binopisexploding(\overname{\binop}{\op}) \aslto \overname{\Bool}{\vb} -\] -determines whether the binary operation $\op$ should lead to applying $\explodeintervals$ -when the $\op$ is applied to a pair of constraint lists. -It is assumed that $\op$ is one of $\MUL$, $\SHL$, $\POW$, $\PLUS$, $\DIV$, $\MINUS$, $\MOD$, $\SHR$, -and $\DIVRM$. - -\subsection{Prose} -The value $\vb$ is $\True$ if and only if $\op$ is one of $\MUL$, $\SHL$, and $\POW$. - -\subsection{Formally} -\begin{mathpar} -\inferrule{}{ - \binopisexploding(\op) \typearrow \overname{\op \in \{\MUL, \SHL, \POW\}}{\vb} -} -\end{mathpar} - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -\chapter{Typing of Types \label{chap:typingoftypes}} -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -\hypertarget{def-annotatetype}{} -The function -\[ - \annotatetype{\overname{\Bool}{\vdecl} \aslsep \overname{\staticenvs}{\tenv} \aslsep \overname{\ty}{\tty}} - \aslto \overname{\ty}{\newty} \cup \overname{\TTypeError}{\TypeErrorConfig} -\] -annotates a type $\tty$ in an environment $\tenv$, resulting in a -annotated type $\newty$. -The flag $\decl$ indicates whether $\tty$ is a type currently being declared. -\ProseOtherwiseTypeError - -The flag $\decl$ is makes a difference only when $\tty$ is an enumeration type or a \structuredtype. - -One of the following applies: -\begin{itemize} - \item TypingRule.TString (see \secref{TypingRule.TString}); - \item TypingRule.TReal (see \secref{TypingRule.TReal}); - \item TypingRule.TBool (see \secref{TypingRule.TBool}); - \item TypingRule.TNamed (see \secref{TypingRule.TNamed}); - \item TypingRule.TInt (see \secref{TypingRule.TInt}); - \item TypingRule.TBits (see \secref{TypingRule.TBits}); - \item TypingRule.TTuple (see \secref{TypingRule.TTuple}); - \item TypingRule.TArray (see \secref{TypingRule.TArray}); - \item TypingRule.TEnumDecl (see \secref{TypingRule.TEnumDecl}); - \item TypingRule.TRecordExceptionDecl (see \secref{TypingRule.TRecordExceptionDecl}); - \item TypingRule.TNonDecl (see \secref{TypingRule.TNonDecl}); -\end{itemize} -\ProseOtherwiseTypeError - -We also define the following helper functions: -\begin{itemize} - \item TypingRule.AnnotateConstraint (see \secref{TypingRule.AnnotateConstraint}) - \item TypingRule.GetVariableEnum (see \secref{TypingRule.GetVariableEnum}) - \item TypingRule.AnnotateStaticInteger (see \secref{TypingRule.AnnotateStaticInteger}) -\end{itemize} - -\section{TypingRule.TString \label{sec:TypingRule.TString}} - -\subsection{Prose} -All of the following apply: -\begin{itemize} - \item $\tty$ is the string type \TString. - \item $\newty$ is the string type \TString. -\end{itemize} - -\subsection{Example} -In the following example, all the uses of \texttt{string} are valid: -\VerbatimInput{../tests/ASLTypingReference.t/TypingRule.TString.asl} - -\CodeSubsection{\TStringBegin}{\TStringEnd}{../Typing.ml} - -\subsection{Formally} -\begin{mathpar} -\inferrule{} -{ - \annotatetype{\overname{\Ignore}{\vdecl}, \tenv, \overname{\TString}{\tty}} \typearrow \overname{\TString}{\newty} -} -\end{mathpar} - -\isempty{\subsection{Comments}} - -\section{TypingRule.TReal \label{sec:TypingRule.TReal}} - -\subsection{Prose} -All of the following apply: -\begin{itemize} - \item $\tty$ is the real type \TReal. - \item $\newty$ is the real type \TReal. -\end{itemize} - -\subsection{Example} -In the following example, all the uses of \texttt{real} are valid: -\VerbatimInput{../tests/ASLTypingReference.t/TypingRule.TReal.asl} - -\subsection{Formally} -\begin{mathpar} -\inferrule{} -{ - \annotatetype{\overname{\Ignore}{\vdecl}, \tenv, \overname{\TReal}{\tty}} \typearrow \overname{\TReal}{\newty} -} -\end{mathpar} - -\CodeSubsection{\TRealBegin}{\TRealEnd}{../Typing.ml} - -\isempty{\subsection{Comments}} - -\section{TypingRule.TBool \label{sec:TypingRule.TBool}} - -\subsection{Prose} -All of the following apply: -\begin{itemize} - \item $\tty$ is the boolean type, \TBool; - \item $\newty$ is the boolean type, \TBool. -\end{itemize} - -\subsection{Example} -In the following example, all the uses of \texttt{boolean} are valid: -\VerbatimInput{../tests/ASLTypingReference.t/TypingRule.TBool.asl} - -\CodeSubsection{\TBoolBegin}{\TBoolEnd}{../Typing.ml} - -\subsection{Formally} -\begin{mathpar} -\inferrule{} -{ - \annotatetype{\overname{\Ignore}{\vdecl}, \tenv, \overname{\TBool}{\tty}} \typearrow \overname{\TBool}{\newty} -} -\end{mathpar} - -\isempty{\subsection{Comments}} - -\section{TypingRule.TNamed \label{sec:TypingRule.TNamed}} - -\subsection{Prose} -All of the following apply: -\begin{itemize} - \item $\tty$ is the named type $\vx$, that is $\TNamed(\vx)$; - \item checking whether $\vx$ is associated with a declared type in $\tenv$ yields $\True$\ProseOrTypeError; - \item $\newty$ is $\tty$. -\end{itemize} - -\subsection{Example} -In the following example, all the uses of \texttt{MyType} are valid: -\VerbatimInput{../tests/ASLTypingReference.t/TypingRule.TNamed.asl} - -\CodeSubsection{\TNamedBegin}{\TNamedEnd}{../Typing.ml} - -\subsection{Formally} -\begin{mathpar} -\inferrule{ - \checktrans{G^\tenv(\vx) \neq \bot}{\UndefinedIdentifier} \typearrow \True \OrTypeError -}{ - \annotatetype{\overname{\Ignore}{\vdecl}, \tenv, \overname{\TNamed(\vx)}{\tty}} \typearrow \overname{\TNamed(\vx)}{\newty} -} -\end{mathpar} - -\isempty{\subsection{Comments}} - -\section{TypingRule.TInt \label{sec:TypingRule.TInt}} - -\subsection{Prose} -One of the following applies: -\begin{itemize} - \item All of the following apply (\textsc{not\_well\_constrained}): - \begin{itemize} - \item $\tty$ is an integer type that is not well-constrained; - \item $\newty$ is the unconstrained integer type. - \end{itemize} - \item All of the following apply (\textsc{well\_constrained}): - \begin{itemize} - \item $\tty$ is the well-constrained integer type constrained by - constraints $\vc_i$, for $u=1..k$; - \item annotating each constraint $\vc_i$, for $i=1..k$, - yields $\newc_i$\ProseOrTypeError; - \item $\newconstraints$ is the list of annotated constraints $\newc_i$, - for $i=1..k$; - \item $\newty$ is the well-constrained integer type constrained - by $\newconstraints$. - \end{itemize} -\end{itemize} - -\subsection{Example} -In the following examples, all the uses of integer types are valid: -\VerbatimInput{../tests/ASLTypingReference.t/TypingRule.TIntUnConstrained.asl} -\VerbatimInput{../tests/ASLTypingReference.t/TypingRule.TIntWellConstrained.asl} -\VerbatimInput{../tests/ASLTypingReference.t/TypingRule.TIntUnderConstrained.asl} - -\CodeSubsection{\TIntBegin}{\TIntEnd}{../Typing.ml} - -\subsection{Formally} -\begin{mathpar} -\inferrule[not\_well\_constrained]{ - \tty \eqname \TInt(\vc)\\ - \astlabel(\vc) \neq \wellconstrained -}{ - \annotatetype{\overname{\Ignore}{\vdecl}, \tenv, \tty} \typearrow \overname{\tty}{\newty} -} -\end{mathpar} - -\begin{mathpar} -\inferrule[well\_constrained]{ - \constraints \eqname \vc_{1..k}\\ - i=1..k: \annotateconstraint(\vc_i) \typearrow\newc_i \OrTypeError\\\\ - \newconstraints \eqdef \newc_{1..k} -}{ - { - \begin{array}{r} - \annotatetype{\overname{\Ignore}{\vdecl}, \tenv, \overname{\TInt(\wellconstrained(\constraints))}{\tty}} \typearrow \\ - \overname{\TInt(\wellconstrained(\newconstraints))}{\newty} - \end{array} - } -} -\end{mathpar} - -\isempty{\subsection{Comments}} - -\section{TypingRule.TBits \label{sec:TypingRule.TBits}} -\subsection{Prose} -All of the following apply: -\begin{itemize} - \item $\tty$ is the bit-vector type with width given by the expression - $\ewidth$ and the bitfields given by $\bitfields$, that is, $\TBits(\ewidth, \bitfields)$; - \item annotating the \staticallyevaluable\ integer expression $\ewidth$ yields $\ewidthp$\ProseOrTypeError; - \item annotating the bitfields $\bitfields$ yields $\bitfieldsp$\ProseOrTypeError; - \item $\newty$ is the bit-vector type with width given by the expression - $\ewidthp$ and the bitfields given by $\bitfieldsp$, that is, $\TBits(\ewidthp, \bitfieldsp)$ -\end{itemize} - -\subsection{Example} -\VerbatimInput{../tests/ASLTypingReference.t/TypingRule.TBits.asl} - -In the following example, all the uses of bitvector types are valid: -\CodeSubsection{\TBitsBegin}{\TBitsEnd}{../Typing.ml} - -\subsection{Formally} -\begin{mathpar} -\inferrule{ - \annotatestaticconstrainedinteger(\tenv, \ewidth) \typearrow \ewidthp \OrTypeError\\\\ - \annotatebitfields(\tenv, \ewidthp, \bitfields) \typearrow \bitfieldsp \OrTypeError -}{ - { - \begin{array}{r} - \annotatetype{\overname{\Ignore}{\vdecl}, \tenv, \TBits(\ewidth, \bitfields)} \typearrow \\ - \TBits(\ewidthp, \bitfieldsp) - \end{array} - } -} -\end{mathpar} - -\subsection{Comments} -The width of a bitvector type $\TBits(\ewidth, \bitfields)$, given by the expression \\ -$\ewidth$, -must be non-negative. - -\section{TypingRule.TTuple \label{sec:TypingRule.TTuple}} - -\subsection{Prose} -All of the following apply: -\begin{itemize} - \item $\tty$ is the tuple type with member types $\tys$, that is, $\TTuple(\tys)$; - \item $\tys$ is the list $\tty_i$, for $i=1..k$; - \item annotating each type $\tty_i$ in $\tenv$, for $i=1..k$, - yields $\ttyp_i$\ProseOrTypeError; - \item $\newty$ is the tuple type with member types $\ttyp$, for $i=1..k$. -\end{itemize} - -In the following example, all the uses of tuple types are valid: -\VerbatimInput{../tests/ASLTypingReference.t/TypingRule.TTuple.asl} -\subsection{Example} - -\CodeSubsection{\TTupleBegin}{\TTupleEnd}{../Typing.ml} - -\subsection{Formally} -\begin{mathpar} -\inferrule{ - k \geq 2\\ - \tys \eqname \tty_{1..k}\\ - i=1..k: \annotatetype{\False, \tenv, \tty_i} \typearrow \ttyp_i \OrTypeError -}{ - \annotatetype{\overname{\Ignore}{\vdecl}, \tenv, \TTuple(\tys)} \typearrow \TTuple(\tysp) -} -\end{mathpar} - -\isempty{\subsection{Comments}} - -\section{TypingRule.TArray \label{sec:TypingRule.TArray}} - -\subsection{Prose} -All of the following apply: -\begin{itemize} - \item $\tty$ is the array type with element type $\vt$; - \item Annotating the type $\vt$ in $\tenv$ yields $\vtp$\ProseOrTypeError; - \item One of the following applies: - \begin{itemize} - \item All of the following apply (\textsc{expr\_is\_enum}): - \begin{itemize} - \item the array index is $\ve$ and determining whether $\ve$ corresponds to an enumeration in $\tenv$ - via $\getvariableenum$ yields the enumeration variable - name $\vs$ of size $\vi$, that is, $\langle \vs, \vi \rangle$\ProseOrTypeError; - \item $\newty$ is the array type indexed by an enumeration type - named $\vs$ of length $\vi$ and of elements of type $\vtp$, that is, $\TArray(\ArrayLengthEnum(\vs, \vi), \vtp)$. - \end{itemize} - - \item All of the following apply (\textsc{expr\_not\_enum}): - \begin{itemize} - \item the array index is $\ve$ and determining whether $\ve$ corresponds to an enumeration in $\tenv$ - via $\getvariableenum$ yields $\None$ (meaning it does not - correspond to an enumeration)\ProseOrTypeError; - \item annotating the statically evaluable integer expression $\ve$ yields - $\vep$\ProseOrTypeError; - \item $\newty$ the array type indexed by integer bounded by - the expression $\vep$ and of elements of type $\vtp$, that is, - $\TArray(\ArrayLengthExpr(\vep), \vtp)$. - \end{itemize} - - \item All of the following apply (\textsc{index\_enum}): - \begin{itemize} - \item the array index is an enumeration type named $\vs$ and a list of $\vi$ labels, - that is, $\ArrayLengthEnum(\vs, \vi)$; - \item let $\tty$ be the named type defined for $\vs$, that is, $\TNamed(\vs)$; - \item determining the \underlyingtype\ of $\tty$ yields $\tsanon$\ProseOrTypeError; - \item checking whether $\tsanon$ is an enumeration type yields $\True$\ProseOrTypeError; - \item $\vt$ is an enumeration with labels $\vli$; - \item checking whether $\vli$ has the same length as $\vi$ yields $\True$\ProseOrTypeError; - \item $\newty$ is the array type indexed by an enumeration type - named $\vs$ of length $\vi$ and of elements of type $\vtp$, that is, $\TArray(\ArrayLengthEnum(\vs, \vi), \vtp)$. - \end{itemize} - \end{itemize} -\end{itemize} - -\subsection{Example} -In the following example, all the uses of array types are valid: -\VerbatimInput{../tests/ASLTypingReference.t/TypingRule.TArray.asl} - -\CodeSubsection{\TArrayBegin}{\TArrayEnd}{../Typing.ml} - -\subsection{Formally} -\begin{mathpar} -\inferrule[expr\_is\_enum]{ - \annotatetype{\False, \tenv, \vt} \typearrow \vtp \OrTypeError\\\\ - \commonprefixline\\\\ - \getvariableenum(\tenv, \ve) \typearrow \langle \vs, \vi \rangle\OrTypeError -}{ - \annotatetype{\overname{\Ignore}{\vdecl}, \tenv, \overname{\AbbrevTArrayLengthExpr{\ve}{\vt}}{\tty}} \typearrow - \overname{\AbbrevTArrayLengthEnum{\ve}{\vi}{\vtp}}{\newty} -} -\end{mathpar} - -\begin{mathpar} -\inferrule[expr\_not\_enum]{ - \annotatetype{\False, \tenv, \vt} \typearrow \vtp \OrTypeError\\\\ - \commonprefixline\\\\ - \getvariableenum(\tenv, \ve) \typearrow \None \OrTypeError\\\\ - \annotatestaticinteger(\tenv, \ve) \typearrow \vep \OrTypeError -}{ - \annotatetype{\overname{\Ignore}{\vdecl}, \tenv, \overname{\AbbrevTArrayLengthExpr{\ve}{\vt}}{\tty}} \typearrow - \overname{\AbbrevTArrayLengthExpr{\vep}{\vtp}}{\newty} -} -\end{mathpar} - -\begin{mathpar} -\inferrule[index\_enum]{ - \annotatetype{\False, \tenv, \vt} \typearrow \vtp \OrTypeError\\\\ - \commonprefixline\\\\ - \tsubs \eqdef \TNamed(\vs)\\ - \makeanonymous(\tenv, \tsubs) \typearrow \tsanon \OrTypeError\\\\ - \checktrans{\astlabel(\tsanon) = \TEnum}{\ExpectedEnumerationType} \checktransarrow \True \OrTypeError\\\\ - \tsanon \eqname \TEnum(\vli)\\ - \checktrans{\equallength(\vli, \vi)}{TypeConflict} \checktransarrow \True \OrTypeError -}{ - \annotatetype{\overname{\Ignore}{\vdecl}, \tenv, \overname{\AbbrevTArrayLengthEnum{\vs}{\vi}{\vt}}{\tty}} \typearrow - \overname{\AbbrevTArrayLengthEnum{\vs}{\vi}{\vtp}}{\newty} -} -\end{mathpar} - -\isempty{\subsection{Comments}} - -\section{TypingRule.TEnumDecl \label{sec:TypingRule.TEnumDecl}} - -\subsection{Prose} -All of the following apply: -\begin{itemize} - \item $\tty$ is the enumeration type with enumeration literals - $\vli$, that is, $\TEnum(\vli)$; - \item $\decl$ is $\True$, indicating that $\tty$ should be considered in the context of a declaration; - \item determining that $\vli$ does not contain duplicates yields $\True$\ProseOrTypeError; - \item determining that none of the labels in $\vli$ is declared in the global environment - yields $\True$\ProseOrTypeError; - \item $\newty$ is the enumeration type $\tty$. -\end{itemize} - -\subsection{Example} -The following example declares a valid enumeration type: -\VerbatimInput{../tests/ASLTypingReference.t/TypingRule.TEnumDecl.asl} - -\CodeSubsection{\TEnumDeclBegin}{\TEnumDeclEnd}{../Typing.ml} - -\subsection{Formally} -\begin{mathpar} -\inferrule{ - \checknoduplicates(\vli) \typearrow \True \OrTypeError\\\\ - \vl \in \vli: \checkvarnotingenv{\tenv, \vl} \typearrow \True \OrTypeError -}{ - \annotatetype{\True, \tenv, \TEnum(\vli)} \typearrow \TEnum(\vli) -} -\end{mathpar} - -\isempty{\subsection{Comments}} -\lrmcomment{This is related to \identd{YZBQ}, \identr{DWSP}, \identi{MZXL}.} - -\section{TypingRule.TRecordExceptionDecl \label{sec:TypingRule.TRecordExceptionDecl}} - -\subsection{Prose} -All of the following apply: -\begin{itemize} - \item $\tty$ is a \structuredtype\ with AST label $L$; - \item the list of fields of $\tty$ is $\fields$; - \item $\decl$ is $\True$, indicating that $\tty$ should be considered in the context of a declaration; - \item $\fields$ is a list of pairs where the first element is an identifier and the second is a type --- $(\vx_i, \vt_i)$, for $i=1..k$; - \item checking that the list of field identifiers $\vx_{1..k}$ does not contain duplicates - yields $\True$\ProseOrTypeError; - \item annotating each field type $\vt_i$, for $i=1..k$, yields an annotated type $\vtp_i$ - \ProseOrTypeError; - \item $\fieldsp$ is the list with $(\vx_i, \vtp_i)$, for $i=1..k$; - \item $\newty$ is the AST node with AST label $L$ (either record type or exception type, - corresponding to the type $\tty$) and fields $\fieldsp$. -\end{itemize} - -\subsection{Example} -In the following example, all the uses of record or exception types are valid: -\VerbatimInput{../tests/ASLTypingReference.t/TypingRule.TRecordExceptionDecl.asl} - -\CodeSubsection{\TRecordExceptionDeclBegin}{\TRecordExceptionDeclEnd}{../Typing.ml} - -\subsection{Formally} -\begin{mathpar} -\inferrule{ - L \in \{\TRecord, \TException\}\\ - \fields \eqname [i=1..k: (\vx_i, \vt_i)]\\ - \checknoduplicates(\vx_{1..k}) \typearrow \True \OrTypeError\\\\ - i=1..k: \annotatetype{\False, \tenv, \vt_i} \typearrow \vtp_i \OrTypeError\\\\ - \fieldsp \eqdef [i=1..k: (\vx_i, \vtp_i)] -}{ - \annotatetype{\True, \tenv, L(\fields)} \typearrow L(\fieldsp) -} -\end{mathpar} - -\isempty{\subsection{Comments}} - -\section{TypingRule.TNonDecl \label{sec:TypingRule.TNonDecl}} -\subsection{Prose} -All of the following apply: -\begin{itemize} - \item $\tty$ is a \structuredtype\ or an enumeration type; - \item $\decl$ is $\False$, indicating that $\tty$ should be considered to be outside the context of a declaration - of $\tty$; - \item a type error is returned, indicating that the use of anonymous form of enumerations, record, - and exceptions types is not allowed here. -\end{itemize} - -\subsection{Example} -In the following example, the use of a record type outside of a declaration is erroneous: -\VerbatimInput{../tests/ASLTypingReference.t/TypingRule.TNonDecl.asl} - -\CodeSubsection{\TNonDeclBegin}{\TNonDeclEnd}{../Typing.ml} - -\subsection{Formally} -\begin{mathpar} -\inferrule{ - \astlabel(\tty) \in \{\TEnum, \TRecord, \TException\} -}{ - \annotatetype{\False, \tenv, \tty} \typearrow \TypeErrorVal{\AnnonymousFormNotAllowedHere} -} -\end{mathpar} - -\isempty{\subsection{Comments}} - -\section{TypingRule.AnnotateConstraint \label{sec:TypingRule.AnnotateConstraint}} -\hypertarget{def-annotateconstraint}{} -The function -\[ -\annotateconstraint(\overname{\staticenvs}{\tenv} \aslsep \overname{\intconstraint}{\vc}) -\aslto \overname{\intconstraint}{\newc} \cup \overname{\TTypeError}{\TypeErrorConfig} -\] -annotates an integer constraint $\vc$ in the static environment $\tenv$ yielding the annotated -integer constraint $\newc$. -\ProseOtherwiseTypeError - -\subsection{Prose} -One of the following applies: -\begin{itemize} - \item All of the following apply (\textsc{exact}): - \begin{itemize} - \item $\vc$ is the exact integer constraint for the expression $\ve$, that is, \\ $\ConstraintExact(\ve)$; - \item applying $\annotatestaticconstrainedinteger$ to $\ve$ in $\tenv$ yields $\vep$\ProseOrTypeError; - \item define $\newc$ as the exact integer constraint for $\vep$, that is, $\ConstraintExact(\vep)$. - \end{itemize} - - \item All of the following apply (\textsc{range}): - \begin{itemize} - \item $\vc$ is the range integer constraint for expressions $\veone$ and $\vetwo$, that is, \\ $\ConstraintRange(\veone, \vetwo)$; - \item applying $\annotatestaticconstrainedinteger$ to $\veone$ in $\tenv$ yields $\veonep$\ProseOrTypeError; - \item applying $\annotatestaticconstrainedinteger$ to $\vetwo$ in $\tenv$ yields $\vetwop$\ProseOrTypeError; - \item define $\newc$ as the range integer constraint for expressions $\veonep$ and $\vetwop$, that is, $\ConstraintRange(\veonep, \vetwop)$. - \end{itemize} -\end{itemize} - -\subsection{Formally} -\begin{mathpar} -\inferrule[exact]{ - \annotatestaticconstrainedinteger(\tenv, \ve) \typearrow \vep \OrTypeError -}{ - \annotateconstraint(\tenv, \overname{\ConstraintExact(\ve)}{\vc}) \typearrow \overname{\ConstraintExact(\vep)}{\newc} -} -\and -\inferrule[range]{ - \annotatestaticconstrainedinteger(\tenv, \veone) \typearrow \veonep \OrTypeError\\\\ - \annotatestaticconstrainedinteger(\tenv, \vetwo) \typearrow \vetwop \OrTypeError -}{ - \annotateconstraint(\tenv, \overname{\ConstraintRange(\veone, \vetwo)}{\vc}) \typearrow \overname{\ConstraintRange(\veonep, \vetwop)}{\newc} -} -\end{mathpar} - -\section{TypingRule.GetVariableEnum \label{sec:TypingRule.GetVariableEnum}} -\hypertarget{def-getvariableenum}{} -The function -\[ -\getvariableenum(\overname{\staticenvs}{\tenv} \aslsep \overname{\expr}{\ve}) \aslto -\langle (\overname{\identifier}{\vx}, \overname{\N}{n})\rangle -\] -tests whether the expression $\ve$ represents a variable of an enumeration type. -If so, the result is $\vx$ --- the name of the variable and the number of labels defined for the enumeration type. -Otherwise, the result is $\None$. - -\subsection{Prose} -One of the following applies: -\begin{itemize} - \item All of the following apply (\textsc{not\_evar}): - \begin{itemize} - \item $\ve$ is not a variable expression; - \item the result is $\None$. - \end{itemize} - - \item All of the following apply (\textsc{no\_declared\_type}): - \begin{itemize} - \item $\ve$ is a variable expression for $\vx$, that is, $\EVar(\vx)$; - \item $\vx$ is not associated with a type in the global environment of $\tenv$; - \item the result is $\None$. - \end{itemize} - - \item All of the following apply (\textsc{declared\_enum}): - \begin{itemize} - \item $\ve$ is a variable expression for $\vx$, that is, $\EVar(\vx)$; - \item $\vx$ is associated with a type $\vt$ in the global environment of $\tenv$; - \item obtaining the \underlyingtype\ of $\vt$ in $\tenv$ yields an enumeration type with labels $\vli$\ProseOrTypeError; - \item the result is the pair consisting of $\vx$ and the length of $\vli$. - \end{itemize} - - \item All of the following apply (\textsc{declared\_not\_enum}): - \begin{itemize} - \item $\ve$ is a variable expression for $\vx$, that is, $\EVar(\vx)$; - \item $\vx$ is associated with a type $\vt$ in the global environment of $\tenv$; - \item obtaining the \underlyingtype\ of $\vt$ in $\tenv$ yields a type that is not an enumeration type; - \item the result is $\None$. - \end{itemize} -\end{itemize} - -\subsection{Formally} -\begin{mathpar} -\inferrule[not\_evar]{ - \astlabel(\ve) \neq \EVar -}{ - \getvariableenum(\tenv, \ve) \typearrow \None -} -\end{mathpar} - -\begin{mathpar} -\inferrule[no\_declared\_type]{ - G^\tenv.\declaredtypes(\vx) \typearrow \None -}{ - \getvariableenum(\tenv, \overname{\EVar(\vx)}{\ve}) \typearrow \None -} -\end{mathpar} - -\begin{mathpar} -\inferrule[declared\_enum]{ - G^\tenv.\declaredtypes(\vx) \typearrow \langle\vt\rangle\\ - \makeanonymous(\tenv, \vt) \typearrow \TEnum(\vli) \OrTypeError -}{ - \getvariableenum(\tenv, \overname{\EVar(\vx)}{\ve}) \typearrow \langle(\vx, |\vli|)\rangle -} -\end{mathpar} - -\begin{mathpar} -\inferrule[declared\_not\_enum]{ - G^\tenv.\declaredtypes(\vx) \typearrow \langle\vt\rangle\\ - \makeanonymous(\tenv, \vt) \typearrow \vtone\\ - \astlabel(\vtone) \neq \TEnum -}{ - \getvariableenum(\tenv, \overname{\EVar(\vx)}{\ve}) \typearrow \None -} -\end{mathpar} - -\section{TypingRule.AnnotateStaticInteger \label{sec:TypingRule.AnnotateStaticInteger}} -\hypertarget{def-annotatestaticinteger}{} -The function -\[ - \annotatestaticinteger(\overname{\staticenvs}{\tenv} \aslsep \overname{\expr}{\ve}) \aslto - \overname{\expr}{\vepp} \cup \overname{\TTypeError}{\TypeErrorConfig} -\] -annotates a \staticallyevaluable\ integer expression $\ve$ in the static environment $\tenv$ -and returns the annotated expression $\vepp$. -\ProseOtherwiseTypeError - -\subsection{Prose} -All of the following apply: -\begin{itemize} - \item annotating the expression $\ve$ in $\tenv$ yields $ (\vt, \vep)$\ProseOrTypeError; - \item determining whether $\vt$ has the structure of an integer yields $\True$\ProseOrTypeError; - \item determining whether $\vep$ is \staticallyevaluable\ in $\tenv$ yields $\True$\ProseOrTypeError; - \item applying $\normalize$ to $\vep$ in $\tenv$ yields $\vepp$. -\end{itemize} - -\CodeSubsection{\AnnotateStaticIntegerBegin}{\AnnotateStaticIntegerEnd}{../Typing.ml} - -\subsection{Formally} -\begin{mathpar} -\inferrule{ - \annotateexpr{\tenv, \ve} \typearrow (\vt, \vep) \OrTypeError\\\\ - \checkstructureinteger(\tenv, \vt) \typearrow \True \OrTypeError\\\\ - \checkstaticallyevaluable(\tenv, \vep) \typearrow \True \OrTypeError\\\\ - \normalize(\tenv, \vep) \typearrow \vepp -}{ - \annotatestaticinteger(\tenv, \ve) \typearrow \vepp -} -\end{mathpar} - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -\chapter{Typing of Bitfields} -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - -We define rules for annotating a single bitfield and a list of bitfields: -\begin{itemize} - \item TypingRule.TBitField (see \secref{TypingRule.TBitField}); - \item TypingRule.TBitFields (see \secref{TypingRule.TBitFields}); -\end{itemize} - -\section{TypingRule.TBitField \label{sec:TypingRule.TBitField}} -\hypertarget{def-annotatebitfield}{} -The function -\[ - \annotatebitfield(\overname{\staticenvs}{\tenv} \aslsep \overname{\Z}{\width} \aslsep \overname{\bitfield}{\vfield}) - \aslto \overname{\bitfield}{\newfield} \cup \overname{\TTypeError}{\TypeErrorConfig} -\] -annotates a bitfield --- $\vfield$ --- with an integer --- $\width$ --- indicating the number of bits in -the bitvector type that contains $\field$, -in an environment $\tenv$, resulting in an -annotated bitfield --- $\newfield$ --- or a type error, if one is detected. - -\subsection{Prose} -\begin{itemize} - \item $\vfield$ is a bitfield with list of slices $\vslices$; - \item annotating the slices $\vslices$ yields $\slicesone$\ProseOrTypeError; - \item One of the following applies: - \begin{itemize} - \item All of the following apply (\textsc{simple}): - \begin{itemize} - \item checking whether the range of positions in $\slicesone$ fits inside $0..\width-1$ yields $\True$\ProseOrTypeError; - \item $\newfield$ is a bitfield named $\name$ with list of slices $\slicesone$, that is, $\BitFieldSimple(\name, \slicesone)$. - \end{itemize} - - \item All of the following apply (\textsc{nested}): - \begin{itemize} - \item converting the $\slicesone$ into a list of positions with $\width$ and static environment $\tenv$ - yields $\positions$\ProseOrTypeError; - \item checking that all positions in $\positions$ fit inside $0..\width$ yields \\ - $\True$\ProseOrTypeError; - \item let $\widthp$ be the length of the list $\positions$; - \item annotating the bitfields $\bitfieldsp$ with $\widthp$ in static environment $\tenv$ yields $\bitfieldspp$\ProseOrTypeError; - \item $\newfields$ is the nested bitfield with $\slicesone$ and bitfields $\bitfieldspp$, that is, $\BitFieldNested(\slicesone, \bitfieldspp)$. - \end{itemize} - - \item All of the following apply (\textsc{type}): - \begin{itemize} - \item Annotating the type $\vt$ yields $\vtp$\ProseOrTypeError; - \item checking whether the range of positions in $\slicesone$ fit inside $0..\width$ yields $\True$\ProseOrTypeError; - \item converting the list of slices $\slicesone$ into a list of positions in $\tenv$ yields $\positions$\ProseOrTypeError; - \item checking that all positions in $\positions$ fit inside $0..\width$ yields $\True$\ProseOrTypeError; - \item let $\widthp$ be the length of the list $\positions$; - \item checking whether the $\vt$ and the bitvector with $\widthp$ bits have the same width yields $\True$\ProseOrTypeError - \item $\newfield$ is the typed-bitfield with name $\name$, list of slices $\slicesone$ and type $\vtp$, that is, \BitFieldType(\name, \slicesone, \vtp). - \end{itemize} - \end{itemize} -\end{itemize} - -\subsection{Example} -In the following example, all the uses of bitvector types with bitfields are valid: -\VerbatimInput{../tests/ASLTypingReference.t/TypingRule.TBitField.asl} - -\CodeSubsection{\TBitFieldBegin}{\TBitFieldEnd}{../Typing.ml} - -\subsection{Formally} -\begin{mathpar} -\inferrule[simple]{ - \annotateslices(\tenv, \vslices) \typearrow \slicesone \OrTypeError\\\\ - \commonprefixline\\\\ - \checkslicesinwidth(\tenv, \width, \slicesone) \typearrow \True \OrTypeError -}{ - \annotatebitfield(\tenv, \width, \BitFieldSimple(\name, \vslices)) \typearrow \\ - \BitFieldSimple(\name, \slicesone) -} -\end{mathpar} - -\begin{mathpar} -\inferrule[nested]{ - \annotateslices(\tenv, \vslices) \typearrow \slicesone \OrTypeError\\\\ - \commonprefixline\\\\ - \disjointslicestopositions(\tenv, \width, \slicesone) \typearrow \positions \OrTypeError\\\\ - \checkpositionsinwidth(\tenv, \width, \positions) \typearrow \True \OrTypeError\\\\ - \widthp \eqdef \listlen{\positions}\\ - \annotatebitfields(\tenv, \widthp, \bitfieldsp) \typearrow \bitfieldspp \OrTypeError\\ -}{ - \annotatebitfield(\tenv, \width, \BitFieldNested(\name, \vslices, \bitfieldsp)) \typearrow \\ - \BitFieldNested(\slicesone, \bitfieldspp) -} -\end{mathpar} - -\begin{mathpar} -\inferrule[type]{ - \annotateslices(\tenv, \vslices) \typearrow \slicesone \OrTypeError\\\\ - \commonprefixline\\\\ - \annotatetype{\tenv, \vt} \typearrow \vtp \OrTypeError\\\\ - \checkslicesinwidth(\tenv, \width, \slicesone) \typearrow \True \OrTypeError\\\\ - \disjointslicestopositions(\tenv, \slicesone) \typearrow \positions \OrTypeError\\\\ - \checkpositionsinwidth(\tenv, \slicesone, \width, \positions) \typearrow \True \OrTypeError\\\\ - \widthp \eqdef \listlen{\positions}\\ - \checkbitsequalwidth(\TBits(\widthp, \emptylist), \vt) \typearrow \True \OrTypeError -}{ - \annotatebitfield(\tenv, \width, \BitFieldType(\name, \vslices, \vt)) \typearrow \\ - \BitFieldType(\name, \slicesone, \vtp) -} -\end{mathpar} - -\isempty{\subsection{Comments}} - -\section{TypingRule.TBitFields \label{sec:TypingRule.TBitFields}} -\hypertarget{def-annotatebitfields}{} -The function -\[ - \annotatebitfields(\overname{\staticenvs}{\tenv} \aslsep \overname{\expr}{\ewidth} \aslsep \overname{\bitfields}{\fields}) - \aslto \overname{\bitfields}{\newfields} \cup \overname{\TTypeError}{\TypeErrorConfig} -\] -annotates a list of bitfields --- $\fields$ --- with an expression denoting the overall number of bits in the containing -bitvector type --- $\ewidth$, -in an environment $\tenv$, resulting in an -annotated list of bitfields --- $\newfields$ or a type error, if one is detected. - -\subsection{Prose} -All of the following apply: -\begin{itemize} - \item checking that the list of bitfield names in $\bitfields$ does not contain duplicates yields $\True$\ProseOrTypeError; - \item symbolically simplifying $\ewidth$ in $\tenv$ via $\reduceconstants$ yields the literal integer for $\width$\ProseOrTypeError; - \item annotating each bitfield $\field$ in $\fields$ with width $\width$ in $\tenv$ yields the corresponding annotated - bitfield $\newfield$\ProseOrTypeError; - \item $\newfields$ is the list of annotated bitfields. -\end{itemize} - -\isempty{\subsection{Example}} - -\CodeSubsection{\TBitFieldsBegin}{\TBitFieldsEnd}{../Typing.ml} - -\subsection{Formally} -\begin{mathpar} -\inferrule{ - \names \eqdef [\field\in\fields: \bitfieldgetname(\field)]\\ - \checknoduplicates(\names) \typearrow \True \OrTypeError\\\\ - \reduceconstants(\tenv, \ewidth) \typearrow \lint(\width) \OrTypeError\\\\ - \field\in\fields: \annotatebitfield(\tenv, \width, \field) \typearrow \newfield \OrTypeError\\\\ - \newfields \eqdef [\field\in\fields: \newfield] -}{ - \annotatebitfields(\tenv, \ewidth, \fields) \typearrow \newfields -} -\end{mathpar} - -\isempty{\subsection{Comments}} - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -\chapter{Typing of Expressions \label{chap:typingexpr}} -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -\hypertarget{def-annotateexpr}{} -The function -\[ - \annotateexpr{\overname{\staticenvs}{\tenv} \aslsep \overname{\expr}{\ve}} - \aslto (\overname{\ty}{\vt} \times \overname{\expr}{\newe}) - \cup \overname{\TTypeError}{\TypeErrorConfig} -\] -specifies how to annotate an expression $\ve$ in -an environment \tenv. Formally, the result of annotating the expression -$\ve$ in \tenv\ is either the pair $(\vt, \newe)$, where $\vt$ is a type and -$\newe$ is an annotated expression, or a type error, and one of the following applies: -\begin{itemize} -\item TypingRule.ELit (see \secref{TypingRule.ELit}); -\item TypingRule.ELocalVar (see \secref{TypingRule.ELocalVar}) -\item TypingRule.EGlobalVarConstant (see \secref{TypingRule.EGlobalVarConstant}) -\item TypingRule.EGlobalVarConstantNoVal (see \secref{TypingRule.EGlobalVarConstantNoVal}) -\item TypingRule.EGlobalVar (see \secref{TypingRule.EGlobalVar}) -\item TypingRule.EUndefIdent (see \secref{TypingRule.EUndefIdent}) -\item TypingRule.Binop (see \secref{TypingRule.Binop}) -\item TypingRule.Unop (see \secref{TypingRule.Unop}) -\item TypingRule.ECond (see \secref{TypingRule.ECond}) -\item TypingRule.ESlice (see \secref{TypingRule.ESlice}) -\item TypingRule.ESetter (see \secref{TypingRule.ESetter}) -\item TypingRule.ECall (see \secref{TypingRule.ECall}) -\item TypingRule.EGetArray (see \secref{TypingRule.EGetArray}) -\item TypingRule.ESliceOrEGetArrayError (see \secref{TypingRule.ESliceOrEGetArrayError}) -\item TypingRule.ERecord (see \secref{TypingRule.ERecord}) -\item TypingRule.EGetRecordField (see \secref{TypingRule.EGetRecordField}) -\item TypingRule.EGetBadRecordField (see \secref{TypingRule.EGetBadRecordField}) -\item TypingRule.EGetBadBitField (see \secref{TypingRule.EGetBadBitField}) -\item TypingRule.EGetBitField (see \secref{TypingRule.EGetBitField}) -\item TypingRule.EGetBitFieldNested (see \secref{TypingRule.EGetBitFieldNested}) -\item TypingRule.EGetBitFieldTyped (see \secref{TypingRule.EGetBitFieldTyped}) -\item TypingRule.EGetTupleItem (see \secref{TypingRule.EGetTupleItem}) -\item TypingRule.EGetBadField (see \secref{TypingRule.EGetBadField}) -\item TypingRule.EConcat (see \secref{TypingRule.EConcat}) -\item TypingRule.ETuple (see \secref{TypingRule.ETuple}) -\item TypingRule.EUnknown (see \secref{TypingRule.EUnknown}) -\item TypingRule.EPattern (see \secref{TypingRule.EPattern}) -\item TypingRule.ATC (see \secref{TypingRule.ATC}) -\end{itemize} - -The annotation rewrites the input expression in the following cases, making the annotation of statements simpler: -\begin{itemize} - \item Variables with constant values are substituted by their constant values. - \item Slicing expressions that correspond to calling a getter are replaced with respective call expressions. - \item Slicing expressions that correspond to \arrayaccess\ expressions are replaced by \arrayaccess\ expressions. -\end{itemize} - -We also define the following helper rules: -\begin{itemize} - \item TypingRule.Lit (\secref{TypingRule.Lit}) - \item TypingRule.ExpressionList (\secref{TypingRule.ExpressionList}) - \item TypingRule.TypingRule.ReduceSlicesToCall (\secref{TypingRule.ReduceSlicesToCall}) - \item TypingRule.StaticConstrainedInteger (\secref{TypingRule.StaticConstrainedInteger}) - \item TypingRule.CheckATC (\secref{TypingRule.CheckATC}) -\end{itemize} - -\section{TypingRule.ELit \label{sec:TypingRule.ELit}} -\subsection{Prose} -All of the following apply: -\begin{itemize} -\item $\ve$ is the literal expression $\vv$; -\item $\vt$ is the type of the literal $\vv$; -\item $\newe$ is $\ve$. -\end{itemize} - -\isempty{\subsection{Example}} - -\CodeSubsection{\ELitBegin}{\ELitEnd}{../Typing.ml} - -\subsection{Formally} -\begin{mathpar} -\inferrule{\annotateliteral{\vv} \typearrow \vt} -{\annotateexpr{\tenv, \ELiteral(\vv)} \typearrow (\vt, \ELiteral(\vv))} -\end{mathpar} - -\section{TypingRule.ELocalVar \label{sec:TypingRule.ELocalVar}} -\subsection{Prose} -One of the following applies: -\begin{itemize} - \item All of the following apply (\textsc{constant}): - \begin{itemize} - \item $\ve$ denotes a local variable $\vx$; - \item $\vx$ is bound to a local constant $\vv$ of type $\vt$ in the local environment given by $\tenv$; - \item $\newe$ is the Literal $\vv$. - \end{itemize} - - \item All of the following apply (\textsc{non\_constant}): - \begin{itemize} - \item $\ve$ denotes a local variable $\vx$; - \item $\vx$ is not bound to a constant in the local environment given by $\tenv$; - \item $\vx$ has type $\vt$ in the local environment given by $\tenv$; - \item $\newe$ is $\ve$. - \end{itemize} -\end{itemize} - -\subsection{Formally} -\begin{mathpar} -\inferrule[constant]{ - L^\tenv.\constantvalues(\vx) = \vv\\ - L^\tenv.\localstoragetypes(\vx) = (\vt, \LDKConstant) -}{ - \annotateexpr{\tenv, \overname{\EVar(\vx)}{\ve}} \typearrow (\vt, \overname{\eliteral{\vv}}{\newe}) -} -\end{mathpar} - -\begin{mathpar} -\inferrule[non\_constant]{ - L^\tenv.\constantvalues(\vx) = \bot\\ - L^\tenv.\localstoragetypes(\vx) = (\vt, k) \\ - k \in \{\LDKVar, \LDKLet\} -}{ - \annotateexpr{\tenv, \overname{\EVar(\vx)}{\ve}} \typearrow (\vt, \overname{\EVar(\vx)}{\newe}) -} -\end{mathpar} - -\section{TypingRule.EGlobalVarConstantVal \label{sec:TypingRule.EGlobalVarConstant}} - -\subsection{Prose} -All of the following apply: -\begin{itemize} -\item $\ve$ denotes a global variable $\vx$; -\item $\vx$ is bound to a constant $\vv$ of type $\tty$ in the global environment given by $\tenv$; -\item $\vt$ is $\tty$; -\item $\newe$ is the Literal for $\vv$. -\end{itemize} - -\isempty{\subsection{Example}} - -\CodeSubsection{\EGlobalVarConstantBegin}{\EGlobalVarConstantEnd}{../Typing.ml} - - \subsection{Formally} -\begin{mathpar} -\inferrule{ - G^\tenv.\globalstoragetypes(\vx) = (\tty, \GDKConstant)\\ - G^\tenv.\constantvalues(\vx) = \vv -}{ - \annotateexpr{\tenv, \EVar(\vx)} \typearrow (\tty, \eliteral{\vv}) -} -\end{mathpar} - -\isempty{\subsection{Comments}} - -\section{TypingRule.EGlobalVarConstantNoVal \label{sec:TypingRule.EGlobalVarConstantNoVal}} -Our type system does not currently address assignments of non-constant expressions (for example, -function calls) to global constant variables. This section can be seen as a place holder until -the right details are filled in. - -\subsection{Prose} -All of the following apply: -\begin{itemize} -\item $\ve$ denotes a global variable $\vx$; -\item $\vx$ is not bound to constant in the global environment given by $\tenv$; -\item $\vt$ is $\tty$; -\item $\newe$ is $\ve$. -\end{itemize} - -\isempty{\subsection{Example}} - -\CodeSubsection{\EGlobalVarConstantNoValBegin}{\EGlobalVarConstantNoValEnd}{../Typing.ml} - - \subsection{Formally} -\begin{mathpar} -\inferrule{ - G^\tenv.\globalstoragetypes(\vx) = (\tty, \GDKConstant)\\ - G^\tenv.\constantvalues(\vx) = \bot - } -{\annotateexpr{\tenv, \EVar(\vx)} \typearrow (\tty, \EVar(\vx))} -\end{mathpar} - -\isempty{\subsection{Comments}} - -\section{TypingRule.EGlobalVar \label{sec:TypingRule.EGlobalVar}} - -\subsection{Prose} -All of the following apply: -\begin{itemize} -\item $\ve$ denotes a global variable $\vx$; -\item $\vx$ is not bound to a global constant; -\item $\vx$ has type $\tty$ in the global environment given by $\tenv$; -\item $\vt$ is $\tty$; -\item $\newe$ is $\ve$. -\end{itemize} - -\isempty{\subsection{Example}} - -\CodeSubsection{\EGlobalVarBegin}{\EGlobalVarEnd}{../Typing.ml} - - \subsection{Formally} -\begin{mathpar} -\inferrule{ - G^\tenv.\constantvalues(\vx) = \bot\\ - G^\tenv.\globalstoragetypes(\vx) = (\tty, k)\\ - k \neq \GDKConstant - } -{\annotateexpr{\tenv, \EVar(\vx)} \typearrow (\tty, \EVar(\vx))} -\end{mathpar} - -\isempty{\subsection{Comments}} - -\section{TypingRule.EUndefIdent \label{sec:TypingRule.EUndefIdent}} - -\subsection{Prose} -All of the following apply: -\begin{itemize} -\item $\ve$ is a variable $\vx$; -\item $\vx$ is not bound to a type in $\tenv$; -\item the result is a type error indicating that $\vx$ is an undefined identifier. -\end{itemize} - -\isempty{\subsection{Example}} - -\CodeSubsection{\EUndefIdentBegin}{\EUndefIdentEnd}{../Typing.ml} - -\subsection{Formally} -\begin{mathpar} -\inferrule{ - G^\tenv.\globalstoragetypes(\vx) = \bot\\ - L^\tenv.\globalstoragetypes(\vx) = \bot\\ -}{ - \annotateexpr{\tenv,\overname{\EVar(\vx)}{\ve}} \typearrow \TypeErrorVal{\UndefinedIdentifier} -} -\end{mathpar} - -\isempty{\subsection{Comments}} - -\section{TypingRule.Binop \label{sec:TypingRule.Binop}} - -\subsection{Prose} -All of the following apply: -\begin{itemize} - \item $\ve$ denotes a binary operation $\op$ over two expressions $\veone$ and $\vetwo$, that is, \\ $\EBinop(\op, \veone, \vetwo)$; - \item the result of annotating $\veone$ in $\tenv$ is $(\vtone, \veonep)$\ProseOrTypeError; - \item the result of annotating $\vetwo$ in $\tenv$ is $(\vttwo, \vetwop)$\ProseOrTypeError; - \item the result of checking compatibility of $\op$ with $\vtone$ and $\vttwo$ as per \secref{TypingRule.CheckBinop} - is $\vt$\ProseOrTypeError; - \item $\newenv$ denotes $\op$ over $\veonep$ and $\vetwop$. -\end{itemize} - -\isempty{\subsection{Example}} - -\CodeSubsection{\BinopBegin}{\BinopEnd}{../Typing.ml} - -\subsection{Formally} -\begin{mathpar} -\inferrule{ - \annotateexpr{\tenv, \veone} \typearrow (\vtone, \veone') \OrTypeError\\\\ - \annotateexpr{\tenv, \vetwo} \typearrow (\vttwo, \vetwo') \OrTypeError\\\\ - \CheckBinop(\tenv, \op, \vtone, \vttwo) \typearrow \vt \OrTypeError -}{ - \annotateexpr{\tenv, \overname{\EBinop(\op, \veone, \vetwo)}{\ve}} \typearrow (\vt, \overname{\EBinop(\op, \veone', \vetwo')}{\newe}) -} -\end{mathpar} - -\isempty{\subsection{Comments}} - -\section{TypingRule.Unop \label{sec:TypingRule.Unop}} - -\subsection{Prose} -All of the following apply: -\begin{itemize} - \item $\ve$ denotes a unary operation $\op$ over an expression $\vep$, that is $\EUnop(\op, \vep)$; - \item annotating $\vep$ in $\tenv$ yields $(\vtpp, \vepp)$\ProseOrTypeError; - \item checking compatibility of $\op$ with $\vtpp$ as per \secref{TypingRule.CheckUnop} yields $\vt$\ProseOrTypeError; - \item $\newe$ denotes $\op$ over $\vepp$, that is, $\EUnop(\op, \vepp)$. -\end{itemize} - -\isempty{\subsection{Example}} - -\CodeSubsection{\UnopBegin}{\UnopEnd}{../Typing.ml} - -\subsection{Formally} -\begin{mathpar} -\inferrule{ - \annotateexpr{\tenv, \vep} \typearrow (\vtpp, \vepp) \OrTypeError\\\\ - \CheckUnop(\tenv, \op, \vtpp) \typearrow \vt \OrTypeError -}{ - \annotateexpr{\tenv, \EUnop(\op, \vep)} \typearrow (\vt, \EUnop(\op, \vepp)) -} -\end{mathpar} - -\isempty{\subsection{Comments}} - -\section{TypingRule.ECond \label{sec:TypingRule.ECond}} - -\subsection{Prose} -All of the following apply: -\begin{itemize} - \item $\ve$ denotes a conditional expression with condition $\econd$ with two options $\etrue$ and $\efalse$; - \item annotating $\econd$ in $\tenv$ results in $(\tcond, \econdp)$\ProseOrTypeError; - \item annotating $\etrue$ in $\tenv$ results in $(\ttrue, \etruep)$\ProseOrTypeError; - \item annotating $\efalse$ in $\tenv$ results in $(\tfalse, \efalsep)$; - \item obtaining the lowest common ancestor of $\ttrue$ and $\tfalse$ results in $\vt$\ProseOrTypeError; - \item $\newe$ is the condition $\econdp$ with two options $\etruep$ and $\efalsep$, that is, $\ECond(\econdp, \etruep, \efalsep)$. -\end{itemize} - -\isempty{\subsection{Example}} - -\CodeSubsection{\ECondBegin}{\ECondEnd}{../Typing.ml} - -\subsection{Formally} -\begin{mathpar} -\inferrule{ - \annotateexpr{\tenv, \econd} \typearrow (\tcond, \econd') \OrTypeError\\\\ - \annotateexpr{\tenv, \etrue} \typearrow (\ttrue, \etrue') \OrTypeError\\\\ - \annotateexpr{\tenv, \efalse} \typearrow (\tfalse, \efalse') \OrTypeError\\\\ - \lca(\ttrue, \tfalse) \typearrow \vt \OrTypeError -}{ - { - \begin{array}{r} - \annotateexpr{\ECond(\econd, \etrue, \efalse)} \typearrow \\ - (\vt, \ECond(\econdp, \etruep, \efalsep)) - \end{array} - } -} -\end{mathpar} - -\isempty{\subsection{Comments}} -\lrmcomment{This is related to \identr{XZVT}.} - -\section{TypingRule.ESlice \label{sec:TypingRule.ESlice}} - -\subsection{Prose} -All of the following apply: -\begin{itemize} - \item $\ve$ denotes the slicing of expression $\vep$ by the slices $\slices$, that is, \\ - $\ESlice(\vep, \slices)$; - \item determining whether $\vep$ together with $\slices$ corresponds to a subprogram call - in $\tenv$ via $\reduceslicestocall$ yields a negative answer --- $\None$\ProseOrTypeError; - \item annotating the expression $\vep$ in $\tenv$ yields $(\tep,\vepp)$\ProseOrTypeError; - \item obtaining the \structure\ of $\tep$ in $\tenv$ yields $\structtep$\ProseOrTypeError; - \item $\structtep$ is either a bitvector or an integer; - \item obtaining the width of $\slices$ in $\tenv$ via $\sliceswidth$ yields $\vw$\ProseOrTypeError; - \item $\slicesp$ is the result of annotating $\slices$ in $\tenv$; - \item $\vt$ is the bitvector type of width $\vw$, that is, $\TBits(\vw, \emptylist)$; - \item $\newe$ is the slicing of expression $\vepp$ by the slices $\slicesp$, that is, \\ - $\ESlice(\vepp, \slicesp)$. -\end{itemize} - -\isempty{\subsection{Example}} - -\CodeSubsection{\ESliceBegin}{\ESliceEnd}{../Typing.ml} - -\subsection{Formally} -\begin{mathpar} -\inferrule{ - \reduceslicestocall(\tenv, \vep, \slices) \typearrow \None \OrTypeError\\\\ - \annotateexpr{\tenv, \vep} \typearrow (\tep, \vepp) \OrTypeError\\\\ - \tstruct(\tenv, \tep) \typearrow \structtep \OrTypeError\\\\ - \astlabel(\structtep) \in \{\TInt, \TBits\}\\ - \sliceswidth(\tenv, \slices) \typearrow \vw \OrTypeError\\\\ - \annotateslices(\tenv, \slices) \typearrow \slicesp \OrTypeError -}{ - \annotateexpr{\tenv, \overname{\ESlice(\vep, \slices)}{\ve}} \typearrow (\overname{\TBits(\vw, \emptylist)}{\vt}, \overname{\ESlice(\vepp, \slicesp)}{\newe}) -} -\end{mathpar} - -\subsection{Comments} - The width of \slices\ might be a symbolic expression if one of the - widths references a \texttt{let} identifier with a non-compile-time-constant - initializer expression. - - \lrmcomment{This is related to \identi{MJWM}.} - -\section{TypingRule.ESetter \label{sec:TypingRule.ESetter}} - -\subsection{Prose} -All of the following apply: -\begin{itemize} - \item $\ve$ denotes the slicing of expression $\vep$ by the slices $\slices$, that is, \\ - $\ESlice(\vep, \slices)$; - \item determining whether $\vep$ together with $\slices$ corresponds to a subprogram call - in $\tenv$ via $\reduceslicestocall$ yields a positive answer --- $\langle (\name, \vargs)\rangle$\ProseOrTypeError; - \item applying $\annotatecall$ to annotate the call with $(\tenv, \name, \vargs, \STSetter)$ - yields $(\nameone, \vargsone, \eqs, \langle\tty\rangle)$\ProseOrTypeError; - \item $\vt$ is $\tty$; - \item $\newe$ is the call expression $\ECall(\nameone, \vargsone, \eqs)$. -\end{itemize} - -\isempty{\subsection{Example}} - -\CodeSubsection{\ReduceSlicesToCallBegin}{\ReduceSlicesToCallEnd}{../Typing.ml} - -\subsection{Formally} -\begin{mathpar} -\inferrule{ - \reduceslicestocall(\tenv, \vep, \slices) \typearrow \langle(\name, \vargs)\rangle \OrTypeError\\\\ - \annotatecall(\tenv, \name, \vargs, \STSetter) \typearrow (\nameone, \vargsone, \eqs, \langle\tty\rangle) \OrTypeError\\ -}{ - \annotateexpr{\tenv, \overname{\ESlice(\vep, \slices)}{\ve}} \typearrow (\overname{\tty}{\vt}, \overname{\ECall(\nameone, \vargsone, \eqs)}{\newe}) -} -\end{mathpar} - -\isempty{\subsection{Comments}} - -\section{TypingRule.ECall \label{sec:TypingRule.ECall}} - -\subsection{Prose} -All of the following apply: -\begin{itemize} - \item $\ve$ denotes a call to a subprogram named $\name$ with arguments $\vargs$, that is, \\ $\ECall(\name, \vargs)$; - \item applying $\annotatecall$ to $\name$, $\vargs$, and $\STFunction$ in $\tenv$ - annotates the call of that subprogram in $\tenv$ as a function (annotating calls is defined in Chapter~\ref{chap:TypingSubprogramCalls}) - and yields $(\namep, \vargsp, \eqsp, \langle \vt \rangle)$\ProseOrTypeError. - Notice that passing $\STFunction$ to $\annotatecall$ checks that $\name$ is not a procedure and that a value is indeed returned; - \item $\newe$ is the call to the subprogram named $\namep$ with arguments $\vargsp$ - and parameters $\eqsp$, that is, $\ECall(\namep, \vargsp, \eqsp)$. -\end{itemize} - -\isempty{\subsection{Example}} - -\CodeSubsection{\ECallBegin}{\ECallEnd}{../Typing.ml} - -\subsection{Formally} -\begin{mathpar} -\inferrule{ - \annotatecall(\tenv, \name, \vargs, \STFunction) \typearrow (\namep, \vargsp, \eqsp, \langle \vt \rangle) \OrTypeError -}{ - \annotateexpr{\tenv, \overname{\ECall(\name, \vargs)}{\ve}} \typearrow (\vt, \overname{\ECall(\namep, \vargsp, \eqsp)}{\newe}) -} -\end{mathpar} - -\isempty{\subsection{Comments}} -\lrmcomment{This is related to \identd{CFYP}, \identr{BQJG}.} - -\section{TypingRule.EGetArray \label{sec:TypingRule.EGetArray}} -\hypertarget{def-arrayaccess}{} -\begin{definition}[Array Access] -We refer to a right-hand-side expression of the form $b[i]$, -where $b, i$ are subexpressions, as an \arrayaccess\ expression. -We refer to $b$ and $i$ as the \emph{base} -and the $\emph{index}$ subexpressions, respectively. - -In the untyped AST, an \arrayaccess\ expression is represented by \\ -$\ESlice(\vbase, [\vindex])$, whereas in the typed AST, -it is represented by \\ -$\EGetArray(\vbase, \vindex)$ -\end{definition} - -\subsection{Prose} -All of the following apply: -\begin{itemize} - \item $\ve$ denotes the slicing of expression $\vep$ by the slices $\slices$; - \item determining whether $\vep$ together with $\slices$ corresponds to a subprogram call - in $\tenv$ via $\reduceslicestocall$ yields a negative answer --- $\None$\ProseOrTypeError; - \item $(\tep,\vepp)$ is the result of annotating the expression $\vep$ in $\tenv$; - \item $\tep$ has the structure of an array with index $\size$ and element type $\tty$'; - \item One of the following applies: - \begin{itemize} - \item All of the following apply (\textsc{okay}): - \begin{itemize} - \item $\slices$ is a list containing a single slice for an expression $\eindex$, that is, $[\SliceSingle(\eindex)]$; - \item annotating the expression $\eindex$ in $\tenv$ yields $(\tindexp, \eindexp)$\ProseOrTypeError; - \item determining the type of the array index for $\size$ in $\tenv$ via \\ $\typeofarraylength$ - yields $\wantedtindex$; - \item determining whether $\tindexp$ \typesatisfies\ $\wantedtindex$ yields \\ - $\True$\ProseOrTypeError; - \item $\vt$ is $\ttyp$; - \item $\newe$ is the \arrayaccess\ expression for $\vepp$ and index $\eindexp$, that is, $\EGetArray(\vepp, \eindexp)$. - \end{itemize} - - \item All of the following apply (\textsc{error}): - \begin{itemize} - \item $\slices$ is not a list containing a single slice for an expression $\eindex$; - \item the result is a type error indicating that an array must be accessed with a slice corresponding - to a single index expression. - \end{itemize} - \end{itemize} -\end{itemize} - -\isempty{\subsection{Example}} - -\CodeSubsection{\EGetArrayBegin}{\EGetArrayEnd}{../Typing.ml} - -\subsection{Formally} -\begin{mathpar} -\inferrule[okay]{ - \reduceslicestocall(\tenv, \vep, \slices) \typearrow \None \OrTypeError\\\\ - \annotateexpr{\tenv, \ve} \typearrow (\tep, \vepp) \OrTypeError\\\\ - \tstruct(\tenv, \tep) \typearrow \TArray(\size, \ttyp) \OrTypeError\\\\ - \commonprefixline\\\\ - \slices = [ \SliceSingle(\eindex) ]\\ - \annotateexpr{\tenv, \eindex} \typearrow (\tindexp, \eindexp) \OrTypeError\\\\ - \typeofarraylength(\tenv, \size) \typearrow \wantedtindex\\ - \checktypesat(\tenv, \tindexp, \wantedtindex) \typearrow \True \OrTypeError\\ -}{ - \annotateexpr{\tenv, \overname{\ESlice(\vep, \slices)}{\ve}} \typearrow (\overname{\ttyp}{\vt}, \overname{\EGetArray(\vepp, \eindexp)}{\newe}) -} -\and -\inferrule[error]{ - \reduceslicestocall(\tenv, \vep, \slices) \typearrow \None \OrTypeError\\\\ - \annotateexpr{\tenv, \ve} \typearrow (\tep, \vepp) \OrTypeError\\\\ - \tstruct(\tenv, \tep) \typearrow \TArray(\size, \ttyp) \OrTypeError\\\\ - \commonprefixline\\\\ - \slices \neq [ \SliceSingle(\Ignore) ]\\ -}{ - \annotateexpr{\tenv, \overname{\ESlice(\vep, \slices)}{\ve}} \typearrow \TypeErrorVal{IllegalArraySlice} -} -\end{mathpar} - -\isempty{\subsection{Comments}} - -\section{TypingRule.ESliceOrEGetArrayError \label{sec:TypingRule.ESliceOrEGetArrayError}} - -\subsection{Prose} -All of the following apply: -\begin{itemize} - \item $\ve$ denotes the slicing of expression $\vep$ by the slices $\slices$; - \item determining whether $\vep$ together with $\slices$ corresponds to a subprogram call - in $\tenv$ via $\reduceslicestocall$ yields a negative answer --- $\None$\ProseOrTypeError; - \item $(\tep,\vepp)$ is the result of annotating the expression $\vep$ in $\tenv$; - \item $\tep$ has the structure $\vtp$; - \item $\vtp$ is neither an integer type, a bitvector type, or an array type; - \item the result is an error indicating that the type of $\vep$ is inappropriate for slicing. -\end{itemize} - -\isempty{\subsection{Example}} - -\CodeSubsection{\ESliceOrEGetArrayErrorBegin}{\ESliceOrEGetArrayErrorEnd}{../Typing.ml} - -\subsection{Formally} -\begin{mathpar} -\inferrule{ - \reduceslicestocall(\tenv, \vep, \slices) \typearrow \None \OrTypeError\\\\ - \annotateexpr{\tenv, \vep} \typearrow (\tep, \vepp) \OrTypeError\\\\ - \tstruct(\tenv, \tep) \typearrow \vtp\\ - \astlabel(\vtp) \not\in \{\TInt, \TBits, \TArray\} -}{ - \annotateexpr{\tenv, \overname{\ESlice(\vep, \slices)}{\ve}} \typearrow \TypeErrorVal{IllegalSliceType} -} -\end{mathpar} - -\isempty{\subsection{Comments}} - -\section{TypingRule.ERecord \label{sec:TypingRule.ERecord}} - -\subsection{Prose} -All of the following apply: -\begin{itemize} - \item $\ve$ denotes the record construction expression (which is also used for creating exceptions) of type $\tty$ with fields $\fields$, - that is, $\ERecord(\tty, \vfields)$; - \item obtaining the \underlyingtype\ of $\tty$ in $\tenv$ yields $\ttyanon$\ProseOrTypeError; - \item checking that $\ttyanon$ is a \structuredtype\ yields $\True$\ProseOrTypeError;% \ProseTerminateAs{\TypeErrorVal{\ExpectedStructuredType}}; - \item $\ttyanon$ is a \structuredtype\ with a list of $\field$ elements (consisting of a field name and a field type); - \item obtaining the list of field names from $\vfields$ yields the list of identifiers \\ - $\initializedfields$; - \item obtaining the list of field names from $\fieldtypes$ yields the list of identifiers $\names$; - \item checking whether the set of identifiers in $\names$ is equal to the set of identifiers in $\initializedfields$ - yields $\True$\ProseOrTypeError; - \item checking that the list $\initializedfields$ does not contain duplicates yields \\ - $\True$\ProseOrTypeError; - \item applying $\annotatefieldinit$ to annotate each $\field$ element $(\name,\vep)$ of \\ - $\vfields$ in $\tenv$ yields $(\name,\ve_\name)$\ProseOrTypeError; - \item define $\fieldsp$ as the list containing $(\name,\ve_\name)$ for each $\field$ element $(\name,\vep)$ of $\vfields$; - \item $\vt$ is $\tty$; - \item $\newe$ is the record expression with type $\tty$ and field initializers $\fieldsp$, that is, $\ERecord(\tty, \fieldsp)$; -\end{itemize} - -\isempty{\subsection{Example}} - -\CodeSubsection{\ERecordBegin}{\ERecordEnd}{../Typing.ml} - -\subsection{Formally} -\begin{mathpar} -\inferrule{ - \checktrans{\astlabel(\tty) = \TNamed}{NamedTypeExpected} \checktransarrow \True \OrTypeError\\\\ - \makeanonymous(\tenv, \tty) \typearrow \ttyanon \OrTypeError\\\\ - \checktrans{\astlabel(\ttyanon) \in \{\TRecord, \TException\}}{\ExpectedStructuredType} \typearrow \True\OrTypeError\\\\ - \ttyanon \eqname L(\fieldtypes)\\ - \initializedfields \eqdef \{\name \;|\; (\name, \Ignore)\in\vfields\}\\ - \names \eqdef \fieldnames(\fieldtypes)\\ - \checktrans{\{\names\} = \{\initializedfields\}}{\MissingFieldInitializer} \typearrow \True \OrTypeError\\\\ - \checknoduplicates(\initializedfields) \typearrow \True \OrTypeError\\\\ - { - \begin{array}{r} - (\name, \vep) \in \vfields: \annotatefieldinit(\tenv, (\name, \vep), \fieldtypes) \typearrow \\ - (\name, \ve_\name) \OrTypeError - \end{array} - }\\ - \fieldsp \eqdef [(\name, \vep) \in \fields : (\name, \ve_\name)] -}{ - \annotateexpr{\tenv, \overname{\ERecord(\tty, \vfields)}{\ve}} \typearrow (\overname{\tty}{\vt}, \overname{\ERecord(\tty, \fieldsp)}{\newe}) -} -\end{mathpar} - -\isempty{\subsection{Comments}} -\lrmcomment{This is related to \identr{WBCQ}.} - -\section{TypingRule.EGetRecordField \label{sec:TypingRule.EGetRecordField}} -\subsection{Prose} -All of the following apply: -\begin{itemize} - \item $\ve$ denotes the access of field $\fieldname$ in the value represented by the expression $\veone$, that is, $\EGetField(\veone, \fieldname)$; - \item annotating the expression $\veone$ in $\tenv$ yields $(\vteone, \vetwo)$\ProseOrTypeError; - \item obtaining the \underlyingtype\ of $\vteone$ yields $\vtetwo$\ProseOrTypeError; - % \item checking whether the field access with expression $\vtetwo$ and $\fieldname$ represents a call yields $\None$\ProseOrTypeError; - \item $\vtetwo$ is a \structuredtype\ with fields $\fields$; - \item the field $\fieldname$ is associated with the type $\vt$ in $\fields$ - \item $\newe$ is the access of field $\fieldname$ on the record or exception object $\vetwo$, that is, $\EGetField(\vetwo, \fieldname)$. -\end{itemize} - -\isempty{\subsection{Example}} - -\CodeSubsection{\EGetRecordFieldBegin}{\EGetRecordFieldEnd}{../Typing.ml} - -\subsection{Formally} -\begin{mathpar} -\inferrule{ - \annotateexpr{\tenv, \veone} \typearrow (\vteone, \vetwo) \OrTypeError\\\\ - \makeanonymous(\tenv, \vteone) \typearrow \vtetwo \OrTypeError\\\\ - % \tododefine{reduce\_field\_to\_call}(\tenv, \vtetwo, \fieldname) \typearrow \None \OrTypeError\\\\ - \vtetwo \eqname L(\fields)\\ - L \in \{\TRecord, \TException\}\\ - \assocopt(\fields, \fieldname) \typearrow \langle \vt\rangle -}{ - \annotateexpr{\tenv, \EGetField(\veone, \fieldname)} \typearrow (\vt, \EGetField(\vetwo, \fieldname)) -} -\end{mathpar} - -\isempty{\subsection{Comments}} - -\section{TypingRule.EGetBadRecordField \label{sec:TypingRule.EGetBadRecordField}} - -\subsection{Prose} -All of the following apply: -\begin{itemize} - \item $\ve$ denotes the access of field $\fieldname$ in the value represented by the expression $\veone$, that is, $\EGetField(\veone, \fieldname)$; - \item annotating the expression $\veone$ in $\tenv$ yields $(\vteone, \vetwo)$\ProseOrTypeError; - \item obtaining the \underlyingtype\ of $\vteone$ yields $\vtetwo$\ProseOrTypeError; - % \item checking whether the field access with expression $\vtetwo$ and $\fieldname$ represents a call yields $\None$\ProseOrTypeError; - \item $\vtetwo$ is a \structuredtype\ with fields $\fields$; - \item the field $\fieldname$ is not associated with any type in $\fields$ - \item the result is a type error indicating the missing field. -\end{itemize} - -\isempty{\subsection{Example}} - -\CodeSubsection{\EGetBadRecordFieldBegin}{\EGetBadRecordFieldEnd}{../Typing.ml} - -\subsection{Formally} -\begin{mathpar} -\inferrule{ - \annotateexpr{\tenv, \veone} \typearrow (\vteone, \vetwo) \OrTypeError\\\\ - \makeanonymous(\tenv, \vteone) \typearrow \vtetwo \OrTypeError\\\\ - % \tododefine{reduce\_field\_to\_call}(\tenv, \vtetwo, \fieldname) \typearrow \None \OrTypeError\\\\ - \vtetwo \eqname L(\fields)\\ - L \in \{\TRecord, \TException\}\\ - \assocopt(\fields, \fieldname) \typearrow \None -}{ - \annotateexpr{\tenv, \EGetField(\veone, \fieldname)} \typearrow \TypeErrorVal{FieldDoesNotExist} -} -\end{mathpar} - -\isempty{\subsection{Comments}} - -\section{TypingRule.EGetBadBitField \label{sec:TypingRule.EGetBadBitField}} - -\subsection{Prose} -All of the following apply: -\begin{itemize} - \item $\ve$ denotes the access of field $\fieldname$ in the value represented by the expression $\veone$, that is, $\EGetField(\veone, \fieldname)$; - \item annotating the expression $\veone$ in $\tenv$ yields $(\vteone, \vetwo)$\ProseOrTypeError; - \item obtaining the \underlyingtype\ of $\vteone$ yields $\vtetwo$\ProseOrTypeError; - % \item checking whether the field access with expression $\vtetwo$ and $\fieldname$ represents a call yields $\None$\ProseOrTypeError; - \item $\vtetwo$ is a bitvector type with bit fields $\bitfields$; - \item the field $\fieldname$ is not found in $\bitfields$ - \item the result is a type error indicating the missing field. -\end{itemize} - -\isempty{\subsection{Example}} - -\CodeSubsection{\EGetBadBitFieldBegin}{\EGetBadBitFieldEnd}{../Typing.ml} - -\begin{mathpar} -\inferrule{ - \annotateexpr{\tenv, \veone} \typearrow (\vteone, \vetwo) \OrTypeError\\\\ - \makeanonymous(\tenv, \vteone) \typearrow \vtetwo \OrTypeError\\\\ - % \tododefine{reduce\_field\_to\_call}(\tenv, \vtetwo, \fieldname) \typearrow \None \OrTypeError\\\\ - \vtetwo \eqname \TBits(\Ignore, \bitfields)\\ - \findbitfieldopt(\bitfields, \fieldname) \typearrow \None -}{ - \annotateexpr{\tenv, \overname{\EGetField(\veone, \fieldname)}{\ve}} \typearrow \TypeErrorVal{FieldDoesNotExist} -} -\end{mathpar} - -\isempty{\subsection{Comments}} - -\section{TypingRule.EGetBitField \label{sec:TypingRule.EGetBitField}} - -\subsection{Prose} -All of the following apply: -\begin{itemize} - \item $\ve$ denotes the access of field $\fieldname$ in the value represented by the expression $\veone$, that is, $\EGetField(\veone, \fieldname)$; - \item annotating the expression $\veone$ in $\tenv$ yields $(\vteone, \vetwo)$\ProseOrTypeError; - \item obtaining the \underlyingtype\ of $\vteone$ yields $\vtetwo$\ProseOrTypeError; - % \item checking whether the field access with expression $\vtetwo$ and $\fieldname$ represents a call yields $\None$\ProseOrTypeError; - \item $\vtetwo$ is a bitvector type with bit fields $\bitfields$; - \item $\fieldname$ is declared in $\bitfields$ with a slice list $\slices$, that is, \\ $\BitFieldSimple(\Ignore, \slices)$; - \item $\vethree$ denotes the slicing of the expression \vetwo\ by the slices $\slices$, that is, \\ $\ESlice(\vetwo, \slices)$; - \item annotating $\vethree$ in $\tenv$ yields $(\vt, \newe)$\ProseOrTypeError. -\end{itemize} - -\isempty{\subsection{Example}} - -\CodeSubsection{\EGetBitFieldBegin}{\EGetBitFieldEnd}{../Typing.ml} - -\subsection{Formally} -\begin{mathpar} -\inferrule{ - \annotateexpr{\tenv, \veone} \typearrow (\vteone, \vetwo) \OrTypeError\\\\ - \makeanonymous(\tenv, \vteone) \typearrow \vtetwo \OrTypeError\\\\ - % \tododefine{reduce\_field\_to\_call}(\tenv, \vtetwo, \fieldname) \typearrow \None \OrTypeError\\\\ - \vtetwo \eqname \TBits(\Ignore, \bitfields)\\ - \findbitfieldopt(\bitfields, \fieldname) \typearrow \langle \BitFieldSimple(\Ignore, \slices)\rangle\\ - \vethree \eqdef \ESlice(\vetwo, \slices)\\ - \annotateexpr{\tenv, \vethree} \typearrow (\vt, \newe) \OrTypeError -}{ - \annotateexpr{\tenv, \overname{\EGetField(\veone, \fieldname)}{\ve}} \typearrow (\vt, \newe) -} -\end{mathpar} - -\isempty{\subsection{Comments}} - -\section{TypingRule.EGetBitFieldNested \label{sec:TypingRule.EGetBitFieldNested}} - -\subsection{Prose} -All of the following apply: -\begin{itemize} - \item $\ve$ denotes the access of field $\fieldname$ in the value represented by the expression $\veone$, that is, $\EGetField(\veone, \fieldname)$; - \item annotating the expression $\veone$ in $\tenv$ yields $(\vteone, \vetwo)$\ProseOrTypeError; - \item obtaining the \underlyingtype\ of $\vteone$ yields $\vtetwo$\ProseOrTypeError; - % \item checking whether the field access with expression $\vtetwo$ and $\fieldname$ represents a call yields $\None$\ProseOrTypeError; - \item $\vtetwo$ is a bitvector type with bit fields $\bitfields$; - \item $\fieldname$ is declared in $\bitfields$ with a slice list $\slices$ and nested bitfields $\bitfieldsp$, that is, - $\BitFieldNested(\Ignore, \slices, \bitfieldsp)$; - \item $\vethree$ denotes the slicing of the expression \vetwo\ by the slices $\slices$, that is, \\ $\ESlice(\vetwo, \slices)$; - \item annotating $\vethree$ in $\tenv$ yields $(\vtefour, \newe)$\ProseOrTypeError; - \item $\vtefour$ is a bitvector type with length expression $\width$, that is, $\TBits(\width, \Ignore)$; - \item $\vt$ is a bitvector type with length expression $\width$ and bitfields $\bitfieldsp$. -\end{itemize} - -\isempty{\subsection{Example}} - -\CodeSubsection{\EGetBitFieldNestedBegin}{\EGetBitFieldNestedEnd}{../Typing.ml} - -\subsection{Formally} -\begin{mathpar} -\inferrule{ - \annotateexpr{\tenv, \veone} \typearrow (\vteone, \vetwo) \OrTypeError\\\\ - \makeanonymous(\tenv, \vteone) \typearrow \vtetwo \OrTypeError\\\\ - % \tododefine{reduce\_field\_to\_call}(\tenv, \vtetwo, \fieldname) \typearrow \None \OrTypeError\\\\ - \vtetwo \eqname \TBits(\Ignore, \bitfields)\\ - { - \begin{array}{r} - \findbitfieldopt(\bitfields, \fieldname) \typearrow \\ \langle \BitFieldNested(\Ignore, \slices, \bitfieldsp)\rangle - \end{array} - }\\ - \vethree \eqdef \ESlice(\vetwo, \slices)\\ - \annotateexpr{\tenv, \vethree} \typearrow (\vtefour, \newe) \OrTypeError\\\\ - \vtefour \eqname \TBits(\width, \Ignore)\\ - \vt \eqdef \TBits(\width, \bitfieldsp) -}{ - \annotateexpr{\tenv, \overname{\EGetField(\veone, \fieldname)}{\ve}} \typearrow (\vt, \newe) -} -\end{mathpar} - -\isempty{\subsection{Comments}} - -\section{TypingRule.EGetBitFieldTyped \label{sec:TypingRule.EGetBitFieldTyped}} - -\subsection{Prose} -All of the following apply: -\begin{itemize} - \item $\ve$ denotes the access of field $\fieldname$ in the value represented by the expression $\veone$, that is, $\EGetField(\veone, \fieldname)$; - \item annotating the expression $\veone$ in $\tenv$ yields $(\vteone, \vetwo)$\ProseOrTypeError; - \item obtaining the \underlyingtype\ of $\vteone$ yields $\vtetwo$\ProseOrTypeError; - % \item checking whether the field access with expression $\vtetwo$ and $\fieldname$ represents a call yields $\None$\ProseOrTypeError; - \item $\vtetwo$ is a bitvector type with bit fields $\bitfields$; - \item $\fieldname$ is declared in $\bitfields$ with a slice list $\slices$ and typed-bitfield with type $\vt$ that is, - $\BitFieldType(\Ignore, \slices, \vt)$; - \item $\vethree$ denotes the slicing of the expression \vetwo\ by the slices $\slices$, that is, \\ $\ESlice(\vetwo, \slices)$; - \item annotating $\vethree$ in $\tenv$ yields $(\vtefour, \newe)$\ProseOrTypeError; - \item determining whether $\vtefour$ \typesatisfies\ $\vt$ yields $\True$\ProseOrTypeError. -\end{itemize} - -\isempty{\subsection{Example}} - -\CodeSubsection{\EGetBitFieldTypedBegin}{\EGetBitFieldTypedEnd}{../Typing.ml} - -\subsection{Formally} -\begin{mathpar} -\inferrule{ - \annotateexpr{\tenv, \veone} \typearrow (\vteone, \vetwo) \OrTypeError\\\\ - \makeanonymous(\tenv, \vteone) \typearrow \vtetwo \OrTypeError\\\\ - % \tododefine{reduce\_field\_to\_call}(\tenv, \vtetwo, \fieldname) \typearrow \None \OrTypeError\\\\ - \vtetwo \eqname \TBits(\Ignore, \bitfields)\\ - \findbitfieldopt(\bitfields, \fieldname) \typearrow \langle \BitFieldType(\Ignore, \slices, \vt)\rangle\\ - \vethree \eqdef \ESlice(\vetwo, \slices)\\ - \annotateexpr{\tenv, \vethree} \typearrow (\vtefour, \newe) \OrTypeError\\\\ - \checktypesat(\tenv, \vtefour, \vt) \typearrow \True \OrTypeError -}{ - \annotateexpr{\tenv, \overname{\EGetField(\veone, \fieldname)}{\ve}} \typearrow (\vt, \newe) -} -\end{mathpar} - -\isempty{\subsection{Comments}} - -\section{TypingRule.EGetTupleItem \label{sec:TypingRule.EGetTupleItem}} - -\subsection{Prose} -All of the following apply: -\begin{itemize} - \item $\ve$ denotes the access of field $\fieldname$ in the value represented by the expression $\veone$, that is, $\EGetField(\veone, \fieldname)$; - \item annotating the expression $\veone$ in $\tenv$ yields $(\vteone, \vetwo)$\ProseOrTypeError; - \item obtaining the \underlyingtype\ of $\vteone$ yields $\vtetwo$\ProseOrTypeError; - % \item checking whether the field access with expression $\vtetwo$ and $\fieldname$ represents a call yields $\None$\ProseOrTypeError; - \item $\vtetwo$ is tuple type with list of types $\tys$, that is, $\TTuple(\tys)$; - \item $\fieldname$ is an identifier with the prefix \texttt{item} and the constant $\vindex$; - \item determining whether $\vindex$ is between $0$ and the number of types in $\tys$, inclusive, yields $\True$\ProseOrTypeError; - \item $\vt$ is the type at position $\vindex$ of $\tys$; - \item $\newe$ is the expression for obtaining the item at index $\vindex$ from the expression $\vetwo$, that is, $\EGetItem(\vetwo, \vindex)$. -\end{itemize} - -\isempty{\subsection{Example}} - -\CodeSubsection{\EGetTupleItemBegin}{\EGetTupleItemEnd}{../Typing.ml} - -\subsection{Formally} -\begin{mathpar} -\inferrule{ - \annotateexpr{\tenv, \veone} \typearrow (\vteone, \vetwo) \OrTypeError\\\\ - \makeanonymous(\tenv, \vteone) \typearrow \vtetwo \OrTypeError\\\\ - % \tododefine{reduce\_field\_to\_call}(\tenv, \vtetwo, \fieldname) \typearrow \None \OrTypeError\\\\ - \vtetwo \eqname \TTuple(\tys)\\ - \fieldname \eqname \texttt{"item"}\\ - \checktrans{0 \leq \vindex \leq \listlen{\tys}}{IndexOutOfRange} \checktransarrow \True \OrTypeError\\\\ - \vt \eqdef \tys[\vindex]\\ - \newe \eqdef \EGetItem(\vetwo, \vindex) -}{ - \annotateexpr{\tenv, \overname{\EGetField(\veone, \fieldname)}{\ve}} \typearrow (\vt, \newe) -} -\end{mathpar} - -\isempty{\subsection{Comments}} - -\section{TypingRule.EGetBadField \label{sec:TypingRule.EGetBadField}} - -\subsection{Prose} -All of the following apply: -\begin{itemize} - \item $\ve$ denotes the access of field $\fieldname$ in the value represented by the expression $\veone$, that is, $\EGetField(\veone, \fieldname)$; - \item annotating the expression $\veone$ in $\tenv$ yields $(\vteone, \vetwo)$\ProseOrTypeError; - \item obtaining the \underlyingtype\ of $\vteone$ yields $\vtetwo$\ProseOrTypeError; - % \item checking whether the field access with expression $\vtetwo$ and $\fieldname$ represents a call yields $\None$\ProseOrTypeError; - \item $\vtetwo$ is neither one of the following types: record, exception, bitvector, or tuple; - \item the result is an error indicating that the type of $\veone$ is inappropriate for accessing the field $\fieldname$. -\end{itemize} - -\isempty{\subsection{Example}} - -\CodeSubsection{\EGetBadFieldBegin}{\EGetBadFieldEnd}{../Typing.ml} - -\subsection{Formally} -\begin{mathpar} -\inferrule{ - \annotateexpr{\tenv, \veone} \typearrow (\vteone, \vetwo) \OrTypeError\\\\ - \makeanonymous(\tenv, \vteone) \typearrow \vtetwo \OrTypeError\\\\ - % \tododefine{reduce\_field\_to\_call}(\tenv, \vtetwo, \fieldname) \typearrow \None \OrTypeError\\\\ - \astlabel(\vtetwo) \not\in \{\TRecord, \TException, \TBits, \TTuple\} -}{ - \annotateexpr{\tenv, \overname{\EGetField(\veone, \fieldname)}{\ve}} \typearrow \TypeErrorVal{ConflictingTypes} -} -\end{mathpar} - -\isempty{\subsection{Comments}} - -\section{TypingRule.EConcat \label{sec:TypingRule.EConcat}} - -\subsection{Prose} -All of the following apply: -\begin{itemize} - \item $\ve$ denotes the concatenation of a non-empty list of expressions $\vli$, that is, \\ $\EConcat(\vli)$; - \item annotating each expression $\vle[i]$ in $\tenv$, for $i=1..k$, yields $(\vt_i, \ve_i$)\ProseOrTypeError; - \item $\ves$ is the list of expressions $\ve_i$, for $i=1..k$; - \item obtaining the bitvector width of $\vt_i$ in $\tenv$ (which also checks that $\vt_i$ is a bitvector type), - for $i=1..k$, yields $\vw_i$\ProseOrTypeError; - \item to obtain the (symbolic) width of the resulting bitvector, first define $\widthsum_1$ to be $\vw_1$; - \item then define $\widthsum_i$, for $i=2..k$, to be obtained by reducing the expression that sums \\ $\widthsum_{i-1}$ with the width $\vw_i$; - \item $\vt$ is the bitvector of length $\widthsum_k$ and the empty bitfield list, that is, \\ $\TBits(\widthsum_k, \emptylist)$; - \item $\newe$ is the concatenation expression for $\ves$, that is, $\EConcat(\ves)$. -\end{itemize} - -\isempty{\subsection{Example}} - -\CodeSubsection{\EConcatBegin}{\EConcatEnd}{../Typing.ml} - -\subsection{Formally} -\begin{mathpar} -\inferrule{ - i=1..k: \annotateexpr{\tenv, \vli[i]} \typearrow (\vt_i, \ve_i) \OrTypeError\\\\ - \vts \eqdef [i=1..k: \vt_i]\\ - \ves \eqdef [i=1..k: \ve_i]\\ - i=1..k: \getbitvectorwidth(\tenv, \vt_i) \typearrow \vw_i \OrTypeError\\\\ - \widthsum_1 \eqdef \vw_1\\ - i=2..k: \normalize(\tenv, \EBinop(\PLUS, \widthsum_{i-1}, \vw_i)) \typearrow \widthsum_i -}{ - \annotateexpr{\tenv, \EConcat(\vli)} \typearrow (\TBits(\widthsum_k, \emptylist), \EConcat(\ves)) -} -\end{mathpar} - -\subsection{Comments} -The sum of the widths of the bitvector types~\texttt{ts} might be a symbolic -expression that is unresolvable to an integer. For example: -\VerbatimInput{../tests/ASLTypingReference.t/TypingRule.EConcatUnresolvableToInteger.asl} - -\lrmcomment{This is related to \identr{NYNK} and \identr{KCZS}.} - -\section{TypingRule.ETuple \label{sec:TypingRule.ETuple}} - -\subsection{Prose} -All of the following apply: -\begin{itemize} - \item $\ve$ denotes a tuple expression with list of expressions $\vli$, that is, $ \ETuple(\vli)$; - \item annotating each expression $\vle[i]$ in $\tenv$, for $i=1..k$, yields $(\vt_i, \ve_i$)\ProseOrTypeError; - \item $\vt$ is the tuple type with list of types $\vt_i$, for $i=1..k$; - \item $\newe$ is tuple expression over list of expressions $\ve_i$, for $i=1..k$. -\end{itemize} - -\isempty{\subsection{Example}} - -\CodeSubsection{\ETupleBegin}{\ETupleEnd}{../Typing.ml} - -\subsection{Formally} -\begin{mathpar} -\inferrule{ - i=1..k: \annotateexpr{\tenv, \vle[i]} \typearrow (\vt_i, \ve_i) \OrTypeError -}{ - \annotateexpr{\tenv, \ETuple(\vli)} \typearrow (\TTuple(\vt_{1..k}), \ETuple(\ve_{1..k})) -} -\end{mathpar} - -\isempty{\subsection{Comments}} - -\section{TypingRule.EUnknown \label{sec:TypingRule.EUnknown}} - -\subsection{Prose} -All of the following apply: -\begin{itemize} - \item $\ve$ denotes an expression \UNKNOWN\ of type $\tty$, that is, $\EUnknown(\tty)$; - \item annotating the type $\tty$ in $\tenv$ yields $\ttyone$\ProseOrTypeError; - \item obtaining the \structure\ of $\ttyone$ in $\tenv$ yields $\ttytwo$\ProseOrTypeError; - \item $\vt$ is $\ttyone$; - \item $\newe$ is an expression \UNKNOWN\ of type $\ttytwo$, that is, $\EUnknown(\ttytwo)$. -\end{itemize} - -\isempty{\subsection{Example}} - -\CodeSubsection{\EUnknownBegin}{\EUnknownEnd}{../Typing.ml} - -\subsection{Formally} -\begin{mathpar} -\inferrule{ - \annotatetype{\tenv, \tty} \typearrow \ttyone \OrTypeError\\\\ - \tstruct(\tenv, \ttyone) \typearrow \ttytwo \OrTypeError -}{ - \annotateexpr{\tenv, \EUnknown(\tty)} \typearrow (\ttyone, \EUnknown(\ttytwo)) -} -\end{mathpar} - -\isempty{\subsection{Comments}} - -\section{TypingRule.EPattern \label{sec:TypingRule.EPattern}} - -\subsection{Prose} -All of the following apply: -\begin{itemize} - \item $\ve$ denotes a pattern expression to test whether $\veone$ matches the pattern $\vpat$, that is, \\ $\EPattern(\veone, \vpat)$; - \item annotating the expression $\veone$ in $\tenv$ yields $(\vtetwo, \vetwo)$\ProseOrTypeError; - \item applying $\annotatepattern$ to $\vtetwo$ and $\vpat$ in $\tenv$ yields $\vpatp$\ProseOrTypeError; - \item $\vt$ is $\TBool$; - \item $\newe$ denotes whether the expression $\vetwo$ matches $\vpatp$, that is, $\EPattern(\vetwo, \vpatp)$. -\end{itemize} - -\isempty{\subsection{Example}} - -\CodeSubsection{\EPatternBegin}{\EPatternEnd}{../Typing.ml} - -\subsection{Formally} -\begin{mathpar} -\inferrule{ - \annotateexpr{\tenv, \veone} \typearrow (\vtetwo, \vetwo) \OrTypeError\\\\ - \annotatepattern(\tenv, \vtetwo, \vpat) \typearrow \vpatp \OrTypeError -}{ - \annotateexpr{\tenv, \overname{\EPattern(\veone, \vpat)}{\ve}} \typearrow (\overname{\TBool}{\vr}, \overname{\EPattern(\vetwo, \vpatp)}{\newe}) -} -\end{mathpar} - -\isempty{\subsection{Comments}} - -\section{TypingRule.ATC \label{sec:TypingRule.ATC}} -\subsection{Prose} -All of the following apply: -\begin{itemize} - \item $\ve$ denotes an asserting type conversion with expression $\vep$ and type $\tty$, that is $\EATC(\vep, \tty)$; - \item annotating the expression $\vep$ in $\tenv$ yields $(\vt, \vepp)$\ProseOrTypeError; - \item obtaining the \structure\ of $\vt$ in $\tenv$ yields $\vtstruct$\ProseOrTypeError; - \item annotating the type $\tty$ in $\tenv$ yields $\tty'$\ProseOrTypeError; - \item obtaining the \structure\ of $\tty'$ in $\tenv$ yields $\vtystruct$\ProseOrTypeError; - \item applying $\checkatc$ to $\vtstruct$ and $\vtystruct$ in $\tenv$ to check whether the type assertion - will always fail yields $\True$\ProseOrTypeError; - \item checking whether $\vt$ \subtypesatisfies\ $\ttyp$ in $\tenv$ yields $\vb$\ProseOrTypeError; - \item $\newe$ is $\EATC(\ttyp, \vepp)$ if $\vb$ is $\True$ and $\vepp$ otherwise; - \item $\vt$ is $\ttyp$. -\end{itemize} - -\isempty{\subsection{Example}} - -\CodeSubsection{\ATCBegin}{\ATCEnd}{../Typing.ml} - -\subsection{Formally} -\begin{mathpar} -\inferrule[type\_equal]{ - \annotateexpr{\tenv, \vep} \typearrow (\vt, \vepp) \OrTypeError\\\\ - \tstruct(\tenv, \vt) \typearrow \vtstruct \OrTypeError\\\\ - \annotatetype{\tenv, \tty} \typearrow \ttyp \OrTypeError\\\\ - \tstruct(\tenv, \ttyp) \typearrow \vtystruct \OrTypeError\\\\ - \checkatc(\tenv, \vtstruct, \vtystruct) \typearrow \True \OrTypeError\\\\ - \subtypesat(\tenv, \vt, \ttyp) \typearrow \vb \OrTypeError\\\\ - \newe \eqdef \choice{\vb}{\EATC(\ttyp, \vepp)}{\vepp} -}{ - \annotateexpr{\tenv, \overname{\EATC(\vep, \tty)}{\ve}} \typearrow (\overname{\ttyp}{\vt}, \newe) -} -\end{mathpar} - -\isempty{\subsection{Comments}} -\lrmcomment{ - This is related to \identr{VBLL}, \identi{KRLL}, \identg{PFRQ}, \identi{XVBG}, - \identr{GYJZ}, \identi{SZVF}, \identr{PZZJ}, \identr{YCPX}, \identi{ZLBW}, - \identi{TCST}, \identi{CGRH}, \identi{YJBB}. -} - -\hypertarget{def-annotateliteral}{} -\section{TypingRule.Lit \label{sec:TypingRule.Lit}} - -Annotating literals is done via the helper function -\[ - \annotateliteral{\overname{\literal}{\vl}} \aslto \overname{\ty}{\vt} -\] -which we use in this chapter for TypingRule.ELit as well as in subsequent chapters. -\subsection{Prose} -The result of annotating a literal $\vl$ is $\vt$ and one of the following applies: -\begin{itemize} -\item (\texttt{int}): $\vl$ is an integer literal $\vn$ and $\vt$ is the well-constrained integer type, constraining -its set to the single value $\vn$; -\item (\texttt{bool}): $\vl$ is a Boolean literal and $\vt$ is the Boolean type; -\item (\texttt{real}): $\vl$ is a real literal and $\vt$ is the real type; -\item (\texttt{string}): $\vl$ is a string literal and $\vt$ is the string type; -\item (\texttt{bitvector}): $\vl$ is a bitvector literal of length $\vn$ and $\vt$ is the bitvector type of fixed width $\vn$. -\end{itemize} - -\subsection{Example} -In the following example, we show several literals and their corresponding types in comments: -\VerbatimInput{../tests/ASLTypingReference.t/TypingRule.Lit.asl} - -\CodeSubsection{\LitBegin}{\LitEnd}{../Typing.ml} - -\subsection{Formally} -\begin{mathpar} -\inferrule[int]{}{\annotateliteral{\lint(n)}\typearrow \TInt(\langle[\ConstraintExact(\ELInt{n})]\rangle)} -\end{mathpar} - -\begin{mathpar} -\inferrule[bool]{}{\annotateliteral{\lbool(\Ignore)}\typearrow \TBool} -\end{mathpar} - -\begin{mathpar} -\inferrule[real]{}{\annotateliteral{\lreal(\Ignore)}\typearrow \TReal} -\end{mathpar} - -\begin{mathpar} -\inferrule[string]{}{\annotateliteral{\lstring(\Ignore)}\typearrow \TString} -\end{mathpar} - -\begin{mathpar} -\inferrule[bitvector]{ - n \eqdef \listlen{\bits} -}{ - \annotateliteral{\lbitvector(\bits)}\typearrow \TBits(\ELInt{n}, \emptylist) -} -\end{mathpar} - -\section{TypingRule.ExpressionList \label{sec:TypingRule.ExpressionList}} -\hypertarget{def-annotateexprs}{} -The function -\[ - \annotateexprlist(\overname{\staticenvs}{\tenv} \aslsep \overname{\expr^*}{\exprs}) - \aslto \overname{(\ty \times \expr)^*}{\typedexprs} - \cup \overname{\TTypeError}{\TypeErrorConfig} -\] -annotates a list of expressions $\exprs$ from left to right, yielding a list of pairs $\typedexprs$, -each consisting of a type and expression. -\ProseOtherwiseTypeError - -\subsection{Prose} -One of the following applies: -\begin{itemize} - \item All of the following apply (\textsc{empty}): - \begin{itemize} - \item $\exprs$ is empty; - \item $\typedexprs$ is empty. - \end{itemize} - - \item All of the following apply (\textsc{non\_empty}): - \begin{itemize} - \item $\exprs$ has $\ve$ as its \head\ expression and $\exprsone$ as its \tail; - \item annotating $\ve$ in $\tenv$ yields the pair $\typedexpr$ consisting of a type and an expression - \ProseOrTypeError; - \item annotating the expression list $\exprsone$ in $\tenv$ yields - $\typedexprs$\ProseOrTypeError; - \item $\typedexprs$ is the list with $\typedexpr$ as its \head\ and $\typedexprs$ as its \tail. - \end{itemize} -\end{itemize} - -\subsection{Formally} -\begin{mathpar} -\inferrule[empty]{} -{ - \annotateexprlist(\tenv, \overname{\emptylist}{\exprs}) \typearrow \overname{\emptylist}{\typedexprs} -} -\end{mathpar} - -\begin{mathpar} -\inferrule[non\_empty]{ - \annotateexpr{\tenv, \ve} \typearrow \typedexpr \OrTypeError\\\\ - \annotateexprlist(\tenv, \exprsone) \typearrow \typedexprsone \OrTypeError -}{ - \annotateexprlist(\tenv, \overname{[\ve] \concat \exprsone}{\exprs}) \typearrow \overname{[\typedexpr] \concat \typedexprsone}{\typedexprs} -} -\end{mathpar} - -\section{TypingRule.ReduceSlicesToCall \label{sec:TypingRule.ReduceSlicesToCall}} -\hypertarget{def-reduceslicestocall}{} -The function -\[ - \reduceslicestocall(\overname{\staticenvs}{\tenv} \aslsep \overname{\expr}{\ve} \aslsep \overname{\slice^*}{\slices}) - \aslto - \langle (\overname{\identifier}{\name} \times \overname{\expr^*}{\vargs})\rangle - \cup \overname{\TTypeError}{\TypeErrorConfig} -\] -checks whether the expression $\ve$ together with the list of slices $\slices$ constitute -a call to a subprogram in $\tenv$. -If so, it returns a pair consisting of the name of the called subprogram --- $\name$ --- -and the list of actual arguments --- $\vargs$. Otherwise, it returns $\None$. -\ProseOtherwiseTypeError - -\subsection{Prose} -One of the following applies: -\begin{itemize} - \item All of the following apply (\textsc{yes}): - \begin{itemize} - \item $\ve$ is a variable expression for $\vx$, that is, $\EVar(\vx)$; - \item determining whether $\vx$ is a subprogram name with $\slices$ as its actual arguments - via $\shouldslicesreducetocall$ - yields a list of actual argument expressions $\vargs$\ProseOrTypeError; - \item the result is $\langle (\vx, \vargs)\rangle$. - \end{itemize} - - \item All of the following apply (\textsc{no}): - \begin{itemize} - \item $\ve$ is a variable expression for $\vx$, that is, $\EVar(\vx)$; - \item determining whether $\vx$ is a subprogram name with $\slices$ as its actual arguments - via $\shouldslicesreducetocall$ - yields $\None$; - \item the result is $\None$. - \end{itemize} - - \item All of the following apply (\textsc{non\_var}): - \begin{itemize} - \item $\ve$ is not a variable expression; - \item the result is $\None$. - \end{itemize} -\end{itemize} - -\CodeSubsection{\ReduceSlicesToCallBegin}{\ReduceSlicesToCallEnd}{../Typing.ml} - -\subsection{Formally} -\begin{mathpar} -\inferrule[yes]{ - \shouldslicesreducetocall(\tenv, \vx, \slices) \typearrow \langle \vargs \rangle\\ -}{ - \reduceslicestocall(\tenv, \EVar(\vx), \slices) \typearrow \langle (\vx, \vargs)\rangle -} -\end{mathpar} - -\begin{mathpar} -\inferrule[no]{ - \shouldslicesreducetocall(\tenv, \vx, \slices) \typearrow \None -}{ - \reduceslicestocall(\tenv, \EVar(\vx), \slices) \typearrow \None -} -\end{mathpar} - -\begin{mathpar} -\inferrule[non\_var]{ - \astlabel(\ve) \neq \EVar -}{ - \reduceslicestocall(\tenv, \ve, \slices) \typearrow \None -} -\end{mathpar} - -\section{TypingRule.StaticConstrainedInteger \label{sec:TypingRule.StaticConstrainedInteger}} -\hypertarget{def-annotatestaticconstrainedinteger}{} -The function -\[ - \annotatestaticconstrainedinteger(\overname{\staticenvs}{\tenv} \aslsep \overname{\expr}{\ve}) \aslto - \overname{\expr}{\vepp} \cup \overname{\TTypeError}{\TypeErrorConfig} -\] -annotates a \staticallyevaluable\ integer expression $\ve$ of a constrained integer type in the static environment $\tenv$ -and returns the annotated expression $\vepp$. -\ProseOtherwiseTypeError - -\subsection{Prose} -All of the following apply: -\begin{itemize} - \item annotating the expression $\ve$ in $\tenv$ yields $ (\vt, \vep)$\ProseOrTypeError; - \item determining whether $\vt$ is a statically \constrainedinteger\ in $\tenv$ yields $\True$\ProseOrTypeError; - \item determining whether $\vep$ is \staticallyevaluable\ in $\tenv$ yields $\True$\ProseOrTypeError; - \item applying $\normalize$ to $\vep$ in $\tenv$ yields $\vepp$. -\end{itemize} - -\CodeSubsection{\StaticConstrainedIntegerBegin}{\StaticConstrainedIntegerEnd}{../Typing.ml} - -\subsection{Formally} -\begin{mathpar} -\inferrule{ - \annotateexpr{\tenv, \ve} \typearrow (\vt, \vep) \OrTypeError\\\\ - \checkconstrainedinteger(\tenv, \vt) \typearrow \True \OrTypeError\\\\ - \checkstaticallyevaluable(\tenv, \vep) \typearrow \True \OrTypeError\\\\ - \normalize(\tenv, \vep) \typearrow \vepp -}{ - \annotatestaticconstrainedinteger(\tenv, \ve) \typearrow \vepp -} -\end{mathpar} - -\section{TypingRule.CheckATC \label{sec:TypingRule.CheckATC}} -\hypertarget{def-checkatc}{} -The function -\[ - \checkatc(\overname{\staticenvs}{\tenv} \aslsep \overname{\ty}{\vtone} \aslsep \overname{\ty}{\vttwo}) \aslto - \{\True\} \cup \overname{\TTypeError}{\TypeErrorConfig} -\] -checks whether the types $\vtone$ and $\vttwo$, which are assumed to not be named types, -are compatible for a typing assertion in the static environment $\tenv$, yielding $\True$. -\ProseOtherwiseTypeError - -\subsection{Prose} -One of the following applies: -\begin{itemize} - \item All of the following apply (\textsc{equal}): - \begin{itemize} - \item determining whether $\vtone$ is \typeequivalent\ to $\vttwo$ in $\tenv$ yields $\True$\ProseOrTypeError; - \item the result is $\True$. - \end{itemize} - - \item All of the following apply (\textsc{different\_labels\_error}): - \begin{itemize} - \item determining whether $\vtone$ is \typeequivalent\ to $\vttwo$ in $\tenv$ yields $\False$; - \item the AST labels of $\vtone$ and $\vttwo$ are different; - \item the result is a type error indicating that the type assertion will always fail. - \end{itemize} - - \item All of the following apply (\textsc{int\_bits}): - \begin{itemize} - \item determining whether $\vtone$ is \typeequivalent\ to $\vttwo$ in $\tenv$ yields $\False$; - \item the AST labels of $\vtone$ and $\vttwo$ are the same; - \item the AST label of $\vtone$ is either $\TInt$ or $\TBits$; - \item the result is $\True$. - \end{itemize} - - \item All of the following apply (\textsc{tuple}): - \begin{itemize} - \item determining whether $\vtone$ is \typeequivalent\ to $\vttwo$ in $\tenv$ yields $\False$; - \item $\vtone$ is a tuple type with list of tuples $\vlone$, that is, $\TTuple(\vlone)$; - \item $\vtone$ is a tuple type with list of tuples $\vltwo$, that is, $\TTuple(\vltwo)$; - \item checking whether $\vlone$ and $\vltwo$ have the same length yields $\True$\ProseTerminateAs{\TypeErrorVal{\TypeAsssertionFails}}; - \item applying $\checkatc$ to $\vlone[\vi]$ and $\vltwo[\vi]$ in $\tenv$ for every $\vi\in\listrange(\vlone)$ yields $\True$\ProseOrTypeError; - \item the result is $\True$; - \end{itemize} - - \item All of the following apply (\textsc{other\_error}): - \begin{itemize} - \item determining whether $\vtone$ is \typeequivalent\ to $\vttwo$ in $\tenv$ yields $\False$; - \item the AST labels of $\vtone$ and $\vttwo$ are the same; - \item the AST label of $\vtone$ is neither $\TInt$, nor $\TBits$, nor $\TTuple$; - \item the result is a type error indicating that the type assertion will always fail. - \end{itemize} -\end{itemize} - -\subsection{Formally} -\begin{mathpar} -\inferrule[equal]{ - \typeequal(\tenv, \vtone, \vttwo) \typearrow \True \OrTypeError -}{ - \checkatc(\tenv, \vtone, \vttwo) \typearrow \True -} -\end{mathpar} - -\begin{mathpar} -\inferrule[different\_labels\_error]{ - \typeequal(\tenv, \vtone, \vttwo) \typearrow \False\\\\ - \astlabel(\vtone) \neq \astlabel(\vttwo) -}{ - \checkatc(\tenv, \vtone, \vttwo) \typearrow \TypeErrorVal{\TypeAsssertionFails} -} -\end{mathpar} - -\begin{mathpar} -\inferrule[int\_bits]{ - \typeequal(\tenv, \vtone, \vttwo) \typearrow \False\\\\ - \astlabel(\vtone) = \astlabel(\vttwo)\\ - \astlabel(\vtone) \in \{\TInt, \TBits\} -}{ - \checkatc(\tenv, \vtone, \vttwo) \typearrow \True -} -\end{mathpar} - -\begin{mathpar} -\inferrule[tuple]{ - \typeequal(\tenv, \vtone, \vttwo) \typearrow \False\\\\ - \vtone = \TTuple(\vlone)\\ - \vttwo = \TTuple(\vltwo)\\ - \checktrans{|\vlone|=|\vltwo|}{\TypeAsssertionFails} \typearrow \True\OrTypeError\\\\ - \vi\in\listrange(\vlone): \checkatc(\vlone[\vi], \vltwo[\vi]) \typearrow \True\OrTypeError -}{ - \checkatc(\tenv, \vtone, \vttwo) \typearrow \True -} -\end{mathpar} - -\begin{mathpar} -\inferrule[other\_error]{ - \typeequal(\tenv, \vtone, \vttwo) \typearrow \False\\\\ - \astlabel(\vtone) = \astlabel(\vttwo)\\ - \astlabel(\vtone) \not\in \{\TInt, \TBits, \TTuple\} -}{ - \checkatc(\tenv, \vtone, \vttwo) \typearrow \True -} -\end{mathpar} - -\section{TypingRule.SlicesWidth \label{sec:TypingRule.SlicesWidth}} -\hypertarget{def-sliceswidth}{} -The function -\[ - \sliceswidth(\overname{\staticenvs}{\tenv} \aslsep \overname{\slice^*}{\vslices}) \aslto - \overname{\expr}{\vwidth} \cup \overname{\TTypeError}{\TypeErrorConfig} -\] -returns an expression $\vslices$ that represents the width of all slices given by $\vslices$ -in the static environment $\tenv$. - -\subsection{Prose} -One of the following applies: -\begin{itemize} - \item All of the following apply (\textsc{empty}): - \begin{itemize} - \item $\vslices$ is the empty list; - \item $\vwidth$ is the literal integer expression for $0$. - \end{itemize} - - \item All of the following apply (\textsc{non\_empty}): - \begin{itemize} - \item $\vslices$ is the list with \head\ $\vs$ and \tail\ $\slicesone$; - \item applying $\slicewidth$ to $\vs$ yields $\veone$; - \item applying $\sliceswidth$ to $\slicesone$ yields $\vetwo$; - \item symbolically simplifying the binary expression summing $\veone$ with $\vetwo$ yields $\vwidth$\ProseOrTypeError. - \end{itemize} -\end{itemize} - -\subsection{Formally} -\begin{mathpar} -\inferrule[empty]{}{ - \sliceswidth(\tenv, \overname{\emptylist}{\vslices}) \typearrow \overname{\ELInt{0}}{\vwidth} -} -\end{mathpar} - -\begin{mathpar} -\inferrule[non\_empty]{ - \slicewidth(\vs) \typearrow \veone\\ - \sliceswidth(\slicesone) \typearrow \vetwo\\ - \normalize(\AbbrevEBinop{\PLUS}{\veone}{\vetwo}) \typearrow \vwidth \OrTypeError -}{ - \sliceswidth(\tenv, \overname{[\vs]\concat\slicesone}{\vslices}) \typearrow \vwidth -} -\end{mathpar} - -\section{TypingRule.SliceWidth \label{sec:TypingRule.SliceWidth}} -\hypertarget{def-slicewidth}{} -The function -\[ - \slicewidth(\overname{\slice}{\vslice}) \aslto - \overname{\expr}{\vwidth} -\] -returns an expression $\vslices$ that represents the width of the slices given by $\vslice$. - -\subsection{Prose} -One of the following applies: -\begin{itemize} - \item All of the following apply (\textsc{single}): - \begin{itemize} - \item $\vslice$ is a single slice, that is, $\SliceSingle(\Ignore)$; - \item $\vwidth$ is the literal integer expression for $1$; - \end{itemize} - - \item All of the following apply (\textsc{star}, \text{length}): - \begin{itemize} - \item $\vslice$ is either a slice of the form \texttt{\_:*$\ve$} or \texttt{\_:+$\ve$}; - \item $\vwidth$ is $\ve$; - \end{itemize} - - \item All of the following apply (\textsc{range}): - \begin{itemize} - \item $\vslice$ is a slice of the form \texttt{$\veone$..$\vetwo$}; - \item $\vwidth$ is the expression for $1 + (\veone - \vetwo)$. - \end{itemize} -\end{itemize} -\subsection{Formally} -\begin{mathpar} -\inferrule[single]{}{ - \slicewidth(\overname{\SliceSingle(\Ignore)}{\vslice}) \typearrow \overname{\ELInt{1}}{\vwidth} -} -\and -\inferrule[star]{}{ - \slicewidth(\overname{\SliceStar(\Ignore, \ve)}{\vslice}) \typearrow \overname{\ve}{\vwidth} -} -\and -\inferrule[length]{}{ - \slicewidth(\overname{\SliceLength(\Ignore, \ve)}{\vslices}) \typearrow \overname{\ve}{\vwidth} -} -\and -\inferrule[range]{}{ - \slicewidth(\overname{\SliceRange(\veone, \vetwo)}{\vslices}) \typearrow - \overname{\AbbrevEBinop{\PLUS}{\ELInt{1}}{(\AbbrevEBinop{\MINUS}{\veone}{\vetwo})}}{\vwidth} -} -\end{mathpar} - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -\chapter{Typing of Left-Hand-Side Expressions \label{chap:typinglexpr}} -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -\hypertarget{def-annotatelexpr}{} -The function -\[ - \annotatelexpr{ - \overname{\staticenvs}{\tenv} \aslsep - \overname{\lexpr}{\vle} \aslsep - \overname{\ty}{\vte}} \aslto - \overname{\lexpr}{\newle} \cup \TTypeError -\] -annotates a left-hand side expression $\vle$ in an environment $\tenv$, assuming $\vte$ -to be the type of the corresponding right-hand-side expression, -resulting in an annotated expression $\newle$. -\ProseOtherwiseTypeError -One of the following applies: -\begin{itemize} -\item TypingRule.LEDiscard (see \secref{TypingRule.LEDiscard}), -\item TypingRule.LEVar (see \secref{TypingRule.LEVar}), -\item TypingRule.LEDestructuring (see \secref{TypingRule.LEDestructuring}), -\item TypingRule.LESlice (see \secref{TypingRule.LESlice}), -\item TypingRule.LESetArray (see \secref{TypingRule.LESetArray}), -\item TypingRule.LESetStructuredField (see \secref{TypingRule.LESetStructuredField}), -\item TypingRule.LESetBitField (see \secref{TypingRule.LESetBitField}), -\item TypingRule.LESetBadField (see \secref{TypingRule.LESetBadField}), -\item TypingRule.LEConcat (see \secref{TypingRule.LEConcat}). -\end{itemize} - -We also make use of the helper tuple -TypingRule.LEBits (see \secref{TypingRule.LEBits}). - -\hypertarget{def-rexpr}{} -Some of the rules require viewing left-hand-side expressions as their corresponding right-hand side expressions. -The correspondence is defined by the function $\torexpr : \lexpr \rightarrow \expr$. - -\section{TypingRule.LEDiscard \label{sec:TypingRule.LEDiscard}} -\subsection{Prose} -All of the following apply: -\begin{itemize} -\item $\vle$ denotes an expression that can be discarded, that is, $\LEDiscard$; -\item $\newle$ is $\vle$. -\end{itemize} - -\isempty{\subsection{Example}} -\CodeSubsection{\LEDiscardBegin}{\LEDiscardEnd}{../Typing.ml} - -\subsection{Formally} -\begin{mathpar} -\inferrule{}{ - \annotatelexpr{\tenv, \overname{\LEDiscard}{\vle}, \vte} \typearrow \overname{\LEDiscard}{\newle} -} -\end{mathpar} - -\isempty{\subsection{Comments}} - -\section{TypingRule.LEVar \label{sec:TypingRule.LEVar}} -\CodeSubsection{\LEVarBegin}{\LEVarEnd}{../Typing.ml} -\subsection{Prose} -All of the following apply: -\begin{itemize} - \item $\vle$ denotes a left-hand-side variable expression for $\vx$, that is, $\LEVar(\vx)$; - \item One of the following applies (\textsc{local}): - \begin{itemize} - \item $\vx$ is declared in $\tenv$ as a local storage element with type $\tty$ and local declaration keyword $k$; - \item checking that $k$ corresponds to a mutable variable, that is, $\LDKVar$, yields $\True$\ProseTerminateAs{\AssignmentToImmutable}; - \item determining whether $\tty$ \typesatisfies\ $\vte$ in $\tenv$ yields $\True$\ProseOrTypeError; - \item $\newle$ is $\vle$. - \end{itemize} - - \item One of the following applies (\textsc{global}): - \begin{itemize} - \item $\vx$ is declared in $\tenv$ as a global storage element with type $\tty$ and global declaration keyword $k$; - \item checking that $k$ corresponds to a mutable variable, that is, $\GDKVar$, yields $\True$\ProseTerminateAs{\AssignmentToImmutable}; - \item determining whether $\tty$ \typesatisfies\ $\vte$ in $\tenv$ yields $\True$\ProseOrTypeError; - \item $\newle$ is $\vle$. - \end{itemize} - - \item One of the following applies (\textsc{error\_undefined}): - \begin{itemize} - \item $\vx$ is not declared in $\tenv$ as a local storage element nor as a global storage element; - \item the result is a type error $\UndefinedIdentifier$. - \end{itemize} -\end{itemize} - -\CodeSubsection{\LEVarBegin}{\LEVarEnd}{../Typing.ml} - -\subsection{Formally} -\begin{mathpar} -\inferrule[local]{ - L^\tenv.\localstoragetypes(\id) = (\tty, k)\\ - \checktrans{k = \LDKVar}{\AssignmentToImmutable} \checktransarrow \True \OrTypeError\\\\ - \checktypesat(\tenv, \vte, \tty) \typearrow \True \OrTypeError -}{ - \annotatelexpr{\tenv, \overname{\LEVar(\vx)}{\vle}, \vte} \typearrow \overname{\vle}{\newle} -} -\end{mathpar} - -\begin{mathpar} -\inferrule[global]{ - L^\tenv.\globalstoragetypes(\id) = (\tty, k)\\ - \checktrans{k = \GDKVar}{AssignToImmutable} \checktransarrow \True \OrTypeError\\\\ - \checktypesat(\tenv, \vte, \tty) \typearrow \True \OrTypeError -}{ - \annotatelexpr{\tenv, \overname{\LEVar(\vx)}{\vle}, \vte} \typearrow \overname{\vle}{\newle} -} -\end{mathpar} - -\begin{mathpar} -\inferrule[error\_undefined]{ - L^\tenv.\localstoragetypes(\id) = \bot\\ - L^\tenv.\globalstoragetypes(\id) = \bot -}{ - \annotatelexpr{\tenv, \overname{\LEVar(\vx)}{\vle}, \vte} \typearrow \TypeErrorVal{\UndefinedIdentifier} -} -\end{mathpar} - -\isempty{\subsection{Comments}} -\lrmcomment{ - This is related to \identr{WDGQ}, \identr{GNTS}, \identi{MMKF}, - \identi{DGWJ}, \identi{KKCC} and \identr{LXQZ}. -} - -\section{TypingRule.LEDestructuring \label{sec:TypingRule.LEDestructuring}} - -\subsection{Prose} -All of the following apply: -\begin{itemize} - \item $\vle$ denotes a tuple of left-hand-side expressions $\les$, that is, $\LEDestructuring(\les)$; - \item $\les$ is a list $\ve_{1..k}$; - \item checking whether $\vte$ is a tuple type yields $\True$\ProseTerminateAs{\ExpectedTupleType}; - \item $\vte$ is a tuple type over the list of types $\tys$, that is, $\TTuple(\tys)$; - \item determining whether $\les$ and $\subtys$ have the same length yields $\True$\ProseTerminateAs{\LengthsMismatch}; - \item $\subtys$ is the list of types $\vt_{1..k}$; - \item annotating the left-hand-side expression $\ve_i$ with the type $\vt_i$, for $i=1..k$, yields $\vep_i$\ProseOrTypeError; - \item the list of expressions $\lesp$ is $\vep_i$, for $i=1..k$; - \item $\newle$ is the list of left-hand-side expressions $\lesp$, that is, $\LEDestructuring(\lesp)$. -\end{itemize} - -\isempty{\subsection{Example}} - -\CodeSubsection{\LEDestructuringBegin}{\LEDestructuringEnd}{../Typing.ml} - -\subsection{Formally} -\begin{mathpar} -\inferrule{ - \les \eqname [\ve_{1..k}]\\ - \checktrans{\astlabel(\vte) = \TTuple}{\ExpectedTupleType} \checktransarrow \True \OrTypeError\\\\ - \vte \eqname \TTuple(\tys)\\ - \equallength(\les, \tys) \typearrow \vb\\ - \checktrans{\vb}{\LengthsMismatch} \checktransarrow \True \OrTypeError\\\\ - \tys \eqname [\vt_{1..k}]\\ - i=1..k: \annotatelexpr{\tenv, \ve_i,\vt_i} \typearrow \vep_i \OrTypeError\\\\ - \lesp \eqname [i=1..k: \vep_i] -}{ - \annotatelexpr{\tenv, \overname{\LEDestructuring(\les)}{\vle}, \vte} \typearrow \overname{\LEDestructuring(\lesp)}{\newle} -} -\end{mathpar} - -\isempty{\subsection{Comments}} - -\section{TypingRule.LESlice \label{sec:TypingRule.LESlice}} - -\subsection{Prose} -All of the following apply: -\begin{itemize} - \item $\vle$ denotes the slicing of a left-hand-side expression $\vleone$ by the slices $\slices$, that is, $\LESlice(\vleone, \slices)$; - \item annotating the right-hand-side expression corresponding to $\vleone$ in $\tenv$ yields \\ - $(\vtleone, \Ignore)$\ProseOrTypeError; - \item $\vtleone$ is a bitvector type; - \item annotating the left-hand-side expression $\vleone$ in $\tenv$ yields $\vletwo$\ProseOrTypeError; - \item obtaining the width of the slices $\slices$ in $\tenv$ and simplifying them yields $\vwidth$; - \item $\vt$ is the bitvector type of width $\width$ and empty list of bitfields; - \item checking whether $\vte$ \typesatisfies\ $\vt$ yields $\True$\ProseOrTypeError; - \item annotating $\slices$ in $\tenv$ yields $\slicestwo$\ProseOrTypeError; - \item checking that the slices $\slicestwo$ are all disjoint yields $\True$\ProseOrTypeError; - \item $\newle$ is the slicing of $\vletwo$ by $\slicestwo$, that is, $\LESlice(\vletwo, \slicestwo)$. -\end{itemize} - -\isempty{\subsection{Example}} - -\CodeSubsection{\LESliceBegin}{\LESliceEnd}{../Typing.ml} - -\subsection{Formally} -\begin{mathpar} -\inferrule{ - \annotateexpr{\tenv, \torexpr(\vleone)} \typearrow (\vtleone, \Ignore)\\ - \tstruct(\tenv, \vtleone) \typearrow \structtleone \OrTypeError\\\\ - \astlabel(\structtleone) = \TBits\\ - \annotatelexpr{\tenv, \vleone, \vtleone} \typearrow \vletwo\\ - \sliceswidth(\tenv, \slices) \typearrow \widthp\\ - \normalize(\tenv, \widthp) \typearrow \vwidth\\ - \vt \eqdef \TBits(\vwidth, \emptylist)\\ - \checktypesat(\tenv, \vte, \vt) \typearrow \True \OrTypeError\\\\ - \annotateslices(\tenv, \slices) \typearrow \slicestwo \OrTypeError\\\\ - \checkdisjointslices(\tenv, \slicestwo) \typearrow \True \OrTypeError\\\\ - \newle \eqdef \LESlice(\vletwo, \slicestwo) -}{ - \annotatelexpr{\tenv, \overname{\LESlice(\vleone, \slices)}{\vle}, \vte} \typearrow \newle -} -\end{mathpar} - -\isempty{\subsection{Comments}} - -\section{TypingRule.LESetArray \label{sec:TypingRule.LESetArray}} - -\subsection{Prose} -All of the following apply: -\begin{itemize} - \item $\vle$ denotes the slicing of a left-hand-side expression $\vleone$ by the slices $\slices$, that is, $\LESlice(\vleone, \slices)$; - \item annotating the right-hand-side expression corresponding to $\vleone$ in $\tenv$ yields \\ $(\vtleone, \Ignore)$\ProseOrTypeError; - \item obtaining the \structure\ of $\vtleone$ in $\tenv$ yields an array type of size $\size$ and element type $\vt$, that is, $\TArray(\size, \vt)$\ProseOrTypeError; - \item annotating the left-hand-side expression $\vleone$ with type $\vtleone$ in $\tenv$ yields $\vletwo$\ProseOrTypeError; - \item determining that $\vte$ \typesatisfies\ $\vt$ in $\tenv$ yields $\True$\ProseOrTypeError; - \item determining whether $\slices$ is a single slice with index expression $\eindex$ yields $\True$\ProseOrTypeError; - \item annotating the index expression $\eindex$ in $\tenv$ yields $(\tindexp, \eindexp)$\ProseOrTypeError; - \item determining the array length type of $\size$ in $\tenv$ (via $\typeofarraylength$) yields $\wantedtindex$; - \item determining whether $\tindexp$ \typesatisfies\ $\wantedtindex$ in $\tenv$ yields \\ - $\True$\ProseOrTypeError; - \item $\newle$ is an access to array $\vletwo$ at index $\eindexp$, that is, \\ $\LESetArray(\vletwo, \eindexp)$. -\end{itemize} - -\isempty{\subsection{Example}} - -\CodeSubsection{\LESetArrayBegin}{\LESetArrayEnd}{../Typing.ml} - -\subsection{Formally} -\begin{mathpar} -\inferrule{ - \annotateexpr{\tenv, \torexpr(\vleone)} \typearrow (\vtleone, \Ignore) \OrTypeError\\\\ - \tstruct(\tenv, \vtleone) \typearrow \TArray(\size, \vt) \OrTypeError\\\\ - \annotatelexpr{\tenv, \vleone, \vtleone} \typearrow \vletwo \OrTypeError\\\\ - \checktypesat(\tenv, \vte, \vt) \typearrow \True \OrTypeError\\\\ - \checktrans{\listlen{\slices} = 1}{ArraySliceShouldBeSingleIndex} \checktransarrow \True \OrTypeError\\\\ - \slices \eqname [\vs]\\ - \checktrans{\astlabel(\vs) = \SliceSingle}{ArraySliceShouldBeSingleIndex} \checktransarrow \True \OrTypeError\\\\ - \vs \eqname \SliceSingle(\eindex)\\ - \annotateexpr{\tenv, \eindex} \typearrow (\tindexp, \eindexp) \OrTypeError\\\\ - \typeofarraylength(\tenv, \size) \typearrow \wantedtindex\\ - \checktypesat(\tenv, \tindexp, \wantedtindex) \typearrow \True \OrTypeError\\\\ - \newle \eqdef \LESetArray(\vletwo, \eindexp) -}{ - \annotatelexpr{\tenv, \overname{\LESlice(\vleone, \slices)}{\vle}, \vte} \typearrow \newle -} -\end{mathpar} - -\isempty{\subsection{Comments}} - -\section{TypingRule.LESetStructuredField \label{sec:TypingRule.LESetStructuredField}} -\subsection{Prose} -All of the following apply: -\begin{itemize} - \item $\vle$ denotes the access to the field named \texttt{field} in $\vleone$; - \item annotating the right-hand-side expression corresponding to $\vleone$ in $\tenv$ yields \\ $(\vtleone, \Ignore)$\ProseOrTypeError; - \item annotating the left-hand-side expression $\vleone$ with type $\vtleone$ in $\tenv$ yields $\vletwo$\ProseOrTypeError; - \item obtaining the \structure\ of $\vtleone$ in $\tenv$ yields a\structuredtype\ with fields \\ - $\fields$\ProseOrTypeError; - \item checking that there exists a type associated with the field $\field$ in $\fields$ $\True$ \ProseTerminateAs{\MissingField}; - \item the type associated with the field $\field$ in $\fields$ is $\vt$; - \item determining whether $\vte$ \typesatisfies\ $\vt$ yields $\True$\ProseOrTypeError; - \item $\newle$ is the access to the field $\field$ in $\vletwo$, that is, $\LESetField(\vletwo, \field)$. -\end{itemize} - -\isempty{\subsection{Example}} - -\CodeSubsection{\LESetStructuredFieldBegin}{\LESetStructuredFieldEnd}{../Typing.ml} - -\subsection{Formally} -\begin{mathpar} -\inferrule{ - \annotateexpr{\tenv, \torexpr(\vleone)} \typearrow (\vtleone, \Ignore) \OrTypeError\\\\ - \annotatelexpr{\tenv, \vleone, \vtleone} \typearrow \vletwo \OrTypeError\\\\ - \tstruct(\tenv, \vtleone) \typearrow L(\fields) \OrTypeError\\\\ - L \in \{\TException, \TRecord\}\\ - \assocopt(\fields, \field) \typearrow \tyopt\\ - \checktrans{\tyopt \neq \None}{\MissingField} \checktransarrow \True \OrTypeError\\\\ - \tyopt \eqname \langle\vt\rangle\\ - \checktypesat(\tenv, \vte, \vt) \typearrow \True \OrTypeError\\\\ - \newle \eqdef \LESetField(\vletwo, \field) -}{ - \annotatelexpr{\tenv, \overname{\LESetField(\vleone, \field)}{\vle}, \vte} \typearrow \newle -} -\end{mathpar} - -\isempty{\subsection{Comments}} - -\section{TypingRule.LESetBitField \label{sec:TypingRule.LESetBitField}} -%%%%%% NEW %%%%%% -\subsection{Prose} -\subsection{Prose} -All of the following apply: -\begin{itemize} - \item $\vle$ denotes the access to the field named $\field$ in $\vleone$, that is, \\ $\LESetField(\vleone, \field)$; - \item annotating the right-hand-side expression corresponding to $\vleone$ in $\tenv$ yields \\ $(\vtleone, \Ignore)$\ProseOrTypeError; - \item annotating the left-hand-side expression $\vleone$ in $\tenv$ yields $\vletwo$\ProseOrTypeError; - \item obtaining the \structure\ of $\vtleone$ in $\tenv$ yields a bitvector type with with bitfields $\bitfields$\ProseOrTypeError; - \item One of the following applies: - \begin{itemize} - \item All of the following applies (\textsc{error\_missing\_field}): - \begin{itemize} - \item applying $\findbitfieldopt$ to $\bitfields$ and $\vfield$ yields $\None$, meaning the field is not declared - in $\vtleone$; - \item the result is a type error $\MissingField$. - \end{itemize} - - \item All of the following applies (\textsc{field\_simple}): - \begin{itemize} - \item applying $\findbitfieldopt$ to $\bitfields$ and $\vfield$ yields a bitfield with corresponding slices $\slices$, - that is, $\BitFieldSimple(\Ignore, \slices)$; - \item $\vw$ is the width of $\slices$; - \item $\vt$ is defined as the bitvector type of width $\vw$ and empty list of bitfields, that is, $\TBits(\vw, \emptylist)$; - \item checking whether$\vte$ \typesatisfies\ $\vt$ in $\tenv$ yields $\True$\ProseOrTypeError; - \item $\vletwo$ is defined as the slicing of $\vleone$ by $\slices$, that is, \\ $\LESlice(\vleone, \slices)$; - \item annotating the left-hand-side expression $\vletwo$ in $\tenv$ yields $\newle$\ProseOrTypeError. - \end{itemize} - - \item All of the following applies (\textsc{field\_nested}): - \begin{itemize} - \item applying $\findbitfieldopt$ to $\bitfields$ and $\vfield$ yields a nested bitfield with corresponding - slices $\slices$ and list of bitfields $\bitfieldsp$, that is, \\ $\BitFieldNested(\Ignore, \slices, \bitfieldsp)$; - \item $\vw$ is the width of $\slices$; - \item $\vt$ is defined as the bitvector type of width $\vw$ and list of bitfields $\bitfieldsp$, that is, $\TBits(\vw, \bitfieldsp)$; - \item checking whether$\vte$ \typesatisfies\ $\vt$ in $\tenv$ yields $\True$\ProseOrTypeError; - \item $\vlethree$ is defined as the slicing of $\vleone$ by $\slices$, that is, \\ $\LESlice(\vleone, \slices)$; - \item annotating the left-hand-side expression $\vlethree$ in $\tenv$ yields $\newle$\ProseOrTypeError. - \end{itemize} - - \item All of the following applies (\textsc{field\_typed}): - \begin{itemize} - \item applying $\findbitfieldopt$ to $\bitfields$ and $\vfield$ yields a typed bitfield with corresponding - slices $\slices$ and a type $\vt$, that is, \\ $\BitFieldType(\Ignore, \vslices, \vt))$; - \item $\vw$ is the width of $\slices$; - \item $\vtp$ is defined as the bitvector type of width $\vw$ and an empty list of bitfields, that is, $\TBits(\vw , \emptylist)$; - \item checking whether $\vtp$ \typesatisfies\ $\vt$ in $\tenv$ yields $\True$\ProseOrTypeError; - \item checking whether$\vte$ \typesatisfies\ $\vt$ in $\tenv$ yields $\True$\ProseOrTypeError; - \item $\vletwo$ is defined as the slicing of $\vleone$ by $\slices$, that is, \\ $\LESlice(\vleone, \slices)$; - \item annotating the left-hand-side expression $\vletwo$ in $\tenv$ yields $\newle$\ProseOrTypeError. - \end{itemize} - \end{itemize} -\end{itemize} - -\subsection{Formally} -\begin{mathpar} -\inferrule[error\_missing\_field]{ - \annotateexpr{\tenv, \torexpr(\vleone)} \typearrow (\vtleone, \Ignore) \OrTypeError\\\\ - \annotatelexpr{\tenv, \vleone, \vtleone} \typearrow \vletwo \OrTypeError\\\\ - \tstruct(\tenv, \vtleone) \typearrow \TBits(\Ignore, \bitfields) \OrTypeError\\\\ - \commonprefixline\\\\ - \findbitfieldopt(\bitfields, \field) \typearrow \None\ -}{ - \annotatelexpr{\tenv, \overname{\LESetField(\vleone, \field)}{\vle}, \vte} \typearrow \TypeErrorVal{\MissingField} -} -\end{mathpar} - -\begin{mathpar} -\inferrule[field\_simple]{ - \annotateexpr{\tenv, \torexpr(\vleone)} \typearrow (\vtleone, \Ignore) \OrTypeError\\\\ - \annotatelexpr{\tenv, \vleone, \vtleone} \typearrow \vletwo \OrTypeError\\\\ - \tstruct(\tenv, \vtleone) \typearrow \TBits(\Ignore, \bitfields) \OrTypeError\\\\ - \commonprefixline\\\\ - \findbitfieldopt(\bitfields, \field) \typearrow \langle \BitFieldSimple(\Ignore, \slices) \rangle\\ - \sliceswidth(\tenv, \vslices) \typearrow \vw\\ - \vt \eqdef \TBits(\vw, \emptylist)\\\\ - \commonsuffixline\\\\ - \checktypesat(\tenv, \vte, \vt) \typearrow \True \OrTypeError\\\\ - \vletwo \eqdef \LESlice(\vleone, \slices)\\ - \annotatelexpr{\tenv, \vletwo, \vte} \typearrow \newle \OrTypeError -}{ - \annotatelexpr{\tenv, \overname{\LESetField(\vleone, \field)}{\vle}, \vte} \typearrow \newle -} -\end{mathpar} - -\begin{mathpar} -\inferrule[field\_nested]{ - \annotateexpr{\tenv, \torexpr(\vleone)} \typearrow (\vtleone, \Ignore) \OrTypeError\\\\ - \annotatelexpr{\tenv, \vleone, \vtleone} \typearrow \vletwo \OrTypeError\\\\ - \tstruct(\tenv, \vtleone) \typearrow \TBits(\Ignore, \bitfields) \OrTypeError\\\\ - \commonprefixline\\\\ - \findbitfieldopt(\bitfields, \field) \typearrow \langle \BitFieldNested(\Ignore, \slices, \bitfieldsp) \rangle\\ - \sliceswidth(\tenv, \vslices) \typearrow \vw\\ - \vt \eqdef \TBits(\vw, \bitfieldsp)\\\\ - \commonsuffixline\\\\ - \checktypesat(\tenv, \vte, \vt) \typearrow \True \OrTypeError\\\\ - \vletwo \eqdef \LESlice(\vleone, \slices)\\ - \annotatelexpr{\tenv, \vletwo, \vte} \typearrow \newle \OrTypeError -}{ - \annotatelexpr{\tenv, \overname{\LESetField(\vleone, \field)}{\vle}, \vte} \typearrow \TypeErrorVal{MissingField} -} -\end{mathpar} - -\begin{mathpar} -\inferrule[field\_typed]{ - \annotateexpr{\tenv, \torexpr(\vleone)} \typearrow (\vtleone, \Ignore) \OrTypeError\\\\ - \annotatelexpr{\tenv, \vleone, \vtleone} \typearrow \vletwo \OrTypeError\\\\ - \tstruct(\tenv, \vtleone) \typearrow \TBits(\Ignore, \bitfields) \OrTypeError\\\\ - \commonprefixline\\\\ - \findbitfieldopt(\bitfields, \field) \typearrow \langle \BitFieldType(\Ignore, \vslices, \vt) \rangle\\ - \sliceswidth(\tenv, \vslices) \typearrow \vw\\ - \vtp \eqdef \TBits(\vw , \emptylist)\\ - \checktypesat(\tenv, \vtp, \vt) \typearrow \True \OrTypeError\\\\ - \commonsuffixline\\\\ - \checktypesat(\tenv, \vte, \vt) \typearrow \True \OrTypeError\\\\ - \vletwo \eqdef \LESlice(\vleone, \slices)\\ - \annotatelexpr{\tenv, \vletwo, \vte} \typearrow \newle \OrTypeError -}{ - \annotatelexpr{\tenv, \overname{\LESetField(\vleone, \field)}{\vle}, \vte} \typearrow \TypeErrorVal{MissingField} -} -\end{mathpar} - -\section{TypingRule.LESetBadField \label{sec:TypingRule.LESetBadField}} - -\subsection{Prose} -All of the following apply: -\begin{itemize} - \item $\vle$ denotes the access to the field named $\field$ in $\vleone$, that is, \\ $\LESetField(\vleone, \field)$; - \item annotating the right-hand-side expression corresponding to $\vleone$ in $\tenv$ yields \\ $(\vtleone, \Ignore)$\ProseOrTypeError; - \item annotating the left-hand-side expression $\vleone$ in $\tenv$ yields $\vletwo$\ProseOrTypeError; - \item obtaining the \structure\ of $\vtleone$ in $\tenv$ yields a type $\vt$\ProseOrTypeError; - \item $\vt$ is neither a \structuredtype\ nor a bitvector type; - \item the result is an error indicating that the type of $\vle$ conflicts with the requirements of a field access expression. -\end{itemize} - -\isempty{\subsection{Example}} - -\CodeSubsection{\LESetBadFieldBegin}{\LESetBadFieldEnd}{../Typing.ml} - -\subsection{Formally} -\begin{mathpar} -\inferrule{ - \annotateexpr{\tenv, \torexpr(\vleone)} \typearrow (\vtleone, \Ignore) \OrTypeError\\\\ - \annotatelexpr{\tenv, \vleone, \vtleone} \typearrow \vletwo \OrTypeError\\\\ - \tstruct(\tenv, \vtleone) \typearrow \vt \OrTypeError\\\\ - \astlabel(\vt) \not\in \{\TException, \TRecord, \TBits\} -}{ - \annotatelexpr{\tenv, \overname{\LESetField(\vleone, \field)}{\vle}, \vte} \typearrow \TypeErrorVal{TypeConflict} -} -\end{mathpar} - -\isempty{\subsection{Comments}} - -\section{TypingRule.LEConcat \label{sec:TypingRule.LEConcat}} - -\subsection{Prose} -All of the following apply: -\begin{itemize} - \item $\vle$ denotes the concatenation of left-hand-side expressions $\les$, that is, \\ $\LEConcat(\les, \Ignore)$; - \item annotating the right-hand-side expression corresponding to $\vle$ in $\tenv$ yields \\ $(\vteeq, \Ignore)$\ProseOrTypeError; - \item checking whether the bitwidth of $\vteeq$ equals the bitwidth of $\vte$ in $\tenv$ yields $\True$\ProseOrTypeError; - \item $\les$ is the list of left-hand-side expressions $\vle_i$, for $i=1..k$; - \item annotating each left-hand-side expression $\vle_i$ as a bitvector-typed expression (via $\annotatelebits$) - yields the annotated left-hand-side expression $\vleone_i$ and corresponding bitwidth $\width_i$, for $i=1..k$; - \item $\lesone$ is defined as the list $\vleone_{1..k}$; - \item $\widths$ is defined as the list $\width_{1..k}$; - \item $\newle$ is the concatenation of left-hand-side expressions $\lesone$ with corresponding list of widths $\widths$. -\end{itemize} - -\isempty{\subsection{Example}} - -\CodeSubsection{\LEConcatBegin}{\LEConcatEnd}{../Typing.ml} - -\subsection{Formally} -\begin{mathpar} -\inferrule{ - \vle \eqname \LEConcat(\les, \Ignore)\\ - \annotateexpr{\tenv, \torexpr(\vle)} \typearrow (\vteeq, \Ignore) \OrTypeError\\\\ - \checkbitsequalwidth(\tenv, \vteeq, \vte) \typearrow \True \OrTypeError\\\\ - \les \eqname \vle_{1..k}\\ - i=1..k: \annotatelebits(\tenv, \vle_i) \typearrow (\vleone_i, \width_i) \OrTypeError\\\\ - \lesone \eqdef \vleone_{1..k}\\ - \widths \eqdef \width_{1..k} -}{ - \annotatelexpr{\tenv, \vle, \vte} \typearrow \overname{\LEConcat(\lesone, \widths)}{\newle} -} -\end{mathpar} - -\isempty{\subsection{Comments}} - -\section{TypingRule.LEBits \label{sec:TypingRule.LEBits}} -\hypertarget{def-annotatelebits}{} -The helper function -\[ - \annotatelebits(\overname{\staticenvs}{\tenv} \aslsep \overname{\lexpr}{\vle}) - \aslto \overname{\lexpr}{\vleone} \times \overname{\N}{\width} -\] -annotates a left-hand-side expression $\vle$, which is checked to be of bitvector type -with width $\width$, -resulting in the annotated expression and $\width$, or a type error, if one is detected. - -All of the following apply: -\begin{itemize} - \item annotating the right-hand-side expression corresponding to $\vle$ in $\tenv$ yields \\ $(\vteone, \Ignore)$\ProseOrTypeError; - \item obtaining the \structure\ of $\vteone$ in $\tenv$ yields $\vteonestruct$\ProseOrTypeError; - \item checking whether $\vteonestruct$ is a bitvector type yields $\True$\ProseOrTypeError; - \item $\vteonestruct$ is a bitvector type with width $\ewidth$; - \item applying $\reduceconstants$ to $\ewidth$ yields the literal $\vl$\ProseOrTypeError; - \item checking whether $\vl$ is an integer literal yields $\True$\ProseOrTypeError; - \item $\vl$ is the integer literal for the integer $\width$; - \item $\vtetwo$ is defined as the bitvector type of width given by $\width$ and an empty list of bitfields, that is, - $\TBits(\ELInt{\width}, \emptylist)$; - \item annotating the left-hand-side expression $\vtetwo$ in $\tenv$ yields $\vleone$\ProseOrTypeError. -\end{itemize} - -\subsection{Formally} -\begin{mathpar} -\inferrule{ - \annotateexpr{\tenv, \torexpr(\vleone)} \typearrow (\vteone, \Ignore) \OrTypeError\\\\ - \tstruct(\tenv, \vteone) \typearrow \vteonestruct \OrTypeError\\\\ - \checktrans{\astlabel(\vteonestruct) = \TBits}{BitvectorTypeExpected} \checktransarrow \True \OrTypeError\\\\ - \vteonestruct \eqname \TBits(\ewidth, \Ignore)\\ - \reduceconstants(\tenv, \ewidth) \typearrow \vl\\ - \checktrans{\astlabel(\vl) = \lint}{IntegerLiteralExpected} \checktransarrow \True \OrTypeError\\\\ - \vl \eqname \lint(\width)\\ - \vtetwo \eqdef \TBits(\ELInt{\width}, \emptylist)\\ - \annotatelexpr{\tenv, \vtetwo} \typearrow \vleone \OrTypeError -}{ - \annotatelebits(\tenv, \vle) \typearrow (\vleone, \width) -} -\end{mathpar} - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -\chapter{Typing of Slices \label{chap:typingslices}} -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -\hypertarget{def-annotateslice}{} -The function -\[ - \annotateslice(\overname{\staticenvs}{\tenv} \aslsep \overname{\slice}{\vs}) - \aslto - \overname{\slice}{\vsp} \cup \overname{\TTypeError}{\TypeErrorConfig} -\] -annotates a single slice $\vs$ in the static environment $\tenv$, -resulting in an annotated slice $\vsp$. -\ProseOtherwiseTypeError - -One of the following applies: -\begin{itemize} -\item TypingRule.SliceSingle (see \secref{TypingRule.SliceSingle}), -\item TypingRule.SliceLength (see \secref{TypingRule.SliceLength}), -\item TypingRule.SliceRange (see \secref{TypingRule.SliceRange}), -\item TypingRule.SliceStar (see \secref{TypingRule.SliceStar}). -\end{itemize} - -We also define a rule for typing of a list of slices: -TypingRule.Slices (see \secref{TypingRule.Slices}). - -\hypertarget{def-annotateslices}{} -The function -\[ - \annotateslices(\overname{\staticenvs}{\tenv} \aslsep \overname{\slice^*}{\slices}) - \aslto - \overname{\slice^*}{\slicesp} \cup \overname{\TTypeError}{\TypeErrorConfig} -\] -annotates a list of slices $\slices$ in the static environment $\tenv$, -resulting in an annotated list of slices $\slicesp$. -\ProseOtherwiseTypeError - -The relevant rule is given by: -\begin{itemize} - \item TypingRule.Slices (see \secref{TypingRule.Slices}) -\end{itemize} - -\section{TypingRule.SliceSingle \label{sec:TypingRule.SliceSingle}} - -\subsection{Prose} -All of the following apply: -\begin{itemize} - \item $\vs$ is a slice at index \vi, that is $\SliceSingle(\vi)$; - \item annotating the slice at offset $\vi$ of length $1$ yields $\vsp$\ProseOrTypeError. -\end{itemize} - -\isempty{\subsection{Example}} - -\CodeSubsection{\SliceSingleBegin}{\SliceSingleEnd}{../Typing.ml} - -\subsection{Formally} -\begin{mathpar} -\inferrule{ - \annotateslice(\SliceLength(\vi, \eliteral{1})) \typearrow \vsp \OrTypeError -}{ - \annotateslice(\tenv, \overname{\SliceSingle(\vi)}{\vs}) \typearrow \vsp -} -\end{mathpar} - -\isempty{\subsection{Comments}} -\lrmcomment{\identr{GXKG}: The notation \texttt{b[i]} is syntactic sugar for \texttt{b[i +: 1]}.} - -\section{TypingRule.SliceLength \label{sec:TypingRule.SliceLength}} -\subsection{Prose} -All of the following apply: -\begin{itemize} - \item $\vs$ is a slice of length $\elength$ and offset $\eoffset$, that is, $\SliceLength(\eoffset, \elength)$; - \item annotating the expression $\eoffset$ in $\tenv$ yields $(\toffset, \eoffsetp)$\ProseOrTypeError; - \item annotating the \staticallyevaluable\ \constrainedinteger\ expression $\elength$ in $\tenv$ yields - $\elength$\ProseOrTypeError; - \item determining whether $\toffset$ has the \structureofinteger\ yields $\True$\ProseOrTypeError; - \item $\vsp$ is the slice at offset $\eoffsetp$ and length $\elength'$, that is,\\ - $\SliceLength(\eoffsetp, \elength')$. -\end{itemize} - -\isempty{\subsection{Example}} - -\CodeSubsection{\SliceLengthBegin}{\SliceLengthEnd}{../Typing.ml} - -\subsection{Formally} -\begin{mathpar} -\inferrule{ - \annotateexpr{\tenv, \eoffset} \typearrow (\toffset, \eoffsetp) \OrTypeError\\\\ - \annotatestaticconstrainedinteger(\tenv, \elength) \typearrow \elengthp \OrTypeError\\\\ - \checkstructureinteger(\tenv, \toffset) \typearrow \True \OrTypeError -}{ - { - \begin{array}{r} - \annotateslice(\tenv, \overname{\SliceLength(\eoffset, \elength)}{\vs}) \typearrow \\ - \overname{\SliceLength(\eoffsetp, \elength')}{\vsp} - \end{array} - } -} -\end{mathpar} - -\isempty{\subsection{Comments}} - -\section{TypingRule.SliceRange \label{sec:TypingRule.SliceRange}} - -\subsection{Prose} -All of the following apply: -\begin{itemize} - \item $\vs$ is a slice for the range \texttt{(j, i)}, that is $\SliceRange(\vj, \vi)$; - \item $\prelength$ is \texttt{i+:(j-i+1)}; - \item annotating the slice at offset $\vi$ of length $\prelength$ yields $\vsp$\ProseOrTypeError. -\end{itemize} - -\isempty{\subsection{Example}} - -\CodeSubsection{\SliceRangeBegin}{\SliceRangeEnd}{../Typing.ml} - -\subsection{Formally} -\begin{mathpar} -\inferrule{ - \binopliterals(\MINUS, \vi, \vi) \typearrow \prelengthp\\ - \binopliterals(\PLUS, \prelengthp, \eliteral{1}) \typearrow \prelength\\ - \annotateslice(\SliceLength(\vi, \prelength)) \typearrow \vsp \OrTypeError -}{ - \annotateslice(\tenv, \overname{\SliceRange(\vj, \vi)}{\vs}) \typearrow \vsp -} -\end{mathpar} - -\isempty{\subsection{Comments}} -\lrmcomment{\identr{GXKG}: The notation \texttt{b[j:i]} is syntactic sugar for \texttt{b[i+:(j-i+1)]}.} - -\section{TypingRule.SliceStar \label{sec:TypingRule.SliceStar}} - -\subsection{Prose} -All of the following apply: -\begin{itemize} - \item $\vs$ is a slice \texttt{[factor *: pre\_length]}, that is, $\SliceStar(\factor, \prelength)$; - \item $\preoffset$ is $\factor * \prelength$; - \item annotating the slice at offset $\preoffset$ of length $\prelength$ yields $\vsp$\ProseOrTypeError. -\end{itemize} - -\isempty{\subsection{Example}} - -\CodeSubsection{\SliceStarBegin}{\SliceStarEnd}{../Typing.ml} - -\subsection{Formally} -\begin{mathpar} -\inferrule{ - \binopliterals(\MUL, \factor, \prelength) \typearrow \preoffset\\ - \annotateslice(\SliceLength(\preoffset, \prelength)) \typearrow \vsp \OrTypeError -}{ - \annotateslice(\tenv, \overname{\SliceStar(\factor, \prelength)}{\vs}) \typearrow \vsp -} -\end{mathpar} - -\isempty{\subsection{Comments}} -\lrmcomment{\identr{GXQG}: The notation \texttt{b[i *: n]} is syntactic sugar for \texttt{b[i*n +: n]}} - -\section{TypingRule.Slices \label{sec:TypingRule.Slices}} -\subsection{Prose} -All of the following apply: -\begin{itemize} - \item annotating the slice $\vslices[\vi]$ in $\tenv$, for each $\vi\in\listrange(\vslices)$, yields the slice $\vs_\vi$\ProseOrTypeError; - \item define $\slicesp$ as the list of slices $\vs_\vi$, for each $\vi\in\listrange(\vslices)$. -\end{itemize} - -\isempty{\subsection{Example}} - -\subsection{Formally} -\begin{mathpar} -\inferrule{ - \vi\in\listrange(\vslices): \annotateslice(\tenv, \vslices[\vi]) \typearrow \vs_\vi \OrTypeError\\\\ - \slicesp \eqdef [\vi\in\listrange(\vslices): \vs_\vi] -}{ - \annotateslices(\tenv, \vslices) \typearrow \slicesp -} -\end{mathpar} - -\isempty{\subsection{Comments}} - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -\chapter{Typing of Patterns \label{chap:typingpatterns}} -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -\hypertarget{def-annotatepattern}{} -The function -\[ - \annotatepattern( - \overname{\staticenvs}{\tenv} \aslsep - \overname{\ty}{\vt} \aslsep - \overname{\pattern}{\vp}) \aslto \overname{\pattern}{\newp} \cup \overname{\TTypeError}{\TypeErrorConfig} -\] -annotates a pattern $\vp$ in a static environment $\tenv$ given a type $\vt$, -resulting in a pattern $\newp$ or a type error, if one is detected, and one of the following applies: -\begin{itemize} -\item TypingRule.PAll (see \secref{TypingRule.PAll}), -\item TypingRule.PAny (see \secref{TypingRule.PAny}), -\item TypingRule.PGeq (see \secref{TypingRule.PGeq}), -\item TypingRule.PLeq (see \secref{TypingRule.PLeq}), -\item TypingRule.PNot (see \secref{TypingRule.PNot}), -\item TypingRule.PRange (see \secref{TypingRule.PRange}), -\item TypingRule.PSingle (see \secref{TypingRule.PSingle}), -\item TypingRule.PMask (see \secref{TypingRule.PMask}), -\item TypingRule.PTuple (see \secref{TypingRule.PTuple}). -\end{itemize} - -\section{TypingRule.PAll \label{sec:TypingRule.PAll}} - -\subsection{Prose} -All of the following apply: -\begin{itemize} - \item $\vp$ is the pattern matching everything, that is, $\PatternAll$; - \item $\newp$ is $\vp$. -\end{itemize} - -\isempty{\subsection{Example}} - -\CodeSubsection{\PAllBegin}{\PAllEnd}{../Typing.ml} - -\subsection{Formally} -\begin{mathpar} -\inferrule{} -{ - \annotatepattern(\tenv, \vt, \overname{\PatternAll}{\vp}) \typearrow \overname{\PatternAll}{\newp} -} -\end{mathpar} - -\isempty{\subsection{Comments}} - -\section{TypingRule.PAny\label{sec:TypingRule.PAny}} - -\subsection{Prose} -All of the following apply: -\begin{itemize} -\item $\vp$ is the pattern which matches anything in a list $\vli$, that is, $\PatternAny(\vli)$; -\item annotating each pattern in $\vli$ yields the list of annotated pattern $\newli$\ProseOrTypeError; -\item $\newp$ is the pattern which matches anything in $\newli$, that is, \\ $\PatternAny(\newli)$. -\end{itemize} - -\isempty{\subsection{Example}} - -\CodeSubsection{\PAnyBegin}{\PAnyEnd}{../Typing.ml} - -\subsection{Formally} -\begin{mathpar} -\inferrule{ - \vl\in\vli: \annotatepattern(\tenv, \vt, \vl) \typearrow \vlp \OrTypeError\\\\ - \newli \eqdef [\vl\in\vli: \vlp] -} -{ - \annotatepattern(\tenv, \vt, \overname{\PatternAny(\vli)}{\vp}) \typearrow \overname{\PatternAny(\newli)}{\newp} -} -\end{mathpar} - -\isempty{\subsection{Comments}} - -\section{TypingRule.PGeq \label{sec:TypingRule.PGeq}} - -\subsection{Prose} -All of the following apply: -\begin{itemize} -\item $\vp$ is the pattern which matches anything greater than or equal to an expression $\ve$, -that is, $\PatternGeq(\ve)$; -\item annotating the expression $\ve$ in $\tenv$ yields $(\vte, \vep)$\ProseOrTypeError; -\item determining whether $\vep$ is a \staticallyevaluable\ expression yields $\True$\ProseOrTypeError; -\item obtaining the \structure\ of $\vt$ in $\tenv$ yields $\vtstruct$\ProseOrTypeError; -\item obtaining the \structure\ of $\vte$ in $\tenv$ yields $\testruct$\ProseOrTypeError; -\item $\vb$ is true if and only if $\vtstruct$ and $\testruct$ are both integer types or both real types; -\item if $\vb$ is $\False$ a type error is returned (indicating that the types of $\vt$ and $\vte$ - are inappropriate for the $\GEQ$ operator), -which short-circuits the entire rule; -\item $\newp$ is the pattern which matches anything greater than or equal to $\vep$. -\end{itemize} - -\isempty{\subsection{Example}} - -\CodeSubsection{\PGeqBegin}{\PGeqEnd}{../Typing.ml} - -\subsection{Formally} -\begin{mathpar} -\inferrule{ - \annotateexpr{\tenv, \ve} \typearrow (\vte, \vep) \OrTypeError\\\\ - \checkstaticallyevaluable(\tenv, \vep) \typearrow \True \OrTypeError\\\\ - \tstruct(\tenv, \vt) \typearrow \vtstruct \OrTypeError\\\\ - \tstruct(\tenv, \vte) \typearrow \testruct \OrTypeError\\\\ - { - \begin{array}{rl} - \vb \eqdef& \astlabel(\vtstruct) = \astlabel(\testruct)\ \land\\ - & \astlabel(\vtstruct) \in \{\TInt, \TReal\} - \end{array} - }\\ - \checktrans{\vb}{InvalidTypesForBinop} \checktransarrow \True \OrTypeError -} -{ - \annotatepattern(\tenv, \vt, \overname{\PatternGeq(\ve)}{\vp}) \typearrow \overname{\PatternGeq(\vep)}{\newp} -} -\end{mathpar} - -\isempty{\subsection{Comments}} - -\section{TypingRule.PLeq \label{sec:TypingRule.PLeq}} - -\subsection{Prose} -All of the following apply: -\begin{itemize} -\item $\vp$ is the pattern which matches anything less than or equal to an expression $\ve$, -that is, $\PatternLeq(\ve)$; -\item annotating the expression $\ve$ in $\tenv$ yields $(\vte, \vep)$\ProseOrTypeError; -\item determining whether $\vep$ is a \staticallyevaluable\ expression yields $\True$\ProseOrTypeError; -\item obtaining the \structure\ of $\vt$ in $\tenv$ yields $\vtstruct$\ProseOrTypeError; -\item obtaining the \structure\ of $\vte$ in $\tenv$ yields $\testruct$\ProseOrTypeError; -\item $\vb$ is true if and only if $\vtstruct$ and $\testruct$ are both integer types or both real types; -\item if $\vb$ is $\False$ a type error is returned (indicating that the types of $\vt$ and $\vte$ - are inappropriate for the $\LEQ$ operator), -which short-circuits the entire rule; -\item $\newp$ is the pattern which matches anything less than or equal to $\vep$. -\end{itemize} - -\isempty{\subsection{Example}} - -\CodeSubsection{\PLeqBegin}{\PLeqEnd}{../Typing.ml} - -\subsection{Formally} -\begin{mathpar} -\inferrule{ - \annotateexpr{\tenv, \ve} \typearrow (\vte, \vep) \OrTypeError\\\\ - \checkstaticallyevaluable(\tenv, \vep) \typearrow \True \OrTypeError\\\\ - \tstruct(\tenv, \vt) \typearrow \vtstruct \OrTypeError\\\\ - \tstruct(\tenv, \vte) \typearrow \testruct \OrTypeError\\\\ - { - \begin{array}{rl} - \vb \eqdef& \astlabel(\vtstruct) = \astlabel(\testruct)\ \land\\ - & \astlabel(\vtstruct) \in \{\TInt, \TReal\} - \end{array} - }\\ - \checktrans{\vb}{InvalidTypesForBinop} \checktransarrow \True \OrTypeError -}{ - \annotatepattern(\tenv, \vt, \overname{\PatternLeq(\ve)}{\vp}) \typearrow \overname{\PatternLeq(\vep)}{\newp} -} -\end{mathpar} - -\isempty{\subsection{Comments}} - -\section{TypingRule.PNot \label{sec:TypingRule.PNot}} - -\subsection{Prose} -All of the following apply: -\begin{itemize} - \item $\vp$ is the pattern which matches the negation of a pattern $\vq$, that is, $\PatternNot(\vq)$; - \item annotating $\vq$ in $\tenv$ yields $\newq$\ProseOrTypeError; - \item $\newp$ is pattern which matches the negation of $\newq$, that is, $\PatternNot(\newq)$. -\end{itemize} - -\isempty{\subsection{Example}} - -\CodeSubsection{\PNotBegin}{\PNotEnd}{../Typing.ml} - -\subsection{Formally} -\begin{mathpar} -\inferrule{ - \annotatepattern(\tenv, \vq) \typearrow \newq \OrTypeError -}{ - \annotatepattern(\tenv, \vt, \overname{\PatternNot(\vq)}{\vp}) \typearrow \overname{\PatternNot(\newq)}{\newp} -} -\end{mathpar} - -\isempty{\subsection{Comments}} - -\section{TypingRule.PRange \label{sec:TypingRule.PRange}} - -\subsection{Prose} -All of the following apply: -\begin{itemize} - \item $\vp$ is the pattern which matches anything within the range given by - expressions $\veone$ and $\vetwo$, that is, $\PatternRange(\veone, \vetwo)$; - \item annotating the expression $\veone$ in $\tenv$ yields $(\vteone, \veonep)$\ProseOrTypeError; - \item annotating the expression $\vetwo$ in $\tenv$ yields $(\vtetwo, \vetwop)$\ProseOrTypeError; - \item determining whether both $\veonep$ and $\vetwop$ are compile-time constant expressions yields $\True$\ProseOrTypeError; - \item obtaining the \structure\ for $\vt$, $\vteone$, and $\vtetwo$ yields - $\vtstruct$, $\vteonestruct$, and $\vtetwostruct$, respectively\ProseOrTypeError; - \item a check the AST labels of $\vtstruct$, $\vteonestruct$, and $\vtetwostruct$ are all the same and are either - $\TInt$ or $\TReal$ yields $\True$. Otherwise, the result is a type error, which short-circuits the entire rule. - The type error indicates that the types of - $\veone$, $\vetwo$ and the type $\vt$ must be either of integer type or of real type. - \item $\newp$ is a range pattern with bounds $\veonep$ and $\vetwop$, that is, $\PatternRange(\veonep, \vetwop)$. -\end{itemize} - -\isempty{\subsection{Example}} - -\CodeSubsection{\PRangeBegin}{\PRangeEnd}{../Typing.ml} - -\subsection{Formally} -\begin{mathpar} -\inferrule{ - \annotateexpr{\tenv, \veone} \typearrow (\vteone, \veonep) \OrTypeError\\\\ - \annotateexpr{\tenv, \vetwo} \typearrow (\vtetwo, \vetwop) \OrTypeError\\\\ - \tstruct(\tenv, \vt) \typearrow \vtstruct \OrTypeError\\\\ - \tstruct(\tenv, \vteone) \typearrow \vteonestruct \OrTypeError\\\\ - \tstruct(\tenv, \vtetwo) \typearrow \vtetwostruct \OrTypeError\\\\ - { - \begin{array}{rl} - \vb \eqdef& \astlabel(\vtstruct) = \astlabel(\vteonestruct) = \astlabel(\vtetwostruct)\ \land\\ - & \astlabel(\vtstruct) \in \{\TInt, \TReal\} - \end{array} - }\\ - \checktrans{\vb}{InvalidTypesForBinop} \checktransarrow \True \OrTypeError -}{ - \annotatepattern(\tenv, \vt, \overname{\PatternRange(\veone, \vetwo)}{\vp}) \typearrow \overname{\PatternRange(\veonep, \vetwop)}{\newp} -} -\end{mathpar} - -\isempty{\subsection{Comments}} - -\section{TypingRule.PSingle \label{sec:TypingRule.PSingle}} - -\subsection{Prose} -All of the following apply: -\begin{itemize} - \item $\vp$ is the pattern that matches the expression $\ve$, that is, $\PatternSingle(\ve)$; - \item annotating the expression $\ve$ in $\tenv$ yields $(\vte, \vep)$\ProseOrTypeError; - \item obtaining the \structure\ of $\vt$ yields $\vtstruct$\ProseOrTypeError; - \item obtaining the \structure\ of $\vte$ yields $\testruct$\ProseOrTypeError; - \item One of the following holds: - \begin{itemize} - \item All of the following apply (\textsc{t\_bool, t\_real, t\_int}): - \begin{itemize} - \item the AST label of $\vtstruct$ is one of $\TBool$, $\TReal$, or $\TInt$; - \item checking that the labels of $\vtstruct$ and $\testruct$ are equal yields $\True$\ProseOrTypeError; - \end{itemize} - - \item All of the following apply (\textsc{t\_bits}): - \begin{itemize} - \item the AST label of $\vtstruct$ is $\TBits$; - \item checking that the labels of $\vtstruct$ and $\testruct$ are equal yields $\True$\ProseOrTypeError; - \item determining whether the bitwidths of $\vtstruct$ and $\testruct$ are equal yields $\True$\ProseOrTypeError; - \end{itemize} - - \item All of the following apply (\textsc{t\_enum}): - \begin{itemize} - \item the AST label of $\vtstruct$ is $\TEnum$; - \item checking that the labels of $\vtstruct$ and $\testruct$ are equal yields $\True$\ProseOrTypeError; - \item determining whether the lists of enumeration literals of $\vtstruct$ and $\testruct$ are equal yields $\True$\ProseOrTypeError; - \end{itemize} - - \item All of the following apply (\textsc{error}): - \begin{itemize} - \item determining whether the labels of $\vtstruct$ and $\testruct$ are the same yields $\True$\ProseOrTypeError; - \item the label of $\vtstruct$ is not one of $\TBool$, $\TReal$, $\TInt$, $\TBits$, or $\TEnum$; - \item the result is a type error indicating that the types $\vt$ and $\vte$ are inappropriate for this pattern. - \end{itemize} - \end{itemize} - \item $\newp$ is the pattern that matches the expression $\vep$, that is, $\PatternSingle(\vep)$. -\end{itemize} - -\isempty{\subsection{Example}} - -\CodeSubsection{\PSingleBegin}{\PSingleEnd}{../Typing.ml} - -\subsection{Formally} -\begin{mathpar} -\inferrule[t\_bool, t\_real, t\_int]{ - \annotateexpr{\tenv, \ve} \typearrow (\vte, \vep) \OrTypeError\\\\ - \tstruct(\tenv, \vt) \typearrow \vtstruct \OrTypeError\\\\ - \tstruct(\tenv, \vte) \typearrow \testruct \OrTypeError\\\\ - \commonprefixline\\\\ - \astlabel(\vtstruct) \in \{\TBool, \TReal, \TInt\}\\ - \checktrans{\astlabel(\vtstruct) = \astlabel(\testruct)}{\InvalidOperandTypesForBinop} \checktransarrow \True \OrTypeError -}{ - \annotatepattern(\tenv, \vt, \overname{\PatternSingle(\ve)}{\vp}) \typearrow \overname{\PatternSingle(\vep)}{\newp} -} -\end{mathpar} - -\begin{mathpar} -\inferrule[t\_bits]{ - \annotateexpr{\tenv, \ve} \typearrow (\vte, \vep) \OrTypeError\\\\ - \tstruct(\tenv, \vt) \typearrow \vtstruct \OrTypeError\\\\ - \tstruct(\tenv, \vte) \typearrow \vtestruct \OrTypeError\\\\ - \commonprefixline\\\\ - \astlabel(\vtstruct) = \TBits\\ - \checktrans{\astlabel(\vtstruct) = \astlabel(\testruct)}{\InvalidOperandTypesForBinop} \checktransarrow \True \OrTypeError\\ - \bitwidthequal(\tenv, \vtstruct, \testruct) \typearrow \vb\\ - \checktrans{\vb}{BitvectorsDifferentWidths} \checktransarrow \True \OrTypeError -}{ - \annotatepattern(\tenv, \vt, \overname{\PatternSingle(\ve)}{\vp}) \typearrow \overname{\PatternSingle(\vep)}{\newp} -} -\end{mathpar} - -\begin{mathpar} -\inferrule[t\_enum]{ - \annotateexpr{\tenv, \ve} \typearrow (\vte, \vep) \OrTypeError\\\\ - \tstruct(\tenv, \vt) \typearrow \vtstruct \OrTypeError\\\\ - \tstruct(\tenv, \vte) \typearrow \vtestruct \OrTypeError\\\\ - \commonprefixline\\\\ - \astlabel(\vtstruct) = \TEnum\\ - \checktrans{\astlabel(\vtstruct) = \astlabel(\testruct)}{\InvalidOperandTypesForBinop} \checktransarrow \True \OrTypeError\\ - \vtstruct \eqname \TEnum(\vlione)\\ - \vtestruct \eqname \TEnum(\vlitwo)\\ - \checktrans{\vlione = \vlitwo}{EnumDifferentLabels} \checktransarrow \True \OrTypeError\\ -}{ - \annotatepattern(\tenv, \vt, \overname{\PatternSingle(\ve)}{\vp}) \typearrow \overname{\PatternSingle(\vep)}{\newp} -} -\end{mathpar} - -\begin{mathpar} -\inferrule[error]{ - \annotateexpr{\tenv, \ve} \typearrow (\vte, \vep) \OrTypeError\\\\ - \tstruct(\tenv, \vt) \typearrow \vtstruct \OrTypeError\\\\ - \tstruct(\tenv, \vte) \typearrow \testruct \OrTypeError\\\\ - \commonprefixline\\\\ - \checktrans{\astlabel(\vtstruct) = \astlabel(\testruct)}{\InvalidOperandTypesForBinop} \checktransarrow \True \OrTypeError\\ - \astlabel(\vtstruct) \not\in \{\TBool, \TReal, \TInt, \TBits, \TEnum\} -}{ - \annotatepattern(\tenv, \vt, \overname{\PatternSingle(\ve)}{\vp}) \typearrow \TypeErrorVal{TypeConflict} -} -\end{mathpar} - -\isempty{\subsection{Comments}} - -\section{TypingRule.PMask \label{sec:TypingRule.PMask}} - -\subsection{Prose} -All of the following apply: - \begin{itemize} - \item $\vp$ is the pattern which matches a mask $\vm$, that is, $\PatternMask(\vm)$; - \item determining whether $\vt$ has the structure of a bitvector type yields $\True$\ProseOrTypeError; - \item $\vn$ is the length of mask $\vm$; - \item determining whether $\vt$ \typesatisfies\ the bitvector type of length $\vn$ \\ - (that is, $\TBits(\vn, \emptylist)$), yields $\True$\ProseOrTypeError; - \item $\newp$ is $\vp$. -\end{itemize} - -\isempty{\subsection{Example}} - -\CodeSubsection{\PMaskBegin}{\PMaskEnd}{../Typing.ml} - -\subsection{Formally} -\begin{mathpar} -\inferrule{ - \checkstructurelabel(\tenv, \vt, \TBits) \typearrow \True \OrTypeError\\\\ - \vn \eqdef \listlen{\vm}\\ - \checktypesat(\tenv, \vt, \TBits(\vn, \emptylist)) \typearrow \True \OrTypeError -}{ - \annotatepattern(\tenv, \vt, \overname{\PatternMask(\vm)}{\vp}) \typearrow \overname{\PatternMask(\vm)}{\newp} -} -\end{mathpar} - -\isempty{\subsection{Comments}} -\lrmcomment{This is related to \identi{VMKF}.} - -\section{TypingRule.PTuple \label{sec:TypingRule.PTuple}} - -\subsection{Prose} -All of the following apply: - \begin{itemize} - \item $\vp$ is the pattern which matches a tuple $\vli$, that is, $\PatternTuple(\vli)$; - \item obtaining the \structure\ of $\vt$ yields $\vtstruct$\ProseOrTypeError; - \item determining whether $\vtstruct$ is a tuple type yields $\True$\ProseOrTypeError; - \item $\vtstruct$ is a tuple type with list of tuple $\vts$; - \item determining whether $\vts$ is a list of the same size as $\vli$ yields $\True$\ProseOrTypeError; - \item annotating each pattern in $\vli$ with the corresponding type in $\vts$ at each position $\vi$ - yields a pattern $\vlip[\vi]$\ProseOrTypeError; - \item $\newli$ is the list of annotated patterns $\vlip[\vi]$ at the same positions those of $\vli$; - \item $\newp$ is the pattern which matches the tuple $\newli$, that is, $\PatternTuple(\newli)$. - \end{itemize} - -\isempty{\subsection{Example}} - -\CodeSubsection{\PTupleBegin}{\PTupleEnd}{../Typing.ml} - -\subsection{Formally} -\begin{mathpar} -\inferrule{ - \tstruct(\tenv, \vt) \typearrow \vtstruct \OrTypeError\\\\ - \checktrans{\astlabel(\vtstruct) = \TTuple}{TypeConflict} \checktransarrow \True \OrTypeError\\\\ - \vtstruct \eqname \TTuple(\vts)\\ - \checktrans{\equallength(\vli, \vts)}{InvalidArity} \checktransarrow \True \OrTypeError\\\\ - \vi\in\listrange(\vli): \annotatepattern(\tenv, \vts[\vi], \vli[\vi]) \typearrow \vlip[i] \OrTypeError\\\\ - \newli \eqdef \vi\in\listrange(\vli): \vlip[\vi] -}{ - \annotatepattern(\tenv, \vt, \overname{\PatternTuple(\vli)}{\vp}) \typearrow \overname{\PatternTuple(\newli)}{\newp} -} -\end{mathpar} - -\isempty{\subsection{Comments}} - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -\chapter{Typing of Local Declarations} -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -\hypertarget{def-annotatelocaldeclitem}{} -The function -\[ - \begin{array}{c} - \annotatelocaldeclitem{ - \overname{\ty}{\tty} \aslsep - \overname{\staticenvs}{\tenv} \aslsep - \overname{\localdeclkeyword}{\ldk} \aslsep - \overname{\localdeclitem}{\ldi} - } \aslto\\ - (\overname{\staticenvs}{\newtenv} \aslsep \overname{\localdeclitem}{\newldi}) - \cup \overname{\TTypeError}{\TypeErrorConfig} - \end{array} -\] -annotates a local declaration item $\ldi$ with a local declaration keyword $\ldk$, given a type $\tty$, -in a static environment $\tenv$ results in $(\newenv, \newldi)$ where $\newenv$ is the modified -static environment and $\newldi$ is the annotated local declaration item. -\ProseOtherwiseTypeError - -One of the following applies: -\begin{itemize} -\item TypingRule.LDDiscard (see \secref{TypingRule.LDDiscard}), -\item TypingRule.LDVar (see \secref{TypingRule.LDVar}), -\item TypingRule.LDTyped (see \secref{TypingRule.LDTyped}), -\item TypingRule.LDTuple (see \secref{TypingRule.LDTuple}). -\end{itemize} - -\lrmcomment{This is related to \identr{YSPM}.} - -We also define the following helper rule: -TypingRule.CheckCanBeInitializedWith \secref{TypingRule.CheckCanBeInitializedWith}. - -\section{TypingRule.LDDiscard \label{sec:TypingRule.LDDiscard}} - -\subsection{Prose} -All of the following apply: -\begin{itemize} - \item $\ldi$ is a local declaration which can be discarded, that is, $\LDIDiscard(\None)$; - \item $\newenv$ is $\tenv$; - \item $\newldi$ is $\ldi$. -\end{itemize} - -\subsection{Example} -\VerbatimInput{../tests/ASLTypingReference.t/TypingRule.LDDiscard.asl} - -\CodeSubsection{\LDDiscardBegin}{\LDDiscardEnd}{../Typing.ml} - -\subsection{Formally} -\begin{mathpar} -\inferrule{}{ - \annotatelocaldeclitem{\tenv, \tty, \LDIDiscard(\None), \ldk} \typearrow (\tenv, \ldi) -} -\end{mathpar} - -\isempty{\subsection{Comments}} - -\section{TypingRule.LDVar \label{sec:TypingRule.LDVar}} - -\subsection{Prose} -All of the following apply: -\begin{itemize} - \item $\ldi$ denotes a variable $\vx$, that is, $\LDIVar(\vx)$; - \item determining whether $\vx$ is not declared in $\tenv$ yields $\True$\ProseOrTypeError; - \item $\newenv$ is $\tenv$ modified so that $\vx$ is locally declared to have type $\tty$; - \item $\newldi$ is the declaration of variable $\vx$. -\end{itemize} - -\subsection{Example} -\VerbatimInput{../tests/ASLTypingReference.t/TypingRule.LDVar.asl} - -\CodeSubsection{\LDVarBegin}{\LDVarEnd}{../Typing.ml} - -\subsection{Formally} -\begin{mathpar} -\inferrule{ - \checkvarnotinenv{\tenv, \vx} \typearrow \True \OrTypeError\\\\ - \addlocal(\tenv, \vx, \tty, \ldk) \typearrow \newtenv -}{ - \annotatelocaldeclitem{\tenv, \tty, \LDIVar(\vx), \ldk} \typearrow (\newtenv, \LDIVar(\vx)) -} -\end{mathpar} - -\isempty{\subsection{Comments}} -\lrmcomment{This is related to \identr{YSPM}, \identd{FXST}.} - -\section{TypingRule.LDTyped\label{sec:TypingRule.LDTyped}} - -\subsection{Prose} -All of the following apply: -\begin{itemize} - \item $\ldi$ denotes a local declaration item $\ldip$ with local declaration keyword $\ldk$ - and a type $\vt$, that is $\LDITyped(\ldip, \vt)$; - \item annotating the type $\vt$ in $\tenv$ yields $\vtp$\ProseOrTypeError; - \item determining whether $\vtp$ can be initialized with $\tty$ in $\tenv$ yields $\True$\ProseOrTypeError; - \item annotating the local declaration item $\ldip$ with the local declaration keyword $\ldk$, given - the type $\vt$, in the environment $\tenv$, yields $(\newtenv,\newldip)$; - \item $\newldi$ is the local declaration denoting $\newldip$ and the type $\vtp$, that is, \\ - $\LDITyped(\newldip, \vtp)$. -\end{itemize} - -\subsection{Example} -\VerbatimInput{../tests/ASLTypingReference.t/TypingRule.LDTyped.asl} - -\CodeSubsection{\LDTypedBegin}{\LDTypedEnd}{../Typing.ml} - -\subsection{Formally} -\begin{mathpar} -\inferrule{ - \annotatetype{\tenv, \vt} \typearrow \vtp \OrTypeError\\\\ - \checkcanbeinitializedwith(\tenv, \vtp, \tty) \typearrow \True \OrTypeError\\\\ - \annotatelocaldeclitem{\tenv, \vtp, \ldip, \ldk} \typearrow (\newtenv, \newldip) \OrTypeError -} -{ - \annotatelocaldeclitem{\tenv, \tty, \LDITyped(\ldip, \vt), \ldk} \typearrow \\ - (\newtenv, \LDITyped(\newldip, \vtp)) -} -\end{mathpar} - -\isempty{\subsection{Comments}} - -\section{TypingRule.LDTuple\label{sec:TypingRule.LDTuple}} -\subsection{Prose} -All of the following apply: -\begin{itemize} - \item $\ldi$ denotes a tuple of local declaration items $\ldi_{1..k}$, that is, $\LDITuple(\ldi_{1..k})$; - \item determining the \structure\ of $\tty$ in $\tenv$ yields $\vtp$\ProseOrTypeError; - \item determining whether $\vtp$ is a tuple type yields $\True$\ProseOrTypeError; - \item determining whether $\vtp$ the number of elements of $\vtp$ is $k$ yields $\True$\ProseOrTypeError; - \item annotating the local declaration items in $\ldis$ from right to left with their corresponding - (that is, with the same index) types $t_{1..k}$ in $\tenv$, - propagating static environments from one annotation to the next, - yields the local declaration items $\ldip_{1..k}$\ProseOrTypeError; - \item $\newtenv$ is the static environment yielded by annotating $\ldi_1$; - \item $\newldi$ is a tuple of local declaration items with $\ldip_{1..k}$, that is, \\ - $\LDITuple(\ldip_{1..k})$. -\end{itemize} - -\subsection{Example} -\VerbatimInput{../tests/ASLTypingReference.t/TypingRule.LDTuple.asl} - -\CodeSubsection{\LDTupleBegin}{\LDTupleEnd}{../Typing.ml} - -\subsection{Formally} -\begin{mathpar} -\inferrule{ - \tstruct(\tenv, \tty) \typearrow \vtp \OrTypeError\\\\ - \checktrans{\astlabel(\vtp) = \TTuple}{TupleTypeExpected} \checktransarrow \True \OrTypeError\\\\ - \vtp \eqname \TTuple([\vt_{1..n}])\\\\ - \checktrans{k = n}{InvalidArity} \checktransarrow \True \OrTypeError\\\\ - \newtenv_k = \tenv\\ - { - \begin{array}{r} - i=k..1: - \annotatelocaldeclitem{\newtenv_{i}, \vt_{i}, \ldi_{i}, \ldk} \typearrow \\ - (\newtenv_{i-1}, \ldip_i) \OrTypeError - \end{array} - }\\ - \newtenv = \newtenv_0 -}{ - \annotatelocaldeclitem{\tenv, \tty, \LDITuple(\ldi_{1..k}), \ldk} \typearrow \\ - (\newtenv, \LDITuple(\ldip_{1..k})) -} -\end{mathpar} - -\isempty{\subsection{Comments}} - -\section{TypingRule.CheckCanBeInitializedWith \label{sec:TypingRule.CheckCanBeInitializedWith}} -\hypertarget{def-checkcanbeinitializedwith}{} -The function -\[ -\checkcanbeinitializedwith(\overname{\staticenvs}{\tenv} \aslsep \overname{\ty}{\vs} \aslsep \overname{\ty}{\vt}) -\typearrow \{\True\} \cup \overname{\TTypeError}{\TypeErrorConfig} -\] -checks whether an expression of type $\vs$ can be used to initialize a storage element of type $\vt$ in the static environment -$\tenv$. -If the answer if $\False$, the result is a type error. - -\subsection{Prose} -One of the following applies: -\begin{itemize} - \item All of the following apply (\textsc{okay}): - \begin{itemize} - \item testing whether $\vt$ \typesatisfies\ $\vs$ in $\tenv$ yields $\True$; - \item the result is $\True$. - \end{itemize} - - \item All of the following apply (\textsc{error}): - \begin{itemize} - \item testing whether $\vt$ \typesatisfies\ $\vs$ in $\tenv$ yields $\False$; - \item the result is a type error indicating that an expression of type $\vs$ cannot - be used to initialize a storage element of type $\vt$. - \end{itemize} -\end{itemize} - -\subsection{Formally} -\begin{mathpar} -\inferrule[okay]{ - \typesatisfies(\tenv, \vt, \vs) \typearrow \True -}{ - \checkcanbeinitializedwith(\tenv, \vs, \vt) \typearrow \True -} -\end{mathpar} - -\begin{mathpar} -\inferrule[error]{ - \typesatisfies(\tenv, \vt, \vs) \typearrow \False -}{ - \checkcanbeinitializedwith(\tenv, \vs, \vt) \typearrow \TypeErrorVal{CannotBeInitializedWith} -} -\end{mathpar} - -\isempty{\subsection{Comments}} -\lrmcomment{This is related to \identr{ZCVD} and \identr{LXQZ}.} - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -\chapter{Typing of Statements} -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -\hypertarget{def-annotatestmt}{} -The function -\[ - \annotatestmt(\overname{\staticenvs}{\tenv} \aslsep \overname{\stmt}{\vs}) \aslto - (\overname{\stmt}{\news}\aslsep \overname{\staticenvs}{\newenv}) - \cup \overname{\TTypeError}{\TypeErrorConfig} -\] -annotates a statement $\vs$ in an environment $\tenv$, resulting in the annotated statement -$\news$ and a modified environment $\newenv$. \ProseOtherwiseTypeError - -One of the following applies: -\begin{itemize} - \item TypingRule.SPass (see \secref{TypingRule.SPass}), - \item TypingRule.SAssign (see \secref{TypingRule.SAssign}), - \item TypingRule.SReturnNone (see \secref{TypingRule.SReturnNone}), - \item TypingRule.SReturnOne (see \secref{TypingRule.SReturnOne}), - \item TypingRule.SReturnSome (see \secref{TypingRule.SReturnSome}), - \item TypingRule.SSeq (see \secref{TypingRule.SSeq}), - \item TypingRule.SCall (see \secref{TypingRule.SCall}), - \item TypingRule.SCond (see \secref{TypingRule.SCond}), - \item TypingRule.SCase (see \secref{TypingRule.SCase}), - \item TypingRule.SAssert (see \secref{TypingRule.SAssert}), - \item TypingRule.SWhile (see \secref{TypingRule.SWhile}), - \item TypingRule.SRepeat (see \secref{TypingRule.SRepeat}), - \item TypingRule.SFor (see \secref{TypingRule.SFor}), - \item TypingRule.SThrowNone (see \secref{TypingRule.SThrowNone}), - \item TypingRule.SThrowSome (see \secref{TypingRule.SThrowSome}), - \item TypingRule.STry (see \secref{TypingRule.STry}). - \item TypingRule.SDeclSome (see \secref{TypingRule.SDeclSome}), - \item TypingRule.SDeclNone (see \secref{TypingRule.SDeclNone}). -\end{itemize} - -We also define the following helper functions: -\begin{itemize} - \item TypingRule.CaseAlt (see \secref{TypingRule.CaseAlt}), - \item TypingRule.SForConstraints (see \secref{TypingRule.SForConstraints}) - \item TypingRule.AnnotateLoopLimit (see \secref{TypingRule.AnnotateLoopLimit}) - \item TypingRule.DeclareLocalConstant (see \secref{TypingRule.DeclareLocalConstant}) - \item TypingRule.AnnotateLocalDelItemUninit (\secref{TypingRule.AnnotateLocalDelItemUninit}) -\end{itemize} - -\section{TypingRule.SPass \label{sec:TypingRule.SPass}} - -\subsection{Prose} -All of the following apply: -\begin{itemize} - \item $\vs$ is a pass statement, that is, $\SPass$; - \item $\news$ is $\vs$; - \item $\newenv$ is $\tenv$. -\end{itemize} - -\isempty{\subsection{Example}} - -\CodeSubsection{\SPassBegin}{\SPassEnd}{../Typing.ml} - -\subsection{Formally} -\begin{mathpar} -\inferrule{}{\annotatestmt(\tenv, \SPass) \typearrow (\SPass,\tenv)} -\end{mathpar} - -\isempty{\subsection{Comments}} - -\section{TypingRule.SAssign \label{sec:TypingRule.SAssign}} - -\subsection{Prose} -All of the following apply: -\begin{itemize} - \item $\vs$ is an assignment \texttt{le = re}, that is, $\SAssign(\vle, \vre)$; - \item One of the following applies: - \begin{itemize} - \item All of the following apply (\textsc{setter}): - \begin{itemize} - \item reducing $(\tenv, \vle, \vre)$ to a setter call via \\ $\inlinesetter$ yields the statement $\news$ - (indicating that the assignment corresponds to setter)\ProseOrTypeError; - \item $\newenv$ is $\tenv$. - \end{itemize} - - \item All of the following apply (\textsc{non\_setter}): - \begin{itemize} - \item reducing $(\tenv, \vle, \vre)$ to a setter call via \\ $\inlinesetter$ yields $\None$ - (indicating the assignment does not correspond to a setter); - \item annotating the right-hand-side expression $\vre$ in $\tenv$ yields $(\vtre, \vreone)$\ProseOrTypeError; - \item annotating the left-hand-side expression $\vle$ with the type $\vtre$ in $\tenv$ yields $\vleone$\ProseOrTypeError; - \item $\news$ is the assignment \texttt{le1 = re1}, that is, $\SAssign(\vleone, \vreone)$; - \item $\newenv$ is $\tenv$. - \end{itemize} - - \end{itemize} -\end{itemize} - -\isempty{\subsection{Example}} - -\CodeSubsection{\SAssignBegin}{\SAssignEnd}{../Typing.ml} - -\subsection{Formally} -\begin{mathpar} -\inferrule[setter]{ - \inlinesetter(\tenv, \vle, \vre) \typearrow \langle \news \rangle \OrTypeError\\ -}{ - \annotatestmt(\tenv, \overname{\SAssign(\vle, \vre)}{\vs}) \typearrow (\news,\overname{\tenv}{\newtenv}) -} -\and -\inferrule[non\_setter]{ - \inlinesetter(\tenv, \vle, \vre) \typearrow \None \OrTypeError\\\\ - \annotateexpr{\tenv, \vre} \typearrow (\vtre, \vreone) \OrTypeError\\\\ - \annotatelexpr{\tenv, \vle, \vtre} \typearrow \vleone \OrTypeError -}{ - \annotatestmt(\tenv, \overname{\SAssign(\vle, \vre)}{\vs}) \typearrow (\overname{\SAssign(\vleone, \vreone)}{\news},\overname{\tenv}{\newtenv}) -} -\end{mathpar} - -\isempty{\subsection{Comments}} - -\section{TypingRule.SReturnNone \label{sec:TypingRule.SReturnNone}} - -\subsection{Prose} -All of the following apply: -\begin{itemize} - \item $\vs$ is a \texttt{return} statement with no expression, that is, $\SReturn(\None)$; - \item the enclosing subprogram does not have a \texttt{return} type (it is either a setter - or a procedure); - \item $\news$ is a \texttt{return} statement with no expression, that is, $\SReturn(\None)$; - \item $\newenv$ is $\tenv$. -\end{itemize} - -\isempty{\subsection{Example}} - -\CodeSubsection{\SReturnNoneBegin}{\SReturnNoneEnd}{../Typing.ml} - -\subsection{Formally} -\begin{mathpar} -\inferrule{ - L^\tenv.\returntype = \None -}{ - \annotatestmt(\tenv, \overname{\SReturn(\None)}{\vs}) \typearrow (\overname{\SReturn(\None)}{\news}, \overname{\tenv}{\newtenv}) -} -\end{mathpar} - -\isempty{\subsection{Comments}} -\lrmcomment{This is related to \identr{FTPK}.} - -\section{TypingRule.SReturnOne \label{sec:TypingRule.SReturnOne}} - -\subsection{Prose} -All of the following apply: -\begin{itemize} -\item One of the following applies: - \begin{itemize} - \item All of the following apply (\textsc{return\_expr\_no\_return\_type}): - \begin{itemize} - \item $\vs$ is a \texttt{return} statement with some expression; - \item the enclosing subprogram does not have a return type; - \end{itemize} - \item All of the following apply (\textsc{return\_type\_no\_return\_expr}): - \begin{itemize} - \item $\vs$ is a \texttt{return} statement with no expression; - \item the enclosing subprogram has a returned type; - \end{itemize} - \end{itemize} - \item the result is an error indicating the mismatch between the declared (existence of the) return type - and the (existence of the) return expression. -\end{itemize} - -\isempty{\subsection{Example}} - -\CodeSubsection{\SReturnOneBegin}{\SReturnOneEnd}{../Typing.ml} - -\subsection{Formally} -\begin{mathpar} -\inferrule[return\_expr\_no\_return\_type]{ - L^\tenv.\returntype = \None -}{ - \annotatestmt(\tenv, \overname{\SReturn(\langle\Ignore\rangle)}{\vs}) \typearrow \TypeErrorVal{InvalidReturnStmt} -} -\and -\inferrule[return\_type\_no\_return\_expr]{ - L^\tenv.\returntype = \langle\Ignore\rangle -}{ - \annotatestmt(\tenv, \overname{\SReturn(\None)}{\vs}) \typearrow \TypeErrorVal{InvalidReturnStmt} -} -\end{mathpar} - -\isempty{\subsection{Comments}} -\lrmcomment{This is related to \identr{FTPK}.} - -\section{TypingRule.SReturnSome \label{sec:TypingRule.SReturnSome}} - -\subsection{Prose} -All of the following apply: -\begin{itemize} - \item $\vs$ is a \texttt{return} statement with an expression $\ve$, that is, $\SReturn(\langle \vep \rangle)$; - \item the enclosing subprogram has a return type $\vt$; - \item annotating the right-hand-side expression $\ve$ in $\tenv$ yields $(\tep,\vep)$\ProseOrTypeError; - \item checking whether $\vtep$ \typesatisfies\ $\vt$ in $\tenv$ yields $\True$\ProseOrTypeError; - \item $\news$ is a \texttt{return} statement with value $\vep$, that is, $\SReturn(\langle \vep \rangle)$; - \item $\newenv$ is $\tenv$. -\end{itemize} - -\isempty{\subsection{Example}} - -\CodeSubsection{\SReturnSomeBegin}{\SReturnSomeEnd}{../Typing.ml} - -\subsection{Formally} -\begin{mathpar} -\inferrule{ - L^\tenv.\returntype = \langle \vt \rangle\\ - \annotateexpr{\tenv, \ve} \typearrow (\vtep, \vep) \OrTypeError\\\\ - \checktypesat(\tenv, \vtep, \vt) \typearrow \True \OrTypeError -}{ - \annotatestmt(\tenv, \overname{\SReturn(\langle \ve \rangle)}{\vs}) \typearrow - (\overname{\SReturn(\langle \vep \rangle)}{\news}, \overname{\tenv}{\newtenv}) -} -\end{mathpar} - -\isempty{\subsection{Comments}} -\lrmcomment{This is related to \identr{FTPK}.} - -\section{TypingRule.SSeq \label{sec:TypingRule.SSeq}} - -\subsection{Prose} -All of the following apply: -\begin{itemize} - \item $\vs$ is the AST node for the sequence of statements $\vsone$ and $\vstwo$, that is, $\SSeq(\vsone, \vstwo)$; - \item annotating $\vsone$ in $\tenv$ yields $(\newsone, \tenvone)$\ProseOrTypeError; - \item annotating $\vstwo$ in $\tenvone$ yields $(\newstwo, \newtenv)$\ProseOrTypeError; - \item $\news$ is the AST node for the sequence of statements $\newsone$ and $\newstwo$, that is, $\SSeq(\newsone, \newstwo)$. -\end{itemize} - -\isempty{\subsection{Example}} - -\CodeSubsection{\SSeqBegin}{\SSeqEnd}{../Typing.ml} - -\subsection{Formally} -\begin{mathpar} -\inferrule{ - \annotatestmt(\tenv, \vs1) \typearrow (\newsone, \tenvone) \OrTypeError\\\\ - \annotatestmt(\tenvone, \vs2) \typearrow (\newstwo, \newtenv) \OrTypeError -}{ - \annotatestmt(\tenv, \overname{\SSeq(\vsone, \vstwo)}{\vs}) \typearrow (\overname{\SSeq(\newsone, \newstwo)}{\news}, \newtenv) -} -\end{mathpar} - -\isempty{\subsection{Comments}} - -\section{TypingRule.SCall \label{sec:TypingRule.SCall}} - -\subsection{Prose} -All of the following apply: -\begin{itemize} - \item $\vs$ is a call to a subprogram named $\name$ with arguments $\vargs$; - \item annotating the call to $\name$ with arguments $\vargs$, as a procedure (that is, with $\STProcedure$), - as per \chapref{TypingSubprogramCalls} (which makes sure that the call does not have a return type), - yields $(\newname, \newargs, \eqs, \None)$\ProseOrTypeError; - \item $\news$ is the call to a subprogram named $\newname$ with arguments - $\newargs$ and parameter assignments $\neweqs$; - \item $\newtenv$ is $\tenv$. -\end{itemize} - -\isempty{\subsection{Example}} - -\CodeSubsection{\SCallBegin}{\SCallEnd}{../Typing.ml} - -\subsection{Formally} -\begin{mathpar} -\inferrule{ - { - \begin{array}{r} - \annotatecall(\tenv, \name, \vargs, \STProcedure) \typearrow \\ (\newname, \newargs, \eqs, \None) \OrTypeError - \end{array} - } -}{ - { - \begin{array}{r} - \annotatestmt(\tenv, \overname{\SCall(\name, \vargs)}{\vs}) \typearrow \\ - (\overname{\SCall(\newname, \newargs, \eqs)}{\news}, \tenv) - \end{array} - } -} -\end{mathpar} - -\subsection{Comments} -Notice that the input statement, which belongs to the untyped AST, has two children nodes --- -$\name$ and $\vargs$, whereas the output statement, which belongs to the typed AST has the additional -node $\neweqs$, which associates expressions with parameters. - -\lrmcomment{This is related to \identd{VXKM}.} - -\section{TypingRule.SCond \label{sec:TypingRule.SCond}} - -\subsection{Prose} -All of the following apply: -\begin{itemize} - \item $\vs$ is a condition $\ve$ with the statements $\vsone$ and $\vstwo$, that is, $\SCond(\ve, \vsone, \vstwo)$; - \item annotating the right-hand-side expression $\ve$ in $\tenv$ yields $(\tcond, \econd)$\ProseOrTypeError; - \item checking that $\tcond$ \typesatisfies\ $\TBool$ yields $\True$\ProseOrTypeError; - \item annotating the statement $\vsone$ in $\tenv$ yields $\vsonep$\ProseOrTypeError; - \item annotating the statement $\vstwo$ in $\tenv$ yields $\vstwop$\ProseOrTypeError; - \item $\news$ is the condition $\econd$ with the statements $\vsonep$ and $\vstwop$, that is, \\ $\SCond(\econd, \vsonep, \vstwop)$; - \item $\newenv$ is $\tenv$. -\end{itemize} - -\isempty{\subsection{Example}} - -\CodeSubsection{\SCondBegin}{\SCondEnd}{../Typing.ml} - -\subsection{Formally} -\begin{mathpar} -\inferrule{ - \annotateexpr{\tenv, \ve} \typearrow (\tcond, \econd) \OrTypeError\\\\ - \checktypesat(\tenv, \tcond, \TBool) \typearrow \True \OrTypeError\\\\ - \annotateblock{\tenv, \vsone} \typearrow \vsonep \OrTypeError\\\\ - \annotateblock{\tenv, \vstwo} \typearrow \vstwop \OrTypeError -}{ - \annotatestmt(\tenv, \overname{\SCond(\ve, \vsone, \vstwo)}{\vs}) \typearrow - (\overname{\SCond(\econd, \vsonep, \vstwop)}{\news}, \overname{\tenv}{\newtenv}) -} -\end{mathpar} - -\isempty{\subsection{Comments}} -\lrmcomment{This is related to \identr{NBDJ}.} - -\section{TypingRule.SCase \label{sec:TypingRule.SCase}} - -\subsection{Prose} -All of the following apply: -\begin{itemize} - \item $\vs$ is a case statement with expression $\ve$ and case clauses $\vcases$, that is, \\ - $\SCase(\veone, \vcasesone)$; - \item annotating the right-hand-side expression $\ve$ in $\tenv$ yields $(\vte, \veone)$\ProseOrTypeError; - \item annotating each case clause as per \secref{TypingRule.CaseAlt} in $\vcases$ yields the annotated list of clauses $\vcasesone$\ProseOrTypeError; - \item $\news$ is a case statement with expression $\veone$ and case clauses $\vcasesone$; - \item $\newenv$ is $\tenvone$. -\end{itemize} - -\isempty{\subsection{Example}} - -\CodeSubsection{\SCaseBegin}{\SCaseEnd}{../Typing.ml} - -\subsection{Formally} -\begin{mathpar} -\inferrule{ - \annotateexpr{\tenv, \ve} \typearrow (\vte, \veone) \OrTypeError\\\\ - \vi\in\listrange(\vcases): \annotatecase{\tenv, \vcases[\vi]} \typearrow \vcase_\vi \OrTypeError\\\\ - \vcasesone \eqdef [\vi\in\listrange(\vcases): \vcase_\vi] -}{ - \annotatestmt(\tenv, \overname{\SCase(\ve, \vcases)}{\vs}) \typearrow - (\overname{\SCase(\veone, \vcasesone)}{\news}, \overname{\tenv}{\newtenv}) -} -\end{mathpar} - -\isempty{\subsection{Comments}} -\lrmcomment{This is related to \identr{WGSY}.} - -\section{TypingRule.SAssert \label{sec:TypingRule.SAssert}} -\subsection{Prose} -All of the following apply: -\begin{itemize} - \item $\vs$ is an assert statement with expression $\ve$, that is, $\SAssert(\ve)$; - \item annotating the right-hand-side expression $\ve$ in $\tenv$ yields $(\tep,\vep)$\ProseOrTypeError; - \item checking that $\vtep$ \typesatisfies\ $\TBool$ in $\tenv$ yields $\True$\ProseOrTypeError; - \item $\news$ is an assert statement with expression $\vep$, that is, $\SAssert(\vep)$; - \item $\newenv$ is $\tenv$. -\end{itemize} - -\isempty{\subsection{Example}} - -\CodeSubsection{\SAssertBegin}{\SAssertEnd}{../Typing.ml} - -\subsection{Formally} -\begin{mathpar} -\inferrule{ - \annotateexpr{\tenv, \ve} \typearrow (\vtep, \vep) \OrTypeError\\\\ - \checktypesat(\tenv, \vtep, \TBool) \typearrow \True \OrTypeError -}{ - \annotatestmt(\tenv, \overname{\SAssert(\ve)}{\vs}) \typearrow (\overname{\SAssert(\vep)}{\news}, \overname{\tenv}{\newtenv}) -} -\end{mathpar} - -\isempty{\subsection{Comments}} -\lrmcomment{This is related to \identr{JQYF}.} - -\section{TypingRule.SWhile \label{sec:TypingRule.SWhile}} -\subsection{Prose} -All of the following apply: -\begin{itemize} -\item $\vs$ is a \texttt{while} statement with expression $\veone$, optional limit expression $\vlimitone$, - and statement block $\vsone$, that is, $\SWhile(\veone, \vsone)$; -\item annotating the right-hand-side expression $\veone$ in $\tenv$ yields $(\vt, \vetwo)$\ProseOrTypeError; -\item annotating the optional limit expression $\vlimitone$ via $\annotatelooplimit$ in $\tenv$ yields $\vlimittwo$\ProseOrTypeError; -\item checking that $\vt$ \typesatisfies\ $\TBool$ in $\tenv$ yields $\True$\ProseOrTypeError; -\item $\news$ is a \texttt{while} statement with expression $\vetwo$, optional limit expression $\vlimittwo$, - and statement block $\vstwo$, that is, $\SWhile(\vetwo, \vstwo)$; -\item $\newenv$ is $\tenv$. -\end{itemize} - -\isempty{\subsection{Example}} - -\CodeSubsection{\SWhileBegin}{\SWhileEnd}{../Typing.ml} - -\subsection{Formally} -\begin{mathpar} -\inferrule{ - \annotateexpr{\tenv, \veone} \typearrow (\vt, \vetwo) \OrTypeError\\\\ - \annotatelooplimit(\tenv, \vlimitone) \typearrow \vlimittwo \OrTypeError\\\\ - \checktypesat(\tenv, \vt, \TBool) \typearrow \True \OrTypeError\\\\ - \annotateblock{\tenv, \vsone} \typearrow \vstwo \OrTypeError -}{ - \annotatestmt(\tenv, \overname{\SWhile(\veone, \vlimitone, \vsone)}{\vs}) \typearrow - (\overname{\SWhile(\vetwo, \vlimittwo, \vstwo)}{\news}, \overname{\tenv}{\newtenv}) -} -\end{mathpar} - -\isempty{\subsection{Comments}} -\lrmcomment{This is related to \identr{FTVN}.} - -\section{TypingRule.SRepeat \label{sec:TypingRule.SRepeat}} - -\subsection{Prose} -All of the following apply: -\begin{itemize} - \item $\vs$ is a \texttt{repeat} statement with statement block $\vsone$, - optional limit expression $\vlimitone$, and expression $\veone$, that is, $\SRepeat(\vsone, \veone, \vlimitone)$; - \item annotating $\vsone$ as a block statement in $\tenv$ yields $\vstwo$\ProseOrTypeError; - \item annotating the optional limit expression $\vlimitone$ via $\annotatelooplimit$ in $\tenv$ yields $\vlimittwo$\ProseOrTypeError; - \item annotating the right-hand-side expression $\veone$ in $\tenv$ yields $(\vt, \vetwo)$\ProseOrTypeError; - \item checking that $\vt$ \typesatisfies\ $\TBool$ in $\tenv$ yields $\True$\ProseOrTypeError; - \item $\news$ is a \texttt{repeat} statement with statement block $\vstwo$, optional limit expression $\vlimittwo$, - and condition expression $\vetwo$ and , that is, $\SRepeat(\vstwo, \vetwo, \vlimittwo)$; - \item $\newenv$ is $\tenv$. -\end{itemize} - -\isempty{\subsection{Example}} - -\CodeSubsection{\SRepeatBegin}{\SRepeatEnd}{../Typing.ml} - -\subsection{Formally} -\begin{mathpar} -\inferrule{ - \annotateblock{\tenv, \vsone} \typearrow \vstwo \OrTypeError\\\\ - \annotatelooplimit(\tenv, \vlimitone) \typearrow \vlimittwo \OrTypeError\\\\ - \annotateexpr{\tenv, \veone} \typearrow (\vt, \vetwo) \OrTypeError\\\\ - \checktypesat(\tenv, \vt, \TBool) \typearrow \True \OrTypeError -}{ - \annotatestmt(\tenv, \overname{\SRepeat(\vsone, \veone, \vlimitone)}{\vs}) \typearrow - (\overname{\SRepeat(\vstwo, \vetwo, \vlimittwo)}{\news}, \overname{\tenv}{\newtenv}) -} -\end{mathpar} - -\isempty{\subsection{Comments}} -\lrmcomment{This is related to \identr{FTVN}.} - -\section{TypingRule.SFor \label{sec:TypingRule.SFor}} -\subsection{Prose} -All of the following apply: -\begin{itemize} - \item $\vs$ is a \texttt{for} statement with index $\vindexname$, - start expression $\vstarte$, - direction $\dir$, - end expression $\vende$, - body statement (block) $\vbody$, - and optional limit expression $\vlimit$, - that is, $\SFor\left\{\begin{array}{rcl} - \Forindexname &:& \vindexname\\ - \Forstarte &:& \vstarte\\ - \fordirection &:& \vdirection\\ - \Forende &:& \vende\\ - \Forbody &:& \vbody\\ - \Forlimit &:& \vlimit - \end{array}\right\}$; - \item annotating the right-hand-side expression $\vstarte$ in $\tenv$ yields \\ - $(\vstartt, \vstartep)$\ProseOrTypeError; - \item annotating the right-hand-side expression $\vende$ in $\tenv$ yields $(\vendt, \vendep)$\ProseOrTypeError; - \item annotating the optional loop limit expression $\vlimit$ via $\annotatelooplimit$ in $\tenv$ - yields $\vlimitp$\ProseOrTypeError; - \item obtaining the \underlyingtype\ of $\vstartt$ in $\tenv$ yields $\vstartstruct$\ProseOrTypeError; - \item obtaining the \underlyingtype\ of $\vendt$ in $\tenv$ yields $\vendstruct$\ProseOrTypeError; - \item applying $\getforconstraints$ to $\vstartstruct$, $\vendstruct$, - $\vstartep$, $\vendep$, and $\dir$ in $\tenv$, - to obtain the constraints on the loop index $\vindexname$, - yields $\cs$\ProseOrTypeError; - \item $\tty$ is the integer type with constraints $\cs$; - \item checking that $\vindexname$ is not already declared in $\tenv$ yields $\True$\ProseOrTypeError; - \item adding $\vindexname$ as a local immutable variable with type $\tty$ to $\tenv$ yields $\tenvp$; - \item annotating $\vbody$ as a block statement in $\tenvp$ yields $\vbodyp$\ProseOrTypeError; - \item $\news$ is the \texttt{for} statement with index $\vindexname$, - start expression $\vstartep$, direction $\dir$, - end expression $\vendep$, - body statement (block) $\vbodyp$, and - optional limit expression $\vlimit$; - \item $\newtenv$ is $\tenv$ (notice that this means $\vindexname$ is only declared for annotating $\vbodyp$ but then goes - out of scope). -\end{itemize} - -\isempty{\subsection{Example}} - -\CodeSubsection{\SForBegin}{\SForEnd}{../Typing.ml} - -\subsection{Formally} -\begin{mathpar} -\inferrule{ - \annotateexpr{\tenv, \vstarte} \typearrow (\vstartt, \vstartep) \OrTypeError\\\\ - \annotateexpr{\tenv, \vende} \typearrow (\vendt, \vendep) \OrTypeError\\\\ - \annotatelooplimit(\tenv, \vlimit) \typearrow \vlimitp \OrTypeError\\\\ - \makeanonymous(\tenv, \vstartt) \typearrow \vstartstruct \OrTypeError\\\\ - \makeanonymous(\tenv, \vendt) \typearrow \vendstruct \OrTypeError\\\\ - { - \begin{array}{r} - \getforconstraints(\tenv, \vstartstruct, \vendstruct, \vstartep, \vendep, \dir) \typearrow \\ - \cs \OrTypeError - \end{array} - }\\\\ - \tty \eqdef \TInt(\cs)\\ - \checkvarnotinenv{\tenv, \vindexname} \typearrow \True \OrTypeError\\\\ - \addlocal(\tenv, \tty, \vindexname, \LDKLet) \typearrow \tenvp\\ - \annotateblock{\tenvp, \vbody} \typearrow \vbodyp \OrTypeError -}{ - { - \begin{array}{r} - \annotatestmt\left(\tenv, \overname{\SFor\left\{\begin{array}{rcl} - \Forindexname &:& \vindexname\\ - \Forstarte &:& \vstarte\\ - \fordirection &:& \vdirection\\ - \Forende &:& \vende\\ - \Forbody &:& \vbody\\ - \Forlimit &:& \vlimit - \end{array}\right\}}{\vs}\right) \typearrow \\ - \left(\overname{\SFor\left\{\begin{array}{rcl} - \Forindexname &:& \vindexname\\ - \Forstarte &:& \vstartep\\ - \fordirection &:& \vdirection\\ - \Forende &:& \vendep\\ - \Forbody &:& \vbodyp\\ - \Forlimit &:& \vlimitp - \end{array}\right\}}{\news}, \overname{\tenv}{\newtenv}\right) -\end{array} - } -} -\end{mathpar} - -\isempty{\subsection{Comments}} -\lrmcomment{This is related to \identr{SSBD}, \identr{ZSND}, \identr{VTJW}.} - -\section{TypingRule.SThrowNone \label{sec:TypingRule.SThrowNone}} - -\subsection{Prose} -All of the following apply: -\begin{itemize} - \item $\vs$ is a throw statement with no expression, that is, $\SThrow(\None)$; - \item $\news$ is $\vs$; - \item $\newenv$ is $\tenv$. -\end{itemize} - -\isempty{\subsection{Example}} - -\CodeSubsection{\SThrowNoneBegin}{\SThrowNoneEnd}{../Typing.ml} - -\subsection{Formally} -\begin{mathpar} -\inferrule{}{ - \annotatestmt(\tenv, \overname{\SThrow(\None)}{\vs}) \typearrow (\overname{\SThrow(\None)}{\news}, \overname{\tenv}{\newtenv}) -} -\end{mathpar} - -\isempty{\subsection{Comments}} -\lrmcomment{Note that \identr{BRCJ} is done in~\cite[SemanticsRule.TopLevel]{ASLSemanticsReference}.} - -\section{TypingRule.SThrowSome \label{sec:TypingRule.SThrowSome}} - -\subsection{Prose} -All of the following apply: -\begin{itemize} - \item $\vs$ is a throw statement with expression $\ve$, that is, $\SThrow(\langle\ve\rangle)$; - \item annotating the right-hand-side expression $\ve$ in $\tenv$ yields $(\vte, \vep)$\ProseOrTypeError; - \item checking that $\vte$ has the structure of an exception type yields $\True$\ProseOrTypeError; - \item $\news$ is a throw statement with expression $\vep$ and type $\vte$, that is, \\ - $\SThrow(\langle (\vep, \vte) \rangle)$; - \item $\newenv$ is $\tenv$. -\end{itemize} - -\isempty{\subsection{Example}} - -\CodeSubsection{\SThrowSomeBegin}{\SThrowSomeEnd}{../Typing.ml} - -\subsection{Formally} -\begin{mathpar} -\inferrule{ - \annotateexpr{\tenv, \ve} \typearrow (\vte, \vep) \OrTypeError\\\\ - \checkstructurelabel(\tenv, \vte, \TException) \typearrow \True \OrTypeError -}{ - \annotatestmt(\tenv, \overname{\SThrow(\langle\ve\rangle)}{\vs}) \typearrow - (\overname{\SThrow(\langle (\vep, \vte) \rangle)}{\news}, \overname{\tenv}{\newtenv}) -} -\end{mathpar} - -\isempty{\subsection{Comments}} -\lrmcomment{This is related to \identr{NXRC}.} - -\section{TypingRule.STry \label{sec:TypingRule.STry}} - -\subsection{Prose} -All of the following apply: -\begin{itemize} - \item $\vs$ is a try statement with statement $\vsp$, list of catchers $\catchers$ and an \optional\ \texttt{otherwise} block; - \item annotating the statement $\vsp$ as a block statement yields $\vspp$\ProseOrTypeError; - \item annotating each catcher $\catchers[\vi]$, for each $\vi$ in $\listrange(\catchers)$ in $\tenv$ yields $\vc\_\vi$\ProseOrTypeError; - \item $\catchersp$ is the list of annotated catchers $\vc\_\vi$ for each $\vi\in\listrange(\catchers)$; - \item One of the following applies: - \begin{itemize} - \item All of the following apply (\textsc{no\_otherwise}): - \begin{itemize} - \item there is no \texttt{otherwise} statement; - \item $\news$ is a try statement with statement $\vspp$, list catchers $\catchersp$ and no \texttt{otherwise} statement, - that is \\ - $\STry(\vspp, \catchersp, \None)$; - \end{itemize} - - \item All of the following apply (\textsc{otherwise}): - \begin{itemize} - \item there is an \texttt{otherwise} statement $\otherwise$; - \item annotating the statement $\otherwise$ as a block statement in $\tenv$ yields $\otherwisep$\ProseOrTypeError; - \item $\news$ is a try statement with statement $\vspp$, list catchers $\catchersp$ and \texttt{otherwise} statement - $\otherwisep$, that is \\ - $\STry(\vspp, \catchersp, \langle\otherwisep\rangle)$; - \end{itemize} - \end{itemize} - \item $\newenv$ is $\tenv$. -\end{itemize} - -\isempty{\subsection{Example}} - -\CodeSubsection{\STryBegin}{\STryEnd}{../Typing.ml} - -\subsection{Formally} -\begin{mathpar} -\inferrule[no\_otherwise]{ - \annotateblock{\tenv, \vsp} \typearrow \vspp \OrTypeError\\\\ - \vi\in\listrange(\catchers): \annotatecatcher{\tenv, \catchers[\vi]} \typearrow \vc_\vi \OrTypeError\\\\ - \catchersp \eqdef [\vi\in\listrange(\catchers) : \vc_\vi]\\\\ - \commonprefixline\\\\ - \news \eqdef \STry(\vspp, \catchersp, \None) -}{ - \annotatestmt(\tenv, \overname{\STry(\vsp, \catchers, \None)}{\vs}) \typearrow (\news, \overname{\tenv}{\newtenv}) -} -\and -\inferrule[otherwise]{ - \annotateblock{\tenv, \vsp} \typearrow \vspp \OrTypeError\\\\ - \vi\in\listrange(\catchers): \annotatecatcher{\tenv, \catchers[\vi]} \typearrow \vc_\vi \OrTypeError\\\\ - \catchersp \eqdef [\vi\in\listrange(\catchers) : \vc_\vi]\\\\ - \commonprefixline\\\\ - \annotateblock{\tenv, \otherwise} \typearrow \otherwisep \OrTypeError\\\\ - \news \eqdef \STry(\vspp, \catchersp, \otherwise') -}{ - \annotatestmt(\tenv, \overname{\STry(\vsp, \catchers, \langle\otherwise\rangle)}{\vs}) \typearrow (\news, \overname{\tenv}{\newtenv}) -} -\end{mathpar} - -\isempty{\subsection{Comments}} -\lrmcomment{This is related to \identr{WVXS}.} - -\section{TypingRule.SDeclSome \label{sec:TypingRule.SDeclSome}} - -\subsection{Prose} -All of the following apply: -\begin{itemize} - \item $\vs$ is a declaration with local declaration keyword $\ldk$, local identifiers $\ldi$, and an expression $\ve$, - that is, $\SDecl(\ldk, \ldi, \langle\ve\rangle)$; - \item annotating the right-hand-side expression $\ve$ in $\tenv$ yields $(\vte,\vep)$\ProseOrTypeError; - \item One of the following applies: - \begin{itemize} - \item All of the following apply (\textsc{constant}): - \begin{itemize} - \item $\ldk$ indicates a local constant declaration, that is, $\LDKConstant$; - \item symbolically simplifying $\ve$ in $\tenv$ yields the literal $\vv$\ProseOrTypeError; - \item declaring a local constant of type $\vte$, literal $\vv$ and identifier $\ldi$ in $\tenv$ yields $(\newtenv, \ldip)$; - \item $\news$ is a declaration with $\ldk$, $\ldip$ and an expression $\vep$. - \end{itemize} - - \item All of the following apply (\textsc{non\_constant}): - \begin{itemize} - \item $\ldk$ indicates that this is not a local constant declaration, that is, $\ldk\neq\LDKConstant$; - \item declaring the local identifiers $\ldi$ of type $\vte$ with local declaration keyword $\ldk$ in $\tenv$ - yields $(\newtenv, \ldip)$; - \item $\news$ is a declaration with $\ldk$, $\ldip$ and an expression $\vep$. - \end{itemize} - \end{itemize} -\end{itemize} - -\isempty{\subsection{Example}} - -\CodeSubsection{\SDeclSomeBegin}{\SDeclSomeEnd}{../Typing.ml} - -\subsection{Formally} -\begin{mathpar} -\inferrule[constant]{ - \annotateexpr{\tenv, \ve} \typearrow (\vte, \vep) \OrTypeError\\\\ - \ldk = \LDKConstant\\ - \reduceconstants(\tenv, \ve) \typearrow \vv \OrTypeError\\\\ - \declarelocalconstant(\tenv, \vv, \ldi) \typearrow \newtenv\\ - \news \eqdef \SDecl(\LDKConstant, \ldip, \langle\vep\rangle) -}{ - \annotatestmt(\tenv, \overname{\SDecl(\ldk, \ldi, \langle\ve\rangle)}{\vs}) \typearrow (\news, \newtenv) -} -\end{mathpar} - -\begin{mathpar} -\inferrule[non\_constant]{ - \annotateexpr{\tenv, \ve} \typearrow (\vte, \vep) \OrTypeError\\\\ - \ldk \neq \LDKConstant\\ - \annotatelocaldeclitem{\tenv, \vte, \ldk, \ldi} \typearrow (\newtenv, \ldip)\\ - \news \eqdef \SDecl(\ldk, \ldip, \langle\vep\rangle) -}{ - \annotatestmt(\tenv, \overname{\SDecl(\ldk, \ldi, \langle\ve\rangle)}{\vs}) \typearrow (\news, \newtenv) -} -\end{mathpar} - -\isempty{\subsection{Comments}} -\lrmcomment{This is related to \identr{YSPM}.} - -\section{TypingRule.SDeclNone \label{sec:TypingRule.SDeclNone}} - -\subsection{Prose} -All of the following apply: -\begin{itemize} -\item $\vs$ is a local declaration statement with a variable keyword and local identifiers $\ldi$, and no initial expression, - that is, $\SDecl(\LDKVar, \ldi, \None)$ (local declarations of \texttt{let} variables and constants require - an initializing expression, otherwise they are rejected by an ASL parser); -\item annotating the uninitialised local declarations $\ldi$ in $\tenv$ yields $(\newtenv, \ldip)$; -\item $\news$ is a local declaration statement with variable keyword, local identifiers $\ldip$, and no initial expression, - that is, $\SDecl(\LDKVar, \ldip, \None)$. -\end{itemize} - -\isempty{\subsection{Example}} - -\CodeSubsection{\SDeclNoneBegin}{\SDeclNoneEnd}{../Typing.ml} - -\subsection{Formally} -\begin{mathpar} -\inferrule{ - \annotatelocaldeclitemuninit(\tenv, \ldi) \typearrow (\newtenv, \ldip) \OrTypeError\\\\ - \news \eqdef \SDecl(\LDKVar, \ldip, \None) -}{ - \annotatestmt(\tenv, \overname{\SDecl(\LDKVar, \ldi, \None)}{\vs}) \typearrow (\news, \newtenv) -} -\end{mathpar} - -\isempty{\subsection{Comments}} - -\section{TypingRule.CaseAlt \label{sec:TypingRule.CaseAlt}} - -\hypertarget{def-annotatecase}{} -The helper function -\[ - \annotatecase{ - \overname{\staticenvs}{\tenv} \aslsep - \overname{\casealt}{\vcase} \aslsep - \overname{\ty}{\vte} - } \aslto - \overname{\casealt}{\vcaseone} \cup \overname{\TTypeError}{\TypeErrorConfig} -\] -annotates the case clause $\vcase$ for an expression of type $\vte$ in $\tenv$, -resulting in the annotated case clause $\vcaseone$. -\ProseOtherwiseTypeError - -\subsection{Prose} -All of the following apply: -\begin{itemize} - \item $\vcase$ is a case clause with pattern $\vpzero$, \optional\ \texttt{where} expression $\vwzero$, - and \texttt{otherwise} statement $\vszero$, that is, - $\{ \CasePattern: \vpzero, \CaseWhere: \vwzero, \CaseStmt: \vszero \}$; - \item annotating the pattern $\vpzero$ with type $\vte$ in $\tenv$ yields $\vpone$\ProseOrTypeError; - \item annotating the statement $\vszero$ as a block statement in $\tenv$ yields $\vsone$\ProseOrTypeError; - \item One of the following applies: - \begin{itemize} - \item All of the following apply (\textsc{no\_where\_stmt}): - \begin{itemize} - \item $\vwzero$ is $\None$ (that is, no \texttt{where} expression); - \item $\vcaseone$ is $\{ \CasePattern: \vpone, \CaseWhere: \None, \CaseStmt: \vsone \}$. - \end{itemize} - - \item All of the following apply (\textsc{where\_stmt}): - \begin{itemize} - \item $\vwzero$ is the singleton expression for $\vewzero$, that is, $\langle\vewzero\rangle$; - \item annotating the expression $\vewzero$ in $\tenv$ yields $(\vtwe, \vewone)$\ProseOrTypeError; - \item checking whether the structure of $\vtwe$ in $\tenv$ is that of the \texttt{boolean} type yields $\True$\ProseOrTypeError; - \item $\vcaseone$ is $\{ \CasePattern: \vpone, \CaseWhere: \langle\vewone\rangle, \CaseStmt: \vsone \}$. - \end{itemize} - \end{itemize} -\end{itemize} - -\subsection{Formally} -\begin{mathpar} -\inferrule[no\_where\_stmt]{ - \vcase = \{ \CasePattern: \vpzero, \CaseWhere: \None, \CaseStmt : \vszero \}\\ - \annotatepattern(\tenv, \vte, \vpzero) \typearrow \vpone \OrTypeError\\\\ - \annotateblock{\tenv, \vszero} \typearrow \vsone \OrTypeError\\ -}{ - \annotatecase{\tenv, \vcase, \vte} \typearrow \overname{\{ \CasePattern: \vpone, \CaseWhere: \None, \CaseStmt : \vsone \}}{\vcaseone} -} -\and -\inferrule[where\_stmt]{ - \vcase = \{ \CasePattern: \vpzero, \CaseWhere: \langle\vewzero\rangle, \CaseStmt : \vszero \}\\ - \annotatepattern(\tenv, \vte, \vpzero) \typearrow \vpone \OrTypeError\\\\ - \annotateblock{\tenv, \vszero} \typearrow \vsone \OrTypeError\\\\ - \annotateexpr{\tenv, \vewzero} \typearrow (\vtwe, \vewone) \OrTypeError\\\\ - \checkstructurelabel(\tenv, \vtwe, \TBool) \typearrow \True \OrTypeError -}{ - \annotatecase{\tenv, \vcase, \vte} \typearrow \overname{\{ \CasePattern: \vpone, \CaseWhere: \langle\vewone\rangle, \CaseStmt : \vsone \}}{\vcaseone} -} -\end{mathpar} - -\section{TypingRule.SForConstraints \label{sec:TypingRule.SForConstraints}} -\hypertarget{def-getforconstraints}{} -The function -\[ - \getforconstraints( - \overname{\staticenvs}{\tenv} \aslsep - \overname{\ty}{\structone} \aslsep - \overname{\ty}{\structtwo} \aslsep - \overname{\expr}{\veonep} \aslsep - \overname{\expr}{\vetwop} \aslsep - \overname{\dir}{\dir} - ) \aslto - \overname{\intconstraints}{\vis} \cup\ \overname{\TTypeError}{\TypeErrorConfig} -\] -infers the integer constraints for a \texttt{for} loop index variable from the following: -\begin{itemize} - \item the \wellconstrainedversion\ of the type of the start expression --- $\structone$ - \item the \wellconstrainedversion\ of the type of the end expression --- $\structtwo$ - \item the annotated start expression --- $\veonep$ - \item the annotated end expression --- $\vetwop$ - \item the loop direction --- $\dir$ -\end{itemize} -The result is $\vis$. -\ProseOtherwiseTypeError - -\subsection{Prose} -One of the following applies: -\begin{itemize} - \item All of the following apply (\textsc{not\_integers}): - \begin{itemize} - \item at least one of $\structone$ and $\structtwo$ is not an integer type; - \item the result is a type error indicating that the start expression and end expression of \texttt{for} loops - must have the \structure\ of integer types. - \end{itemize} - - \item All of the following apply (\textsc{unconstrained}): - \begin{itemize} - \item both of $\structone$ and $\structtwo$ are integer types; - \item at least one of $\structone$ and $\structtwo$ is the unconstrained integer type; - \item define $\vis$ as $\unconstrained$. - \end{itemize} - - \item All of the following apply (\textsc{well\_constrained}): - \begin{itemize} - \item both of $\structone$ and $\structtwo$ are integer types; - \item neither $\structone$ nor $\structtwo$ is the unconstrained integer type; - \item symbolically simplifying $\veonep$ in $\tenv$ yields $\eonen$\ProseOrTypeError; - \item symbolically simplifying $\vetwop$ in $\tenv$ yields $\etwon$\ProseOrTypeError; - \item define $\icsup$ as the single range constraint with expressions $\eonen$ and $\etwon$; - \item define $\icsdown$ as the single range constraint with expressions $\etwon$ and $\eonen$; - \item define $\vis$ as $\icsup$ if $\dir$ is $\UP$ and $\icsdown$ otherwise. - \end{itemize} -\end{itemize} - -\subsection{Formally} -\begin{mathpar} -\inferrule[not\_integers]{ - \astlabel(\structone) \neq \TInt \lor \astlabel(\structtwo) \neq \TInt -}{ - \getforconstraints(\tenv, \structone, \structtwo, \veonep, \vetwop, \dir) \typearrow \TypeErrorVal{\RequireIntegerForLoopBounds} -} -\end{mathpar} - -\begin{mathpar} -\inferrule[unconstrained]{ - \astlabel(\structone) = \TInt \land \astlabel(\structtwo) = \TInt\\ - \structone = \unconstrainedinteger \lor \structtwo = \unconstrainedinteger\\ -}{ - \getforconstraints(\tenv, \structone, \structtwo, \veonep, \vetwop, \dir) \typearrow \overname{\unconstrained}{\vis} -} -\end{mathpar} - -\begin{mathpar} -\inferrule[well\_constrained]{ - \astlabel(\structone) = \TInt \land \astlabel(\structtwo) = \TInt\\ - \structone \neq \unconstrainedinteger \land \structtwo \neq \unconstrainedinteger\\ - \normalize(\tenv, \veonep) \typearrow \eonen \OrTypeError\\\\ - \normalize(\tenv, \vetwop) \typearrow \etwon \OrTypeError\\\\ - \icsup \eqdef \wellconstrained([\ConstraintRange(\eonen, \etwon)])\\ - \icsdown \eqdef \wellconstrained([\ConstraintRange(\etwon, \eonen)])\\ - \vis \eqdef \choice{\dir=\UP}{\icsup}{\icsdown} -}{ - \getforconstraints(\tenv, \structone, \structtwo, \veonep, \vetwop, \dir) \typearrow \vis -} -\end{mathpar} - -\section{TypingRule.AnnotateLoopLimit \label{sec:TypingRule.AnnotateLoopLimit}} -\hypertarget{def-annotatelooplimit}{} -The function -\[ - \annotatelooplimit( - \overname{\staticenvs}{\tenv} \aslsep - \overname{\langle\expr\rangle}{\ve} \aslsep - ) \aslto - \overname{\expr}{\vep} \cup\ \overname{\TTypeError}{\TypeErrorConfig} -\] -annotates an optional expression $\ve$ serving as the limit of a loop in $\tenv$, -yielding the optional loop expression $\vep$. -\ProseOtherwiseTypeError - -\subsection{Prose} -One of the following applies: -\begin{itemize} - \item All of the following apply (\textsc{none}): - \begin{itemize} - \item $\ve$ is $\None$; - \item $\vep$ is $\None$. - \end{itemize} - - \item All of the following apply (\textsc{some}): - \begin{itemize} - \item $\ve$ is $\langle\vlimit\rangle$; - \item annotating $\vlimit$ in $\tenv$ yields $(\vt, \vlimitp)$\ProseOrTypeError; - \item checking that $\vt$ is a constrained integer in $\tenv$ via \\ - $\checkconstrainedinteger$ yields $\True$\ProseOrTypeError; - \item $\vep$ is $\langle\vlimitp\rangle$. - \end{itemize} -\end{itemize} - -\subsection{Formally} -\begin{mathpar} -\inferrule[none]{}{ - \annotatelooplimit(\tenv, \overname{\None}{\vlimit}) \typearrow \overname{\None}{\vlimitp} -} -\end{mathpar} - -\CodeSubsection{\AnnotateLoopLimitBegin}{\AnnotateLoopLimitEnd}{../Typing.ml} - -\begin{mathpar} -\inferrule[some]{ - \annotateexpr{\tenv, \vlimit} \typearrow (\vt, \vlimitp) \OrTypeError\\\\ - \checkconstrainedinteger(\tenv, \vt) \typearrow \True \OrTypeError -}{ - \annotatelooplimit(\tenv, \overname{\langle\vlimit\rangle}{\vlimit}) \typearrow \overname{\langle\vlimitp\rangle}{\vlimitp} -} -\end{mathpar} - -\section{TypingRule.DeclareLocalConstant \label{sec:TypingRule.DeclareLocalConstant}} -\hypertarget{def-declarelocalconstant}{} -The function -\[ -\declarelocalconstant(\overname{\staticenvs}{\tenv} \aslsep \overname{\literal}{\vv} \aslsep \overname{\localdeclitem}{\ldi}) -\typearrow \overname{\staticenvs}{\newtenv} -\] -adds the literal $\vv$ with the local declaration item $\ldi$ as a constant to the local component of the static environment $\tenv$, -yielding the modified static environment $\newtenv$. - -\subsection{Prose} -One of the following applies: -\begin{itemize} - \item All of the following apply (\textsc{discard}): - \begin{itemize} - \item $\ldi$ corresponds to a discarding declaration, that is, $\LDIDiscard$; - \item $\newtenv$ is $\tenv$. - \end{itemize} - - \item All of the following apply (\textsc{var}): - \begin{itemize} - \item $\ldi$ corresponds to a variable declaration for $\vx$, that is, $\LDIVar(\vx)$; - \item define $\newtenv$ and the environment $\tenv$ with its global component updated by binding - $\vx$ to $\vv$ in its $\constantvalues$ map. - \end{itemize} - - \item All of the following apply (\textsc{tuple}): - \begin{itemize} - \item $\ldi$ corresponds to a tuple declaration, that is, $\LDIVar(\Ignore)$; - \item this case is not yet implemented. - \end{itemize} - - \item All of the following apply (\textsc{typed}): - \begin{itemize} - \item $\ldi$ corresponds to a typed declaration of the local declaration item $\ldip$ and some type, that is, $\LDITyped(\ldip, \Ignore)$; - \item applying $\declarelocalconstant$ to $\vv$ and $\ldip$ in $\tenv$ yields $\newtenv$. - \end{itemize} -\end{itemize} - -\CodeSubsection{\DeclareLocalConstantBegin}{\DeclareLocalConstantEnd}{../Typing.ml} - -\subsection{Formally} -\begin{mathpar} -\inferrule[discard]{}{ - \declarelocalconstant(\tenv, \vv, \overname{\LDIDiscard}{\ldi}) \typearrow \overname{\tenv}{\newtenv} -} -\end{mathpar} - -\begin{mathpar} -\inferrule[var]{ - \newtenv \eqdef (G^\tenv, L^\tenv.\constantvalues[\vx \mapsto \vv]) -}{ - \declarelocalconstant(\tenv, \vv, \overname{\LDIVar(\vx)}{\ldi}) \typearrow \newtenv -} -\end{mathpar} - -\begin{mathpar} -\inferrule[tuple]{}{ - \declarelocalconstant(\tenv, \vv, \overname{\LDITuple(\Ignore)}{\ldi}) \typearrow \tododefine{not implemented yet} -} -\end{mathpar} - -\begin{mathpar} -\inferrule[typed]{ - \declarelocalconstant(\tenv, \vv, \ldip) \typearrow \newtenv -}{ - \declarelocalconstant(\tenv, \vv, \overname{\LDITyped(\ldip, \Ignore)}{\ldi}) \typearrow \newtenv -} -\end{mathpar} - -\section{TypingRule.AnnotateLocalDelItemUninit \label{sec:TypingRule.AnnotateLocalDelItemUninit}} -\hypertarget{def-annotatelocaldeclitemuninit}{} -The function -\[ -\begin{array}{r} -\annotatelocaldeclitemuninit(\overname{\staticenvs}{\tenv} \aslsep \overname{\localdeclitem}{\ldi}) -\typearrow \\ -(\overname{\staticenvs}{\newtenv} \times \overname{\localdeclitem}{\newldi}) -\cup \overname{\TTypeError}{\TypeErrorConfig} -\end{array} -\] -annotates the local declaration for a variable declaration without an initializing expressions in the static environment $\tenv$, -yielding a pair consisting of the annotated local declaration item $\newldi$ and the modified static environment $\newtenv$. -\ProseOtherwiseTypeError - -\subsection{Prose} -One of the following applies: -\begin{itemize} - \item All of the following apply (\textsc{discard}): - \begin{itemize} - \item $\ldi$ corresponds to a discarding declaration, that is, $\LDIDiscard$; - \item $\newtenv$ is $\tenv$ and $\newldi$ is $\ldi$. - \end{itemize} - - \item All of the following apply (\textsc{typed}): - \begin{itemize} - \item $\ldi$ corresponds to a variable declaration via the local declaration item $\ldip$ and type annotation $\vt$, - that is, $\LDITyped(\ldip, \vt)$; - \item annotating $\vt$ in $\tenv$ yields $\vtp$\ProseOrTypeError; - \item annotating the local declaration item $\ldip$ with the type $\vtp$ and local declaration keyword $\LDIVar$ - yields $(\newtenv, \newldip)$\ProseOrTypeError; - \item define $\newldi$ as the typed local declaration item with local declaration item $\newldip$ and type $\vtp$. - \end{itemize} -\end{itemize} - -\subsection{Formally} -\begin{mathpar} -\inferrule[discard]{}{ - \annotatelocaldeclitemuninit(\tenv, \overname{\LDIDiscard}{\ldi}) \typearrow (\overname{\tenv}{\newtenv}, \overname{\ldi}{\newldi}) -} -\end{mathpar} - -\begin{mathpar} -\inferrule[typed]{ - \annotatetype{\tenv, \vt} \typearrow \vtp \OrTypeError\\\\ - \annotatelocaldeclitem{\tenv, \vtp, \LDKVar, \ldip} \typearrow (\newtenv, \newldip) \OrTypeError\\\\ - \newldi \eqdef \LDITyped(\newldip, \vtp) -}{ - \annotatelocaldeclitemuninit(\tenv, \overname{\LDITyped(\ldip, \vt)}{\ldi}) \typearrow (\newtenv, \newldi) -} -\end{mathpar} - -\begin{mathpar} -\inferrule[error]{ - \astlabel(\ldi) \in \{\LDIVar, \LDITuple\} -}{ - \annotatelocaldeclitemuninit(\tenv, \ldi) \typearrow \TypeErrorVal{ExpectedTypedDeclaration} -} -\end{mathpar} - -\CodeSubsection{\AnnotateLocalDeclItemUninitBegin}{\AnnotateLocalDeclItemUninitEnd}{../Typing.ml} - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -\chapter{Typing of Blocks} -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -\hypertarget{def-annotateblock}{} -The function -\[ - \annotateblock{\overname{\staticenvs}{\tenv} \aslsep \overname{\stmt}{\vs}} \aslto - \overname{\stmt}{\newstmt} \cup \overname{\TTypeError}{\TypeErrorConfig} -\] -annotates a block statement $\vs$ in static environment $\tenv$ and returns the annotated -statement $\newstmt$ or a type error, if one is detected. - -\section{TypingRule.Block \label{sec:TypingRule.Block}} - -\subsection{Prose} -All of the following apply: -\begin{itemize} - \item annotating the statement $\vs$ in $\tenv$ yields $(\newstmt, \newtenv)$\ProseOrTypeError; - \item the modified environment $\newtenv$ is dropped. -\end{itemize} - -\subsection{Example} -\VerbatimInput{../tests/ASLTypingReference.t/TypingRule.Block0.asl} - -\CodeSubsection{\BlockBegin}{\BlockEnd}{../Typing.ml} - -\subsection{Formally} -\begin{mathpar} -\inferrule{ - \annotatestmt(\tenv, \vs) \typearrow (\newstmt, \Ignore) \OrTypeError -}{ - \annotateblock{\tenv, \vs} \typearrow \newstmt -} -\end{mathpar} - -\subsection{Comments} -A local identifier declared in a block statement (with \texttt{var}, \texttt{let}, or \texttt{constant}) -is in scope from the point immediately after its declaration until the end of the -immediately enclosing block. This means, we can discard the environment at the end of -an enclosing block, which has the effect of dropping bindings of the identifiers declared inside the block. - -\lrmcomment{This is related to \identr{JBXQ}.} - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -\chapter{Typing of Catchers} -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -\hypertarget{def-annotatecatcher}{} -The function -\[ -\begin{array}{r} - \annotatecatcher{ - \overname{\staticenvs}{\tenv} \aslsep - (\overname{\langle\identifier\rangle}{\nameopt} \times \overname{\ty}{\tty} \times \overname{\stmt}{\vstmt}) - } \aslto \\ - (\overname{\langle\identifier\rangle}{\nameopt} \times \overname{\ty}{\ttyp} \times \overname{\stmt}{\newstmt}) - \cup \overname{\TTypeError}{\TypeErrorConfig} -\end{array} -\] -annotates a catcher given by the \optional\ name of the matched exception --- $\nameopt$ --- -the exception type --- $\tty$ --- and the statement to execute upon catching the exception --- $\vstmt$. -The result is the catcher with the same \optional\ name --- $\nameopt$, an annotated type $\ttyp$, and annotated statement $\newstmt$. -\ProseOtherwiseTypeError - -One of the following applies: -\begin{itemize} -\item TypingRule.CatcherNone (see \secref{TypingRule.CatcherNone}), -\item TypingRule.CatcherSome (see \secref{TypingRule.CatcherSome}). -\end{itemize} - -\section{TypingRule.CatcherNone \label{sec:TypingRule.CatcherNone}} - -\subsection{Prose} -All of the following apply: -\begin{itemize} - \item the catcher has no named identifier, that is, $(\None, \tty, \vstmt)$; - \item annotating the type $\tty$ in $\tenv$ yields $\ttyp$\ProseOrTypeError; - \item determining whether $\ttyp$ has the \structure\ of an exception type yields $\True$\ProseOrTypeError; - \item annotating the block $\vstmt$ in $\tenv$ yields $\newstmt$. -\end{itemize} - -\isempty{\subsection{Example}} - -\CodeSubsection{\CatcherNoneBegin}{\CatcherNoneEnd}{../Typing.ml} - -\subsection{Formally} -\begin{mathpar} -\inferrule{ - \annotatetype{\tenv, \vt} \typearrow \ttyp \OrTypeError\\\\ - \checkstructurelabel(\tenv, \ttyp, \TException) \typearrow \True \OrTypeError\\\\ - \annotateblock{\tenv, \vstmt} \typearrow \newstmt \OrTypeError -}{ - \annotatecatcher{\tenv, (\overname{\None}{\nameopt}, \tty, \vstmt)} \typearrow (\overname{\None}{\nameopt}, \ttyp, \newstmt) -} -\end{mathpar} - -\isempty{\subsection{Comments}} -\lrmcomment{This is related to \identr{SDJK}.} - -\section{TypingRule.CatcherSome \label{sec:TypingRule.CatcherSome}} - -\subsection{Prose} -All of the following apply: -\begin{itemize} - \item the catcher has a named identifier, that is, $(\langle\name\rangle, \tty, \vstmt)$; - \item annotating the type $\tty$ in $\tenv$ yields $\ttyp$\ProseOrTypeError; - \item determining whether $\ttyp$ has the \structure\ of an exception type yields $\True$\ProseOrTypeError; - \item the identifier $\name$ is not bound in $\tenv$; - \item binding $\name$ in the local environment of $\tenv$ with the type $\ttyp$ as an immutable variable - (that is, with the local declaration keyword $\LDKLet$), yields the static environment $\tenvp$; - \item annotating the block $\vstmt$ in $\tenvp$ yields $\newstmt$. -\end{itemize} - -\isempty{\subsection{Example}} - -\CodeSubsection{\CatcherSomeBegin}{\CatcherSomeEnd}{../Typing.ml} - -\subsection{Formally} -\begin{mathpar} -\inferrule{ - \annotatetype{\tenv, \vt} \typearrow \ttyp \OrTypeError\\\\ - \checkstructurelabel(\tenv, \ttyp, \TException) \typearrow \True \OrTypeError\\\\ - \checkvarnotinenv{\tenv, \name} \typearrow \True \OrTypeError\\\\ - \addlocal(\tenv, \name, \ttyp, \LDKLet) \typearrow \tenvp\\ - \annotateblock{\tenvp, \vstmt} \typearrow \newstmt \OrTypeError -}{ - \annotatecatcher{\tenv, (\overname{\langle\name\rangle}{\nameopt}, \tty, \vstmt)} \typearrow - (\overname{\langle\name\rangle}{\nameopt}, \ttyp, \newstmt) -} -\end{mathpar} - -\isempty{\subsection{Comments}} -\lrmcomment{This is related to \identr{SDJK}, \identr{WVXS}, \identi{FCGK}.} - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -\chapter{Typing of Subprogram Calls \label{chap:TypingSubprogramCalls}} -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -\hypertarget{def-annotatecall} -The function -\[ - \begin{array}{rl} - \annotatecall( & - \overname{\staticenvs}{\tenv} \aslsep - \overname{\identifier}{\name} \aslsep - \overname{\expr^*}{\vargs} \aslsep - \overname{\subprogramtype}{\calltype} - ) \aslto \\ & - (\overname{\identifier}{\nameone} \aslsep - \overname{\expr^*}{\vargsone} \aslsep - \overname{(\identifier\times\expr)^*}{\eqs} \aslsep - \overname{\langle \ty \rangle}{\rettyopt}) -\end{array} -\] -annotates the call to subprogram $\name$ with arguments $\vargs$ -and call type $\calltype$, resulting in the following: -\begin{itemize} - \item $\nameone$ --- a string, which uniquely identifies $\name$ among the set of overloading subprograms declared with $\name$; - \item $\vargsone$ --- the annotated argument expressions; - \item $\eqs$ --- the expressions providing values to the parameters; - \item $\rettyopt$ --- the \optional\ annotated return type. -\end{itemize} -\ProseOtherwiseTypeError - -The function is defined by the rule TypingRule.AnnotateCall (see \secref{TypingRule.AnnotateCall}). - -We also define helper functions via respective rules: -\begin{itemize} - \item TypingRule.AnnotateCallArgTyped (see \secref{TypingRule.AnnotateCallArgTyped}) - \item TypingRule.CheckCalleeParams (see \secref{TypingRule.CheckCalleeParams}) - \item TypingRule.RenameTyEqs (see \secref{TypingRule.RenameTyEqs}) - \item TypingRule.SubstExprNormalize (see \secref{TypingRule.SubstExprNormalize}) - \item TypingRule.SubstExpr (see \secref{TypingRule.SubstExpr}) - \item TypingRule.SubstConstraint (see \secref{TypingRule.SubstConstraint}) - \item TypingRule.CheckArgsTypeSat (see \secref{TypingRule.CheckArgsTypeSat}) - \item TypingRule.AnnotateParameterDefining (see \secref{TypingRule.AnnotateParameterDefining}) - \item TypingRule.AnnotateRetTy (\secref{TypingRule.AnnotateRetTy}) - \item TypingRule.SubprogramForName (see \secref{TypingRule.SubprogramForName}) - \item TypingRule.DeduceEqs (see \secref{TypingRule.DeduceEqs}) - \item TypingRule.FilterCallCandidates (see \secref{TypingRule.FilterCallCandidates}) - \item TypingRule.HasArgClash (see \secref{TypingRule.HasArgClash}) -\end{itemize} - -\section{TypingRule.AnnotateCall \label{sec:TypingRule.AnnotateCall}} -\subsection{Prose} -All of the following apply: -\begin{itemize} - \item applying $\annotateexprlist$ to annotate the expression list $\vargs$ in $\tenv$ yields \\ - $\callerargtyped$\ProseOrTypeError; - \item applying $\annotatecallargtyped$ to $\name$, $\callerargtyped$, $\calltype$ in $\tenv$ yields - $(\nameone, \vargsone, \eqs, \retty)$\ProseOrTypeError. -\end{itemize} - -\CodeSubsection{\AnnotateCallBegin}{\AnnotateCallEnd}{../Typing.ml} - -\subsection{Formally} -\begin{mathpar} -\inferrule{ - \annotateexprlist(\tenv, \vargs) \typearrow \callerargtyped \OrTypeError\\\\ - { - \begin{array}{r} - \annotatecallargtyped(\tenv, \name, \callerargtyped, \calltype) \typearrow \\ - (\nameone, \vargsone, \eqs, \retty) \OrTypeError - \end{array} - } -}{ - \annotatecall(\tenv, \name, \vargs, \calltype) \typearrow - (\nameone, \vargsone, \eqs, \retty) -} -\end{mathpar} - -\isempty{\subsection{Comments}} -\lrmcomment{ - This is related to \identi{VFDP}, \identd{TRFW}, \identr{KMDB}, - \identi{YMHX}, \identr{CCVD}, \identr{QYBH}, \identr{PFWQ}, \identr{ZLWD}, - \identi{FLKF}, \identd{PMBL}, \identr{MWBN}, \identr{TZSP}, \identr{SBWR}, - \identi{CMLP}, \identr{BQJG}, \identr{RTCF}. -} - -\section{TypingRule.AnnotateCallArgTyped \label{sec:TypingRule.AnnotateCallArgTyped}} -\hypertarget{def-annotatecallargtyped}{} -The function -\[ - \begin{array}{r} - \annotatecallargtyped( - \overname{\staticenvs}{\tenv} \aslsep - \overname{\identifier}{\name} \aslsep - \overname{(\ty \times\expr)^*}{\callerargstyped} \aslsep - \overname{\subprogramtype}{\calltype} - ) \aslto \\ - (\overname{\identifier}{\nameone} \aslsep - \overname{\expr^*}{\vargsone} \aslsep - \overname{(\identifier\times\expr)^*}{\eqs} \aslsep - \overname{\langle \ty \rangle}{\rettyopt}) - \cup \overname{\TTypeError}{\TypeErrorConfig} -\end{array} -\] -is similar to $\annotatecall$, except that the argument expressions are replaced by -the annotated expressions. That is, pairs consisting of a type and an expression. -\ProseOtherwiseTypeError - -\subsection{Prose} -All of the following apply: -\begin{itemize} - \item applying $\unziplist$ to $\callerargtyped$ yields the corresponding lists of types - and expressions $\callerargtypes$ and $\vargsone$; - \item applying $\subprogramforname$ to match $\name$ and $\callerargtypes$ in $\tenv$ - yields $(\eqsone, \nameone, \callee)$\ProseOrTypeError; - \item checking that $\subprogramtype$ of $\callee$ equals $\calltype$ yields $\True$\ProseOrTypeError; - \item checking that the lengths of $\callee.\funcargs$ and $\vargsone$ are the same yields $\True$\ProseOrTypeError; - \item applying $\annotateparameterdefining$ to $\callee.\funcargs$, - $\callerargstyped$, and \\ - $\calleeparams$ in $\tenv$ to annotate the implicit parameters - yields $\eqsthreep$\ProseOrTypeError; - \item define $\eqsthree$ is the concatenation of $\eqsthreep$ and $\eqsone$; - \item applying $\checkargstypesat$ to $\calleeargtypes$ - to check that the actual arguments have correct types with respect to $\callerargtypes$ - in $\tenv$ yields $\True$\ProseOrTypeError; - \item applying $\checkcalleeparams$ to $\calleeparams$ to check they have correct types - with respect to $\eqsthree$ in $\tenv$ yields $\True$\ProseOrTypeError; - \item applying $\annotateretty$ to $\calltype$ and $\callee.\funcreturntype$ - to check that the two call types match and to substitute actual parameter arguments in the formal return type - yields $\rettyopt$ \ProseOrTypeError; - \item define $\eqs$ as $\eqsthree$. -\end{itemize} - -\CodeSubsection{\AnnotateCallArgTypedBegin}{\AnnotateCallArgTypedEnd}{../Typing.ml} - -\subsection{Formally} -\begin{mathpar} -\inferrule{ - \unziplist(\callerargstyped) = (\callerargtypes, \vargsone)\\ - { - \begin{array}{r} - \subprogramforname(\tenv, \name, \callerargtypes) \typearrow \\ - (\eqsone, \nameone, \callee) \OrTypeError - \end{array} - }\\ - \checktrans{\callee.\subprogramtype = \calltype}{\MismatchedReturnValue} \checktransarrow \True\OrTypeError\\\\ - \equallength(\callee.\funcargs, \vargsone) \typearrow \aritymatch\\ - \checktrans{\aritymatch}{\CallBadArity} \checktransarrow \True \OrTypeError\\\\ - { - \annotateparameterdefining\left( - \begin{array}{l} - \tenv,\\ - \callee.\funcargs, \\ - \callerargstyped, \\ - \callee.\funcparameters - \end{array} - \right) - \typearrow \eqsthreep \OrTypeError - }\\ - \eqsthree \eqdef \eqsthreep \concat \eqsone\\ - \checkargstypesat(\tenv, \callee.\funcargs, \callerargtypes, \eqsthree) \typearrow \True \OrTypeError\\\\ - \checkcalleeparams(\tenv, \callee.\funcparameters, \eqsthree) \typearrow \True \OrTypeError\\\\ - \annotateretty(\tenv, \calltype, \callee.\funcreturntype) \typearrow \rettyopt \OrTypeError -}{ - { - \begin{array}{r} - \annotatecallargtyped(\tenv, \name, \callerargstyped, \calltype) \typearrow \\ - (\nameone, \vargsone, \overname{\eqsthree}{\eqs}, \rettyopt) - \end{array} - } -} -\end{mathpar} - -\section{TypingRule.CheckCalleeParams \label{sec:TypingRule.CheckCalleeParams}} -\hypertarget{def-checkcalleeparams}{} -The function -\[ -\checkcalleeparams( - \overname{\staticenvs}{\tenv} \aslsep - \overname{(\identifier\times\langle\ty\rangle)^*}{\calleeparams} - \overname{(\identifier\times\expr)^*}{\eqsthree} - ) \aslto \\ - \{\True\}\ \cup \overname{\TTypeError}{\TypeErrorConfig} -\] -checks that the parameters in $\calleeparams$ are correct with respect -to the parameter expressions $\eqsthree$. -\ProseOtherwiseTypeError - -\subsection{Prose} -One of the following applies: -\begin{itemize} - \item All of the following apply (\textsc{empty}): - \begin{itemize} - \item $\calleeparams$ is an empty list; - \item the result is $\True$. - \end{itemize} - - \item All of the following apply: - \begin{itemize} - \item $\calleeparams$ is a non-empty list with \head\ $\calleeparam$ and \tail\ \\ - $\calleeparamsone$; - \item One of the following applies: - \begin{itemize} - \item All of the following apply (\textsc{no\_type}): - \begin{itemize} - \item $\calleeparam$ does not have a type annotation, that is, $(\Ignore, \None)$. - \end{itemize} - - \item All of the following apply (\textsc{parameterized}): - \begin{itemize} - \item $\calleeparam$ is a parameter $\vs$ with a type annotation of a - \parameterizedintegertype\ for the same parameter, that is, \\ - $(\vs, \langle\TInt(\parameterized(\vs))\rangle)$. - \end{itemize} - - \item All of the following apply (\textsc{other}): - \begin{itemize} - \item $\calleeparam$ is a parameter $\vs$ whose type annotation is \\ - $\calleeparamt$, that is, $(\vs, \langle\calleeparamt\rangle)$; - \item $\calleeparamt$ is not the \parameterizedintegertype\ for the same parameter; - \item substituting the parameter expressions from $\eqsthree$ in $\calleeparamt$ - yields $\calleeparamtrenamed$\ProseOrTypeError; - \item applying $\assocopt$ to $\eqsthree$ and $\vs$ yields the expression $\callerparame$ - (that is, the parameter $\vs$ is associated with the expression \\ - $\callerparame$); - \item annotating the expression $\callerparame$ in $\tenv$ yields \\ - $(\callerparamt, \Ignore)$\ProseOrTypeError; - \item checking that $\callerparamt$ \typesatisfies\ $\calleeparamtrenamed$ in $\tenv$ yields - $\True$\ProseOrTypeError; - \end{itemize} - \end{itemize} - \item applying $\checkcalleeparams$ to $\calleeparamsone$ and $\eqsthree$ in $\tenv$ - yields \\ $\True$\ProseOrTypeError. - \end{itemize} -\end{itemize} - -\subsection{Formally} -\begin{mathpar} -\inferrule[empty]{ -}{ - \checkcalleeparams(\tenv, \overname{\emptylist}{\calleeparams}, \eqsthree) \typearrow \True -} -\and -\inferrule[no\_type]{ - \calleeparams = [(\Ignore, \None)] \concat \calleeparamsone\\ - \checkcalleeparams(\tenv, \calleeparamsone, \eqsthree) \typearrow \True \OrTypeError -}{ - \checkcalleeparams(\tenv, \calleeparams, \eqsthree) \typearrow \True -} -\and -\inferrule[parameterized]{ - \calleeparams = [(\vs, \langle\TInt(\parameterized(\vs))\rangle)] \concat \calleeparamsone\\ - \checkcalleeparams(\tenv, \calleeparamsone, \eqsthree) \typearrow \True \OrTypeError -}{ - \checkcalleeparams(\tenv, \calleeparams, \eqsthree) \typearrow \True -} -\and -\inferrule[other]{ - \calleeparams = [(\vs, \langle\calleeparamt\rangle)] \concat \calleeparamsone\\ - \calleeparamt \neq \TInt(\parameterized(\vs))\\ - \renametyeqs(\tenv, \eqsthree, \calleeparamt) \typearrow \calleeparamtrenamed \OrTypeError\\\\ - \assocopt(\eqsthree, \vs) \typearrow \langle \callerparame \rangle\\ - \annotateexpr{\tenv, \callerparame} \typearrow \callerparamt \OrTypeError\\\\ - \checktypesat(\tenv, \callerparamt, \calleeparamtrenamed) \typearrow \True \OrTypeError\\\\ - \checkcalleeparams(\tenv, \calleeparamsone, \eqsthree) \typearrow \True \OrTypeError -}{ - \checkcalleeparams(\tenv, \calleeparams, \eqsthree) \typearrow \True -} -\end{mathpar} - -\section{TypingRule.RenameTyEqs \label{sec:TypingRule.RenameTyEqs}} -\hypertarget{def-renametyeqs}{} -The function -\[ -\renametyeqs( - \overname{\staticenvs}{\tenv} \aslsep - \overname{(\identifier\times\expr)^*}{\eqs} \aslsep - \overname{\ty}{\tty} -) \aslto -\overname{\ty}{\newty} \cup \overname{\TTypeError}{\TypeErrorConfig} -\] -transforms the type $\tty$ in the static environment $\tenv$, -by substituting parameter names with their corresponding expressions in -$\eqs$, yielding the type $\newty$. -\ProseOtherwiseTypeError - -\subsection{Prose} -One of the following applies: -\begin{itemize} - \item All of the following apply (\textsc{t\_bits}): - \begin{itemize} - \item $\tty$ is a bitvector type with width expression $\ve$ and fields $\fields$, that is, $\TBits(\ve, \fields)$; - \item applying $\substexprnormalize$ to $\eqs$ and $\ve$ in $\tenv$ yields the expression $\newe$; - \item define $\newty$ as a bitvector type with with expression $\newe$ and fields $\fields$. - \end{itemize} - - \item All of the following apply (\textsc{t\_int\_wellconstrained}): - \begin{itemize} - \item $\tty$ is a well-constrained integer type with constraints $\constraints$; - \item applying $\substconstraint$ to each constraint $\constraints[\vi]$, for $\vi$ in \\ - $\listrange(\constraints)$, yields the constraint $\newc_\vi$; - \item define $\newconstraints$ as the list of constraints $\newc_\vi$, for $\vi$ in \\ - $\listrange(\constraints)$; - \item define $\newty$ as the well-constrained integer type with constraints \\ - $\newconstraints$. - \end{itemize} - - \item All of the following apply (\textsc{t\_int\_parameterized}): - \begin{itemize} - \item $\tty$ is a \parameterizedintegertype\ for the parameter $\name$; - \item applying $\substexprnormalize$ to $\eqs$ and the expression $\EVar(\name)$ yields $\ve$; - \item define $\newty$ as the well-constrained integer type with the single constraint for $\ve$, that is, - $\TInt(\wellconstrained(\ConstraintExact(\ve)))$. - \end{itemize} - - \item All of the following apply (\textsc{t\_tuple}): - \begin{itemize} - \item $\tty$ is the tuple type over the list of tuples $\tys$, that is, $\TTuple(\tys)$; - \item applying $\renametyeqs$ to $\eqs$ and the type $\tys[\vi]$, for each $\vi$ in \\ - $\listrange(\tys)$, yields the type $\newty_\vi$; - \item define $\newtys$ as the list of types $\newty_\vi$, for each $\vi$ in $\listrange(\tys)$; - \item define $\newty$ as the tuple type over $\newtys$, that is, $\TTuple(\newtys)$. - \end{itemize} - - \item All of the following apply (\textsc{other}): - \begin{itemize} - \item $\tty$ is not one of the types in the previous cases, - that is, $\tty$ is not a bitvector type, nor an integer type, nor a tuple type; - \item $\newty$ is $\tty$. - \end{itemize} -\end{itemize} - -\subsection{Formally} -\begin{mathpar} -\inferrule[t\_bits]{ - \substexprnormalize(\tenv, \eqs, \ve) \typearrow \newe -}{ - \renametyeqs(\tenv, \eqs, \overname{\TBits(\ve, \fields)}{\tty}) \typearrow \overname{\TBits(\newe, \fields)}{\newty} -} -\and -\inferrule[t\_int\_wellconstrained]{ - \vi\in\listrange(\constraints): \substconstraint(\tenv, \constraints[\vi]) \typearrow \newc_\vi\\ - \newconstraints \eqdef [\vi\in\listrange(\constraints): \newc_\vi]\\ - \newty \eqdef \TInt(\wellconstrained(\newconstraints)) -}{ - \renametyeqs(\tenv, \eqs, \overname{\TInt(\wellconstrained(\constraints))}{\tty}) \typearrow - \newty -} -\and -\inferrule[t\_int\_parameterized]{ - \substexprnormalize(\eqs, \EVar(\name)) \typearrow \ve\\ - \newty \eqdef \TInt(\wellconstrained(\ConstraintExact(\ve))) -}{ - \renametyeqs(\tenv, \eqs, \overname{\TInt(\parameterized(\name))}{\tty}) \typearrow \newty -} -\and -\inferrule[t\_tuple]{ - \vi\in\listrange(\tys): \renametyeqs(\eqs, \tys[\vi]) \typearrow \newty_\vi\\ - \newtys \eqdef [\vi\in\listrange(\tys): \newty_\vi] -}{ - \renametyeqs(\tenv, \eqs, \overname{\TTuple(\tys)}{\tty}) \typearrow - \overname{\TTuple(\newtys)}{\newty} -} -\and -\inferrule[other]{ - \astlabel(\tty) \not\in \{\TBits, \TInt, \TTuple\} -}{ - \renametyeqs(\tenv, \eqs, \tty) \typearrow \overname{\tty}{\newty} -} -\end{mathpar} - -\section{TypingRule.SubstExprNormalize \label{sec:TypingRule.SubstExprNormalize}} -\hypertarget{def-substexprnormalize}{} -The function -\[ -\substexprnormalize( - \overname{\staticenvs}{\tenv} \aslsep - \overname{(\identifier\times\expr)^*}{\eqs} \aslsep - \overname{\expr}{\ve} -) \aslto \overname{\newe}{\expr} -\] -transforms the expression $\ve$ in the static environment $\tenv$, -by substituting parameter names with their corresponding expressions in -$\eqs$, and then attempting to symbolically simplify the result, yielding the expression $\newe$. -\ProseOtherwiseTypeError - -\subsection{Prose} -All of the following apply: -\begin{itemize} - \item transforming $\ve$ in the static environment $\tenv$, by substituting the parameter expressions - $\eqs$, yields $\veone$; - \item symbolically simplifying $\veone$ in $\tenv$ yields $\newe$. -\end{itemize} - -\subsection{Formally} -\begin{mathpar} -\inferrule{ - \substexpr(\tenv, \ve) \typearrow \veone\\ - \normalize(\tenv, \veone) \typearrow \newe -}{ - \substexprnormalize(\tenv, \eqs, \ve) \typearrow \newe -} -\end{mathpar} - -\section{TypingRule.SubstExpr \label{sec:TypingRule.SubstExpr}} -\hypertarget{def-substexpr}{} -The function -\[ -\substexpr( - \overname{\staticenvs}{\tenv} \aslsep - \overname{(\identifier\times\expr)^*}{\substs} \aslsep - \overname{\expr}{\ve} -) \aslto \overname{\expr}{\newe} -\] -transforms the expression $\ve$ in the static environment $\tenv$, -by substituting parameter names with their corresponding expressions in -$\substs$, yielding the expression $\newe$. -\ProseOtherwiseTypeError - -\subsection{Prose} -One of the following applies: -\begin{itemize} - \item All of the following apply (\textsc{e\_var\_in\_substs}): - \begin{itemize} - \item $\ve$ is a variable expression for the identifier $\vs$, that is, $\EVar(\vs)$; - \item applying $\assocopt$ to $\vs$ and $\substs$ yields the expression $\newe$. - That is, $\vs$ is a parameter with an associated expression; - \end{itemize} - - \item All of the following apply (\textsc{e\_var\_not\_in\_substs}): - \begin{itemize} - \item $\ve$ is the variable expression for the identifier $\vs$, that is, $\EVar(\vs)$; - \item applying $\assocopt$ to $\vs$ and $\substs$ yields $\None$. - That is, $\vs$ is not a parameter with an associated expression; - \item define $\newe$ is $\ve$. - \end{itemize} - - \item All of the following apply (\textsc{e\_unop}): - \begin{itemize} - \item $\ve$ is the unary operator expression for the operator $\op$ and expression $\ve$, that is, $\EUnop(\op, \veone)$; - \item applying $\substexpr$ to $\substs$ and $\veone$ in $\tenv$ yields $\veonep$; - \item define $\newe$ as the unary operator expression for the operator $\op$ and expression $\veonep$, that is, $\EUnop(\op, \veonep)$. - \end{itemize} - - \item All of the following apply (\textsc{e\_binop}): - \begin{itemize} - \item $\ve$ is the binary operator expression for the operator $\op$ and expressions $\veone$ and $\vetwo$, that is, $\EBinop(\op, \veone, \vetwo)$; - \item applying $\substexpr$ to $\substs$ and $\veone$ in $\tenv$ yields $\veonep$; - \item applying $\substexpr$ to $\substs$ and $\vetwo$ in $\tenv$ yields $\vetwop$; - \item define $\newe$ as the unary operator expression for the operator $\op$ and expression $\veonep$, that is, $\EUnop(\op, \veonep)$. - \end{itemize} - - \item All of the following apply (\textsc{e\_cond}): - \begin{itemize} - \item $\ve$ is the conditional expression for expressions $\veone$, $\vetwo$, and $\vethree$, that is, \\ - $\ECond(\veone, \vetwo, \vethree)$; - \item applying $\substexpr$ to $\substs$ and $\veone$ in $\tenv$ yields $\veonep$; - \item applying $\substexpr$ to $\substs$ and $\vetwo$ in $\tenv$ yields $\vetwop$; - \item applying $\substexpr$ to $\substs$ and $\vethree$ in $\tenv$ yields $\vethreep$; - \item define $\newe$ as the conditional expression for expressions $\veonep$, $\vetwop$, and $\vethreep$, that is, $\ECond(\veonep, \vetwop, \vethreep)$. - \end{itemize} - - \item All of the following apply (\textsc{e\_concat}): - \begin{itemize} - \item $\ve$ is the concatenation of expressions $\ves$, that is, $\EConcat(\ves)$; - \item applying $\substexpr$ to $\substs$ and every expression $\ves[\vi]$, for $\vi$ in \\ - $\listrange(\ves)$ yields $\newes_\vi$; - \item define $\vesp$ as the list of expressions $\newes_\vi$, for $\vi$ in $\listrange(\ves)$; - \item define $\newe$ as the concatenation of expressions $\vesp$, that is, $\EConcat(\vesp)$. - \end{itemize} - - \item All of the following apply (\textsc{e\_call}): - \begin{itemize} - \item $\ve$ is the call expression for subprogram $\vx$ with arguments $\vargs$ and parameter expressions $\paramargs$, - that is, $\ECall(\vx, \vargs, \paramargs)$; - \item applying $\substexpr$ to $\substs$ and every argument expression $\vargs[\vi]$, for $\vi$ in - $\listrange(\vargs)$ yields $\ve_\vi$; - \item define $\vargsp$ as $\ve_\vi$ for each $\vi$ in $\listrange(\vargs)$; - \item define $\newe$ as the call expression for subprogram $\vx$ with arguments $\vargsp$ and parameter expressions $\paramargs$, - that is, $\ECall(\vx, \vargsp, \paramargs)$. - \end{itemize} - - \item All of the following apply (\textsc{e\_getarray}): - \begin{itemize} - \item $\ve$ is the \arrayaccess\ expression for base expression $\veone$ and index expression $\vetwo$, - that is, $\EGetArray(\veone, \vetwo)$; - \item applying $\substexpr$ to $\substs$ and $\veone$ in $\tenv$ yields $\veonep$; - \item applying $\substexpr$ to $\substs$ and $\vetwo$ in $\tenv$ yields $\vetwop$; - \item define $\newe$ as the \arrayaccess\ expression for base expression $\veonep$ and index expression $\vetwop$, - that is, $\EGetArray(\veonep, \vetwop)$. - \end{itemize} - - \item All of the following apply (\textsc{e\_getfield}): - \begin{itemize} - \item $\ve$ is the field access expression for base expression $\ve$ and field $\vx$, - that is, $\EGetField(\veone, \vx)$; - \item applying $\substexpr$ to $\substs$ and $\veone$ in $\tenv$ yields $\veonep$; - \item define $\newe$ as the field access expression for base expression $\ve$ and field $\vx$, - that is, $\EGetField(\veonep, \vx)$. - \end{itemize} - - \item All of the following apply (\textsc{e\_getfields}): - \begin{itemize} - \item $\ve$ is the access to fields $\fields$ with base expression $\veone$, that is, \\ - $\EGetFields(\veone, \fields)$; - \item applying $\substexpr$ to $\substs$ and $\veone$ in $\tenv$ yields $\veonep$; - \item define $\newe$ as the access to fields $\fields$ with base expression $\veonep$, that is, $\EGetFields(\veonep, \fields)$. - \end{itemize} - - \item All of the following apply (\textsc{e\_getitem}): - \begin{itemize} - \item $\ve$ is the access to tuple item $\vi$ of the tuple expression $\veone$, that is, \\ - $\EGetItem(\veone, \vi)$; - \item applying $\substexpr$ to $\substs$ and $\veone$ in $\tenv$ yields $\veonep$; - \item define $\newe$ as the access to tuple item $\vi$ of the tuple expression $\veonep$, that is, \\ - $\EGetItem(\veonep, \vi)$. - \end{itemize} - - \item All of the following apply (\textsc{e\_pattern}): - \begin{itemize} - \item $\ve$ is the pattern expression of expression $\veone$ and patterns $\vps$, that is, \\ - $\EPattern(\veone, \vps)$; - \item applying $\substexpr$ to $\substs$ and $\veone$ in $\tenv$ yields $\veonep$; - \item define $\newe$ as the pattern expression of expression $\veonep$ and patterns $\vps$, that is, $\EPattern(\veonep, \vps)$. - \end{itemize} - - \item All of the following apply (\textsc{e\_record}): - \begin{itemize} - \item $\ve$ is the record expression of record type $\vt$ and list of fields $\fields$; - \item for every pair $(\vx,\veone)$ in $\fields$, applying $\substexpr$ to $\substs$ $\veone$ in $\tenv$ yields $\veonep_\vx$; - \item define $\fieldsp$ as the list of pairs $(\vx,\veonep_\vx)$ for every pair $(\vx,\veone)$ in $\fields$; - \item define $\newe$ as the record expression of record type $\vt$ and list of fields $\fieldsp$. - \end{itemize} - - \item All of the following apply (\textsc{e\_slice}): - \begin{itemize} - \item $\ve$ is the slicing expression for sub-expression $\veone$ and list of slices $\vslices$, that is, $\ESlice(\veone, \vslices)$; - \item applying $\substexpr$ to $\veone$ in $\tenv$ yields $\veonep$; - \item define $\newe$ as slicing expression for sub-expression $\veonep$ and list of slices $\vslices$, that is, $\ESlice(\veonep, \vslices)$. - \end{itemize} - - \item All of the following apply (\textsc{e\_tuple}): - \begin{itemize} - \item $\ve$ is the tuple expression of expressions $\ves$, that is, $\ETuple(\ves)$; - \item applying $\substexpr$ to $\substs$ and every expression $\ves[\vi]$ in $\tenv$, for every $\vi$ in $\listrange(\ves)$ - yields $\newe_\vi$; - \item define $\vesp$ as the list of expressions $\newe_\vi$, for every $\vi$ in $\listrange(\ves)$; - \item define $\newe$ as the tuple expression of expressions $\vesp$, that is, $\ETuple(\vesp)$. - \end{itemize} - - \item All of the following apply (\textsc{e\_atc}): - \begin{itemize} - \item $\ve$ is the type assertion of expression $\veone$ and type $\vt$, that is, $\EATC(\veone, \vt)$; - \item applying $\substexpr$ to $\substs$ and $\veone$ in $\tenv$ yields $\veonep$; - \item define $\newe$ as the type assertion of expression $\veonep$ and type $\vt$, that is, $\EATC(\veonep, \vt)$. - \end{itemize} - - \item All of the following apply (\textsc{other}): - \begin{itemize} - \item $\ve$ is either a literal expression or an unknown value expression; - \item define $\newe$ as $\ve$. - \end{itemize} -\end{itemize} - -\subsection{Formally} -\begin{mathpar} -\inferrule[e\_var\_in\_substs]{ - \assocopt(\vs, \substs) \typearrow \langle\newe\rangle -}{ - \substexpr(\tenv, \substs, \overname{\EVar(\vs)}{\ve}) \typearrow \newe -} -\end{mathpar} - -\begin{mathpar} -\inferrule[e\_var\_not\_in\_substs]{ - \assocopt(\vs, \substs) \typearrow \None -}{ - \substexpr(\tenv, \substs, \overname{\EVar(\vs)}{\ve}) \typearrow \overname{\ve}{\newe} -} -\end{mathpar} - -\begin{mathpar} -\inferrule[e\_unop]{ - \substexpr(\tenv, \substs, \veone) \typearrow \veonep\ -}{ - \substexpr(\tenv, \substs, \overname{\EUnop(\op, \veone)}{\ve}) \typearrow \overname{\EUnop(\op, \veonep)}{\newe} -} -\end{mathpar} - -\begin{mathpar} -\inferrule[e\_binop]{ - \substexpr(\tenv, \substs, \veone) \typearrow \veonep\\ - \substexpr(\tenv, \substs, \vetwop) \typearrow \vetwop -}{ - \substexpr(\tenv, \substs, \overname{\EBinop(\op, \veone, \vetwo)}{\ve}) \typearrow \overname{\EBinop(\op, \veonep, \vetwop)}{\newe} -} -\end{mathpar} - -\begin{mathpar} -\inferrule[e\_cond]{ - \substexpr(\tenv, \substs, \veone) \typearrow \veonep\\ - \substexpr(\tenv, \substs, \vetwop) \typearrow \vetwop\\ - \substexpr(\tenv, \substs, \vethreep) \typearrow \vethreep\\ -}{ - \substexpr(\tenv, \substs, \overname{\ECond(\veone, \vetwo, \vethree)}{\ve}) \typearrow \overname{\ECond(\veonep, \vetwop, \vethreep)}{\newe} -} -\end{mathpar} - -\begin{mathpar} -\inferrule[e\_concat]{ - \vi\in\listrange(\ves): \substexpr(\tenv, \substs, \ves[\vi]) \typearrow \newes_\vi\\ - \vesp \eqdef [\vi\in\listrange(\ves): \newes_\vi] -}{ - \substexpr(\tenv, \substs, \overname{\EConcat(\ves)}{\ve}) \typearrow \overname{\EConcat(\vesp)}{\newe} -} -\end{mathpar} - -\begin{mathpar} -\inferrule[e\_call]{ - \vi\in\listrange(\vargs): \substexpr(\tenv, \substs, \vargs[\vi]) \typearrow \ve_\vi\\ - \vargsp \eqdef [\vi\in\listrange(\vargs): \ve_\vi] -}{ - { - \begin{array}{r} - \substexpr(\tenv, \substs, \overname{\ECall(\vx, \vargs, \paramargs)}{\ve}) \typearrow \\ \overname{\ECall(\vx, \vargsp, \paramargs)}{\newe} - \end{array} - } -} -\end{mathpar} - -\begin{mathpar} -\inferrule[e\_getarray]{ - \substexpr(\tenv, \substs, \veone) \typearrow \veonep\\ - \substexpr(\tenv, \substs, \vetwop) \typearrow \vetwop -}{ - \substexpr(\tenv, \substs, \overname{\EGetArray(\veone, \vetwo)}{\ve}) \typearrow \overname{\EGetArray(\veonep, \vetwop)}{\newe} -} -\end{mathpar} - -\begin{mathpar} -\inferrule[e\_getfield]{ - \substexpr(\tenv, \substs, \veone) \typearrow \veonep -}{ - \substexpr(\tenv, \substs, \overname{\EGetField(\veone, \vx)}{\ve}) \typearrow \overname{\EGetField(\veonep, \vx)}{\newe} -} -\end{mathpar} - -\begin{mathpar} -\inferrule[e\_getfields]{ - \substexpr(\tenv, \substs, \veone) \typearrow \veonep -}{ - \substexpr(\tenv, \substs, \overname{\EGetFields(\veone, \fields)}{\ve}) \typearrow \overname{\EGetFields(\veonep, \fields)}{\newe} -} -\end{mathpar} - -\begin{mathpar} -\inferrule[e\_getitem]{ - \substexpr(\tenv, \substs, \veone) \typearrow \veonep -}{ - \substexpr(\tenv, \substs, \overname{\EGetItem(\veone, \vi)}{\ve}) \typearrow \overname{\EGetItem(\veonep, \vi)}{\newe} -} -\end{mathpar} - -\begin{mathpar} -\inferrule[e\_pattern]{ - \substexpr(\tenv, \substs, \veone) \typearrow \veonep -}{ - \substexpr(\tenv, \substs, \overname{\EPattern(\veone, \vps)}{\ve}) \typearrow \overname{\EPattern(\veonep, \vps)}{\newe} -} -\end{mathpar} - -\begin{mathpar} -\inferrule[e\_record]{ - (\vx, \veone)\in\fields: \substexpr(\tenv, \substs, \veone) \typearrow \veone_\vx\\ - \fieldsp \eqdef [(\vx, \veone)\in\fields: (\vx, \veone_\vx)] -}{ - \substexpr(\tenv, \substs, \overname{\ERecord(\vt, \fields)}{\ve}) \typearrow \overname{\ERecord(\vt, \fieldsp)}{\newe} -} -\end{mathpar} - -\begin{mathpar} -\inferrule[e\_slice]{ - \substexpr(\tenv, \substs, \veone) \typearrow \veonep -}{ - \substexpr(\tenv, \substs, \overname{\ESlice(\veone, \slices)}{\ve}) \typearrow \overname{\ESlice(\veonep, \slices)}{\newe} -} -\end{mathpar} - -\begin{mathpar} -\inferrule[e\_tuple]{ - \vi\in\listrange(\ves): \substexpr(\tenv, \substs, \ves[\vi]) \typearrow \newe_\vi\\ - \vesp \eqdef [\vi\in\listrange(\ves): \newe_\vi] -}{ - \substexpr(\tenv, \substs, \overname{\ETuple(\ves)}{\ve}) \typearrow \overname{\ETuple(\vesp)}{\newe} -} -\end{mathpar} - -\begin{mathpar} -\inferrule[e\_atc]{ - \substexpr(\tenv, \substs, \veone) \typearrow \veonep -}{ - \substexpr(\tenv, \substs, \overname{\EATC(\veone, \vt)}{\ve}) \typearrow \overname{\EATC(\veonep, \vt)}{\newe} -} -\end{mathpar} - -\begin{mathpar} -\inferrule[other]{ - \astlabel(\ve) \in \{\ELiteral, \EUnknown\}\ -}{ - \substexpr(\tenv, \substs, \ve) \typearrow \overname{\ve}{\newe} -} -\end{mathpar} - -\CodeSubsection{\SubstExprBegin}{\SubstExprEnd}{../ASTUtils.ml} - -\section{TypingRule.SubstConstraint \label{sec:TypingRule.SubstConstraint}} -\hypertarget{def-substconstraint}{} -The function -\[ -\substconstraint( - \overname{\staticenvs}{\tenv} \aslsep - \overname{(\identifier\times\expr)^*}{\eqs} \aslsep - \overname{\intconstraint}{\vc} -) \aslto \overname{\newc}{\intconstraint} -\] -transforms the integer constraint $\vc$ in the static environment $\tenv$, -by substituting parameter names with their corresponding expressions in -$\eqs$, and then attempting to symbolically simplify the result, -yielding the integer constraint $\newc$. -\ProseOtherwiseTypeError - -\subsection{Prose} -One of the following applies: -\begin{itemize} - \item All of the following apply (\textsc{exact}): - \begin{itemize} - \item $\vc$ is an exact constraint for the expression $\ve$, that is, $\ConstraintExact(\ve)$; - \item applying $\substexprnormalize$ in $\tenv$ to $\eqs$ and $\ve$ yields $\newe$; - \item define $\newc$ as the exact constraint for the expression $\newe$, that is, \\ - $\ConstraintExact(\newe)$. - \end{itemize} - - \item All of the following apply (\textsc{range}): - \begin{itemize} - \item $\vc$ is a range constraint for the expressions $\veone$ and $\vetwo$, that is, \\ - $\ConstraintRange(\veone, \vetwo)$; - \item applying $\substexprnormalize$ in $\tenv$ to $\eqs$ and $\veone$ yields $\veonep$; - \item applying $\substexprnormalize$ in $\tenv$ to $\eqs$ and $\vetwo$ yields $\vetwop$; - \item define $\newc$ as the range constraint for the expressions $\veonep$ and $\vetwop$, that is, $\ConstraintRange(\veonep, \vetwop)$. - \end{itemize} -\end{itemize} - -\subsection{Formally} -\begin{mathpar} -\inferrule[exact]{ - \substexprnormalize(\tenv, \eqs, \ve) \typearrow \newe -}{ - \substconstraint(\tenv, \eqs, \overname{\ConstraintExact(\ve)}{\vc}) \typearrow \overname{\ConstraintExact(\newe)}{\newc} -} -\and -\inferrule[range]{ - \substexprnormalize(\tenv, \eqs, \veone) \typearrow \veonep\\ - \substexprnormalize(\tenv, \eqs, \vetwo) \typearrow \vetwop -}{ - \substconstraint(\tenv, \eqs, \overname{\ConstraintRange(\veone, \vetwo)}{\vc}) \typearrow \overname{\ConstraintRange(\veonep, \vetwop)}{\newc} -} -\end{mathpar} - -\section{TypingRule.CheckArgsTypeSat \label{sec:TypingRule.CheckArgsTypeSat}} -\hypertarget{def-checkargstypesat}{} -The function -\[ -\begin{array}{r} - \checkargstypesat( - \overname{\staticenvs}{\tenv} \aslsep - \overname{(\identifier\times\ty)^*}{\calleeargs} \aslsep - \overname{\ty^*}{\callerargtypes} \aslsep - \overname{(\identifier\times\expr)^*}{\eqsthree} - ) \aslto \\ - \{\True\}\ \cup \overname{\TTypeError}{\TypeErrorConfig} -\end{array} -\] -checks that the types $\callerargtypes$ \typesatisfy\ the types of the corresponding -formal arguments $\calleeargs$ with the parameters substituted with their corresponding -arguments as per $\eqsthree$ and results in a type error otherwise. - -\subsection{Prose} -One of the following applies: -\begin{itemize} - \item All of the following apply (\textsc{empty}): - \begin{itemize} - \item both $\calleeargs$ and $\callerargtypes$ are empty; - \item the result is $\True$. - \end{itemize} - - \item All of the following apply (\textsc{non\_empty}): - \begin{itemize} - \item view $\calleeargs$ as a list with \head\ $(\calleeargname, \calleearg)$ and \tail\ $\calleeargsone$; - \item view $\callerargtypes$ as a list with \head\ $\callerarg$ and \tail\ \\ - $\callerargtypesone$; - \item applying $\renametyeqs$ to $\eqsthree$ and $\calleearg$ in $\tenv$ - to substitute parameter arguments in $\calleearg$ yields $\calleeargone$\ProseOrTypeError; - \item checking that $\callerarg$ \typesatisfies\ $\calleeargone$ in $\tenv$ yields $\True$\ProseOrTypeError; - \item applying $\checkargstypesat$ to $\calleeargsone$, $\callerargtypesone$, \\ - and $\eqsthree$ in $\tenv$ - yields $\True$\ProseOrTypeError; - \item the result is $\True$. - \end{itemize} -\end{itemize} - -\subsection{Formally} -We note that it is guaranteed by TypingRule.AnnotateCallArgTyped -that $\vargs$ and $\callerargstyped$ have the same length. - -\begin{mathpar} -\inferrule[empty]{}{ - \checkargstypesat(\tenv, \overname{\emptylist}{\calleeargs}, \overname{\emptylist}{\callerargtypes}, \eqsthree) - \typearrow \True -} -\and -\inferrule[non\_empty]{ - \calleeargs \eqname [(\calleeargname, \calleearg)] \concat \calleeargsone\\ - \callerargtypes \eqname [\callerarg] \concat \callerargtypesone\\ - \renametyeqs(\tenv, \eqsthree, \calleearg) \typearrow \calleeargone\OrTypeError\\\\ - \checktypesat(\tenv, \callerarg, \calleeargone) \typearrow \True\OrTypeError\\\\ - \checkargstypesat(\tenv, \calleeargsone, \callerargtypesone, \eqsthree) \typearrow \True -}{ - \checkargstypesat(\tenv, \calleeargs, \callerargtypes, \eqsthree) \typearrow \True -} -\end{mathpar} - -\section{TypingRule.AnnotateParameterDefining \label{sec:TypingRule.AnnotateParameterDefining}} -\hypertarget{def-annotateparameterdefining}{} -The function -\[ - \annotateparameterdefining - \left( - \begin{array}{c} - \overname{\staticenvs}{\tenv} \aslsep\\ - \overname{(\identifier\times\expr)^*}{\eqsone} \aslsep\\ - \overname{(\identifier\times\ty)^*}{\vargs} \aslsep\\ - \overname{(\ty\times\expr)^*}{\callerargstyped} \aslsep\\ - \overname{(\identifier\times\langle\ty\rangle)^*}{\calleeparams} - \end{array} - \right) - \aslto - \begin{array}{c} - \overname{(\identifier\times\expr)^*}{\eqs} \cup \\ - \overname{\TTypeError}{\TypeErrorConfig} - \end{array} -\] -checks that all parameter-defining arguments -in $\calleeparams$ are \staticallyevaluable\ constrained integers. -The result --- $\eqs$ --- is the list of parameter identifiers and their corresponding expressions, -added to $\eqsone$. -\ProseOtherwiseTypeError - -\subsection{Prose} -One of the following applies: -\begin{itemize} - \item All of the following apply (\textsc{empty}): - \begin{itemize} - \item both $\vargs$ and $\callerargstyped$ are empty; - \item define $\eqs$ as $\eqsone$. - \end{itemize} - - \item All of the following apply: - \begin{itemize} - \item view $\vargs$ as a list with \head\ $(\calleex, \Ignore)$ and \tail\ $\vargsone$; - \item view $\callerargstyped$ as a list with \head\ $(\callerty, \callere)$ and \tail\ $\callerargstypedone$; - \item define $\calleeargisparam$ as $\True$ if and only if $\calleex$ is listed as a parameter in $\calleeparams$; - \item One of the following applies: - \begin{itemize} - \item All of the following apply (\textsc{arg\_is\_param}): - \begin{itemize} - \item $\calleeargisparam$ is $\True$; - \item checking that $\callere$ is \staticallyevaluable\ in $\tenv$ yields $\True$\ProseOrTypeError; - \item checking that $\callerty$ is a constrained integer in $\tenv$ yields \\ - $\True$\ProseOrTypeError; - \item applying $\annotateparameterdefining$ to $\vargsone$, \\ - $\callerargstypedone$, $\eqsone$ in $\tenv$ yields $\eqstwo$\ProseOrTypeError; - \item define $\eqs$ as a list with \head\ $(\calleex, \callere)$ and \tail\ $\eqstwo$. - \end{itemize} - - \item All of the following apply (\textsc{arg\_is\_not\_param}): - \begin{itemize} - \item $\calleeargisparam$ is $\False$; - \item applying $\annotateparameterdefining$ to $\vargsone$, \\ - $\callerargstypedone$, $\eqsone$ in $\tenv$ yields $\eqs$\ProseOrTypeError. - \end{itemize} - \end{itemize} - \end{itemize} -\end{itemize} - -\subsection{Formally} -We note that it is guaranteed by TypingRule.AnnotateCallArgTyped -that $\vargs$ and $\callerargstyped$ have the same length. - -\begin{mathpar} -\inferrule[empty]{}{ - { - \begin{array}{r} - \annotateparameterdefining(\tenv, \eqsone, \overname{\emptylist}{\vargs}, \overname{\emptylist}{\callerargstyped}, \calleeparams) - \typearrow \\ - \overname{\eqsone}{\eqs} - \end{array} - } -} -\end{mathpar} - -\begin{mathpar} -\inferrule[arg\_is\_param]{ - \vargs \eqname [(\calleex, \Ignore)] \concat \vargsone\\ - \callerargstyped \eqname [(\callerty, \callere)] \concat \callerargstypedone\\ - { - \left(\begin{array}{l} - \calleeargisparam \eqdef \\ - \exists \vi\in\listrange(\calleeparams).\ \calleeparams[\vi]=(\calleex, \Ignore) - \end{array}\right) - }\\\\ - \commonprefixline\\\\ - \calleeargisparam\ = \True\\ - \checkstaticallyevaluable(\tenv, \callere) \typearrow \True\OrTypeError\\\\ - \checkconstrainedinteger(\tenv, \callerty) \typearrow \True\OrTypeError\\\\ - { - \begin{array}{r} - \annotateparameterdefining(\tenv, \vargsone, \callerargstypedone, \eqsone) \typearrow \\ \eqstwo \OrTypeError - \end{array} - }\\ - \eqs \eqdef [(\calleex, \callere)] \concat \eqstwo -}{ - { - \annotateparameterdefining - \left( - \begin{array}{c} - \tenv, \\ - \eqsone, \\ - \vargs, \\ - \callerargstyped, \\ - \calleeparams - \end{array} - \right) - \typearrow \eqs \OrTypeError - } -} -\end{mathpar} - -\begin{mathpar} -\inferrule[arg\_is\_not\_param]{ - \vargs \eqname [(\calleex, \Ignore)] \concat \vargsone\\ - \callerargstyped \eqname [(\callerty, \callere)] \concat \callerargstypedone\\ - { - \left(\begin{array}{l} - \calleeargisparam \eqdef \\ - \exists \vi\in\listrange(\calleeparams).\ \calleeparams[\vi]=(\calleex, \Ignore) - \end{array}\right) - }\\\\ - \commonprefixline\\\\ - \calleeargisparam = \False\\ - \annotateparameterdefining(\tenv, \vargsone, \callerargstypedone, \eqsone) \typearrow \eqs\\ -}{ - { - \annotateparameterdefining - \left( - \begin{array}{c} - \tenv, \\ - \eqsone, \\ - \vargs, \\ - \callerargstyped, \\ - \calleeparams - \end{array} - \right) - \typearrow \eqs \OrTypeError - } -} -\end{mathpar} - -\section{TypingRule.AnnotateRetTy \label{sec:TypingRule.AnnotateRetTy}} -\hypertarget{def-annotateretty}{} -The function -\[ -\begin{array}{r} -\annotateretty( - \overname{\staticenvs}{\tenv} \aslsep - \overname{\subprogramtype}{\calltype} \aslsep - \overname{\langle\ty\rangle}{\calleerettyopt} - \overname{(\identifier\times\expr)^*}{\eqsthree} -) \aslto \\ -\overname{\langle\ty\rangle}{\rettyopt} -\cup \overname{\TTypeError}{\TypeErrorConfig} -\end{array} -\] -annotates the \optional\ return type $\calleerettyopt$ given with the subprogram type -$\calltype$ with respect to the parameter expressions $\eqsthree$, -yielding the \optional\ annotated type $\rettyopt$. -\ProseOtherwiseTypeError - -\subsection{Prose} -One of the following applies: -\begin{itemize} - \item All of the following apply (\textsc{function\_or\_getter}): - \begin{itemize} - \item $\calltype$ is one of $\STFunction$, $\STGetter$, or $\STEmptyGetter$; - \item $\calleerettyopt$ is $\langle\tty\rangle$; - \item applying $\renametyeqs$ to $\eqsthree$ and $\tty$ yields $\ttyone$\ProseOrTypeError; - \item $\rettyopt$ is $\langle\ttyone\rangle$. - \end{itemize} - - \item All of the following apply (\textsc{procedure\_or\_setter}): - \begin{itemize} - \item $\calltype$ is one of $\STProcedure$, $\STSetter$, or $\STEmptySetter$; - \item $\calleerettyopt$ is $\None$; - \item define $\rettyopt$ as $\None$. - \end{itemize} - - \item All of the following apply (\textsc{ret\_type\_mismatch}): - \begin{itemize} - \item the condition that $\calltype$ is one of $\STProcedure$, $\STSetter$, or \\ - $\STEmptySetter$ - if and only if $\calleerettyopt$ is $\None$ does not hold; - \item the result is a type error indicating the mismatch. - \end{itemize} -\end{itemize} - -\subsection{Formally} -\begin{mathpar} -\inferrule[function\_or\_getter]{ - \calltype \in \{\STFunction, \STGetter, \STEmptyGetter\}\\ - \renametyeqs(\eqsthree, \tty) \typearrow \ttyone \OrTypeError -}{ - \annotateretty(\tenv, \calltype, \overname{\langle\tty\rangle}{\calleerettyopt}, \eqsthree) \typearrow - \overname{\langle\ttyone\rangle}{\rettyopt} -} -\end{mathpar} - -\begin{mathpar} -\inferrule[procedure\_or\_setter]{ - \calltype \in \{\STProcedure, \STSetter, \STEmptySetter\}\\ -}{ - \annotateretty(\tenv, \calltype, \overname{\None}{\calleerettyopt}, \eqsthree) \typearrow - \overname{\None}{\rettyopt} -} -\end{mathpar} - -\begin{mathpar} -\inferrule[ret\_type\_mismatch]{ - { - \neg\left( - \begin{array}{c}\calltype \in \{\STProcedure, \STSetter, \STEmptySetter\} \leftrightarrow \\ - \calleerettyopt=\None - \end{array} - \right) - } -}{ - \annotateretty(\tenv, \calltype, \calleerettyopt, \eqsthree) \typearrow - \TypeErrorVal{\MismatchedReturnValue} -} -\end{mathpar} - -\section{TypingRule.SubprogramForName \label{sec:TypingRule.SubprogramForName}} -\hypertarget{def-subprogramforname}{} -The function -\[ - \begin{array}{rl} - \subprogramforname( - \overname{\staticenvs}{\tenv} \aslsep - \overname{\Strings}{\name} \aslsep - \overname{\ty^*}{\callerargtypes} - ) - \aslto & - (\overname{(\identifier \times \expr)^*}{\extranargs} \aslsep - \overname{\Strings}{\namep} \aslsep - \overname{\func}{\callee} - )\\ - & \cup\ \overname{\TTypeError}{\TypeErrorConfig} - \end{array} -\] -looks up the static environment $\tenv$ for a subprogram associated with $\name$ -and the list of argument types $\calleeargtypes$ and determines which one of the following -cases holds: -\begin{itemize} - \item there is no declared subprogram that matches $\name$ and $\calleeargtypes$; - \item there is exactly one subprogram that matches $\name$ and $\calleeargtypes$; - \item there is more than one subprogram that matches $\name$ and $\calleeargtypes$; -\end{itemize} -The first and last cases result in a type error. -If the second case holds, the function returns a tuple comprised of: -\begin{itemize} -\item $\extranargs$ --- the list of extra named arguments (parameters); -\item $\namep$ --- the string that uniquely identifies this subprogram; -\item $\callee$ --- the AST node defining the called subprogram. -\end{itemize} -\ProseOtherwiseTypeError - -\subsection{Prose} -One of the following applies: -\begin{itemize} - \item All of the following apply (\textsc{undefined}): - \begin{itemize} - \item $\tenv$ does not contain a binding for $\name$ in the $\subprogramrenamings$ map - ($G^\tenv.\subprogramrenamings$); - \item the result is a type error indicating that the identifier has not been declared (as a subprogram). - \end{itemize} - - \item All of the following apply (\textsc{no\_candidates}): - \begin{itemize} - \item $\tenv$ binds $\name$ via $\subprogramrenamings$ map to $\renamingset$; - \item filtering the subprograms in $\renamingset$ with the caller argument types $\callerargtypes$ - in $\tenv$ (see \secref{TypingRule.FilterCallCandidates}) yields an empty set\ProseOrTypeError; - \item the result is a type error indicating that the call given by $\name$ and \\ $\callerargtypes$ - does not match any defined subprogram. - \end{itemize} - - \item All of the following apply (\textsc{too\_many\_candidates}): - \begin{itemize} - \item $\tenv$ binds $\name$ via $\subprogramrenamings$ map to $\renamingset$; - \item filtering the subprograms in $\renamingset$ with the caller argument types $\callerargtypes$ - in $\tenv$ (see \secref{TypingRule.FilterCallCandidates}) yields $\matchingrenamings$\ProseOrTypeError; - \item $\matchingrenamings$ contains at least two elements; - \item the result is a type error indicating that the call given by $\name$ and \\ - $\callerargtypes$ matches more than one defined subprogram. - \end{itemize} - - \item All of the following apply (\textsc{one\_candidate}): - \begin{itemize} - \item $\tenv$ binds $\name$ via $\subprogramrenamings$ map to $\renamingset$; - \item filtering the subprograms in $\renamingset$ with the caller argument types $\callerargtypes$ - in $\tenv$ (see \secref{TypingRule.FilterCallCandidates}) yields $\matchingrenamings$\ProseOrTypeError; - \item $\matchingrenamings$ contains a single element --- $(\matchedname, \funcsig)$; - \item deducing the argument values for the parameters via $\deduceeqs$ with \\ - $\callerargtypes$, $\funcsig.\funcargs$ in $\tenv$ yields \\ - $(\extranargs, \namep, \callee)$\ProseOrTypeError. - \end{itemize} -\end{itemize} - -\isempty{\subsection{Example}} - -\CodeSubsection{\SubprogramForNameBegin}{\SubprogramForNameEnd}{../Typing.ml} - -\subsection{Formally} -\begin{mathpar} -\inferrule[undefined]{ - G^\tenv.\subprogramrenamings(\name) = \bot -}{ - \subprogramforname(\tenv, \name, \callerargtypes) \typearrow \TypeErrorVal{\UndefinedIdentifier} -} -\end{mathpar} - -\begin{mathpar} -\inferrule[no\_candidates]{ - G^\tenv.\subprogramrenamings(\name) = \renamingset\\ - { - \begin{array}{r} - \filtercallcandidates(\tenv, \callerargtypes, \renamingset) \typearrow \emptyset \OrTypeError - \end{array} - } -}{ - \subprogramforname(\tenv, \name, \callerargtypes) \typearrow \TypeErrorVal{\NoCallCandidates} -} -\end{mathpar} - -\begin{mathpar} -\inferrule[too\_many\_candidates]{ - G^\tenv.\subprogramrenamings(\name) = \renamingset\\ - { - \begin{array}{r} - \filtercallcandidates(\tenv, \callerargtypes, \renamingset) \typearrow \\ \matchingrenamings \OrTypeError - \end{array} - }\\\\ - \cardinality{\matchingrenamings} \geq 2 -}{ - \subprogramforname(\tenv, \name, \callerargtypes) \typearrow \TypeErrorVal{\TooManyCandidates} -} -\end{mathpar} - -\begin{mathpar} -\inferrule[one\_candidate]{ - G^\tenv.\subprogramrenamings(\name) = \renamingset\\ - { - \begin{array}{r} - \filtercallcandidates(\tenv, \callerargtypes, \renamingset) \typearrow \\ \matchingrenamings \OrTypeError - \end{array} - }\\\\ - \matchingrenamings = [(\matchedname, \funcsig)]\\ - { - \begin{array}{r} - \deduceeqs(\tenv, \callerargtypes, \funcsig.\funcargs) - \typearrow \\ (\extranargs, \namep, \callee) \OrTypeError - \end{array} - } -}{ - { - \begin{array}{r} - \subprogramforname(\tenv, \name, \callerargtypes) \typearrow \\ (\extranargs, \namep, \callee) - \end{array} - } -} -\end{mathpar} - -\section{TypingRule.DeduceEqs \label{sec:TypingRule.DeduceEqs}} -\hypertarget{def-deduceeqs}{} -The function -\[ -\deduceeqs( - \overname{\staticenvs}{\tenv} \aslsep - \overname{\ty^*}{\callerargtypes} \aslsep - \overname{(\identifier\times\ty)^*}{\vargs} -) \aslto -\overname{(\identifier\times\expr)^*}{\eqs} -\cup \overname{\TTypeError}{\TypeErrorConfig} -\] -takes the types of the actual arguments of a call --- $\callerargtypes$, -the list of formal arguments --- $\vargs$ --- which consist of the names of a subprogram arguments -and their associated types, and -infers the expressions associated with parameters that correspond to bitvector widths, -yielding the result in $\eqs$. -\ProseOtherwiseTypeError - -It guaranteed that by TypingRule.HasArgClash, -which is used by \\ TypingRule.FilterCallCandidates before calling $\deduceeqs$, -that $\callerargtypes$ and $\vargs$ have the same length. - -\subsection{Prose} -One of the following applies: -\begin{itemize} - \item All of the following apply (\textsc{empty}): - \begin{itemize} - \item both $\callerargtypes$ and $\vargs$ are empty lists; - \item define $\eqs$ as the empty list. - \end{itemize} - - \item All of the following apply (\textsc{not\_bits\_parameter}): - \begin{itemize} - \item $\callerargtypes$ has \head\ $\caller$ and \tail\ $\callerargtypesone$; - \item $\vargs$ has \head\ $(\Ignore, \callee)$ and \tail\ $\vargsone$; - \item $\caller$ is not a bitvector type with a width expression that is a variable expression; - \item applying $\deduceeqs$ to $\callerargtypesone$ and $\vargsone$ in $\tenv$ yields $\eqs$. - \end{itemize} - - \item All of the following apply (\textsc{bits\_parameter}): - \begin{itemize} - \item $\callerargtypes$ has \head\ $\caller$ and \tail\ $\callerargtypesone$; - \item $\vargs$ has \head\ $(\Ignore, \callee)$ and \tail\ $\vargsone$; - \item $\caller$ is bitvector type whose width expression is the variable expression for $\vx$; - \item obtaining the \structure\ of $\caller$ in $\tenv$ yields the bitvector type with width expression $\ecaller$\ProseOrTypeError; - \item applying $\deduceeqs$ to $\callerargtypesone$ and $\vargsone$ in $\tenv$ yields $\eqsone$; - \item define $\eqs$ as the list with \head\ $(\vx, \ecaller)$. - \end{itemize} -\end{itemize} - -\subsection{Formally} -\begin{mathpar} -\inferrule[empty]{}{ - \deduceeqs(\tenv, \overname{\emptylist}{\callerargtypes}, \overname{\emptylist}{\vargs}) \typearrow \overname{\emptylist}{\eqs} -} -\end{mathpar} - -\begin{mathpar} -\inferrule[not\_bits\_parameter]{ - \caller \neq \TBits(\EVar(\Ignore))\\ - \deduceeqs(\tenv, \callerargtypesone, \vargsone) \typearrow \eqs -}{ - \deduceeqs( - \tenv, - \overname{[\caller] \concat \callerargtypesone}{\callerargtypes}, - \overname{[(\Ignore, \callee)] \concat \vargsone}{\vargs}) \typearrow \eqs -} -\end{mathpar} - -\begin{mathpar} -\inferrule[bits\_parameter]{ - \caller = \TBits(\EVar(\vx))\\ - \tstruct(\tenv, \caller) \typearrow \TBits(\ecaller, \Ignore) \OrTypeError\\\\ - \deduceeqs(\tenv, \callerargtypesone, \vargsone) \typearrow \eqsone\\ - \eqs \eqdef [(\vx, \ecaller)] \concat \eqsone -}{ - \deduceeqs( - \tenv, - \overname{[\caller] \concat \callerargtypesone}{\callerargtypes}, - \overname{[(\Ignore, \callee)] \concat \vargsone}{\vargs}) \typearrow \eqs -} -\end{mathpar} - -\section{TypingRule.FilterCallCandidates \label{sec:TypingRule.FilterCallCandidates}} -\hypertarget{def-filtercandidates}{} -The helper function -\[ - \filtercallcandidates( - \overname{\staticenvs}{\tenv} \aslsep - \overname{\ty^*}{\formaltypes} \aslsep - \overname{\pow{\Strings}}{\candidates} - ) - \aslto \overname{(\Strings\times\func)^*}{\matches} -\] -iterates over the list of unique subprogram names in $\candidates$ and checks whether -their lists of arguments clash with the types in $\formaltypes$ in $\tenv$. -The result is the set of pairs consisting of the names and function definitions of the -subprograms whose arguments clash in $\candidates$. -\ProseOtherwiseTypeError - -The names $\candidates$ are assumed to exist in $G^\tenv.\subprograms$. - -\subsection{Prose} -One of the following applies: -\begin{itemize} - \item All of the following apply (\textsc{no\_candidates}): - \begin{itemize} - \item $\candidates$ is empty; - \item $\matches$ is empty. - \end{itemize} - - \item All of the following apply (\textsc{candidates\_exist}): - \begin{itemize} - \item $\candidates$ is a list with \head\ $\name$ and \tail\ $\candidatesone$; - \item the function definition associated with $\name$ in $\tenv$ is $\funcdef$; - \item determining whether there is an argument clash between $\formaltypes$ and the arguments in $\funcdef$ - (that is, $\funcdef.\funcargs$) yields $\vb$\ProseOrTypeError; - \item filtering the call candidates in $\candidatesone$ with $\formaltypes$ in $\tenv$ yields $\matchesone$\ProseOrTypeError; - \item if $\vb$ is $\True$ then $\matches$ is the list with \head\ $(\name,\funcdef)$ and \tail\ $\matchesone$, - and otherwise it is $\matchesone$. - \end{itemize} -\end{itemize} - -\subsection{Formally} -\begin{mathpar} -\inferrule[no\_candidates] -{}{ - \filtercallcandidates(\tenv, \formaltypes, \overname{\emptylist}{\candidates}) \typearrow \overname{\emptylist}{\matches} -} -\and -\inferrule[candidates\_exist] -{ - \funcdef \eqdef G^\tenv.\subprograms(\name) \\ - \hasargclash(\tenv, \formaltypes, \funcdef.\funcargs) \typearrow \vb \OrTypeError\\\\ - \filtercallcandidates(\tenv, \formaltypes, \candidatesone) \typearrow \matchesone \OrTypeError\\\\ - \matches \eqdef \choice{\vb}{\;[(\name,\funcdef)] \concat \matchesone}{\;\matchesone} -}{ - \filtercallcandidates(\tenv, \formaltypes, \overname{[\name] \concat \candidatesone}{\candidates}) \typearrow \matches -} -\end{mathpar} - -\section{TypingRule.HasArgClash \label{sec:TypingRule.HasArgClash}} -\hypertarget{def-hasargclash}{} -The function -\[ - \hasargclash( - \overname{\staticenvs}{\tenv} \aslsep - \overname{\ty^*}{\formaltys} \aslsep - \overname{(\identifier\times\ty)^*}{\vargs} - ) - \aslto \overname{\Bool}{\vb} \cup \overname{\TTypeError}{\TypeErrorConfig} -\] -checks whether a list of types $\formaltys$ clashes with the list of types appearing -in the list of arguments $\vargs$ in $\tenv$, yielding the result in $\vb$. -\ProseOtherwiseTypeError - -\subsection{Prose} -All of the following apply: -\begin{itemize} - \item equating the list lengths of $\formaltys$ and $\vargs$ either yields $\True$ - or $\False$, which short-circuits the entire rule; - \item $\argtys$ is the list of types appearing in $\vargs$, in the same order; - \item for each $\vi$ in the list of indices of $\formaltys$, applying $\typeclashes$ to - $\formaltys[\vi]$ and $\argtys[\vi]$ in $\tenv$ yields $\True$\ProseTerminateAs{\False, \TypeErrorConfig}; - \item $\vb$ is $\True$ (unless the rule short-circuited with $\False$ or a type error). -\end{itemize} - -\CodeSubsection{\HasArgClashBegin}{\HasArgClashEnd}{../Typing.ml} - -\subsection{Formally} -\begin{mathpar} -\inferrule{ - \equallength(\formaltypes, \vargs) \typearrow \True \terminateas \False\\ - \argtys \eqdef [(\Ignore, \vt) \in \vargs: \vt]\\ - \vi\in\listrange(\formaltys): \typeclashes(\tenv, \formaltys[\vi], \argtys[\vi]) \typearrow \True \terminateas \False,\TypeErrorConfig -}{ - \hasargclash(\tenv, \formaltys, \vargs) \typearrow \overname{\True}{\vb} -} -\end{mathpar} - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -\chapter{Typing of Subprograms \label{chap:TypingSubprograms}} -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -\hypertarget{def-annotatesubprogram}{} -The function -\[ - \annotatesubprogram{\overname{\staticenvs}{\tenv} \aslsep \overname{\func}{\vf}} \aslto \overname{\func}{\vfp} - \cup \overname{\TTypeError}{\TypeErrorConfig} -\] -annotates a subprogram $\vf$ in an environment $\tenv$, resulting in an annotated subprogram $\vfp$. -\ProseOtherwiseTypeError - -Note that the return type in $\vf$ has already been annotated by $\annotatefuncsig$. - -\section{TypingRule.Subprogram \label{sec:TypingRule.Subprogram}} - -\subsection{Prose} -All of the following apply: -\begin{itemize} - \item $\vf$ is a $\func$ AST node subprogram body $\body$; - \item annotating the block $\body$ in $\tenv$ as per \secref{TypingRule.Block} yields $\newbody$\ProseOrTypeError; - \item $\vfp$ is $\vf$ with the subprogram body substituted with $\newbody$. -\end{itemize} - -\isempty{\subsection{Example}} - -\subsection{Formally} -\begin{mathpar} -\inferrule{ - { - \begin{array}{rrcl} - \vf \eqname \{ & \funcname &:& \id,\\ - & \funcparameters &:& \vp,\\ - & \funcargs &:& \vargs,\\ - & \funcbody &:& \SBASL(\body),\\ - & \funcreturntype &:& \vt,\\ - & \funcsubprogramtype &:& \subprogramtype \\ - \} &&& - \end{array} - }\\ - \annotateblock{\tenv, \body} \typearrow \newbody \OrTypeError\\\\ - { - \begin{array}{rrcl} - \vfp \eqdef \{ & \funcname &:& \id,\\ - & \funcparameters &:& \vp,\\ - & \funcargs &:& \vargs,\\ - & \funcbody &:& \SBASL(\newbody),\\ - & \funcreturntype &:& \vt,\\ - & \funcsubprogramtype &:& \subprogramtype \\ - \} &&& - \end{array} - }\\ -}{ - \annotatesubprogram{\tenv, \vf} \typearrow \vfp -} -\end{mathpar} - -\isempty{\subsection{Comments}} -\lrmcomment{ -This is related to \identi{GHGK}, \identr{HWTV}, \identr{SCHV}, \identr{VDPC}, -\identr{TJKQ}, \identi{LFJZ}, \identi{BZVB}, \identi{RQQB}. -} -\CodeSubsection{\SubprogramBegin}{\SubprogramEnd}{../Typing.ml} - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -\chapter{Typing of Global Declarations} -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -\hypertarget{def-typecheckdecl}{} -The function -\[ - \typecheckdecl( - \overname{\staticenvs}{\tenv} \aslsep - \overname{\decl}{\vd} - ) - \aslto (\overname{\decl}{\newd} \times \overname{\staticenvs}{\newtenv}) - \cup \overname{\TTypeError}{\TypeErrorConfig} -\] -annotates a global declaration $\vd$ in the static environment $\tenv$, -yielding an annotated global declaration $\newd$ and modified environment $\newtenv$. -\ProseOtherwiseTypeError - -One of the following applies: -\begin{itemize} - \item TypingRule.TypecheckFunc (see \secref{TypingRule.TypecheckFunc}) - \item TypingRule.TypecheckGlobalStorage (see \secref{TypingRule.TypecheckGlobalStorage}) - \item TypingRule.TypecheckTypeDecl (see \secref{TypingRule.TypecheckTypeDecl}) -\end{itemize} -We also define the following helper rules: -\begin{itemize} - \item TypingRule.AnnotateAndDeclareFunc (see \secref{TypingRule.AnnotateAndDeclareFunc}) - \item TypingRule.AnnotateFuncSig (see \secref{TypingRule.AnnotateFuncSig}) - \item TypingRule.UseFuncSig (\secref{TypingRule.UseFuncSig}) - \item TypingRule.GetUndeclaredDefining (see \secref{TypingRule.GetUndeclaredDefining}) - \item TypingRule.ScanForParams (see \secref{TypingRule.ScanForParams}) - \item TypingRule.AnnotateParams (see \secref{TypingRule.AnnotateParams}) - \item TypingRule.AnnotateOneParam (see \secref{TypingRule.AnnotateOneParam}) - \item TypingRule.ArgsAsParams (see \secref{TypingRule.ArgsAsParams}) - \item TypingRule.ArgAsParam (see \secref{TypingRule.ArgAsParam}) - \item TypingRule.AnnotateParamType (see \secref{TypingRule.AnnotateParamType}) - \item TypingRule.AnnotateArgs (see \secref{TypingRule.AnnotateArgs}) - \item TypingRule.AnnotateOneArg (see \secref{TypingRule.AnnotateOneArg}) - \item TypingRule.AnnotateReturnType (see \secref{TypingRule.AnnotateReturnType}) - \item TypingRule.DeclareOneFunc (see \secref{TypingRule.DeclareOneFunc}) - \item TypingRule.SubprogramClash (see \secref{TypingRule.SubprogramClash}) - \item TypingRule.AddNewFunc (see \secref{TypingRule.AddNewFunc}) - \item TypingRule.CheckSetterHasGetter (see \secref{TypingRule.CheckSetterHasGetter}) - \item TypingRule.AddSubprogram (see \secref{TypingRule.AddSubprogram}) - \item TypingRule.DeclareGlobalStorage (see \secref{TypingRule.DeclareGlobalStorage}) - \item TypingRule.AnnotateTypeOpt (see \secref{TypingRule.AnnotateTypeOpt}) - \item TypingRule.AnnotateExprOpt (see \secref{TypingRule.AnnotateExprOpt}) - \item TypingRule.AnnotateInitType (see \secref{TypingRule.AnnotateInitType}) - \item TypingRule.AddGlobalStorage (see \secref{TypingRule.AddGlobalStorage}) - \item TypingRule.DeclareType (see \secref{TypingRule.DeclareType}) - \item TypingRule.AnnotateExtraFields (see \secref{TypingRule.AnnotateExtraFields}) - \item TypingRule.AnnotateEnumLabels (see \secref{TypingRule.AnnotateEnumLabels}) - \item TypingRule.DeclareConst (see \secref{TypingRule.DeclareConst}) -\end{itemize} - -\section{TypingRule.TypecheckFunc \label{sec:TypingRule.TypecheckFunc}} -\subsection{Prose} -All of the following apply: -\begin{itemize} - \item $\vd$ is a subprogram AST node with a subprogram definition $\vf$, that is, $\DFunc(\vf)$; - \item annotating and declaring the subprogram for $\vf$ in $\tenv$ as per \secref{TypingRule.AnnotateAndDeclareFunc} - yields the new environment $\newtenv$ and a subprogram definition $\vfone$\ProseOrTypeError; - \item annotating the subprogram definition $\vfone$ in $\tenv$ as per \chapref{TypingSubprograms} yields - the annotated subprogram definition $\vftwo$\ProseOrTypeError; - \item define $\newd$ as the subprogram AST node with $\vftwo$, that is, $\DFunc(\vftwo)$. -\end{itemize} - -\isempty{\subsection{Example}} -\CodeSubsection{\TypecheckFuncBegin}{\TypecheckFuncEnd}{../Typing.ml} - -\subsection{Formally} -\begin{mathpar} -\inferrule{ - \vf \eqname \{\text{body}: \SBASL, \ldots\}\\ - \annotateanddeclarefunc(\tenv, \vf) \typearrow (\newtenv, \vfone) \OrTypeError\\\\ - \annotatesubprogram{\newtenv, \vfone} \typearrow \vftwo \OrTypeError -}{ - \typecheckdecl(\tenv, \overname{\DFunc(\vf)}{\vd}) - \typearrow (\overname{\DFunc(\vftwo)}{\newd}, \newtenv) -} -\end{mathpar} - -\section{TypingRule.TypecheckGlobalStorage \label{sec:TypingRule.TypecheckGlobalStorage}} -\subsection{Prose} -All of the following apply: -\begin{itemize} - \item $\vd$ is a global storage declaration with description $\gsd$, that is, \\ $\DGlobalStorage(\gsd)$; - \item declaring the global storage with description $\gsd$ in $\tenv$ yields the new environment - $\newtenv$ and new global storage description $\gsdp$\ProseOrTypeError; - \item define $\newd$ as the global storage declaration with description $\gsdp$, that is, \\ $\DGlobalStorage(\gsdp)$. -\end{itemize} -\isempty{\subsection{Example}} - -\CodeSubsection{\TypecheckGlobalStorageBegin}{\TypecheckGlobalStorageEnd}{../Typing.ml} - -\subsection{Formally} -\begin{mathpar} -\inferrule{ - \declareglobalstorage(\tenv, \gsd) \typearrow (\newtenv, \gsdp) \OrTypeError -}{ - { - \begin{array}{r} - \typecheckdecl(\tenv, \overname{\DGlobalStorage(\gsd)}{\vd}) - \typearrow \\ (\overname{\DGlobalStorage(\gsdp)}{\newd}, \newtenv) - \end{array} - } -} -\end{mathpar} - -\section{TypingRule.TypecheckTypeDecl \label{sec:TypingRule.TypecheckTypeDecl}} -\subsection{Prose} -All of the following apply: -\begin{itemize} - \item $\vd$ is a type declaration with identifier $\vx$, type $\tty$, - and \optional\ field initializers $\vs$, that is, $\DTypeDecl(\vx, \tty, \vs)$; - \item declaring the type described by $(\vx, \tty, \vs)$ in $\tenv$ - as per \secref{TypingRule.DeclaredType} yields the modified environment $\newtenv$\ProseOrTypeError; - \item define $\newd$ as $\vd$. - \end{itemize} - -\isempty{\subsection{Example}} - -\CodeSubsection{\TypecheckTypeDeclBegin}{\TypecheckTypeDeclEnd}{../Typing.ml} - -\subsection{Formally} -\begin{mathpar} -\inferrule{ - \declaretype(\tenv, \vx, \tty, \vs) \typearrow \newtenv \OrTypeError -}{ - \typecheckdecl(\tenv, \overname{\DTypeDecl(\vx, \tty, \vs)}{\vd}) \typearrow (\overname{\vd}{\newd}, \newtenv) -} -\end{mathpar} - -\section{TypingRule.AnnotateAndDeclareFunc \label{sec:TypingRule.AnnotateAndDeclareFunc}} -\hypertarget{def-annotateanddeclarefunc}{} -The function -\[ - \annotateanddeclarefunc(\overname{\staticenvs}{\tenv}, \overname{\func}{\funcsig}) - \aslto (\overname{\staticenvs}{\tenv} \times \overname{\func}{\newfuncsig}) - \cup \overname{\TTypeError}{\TypeErrorConfig} -\] -annotates a subprogram definition $\funcsig$ in the static environment $\tenv$, -yielding a new subprogram definition $\newfuncsig$ and modified static environment -$\newtenv$. -\ProseOtherwiseTypeError - -\subsection{Prose} -All of the following apply: -\begin{itemize} - \item annotating the signature of $\funcsig$ in $\tenv$ as per - \secref{TypingRule.AnnotateFuncSig} yields - the environment $\tenvone$ and subprogram definition $\funcsigone$\ProseOrTypeError; - \item declaring the subprogram defined by $\funcsigone$ in $\tenvone$ - as per \secref{TypingRule.DeclareOneFunc} yields the environment $\newtenv$ - and new $\func$ node $\newfuncsig$\ProseOrTypeError. -\end{itemize} - -\isempty{\subsection{Example}} - -\CodeSubsection{\AnnotateAndDeclareFuncBegin}{\AnnotateAndDeclareFuncEnd}{../Typing.ml} - -\subsection{Formally} -\begin{mathpar} -\inferrule{ - \annotatefuncsig(\tenv, \funcsig) \typearrow (\tenvone, \funcsigone) \OrTypeError\\\\ - \declareonefunc(\tenvone, \funcsigone) \typearrow (\newtenv, \newfuncsig) \OrTypeError -}{ - \annotateanddeclarefunc(\tenv, \funcsig) \typearrow (\newtenv, \newfuncsig) -} -\end{mathpar} - -\section{TypingRule.AnnotateFuncSig \label{sec:TypingRule.AnnotateFuncSig}} -\hypertarget{def-annotatefuncsig}{} -The function -\[ - \annotatefuncsig(\overname{\staticenvs}{\tenv}, \overname{\func}{\funcsig}) - \aslto (\overname{\staticenvs}{\newtenv} \times \overname{\func}{\newfuncsig}) - \cup \overname{\TTypeError}{\TypeErrorConfig} -\] -annotates the signature of a function definition $\funcsig$ in the static environment $\tenv$, -yielding a new function definition $\newfuncsig$ and modified static environment -$\newtenv$. -\ProseOtherwiseTypeError - -\subsection{Prose} -All of the following apply: -\begin{itemize} - \item $\tenvone$ is the static environment comprised of the global environment of $\tenv$ and an empty local environment; - \item obtaining the variables appearing in the formal types in $\funcsig$ that may be parameter-defining - in $\tenvone$ via $\getundeclareddefining$ yields \\ $\potentialparams$; - \item annotating the parameters explicitly listed in $\funcsig$ ($\funcsig.\funcparameters)$ \\ - yields environment $\tenvtwo$, in which the parameters are declared, - and the function \\ - $\declaredparams$, which binds parameter identifiers to their types\ProseOrTypeError; - \item annotating arguments from $\funcsig$ that serve as parameters in $\tenvtwo$ yields the list of parameters - $\argparams$ and modified environment $\tenvthree$\ProseOrTypeError; - \item $\vparameters$ is the list $\declaredparams$ concatenated with $\argparams$ with each type - transformed to an \optional\ type; - \item annotating the arguments listed in $\funcsig$ in $\tenvthree$ with $\tenvtwo$ via \\ - $\annotateargs$ yields the list of annotated - arguments $\vargs$ and modified environment $\tenvfour$\ProseOrTypeError; - \item annotating the return type of $\funcsig$ in $\tenvfour$ with $\tenvthree$ via \\ $\annotatereturntype$ yields - the annotated return type $\vreturntype$ and modified environment $\tenvfive$\ProseOrTypeError; - \item $\newfuncsig$ is $\funcsig$ with the listed of parameters substituted with \\ $\vparameters$, - the list of arguments substituted with $\vargs$, and return type substituted with $\vreturntype$; - \item $\newtenv$ is $\tenvfive$. -\end{itemize} -\isempty{\subsection{Example}} - -\CodeSubsection{\AnnotateFuncSigBegin}{\AnnotateFuncSigEnd}{../Typing.ml} - -\subsection{Formally} -\begin{mathpar} -\inferrule{ - \tenvone \eqdef (G^\tenv, L^{\emptytenv})\\ - \getundeclareddefining(\tenvone, \funcsig) \typearrow \potentialparams\\ - { - \begin{array}{r} - \annotateparams(\tenvone, \potentialparams, \funcsig.\funcparameters, (\tenvone, \emptyfunc)) \typearrow \\ - (\tenvtwo, \declaredparams) \OrTypeError - \end{array} - }\\ - { - \begin{array}{r} - \argsasparams(\tenvtwo, \funcsig) \typearrow (\tenvthree, \argparams) \OrTypeError - \end{array} - }\\ - { - \begin{array}{rl} - \vparameters \eqdef & [(\id,\vt) \in \declaredparams: (\id, \langle\vt\rangle)]\ \concat \\ - & [(\id,\vt) \in \argparams: (\id, \langle\vt\rangle)] - \end{array} - }\\ - \annotateargs(\tenvthree, \tenvtwo, \funcsig, \argparams) \typearrow (\tenvfour, \vargs) \OrTypeError\\\\ - { - \begin{array}{r} - \annotatereturntype(\tenvfour, \tenvthree, \funcsig.\funcreturntype) \typearrow \\ - (\tenvfive, \vreturntype) \OrTypeError - \end{array} - }\\\\ - { - \begin{array}{rrcl} - \newfuncsig \eqdef \{ - & \funcname &:& \funcsig.\funcname,\\ - & \funcparameters &:& \vparameters,\\ - & \funcargs &:& \vargs,\\ - & \funcbody &:& \funcsig.\funcbody,\\ - & \funcreturntype &:& \vreturntype,\\ - & \funcsubprogramtype &:& \funcsig.\subprogramtype \\ - \} & && - \end{array} - } -}{ - \annotatefuncsig(\tenv, \funcsig) \typearrow (\overname{\tenvfive}{\newtenv}, \newfuncsig, \argparams) -} -\end{mathpar} - -\section{TypingRule.UseFuncSig \label{sec:TypingRule.UseFuncSig}} -\hypertarget{def-usefuncsig}{} -The function -\[ -\usefuncsig(\overname{\func}{\vf}) \aslto \overname{\pow{\identifier}}{\ids} -\] -returns the set of identifiers $\ids$ which the subprogram signature given -by $\vf$ depends on. - -\subsection{Prose} -Define $\ids$ as the union of applying $\usety$ to every type of an argument of $\vf$ -and applying $\usety$ to the \optional\ return type of $\vf$. - -\subsection{Formally} -\begin{mathpar} -\inferrule{}{ - \usefuncsig(\vf) \typearrow \overname{\bigcup_{(\Ignore, \vt) \in \vf.\funcargs}\usety(\vt) \cup \usety(\vf.\funcreturntype)}{\ids} -} -\end{mathpar} - -\section{TypingRule.GetUndeclaredDefining \label{sec:TypingRule.GetUndeclaredDefining}} -\hypertarget{def-getundeclareddefining}{} -The function -\[ -\getundeclareddefining(\overname{\staticenvs}{\tenv} \aslsep \overname{\func}{\funcsig}) -\aslto \overname{\pow{\identifier}}{\potentialparams} -\] -scans the list of types appearing in $\funcsig.\funcargs$ and in the return type -and returns the set of -identifiers that may be parameter-defining in $\tenv$. - -\subsection{Example} -In the following specification, the set of identifiers that may correspond -to parameters of the function \texttt{signature\_example} is $\{\texttt{A}\}$, -since \texttt{A} appears in the type \texttt{bits(A)} -of the argument \texttt{bv}. - -\VerbatimInput{\typingtests/TypingRule.AnnotateFuncSig.asl} - -\CodeSubsection{\GetUndeclaredDefiningBegin}{\GetUndeclaredDefiningEnd}{../Typing.ml} - -\subsection{Prose} -All of the following apply: -\begin{itemize} - \item define $\formaltypes$ to consist of the types associated with the list of arguments in $\funcsig$ - and the return type in $\funcsig$, if one exists; - \item scanning each type $\vt$ in $\formaltypes$ via $\scanforparams$ yields the set $\vparams_\vt$; - \item $\potentialparams$ is the union of $\vparams_\vt$ for each type $\vt$ in $\formaltypes$. -\end{itemize} - -\subsection{Formally} -\begin{mathpar} -\inferrule{ - { - \begin{array}{rcl} - \formaltypes &\eqdef& - [(\Ignore, \vt) \in \funcsig.\funcargs: \vt]\ \concat \\ - && \choice{\funcsig.\funcreturntype = \langle\retty\rangle}{[\retty]}{\emptylist} - \end{array} - }\\ - \vt\in\formaltypes: \scanforparams(\tenv, \vt) \typearrow \vparams_\vt -}{ - \getundeclareddefining(\tenv, \funcsig) \typearrow \overname{\bigcup_{\vt \in \tys} \vparams_\vt}{\potentialparams} -} -\end{mathpar} - -\section{TypingRule.ScanForParams \label{sec:TypingRule.ScanForParams}} -\hypertarget{def-scanforparams}{} -The function -\[ -\scanforparams(\overname{\staticenvs}{\tenv} \aslsep \overname{\ty}{\tty}) -\aslto \overname{\pow{\identifier}}{\potentialparams} -\] -scans a single type $\tty$ in $\tenv$ and returns the set of -identifiers that may be parameters in $\tenv$. - -\subsection{Example} -Consider the following specification: -\VerbatimInput{\typingtests/TypingRule.AnnotateFuncSig.asl} - -Scanning each type in the signature -of the function \texttt{signature\_example} yields the following results: -\begin{center} -\begin{tabular}{lll} -\textbf{Expression} & \textbf{Result} & \textbf{Reason}\\ -\hline -\texttt{bits(A)} & $\{\texttt{A}\}$ & \texttt{A} is a variable expression \\ -& & and \texttt{A} is not defined in the environment.\\ -\texttt{bits(W)} & $\emptyset$ & \texttt{W} is defined in the environment.\\ -\texttt{bits(A+B)} & $\emptyset$ & \texttt{A+B} is not a variable expression.\\ -\end{tabular} -\end{center} - -\subsection{Prose} -One of the following applies: -\begin{itemize} - \item All of the following apply (\textsc{tbits\_evar}): - \begin{itemize} - \item $\tty$ is a bitvector type over a variable expression for $\vx$, that is, \\ $\TBits(\EVar(\vx), \Ignore)$; - \item $\potentialparams$ is the singleton set consisting of $\vx$ if $\vx$ is not defined as a storage type in $\tenv$ - and the empty set, otherwise. - \end{itemize} - - \item All of the following apply (\textsc{tbits\_other}): - \begin{itemize} - \item $\tty$ is a bitvector type where the bitwidth expression is not a variable expression; - \item $\potentialparams$ is the empty set. - \end{itemize} - - \item All of the following apply (\textsc{ttuple}): - \begin{itemize} - \item $\tty$ is a tuple type over a list of types $\tys$; - \item obtaining the set of potential parameters for each type $\vt$ of $\tys$ in $\tenv$ yields $\vparams_\vt$; - \item $\potentialparams$ is the union of sets $\vparams_\vt$, for each type $\vt$ of $\tys$. - \end{itemize} - - \item All of the following apply (\textsc{other}): - \begin{itemize} - \item $\tty$ is neither a bitvector type or a tuple type; - \item $\potentialparams$ is the empty set. - \end{itemize} -\end{itemize} - -\begin{mathpar} - \inferrule[tbits\_evar]{ - \isundefined(\tenv, \vx) \typearrow \vb\\ - \potentialparams \eqdef \choice{\vb}{\{\vx\}}{\emptyset} - }{ - \scanforparams(\tenv, \overname{\TBits(\EVar(\vx), \Ignore)}{\tty}) \typearrow \potentialparams - } - \and - \inferrule[tbits\_other]{ - \astlabel(\ve) \neq \EVar - }{ - \scanforparams(\tenv, \overname{\TBits(\ve, \Ignore)}{\tty}) \typearrow \overname{\emptyset}{\potentialparams} - } - \and - \inferrule[ttuple]{ - \vt \in \tys: \scanforparams(\tenv, \vt) \typearrow \vparams_\vt - }{ - \scanforparams(\tenv, \overname{\TTuple(\tys)}{\tty}) \typearrow \overname{\bigcup_{\vt \in \tys} \vparams_\vt}{\potentialparams} - } - \and - \inferrule[other]{ - \astlabel(\tty) \not\in \{\TBits, \TTuple\} - }{ - \scanforparams(\tenv, \tty) \typearrow \overname{\emptyset}{\potentialparams} - } - \end{mathpar} - -\section{TypingRule.AnnotateParams \label{sec:TypingRule.AnnotateParams}} -\hypertarget{def-annotateparams}{} -The function -\[ -\begin{array}{r} -\annotateparams( - \overname{\staticenvs}{\tenv} \aslsep - \overname{\pow{\identifier}}{\potentialparams} \aslsep - \overname{(\identifier \times \langle\ty\rangle)^*}{\vparameters} \aslsep\ - (\overname{\staticenvs}{\tenvonep} \times \overname{\identifier\rightarrow\ty}{\acc}) -) \aslto \\ -(\overname{\staticenvs}{\newtenv} \times \overname{\identifier\rightarrow\ty}{\declaredparams}) -\cup \overname{\TTypeError}{\TypeErrorConfig} -\end{array} -\] -scans the list of explicitly defined parameters $\vparameters$ with respect to the set of potential -parameters $\potentialparams$ in $\tenv$ and then updates a pair -consisting of an updated environment $\tenvonep$, which accumulates local storage declarations -for the parameters, and a function $\acc$, which maps identifiers corresponding to parameters -to their associated types. -The updated pair is given in $\newtenv$ and $\declaredparams$. -\ProseOtherwiseTypeError - -\subsection{Example} -In the following specification, the list of explicitly defined parameters -of the function \texttt{signature\_example} is $\{\texttt{A}\}$. -Therefore, $\declaredparams$ binds \texttt{A} to the type \verb|integer{A}| -and $\newtenv$ effectively reflects an added declaration \verb|let A: integer{A}|. - -\VerbatimInput{\typingtests/TypingRule.AnnotateFuncSig.asl} - -\subsection{Prose} -One of the following applies: -\begin{itemize} - \item All of the following apply (\textsc{empty}): - \begin{itemize} - \item $\vparameters$ is the empty list; - \item $\newtenv$ is $\tenvonep$; - \item $\declaredparams$ is $\acc$. - \end{itemize} - - \item All of the following apply (\textsc{non\_empty}): - \begin{itemize} - \item $\vparameters$ is a list with $(\vx, \tyopt)$ as its \head\ and $\vparametersone$ as its \tail; - \item applying $\annotateoneparam$ to the parameter $(\vx, \tyopt)$ in $\tenvone$ with \\ - $\potentialparams$ and the pair $(\tenvonep, \acc)$ - yields the pair \\ - $(\tenvonepp, \accp)$\ProseOrTypeError; - \item annotating the parameter list $\vparametersone$ in $\tenvone$ with $\potentialparams$, starting with the pair - $(\tenvonepp, \accp)$ yields the pair \\ $(\newtenv, \declaredparams)$. - \end{itemize} -\end{itemize} - -\subsection{Formally} -\begin{mathpar} -\inferrule[empty]{}{ - { - \begin{array}{r} - \annotateparams(\tenvone, \potentialparams, \overname{\emptylist}{\vparameters}, (\tenvonep, \acc)) \typearrow \\ - (\overname{\tenvonep}{\newtenv}, \overname{\acc}{\declaredparams}) - \end{array} - } -} -\and -\inferrule[non\_empty]{ - \vparameters \eqname [(\vx,\tyopt)]\concat\vparametersone\\ - { - \begin{array}{r} - \annotateoneparam(\tenvone, \potentialparams, (\vx,\tyopt), (\tenvonep, \acc)) \typearrow \\ (\tenvonepp, \accp) \OrTypeError - \end{array} - }\\\\ - { - \begin{array}{r} - \annotateparams(\tenvone, \potentialparams, \vparametersone, (\tenvonepp, \accp)) \typearrow \\ (\newtenv, \declaredparams) \OrTypeError -\end{array} -}\\\\ -}{ - { - \begin{array}{r} - \annotateparams(\tenvone, \potentialparams, \vparameters, (\tenvonep, \acc)) \typearrow \\ - (\newtenv, \declaredparams) - \end{array} -} -} -\end{mathpar} - -\section{TypingRule.AnnotateOneParam \label{sec:TypingRule.AnnotateOneParam}} -The function -\hypertarget{def-annotateoneparam}{} -\[ -\begin{array}{r} -\annotateoneparam( - \overname{\staticenvs}{\tenv} \aslsep - \overname{\pow{\identifier}}{\potentialparams} \aslsep - (\overname{\identifier}{\vx} \times \overname{\langle\ty\rangle}{\tyopt}) \aslsep - (\overname{\staticenvs}{\tenvonep} \times \overname{\identifier\rightarrow\ty}{\acc}) -) \\ \aslto -(\overname{\staticenvs}{\newtenv} \times \overname{\identifier\rightarrow\ty}{\declaredparams}) -\cup \overname{\TTypeError}{\TypeErrorConfig} -\end{array} -\] -annotates the explicitly defined parameter given by $\vx$ and the \optional\ type $\tyoptp$ -with respect to the set of potential -parameters $\potentialparams$ in $\tenv$ and then updates a pair -consisting of an updated environment $\tenvonep$, which accumulates local storage declarations -for the parameters, and a function $\acc$, which maps identifiers corresponding to parameters -to their associated types. -The updated pair is given in $\newtenv$ and $\declaredparams$. -\ProseOtherwiseTypeError - -\subsection{Prose} -All of the following apply: -\begin{itemize} - \item checking that $\vx$ is not defined as a variable in $\tenvonep$ yields $\True$\ProseOrTypeError; - \item checking whether $\vx$ is included in the set $\potentialparams$ yields $\True$ or a type error - indicating that each parameter must have a defining argument, thus short-circuiting the entire rule; - \item One of the following applies: - \begin{itemize} - \item All of the following apply (\textsc{type\_parameterized}): - \begin{itemize} - \item $\tyopt$ is either $\None$ or a \parameterizedintegertype; - \item $\vt$ is defined as the \parameterizedintegertype\ for the identifier $\vx$. - \end{itemize} - - \item All of the following apply (\textsc{type\_annotated}): - \begin{itemize} - \item $\tyopt$ is the type $\vtone$, which is not the unconstrained integer type; - \item annotating $\vtone$ in $\tenvone$ yields $\vt$\ProseOrTypeError. - \end{itemize} - \end{itemize} - \item checking that $\vt$ is a constrained integer in $\tenvone$ via $\checkconstrainedinteger$ - yields $\True$\ProseOrTypeError; - \item adding the local storage element given by the identifier $\vx$, type $\vt$, and local declaration keyword - $\LDKLet$ in $\tenvonep$ yields $\newtenv$; - \item $\declaredparams$ is $\acc$ updated by the binding of $\vx$ to $\vt$. -\end{itemize} - -\subsection{Formally} -\begin{mathpar} -\inferrule[type\_parameterized]{ - \checkvarnotinenv{\tenvonep, \vx} \typearrow \True \OrTypeError\\\\ - \checktrans{\vx \in \potentialparams}{\ParameterWithoutDecl} \checktransarrow \True \OrTypeError\\\\ - (\tyopt = \None \lor \tyopt = \langle \unconstrainedinteger\rangle) \\ - \vt \eqdef \TInt(\parameterized(\vx))\\ - \checkconstrainedinteger(\tenvone, \vt) \typearrow \True \OrTypeError\\\\ - \addlocal(\tenvonep, \vx, \vt, \LDKLet) \typearrow \newtenv\\ - \declaredparams \eqdef \acc[\vx \mapsto \vt] -}{ - { - \begin{array}{r} - \annotateoneparam(\tenvone, \potentialparams, (\vx, \tyopt), (\tenvonep, \acc)) \typearrow \\ (\newtenv, \declaredparams) - \end{array} - } -} -\and -\inferrule[type\_annotated]{ - \checkvarnotinenv{\tenvonep, \vx} \typearrow \True \OrTypeError\\\\ - \checktrans{\vx \in \potentialparams}{\ParameterWithoutDecl} \checktransarrow \True \OrTypeError\\\\ - \vtone \neq \unconstrainedinteger\\ - \annotatetype{\False, \tenvone, \vtone} \typearrow \vt \OrTypeError\\\\ - \checkconstrainedinteger(\tenvone, \vt) \typearrow \True \OrTypeError\\\\ - \addlocal(\tenvonep, \vx, \vt, \LDKLet) \typearrow \newtenv\\ - \declaredparams \eqdef \acc[\vx \mapsto \vt] -}{ - { - \begin{array}{r} - \annotateoneparam(\tenvone, \potentialparams, (\vx, \overname{\langle\vtone\rangle}{\tyopt}), (\tenvonep, \acc)) \typearrow \\ (\newtenv, \declaredparams) - \end{array} - } -} - \end{mathpar} - -\section{TypingRule.ArgsAsParams \label{sec:TypingRule.ArgsAsParams}} -\hypertarget{def-argsasparams}{} -The function -\[ -\begin{array}{r} -\argsasparams( - \overname{\staticenvs}{\tenvone} \aslsep - \overname{\staticenvs}{\tenvtwo} \aslsep - \overname{\func}{\funcsig} \aslsep - \overname{\identifier\rightarrow\ty}{\declaredparams} - ) -\aslto \\ -(\overname{\staticenvs}{\newtenv} \times \overname{\identifier\rightarrow\ty}{\argparams}) -\cup \overname{\TTypeError}{\TypeErrorConfig} -\end{array} -\] -scans the list of arguments in $\func$ ($\func.\funcargs$) to find the ones that serve as -implicit parameters in $\tenvone$ and are not already included in the domain of $\declaredparams$. -The found parameters are added as local declarations to $\tenvtwo$, resulting in $\newtenv$, -and are used to update $\argparams$. -\ProseOtherwiseTypeError - -\subsection{Prose} -One of the following applies: -\begin{itemize} - \item All of the following apply (\textsc{empty}): - \begin{itemize} - \item the subprogram defined by $\funcsig$ has an empty list of arguments; - \item $\newtenv$ is $\tenvtwo$; - \item $\argparams$ is the empty list. - \end{itemize} - - \item All of the following apply (\textsc{non\_empty}): - \begin{itemize} - \item the subprogram defined by $\funcsig$ has arguments $\varg_{1..k}$; - \item obtaining the identifiers that can serve as parameters in the types of the formal arguments of $\funcsig$ - and in its return type yields $\vusedone$; - \item the set $\vused$ contains all identifiers $\vs$ from $\vusedone$ that are undefined in $\tenvone$ and are not - bound in $\declaredparams$; - \item the following premises define the sequences $\argparams_{1..k}$ and $\tenvtwo_{0..k}$ as follows; - \item $\argparams_1$ is $\declaredparams$; - \item $\tenvtwo_0$ is $\tenvtwo$; - \item for $\vi=1..k$, annotating the argument $\varg_\vi$ in $\tenvtwo$ with $\vused$ and the static environment $\tenvtwo_{\vi-1}$ - via $\argasparam$ yields $\tenvtwo_\vi$ and $\argparams_\vi$\ProseOrTypeError; - \item $\newtenv$ is $\tenvtwo_k$; - \item $\argparams$ is $\argparams_k$. - \end{itemize} -\end{itemize} - -\subsection{Example} -In the following specification, the argument \texttt{B} -of the function \texttt{signature\_example} is an implicit parameter -as it appears in the type \texttt{bits(A+B)} -(both for the argument \texttt{bv3} and as the return type) -and it is not listed as an explicit parameter. -Therefore, $\newtenv$ will effectively contain the declaration \verb|let B: integer{B}|. - -\VerbatimInput{\typingtests/TypingRule.AnnotateFuncSig.asl} - -\subsection{Formally} -\begin{mathpar} -\inferrule[empty]{ - \funcsig.\funcargs = \emptylist -}{ - { - \begin{array}{r} - \argsasparams(\tenvone, \tenvtwo, \funcsig, \declaredparams) \typearrow \\ - (\overname{\tenvtwo}{\newtenv}, \overname{\emptylist}{\argparams}) - \end{array} - } -} -\end{mathpar} - -\begin{mathpar} -\inferrule[non\_empty]{ - \funcsig.\funcargs \eqname \varg_{1..k}\\ - \usefuncsig(\funcsig) \typearrow \vusedone\\ - \vs\in\vusedone : \isundefined(\tenvone, \vs) \typearrow \vb_\vs\\ - \vused \eqdef \setcomprehension{\vs\in\vusedone \land \vb_\vs \land \declaredparams(\vs) = \bot}{\vs}\\ - \argparams_1 \eqdef \declaredparams\\ - \tenvtwo_0 \eqdef \tenvtwo\\ - \vi=1..k: \argasparam(\tenvtwo, \vused, \varg_\vi,\tenvtwo_{\vi-1}) \typearrow (\tenvtwo_\vi, \argparams_\vi) \OrTypeError -}{ - \argsasparams(\tenvone, \tenvtwo, \funcsig, \declaredparams) \typearrow - (\overname{\tenvtwo_k}{\newtenv}, \overname{\argparams_k}{\argparams}) -} -\end{mathpar} - -\section{TypingRule.ArgAsParam \label{sec:TypingRule.ArgAsParam}} -\hypertarget{def-argasparam}{} -The function -\[ -\argasparam\left( - \begin{array}{c} - \overname{\staticenvs}{\tenvtwo} \aslsep\\ - \overname{\pow{\identifier}}{\vused} \aslsep\\ - (\overname{\identifier}{\vx} \times \overname{\ty}{\tty}) \aslsep\\ - (\overname{\staticenvs}{\tenvtwop} \times \overname{\identifier\rightarrow\ty}{\acc}) - \end{array} - \right) -\aslto -(\overname{\staticenvs}{\newtenv} \times \overname{\identifier\rightarrow\ty}{\accp}) -\cup \overname{\TTypeError}{\TypeErrorConfig} -\] -checks whether the argument given by $\vx$ and type $\tty$ is an implicit parameter -by checking whether it appears in $\vused$ and not in $\acc$. -If it is identified as an implicit parameter, it is used to update $\tenvtwop$ to yield $\newtenv$ -and to update $\acc$ to yield $\accp$. -\ProseOtherwiseTypeError - -\subsection{Prose} -One of the following applies: -\begin{itemize} - \item All of the following apply (\textsc{not\_used}): - \begin{itemize} - \item $\vx$ is not a member of $\vused$; - \item $\newtenv$ is $\tenvtwop$; - \item $\accp$ is $\acc$. - \end{itemize} - - \item All of the following apply (\textsc{used}): - \begin{itemize} - \item $\vx$ is a member of $\vused$; - \item checking that $\vx$ is not declared in $\tenvtwop$ yields $\True$\ProseOrTypeError; - \item annotating $\tty$ with identifier $\vx$ as a potential parameter type in $\tenvtwo$, - which is an environment to which all explicit parameters have been added but implicit parameters were not added to, - via $\annotateparamtype$ yields $\vt$\ProseOrTypeError; - \item checking whether $\vt$ is a constrained integer type in $\tenvtwo$ yields $\True$\ProseOrTypeError; - \item adding $\vx$ as a local storage element to $\tenvtwop$ with type $\vt$ and local declaration keyword $\LDKLet$ yields - $\newtenv$; - \item $\accp$ is $\acc$ updated by binding $\vx$ to $\vt$. - \end{itemize} -\end{itemize} - -\subsection{Formally} -\begin{mathpar} -\inferrule[not\_used]{ - \vx \not\in \vused -}{ - \argasparam(\tenvtwo, \vused, (\vx, \tty), (\tenvtwop, \acc)) - \typearrow (\overname{\tenvtwop}{\newtenv}, \overname{\acc}{\accp}) -} -\and -\inferrule[used]{ - \vx \in \vused\\ - \checkvarnotinenv{\tenvtwop, \vx} \typearrow \True \OrTypeError\\\\ - \annotateparamtype(\tenvtwo, \tty, \vx) \typearrow \vt \OrTypeError\\\\ - \checkconstrainedinteger(\tenvtwo, \vt) \typearrow \True \OrTypeError\\\\ - \addlocal(\tenvtwop, \vx, \vt, \LDKLet) \typearrow \newtenv\\ - \accp \eqdef \acc[\vx\mapsto\vt] -}{ - \argasparam(\tenvtwo, \vused, (\vx, \tty), (\tenvtwop, \acc)) - \typearrow (\newtenv, \accp) -} -\end{mathpar} - -\section{TypingRule.AnnotateParamType \label{sec:TypingRule.AnnotateParamType}} -\hypertarget{def-annotateparamtype}{} -The function -\[ - \annotateparamtype(\overname{\staticenvs}{\tenv} \aslsep \overname{\ty}{\tty} \aslsep \overname{\identifier}{\vx}) - \typearrow \overname{\ty}{\newty} -\] -annotates the type $\tty$ in $\tenv$, considering it as a subprogram parameter with identifier $\vx$, -yielding the type $\newtenv$. -It is assumed that $\tenv$ is an environment to which all explicitly defined parameters of the subprogram -in context were added to, but the implicitly defined parameters were not added to. -\ProseOtherwiseTypeError - -\subsection{Prose} -One of the following applies: -\begin{itemize} - \item All of the following apply (\textsc{tint\_unconstrained}): - \begin{itemize} - \item $\tty$ is the unconstrained integer type; - \item $\newty$ is the \parameterizedintegertype\ for the identifier $\vx$. - \end{itemize} - - \item All of the following apply (\textsc{other}): - \begin{itemize} - \item $\tty$ is not the unconstrained integer type; - \item annotating the type $\tty$ in $\tenv$ yields $\newty$\ProseOrTypeError. - \end{itemize} -\end{itemize} - -\begin{mathpar} -\inferrule[tint\_unconstrained]{} -{ - \annotateparamtype(\tenv, \overname{\unconstrainedinteger}{\tty}, \vx) \typearrow \overname{\TInt(\parameterized(\vx))}{\newty} -} -\end{mathpar} - -\begin{mathpar} -\inferrule[other]{ - \tty \neq \unconstrainedinteger\\ - \annotatetype{\tenv, \tty} \typearrow \newty \OrTypeError -}{ - \annotateparamtype(\tenv, \tty, \vx) \typearrow \newty -} -\end{mathpar} - -\section{TypingRule.AnnotateArgs \label{sec:TypingRule.AnnotateArgs}} -\hypertarget{def-annotateargs}{} -The function -\[ -\begin{array}{r} -\annotateargs( - \overname{\staticenvs}{\tenvtwo} \aslsep - \overname{\staticenvs}{\tenvthree} \aslsep - \overname{\func}{\funcsig} \aslsep - \overname{\identifier\rightarrow\ty}{\argparams} -) -\aslto \\ -(\overname{\staticenvs}{\newtenv} \times \overname{(\identifier\times\ty)^*}{\vnewargs}) -\cup \overname{\TTypeError}{\TypeErrorConfig} -\end{array} -\] -annotates the arguments listed in $\funcsig$ in the context of -of $\argparams$, which binds parameters to their types, -and two static environments: -$\tenvtwo$ --- the environment to which only explicit parameters were added, and -$\tenvthree$ --- the environment to which all parameters (explicit and implicit) were added. -The result is the environment $\newtenv$ where all arguments have been declared and -the annotated list of arguments $\vnewargs$. -\ProseOtherwiseTypeError - -\subsection{Prose} -One of the following applies: -\begin{itemize} - \item All of the following apply (\textsc{no\_args}): - \begin{itemize} - \item the function defined by $\funcsig$ has an empty list of arguments; - \item $\newtenv$ is $\tenvthree$; - \item $\vnewargs$ is the empty list. - \end{itemize} - - \item All of the following apply (\textsc{some\_args}): - \begin{itemize} - \item the function defined by $\funcsig$ has arguments $\varg_{1..k}$; - \item the following premises define the sequence of static environments $\tenvthree_{0..k}$ and - list of typed identifiers $\vnewarg_{1..k}$; - \item $\tenvthree_0$ is $\tenvthree$; - \item annotating the argument $\varg_\vi$ in the context of $\tenvtwo$, $\tenvthree$, $\argparams$, - and $\tenvthree_{\vi-1}$ via $\annotateonearg$ yields $(\tenvthree_\vi, \vnewarg_\vi)$\ProseOrTypeError; - \item $\newtenv$ is $\tenvthree_k$; - \item $\vnewargs$ is the list $\vnewarg_{1..k}$. - \end{itemize} -\end{itemize} - -\subsection{Example} -In the following specification, the annotated arguments are -\texttt{bv}, \texttt{bv2}, \texttt{bv3}, and \texttt{C}. -The argument \texttt{B} is not annotated as an argument since it is classified -and annotated as a parameter. - -\VerbatimInput{\typingtests/TypingRule.AnnotateFuncSig.asl} - -\subsection{Formally} -\begin{mathpar} -\inferrule[no\_args]{ - \funcsig.\funcargs = \emptylist -}{ - \annotateargs(\tenvtwo, \tenvthree, \funcsig, \argparams) \typearrow (\overname{\tenvthree}{\newtenv}, \overname{\emptylist}{\vnewargs}) -} -\and -\inferrule[some\_args]{ - \funcsig.\funcargs \eqname \varg_{1..k}\\ - \tenvthree_{0} \eqdef \tenvthree\\ - { - \begin{array}{r} - \vi=1..k: \annotateonearg(\tenvtwo, \tenvthree, \argparams, (\tenvthree_{\vi-1}, \varg_{\vi})) \typearrow \\ - (\tenvthree_{\vi}, \vnewarg_\vi) \OrTypeError - \end{array} - }\\ - \vnewargs \eqdef [i=1..k: \vnewarg_{\vi}] -}{ - \annotateargs(\tenvtwo, \tenvthree, \funcsig, \argparams) \typearrow - (\overname{\tenvthree_k}{\newtenv}, \vnewargs) -} -\end{mathpar} - -\section{TypingRule.AnnotateOneArg \label{sec:TypingRule.AnnotateOneArg}} -\hypertarget{def-annotateonearg}{} -The function -\[ -\begin{array}{r} -\annotateonearg( - \overname{\staticenvs}{\tenvtwo} \aslsep - \overname{\staticenvs}{\tenvthree} \aslsep - \overname{\identifier\rightarrow\ty}{\argparams} \aslsep - (\overname{\staticenvs}{\tenvthreep} \times (\overname{\vx}{\identifier} \times \overname{\ty}{\tty})) -) \aslto \\ -(\overname{\staticenvs}{\newtenv} \times\ (\overname{\vx}{\identifier} \times \overname{\ty}{\ttyp})) -\cup \overname{\TTypeError}{\TypeErrorConfig} -\end{array} -\] -annotates the argument $\vx$ of type $\tty$ in the context of $\argparams$, which binds parameters to their types, -and the following static environments: -$\tenvtwo$ --- the environment to which only explicit parameters were added, -$\tenvthree$ --- $\tenvtwo$ with the addition of implicit parameters, and -$\tenvthreep$ --- same as $\tenvthree$ but updated with previously annotated arguments. -The result is the updated environment $\newtenv$ with the added declaration for the current argument -and the annotated argument, which has the same identifier $\vx$ and the annotated type $\vtp$. -\ProseOtherwiseTypeError - -\subsection{Prose} -One of the following applies: -\begin{itemize} - \item All of the following apply (\textsc{param}): - \begin{itemize} - \item $\vx$ is not bound in $\argparams$; - \item annotating the type $\tty$ in $\tenvtwo$ yields $\ttyp$; - \item $\newtenv$ is $\tenvthreep$. - \end{itemize} - - \item All of the following apply (\textsc{not\_param}): - \begin{itemize} - \item $\vx$ is bound in $\argparams$; - \item checking that $\vx$ is not defined in $\tenvthreep$ yields $\True$\ProseOrTypeError; - \item annotating the type $\tty$ in $\tenvthree$ yields $\ttyp$; - \item adding a local storage element $\vx$ with type $\ttyp$ and local declaration keyword $\LDKLet$ yields - $\newtenv$. - \end{itemize} -\end{itemize} - -\subsection{Formally} -\begin{mathpar} -\inferrule[param]{ - \argparams(\vx) \neq \bot\\ - \annotatetype{\tenvtwo, \tty} \typearrow \ttyp \OrTypeError -}{ - \annotateonearg(\tenvtwo, \tenvthree, \argparams, (\tenvthreep, (\vx, \tty))) - \typearrow (\overname{\tenvthreep}{\newtenv}, (\vx, \ttyp)) -} -\end{mathpar} - -\begin{mathpar} -\inferrule[not\_param]{ - \argparams(\vx) = \bot\\ - \checkvarnotinenv{\tenvthreep, \vx} \typearrow \True \OrTypeError\\\\ - \annotatetype{\tenvthree, \tty} \typearrow \ttyp \OrTypeError\\\\ - \addlocal(\tenvthreep, \vx, \ttyp, \LDKLet) \typearrow \newtenv -}{ - { - \begin{array}{r} - \annotateonearg(\tenvtwo, \tenvthree, \argparams, (\tenvthreep, (\vx, \tty))) - \typearrow \\ (\newtenv, (\vx, \ttyp)) - \end{array} - } -} -\end{mathpar} - -\section{TypingRule.AnnotateReturnType \label{sec:TypingRule.AnnotateReturnType}} -\hypertarget{def-annotatereturntype}{} -The function -\[ -\annotatereturntype( - \overname{\staticenvs}{\tenvthree} \aslsep - \overname{\staticenvs}{\tenvfour} \aslsep - \overname{\langle\ty\rangle}{\returntype} -) \aslto -(\overname{\staticenvs}{\newtenv} \times \overname{\ty}{\newreturntype}) -\cup \overname{\TTypeError}{\TypeErrorConfig} -\] -annotates the \optional\ return type $\returntype$ in the context of the static environment -$\tenvthree$ where all parameters have been added to, and -$\tenvfour$ where all parameters and arguments have been added to. -The result is the static environment $\newtenv$, which is $\tenvfour$ with the -annotated return type and the \optional\ annotated return type $\newreturntype$. -\ProseOtherwiseTypeError - -\subsection{Prose} -One of the following applies: -\begin{itemize} - \item All of the following apply (\textsc{no\_return\_type}): - \begin{itemize} - \item $\returntype$ is $\None$; - \item $\newtenv$ is $\tenvfour$; - \item $\newreturntype$ is $\None$. - \end{itemize} - - \item All of the following apply (\textsc{has\_return\_type}): - \begin{itemize} - \item $\returntype$ is $\langle\tty\rangle$; - \item annotating $\tty$ in $\tenvthree$ yields $\ttyp$\ProseOrTypeError; - \item $\newreturntype$ is $\langle\ttyp\rangle$; - \item $\newtenv$ is $\tenvfour$ with its local environment updated by binding its \\ $\funcreturntype$ field - to $\newreturntype$. - \end{itemize} -\end{itemize} - -\subsection{Formally} -\begin{mathpar} -\inferrule[no\_return\_type]{} -{ - \annotatereturntype(\tenvthree, \tenvfour, \overname{\None}{\returntype}) \typearrow - (\overname{\tenvfour}{\newtenv}, \overname{\None}{\newreturntype}) -} -\and -\inferrule[has\_return\_type]{ - \annotatetype{\tenvthree, \tty} \typearrow \ttyp \OrTypeError\\\\ - \newreturntype \eqdef \langle\ttyp\rangle\\ - \newtenv \eqdef (G^\tenvfour, L^\tenvfour[\funcreturntype\mapsto\newreturntype]) -}{ - \annotatereturntype(\tenvthree, \tenvfour, \overname{\langle\tty\rangle}{\returntype}) \typearrow - (\newtenv, \newreturntype) -} -\end{mathpar} - -\section{TypingRule.DeclareOneFunc \label{sec:TypingRule.DeclareOneFunc}} -\hypertarget{def-declareonefunc}{} -The function -\[ - \declareonefunc(\overname{\staticenvs}{\tenv}, \overname{\func}{\funcsig}) - \aslto (\overname{\staticenvs}{\newtenv} \times \overname{\func}{\newfuncsig}) - \cup \overname{\TTypeError}{\TypeErrorConfig} -\] -checks that a subprogram defined by $\funcsig$ can be added to the static environment $\tenv$, -resulting in an annotated function definition $\newfuncdef$ and new static environment $\newtenv$. -\ProseOtherwiseTypeError - -\subsection{Prose} -All of the following apply: -\begin{itemize} - \item $\funcsig$ has name $\name$, arguments $\vargs$, and type $\subprogramtype$, that is, - \[ - \begin{array}{rrcl} - \funcsig \eqdef \{ - & \funcname &:& \name,\\ - & \funcparameters &:& \vp,\\ - & \funcargs &:& \vargs,\\ - & \funcbody &:& \SBASL(\bd),\\ - & \funcreturntype &:& \vt,\\ - & \funcsubprogramtype &:& \subprogramtype \\ - \} & ; && - \end{array} - \] - \item adding a new subprogram with $\name$, $\vargs$, and $\subprogramtype$ to $\tenv$ yields the new - environment $\tenvone$ and new name $\namep$\ProseOrTypeError; - \item checking that $\namep$ is not already declared in the global environment of $\tenvone$ - yields $\True$\ProseOrTypeError; - \item ensuring that each setter has a getter given $\funcsig$ in $\tenv$ yields $\True$\ProseOrTypeError; - \item $\funcsigone$ is $\funcsig$ with $\name$ substituted by $\nameone$; - \item adding a subprogram with name $\namep$ and definition $\funcsigone$ to $\tenvone$ yields $\newtenv$\ProseOrTypeError. -\end{itemize} - -\isempty{\subsection{Example}} - -\CodeSubsection{\DeclareOneFuncBegin}{\DeclareOneFuncEnd}{../Typing.ml} - -\subsection{Formally} -\begin{mathpar} -\inferrule{ - { - \begin{array}{rrcl} - \funcsig \eqdef \{ - & \funcname &:& \name,\\ - & \funcparameters &:& \vp,\\ - & \funcargs &:& \vargs,\\ - & \funcbody &:& \SBASL(\bd),\\ - & \funcreturntype &:& \vt,\\ - & \funcsubprogramtype &:& \subprogramtype \\ - \} &&& - \end{array} - }\\ - \addnewfunc(\tenv, \name, \vargs, \subprogramtype) \typearrow - (\tenvone, \namep) \OrTypeError\\\\ - \checkvarnotingenv{\tenvone, \namep} \typearrow \True \OrTypeError\\\\ - \checksetterhasgetter(\tenvone, \funcsig) \typearrow \True \OrTypeError\\\\ - { - \begin{array}{rrcl} - \newfuncsig \eqdef \{ - & \funcname &:& \namep,\\ - & \funcparameters &:& \vp,\\ - & \funcargs &:& \vargs,\\ - & \funcbody &:& \SBASL(\bd),\\ - & \funcreturntype &:& \vt,\\ - & \funcsubprogramtype &:& \subprogramtype \\ - \} &&& - \end{array} - }\\ - \addsubprogram(\tenvone, \namep, \funcsigone) \typearrow \newtenv \OrTypeError -}{ - \declareonefunc(\tenv, \funcsig) \typearrow (\newtenv, \newfuncsig) -} -\end{mathpar} - -\isempty{\subsection{Comments}} -\lrmcomment{This relates to \identi{HJRD}, \identd{BTBR}, \identi{FSFQ}, \identi{PFGQ}, and \identr{PGFC}.} - -\section{TypingRule.SubprogramClash \label{sec:TypingRule.SubprogramClash}} -\hypertarget{def-subprogramclash}{} -The function -\[ - \subprogramclash( - \overname{\staticenvs}{\tenv} \aslsep - \overname{\Strings}{\name} \aslsep - \overname{\subprogramtype}{\subpgmtype} \aslsep - \overname{\ty^*}{\formaltypes} - ) - \aslto - \overname{\Bool}{\vb} \cup \overname{\TTypeError}{\TypeErrorConfig} -\] -checks whether the unique subprogram associated with $\name$ -clashes with another subprogram -that has subprogram type $\subpgmtype$ and list of formal types $\formaltypes$, -yielding a Boolean value in $\vb$. -\ProseOtherwiseTypeError - -The function is only defined when there exists a binding for $\name$ in the -$\subprograms$ map of $\tenv$. - -\subsection{Prose} -All of the following apply: -\begin{itemize} - \item the subprogram type associated with the unique subprogram named by $\name$ is $\namesubpgmtype$; - \item applying $\subprogramtypesclash$ to $\namesubpgmtype$ and $\subpgmtype$ yields \\ - $\True$\ProseTerminateAs{\False} - (that is, if both $\namesubpgmtype$ and $\subpgmtype$ are $\STGetter$ or both are $\STSetter$ then the - subprogram types are considered to be non-clashing and the entire rule short-circuits to $\False$); - \item $\nameargs$ is the list of pairs of types and identifiers associated with the function definition - of $\name$ in $\tenv$; - \item determining whether there is an argument clash between $\formaltypes$ and \\ - $\nameformals$ in $\tenv$ yields $\vb$\ProseOrTypeError. -\end{itemize} - -\isempty{\subsection{Example}} - -\subsection{Formally} -\hypertarget{def-subprogramtypeclash}{} -We first introduce the helper predicate -\[ - \subprogramtypesclash( - \overname{\subprogramtype}{\subpgmtypeone} \aslsep - \overname{\subprogramtype}{\subpgmtypetwo} - ) \aslto \overname{\Bool}{\vb} -\] -which defines whether two subprogram types are considered to be clashing: -\begin{mathpar} -\inferrule{ - \vbone \eqdef - { - \begin{array}{l} - (\subpgmtypeone=\STGetter \land \subpgmtypetwo=\STSetter)\ \lor\\ - (\subpgmtypeone=\STSetter \land \subpgmtypetwo=\STGetter) - \end{array} - }\\\\ - \vb \eqdef \neg\vbone -}{ - \subprogramtypesclash(\subpgmtypeone, \subpgmtypetwo) \typearrow \vb -} -\end{mathpar} - -\begin{mathpar} -\inferrule{ - \namesubpgmtype \eqdef G^\tenv.\subprograms(\name).\subprogramtype\\ - \subprogramtypesclash(\namesubpgmtype, \subpgmtype) \typearrow \True \terminateas \False\\ - \nameargs \eqdef G^\tenv.\subprograms(\name).\funcargs\\ - \hasargclash(\formaltypes, \nameargs) \typearrow \vb -}{ - \subprogramclash(\tenv, \namep, \subpgmtype, \formaltypes) \typearrow \vb -} -\end{mathpar} - -\isempty{\subsection{Comments}} -\lrmcomment{This is related to \identd{BTBR}, \identi{FSFQ}, \identi{PFGQ}.} - -\section{TypingRule.AddNewFunc \label{sec:TypingRule.AddNewFunc}} -\hypertarget{def-addnewfunc}{} -The function -\[ - \begin{array}{rl} - \addnewfunc( - \overname{\staticenvs}{\tenv} \aslsep - \overname{\identifier}{\name} \aslsep - \overname{\typedidentifier^*}{\formals} \aslsep - \overname{\subprogramtype}{\subpgmtype}) - & \aslto\\ - (\overname{\staticenvs}{\newtenv} \times \overname{\Strings}{\newname}) - \cup \overname{\TTypeError}{\TypeErrorConfig} & - \end{array} -\] -ensures that the subprogram given by the identifier $\name$, list of formals $\formals$, -and subprogram type $\subpgmtype$ has a unique name among all the potential subprograms -that overload $\name$. -The result is the unique subprogram identifier $\newname$, which is used to distinguish it in the set -of overloaded subprograms (that is, other subprograms that share the same name) -and the environment $\newtenv$, which is updated with $\newname$. -\ProseOtherwiseTypeError - -\subsection{Prose} -One of the following applies: -\begin{itemize} - \item All of the following apply (\textsc{first\_name}): - \begin{itemize} - \item the $\subprogramrenamings$ map in the global environment of $\tenv$ does not have a binding for $\name$; - \item $\newtenv$ is $\tenv$ with the $\subprogramrenamings$ updated by binding $\name$ to the singleton set containing - $\name$. - \end{itemize} - - \item All of the following apply (\textsc{name\_exists}): - \begin{itemize} - \item the $\subprogramrenamings$ map in the global environment of $\tenv$ binds $\name$ to the set of strings $\othernames$; - \item $\newname$ is the unique name that will be associated with the subprogram given by the identifier $\name$, list of formals $\formals$, - and subprogram type $\subpgmtype$. It is constructed by concatenating a hyphen (\texttt{-}) to $\name$, followed - by a string corresponding to the number of strings in $\othernames$. - Notice that this is not an ASL identifier, as ASL identifiers do not contain hyphens, which ensures that this string - does not occur in any specification; - \item $\formaltypes$ is the list of types that appear in $\formals$ in the same order; - \item checking for each $\namep$ in $\othernames$ whether the subprogram associated with $\namep$ clashes - with the subprogram type $\subpgmtype$ and list of types $\formaltypes$ yields $\False$ - or a type error that indicates there are multiply defined subprograms, which short-circuits the entire rule; - \item $\newtenv$ is $\tenv$ with the $\subprogramrenamings$ updated by binding $\name$ to the union of $\othernames$ and - $\{\newname\}$. - \end{itemize} -\end{itemize} - -\isempty{\subsection{Example}} - -\subsection{Formally} -\newcommand\stringconcat[0]{\hyperlink{def-stringconcat}{\texttt{+}}} -\newcommand\stringofint[0]{\hyperlink{def-stringofnat}{\texttt{string\_of\_nat}}} - -We use the following functions to construct a unique string for each subprogram: -\begin{itemize} -\hypertarget{def-stringconcat}{} -\item The function $\stringconcat : \Strings \times \Strings \rightarrow \Strings$ -concatenates two strings. - -\hypertarget{def-stringofnat}{} -\item The function $\stringofint : \N \rightarrow \Strings$ converts a natural number -to the corresponding string. -\end{itemize} - -\begin{mathpar} -\inferrule[first\_name]{ - G^\tenv.\subprogramrenamings(\name) = \bot\\ - \newtenv \eqdef (G^\tenv.\subprogramrenamings[\name\mapsto\{\name\}], L^\tenv) -}{ - \addnewfunc(\tenv, \name, \formals, \subpgmtype) \typearrow - (\newtenv, \overname{\name}{\newname}) -} -\end{mathpar} - -\begin{mathpar} -\inferrule[name\_exists]{ - G^\tenv.\subprogramrenamings(\name) = \othernames\\ - k \eqdef \cardinality{\othernames}\\ - \newname \eqdef \name\ \stringconcat\ \texttt{"-"}\ \stringconcat\ \stringofint(k)\\ - \formaltypes \eqdef [(\id,\vt) \in \formals : \vt]\\ - { - \left(\begin{array}{l} - \namep \in \othernames: \\ \subprogramclash(\tenv, \namep, \subpgmtype, \formaltypes) \typearrow - \vb_{\namep} \OrTypeError - \end{array}\right) - }\\\\ - \namep \in \othernames: \checktrans{\neg\vb_{\namep}}{\SubrogramDeclaredMultipleTimes} \typearrow \True \OrTypeError\\\\ - \newtenv \eqdef (G^\tenv.\subprogramrenamings[\name\mapsto \othernames \cup \{\newname\}], L^\tenv) -}{ - \addnewfunc(\tenv, \name, \formals, \subpgmtype) \typearrow - (\newtenv, \newname) -} -\end{mathpar} - -\isempty{\subsection{Comments}} -\lrmcomment{This is related to \identr{PGFC}.} - -\CodeSubsection{\AddNewFuncBegin}{\AddNewFuncEnd}{../Typing.ml} - -\section{TypingRule.CheckSetterHasGetter \label{sec:TypingRule.CheckSetterHasGetter}} -\hypertarget{def-checksetterhashgetter}{} -The function -\[ - \checksetterhasgetter(\overname{\staticenvs}{\tenv} \aslsep \overname{\func}{\funcsig}) - \aslto \overname{\True}{\vb} \cup \overname{\TTypeError}{\TypeErrorConfig} -\] -checks whether the setter procedure given by $\funcsig$ has a corresponding getter, -returning $\True$ if this condition holds and a type error otherwise. - -\subsection{Prose} -All of the following apply: -\begin{itemize} - \item checking that the subprogram type of $\funcsig$ is one of $\STSetter$ and \\ $\STEmptySetter$ - has one of two outcomes: - $\False$, which satisfies the premise; - or $\True$, which short-circuits the entire rule - (since the subprogram is not any kind of setter and no getter is required); - \item \view\ the list of arguments of $\funcsig$ (that is, $\funcsig.\funcargs$) as follows: - the \head\ is an argument that has the type $\rettype$; - the \tail\ is a list with arguments that have the types $\argtypes$; - \item applying $\subprogramforname$ to look up $\tenv$ for a subprogram with the name given by $\funcsig$ (that is, $\funcsig.\funcname$) - yields a subprogram definition AST node $\funcsigp$\ProseOrTypeError; - \item define $\watendgettertype$ as $\STGetter$ if $\funcsig.\subprogramtype$ is \\ $\STSetter$ and - $\STEmptyGetter$ otherwise (meaning, $\funcsig.\subprogramtype$ is $\STEmptySetter$); - \item checking that $\watendgettertype$ is the same as $\funcsigp.\funcsubprogramtype$ \\ yields $\True$\ProseOrTypeError; - \item define $\argtypesp$ as the list of types appearing in the signature of $\funcsigp$ (that is, in $\funcsigp.\funcargs$); - \item checking, for each index $\vi$ in the indices for $\argtypes$, that the type at $\argtypes[\vi]$ and the type at $\argtypesp[\vi]$ - are \typeequivalent\ yields $\True$\ProseOrTypeError; - \item checking that $\rettype$ and $\funcsigp.\funcreturntype$ are \typeequivalent\ yields \\ - $\True$\ProseOrTypeError; - \item define $\vb$ as $\True$ (that is, unless the rule short-circuited with a type error). -\end{itemize} - -\isempty{\subsection{Example}} - -\CodeSubsection{\CheckSetterHasGetterBegin}{\CheckSetterHasGetterEnd}{../Typing.ml} - -\subsection{Formally} -We define the helper function -\newcommand\matchsettertype[0]{\hyperlink{def-matchsettertype}{\texttt{match\_setter\_type}}} -\hypertarget{def-matchsettertype}{} -\[ - \matchsettertype \triangleq [\STSetter \mapsto \STGetter, \STEmptySetter \mapsto \STEmptyGetter] \enspace. -\] - -\begin{mathpar} -\inferrule{ - \issetter \eqdef \funcsig.\subprogramtype \in \{ \STSetter, \STEmptySetter\}\\ - \booltrans{\issetter} \booltransarrow \False \terminateas \True\\\\ - \funcsig.\funcargs \eqname (\Ignore, \rettype) \concat \vargs\\ - \argtypes \eqdef [(\Ignore, \vt) \in \vargs: \vt]\\ - \subprogramforname(\tenv, \funcsig.\funcname, \argtypes) \typearrow (\Ignore, \Ignore, \funcsigp) \OrTypeError\\\\ - \matchsettertype(\funcsig.\funcsubprogramtype) \typearrow \watendgettertype\\ - \checktrans{\watendgettertype = \funcsigp.\funcsubprogramtype}{\SetterWithoutGetter} \typearrow \True \OrTypeError\\\\ - \argtypesp \eqdef [(\Ignore, \vt) \in \funcsigp.\funcargs : \vt]\\ - \vi\in\listrange(\argtypes): \typeequal(\argtypes[\vi], \argtypesp[\vi]) \typearrow \vb_\vi \OrTypeError\\\\ - \vi\in\listrange(\argtypes): \checktrans{\vb_\vi}{\SetterWithoutGetter} \typearrow \True \OrTypeError\\\\ - \typeequal(\rettype, \funcsigp.\funcreturntype) \typearrow \vb_\ret \OrTypeError\\\\ - \checktrans{\vb_\ret}{\SetterWithoutGetter} \typearrow \True \OrTypeError -}{ - \checksetterhasgetter(\tenv, \funcsig) \typearrow \overname{\True}{\vb} -} -\end{mathpar} - -\section{TypingRule.AddSubprogram \label{sec:TypingRule.AddSubprogram}} -\hypertarget{def-addsubprogram}{} -The function -\[ - \addsubprogram( - \overname{\staticenvs}{\tenv} \aslsep - \overname{\Strings}{\name} \aslsep - \overname{\func}{\funcdef}) - \aslto - \overname{\staticenvs}{\newtenv} -\] -updates the global environment of $\tenv$ by mapping the (unique) subprogram identifier $\name$ -to the function definition $\funcdef$ in $\tenv$, resulting in a new static environment $\newtenv$. - -\subsection{Prose} -$\newtenv$ is $\tenv$ with its $\subprograms$ component updated by binding $\name$ to $\funcdef$. - -\subsection{Formally} -\begin{mathpar} -\inferrule{ - \newtenv \eqdef (G^\tenv.\subprograms[\name\mapsto\funcdef], L^\tenv) -}{ - \addsubprogram(\tenv, \name, \funcdef) \typearrow \newtenv -} -\end{mathpar} - -\section{TypingRule.DeclareGlobalStorage \label{sec:TypingRule.DeclareGlobalStorage}} -\hypertarget{def-declareglobalstorage}{} -The function -\[ - \declareglobalstorage(\overname{\staticenvs}{\tenv} \aslsep \overname{\globaldecl}{\gsd}) - \aslto - \overname{\staticenvs}{\newtenv} \aslsep \overname{\globaldecl}{\newgsd} - \cup - \overname{\TTypeError}{\TypeErrorConfig} -\] -annotates the global storage declaration $\gsd$ in the static environment $\tenv$, -yielding a modified static environment $\newtenv$ and annotated global storage declaration $\newgsd$. -\ProseOtherwiseTypeError - -\subsection{Prose} -All of the following apply: -\begin{itemize} - \item $\gsd$ is a global storage declaration with keyword $\keyword$, initial value \\ $\initialvalue$, - \optional\ type $\tyopt$, and name $\name$; - \item checking that $\name$ is not already declared in the global environment of $\tenv$ yields $\True$\ProseOrTypeError; - \item annotating the \optional\ type $\tyopt$ in $\tenv$ via $\annotatetypeopt$ yields \\ - $\tyoptp$\ProseOrTypeError; - \item annotating the \optional\ expression $\initialvalue$ in $\tenv$ via $\annotateexpropt$ yields - $(\initialvaluetype, \initialvaluep)$\ProseOrTypeError; - \item choosing the correct type between $\initialvaluetype$ and $\tyoptp$ in $tenv$ via $\annotateinittype$ yields - $\declaredt$; - \item adding a global storage element with name $\name$, global declaration keyword \\ $\keyword$ and type $\declaredt$ - to $\tenv$ via $\addglobalstorage$ yields $\tenvone$\ProseOrTypeError; - \item One of the following applies: - \begin{itemize} - \item All of the following apply (\textsc{constant}): - \begin{itemize} - \item $\keyword$ is $\GDKConstant$ and therefore $\initialvalue$ is some expression $\ve$ (the ASL parser guarantees - that the expression exists); - \item symbolically simplifying $\ve$ in $\tenvone$ via $\reduceconstants$ yields the literal $\vv$\ProseOrTypeError; - \item $\tenvtwo$ is $\tenvone$ with its $\constantvalues$ component updated by binding $\name$ to $\vv$; - \item $\newgsd$ is $\gsd$ with its type component as $\tyoptp$; - \item $\newtenv$ is $\tenvtwo$. - \end{itemize} - - \item All of the following apply (\textsc{non\_constant}): - \begin{itemize} - \item $\keyword$ is not $\GDKConstant$; - \item $\newtenv$ is $\tenvone$. - \end{itemize} - \end{itemize} - \item $\newgsd$ is $\gsd$ with its type component as $\tyoptp$ and $\initialvalue$ component as $\initialvaluep$; -\end{itemize} - -\isempty{\subsection{Example}} - -\subsection{Formally} -\begin{mathpar} -\inferrule[constant]{ - \gsd \eqname \{ - \GDkeyword : \keyword, - \GDinitialvalue : \initialvalue, - \GDty : \tyopt, - \GDname: \name - \}\\ -\checkvarnotingenv{\tenv, \name} \typearrow \True \OrTypeError\\\\ -\annotatetypeopt(\tenv, \tyopt) \typearrow \tyoptp \OrTypeError\\\\ -{ - \begin{array}{r} -\annotateexpropt(\tenv, \initialvalue) \typearrow \\ (\initialvaluetype, \initialvaluep) \OrTypeError - \end{array} -}\\ -\annotateinittype(\tenv, \initialvaluetype, \tyoptp) \typearrow \declaredt\\ -\addglobalstorage(\tenv, \name, \keyword, \declaredt) \typearrow \tenvone \OrTypeError\\\\ -\commonprefixline\\\\ -\keyword = \GDKConstant\\ -\initialvaluep \eqname \langle \ve \rangle\\ -\reduceconstants(\tenvone, \ve) \typearrow \vv \OrTypeError\\\\ -\tenvtwo \eqdef (G^\tenvone.\constantvalues[\name\mapsto\vv], L^\tenvone)\\ -{ -\newgsd \eqdef \left\{ - \begin{array}{rcl} - \GDkeyword &:& \keyword, \\ - \GDinitialvalue &:& \initialvalue, \\ - \GDty &:& \tyoptp, \\ - \GDname &:& \name - \end{array} -\right\} -} -}{ - \declareglobalstorage(\tenv, \gsd) \typearrow (\overname{\tenvtwo}{\newtenv}, \newgsd) -} -\end{mathpar} - -\begin{mathpar} -\inferrule[non\_constant]{ - \gsd \eqname \{ - \GDkeyword : \keyword, - \GDinitialvalue : \initialvalue, - \GDty : \tyopt, - \GDname: \name - \}\\ -\checkvarnotingenv{\tenv, \name} \typearrow \True \OrTypeError\\\\ -\annotatetypeopt(\tenv, \tyopt) \typearrow \tyoptp \OrTypeError\\\\ -{ - \begin{array}{r} -\annotateexpropt(\tenv, \initialvalue) \typearrow \\ (\initialvaluetype, \initialvaluep) \OrTypeError - \end{array} -}\\ -\annotateinittype(\tenv, \initialvaluetype, \tyoptp) \typearrow \declaredt\\ -\addglobalstorage(\tenv, \name, \keyword, \declaredt) \typearrow \tenvone \OrTypeError\\\\ -\commonprefixline\\\\ -\keyword \neq \GDKConstant\\ -{ -\newgsd \eqdef \left\{ - \begin{array}{rcl} - \GDkeyword &:& \keyword, \\ - \GDinitialvalue &:& \initialvalue, \\ - \GDty &:& \tyoptp, \\ - \GDname &:& \name - \end{array} -\right\} -} -}{ - \declareglobalstorage(\tenv, \gsd) \typearrow (\overname{\tenvone}{\newtenv}, \newgsd) -} -\end{mathpar} - -\isempty{\subsection{Comments}} -\lrmcomment{This relates to \identr{YSPM} and \identr{FWQM}.} -\CodeSubsection{\DeclareGlobalStorageBegin}{\DeclareGlobalStorageEnd}{../Typing.ml} - -\section{TypingRule.AnnotateTypeOpt \label{sec:TypingRule.AnnotateTypeOpt}} -\hypertarget{def-annotatetypeopt}{} -The function -\[ -\annotatetypeopt(\overname{\staticenvs}{\tenv} \aslsep \overname{\langle\overname{\ty}{\vt}\rangle}{\tyopt}) -\typearrow \overname{\langle\ty\rangle}{\tyoptp} -\cup \overname{\TTypeError}{\TypeErrorConfig} -\] -annotates the type $\vt$ inside an \optional\ $\tyopt$, if there is one, and leaves it as is if $\tyopt$ is $\None$. -\ProseOtherwiseTypeError - -\subsection{Prose} -One of the following applies: -\begin{itemize} - \item All of the following apply (\textsc{none}): - \begin{itemize} - \item $\tyopt$ is $\None$; - \item $\tyoptp$ is $\tyopt$. - \end{itemize} - - \item All of the following apply (\textsc{some}): - \begin{itemize} - \item $\tyopt$ contains the type $\vt$; - \item annotating $\vt$ in $\tenv$ yields $\vtone$\ProseOrTypeError; - \item $\tyoptp$ is $\langle\vtone\rangle$. - \end{itemize} -\end{itemize} - -\subsection{Formally} -\begin{mathpar} -\inferrule[none]{}{ - \annotatetypeopt(\tenv, \overname{\None}{\tyopt}) \typearrow \overname{\tyopt}{\tyoptp} -} -\and -\inferrule[some]{ - \annotatetype{\tenv, \vt} \typearrow \vtone \OrTypeError -}{ - \annotatetypeopt(\tenv, \overname{\langle\vt\rangle}{\tyopt}) \typearrow\overname{\langle\vtone\rangle}{\tyoptp} -} -\end{mathpar} - -\section{TypingRule.AnnotateExprOpt \label{sec:TypingRule.AnnotateExprOpt}} -\hypertarget{def-annotateexpropt}{} -The function -\[ - \annotateexpropt(\overname{\staticenvs}{\tenv} \aslsep \overname{\langle\ve\rangle}{\expropt}) - \aslto \overname{(\langle\expr\rangle \times \langle\ty\rangle)}{\vres} - \cup \overname{\TTypeError}{\TypeErrorConfig} -\] -annotates the \optional\ expression $\expropt$ in $\tenv$ and returns a pair of \optional\ expressions -for the type and annotated expression in $\vres$. -\ProseOtherwiseTypeError - -\subsection{Prose} -One of the following applies: -\begin{itemize} - \item All of the following apply (\textsc{none}): - \begin{itemize} - \item $\expropt$ is $\None$; - \item $\vres$ is $(\None, \None)$. - \end{itemize} - - \item All of the following apply (\textsc{some}): - \begin{itemize} - \item $\expropt$ contains the expression $\ve$; - \item annotating $\ve$ in $\tenv$ yields $(\vt, \vep)$\ProseOrTypeError; - \item $\vres$ is $(\langle\vt\rangle, \langle\vep\rangle)$. - \end{itemize} -\end{itemize} - -\subsection{Formally} -\begin{mathpar} -\inferrule[none]{}{ - \annotateexpropt(\tenv, \overname{\None}{\expropt}) \typearrow (\None, \None) -} -\and -\inferrule[some]{ - \annotateexpr{\tenv, \ve} \typearrow (\vt, \vep)\OrTypeError -}{ - \annotateexpropt(\tenv, \overname{\langle\ve\rangle}{\expropt}) \typearrow \overname{(\langle\vt\rangle, \langle\vep\rangle)}{\vres} -} -\end{mathpar} - -\section{TypingRule.AnnotateInitType \label{sec:TypingRule.AnnotateInitType}} -\hypertarget{def-annotateinittype}{} -The function -\[ - \annotateinittype(\overname{\staticenvs}{\tenv} \aslsep - \overname{\langle\ty\rangle}{\initialvaluetype} \aslsep - \overname{\langle\ty\rangle}{\typeannotation} - ) - \aslto \overname{\ty}{\declaredtype} - \cup \overname{\TTypeError}{\TypeErrorConfig} -\] -takes the \optional\ type associated with the initialization value of a global storage declaration --- $\initialvaluetype$ --- -and the \optional\ type annotation for the same global storage declaration --- $\typeannotation$ --- -and chooses the type that should be associated with the declaration --- $\declaredtype$ -- in $\tenv$. -\ProseOtherwiseTypeError - -The ASL parser ensures that at least one of $\initialvaluetype$ and \\ -$\typeannotation$ should not be $\None$. - -\subsection{Prose} -One of the following applies: -\begin{itemize} - \item All of the following apply (\textsc{both}): - \begin{itemize} - \item $\initialvaluetype$ is $\langle\vtone\rangle$ and $\typeannotation$ is $\langle\vttwo\rangle$; - \item checking that $\vtone$ \typesatisfies\ $\vttwo$ in $\tenv$ yields $\True$\ProseOrTypeError; - \item $\declaredtype$ is $\vtone$. - \end{itemize} - - \item All of the following apply (\textsc{annotated}): - \begin{itemize} - \item $\initialvaluetype$ is $\None$ and $\typeannotation$ is $\langle\vttwo\rangle$; - \item $\declaredtype$ is $\vttwo$. - \end{itemize} - - \item All of the following apply (\textsc{initial}): - \begin{itemize} - \item $\initialvaluetype$ is $\langle\vtone\rangle$ and $\typeannotation$ is $\None$; - \item $\declaredtype$ is $\vtone$. - \end{itemize} -\end{itemize} - -\begin{mathpar} -\inferrule[both]{ - \checktypesat(\tenv, \vtone, \vttwo) \typearrow \True \OrTypeError -}{ - \annotateinittype(\tenv, \overname{\langle\vtone\rangle}{\initialvaluetype}, \overname{\langle\vttwo\rangle}{\typeannotation}) - \typearrow \vttwo -} -\and -\inferrule[annotated]{}{ - \annotateinittype(\tenv, \overname{\None}{\initialvaluetype}, \overname{\langle\vttwo\rangle}{\typeannotation}) - \typearrow \vttwo -} -\and -\inferrule[initial]{}{ - \annotateinittype(\tenv, \overname{\langle\vtone\rangle}{\initialvaluetype}, \overname{\None}{\typeannotation}) - \typearrow \vtone -} -\end{mathpar} - -\section{TypingRule.AddGlobalStorage \label{sec:TypingRule.AddGlobalStorage}} -\hypertarget{def-addglobalstorage}{} -The function -\[ - \addglobalstorage( - \overname{\staticenvs}{\tenv} \aslsep - \overname{\identifier}{\name} \aslsep - \overname{\GDkeyword}{\keyword} \aslsep - \overname{\ty}{\declaredt} - ) - \aslto - \overname{\staticenvs}{\newtenv} \aslsep - \cup \overname{\TTypeError}{\TypeErrorConfig} -\] -modifies the static environment $\tenv$ by adding a global storage -for the identifier $\name$ with global storage keyword $\keyword$ and type $\declaredtypes$, -resulting in the environment $\newtenv$. -\ProseOtherwiseTypeError - -\subsection{Prose} -All of the following apply: -\begin{itemize} - \item checking that $\name$ is not declared in the global environment of $\tenv$ yields $\True$\ProseOrTypeError; - \item $\newtenv$ is $\tenv$ with its $\globalstoragetypes$ component updated by binding $\name$ to - $(\declaredt, \keyword)$. -\end{itemize} - -\subsection{Formally} -\begin{mathpar} -\inferrule{ - \checkvarnotingenv{\tenv, \name} \typearrow \True \OrTypeError\\\\ - \newtenv \eqdef (G^\tenv.\globalstoragetypes[\name \mapsto (\declaredt, \keyword)], L^\tenv) -} -{ - \addglobalstorage(\tenv, \name, \keyword, \declaredt) \typearrow \newtenv -} -\end{mathpar} - -\section{TypingRule.DeclareType \label{sec:TypingRule.DeclareType}} -\hypertarget{def-declaretype}{} -The function -\[ -\declaretype(\overname{\staticenvs}{\tenv} \aslsep - \overname{\identifier}{\name} \aslsep - \overname{\ty}{\tty} \aslsep - \overname{\langle(\identifier\times\field^*)\rangle}{\vs} -) \aslto \overname{\staticenvs}{\newtenv} -\cup \overname{\TTypeError}{\TypeErrorConfig} -\] -declares a type named $\name$ with type $\tty$ and \optional\ additional fields -over another type $\vs$ -in the static environment $\tenv$, resulting in the modified environment $\newtenv$. -\ProseOtherwiseTypeError - -\subsection{Prose} -All of the following apply: -\begin{itemize} - \item checking that $\name$ is not already declared in the global environment of $\tenv$ yields $\True$\ProseOrTypeError; - \item annotating the \optional\ extra fields $\vs$ for $\tty$ in $\tenv$ yields via \\ $\annotateextrafields$ - yields the modified environment $\tenvone$ and type $\vtone$\ProseOrTypeError; - \item annotating $\vtone$ in $\tenvone$ yields $\vttwo$\ProseOrTypeError; - \item $\tenvtwo$ is $\tenvone$ with its $\declaredtypes$ component updated by binding $\name$ to $\vttwo$; - \item One of the following applies: - \begin{itemize} - \item All of the following apply (\textsc{enum}): - \begin{itemize} - \item $\vttwo$ is an enumeration type with labels $\ids$, that is, $\TEnum(\ids)$; - \item applying $\declareenumlabels$ to $\vttwo$ in $\tenvtwo$ $\newtenv$\ProseOrTypeError. - \end{itemize} - - \item All of the following apply (\textsc{not\_enum}): - \begin{itemize} - \item $\vttwo$ is not an enumeration type; - \item $\newtenv$ is $\tenvtwo$. - \end{itemize} - \end{itemize} -\end{itemize} - -\isempty{\subsection{Example}} - -\CodeSubsection{\DeclareTypeBegin}{\DeclareTypeEnd}{../Typing.ml} - -\subsection{Formally} -\begin{mathpar} -\inferrule[enum]{ - \checkvarnotingenv{\tenv, \name} \typearrow \True \OrTypeError\\\\ - \annotateextrafields(\tenv, \tty, \vs) \typearrow (\tenvone, \vtone)\\ - \annotatetype{\True, \tenvone, \vtone} \typearrow \vttwo \OrTypeError\\\\ - \tenvtwo \eqdef (G^\tenvone.\declaredtypes[\name\mapsto\vttwo], L^\tenvone)\\ - \vttwo = \TEnum(\ids)\\ - \declareenumlabels(\tenvtwo, \vttwo) \typearrow \newtenv \OrTypeError -}{ - \declaretype(\tenv, \name, \tty, \vs) \typearrow \newtenv -} -\and -\inferrule[not\_enum]{ - \checkvarnotingenv{\tenv, \name} \typearrow \True \OrTypeError\\\\ - \annotateextrafields(\tenv, \tty, \vs) \typearrow (\tenvone, \vtone)\\ - \annotatetype{\True, \tenvone, \vtone} \typearrow \vttwo \OrTypeError\\\\ - \tenvtwo \eqdef (G^\tenvone.\declaredtypes[\name\mapsto\vttwo], L^\tenvone)\\ - \astlabel(\vttwo) \neq \TEnum -}{ - \declaretype(\tenv, \name, \tty, \vs) \typearrow \overname{\tenvtwo}{\newtenv} -} -\end{mathpar} - -\isempty{\subsection{Comments}} -\lrmcomment{This is related to \identr{DHRC}, \identd{YZBQ}, \identr{DWSP}, \identi{MZXL}, \identr{MDZD}, \identr{CHKR}.} - -\section{TypingRule.AnnotateExtraFields \label{sec:TypingRule.AnnotateExtraFields}} -\hypertarget{def-annotateextrafields}{} -The function -\[ -\begin{array}{r} -\annotateextrafields(\overname{\staticenvs}{\tenv} \aslsep - \overname{\ty}{\tty} \aslsep - \overname{\langle(\overname{\identifier}{\vsuper}\times\overname{\field^*}{\extrafields})\rangle}{\vs} -) -\aslto \\ -(\overname{\staticenvs}{\newtenv} \times \overname{\ty}{\newty}) -\cup \overname{\TTypeError}{\TypeErrorConfig} -\end{array} -\] -annotates the type $\tty$ with the \optional\ extra fields $\vs$ in $\tenv$, yielding -the modified environment $\newtenv$ and type $\newty$. -\ProseOtherwiseTypeError - -\subsection{Prose} -One of the following applies: -\begin{itemize} - \item All of the following apply (\textsc{none}): - \begin{itemize} - \item $\vs$ is $\None$; - \item $\newtenv$ is $\tenv$; - \item $\newty$ is $\tty$. - \end{itemize} - - \item All of the following apply (\textsc{empty\_fields}): - \begin{itemize} - \item $\vs$ is $\langle(\vsuper, \extrafields)\rangle$; - \item checking that $\tty$ \subtypesatisfies\ the named type $\vsuper$ (that is, \\ $\TNamed(\vsuper)$) yields - $\True$\ProseOrTypeError; - \item $\extrafields$ is the empty list; - \item $\newtenv$ is $\tenv$; - \item $\newty$ is $\tty$. - \end{itemize} - - \item All of the following apply (\textsc{no\_super}): - \begin{itemize} - \item $\vs$ is $\langle(\vsuper, \extrafields)\rangle$; - \item checking that $\tty$ \subtypesatisfies\ the named type $\vsuper$ (that is, \\ $\TNamed(\vsuper)$) yields - $\True$\ProseOrTypeError; - \item $\extrafields$ is not an empty list; - \item $\vsuper$ is not bound to a type in $\tenv$; - \item the result is a type error indicating that $\vsuper$ is not a declared type. - \end{itemize} - - \item All of the following apply (\textsc{structured}): - \begin{itemize} - \item $\vs$ is $\langle(\vsuper, \extrafields)\rangle$; - \item checking that $\tty$ \subtypesatisfies\ the named type $\vsuper$ (that is,\\ $\TNamed(\vsuper)$) yields - $\True$\ProseOrTypeError; - \item $\extrafields$ is not an empty list; - \item $\vsuper$ is bound to a type $\vt$ in $\tenv$; - \item checking that $\vt$ is a \structuredtype\ yields $\True$ or a type error - indicating that a \structuredtype\ was expected, thereby short-circuiting the entire rule; - \item $\vt$ has AST label $L$ and fields $\fields$; - \item $\newty$ is the type with AST label $L$ and list fields that is the concatenation of $\fields$ and $\extrafields$; - \item $\newtenv$ is $\tenv$ with its $\subtypes$ component updated by binding $\name$ to $\vsuper$. - \end{itemize} -\end{itemize} - -\subsection{Formally} -\begin{mathpar} -\inferrule[none]{}{ - \annotateextrafields(\tenv, \tty, \overname{\None}{\vs}) \typearrow (\overname{\tenv}{\newtenv}, \overname{\tty}{\newty}) -} -\end{mathpar} - -\begin{mathpar} -\inferrule[empty\_fields]{ - \subtypesat(\tty, \TNamed(\vsuper)) \typearrow \vb\\ - \checktrans{\vb}{TypeConflict} \typearrow \True \OrTypeError\\\\ - \extrafields = \emptylist -}{ - \annotateextrafields(\tenv, \tty, \overname{\langle(\vsuper, \extrafields)\rangle}{\vs}) \typearrow (\overname{\tenv}{\newtenv}, \overname{\tty}{\newty}) -} -\end{mathpar} - -\begin{mathpar} -\inferrule[no\_super]{ - \subtypesat(\tty, \TNamed(\vsuper)) \typearrow \vb\\ - \checktrans{\vb}{TypeConflict} \typearrow \True \OrTypeError\\\\ - \extrafields \neq \emptylist\\\\ - G^\tenv.\declaredtypes(\vsuper) = \bot -}{ - \annotateextrafields(\tenv, \tty, \overname{\langle(\vsuper, \extrafields)\rangle}{\vs}) \typearrow - \TypeErrorVal{\UndefinedIdentifier} -} -\end{mathpar} - -\begin{mathpar} -\inferrule[structured]{ - \subtypesat(\tty, \TNamed(\vsuper)) \typearrow \vb\\ - \checktrans{\vb}{TypeConflict} \typearrow \True \OrTypeError\\\\ - \extrafields \neq \emptylist\\\\ - G^\tenv.\declaredtypes(\vsuper) = \vt\\ - { - \begin{array}{r} - \checktrans{\astlabel(\vt) \in \{\TRecord, \TException\}}{ExpectedStructuredType} \typearrow \\ \True \OrTypeError - \end{array} - }\\ - \vt \eqname L(\fields)\\ - \newty \eqdef L(\fields \concat \extrafields)\\ - \newtenv \eqdef (G^\tenv.\subtypes[\name\mapsto\vsuper], L^\tenv) -}{ - \annotateextrafields(\tenv, \tty, \overname{\langle(\vsuper, \extrafields)\rangle}{\vs}) \typearrow (\newtenv, \newty) -} -\end{mathpar} - -\section{TypingRule.AnnotateEnumLabels \label{sec:TypingRule.AnnotateEnumLabels}} -\hypertarget{def-annotateenumlabels}{} -The function -\[ -\declareenumlabels(\overname{\staticenvs}{\tenv} \aslsep - \overname{\identifier}{\name} \aslsep - \overname{\identifier^+}{\ids} \aslsep - \aslto \overname{\staticenvs}{\newtenv} - \cup \overname{\TTypeError}{\TypeErrorConfig} -) -\] -updates the static environment $\tenv$ with the identifiers $\ids$ listed by an enumeration type, -yielding the modified environment $\newtenv$. -\ProseOtherwiseTypeError - -\subsection{Prose} -All of the following apply: -\begin{itemize} - \item $\ids$ is the (non-empty) list of labels $\id_{1..k}$; - \item $\tenv_0$ is $\tenv$; - \item declaring the constant $\id_i$ with the type $\TNamed(\name)$ and literal \lint(i-1) in $\tenv_{i-1}$ - via $\declareconst$ - yields $\tenv_i$, for $i=1 $ to $k$ (if $k>1$)\ProseOrTypeError; - \item $\newtenv$ is $\tenv_k$. -\end{itemize} - -\subsection{Formally} -\begin{mathpar} -\inferrule{ - \ids \eqname \id_{1..k}\\ - \tenv_0 \eqdef \tenv\\ - \vi=1..k: \declareconst(\tenv_{\vi-1}, \id_\vi, \TNamed(\name), \lint(\vi-1)) \typearrow \tenv_{\vi} \OrTypeError -}{ - \declareenumlabels(\tenv, \name, \ids) \typearrow \overname{\tenv_k}{\newtenv} -} -\end{mathpar} - -\section{TypingRule.DeclareConst \label{sec:TypingRule.DeclareConst}} -\hypertarget{def-declareconst}{} -The function -\[ -\declareconst(\overname{\staticenvs}{\tenv} \aslsep - \overname{\identifier}{\name} \aslsep - \overname{\ty}{\tty} \aslsep - \overname{\literal}{vv}) - \aslto - \overname{\staticenvs}{\newtenv} \cup \overname{\TTypeError}{\TypeErrorConfig} -\] -adds a constant given by the identifier $\name$, type $\tty$, and literal $\vv$ to the -static environment $\tenv$, yielding the modified environment $\newtenv$. -\ProseOtherwiseTypeError - -\subsection{Prose} -All of the following apply: -\begin{itemize} - \item adding the global storage given by the identifier $\name$, global declaration keyword $\GDKConstant$, - and type $\tty$ to $\tenv$ yields $\tenvone$; - \item $\newtenv$ is $\tenvone$ with its $\constantvalues$ component updated by binding $\name$ to $\vv$. -\end{itemize} - -\begin{mathpar} -\inferrule{ - \addglobalstorage(\tenv, \name, \GDKConstant, \tty) \typearrow \tenvone\\ - \newtenv \eqdef (G^\tenvone.\constantvalues[\name, \vv], L^\tenvone) -}{ - \declareconst(\tenv, \name, \tty, \vv) \typearrow \newtenv -} -\end{mathpar} - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -\chapter{Typing of Specifications} -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - -The untyped AST of an ASL specification consists of a list of declarations. -Type-checking the untyped AST succeeds if all declarations can be successfully annotated. -This is achieved via the function $\typecheckast$, which is detailed in -TypingRule.TypeCheckAST (see \secref{TypingRule.TypeCheckAST}). - -We define the following helper rules: -\begin{itemize} - \item TypingRule.AnnotateDeclComps (see \secref{TypingRule.AnnotateDeclComps}) - \item TypingRule.BuildDependencies (see \secref{TypingRule.BuildDependencies}) - \item TypingRule.DeclDependencies (see \secref{TypingRule.DeclDependencies}) - \item TypingRule.TypeCheckMutuallyRec (see \secref{TypingRule.TypeCheckMutuallyRec}) - \item TypingRule.FoldEnvAndFs (see \secref{TypingRule.FoldEnvAndFs}) - \item TypingRule.DefDecl (see \secref{TypingRule.DefDecl}) - \item TypingRule.DefEnumLabels (see \secref{TypingRule.DefEnumLabels}) - \item TypingRule.UseDecl (see \secref{TypingRule.UseDecl}) - \item TypingRule.UseTy (see \secref{TypingRule.UseTy}) - \item TypingRule.UseSubtypes (see \secref{TypingRule.UseSubtypes}) - \item TypingRule.UseExpr (see \secref{TypingRule.UseExpr}) - \item TypingRule.UseLexpr (see \secref{TypingRule.UseLexpr}) - \item TypingRule.UsePattern (see \secref{TypingRule.UsePattern}) - \item TypingRule.UseSlice (see \secref{TypingRule.UseSlice}) - \item TypingRule.UseBitfield (see \secref{TypingRule.UseBitfield}) - \item TypingRule.UseConstraint (see \secref{TypingRule.UseConstraint}) - \item TypingRule.UseStmt (see \secref{TypingRule.UseStmt}) - \item TypingRule.UseLDI (see \secref{TypingRule.UseLDI}) - \item TypingRule.UseCase (see \secref{TypingRule.UseCase}) - \item TypingRule.UseCatcher (see \secref{TypingRule.UseCatcher}) -\end{itemize} - -\section{TypingRule.TypeCheckAST \label{sec:TypingRule.TypeCheckAST}} -\hypertarget{def-typecheckast}{} -The relation -\[ -\typecheckast( - \overname{\staticenvs}{\tenv} \aslsep - \overname{\decl^*}{\decls} -) \aslrel -(\overname{\decl^*}{\newdecls} \times \overname{\staticenvs}{\newtenv}) -\cup \overname{\TTypeError}{\TypeErrorConfig} -\] -annotates a list of declarations $\decls$ in an input static environment $\tenv$, -yielding an output static environment $\newtenv$ and annotated list of declarations $\newdecls$. -\ProseOtherwiseTypeError - -\begin{definition}[Strongly Connected Components] -\hypertarget{def-scc}{} -Given a graph $G=(V, E)$, a \\ subset of its nodes $C \subseteq V$ is called -a \emph{strongly connected component} of $G$ if -every pair of nodes $u,v \in C$ reachable from one another. - -The \emph{strongly connected components} of a graph $(V, E)$ uniquely partitions its set of -nodes $V$ into a set of strongly connected components: -\[ -\SCC(V, E) \triangleq \{ C \subseteq V \;|\; \forall u,v\in C.\ (u,v), (v,u) \in E^* \} \enspace. -\] - -We write $E^*$ to denote the reflexive-transitive closure of $E$. -\end{definition} - -\begin{definition}[Topological Ordering] -For a graph $G=(V, E)$ and its \\ -strongly connected components $\comps \triangleq \SCC(V, E)$, -we say that $C_1\in\comps$ is ordered before $C_2\in\comps$, denoted $C_1 < C_2$, -if the following condition holds: -\[ -C_1 < C_2 \Leftrightarrow \exists c_1\in C_1.\ c_2\in C_2.\ (c_1,c_2) \in E^* \enspace. -\] -This ordering is not total. That is, there may exist strongly connected components -$A,B\in\comps$ such that $A \not< B$ and $B \not< A$. - -\hypertarget{def-topologicalordering}{} -We say that a list of subsets of $V$ --- $\compstwo$ --- respects the topological ordering of $\comps$ -if each element of $\compstwo$ is a member of $\comps$ and for every $C_1,C_2\in\comps$ such that -$C_1 < C_2$ we have that $C_1$ appears before $C_2$ in $\compstwo$. -We denote this as $\compstwo \in \topologicalordering(V, E, \comps)$. -\end{definition} - -\subsection{Prose} -All of the following apply: -\begin{itemize} - \item applying $\builddependencies$ to $\decls$ yields the dependency graph \\ $(\defs, \dependencies)$; - \item partitioning the nodes of the dependency graph $(\defs, \dependencies)$ into strongly connected components - yields $\comps$; - \item $\compstwo$ is an ordering of $\comps$ that respects the topological ordering induced by $\dependencies$; - \item $\compdecls$ applies $\declsofcomp$ to each component $\vc$ in $\compstwo$ to transform it into a list, - yielding a list of lists where each sublist corresponds to one strongly connected component; - \item applying $\annotatedeclcomps$ to $\compdecls$ in $\tenv$ yields \\ - $(\newdecls, \newtenv)$\ProseOrTypeError. -\end{itemize} - -\isempty{\subsection{Example}} - -\CodeSubsection{\TypeCheckASTBegin}{\TypeCheckASTEnd}{../Typing.ml} - -\subsection{Formally} -\begin{mathpar} -\inferrule{ - \builddependencies(\decls) \typearrow (\defs, \dependencies)\\ - \SCC(\defs, \dependencies) = \compsone\\ - \compstwo \in \topologicalordering(\compsone, \dependencies)\\ - \compdecls \eqdef [ \vc\in\compstwo: \declsofcomp(\vc, \decls) ]\\ - \annotatedeclcomps(\tenv, \compdecls) \typearrow (\newdecls, \newtenv) \OrTypeError -}{ - \typecheckast(\tenv, \decls) \typearrow (\newdecls, \newtenv) -} -\end{mathpar} - -\subsection{Comments} -It is crucial to process the strongly connected components obtained from the dependency graph -according to the topological ordering of the components. Otherwise, the type-system could -falsely result in a type error indicating that some identifier is not defined. -However, a topological ordering is not unique, which is why $\typecheckast$ is a relation rather than -a function. -It is possible to obtain a deterministic ordering by ordering components so as to respect -the order of declarations in $\decls$, that is, -the order in which declarations appear in the specification. -Similarly, any ordering of the declarations within a single strongly connected component is correct, -but it is possible to order the declarations according to their order of appearance in $\decls$, -as demonstrated in TypingRule.DeclsOfComp. - -\lrmcomment{This relates to \identi{LWQQ}.} - -\section{TypingRule.DeclsOfComp \label{sec:TypingRule.DeclsOfComp}} -\hypertarget{def-declsofcomp}{} -The helper function -\[ -\declsofcomp( - \overname{\pow{\identifier}}{\comp} \aslsep - \overname{\decl^*}{\decls} -) \aslto \overname{\decl^*}{\compdecls} -\] -lists the sublist of declarations in $\decls$ corresponding to the identifiers in $\comp$ -yielding $\compdecls$ - -\subsection{Prose} -One of the following applies: -\begin{itemize} - \item All of the following apply (\textsc{empty}): - \begin{itemize} - \item $\decls$ is the empty list; - \item define $\compdecls$ as the empty list. - \end{itemize} - - \item All of the following apply (\textsc{non\_empty}): - \begin{itemize} - \item $\decls$ is the list with \head\ $\vd$ and \tail\ $declsone$; - \item define $\declstwo$ as the singleton list for $\vd$ if applying $\defdecl$ to $\vd$ yields an identifier - that is a member of $\comp$ and the empty list, otherwise; - \item applying $\declsofcomp$ to $\comp$ and $\declsone$ yields $\declsthree$; - \item define $\compdecls$ as the concatenation of $\declstwo$ and $\declsthree$. - \end{itemize} -\end{itemize} - -\subsection{Formally} -\begin{mathpar} -\inferrule[empty]{}{ - \declsofcomp(\comp, \overname{\emptylist}{\decls}) \typearrow \overname{\emptylist}{\compdecls} -} -\and -\inferrule[non\_empty]{ - \declstwo \eqdef \choice{\defdecl(\vd) \in \comp}{[\vd]}{\emptylist}\\ - \declsofcomp(\comp, \declsone) \typearrow \declsthree -}{ - \declsofcomp(\comp, \overname{[\vd]\concat\declsone}{\decls}) \typearrow \overname{\declstwo\concat\declsthree}{\compdecls} -} -\end{mathpar} - -\section{TypingRule.AnnotateDeclComps \label{sec:TypingRule.AnnotateDeclComps}} -\hypertarget{def-annotatedeclcomps}{} -The function -\[ -\annotatedeclcomps(\overname{\staticenvs}{\tenv} \aslsep \overname{(\decl^*)^*}{\comps}) -\aslto -(\overname{\staticenvs}{\newtenv} \times \overname{\decl^*}{\newdecls}) -\cup \overname{\TTypeError}{\TypeErrorConfig} -\] -annotates a list of declaration components $\comps$ -(a list of lists) in the static environment $\tenv$, -yielding the annotated list of declarations $\newdecls$ and modified environment $\newtenv$. -\ProseOtherwiseTypeError - -We note that a strongly-connected component containing just a single declaration may contain -any kind of global declaration --- -a type declaration, a global storage declaration, or a subprogram declaration --- -whereas a strongly-connected component containing multiple declarations must be checked -to contain only subprograms. This is because the only type of mutually-recursive declarations -allows in ASL are between subprograms. The rules below handle these cases separately (\textsc{single} -for single declarations and \textsc{mutually\_recursive} for more than one declaration). - -\subsection{Prose} -One of the following applies: -\begin{itemize} - \item All of the following apply (\textsc{empty}): - \begin{itemize} - \item $\comps$ is the empty list; - \item define $\newtenv$ as $\tenv$; - \item define $\newdecls$ as the empty list. - \end{itemize} - - \item All of the following apply (\textsc{single}): - \begin{itemize} - \item $\comps$ is a list with \head\ $\comp$ and \tail\ $\compsone$; - \item $\comp$ is a single declaration $\vd$; - \item applying $\typecheckdecl$ to $\vd$ in $\tenv$ yields $(\vdone, \tenvone)$\ProseOrTypeError; - \item applying $\annotatedeclcomps$ to $\compsone$ in $\tenvone$ yields \\ $(\newtenv, \declsone)$\ProseOrTypeError; - \item define $\newdecls$ as the list with \head\ $\vdone$ and \tail\ $\declsone$. - \end{itemize} - - \item All of the following apply (\textsc{mutually\_recursive}): - \begin{itemize} - \item $\comps$ is a list with \head\ $\comp$ and \tail\ $\compsone$; - \item $\comp$ is a list with more than one declaration (which together represent a mutually-recursive - list of declarations); - \item applying $\typecheckmutuallyrec$ to $\comp$ in $\tenv$ yields \\ $(\declsone, \tenvone)$\ProseOrTypeError; - \item applying $\annotatedeclcomps$ to $\compsone$ in $\tenvone$ yields \\ $(\newtenv, \declstwo)$\ProseOrTypeError; - \item define $\newdecls$ as the concatenation of $\declsone$ and $\declstwo$. - \end{itemize} -\end{itemize} - -\subsection{Formally} -\begin{mathpar} -\inferrule[empty]{}{ - \annotatedeclcomps(\tenv, \overname{\emptylist}{\comps}) \aslto (\overname{\tenv}{\newtenv}, \overname{\emptylist}{\newdecls}) -} -\and -\inferrule[single]{ - \comp = [\vd]\\ - \typecheckdecl(\tenv, \vd) \typearrow (\vdone, \tenvone) \OrTypeError\\\\ - \annotatedeclcomps(\tenvone, \compsone) \typearrow (\newtenv, \declsone) \OrTypeError -}{ - \annotatedeclcomps(\tenv, \overname{[\comp] \concat \compsone}{\comps}) \aslto - (\newtenv, \overname{[\vdone] \concat \declsone}{\newdecls}) -} -\and -\inferrule[mutually\_recursive]{ - |\comp| > 1\\ - \typecheckmutuallyrec(\tenv, \comp) \typearrow (\declsone, \tenvone) \OrTypeError\\\\ - \annotatedeclcomps(\tenvone, \compsone) \typearrow (\newtenv, \declstwo) \OrTypeError -}{ - \annotatedeclcomps(\tenv, \overname{[\comp] \concat \compsone}{\comps}) \aslto - (\newtenv, \overname{\declsone \concat \declstwo}{\newdecls}) -} -\end{mathpar} - -\section{TypingRule.BuildDependencies \label{sec:TypingRule.BuildDependencies}} -\hypertarget{def-builddependencies}{} -The function -\[ -\builddependencies(\overname{\decl^*}{\decls}) -\aslto -(\overname{\identifier^*}{\defs}, \overname{(\identifier\times\identifier)^*}{\dependencies}) -\] -takes a set of declarations $\decls$ and -returns a graph whose set of nodes are the identifiers that are used to name declarations -and whose set of edges $\dependencies$ consists of pairs $(a,b)$ -where the declaration of $a$ uses an identifier defined by $b$. -We refer to this graph as the \emph{dependency graph} (of $\decls$). - -\subsection{Prose} -All of the following apply: -\begin{itemize} - \item define $\defs$ as the union of two sets: - \begin{enumerate} - \item the set of identifiers obtained by applying $\defdecl$ to each declaration in $\decls$; - \item the union of applying $\defenumlabels$ to each declaration in $\decls$. - \end{enumerate} - \item define $\dependencies$ as the union of applying $\decldependencies$ to each declaration in $\decls$. -\end{itemize} - -\subsection{Formally} -\begin{mathpar} -\inferrule{ - \defs \eqdef \{ \defdecl(\vd) \;|\; \vd \in \decls\} \cup \bigcup_{\vd\in\decls} \defenumlabels(\vd)\\ - \dependencies \eqdef \bigcup_{\vd \in \decls} \decldependencies(\vd) -}{ - \builddependencies(\decls) \typearrow (\ids, \dependencies) -} -\end{mathpar} - -\section{TypingRule.DeclDependencies \label{sec:TypingRule.DeclDependencies}} -\hypertarget{def-decldependencies}{} -The function -\[ -\decldependencies(\overname{\decl}{\vd}) \aslto \overname{(\identifier\times\identifier)^*}{\dependencies} -\] -returns the set of dependent pairs of identifiers $\dependencies$ induced by the declaration $\vd$. - -\subsection{Prose} -Define $\dependencies$ as the union of the following two sets: -\begin{enumerate} - \item a pair $(\idone, \idtwo)$ where $\idone$ is the result of applying $\defdecl$ to $\vd$ - and $\idtwo$ included in the result of applying $\defenumlabels$ to $\vd$; and - \item a pair $(\idone, \idtwo)$ where $\idone$ is the result of applying $\defdecl$ to $\vd$ - and $\idtwo$ included in the result of applying $\usedecl$ to $\vd$; and -\end{enumerate} - -\subsection{Formally} -\begin{mathpar} -\inferrule{ - { - \begin{array}{rcll} - \dependencies & \eqdef & \{ (\idone, \idtwo) \;|\; \idone = \defdecl(\vd) \land \idtwo \in \defenumlabels(\vd) \} & \cup\\ - & & \{ (\idone, \idtwo) \;|\; \idone = \defdecl(\vd) \land \idtwo \in \usedecl(\vd) \} & - \end{array} - } -}{ - \decldependencies(\vd) \typearrow \dependencies -} -\end{mathpar} - -\section{TypingRule.TypeCheckMutuallyRec \label{sec:TypingRule.TypeCheckMutuallyRec}} -\hypertarget{def-typecheckmutuallyrec}{} -The function -\[ - \typecheckmutuallyrec( - \overname{\staticenvs}{\tenv} \aslsep - \overname{\decl^*}{\decls} - ) - \aslto - ( - \overname{\decl^*}{\newdecls} \times - \overname{\staticenvs}{\newtenv} - ) - \cup \overname{\TTypeError}{\TypeErrorConfig} -\] -annotates a list of mutually recursive declarations -$\decls$ in the static environment $\tenv$, -yielding the annotated list of subprogram declarations $\newdecls$ -and modified environment $\newtenv$. - -One of the requirements from an ASL specification is that each setter has a corresponding getter. -To facilitate checking this requirement, the type-system annotates the declarations of all subprograms -that are not setters before annotating the declarations of setters. This way, when annotating a setter, -the corresponding getter should have already been annotated and added to the environment, making it -easy to check this requirement. - -\subsection{Prose} -All of the following apply: -\begin{itemize} - \item checking that each declaration in $\vd$ is a subprogram declaration yields $\True$\ProseOrTypeError; - \item applying $\annotatefuncsig$ to each node $\vf$ in $\tenv$, where $\DFunc(\vf)$ is a declaration in $\decls$, - yields $(\tenv_\vf, \vd_\vf)$\ProseOrTypeError; - \item define $\envandfs$ as the list of pairs, each consisting of the local environment component of $\tenv_\vf$ - and the annotated subprogram $\vd_\vf$, for each subprogram declaration $\DFunc(\vf)$ in $\decls$; - \item splitting $\envandfs$ into two sublists by testing each pair to check whether the subprogram declaration - component is that of a setter (or an empty setter) yields $\setters$ and $\others$, respectively; - \item define $\envandfsone$ as the concatenation of $\others$ and $\setters$; - \item applying $\foldenvandfs$ to the global component of $\tenv$ and $\envandfsone$ yields $(\genv, \envandfstwo)$\ProseOrTypeError; - \item for each pair consisting of a local static environment and subprogram declaration $(\lenv, \DFunc(\vf))$, - applying $\annotatesubprogram$ to the static environment $(\genv, \lenv)$ and $\vf$ yields $\newd_\vf$\ProseOrTypeError; - \item define $\newdecls$ as the list of subprogram declarations $\DFunc(\newd_\vf)$, for each pair $(\Ignore, \DFunc(\vf))$ in - $\envandfstwo$; - \item define $\newtenv$ as the static environment $(\genv, L^\tenv)$. -\end{itemize} - -\CodeSubsection{\TypeCheckMutuallyRecBegin}{\TypeCheckMutuallyRecEnd}{../Typing.ml} - -\subsection{Formally} -\begin{mathpar} -\inferrule{ - \vd\in\decls: \checktrans{\astlabel(\vd) = \DFunc}{\BadRecursiveDecls} \typearrow \True\OrTypeError\\\\ - \DFunc(\vf)\in\decls: \annotatefuncsig(\tenv, \vf) \typearrow (\tenv_\vf, \vd_\vf)\OrTypeError\\\\ - \envandfs \eqdef [\DFunc(\vf)\in\decls: (L^{\tenv_\vf}, \vd_\vf)]\\ - { - \setters \eqdef \left[ \begin{array}{r|l} - (\lenv,\vd) & (\lenv, \DFunc(\vf)) \in \envandfs\ \land \\ - & \astlabel(\vf) \in \{\STSetter, \STEmptySetter\} - \end{array}\right] - }\\ - { - \others \eqdef \left[ \begin{array}{r|l} - (\lenv,\vd) & (\lenv, \DFunc(\vf)) \in \envandfs\ \land \\ - & \astlabel(\vf) \not\in \{\STSetter, \STEmptySetter\} - \end{array}\right] - }\\ - \envandfsone \eqdef \others \concat \setters\\ - \foldenvandfs(G^\tenv, \envandfsone) \typearrow (\genv, \envandfstwo) \OrTypeError\\\\ - { - \begin{array}{r} - (\lenv, \DFunc(\vf))\in\envandfstwo: \annotatesubprogram{(\genv, \lenv), \vf} \typearrow \\ \newd_\vf \OrTypeError - \end{array} - }\\\\ - \newdecls \eqdef [(\Ignore, \DFunc(\vf))\in\envandfstwo: \DFunc(\newd_\vf)] -}{ - \typecheckmutuallyrec(\tenv, \decls) \typearrow (\newdecls, \overname{(\genv, L^\tenv)}{\newtenv}) -} -\end{mathpar} - -\section{TypingRule.FoldEnvAndFs \label{sec:TypingRule.FoldEnvAndFs}} -\hypertarget{def-foldenvandfs}{} -The function -\[ - \foldenvandfs( - \overname{\globalstaticenvs}{\genv} \aslsep - \overname{(\localstaticenvs\times\func)^*}{\envandfs} - ) \aslto - \overname{\globalstaticenvs}{\newgenv} \times - \overname{(\localstaticenvs\times\func)^*}{\newenvandfs} - \cup \overname{\TTypeError}{\TypeErrorConfig} -\] -processes a list of pairs, each consisting of a local static environment and a subprogram declaration, $\envandfs$, -in the context of a global static environment $\genv$. -The result is a modified global static environment $\newgenv$ and list of pairs $\newenvandfs$. - -\subsection{Prose} -One of the following applies: -\begin{itemize} - \item All of the following apply (\textsc{empty}): - \begin{itemize} - \item $\envandfs$ is the empty list; - \item define $\newgenv$ as $\genv$; - \item define $\newenvandfs$ as the empty list. - \end{itemize} - - \item All of the following apply (\textsc{non\_empty}): - \begin{itemize} - \item $\envandfs$ is the list with \head\ $(\lenv, \vf)$ and \tail\ $\envandfsone$; - \item define $\tenv$ as the environment where the global environment component is $\genv$ and the local environment component is $\lenv$; - \item applying $\declareonefunc$ to $\vf$ in $\tenv$ yields $(\tenvone, \vfone)$\ProseOrTypeError; - \item applying $\foldenvandfs$ to the global environment of $\tenvone$ and \\ - $\envandfsone$ yields $(\newgenv, \envandfstwo)$\ProseOrTypeError; - \item define $\newenvandfs$ as the list with \head\ $(\lenv, \vfone)$ and \tail\ $\envandfstwo$. - \end{itemize} -\end{itemize} - -\subsection{Formally} -\begin{mathpar} -\inferrule[empty]{}{ - \foldenvandfs(\genv, \overname{\emptylist}{\envandfs}) \typearrow (\overname{\genv}{\newgenv}, \overname{\emptylist}{\newenvandfs}) -} -\and -\inferrule[non\_empty]{ - \tenv \eqdef (\genv, \lenv)\\ - \declareonefunc(\tenv, \vf) \typearrow (\tenvone, \vfone) \OrTypeError\\\\ - \foldenvandfs(G^\tenvone, \envandfsone) \typearrow (\newgenv, \envandfstwo) \OrTypeError\\\\ - \newenvandfs \eqdef [(\lenv, \vfone)] \concat \envandfstwo -}{ - \foldenvandfs(\genv, \overname{[(\lenv, \vf)]\concat\envandfsone}{\envandfs}) \typearrow (\overname{\genv}{\newgenv}, \newenvandfs) -} -\end{mathpar} - -\section{TypingRule.DefDecl \label{sec:TypingRule.DefDecl}} -\hypertarget{def-defdecl}{} -The function -\[ -\defdecl(\overname{\decl}{\vd}) \aslto \overname{\identifier}{\name} -\] -returns the identifier $\name$ being defined by the declaration $\vd$. - -\subsection{Prose} -One of the following applies: -\begin{itemize} - \item All of the following apply (\textsc{d\_func}): - \begin{itemize} - \item $\vd$ declares a subprogram for the identifier $\name$. - \end{itemize} - - \item All of the following apply (\textsc{d\_globalstorage}): - \begin{itemize} - \item $\vd$ declares a global storage element for the identifier $\name$. - \end{itemize} - - \item All of the following apply (\textsc{d\_typedecl}): - \begin{itemize} - \item $\vd$ declares a type for the identifier $\name$. - \end{itemize} -\end{itemize} - -\begin{mathpar} -\inferrule[d\_func]{}{ - \defdecl(\overname{\DFunc(\funcname: \name, \ldots)}{\vd}) \typearrow \name -} -\and -\inferrule[d\_globalstorage]{}{ - \defdecl(\overname{\DGlobalStorage(\GDname: \name, \ldots)}{\vd}) \typearrow \name -} -\and -\inferrule[d\_typedecl]{}{ - \defdecl(\overname{\DTypeDecl(\name, \Ignore, \Ignore)}{\vd}) \typearrow \name -} -\end{mathpar} - -\section{TypingRule.DefEnumLabels \label{sec:TypingRule.DefEnumLabels}} -\hypertarget{def-defenumlabels}{} -The function -\[ -\defenumlabels(\overname{\decl}{\vd}) \aslto \overname{\pow{\identifier}}{\vlabels} -\] -takes a declaration $\vd$ and returns the set of enumeration labels it defines --- $\vlabels$ -- -if it defines any. - -\subsection{Prose} -One of the following applies: -\begin{itemize} - \item All of the following apply (\textsc{decl\_enum}): - \begin{itemize} - \item $\vd$ is a declaration of an enumeration type with labels $\vlabels$; - \item the result is $\vlabels$ as a set (rather than a list). - \end{itemize} - - \item All of the following apply (\textsc{other}): - \begin{itemize} - \item $\vd$ is not a declaration of an enumeration type; - \item define $\vlabels$ as the empty set. - \end{itemize} -\end{itemize} - -\begin{mathpar} -\inferrule[decl\_enum]{ - \vd = \DTypeDecl(\name, \TEnum(\vlabels, \Ignore)) -}{ - \defenumlabels(\vd) \typearrow \overname{\{\vlabels\}}{\vlabels} -} -\and -\inferrule[other]{ - \vd \neq \DTypeDecl(\name, \TEnum(\vlabels, \Ignore)) -}{ - \defenumlabels(\vd) \typearrow \overname{\emptyset}{\vlabels} -} -\end{mathpar} - -\section{TypingRule.UseDecl \label{sec:TypingRule.UseDecl}} -\hypertarget{def-usedecl}{} -The function -\[ -\usedecl(\overname{\decl}{\vd}) \aslto \overname{\pow{\identifier}}{\ids} -\] -returns the set of identifiers $\ids$ which the declaration $\vd$ depends on. - -\subsection{Prose} -One of the following applies: -\begin{itemize} - \item All of the following apply (\textsc{D\_TypeDecl}): - \begin{itemize} - \item $\vd$ declares a type $\tty$ and fields $\fields$, that is, - $\DTypeDecl(\Ignore, \tty, \fields)$ (the first component is the name, which is being defined); - \item define $\ids$ as the union of applying $\usety$ to $\tty$ and applying $\usesubtypes$ to $\fields$. - \end{itemize} - - \item All of the following apply (\textsc{D\_GlobalStorage}): - \begin{itemize} - \item $\vd$ declares a global storage element with initial value $\initialvalue$ and type $\tty$; - \item define $\ids$ as the union of applying $\useexpr$ to $\initialvalue$ and applying $\usety$ to $\tty$. - \end{itemize} - - \item All of the following apply (\textsc{D\_Func}): - \begin{itemize} - \item $\vd$ declares a subprogram with arguments $\vargs$, \optional\ return type \\ - $\rettyopt$, parameters $\vparams$, and body statement $\body$; - \item define $\ids$ as the union of applying $\usety$ to each type of an argument in $\vargs$, - applying $\usety$ to $\rettyopt$, applying $\usety$ to each type of a parameter in $\vparams$, - and applying $\useexpr$ to $\body$. - \end{itemize} -\end{itemize} - -\subsection{Formally} -\begin{mathpar} -\inferrule[D\_TypeDecl]{}{ - \usedecl(\overname{\DTypeDecl(\Ignore, \tty, \fields)}{\vd}) \typearrow \overname{\usety(\tty) \cup \usesubtypes(\fields)}{\ids} -} -\and -\inferrule[D\_GlobalStorage]{ - \ids \eqdef \useexpr(\initialvalue) \cup \usety(\tty) -}{ - \usedecl(\overname{\DGlobalStorage(\{ - \GDinitialvalue: \initialvalue, - \GDty: \tty\ldots\})}{\vd}) - \typearrow \ids -} -\and -\inferrule[D\_Func]{ - { - \begin{array}{rcll} - \ids &\eqdef& \{ (\Ignore, \vt) \in \usety(\vt) : \id \} &\cup\\ - && \usety(\rettyopt) &\cup\\ - && \{ (\Ignore, \vt) \in \vparams : \usety(\vt) \} &\cup \\ - && \useexpr(\body) & - \end{array} - } -}{ - { - \usedecl\left(\overname{ - \DFunc\left( - \left\{ - \begin{array}{l} - \funcbody: \body,\\ - \funcargs: \vargs,\\ - \funcreturntype: \rettyopt,\\ - \funcparameters: \vparams,\\ - \ldots\\ - \end{array} - \right\} - \right)}{\vd} - \right) - \typearrow \ids - } -} -\end{mathpar} - -\section{TypingRule.UseTy \label{sec:TypingRule.UseTy}} -\hypertarget{def-usety}{} -The function -\[ -\usety(\overname{\ty \cup \langle\ty\rangle}{\vt}) \aslto \overname{\pow{\identifier}}{\ids} -\] -returns the set of identifiers $\ids$ which the type or \optional\ type $\vt$ depends on. - -\subsection{Prose} -One of the following applies: -\begin{itemize} - \item All of the following apply (\textsc{none}): - \begin{itemize} - \item $\vt$ is $\None$; - \item define $\ids$ as $\emptyset$. - \end{itemize} - - \item All of the following apply (\textsc{some}): - \begin{itemize} - \item $\vt$ is $\langle\tty\rangle$; - \item applying $\usety$ to $\tty$ yields $\ids$. - \end{itemize} - - \item All of the following apply (\textsc{simple}): - \begin{itemize} - \item $\vt$ is one of the following types: enumeration, Boolean, real, or string; - \item define $\ids$ as the empty set. - \end{itemize} - - \item All of the following apply (\textsc{t\_named}): - \begin{itemize} - \item $\vt$ is the named type for $\vs$; - \item define $\ids$ as the singleton set for $\vs$. - \end{itemize} - - \item All of the following apply (\textsc{int\_no\_constraints}): - \begin{itemize} - \item $\vt$ is either the unconstrained integer type or a \parameterizedintegertype; - \item define $\ids$ as the empty set. - \end{itemize} - - \item All of the following apply (\textsc{int\_well\_constrained}): - \begin{itemize} - \item $\vt$ is the well-constrained integer type with constraints $\vcs$; - \item define $\ids$ as the union of applying $\useconstraint$ to each constraint in $\vcs$. - \end{itemize} - - \item All of the following apply (\textsc{t\_tuple}): - \begin{itemize} - \item $\vt$ is the tuple type with list of types $\vli$; - \item define $\ids$ as the union of applying $\useconstraint$ to each constraint in $\vcs$. - \end{itemize} - - \item All of the following apply (\textsc{structured}): - \begin{itemize} - \item $\vt$ is a \structuredtype\ with fields $\fields$; - \item define $\ids$ as the union of applying $\usety$ to each field type in $\fields$. - \end{itemize} - - \item All of the following apply (\textsc{array\_expr}): - \begin{itemize} - \item $\vt$ is an array expression with length expression $\ve$ and element type $\vtp$; - \item define $\ids$ as the union of applying $\useexpr$ to $\ve$ and applying $\usety$ to $\vtp$. - \end{itemize} - - \item All of the following apply (\textsc{array\_enum}): - \begin{itemize} - \item $\vt$ is an array expression with enumeration type $\vs$ and element type $\vtp$; - \item define $\ids$ as the union of the singleton set for $\vs$ and applying $\usety$ to $\vtp$. - \end{itemize} - - \item All of the following apply (\textsc{t\_bits}): - \begin{itemize} - \item $\vt$ is a bitvector type with width expression $\ve$ and bitfields $\bitfields$; - \item define $\ids$ as the union of applying $\useexpr$ to $\ve$ and applying $\usebitfield$ to each field in $\bitfields$. - \end{itemize} -\end{itemize} - -\subsection{Formally} -\begin{mathpar} -\inferrule[none]{}{ - \usety(\overname{\None}{\vt}) \typearrow \overname{\emptyset}{\ids} -} -\and -\inferrule[some]{ - \usety(\tty) \typearrow \ids -}{ - \usety(\overname{\langle\tty\rangle}{\vt}) \typearrow \ids -} -\and -\inferrule[simple]{ - \astlabel(\vt) \in \{\TEnum, \TBool, \TReal, \TString\} -}{ - \usety(\vt) \typearrow \overname{\emptyset}{\ids} -} -\and -\inferrule[t\_named]{}{ - \usety(\overname{\TNamed(\vs)}{\vt}) \typearrow \overname{\{\vs\}}{\ids} -} -\end{mathpar} - -\begin{mathpar} -\inferrule[int\_no\_constraints]{ - \astlabel(\vc) \in \{\unconstrained, \parameterized\} -}{ - \usety(\overname{\TInt(\vc)}{\vt}) \typearrow \overname{\emptyset}{\ids} -} -\end{mathpar} - -\begin{mathpar} -\inferrule[int\_well\_constrained]{}{ - \usety(\overname{\TInt(\wellconstrained(\vcs))}{\vt}) \typearrow \overname{\bigcup_{\vc \in \vcs} \useconstraint(\vc)}{\ids} -} -\end{mathpar} - -\begin{mathpar} -\inferrule[t\_tuple]{}{ - \usety(\overname{\TTuple(\vli)}{\vt}) \typearrow \overname{\bigcup_{\vt \in \vli} \usety(\vt)}{\ids} -} -\end{mathpar} - -\begin{mathpar} -\inferrule[structured]{ - L \in \{\TRecord, \TException\}}{ - \usety(\overname{L(\fields)}{\vt}) \typearrow \overname{\bigcup_{(\Ignore, \vt) \in \fields} \usety(\vt)}{\ids} -} -\end{mathpar} - -\begin{mathpar} -\inferrule[array\_expr]{}{ - \usety(\overname{\TArray(\ArrayLengthExpr(\ve), \vtp)}{\vt}) \typearrow \overname{\useexpr(\ve) \cup \usety(\vtp)}{\ids} -} -\end{mathpar} - -\begin{mathpar} -\inferrule[array\_enum]{}{ - \usety(\overname{\TArray(\ArrayLengthEnum(\vs, \Ignore), \vtp)}{\vt}) \typearrow \overname{\{\vs\} \cup \usety(\vtp)}{\ids} -} -\end{mathpar} - -\begin{mathpar} -\inferrule[t\_bits]{}{ - \usety(\overname{\TBits(\ve, \bitfields)}{\vt}) \typearrow \overname{\useexpr(\ve) \cup \bigcup_{\vf \in\bitfields}\usebitfield(\vf)}{\ids} -} -\end{mathpar} - -\section{TypingRule.UseSubtypes \label{sec:TypingRule.UseSubtypes}} -\hypertarget{def-usesubtypes}{} -The function -\[ -\usesubtypes(\overname{\langle(\overname{\identifier}{\vx}\times\overname{\field^*}{\subfields})\rangle}{\fields}) \aslto \overname{\pow{\identifier}}{\ids} -\] -returns the set of identifiers $\ids$ which the \optional\ pair consisting of -identifier $\vx$ (the type being subtyped) and fields $\subfields$ depends on. - -\subsection{Prose} -One of the following applies: -\begin{itemize} - \item All of the following apply (\textsc{none}): - \begin{itemize} - \item $\fields$ is $\None$; - \item define $\ids$ as the empty set. - \end{itemize} - - \item All of the following apply (\textsc{some}): - \begin{itemize} - \item $\fields$ is $\langle(\vx, \subfields)\rangle$; - \item define $\ids$ as the union of the singleton set for $\vx$ and the union of applying $\usety$ - to each field type in $\subfields$. - \end{itemize} -\end{itemize} - -\subsection{Formally} -\begin{mathpar} -\inferrule[none]{}{ - \usesubtypes(\None) \typearrow \overname{\emptyset}{\ids} -} -\and -\inferrule[some]{ - \ids \eqdef \{\vx\} \cup \bigcup_{(\Ignore, \vt) \usety(\vt)} -}{ - \usesubtypes(\langle(\vx, \subfields)\rangle) \typearrow \ids -} -\end{mathpar} - -\section{TypingRule.UseExpr \label{sec:TypingRule.UseExpr}} -\hypertarget{def-useexpr}{} -The function -\[ -\useexpr(\overname{\expr}{\ve} \cup \langle\overname{\expr}{\ve}\rangle) \aslto \overname{\pow{\identifier}}{\ids} -\] -returns the set of identifiers $\ids$ which the expression or \optional\ expression $\ve$ depends on. - -\subsection{Prose} -One of the following applies: -\begin{itemize} - \item All of the following apply (\textsc{none}): - \begin{itemize} - \item $\ve$ is $\None$; - \item define $\ids$ as the empty set. - \end{itemize} - - \item All of the following apply (\textsc{some}): - \begin{itemize} - \item $\ve$ is $\langle\veone\rangle$; - \item applying $\useexpr$ to $\veone$ yields $\ids$. - \end{itemize} - - \item All of the following apply (\textsc{e\_literal}): - \begin{itemize} - \item $\ve$ is a literal expression; - \item define $\ids$ as the empty set. - \end{itemize} - - \item All of the following apply (\textsc{e\_atc}): - \begin{itemize} - \item $\ve$ is the typing assertion for expression $\ve$ and type $\tty$; - \item define $\ids$ as the union of applying $\useexpr$ to $\veone$ and applying $\usety$ to $\tty$. - \end{itemize} - - \item All of the following apply (\textsc{e\_var}): - \begin{itemize} - \item $\ve$ is the variable expression for identifier $\vx$; - \item define $\ids$ as the singleton set for $\vx$. - \end{itemize} - - \item All of the following apply (\textsc{e\_getarray}): - \begin{itemize} - \item $\ve$ is the \arrayaccess\ expression for base expression $\veone$ and index expression $\vetwo$; - \item define $\ids$ as the union of applying $\useexpr$ to $\veone$ and applying $\useexpr$ to $\vetwo$. - \end{itemize} - - \item All of the following apply (\textsc{e\_binop}): - \begin{itemize} - \item $\ve$ is the binary operation expression over expressions $\veone$ and $\vetwo$; - \item define $\ids$ as the union of applying $\useexpr$ to $\veone$ and applying $\useexpr$ to $\vetwo$. - \end{itemize} - - \item All of the following apply (\textsc{e\_unop}): - \begin{itemize} - \item $\ve$ is the unary operation expression over any unary operation and an expression $\veone$; - \item define $\ids$ as the union of applying $\useexpr$ to $\veone$. - \end{itemize} - - \item All of the following apply (\textsc{e\_call}): - \begin{itemize} - \item $\ve$ is the call expression of the subprogram named $\vx$ with argument expressions $\vargs$ and parameter expressions $\namedargs$; - \item define $\ids$ as the union of the singleton set for $\vx$, and the set obtained by applying $\useexpr$ to each expression in - $\vargs$ and each expression in $\namedargs$. - \end{itemize} - - \item All of the following apply (\textsc{e\_slice}): - \begin{itemize} - \item $\ve$ is the slicing expression over expression $\veone$ and slices $\slices$; - \item define $\ids$ as the union of applying $\useexpr$ to $\veone$ and applying $\useslice$ to each slice in $\slices$. - \end{itemize} - - \item All of the following apply (\textsc{e\_cond}): - \begin{itemize} - \item $\ve$ is the conditional expression over expressions $\veone$, $\vetwo$, and $\vethree$; - \item define $\ids$ as the union of applying $\useexpr$ to each of $\veone$, $\vetwo$, and $\vethree$. - \end{itemize} - - \item All of the following apply (\textsc{e\_getitem}): - \begin{itemize} - \item $\ve$ is the tuple access expression over expression $\veone$; - \item define $\ids$ as the application of $\useexpr$ to $\veone$. - \end{itemize} - - \item All of the following apply (\textsc{e\_getfield}): - \begin{itemize} - \item $\ve$ is the field access expression over expression $\veone$; - \item define $\ids$ as the application of $\useexpr$ to $\veone$. - \end{itemize} - - \item All of the following apply (\textsc{e\_getfields}): - \begin{itemize} - \item $\ve$ is the multiple field access expression over expression $\veone$; - \item define $\ids$ as the application of $\useexpr$ to $\veone$. - \end{itemize} - - \item All of the following apply (\textsc{e\_record}): - \begin{itemize} - \item $\ve$ is the record construction expression of type $\tty$ and field initializations $\vli$; - \item define $\ids$ as the union of applying of $\usety$ to $\tty$ and applying $\usety$ to each field type in $\vli$. - \end{itemize} - - \item All of the following apply (\textsc{e\_concat}): - \begin{itemize} - \item $\ve$ is the concatenation of expression $\ves$; - \item define $\ids$ as the union of applying of $\useexpr$ to each expression in $\ves$. - \end{itemize} - - \item All of the following apply (\textsc{e\_tuple}): - \begin{itemize} - \item $\ve$ is the tuple construction expression for the expressions $\ves$; - \item define $\ids$ as the union of applying of $\useexpr$ to each expression in $\ves$. - \end{itemize} - - \item All of the following apply (\textsc{e\_unknown}): - \begin{itemize} - \item $\ve$ is the unknown expression with type $\vt$; - \item define $\ids$ as the application of $\usety$ to $\vt$. - \end{itemize} - - \item All of the following apply (\textsc{e\_pattern}): - \begin{itemize} - \item $\ve$ is the pattern testing expression for subexpression $\veone$ and pattern $\vp$; - \item define $\ids$ as the union of applying $\useexpr$ to $\veone$ and applying $\usepattern$ to $\vp$. - \end{itemize} -\end{itemize} - -\subsection{Formally} -\begin{mathpar} -\inferrule[none]{}{ - \useexpr(\overname{\None}{\ve}) \typearrow \overname{\emptyset}{\ids} -} -\and -\inferrule[some]{ - \useexpr(\veone) \typearrow \ids -}{ - \useexpr(\overname{\langle\veone\rangle}{\ve}) \typearrow \overname{\emptyset}{\ids} -} -\and -\inferrule[e\_literal]{}{ - \useexpr(\overname{\ELiteral(\Ignore)}{\ve}) \typearrow \overname{\emptyset}{\ids} -} -\and -\inferrule[e\_atc]{}{ - \useexpr(\overname{\EATC(\veone, \tty)}{\ve}) \typearrow \overname{\useexpr(\veone) \cup \usety(\tty)}{\ids} -} -\and -\inferrule[e\_var]{}{ - \useexpr(\overname{\EVar(\vx)}{\ve}) \typearrow \overname{\{\vx\}}{\ids} -} -\end{mathpar} - -\begin{mathpar} -\inferrule[e\_getarray]{}{ - \useexpr(\overname{\EGetArray(\veone, \vetwo)}{\ve}) \typearrow \overname{\useexpr(\veone) \cup \useexpr(\vetwo)}{\ids} -} -\end{mathpar} - -\begin{mathpar} -\inferrule[e\_binop]{}{ - \useexpr(\overname{\EBinop(\Ignore, \veone, \vetwo)}{\ve}) \typearrow \overname{\useexpr(\veone) \cup \useexpr(\vetwo)}{\ids} -} -\end{mathpar} - -\begin{mathpar} -\inferrule[e\_unop]{}{ - \useexpr(\overname{\EUnop(\Ignore, \veone)}{\ve}) \typearrow \overname{\useexpr(\veone)}{\ids} -} -\end{mathpar} - -\begin{mathpar} -\inferrule[e\_call]{ - \ids \eqdef \{\vx\} \cup \bigcup_{\veone\in\vargs}\useexpr(\veone) \cup \bigcup_{(\Ignore, \vt)\in\namedargs}\usety(\vt) -}{ - \useexpr(\overname{\ECall(\vx, \vargs, \namedargs)}{\ve}) \typearrow \ids -} -\end{mathpar} - -\begin{mathpar} -\inferrule[e\_slice]{}{ - \useexpr(\overname{\ESlice(\veone, \slices)}{\ve}) \typearrow \overname{\useexpr(\veone) \cup \bigcup_{\vs\in\slices}\useslice(\vs)}{\ids} -} -\end{mathpar} - -\begin{mathpar} -\inferrule[e\_cond]{}{ - \useexpr(\overname{\ECond(\veone, \vetwo, \vethree)}{\ve}) \typearrow \overname{\useexpr(\veone) \cup \useexpr(\vetwo) \cup \useexpr(\vethree)}{\ids} -} -\end{mathpar} - -\begin{mathpar} -\inferrule[e\_getitem]{}{ - \useexpr(\overname{\EGetItem(\veone, \Ignore)}{\ve}) \typearrow \overname{\useexpr(\veone)}{\ids} -} -\and -\inferrule[e\_getfield]{}{ - \useexpr(\overname{\EGetField(\veone, \Ignore)}{\ve}) \typearrow \overname{\useexpr(\veone)}{\ids} -} -\end{mathpar} - -\begin{mathpar} -\inferrule[e\_getfields]{}{ - \useexpr(\overname{\EGetFields(\veone, \Ignore)}{\ve}) \typearrow \overname{\useexpr(\veone)}{\ids} -} -\end{mathpar} - -\begin{mathpar} -\inferrule[e\_record]{}{ - \useexpr(\overname{\ERecord(\tty, \vli)}{\ve}) \typearrow \overname{\usety(\tty) \cup \bigcup_{(\Ignore, \vt)\in\vli}\usety(\vt)}{\ids} -} -\end{mathpar} - -\begin{mathpar} -\inferrule[e\_concat]{}{ - \useexpr(\overname{\EConcat(\ves)}{\ve}) \typearrow \overname{\bigcup_{\veone\in\ves}\useexpr(\veone)}{\ids} -} -\end{mathpar} - -\begin{mathpar} -\inferrule[e\_tuple]{}{ - \useexpr(\overname{\EConcat(\ves)}{\ve}) \typearrow \overname{\bigcup_{\veone\in\ves}\useexpr(\veone)}{\ids} -} -\and -\inferrule[e\_unknown]{}{ - \useexpr(\overname{\EUnknown(\vt)}{\ve}) \typearrow \overname{\usety(\vt)}{\ids} -} -\end{mathpar} - -\begin{mathpar} -\inferrule[e\_pattern]{}{ - \useexpr(\overname{\EPattern(\veone, \vp)}{\ve}) \typearrow \overname{\useexpr(\veone) \cup \usepattern(\vp)}{\ids} -} -\end{mathpar} - -\section{TypingRule.UseLexpr \label{sec:TypingRule.UseLexpr}} -\hypertarget{def-uselexpr}{} -The function -\[ -\uselexpr(\overname{\lexpr}{\vle}) \aslto \overname{\pow{\identifier}}{\ids} -\] -returns the set of identifiers $\ids$ which the left-hand-side expression $\vle$ depends on. - -\subsection{Prose} -One of the following applies: -\begin{itemize} - \item All of the following apply (\textsc{le\_var}): - \begin{itemize} - \item $\vle$ is a left-hand-side variable expression for $\vx$; - \item define $\ids$ as the singleton set for $\vx$. - \end{itemize} - - \item All of the following apply (\textsc{le\_destructuring}): - \begin{itemize} - \item $\vle$ is a left-hand-side expression for assigning to a list of expressions $\vles$, - that is $\LEDestructuring(\vles)$; - \item define $\ids$ as the union of applying $\uselexpr$ to each expression in $\vles$. - \end{itemize} - - \item All of the following apply (\textsc{le\_concat}): - \begin{itemize} - \item $\vle$ is a left-hand-side concatenation of the list of expressions $\vles$; - \item define $\ids$ as the union of applying $\uselexpr$ to each expression in $\vles$. - \end{itemize} - - \item All of the following apply (\textsc{le\_discard}): - \begin{itemize} - \item $\vle$ is a left-hand-side discard expression; - \item define $\ids$ as the empty set. - \end{itemize} - - \item All of the following apply (\textsc{le\_setarray}): - \begin{itemize} - \item $\vle$ is a left-hand-side array update of the array given by the expression $\veone$ and index expression $\vetwo$; - \item define $\ids$ as the union of applying $\uselexpr$ to $\veone$ and applying $\useexpr$ to $\vetwo$. - \end{itemize} - - \item All of the following apply (\textsc{le\_setfield}): - \begin{itemize} - \item $\vle$ is a left-hand-side field update of the record given by the expression $\veone$; - \item define $\ids$ as the application of $\uselexpr$ to $\veone$. - \end{itemize} - - \item All of the following apply (\textsc{le\_setfields}): - \begin{itemize} - \item $\vle$ is a left-hand-side multiple field updates of the record given by the expression $\veone$; - \item define $\ids$ as the application of $\uselexpr$ to $\veone$. - \end{itemize} - - \item All of the following apply (\textsc{le\_slice}): - \begin{itemize} - \item $\vle$ is a left-hand-side slicing of the expression $\veone$ by slices $\slices$; - \item define $\ids$ as the union of applying $\uselexpr$ to $\veone$ and applying $\useslice$ to each slice in $\slices$. - \end{itemize} -\end{itemize} - -\subsection{Formally} -\begin{mathpar} -\inferrule[le\_var]{}{ - \uselexpr(\overname{\LEVar(\vx)}{\vle}) \typearrow \overname{\vx}{\ids} -} -\and -\inferrule[le\_destructuring]{}{ - \uselexpr(\overname{\LEDestructuring(\vles)}{\vle}) \typearrow \overname{\bigcup_{\ve\in\vles}\uselexpr(\ve)}{\ids} -} -\and -\inferrule[le\_concat]{}{ - \uselexpr(\overname{\LEConcat(\vles)}{\vle}) \typearrow \overname{\bigcup_{\ve\in\vles}\uselexpr(\ve)}{\ids} -} -\and -\inferrule[le\_discard]{}{ - \uselexpr(\overname{\LEDiscard}{\vle}) \typearrow \overname{\emptyset}{\ids} -} -\end{mathpar} - -\begin{mathpar} -\inferrule[le\_setarray]{}{ - \uselexpr(\overname{\LESetArray(\veone, \vetwo)}{\vle}) \typearrow \overname{\uselexpr(\veone) \cup \useexpr(\vetwo)}{\ids} -} -\end{mathpar} - -\begin{mathpar} -\inferrule[le\_setfield]{}{ - \uselexpr(\overname{\LESetField(\veone, \Ignore)}{\vle}) \typearrow \overname{\uselexpr(\veone)}{\ids} -} -\end{mathpar} - -\begin{mathpar} -\inferrule[le\_setfields]{}{ - \uselexpr(\overname{\LESetFields(\veone, \Ignore)}{\vle}) \typearrow \overname{\uselexpr(\veone)}{\ids} -} -\end{mathpar} - -\begin{mathpar} -\inferrule[le\_slice]{}{ - \uselexpr(\overname{\LESlice(\veone, \slices)}{\vle}) \typearrow \overname{\uselexpr(\veone) \cup \bigcup_{\vs\in\slices}\useslice(\vs)}{\ids} -} -\end{mathpar} - -\section{TypingRule.UsePattern \label{sec:TypingRule.UsePattern}} -\hypertarget{def-usepattern}{} -The function -\[ -\usepattern(\overname{\pattern}{\vp}) \aslto \overname{\pow{\identifier}}{\ids} -\] -returns the set of identifiers $\ids$ which the declaration $\vd$ depends on. - -\subsection{Prose} -One of the following applies: -\begin{itemize} - \item All of the following apply (\textsc{mask\_all}): - \begin{itemize} - \item $\vp$ is either a mask pattern ($\PatternMask$) or a match-all pattern ($\PatternAll$); - \item define $\ids$ as the empty set. - \end{itemize} - - \item All of the following apply (\textsc{tuple}): - \begin{itemize} - \item $\vp$ is a tuple pattern list of patterns $\vli$; - \item define $\ids$ as the union of the application of $\usepattern$ for each pattern in $\vli$. - \end{itemize} - - \item All of the following apply (\textsc{any}): - \begin{itemize} - \item $\vp$ is a pattern for matching any of the patterns in the list of patterns $\vli$; - \item define $\ids$ as the union of the application of $\usepattern$ for each pattern in $\vli$. - \end{itemize} - - \item All of the following apply (\textsc{single}): - \begin{itemize} - \item $\vp$ is a pattern for matching the expression $\ve$; - \item define $\ids$ as the application of $\useexpr$ to $\ve$. - \end{itemize} - - \item All of the following apply (\textsc{geq}): - \begin{itemize} - \item $\vp$ is a pattern for testing greater-or-equal with respect to the expression $\ve$; - \item define $\ids$ as the application of $\useexpr$ to $\ve$. - \end{itemize} - - \item All of the following apply (\textsc{leq}): - \begin{itemize} - \item $\vp$ is a pattern for testing less-than-or-equal with respect to the expression $\ve$; - \item define $\ids$ as the application of $\useexpr$ to $\ve$. - \end{itemize} - - \item All of the following apply (\textsc{not}): - \begin{itemize} - \item $\vp$ is a pattern negating the pattern $\vpone$; - \item define $\ids$ as the application of $\usepattern$ to $\vpone$. - \end{itemize} - - \item All of the following apply (\textsc{range}): - \begin{itemize} - \item $\vp$ is a pattern for testing the range of expressions from $\veone$ to $\vetwo$; - \item define $\ids$ as the union of the application of $\useexpr$ to both $\veone$ and $\vetwo$. - \end{itemize} -\end{itemize} - -\subsection{Formally} -\begin{mathpar} -\inferrule[mask\_all]{ - \astlabel(\vp) \in \{\PatternMask, \PatternAll\} -}{ - \usepattern(\vp) \typearrow \overname{\emptyset}{\ids} -} -\end{mathpar} - -\begin{mathpar} -\inferrule[tuple]{}{ - \usepattern(\overname{\PatternTuple(\vli)}{\vp}) \typearrow \overname{\bigcup_{\vpone\in\vli}\usepattern(\vpone)}{\ids} -} -\end{mathpar} - -\begin{mathpar} -\inferrule[any]{}{ - \usepattern(\overname{\PatternAny(\vli)}{\vp}) \typearrow \overname{\bigcup_{\vpone\in\vli}\usepattern(\vpone)}{\ids} -} -\end{mathpar} - -\begin{mathpar} -\inferrule[single]{}{ - \usepattern(\overname{\PatternSingle(\ve)}{\vp}) \typearrow \overname{\useexpr(\ve)}{\ids} -} -\end{mathpar} - -\begin{mathpar} -\inferrule[geq]{}{ - \usepattern(\overname{\PatternGeq(\ve)}{\vp}) \typearrow \overname{\useexpr(\ve)}{\ids} -} -\end{mathpar} - -\begin{mathpar} -\inferrule[leq]{}{ - \usepattern(\overname{\PatternLeq(\ve)}{\vp}) \typearrow \overname{\useexpr(\ve)}{\ids} -} -\end{mathpar} - -\begin{mathpar} -\inferrule[not]{}{ - \usepattern(\overname{\PatternNot(\vpone)}{\vp}) \typearrow \overname{\usepattern(\vpone)}{\ids} -} -\end{mathpar} - -\begin{mathpar} -\inferrule[range]{}{ - \usepattern(\overname{\PatternRange(\veone, \vetwo)}{\vp}) \typearrow \overname{\useexpr(\veone) \cup \useexpr(\vetwo)}{\ids} -} -\end{mathpar} - -\section{TypingRule.UseSlice \label{sec:TypingRule.UseSlice}} -\hypertarget{def-useslice}{} -The function -\[ -\useslice(\overname{\slice}{\vs}) \aslto \overname{\pow{\identifier}}{\ids} -\] -returns the set of identifiers $\ids$ which the slice $\vs$ depends on. - -\subsection{Prose} -One of the following applies: -\begin{itemize} - \item All of the following apply (\textsc{single}): - \begin{itemize} - \item $\vs$ is the slice at the position given by the expression $\ve$; - \item define $\ids$ as the application of $\useexpr$ to $\ve$. - \end{itemize} - - \item All of the following apply (\textsc{start\_length\_rang}): - \begin{itemize} - \item $\vs$ is a slice given by the pair of expressions $\veone$ and $\vetwo$; - \item define $\ids$ as the union of applying $\useexpr$ to both $\veone$ and $\vetwo$. - \end{itemize} -\end{itemize} - -\subsection{Formally} -\begin{mathpar} -\inferrule[single]{}{ - \useslice(\overname{\SliceSingle(\ve)}{\vs}) \typearrow \overname{\useexpr(\ve)}{\ids} -} -\and -\inferrule[star\_length\_range]{ - L \in \{\SliceStar, \SliceLength, \SliceRange\} -}{ - \useslice(\overname{L(\veone, \vetwo)}{\vs}) \typearrow \overname{\useexpr(\veone) \cup \useexpr(\vetwo)}{\ids} -} -\end{mathpar} - -\section{TypingRule.UseBitfield \label{sec:TypingRule.UseBitfield}} -\hypertarget{def-usebitfield}{} -The function -\[ -\usebitfield(\overname{\decl}{\vbf}) \aslto \overname{\pow{\identifier}}{\ids} -\] -returns the set of identifiers $\ids$ which the bitfield $\vbf$ depends on. - -\subsection{Prose} -One of the following applies: -\begin{itemize} - \item All of the following apply (\textsc{simple}): - \begin{itemize} - \item $\vbf$ is the single field with slices $\slices$; - \item define $\ids$ as the union of applying $\useslice$ to each slice in $\slices$. - \end{itemize} - - \item All of the following apply (\textsc{nested}): - \begin{itemize} - \item $\vbf$ is the nested bitfield with slices $\slices$ and bitfields $\bitfields$; - \item define $\ids$ as the union of applying $\useslice$ to each slice in $\slices$ and applying - $\usebitfield$ to each bitfield in $\bitfields$. - \end{itemize} - - \item All of the following apply (\textsc{type}): - \begin{itemize} - \item $\vbf$ is the typed bitfield with slices $\slices$ and type $\tty$; - \item define $\ids$ as the union of applying $\useslice$ to each slice in $\slices$ and applying - $\usety$ to $\tty$. - \end{itemize} -\end{itemize} - -\subsection{Formally} -\begin{mathpar} -\inferrule[simple]{}{ - \usebitfield(\overname{\BitFieldSimple(\Ignore, \slices)}{\vbf}) \typearrow \overname{\bigcup_{\vs\in\slices}\useslice(\vs)}{\ids} -} -\and -\inferrule[nested]{ - \ids \eqdef \bigcup_{\bfone\in\bitfields}\usebitfield(\vs) \cup \bigcup_{\vs\in\slices}\useslice(\vs) -}{ - \usebitfield(\overname{\BitFieldNested(\Ignore, \slices, \bitfields)}{\vbf}) \typearrow \ids -} -\and -\inferrule[type]{ - \ids \eqdef \bigcup_{\vs\in\slices}\useslice(\vs) \cup \usety(\tty) -}{ - \usebitfield(\overname{\BitFieldType(\Ignore, \slices, \tty)}{\vbf}) \typearrow \ids -} -\end{mathpar} - -\section{TypingRule.UseConstraint \label{sec:TypingRule.UseConstraint}} -\hypertarget{def-useconstraint}{} -The function -\[ -\useconstraint(\overname{\intconstraint}{\vc}) \aslto \overname{\pow{\identifier}}{\ids} -\] -returns the set of identifiers $\ids$ which the integer constraint $\vc$ depends on. - -\subsection{Prose} -One of the following applies: -\begin{itemize} - \item All of the following apply (\textsc{exact}): - \begin{itemize} - \item $\vc$ is the single-value expression constraint with expression $\ve$; - \item define $\ids$ as the application of $\useexpr$ to $\ve$. - \end{itemize} - - \item All of the following apply (\textsc{range}): - \begin{itemize} - \item $\vc$ is the range constraint with expressions $\veone$ and $\vetwo$; - \item define $\ids$ as the union of applying $\useexpr$ to both $\veone$ and $\vetwo$. - \end{itemize} -\end{itemize} - -\subsection{Formally} -\begin{mathpar} -\inferrule[exact]{}{ - \useconstraint(\overname{\ConstraintExact(\ve)}{\vc}) \typearrow \overname{\useexpr(\ve)}{\ids} -} -\and -\inferrule[range]{}{ - \useconstraint(\overname{\ConstraintRange(\veone, \vetwo)}{\vc}) \typearrow \overname{\useexpr(\veone) \cup \useexpr(\vetwo)}{\ids} -} -\end{mathpar} - -\section{TypingRule.UseStmt \label{sec:TypingRule.UseStmt}} -\hypertarget{def-usestmt}{} -The function -\[ -\usestmt(\overname{\stmt}{\vs}) \aslto \overname{\pow{\identifier}}{\ids} -\] -returns the set of identifiers $\ids$ which the statement $\vs$ depends on. - -\subsection{Prose} -One of the following applies: -\begin{itemize} - \item All of the following apply (\textsc{pass\_return\_none\_throw\_none}): - \begin{itemize} - \item $\vs$ is either a pass statement $\SPass$, a return-nothing statement $\SReturn(\None)$, - or a throw-nothing statement ($\SThrow(\None)$); - \item define $\ids$ as the empty set. - \end{itemize} - - \item All of the following apply (\textsc{s\_seq}): - \begin{itemize} - \item $\vs$ is a sequencing statement for $\vsone$ and $\vstwo$; - \item define $\ids$ as the union of applying $\usestmt$ to both $\vsone$ and $\vstwo$. - \end{itemize} - - \item All of the following apply (\textsc{assert\_return\_some}): - \begin{itemize} - \item $\vs$ is either an assertion with expression $\ve$ or a return statement with expression $\ve$; - \item define $\ids$ as the application of $\useexpr$ to $\ve$. - \end{itemize} - - \item All of the following apply (\textsc{s\_assign}): - \begin{itemize} - \item $\vs$ is an assignment statement with left-hand-side $\vle$ and right-hand-side $\ve$; - \item define $\ids$ as the union of applying $\uselexpr$ to $\vle$ and $\useexpr$ to $\ve$. - \end{itemize} - - \item All of the following apply (\textsc{s\_call}): - \begin{itemize} - \item $\vs$ is a call statement for the subprogram with name $\vx$, arguments $\vargs$, and list of - pairs consisting of a parameter identifier and associated expression $\namedargs$; - \item define $\ids$ as the union of the singleton set for $\vx$, applying $\useexpr$ to - every expression in $\vargs$ and applying $\useexpr$ to every expression associated with - a parameter in $\namedargs$. - \end{itemize} - - \item All of the following apply (\textsc{s\_cond}): - \begin{itemize} - \item $\vs$ is the conditional statement with expression $\ve$ and statements $\vsone$ and $\vstwo$; - \item define $\ids$ as the union of applying $\useexpr$ to $\ve$ and $\usestmt$ to both of $\vsone$ and $\vstwo$. - \end{itemize} - - \item All of the following apply (\textsc{s\_case}): - \begin{itemize} - \item $\vs$ is the case statement with expression $\ve$ and case list $\vcases$; - \item define $\ids$ as the union of applying $\useexpr$ to $\ve$ and $\usecase$ to every case in $\vcases$. - \end{itemize} - - \item All of the following apply (\textsc{s\_for}): - \begin{itemize} - \item $\vs$ is the for statement $\SFor\left\{\begin{array}{rcl} - \Forindexname &:& \Ignore\\ - \Forstarte &:& \vstarte\\ - \fordirection &:& \vdirection\\ - \Forende &:& \vende\\ - \Forbody &:& \vbody\\ - \Forlimit &:& \vlimit - \end{array}\right\}$; - \item define $\ids$ as the union of applying $\useexpr$ to $\vlimit$, $\vstarte$, and $\vende$ and applying $\usestmt$ to $\vsone$. - \end{itemize} - - \item All of the following apply (\textsc{while\_repeat}): - \begin{itemize} - \item $\vs$ is either a while statement or repeat statement, each with expression $\ve$, body statement $\vsone$, - and optional limit expression $\vlimit$; - \item define $\ids$ as the union of applying $\useexpr$ to $\vlimit$ and to $\ve$, and applying $\usestmt$ to $\vsone$. - \end{itemize} - - \item All of the following apply (\textsc{s\_decl}): - \begin{itemize} - \item $\vs$ is a declaration statement with local declaration item $\ldi$ and \optional\ initialization expression $\ve$; - \item define $\ids$ as the union of applying $\useexpr$ to $\ve$ and $\useldi$ to $\ldi$. - \end{itemize} - - \item All of the following apply (\textsc{s\_try}): - \begin{itemize} - \item $\vs$ is a try statement with statement $\vsone$, catcher list $\catchers$, and otherwise statement $\vstwo$; - \item define $\ids$ as the union of applying $\usestmt$ to both $\vsone$ and $\vstwo$ and $\usecatcher$ to - every catcher in $\catchers$. - \end{itemize} - - \item All of the following apply (\textsc{s\_print}): - \begin{itemize} - \item $\vs$ is a print statement with list of expressions $\vargs$; - \item define $\ids$ as the union of applying $\useexpr$ to each expression in $\vargs$. - \end{itemize} -\end{itemize} - -\subsection{Formally} -\begin{mathpar} -\inferrule[pass\_return\_none\_throw\_none]{ - \vs = \SPass \lor \vs = \SReturn(\None) \lor \vs = \SThrow(\None) -}{ - \usestmt(\vs) \typearrow \overname{\emptyset}{\ids} -} -\end{mathpar} - -\begin{mathpar} -\inferrule[s\_seq]{}{ - \usestmt(\overname{\SSeq(\vsone, \vstwo)}{\vs}) \typearrow \overname{\usestmt(\vsone)\cup\usestmt(\vstwo)}{\ids} -} -\and -\inferrule[assert\_return\_some]{ - \vs = \SAssert(\ve) \lor \SReturn(\langle\ve\rangle) -}{ - \usestmt(\vs) \typearrow \overname{\useexpr(\ve)}{\ids} -} -\end{mathpar} - -\begin{mathpar} - -\inferrule[s\_assign]{}{ - \usestmt(\overname{\SAssign(\vle, \ve)}{\vs}) \typearrow \overname{\uselexpr(\vle) \cup \useexpr(\ve)}{\ids} -} -\end{mathpar} - -\begin{mathpar} -\inferrule[s\_call]{ - \ids \eqdef \{\vx\} \cup \bigcup_{\ve\in\vargs}\useexpr(\ve) \cup \bigcup_{(\Ignore, \ve)\in\namedargs} \useexpr(\ve) -}{ - \usestmt(\overname{\SCall(\vx, \vargs, \namedargs)}{\vs}) \typearrow \ids -} -\end{mathpar} - -\begin{mathpar} -\inferrule[s\_cond]{}{ - \usestmt(\overname{\SCond(\ve, \vsone, \vstwo)}{\vs}) \typearrow \overname{\useexpr(\ve) \cup \usestmt(\vsone) \cup \usestmt(\vstwo)}{\ids} -} -\end{mathpar} - -\begin{mathpar} -\inferrule[s\_case]{}{ - \usestmt(\overname{\SCase(\ve, \vcases)}{\vs}) \typearrow \overname{\useexpr(\ve) \cup \bigcup_{\vc\in\vcases}\usecase(\vc)}{\ids} -} -\end{mathpar} - -\begin{mathpar} -\inferrule[s\_for]{ - \ids \eqdef \useexpr(\vlimit) \cup \useexpr(\vstarte) \cup \useexpr(\vende) \cup \usestmt(\vbody) -}{ - { - \usestmt\left(\overname{\SFor\left\{\begin{array}{rcl} - \Forindexname &:& \Ignore\\ - \Forstarte &:& \vstarte\\ - \fordirection &:& \vdirection\\ - \Forende &:& \vende\\ - \Forbody &:& \vbody\\ - \Forlimit &:& \vlimit - \end{array}\right\}}{\vs}\right) \typearrow \ids - } -} -\and -\inferrule[while\_repeat]{ - \vs = \SWhile(\ve, \vlimit, \vs) \lor \vs = \SRepeat(\vs, \ve, \vlimit) -}{ - \usestmt(\vs) \typearrow \overname{\useexpr(\vlimit) \cup \useexpr(\ve) \cup \usestmt(\vsone)}{\ids} -} -\end{mathpar} - -\begin{mathpar} -\inferrule[s\_decl]{}{ - \usestmt(\overname{\SDecl(\Ignore, \ldi, \ve)}\vs) \typearrow \overname{\useexpr(\ve) \cup \useldi(\ldi)}{\ids} -} -\end{mathpar} - -\begin{mathpar} -\inferrule[s\_throw\_some]{}{ - \usestmt(\overname{\SThrow(\langle\ve\rangle)}\vs) \typearrow \overname{\useexpr(\ve)}{\ids} -} -\end{mathpar} - -\begin{mathpar} -\inferrule[s\_try]{ - \ids \eqdef \usestmt(\vsone) \cup \bigcup_{\vc\in\catchers}\usecatcher(\vc) \cup \usestmt(\vstwo) -}{ - \usestmt(\overname{\STry(\vsone, \catchers, \vstwo)}{\vs}) \typearrow \ids -} -\end{mathpar} - -\begin{mathpar} -\inferrule[s\_print]{}{ - \usestmt(\overname{\SPrint(\vargs)}{\vs}) \typearrow \overname{\bigcup_{\ve\in\vargs}\useexpr(\ve)}{\ids} -} -\end{mathpar} - -\section{TypingRule.UseLDI \label{sec:TypingRule.UseLDI}} -\hypertarget{def-useldi}{} -The function -\[ -\useldi(\overname{\localdeclitem}{\ldi}) \aslto \overname{\pow{\identifier}}{\ids} -\] -returns the set of identifiers $\ids$ which the local declaration item $\ldi$ depends on. - -\subsection{Prose} -One of the following applies: -\begin{itemize} - \item All of the following apply (\textsc{discard}): - \begin{itemize} - \item $\ldi$ is a discarding declaration; - \item define $\ids$ as the empty set. - \end{itemize} - - \item All of the following apply (\textsc{typed}): - \begin{itemize} - \item $\ldi$ is a typed declaration for the local declaration item $\ldione$ and type $\vt$; - \item define $\ids$ as the union of applying $\useldi$ to $\ldione$ and $\usety$ to $\vt$. - \end{itemize} - - \item All of the following apply (\textsc{tuple}): - \begin{itemize} - \item $\ldi$ is a multi-variable declaration for the list of local declarations $\ldis$; - \item define $\ids$ as the union of applying $\useldi$ to each local declaration item in $\ldis$. - \end{itemize} -\end{itemize} - -\subsection{Formally} -\begin{mathpar} -\inferrule[discard]{}{ - \useldi(\overname{\LDIDiscard}{\ldi}) \typearrow \overname{\emptyset}{\ids} -} -\end{mathpar} - -\begin{mathpar} -\inferrule[typed]{}{ - \useldi(\overname{\LDITyped(\ldione, \vt)}{\ldi}) \typearrow \overname{\useldi(\ldione) \cup \usety(\vt)}{\ids} -} -\end{mathpar} - -\begin{mathpar} -\inferrule[tuple]{}{ - \useldi(\overname{\LDITuple(\ldis)}{\ldi}) \typearrow \overname{\bigcup_{\ldione\in\ldis}\useldi(\ldione)}{\ids} -} -\end{mathpar} - -\section{TypingRule.UseCase \label{sec:TypingRule.UseCase}} -\hypertarget{def-usecase}{} -The function -\[ -\usecase(\overname{\casealt}{\vc}) \aslto \overname{\pow{\identifier}}{\ids} -\] -returns the set of identifiers $\ids$ which the case alternative $\vc$ depends on. - -\subsection{Prose} -All of the following apply: -\begin{itemize} - \item $\vc$ is the case alternative for the pattern $\pattern$, \optional\ \texttt{where} expression - $\veopt$ and \texttt{otherwise} statement $\vs$; - \item define $\ids$ as the union of applying $\usepattern$ to $\pattern$, applying $\useexpr$ to $\veopt$, - and applying $\usestmt$ to $\vs$. -\end{itemize} - -\subsection{Formally} -\begin{mathpar} -\inferrule{ - \ids \eqdef \usepattern(\pattern) \cup \useexpr(\veopt) \cup \usestmt(\vs) -}{ - \usecase(\overname{\{ \CasePattern : \pattern, \CaseWhere : \veopt, \CaseStmt : \vs \}}{\vc}) \typearrow \ids -} -\end{mathpar} - -\section{TypingRule.UseCatcher \label{sec:TypingRule.UseCatcher}} -\hypertarget{def-usecatcher}{} -The function -\[ -\usecatcher(\overname{\catcher}{\vc}) \aslto \overname{\pow{\identifier}}{\ids} -\] -returns the set of identifiers $\ids$ which the try statement catcher $\vc$ depends on. - -\subsection{Prose} -All of the following apply: -\begin{itemize} - \item $\vc$ is a case alternative with type $\tty$ and statement $\vs$; - \item define $\ids$ as the union of applying $\usety$ to $\ty$ and applying $\usestmt$ to $\vs$. -\end{itemize} - -\subsection{Formally} -\begin{mathpar} -\inferrule{}{ - \usecatcher(\overname{(\Ignore, \tty, \vs)}{\vc}) \typearrow \overname{\usety(\tty) \cup \usestmt(\vs)}{\ids} -} -\end{mathpar} - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -\chapter{Static Evaluation \label{chap:staticevaluation}} -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - -In this chapter, we define how to statically evaluate a subset of expressions -and how to apply basic operators to literals via the following rules: -\begin{itemize} - \item TypingRule.StaticEval (see \secref{TypingRule.StaticEval}) - \item TypingRule.UnopLiterals (see \secref{TypingRule.UnopLiterals}) - \item TypingRule.BinopLiterals (see \secref{TypingRule.BinopLiterals}) -\end{itemize} -We also define the following helper rules: -\begin{itemize} - \item TypingRule.SlicesToPositions (see \secref{TypingRule.SlicesToPositions}) - \item TypingRule.SliceToPositions (see \secref{TypingRule.SliceToPositions}) - \item TypingRule.EvalToInt (see \secref{TypingRule.EvalToInt}) - \item TypingRule.ExtractSlice (see \secref{TypingRule.ExtractSlice}) -\end{itemize} - -\hypertarget{def-unsupportedexpression} -In this chapter and the following ones, we use the special value $\CannotBeTransformed$ -to represent a failure in transforming an expression into a desired form (the specific -desired form varies according to the functions utilizing this value). - -\hypertarget{def-staticeval}{} -\section{TypingRule.StaticEval \label{sec:TypingRule.StaticEval}} -The function -\[ - \staticeval(\overname{\staticenvs}{\tenv} \aslsep \overname{\expr}{\ve}) \;\aslto\; - \overname{\literals}{\vv} \cup - \{\CannotBeTransformed\} - \overname{\TTypeError}{\TypeErrorConfig} -\] -evaluates an expression $\ve$, from a restricted subset of all expressions, -in the static environment $\tenv$, returning a literal $\vv$. -If $\ve$ is not in the restricted set of expressions or cannot be statically evaluated to a compile-time -constant, the result is $\CannotBeTransformed$. -\ProseOtherwiseTypeError - -\subsection{Prose} -One of the following applies: -\begin{itemize} - \item All of the following apply (\textsc{e\_literal}): - \begin{itemize} - \item $\ve$ is the literal expression for the literal $\vv$, that is, $\ELiteral(\vv)$. - \end{itemize} - - \item All of the following apply (\textsc{e\_var\_constant}): - \begin{itemize} - \item $\ve$ is a variable expression with the identifier $\vx$, that is, $\EVar(\vx)$; - \item determining whether $\vx$ is bound to a constant in $\tenv$ via $\lookupconstant$ yields the literal $\vv$. - \end{itemize} - - \item All of the following apply (\textsc{e\_var\_non\_constant}): - \begin{itemize} - \item $\ve$ is a variable expression with the identifier $\vx$, that is, $\EVar(\vx)$; - \item determining whether $\vx$ is bound to a constant in $\tenv$ via $\lookupconstant$ yields $\bot$ - (that is, $\vx$ is not bound to a constant); - \item checking whether $\vx$ is defined in $\tenv$ yields $\True$\ProseOrTypeError; - \item the result is $\CannotBeTransformed$. - \end{itemize} - - \item All of the following apply (\textsc{e\_binop}): - \begin{itemize} - \item $\ve$ is a binary operation expression with operator $\op$ and operand expressions $\veone$ and $\vetwo$, - that is, $\EBinop(\op, \veone, \vetwo)$; - \item applying $\staticeval$ to $\veone$ in $\tenv$ yields the literal $\vvone$\ProseTerminateAs{\CannotBeTransformed, \TypeErrorConfig}; - \item applying $\staticeval$ to $\vetwo$ in $\tenv$ yields the literal $\vvtwo$\ProseTerminateAs{\CannotBeTransformed, \TypeErrorConfig}; - \item applying $\op$ to $\vvone$ and $\vvtwo$ via $\binopliterals$ yields $\vv$\ProseOrTypeError. - \end{itemize} - - \item All of the following apply (\textsc{e\_unop}): - \begin{itemize} - \item $\ve$ is a unary operation expression with operator $\op$ and operand expression $\veone$, - that is, $\EUnop(\op, \veone)$; - \item applying $\staticeval$ to $\veone$ in $\tenv$ yields the literal $\vvone$\ProseTerminateAs{\CannotBeTransformed, \TypeErrorConfig}; - \item applying $\op$ to $\vvone$ via $\unopliterals$ yields $\vv$\ProseOrTypeError. - \end{itemize} - - \item All of the following apply (\textsc{e\_slice\_int}): - \begin{itemize} - \item $\ve$ is a slicing expression of the integer literal for $\vi$ and slice list $\vslices$, that is, - $\ESlice(\lint(\vi), \vslices)$; - \item obtaining the indices of the slice list $\vslices$ in $\tenv$ via $\typingslicestopositions$ - yields $\positions$\ProseOrTypeError; - \item $\posmax$ is the maximum index in $\positions$; - \item converting the first $\posmax+1$ digits of the binary representation of $\vi$ into a bitvector - via $\inttobits$ yields $\bvone$; - \item extracting the slice of $\bvone$ given by $\positions$ yields $\bvtwo$\ProseOrTypeError; - \item $\vv$ is the bitvector literal for $\bvtwo$. - \end{itemize} - - \item All of the following apply (\textsc{e\_slice\_bitvector}): - \begin{itemize} - \item $\ve$ is a slicing expression of the bitvector literal for $\bv$ and slice list $\vslices$, that is, - $\ESlice(\lbitvector(\bv), \vslices)$; - \item obtaining the indices of the slice list $\vslices$ in $\tenv$ via $\typingslicestopositions$ - yields $\positions$\ProseOrTypeError; - \item $\posmax$ is the maximum index in $\positions$; - \item checking that the length of $\bv$ is greater than $\posmax$ (which is $0$-based) yields $\True$\ProseOrTypeError; - \item extracting the slice of $\bv$ given by $\positions$ yields $\bvtwo$\ProseOrTypeError; - \item $\vv$ is the bitvector literal for $\bvtwo$. - \end{itemize} - - \item All of the following apply (\textsc{e\_slice\_type\_error}): - \begin{itemize} - \item $\ve$ is a slicing expression of subexpression $\veone$ and slice list $\vslices$, that is, $\ESlice(\veone, \vslices)$; - \item $\veone$ is neither an integer literal nor a bitvector literal; - \item the result is a type error indicating that either an integer literal or a bitvector literal were expected. - \end{itemize} - - \item All of the following apply (\textsc{e\_cond}): - \begin{itemize} - \item $\ve$ is a conditional expression with condition subexpression $\econd$ and subexpressions $\veone$ (true case) - and $\vetwo$ (false case), that is, $\ECond(\econd, \veone, \vetwo)$; - \item evaluating $\econd$ in $\tenv$ either yields a Boolean literal $\vb$ or a type error or $\CannotBeTransformed$, - either of which short-circuits the rule; - \item $\vep$ is $\veone$ if $\vb$ is $\True$ and $\vetwo$ otherwise; - \item the result is given by applying $\staticeval$ to $\vep$ in $\tenv$. - \end{itemize} - - \item All of the following apply (\textsc{unsupported}): - \begin{itemize} - \item $\ve$ is an expression that is not one of the following: a literal, a variable, a binary operation expression, - a unary operation expression, a slice expression, and a conditional expression; - \item the result is a type error indicating that $\ve$ is not an expression that is supported - for static evaluation. - \end{itemize} -\end{itemize} - -\subsection{Formally} -\begin{mathpar} -\inferrule[e\_literal]{} -{ - \staticeval(\tenv, \overname{\ELiteral(\vv)}{\ve}) \typearrow \vv -} -\end{mathpar} - -\begin{mathpar} -\inferrule[e\_var\_constant]{ - \lookupconstant(\tenv, \vx) \typearrow \vv -}{ - \staticeval(\tenv, \overname{\EVar(\vx)}{\ve}) \typearrow \vv -} -\and -\inferrule[e\_var\_non\_constant]{ - \lookupconstant(\tenv, \vx) \typearrow \bot\\ - \isundefined(\tenv, \vx) \typearrow \vb\\ - \checktrans{\neg\vb}{\UndefinedIdentifier} \typearrow \True \OrTypeError -}{ - \staticeval(\tenv, \overname{\EVar(\vx)}{\ve}) \typearrow \CannotBeTransformed -} -\end{mathpar} - -\begin{mathpar} -\inferrule[e\_binop]{ - \staticeval(\tenv, \veone) \typearrow \vvone \terminateas \TypeErrorConfig, \CannotBeTransformed\\\\ - \staticeval(\tenv, \vetwo) \typearrow \vvtwo \terminateas \TypeErrorConfig, \CannotBeTransformed\\\\ - \binopliterals(\op, \vvone, \vvtwo) \typearrow \vv \OrTypeError -}{ - \staticeval(\tenv, \overname{\EBinop(\op, \veone, \vetwo)}{\ve}) \typearrow \vv -} -\end{mathpar} - -\begin{mathpar} -\inferrule[e\_unop]{ - \staticeval(\tenv, \veone) \typearrow \vvone \terminateas \TypeErrorConfig, \CannotBeTransformed\\\\ - \unopliterals(\op, \vvone) \typearrow \vv \OrTypeError -}{ - \staticeval(\tenv, \overname{\EUnop(\op, \veone)}{\ve}) \typearrow \vv -} -\end{mathpar} - -\begin{mathpar} -\inferrule[e\_slice\_int]{ - \typingslicestopositions(\tenv, \slices) \typearrow \positions \OrTypeError\\\\ - \posmax \eqdef \max(\positions)\\ - \bvone \eqdef \inttobits(\vi, \posmax + 1)\\ - \extractslice(\bvone, \positions) \typearrow \bvtwo \OrTypeError -}{ - \staticeval(\tenv, \overname{\ESlice(\lint(\vi), \slices)}{\ve}) \typearrow \overname{\lbitvector(\bvtwo)}{\vv} -} -\end{mathpar} - -\begin{mathpar} -\inferrule[e\_slice\_bitvector]{ - \typingslicestopositions(\tenv, \slices) \typearrow \positions \OrTypeError\\\\ - \posmax \eqdef \max(\positions)\\ - \checktrans{\listlen{\bv} > \posmax}{SliceOutOfRange} \checktransarrow \True \OrTypeError\\\\ - \extractslice(\bv, \positions) \typearrow \bvtwo \OrTypeError -}{ - \staticeval(\tenv, \overname{\ESlice(\lbitvector(\bv), \slices)}{\ve}) \typearrow \overname{\lbitvector(\bvtwo)}{\vv} -} -\end{mathpar} - -\begin{mathpar} -\inferrule[e\_slice\_type\_error]{ - \astlabel(\veone) \not\in \{\lint, \lbitvector\} -}{ - \staticeval(\tenv, \overname{\ESlice(\veone, \slices)}{\ve}) \typearrow \TypeErrorVal{TypeMismatch} -} -\end{mathpar} - -\begin{mathpar} -\inferrule[e\_cond]{ - \staticeval(\tenv, \econd) \typearrow \vcond \terminateas \TypeErrorConfig, \CannotBeTransformed\\\\ - \vcond \eqname \lbool(\vb)\\ - \vep \eqdef \choice{\vb}{\veone}{\vetwo}\\ - \staticeval(\tenv, \vep) \typearrow \vv \terminateas \TypeErrorConfig, \CannotBeTransformed -}{ - \staticeval(\tenv, \overname{\ECond(\econd, \veone, \vetwo)}{\ve}) \typearrow \vv -} -\end{mathpar} - -\begin{mathpar} -\inferrule[unsupported]{ - \astlabel(\ve) \not\in \{ \ELiteral, \EVar, \EBinop, \EUnop, \ESlice, \ECond\} -}{ - \staticeval(\tenv, \ve) \typearrow \TypeErrorVal{UnsupportedExpression} -} -\end{mathpar} - -\section{TypingRule.UnopLiterals \label{sec:TypingRule.UnopLiterals}} -\hypertarget{def-unopliterals}{} -The function -\[ - \unopliterals(\overname{\unop}{\op} \aslsep \overname{\literals}{\vl}) \aslto - \overname{\literals}{\vr} \cup \TTypeError -\] -statically evaluates a unary operator $\op$ (a terminal derived from the AST non-terminal for unary operators) -over a literal $\vl$ and returns the resulting literal $\vr$. -\ProseOtherwiseTypeError - -\hypertarget{def-unopsignatures}{} -The following set of unary operator types and argument types defines the correct argument type -for a given unary operator: -\[ -\unopsignatures \triangleq -\left\{ -\begin{array}{lcll} - (\NEG &,& \lint) &,\\ - (\NEG &,& \lreal) &,\\ - (\BNOT &,& \lbool) &,\\ - (\NOT &,& \lbitvector) &\\ -\end{array} -\right\} -\] - -\subsection{Prose} -One of the following applies: -\begin{itemize} - \item All of the following apply (\textsc{error}): - \begin{itemize} - \item $(\op, \astlabel(\vl))$ is not in $\unopsignatures$; - \item the result is a type error indicating that the combination of $\op$ and $\astlabel(\vl)$ - is not legal. - \end{itemize} - - \item All of the following apply (\textsc{negate\_int}): - \begin{itemize} - \item $\op$ is $\NEG$ and $\vl$ is an integer literal for $\vn$; - \item define $\vr$ as the integer literal for $- \vn$. - \end{itemize} - - \item All of the following apply (\textsc{negate\_real}): - \begin{itemize} - \item $\op$ is $\NEG$ and $\vl$ is a real literal for $\vq$; - \item define $\vr$ as the real literal for $- \vq$. - \end{itemize} - - \item All of the following apply (\textsc{not\_bool}): - \begin{itemize} - \item $\op$ is $\BNOT$ and $\vl$ is a Boolean literal for $\vb$; - \item define $\vr$ as the Boolean literal for $\neg\vb$. - \end{itemize} - - \item All of the following apply (\textsc{not\_bits\_empty}, \textsc{not\_bits\_empty}): - \begin{itemize} - \item $\op$ is $\NOT$ and $\vl$ is a bitvector literal for the sequence of bits $\bits$; - \item $\vc$ is the sequence of bits of the same length as $\bits$ where in each position - the bit in $\vr$ is defined as the negation of the bit of $\bits$ in the same position; - \item define $\vr$ as the bitvector literal for $\vc$. - \end{itemize} -\end{itemize} - -\subsection{Formally} -\begin{mathpar} -\inferrule[error]{ - (\op, \vl) \not\in \unopsignatures -}{ - \unopliterals(\op, \astlabel(\vl)) \typearrow \TypeErrorVal{TypeMismatch} -} -\and -\inferrule[negate\_int]{}{ - \unopliterals(\overname{\NEG}{\op}, \overname{\lint(n)}{\vl}) \typearrow \overname{\lint(- n)}{\vr} -} -\and -\inferrule[negate\_real]{}{ - \unopliterals(\overname{\NEG}{\op}, \overname{\lreal(q)}{\vl}) \typearrow \overname{\lreal(- q)}{\vr} -} -\and -\inferrule[not\_bool]{}{ - \unopliterals(\overname{\BNOT}{\op}, \overname{\lbool(b)}{\vl}) \typearrow \overname{\lbool(\neg b)}{\vr} -} -\and -\inferrule[not\_bits\_empty]{ - \bits \eqname \emptylist\\ - c \eqdef \emptylist -}{ - \unopliterals(\overname{\NOT}{\op}, \overname{\lbitvector(\bits)}{\vl}) \typearrow\overname{\lbitvector(c)}{\vr} -} -\and -\inferrule[not\_bits\_not\_empty]{ - \bits \eqname \vb_{1..k}\\ - c \eqdef [i=1..k: (1-\vb_\vi)] -}{ - \unopliterals(\overname{\NOT}{\op}, \overname{\lbitvector(\bits)}{\vl}) \typearrow\overname{\lbitvector(c)}{\vr} -} -\end{mathpar} - -\section{TypingRule.BinopLiterals \label{sec:TypingRule.BinopLiterals}} -\hypertarget{def-binopliterals}{} -The function -\[ - \binopliterals(\overname{\binop}{\op} \aslsep \overname{\literals}{\vvone} \aslsep \overname{\literals}{\vvtwo}) \aslto - \overname{\literals}{\vr} \cup \TTypeError -\] -statically evaluates a binary operator $\op$ (a terminal derived from the AST non-terminal for binary operators) -over a pair of literals $\vlone$ and $\vltwo$ -and returns the resulting literal $\vr$. -The result is a type error, if it is illegal to apply the operator -to the given values, or a different kind of type error is detected. - -\hypertarget{def-binopsignatures}{} -The following set of binary operator types and argument types defines the correct -argument types for a given binary operator: -\[ -\binopsignatures \triangleq -\left\{ -\begin{array}{lclcll} - (\PLUS &,& \lint &,& \lint)&,\\ - (\MINUS &,& \lint &,& \lint)&,\\ - (\MUL &,& \lint &,& \lint)&,\\ - (\DIV &,& \lint &,& \lint)&,\\ - (\DIVRM &,& \lint &,& \lint)&,\\ - (\MOD &,& \lint &,& \lint)&,\\ - (\POW &,& \lint &,& \lint)&,\\ - (\SHL &,& \lint &,& \lint)&,\\ - (\SHR &,& \lint &,& \lint)&,\\ - (\EQOP &,& \lint &,& \lint)&,\\ - (\NEQ &,& \lint &,& \lint)&,\\ - (\LEQ &,& \lint &,& \lint)&,\\ - (\LT &,& \lint &,& \lint)&,\\ - (\GEQ &,& \lint &,& \lint)&,\\ - (\GT &,& \lint &,& \lint)&,\\ - (\BAND &,& \lbool &,& \lbool)&,\\ - (\BOR &,& \lbool &,& \lbool)&,\\ - (\IMPL &,& \lbool &,& \lbool)&,\\ - (\EQOP &,& \lbool &,& \lbool)&,\\ - (\NEQ &,& \lbool &,& \lbool)&,\\ - (\PLUS &,& \lreal &,& \lreal)&,\\ - (\MINUS &,& \lreal &,& \lreal)&,\\ - (\MUL &,& \lreal &,& \lreal)&,\\ - (\RDIV &,& \lreal &,& \lreal)&,\\ - (\POW &,& \lreal &,& \lint)&,\\ - (\EQOP &,& \lreal &,& \lreal)&,\\ - (\NEQ &,& \lreal &,& \lreal)&,\\ - (\LEQ &,& \lreal &,& \lreal)&,\\ - (\LT &,& \lreal &,& \lreal)&,\\ - (\GEQ &,& \lreal &,& \lreal)&,\\ - (\GT &,& \lreal &,& \lreal)&,\\ - (\EQOP &,& \lbitvector &,& \lbitvector)&,\\ - (\NEQ &,& \lbitvector &,& \lbitvector)&,\\ - (\OR &,& \lbitvector &,& \lbitvector)&,\\ - (\AND &,& \lbitvector &,& \lbitvector)&,\\ - (\XOR &,& \lbitvector &,& \lbitvector)&,\\ - (\MINUS &,& \lbitvector &,& \lbitvector)&,\\ - (\PLUS &,& \lbitvector &,& \lbitvector)&,\\ - (\MINUS &,& \lbitvector &,& \lint)&,\\ - (\PLUS &,& \lbitvector &,& \lint)&\\ -\end{array} -\right\} -\] - -\subsection{Prose} -One of the following applies: -\begin{itemize} - \item All of the following apply (\textsc{error}): - \begin{itemize} - \item $(\op, \astlabel(\vlone), \astlabel(\vltwo))$ is not included in $\binopsignatures$; - \item the result is a type error indicating the $\op$ cannot be applied to the arguments - with the types given by $\astlabel(\vlone)$ and $\astlabel(\vltwo)$. - \end{itemize} - - \item All of the following apply (\textsc{add\_int}): - \begin{itemize} - \item $\op$ is $\PLUS$, $\vlone$ is the literal integer for $a$, and $\vltwo$ is the literal integer for $b$; - \item define $\vr$ as the literal integer for $a+b$. - \end{itemize} - - \item All of the following apply (\textsc{sub\_int}): - \begin{itemize} - \item $\op$ is $\MINUS$, $\vlone$ is the literal integer for $a$, and $\vltwo$ is the literal integer for $b$; - \item define $\vr$ as the literal integer for $a-b$. - \end{itemize} - - \item All of the following apply (\textsc{mul\_int}): - \begin{itemize} - \item $\op$ is $\MUL$, $\vlone$ is the literal integer for $a$, and $\vltwo$ is the literal integer for $b$; - \item define $\vr$ as the literal integer for $a\times b$. - \end{itemize} - - \item All of the following apply (\textsc{div\_int}): - \begin{itemize} - \item $\op$ is $\DIV$, $\vlone$ is the literal integer for $a$, and $\vltwo$ is the literal integer for $b$; - \item checking that $b$ is positive yields $\True$\ProseOrTypeError; - \item define $n$ as $a$ divided by $b$ (note that $n$ is potentially a fraction); - \item checking that $n$ is an integer yields $\True$\ProseOrTypeError; - \item define $\vr$ as the literal integer for $a\div b$. - \end{itemize} - - \item All of the following apply (\textsc{fdiv\_int}): - \begin{itemize} - \item $\op$ is $\DIVRM$, $\vlone$ is the literal integer for $a$, and $\vltwo$ is the literal integer for $b$; - \item checking that $b$ is positive yields $\True$\ProseOrTypeError; - \item define $n$ as $a$ divided by $b$, rounded down (if $a$ is negative, $n$ is rounded down towards infinity); - \item define $\vr$ as the literal integer for $n$. - \end{itemize} - - \item All of the following apply (\textsc{frem\_int}): - \begin{itemize} - \item $\op$ is $\MOD$, $\vlone$ is the literal integer for $a$, and $\vltwo$ is the literal integer for $b$; - \item applying $\binopliterals$ to $\DIVRM$ with $\vlone$ and $\vltwo$ yields $c$\ProseOrTypeError; - \item define $n$ as $a-c$; - \item define $\vr$ as the literal integer for $n$. - \end{itemize} - - \item All of the following apply (\textsc{exp\_int}): - \begin{itemize} - \item $\op$ is $\POW$, $\vlone$ is the literal integer for $a$, and $\vltwo$ is the literal integer for $b$; - \item checking that $b$ is non-negative yields $\True$\ProseOrTypeError; - \item define $n$ as $a^b$; - \item define $\vr$ as the literal integer for $n$. - \end{itemize} - - \item All of the following apply (\textsc{shl}): - \begin{itemize} - \item $\op$ is $\SHL$, $\vlone$ is the literal integer for $a$, and $\vltwo$ is the literal integer for $b$; - \item checking that $b$ is non-negative yields $\True$\ProseOrTypeError; - \item applying $\binopliterals$ to $\POW$ with $2$ and $\vltwo$ yields the literal integer for $e$; - \item applying $\binopliterals$ to $\MUL$ with $2$ and the literal integer for $e$ yields $\vr$. - \end{itemize} - - \item All of the following apply (\textsc{shr}): - \begin{itemize} - \item $\op$ is $\SHR$, $\vlone$ is the literal integer for $a$, and $\vltwo$ is the literal integer for $b$; - \item checking that $b$ is non-negative yields $\True$\ProseOrTypeError; - \item applying $\binopliterals$ to $\POW$ with $2$ and $\vltwo$ yields the literal integer for $e$; - \item applying $\binopliterals$ to $\DIVRM$ with $2$ and the literal integer for $e$ yields $\vr$. - \end{itemize} - - \item All of the following apply (\textsc{eq\_int}): - \begin{itemize} - \item $\op$ is $\EQOP$, $\vlone$ is the literal integer for $a$, and $\vltwo$ is the literal integer for $b$; - \item define $\vr$ as the Boolean literal that is $\True$ if and only if $a$ is equal to $b$. - \end{itemize} - - \item All of the following apply (\textsc{ne\_int}): - \begin{itemize} - \item $\op$ is $\NEQ$, $\vlone$ is the literal integer for $a$, and $\vltwo$ is the literal integer for $b$; - \item define $\vr$ as the Boolean literal that is $\True$ if and only if $a$ is different from $b$ holds. - \end{itemize} - - \item All of the following apply (\textsc{le\_int}): - \begin{itemize} - \item $\op$ is $\LEQ$, $\vlone$ is the literal integer for $a$, and $\vltwo$ is the literal integer for $b$; - \item define $\vr$ as the Boolean literal that is $\True$ if and only if $a$ is less than or equal to $b$s. - \end{itemize} - - \item All of the following apply (\textsc{lt\_int}): - \begin{itemize} - \item $\op$ is $\LT$, $\vlone$ is the literal integer for $a$, and $\vltwo$ is the literal integer for $b$; - \item define $\vr$ as the Boolean literal that is $\True$ if and only if $a$ is less than $b$s. - \end{itemize} - - \item All of the following apply (\textsc{ge\_int}): - \begin{itemize} - \item $\op$ is $\GEQ$, $\vlone$ is the literal integer for $a$, and $\vltwo$ is the literal integer for $b$; - \item define $\vr$ as the Boolean literal that is $\True$ if and only if $a$ is greater or equal than $b$s. - \end{itemize} - - \item All of the following apply (\textsc{gt\_int}): - \begin{itemize} - \item $\op$ is $\GT$, $\vlone$ is the literal integer for $a$, and $\vltwo$ is the literal integer for $b$; - \item define $\vr$ as the Boolean literal that is $\True$ if and only if $a$ is greater than $b$s. - \end{itemize} - - \item All of the following apply (\textsc{and\_bool}): - \begin{itemize} - \item $\op$ is $\BAND$, $\vlone$ is the literal Boolean for $a$, and $\vltwo$ is the literal Boolean for $b$; - \item define $\vr$ as the Boolean literal that is $\True$ if and only if both $a$ and $b$ are $\True$. - \end{itemize} - - \item All of the following apply (\textsc{or\_bool}): - \begin{itemize} - \item $\op$ is $\BOR$, $\vlone$ is the literal Boolean for $a$, and $\vltwo$ is the literal Boolean for $b$; - \item define $\vr$ as the Boolean literal that is $\True$ if and only if at least one of $a$ and $b$ is $\True$. - \end{itemize} - - \item All of the following apply (\textsc{implies\_bool}): - \begin{itemize} - \item $\op$ is $\IMPL$, $\vlone$ is the literal Boolean for $a$, and $\vltwo$ is the literal Boolean for $b$; - \item define $\vr$ as the Boolean literal that is $\True$ if and only if $a$ is $\False$ or $b$ is $\True$. - \end{itemize} - - \item All of the following apply (\textsc{eq\_bool}): - \begin{itemize} - \item $\op$ is $\EQOP$, $\vlone$ is the literal Boolean for $a$, and $\vltwo$ is the literal Boolean for $b$; - \item define $\vr$ as the Boolean literal that is $\True$ if and only if $a$ is equal to $b$. - \end{itemize} - - \item All of the following apply (\textsc{ne\_bool}): - \begin{itemize} - \item $\op$ is $\NEQ$, $\vlone$ is the literal Boolean for $a$, and $\vltwo$ is the literal Boolean for $b$; - \item define $\vr$ as the Boolean literal that is $\True$ if and only if $a$ is different from $b$. - \end{itemize} - - \item All of the following apply (\textsc{add\_real}): - \begin{itemize} - \item $\op$ is $\PLUS$, $\vlone$ is the literal real for $a$, and $\vltwo$ is the literal real for $b$; - \item define $\vr$ as the real literal for $a + b$. - \end{itemize} - - \item All of the following apply (\textsc{sub\_real}): - \begin{itemize} - \item $\op$ is $\MINUS$, $\vlone$ is the literal real for $a$, and $\vltwo$ is the literal real for $b$; - \item define $\vr$ as the real literal for $a - b$. - \end{itemize} - - \item All of the following apply (\textsc{mul\_real}): - \begin{itemize} - \item $\op$ is $\MUL$, $\vlone$ is the literal real for $a$, and $\vltwo$ is the literal real for $b$; - \item define $\vr$ as the real literal for $a \times b$. - \end{itemize} - - \item All of the following apply (\textsc{div\_real}): - \begin{itemize} - \item $\op$ is $\RDIV$, $\vlone$ is the literal real for $a$, and $\vltwo$ is the literal real for $b$; - \item checking whether $b$ is different from $0$ yields $\True$\ProseOrTypeError; - \item define $\vr$ as the real literal for $a \div b$. - \end{itemize} - - \item All of the following apply (\textsc{exp\_real}): - \begin{itemize} - \item $\op$ is $\POW$, $\vlone$ is the literal real for $a$, and $\vltwo$ is the literal integer for $b$; - \item define $\vr$ as the real literal for $a^b$. - \end{itemize} - - \item All of the following apply (\textsc{eq\_real}): - \begin{itemize} - \item $\op$ is $\EQOP$, $\vlone$ is the literal real for $a$, and $\vltwo$ is the literal real for $b$; - \item define $\vr$ as the Boolean literal that is $\True$ if and only if $a$ is equal to $b$. - \end{itemize} - - \item All of the following apply (\textsc{ne\_real}): - \begin{itemize} - \item $\op$ is $\NEQ$, $\vlone$ is the literal real for $a$, and $\vltwo$ is the literal real for $b$; - \item define $\vr$ as the Boolean literal that is $\True$ if and only if $a$ is different from $b$. - \end{itemize} - - \item All of the following apply (\textsc{le\_real}): - \begin{itemize} - \item $\op$ is $\LEQ$, $\vlone$ is the literal real for $a$, and $\vltwo$ is the literal real for $b$; - \item define $\vr$ as the Boolean literal that is $\True$ if and only if $a$ is less than or equal to $b$. - \end{itemize} - - \item All of the following apply (\textsc{lt\_real}): - \begin{itemize} - \item $\op$ is $\LT$, $\vlone$ is the literal real for $a$, and $\vltwo$ is the literal real for $b$; - \item define $\vr$ as the Boolean literal that is $\True$ if and only if $a$ is less than $b$. - \end{itemize} - - \item All of the following apply (\textsc{ge\_real}): - \begin{itemize} - \item $\op$ is $\GEQ$, $\vlone$ is the literal real for $a$, and $\vltwo$ is the literal real for $b$; - \item define $\vr$ as the Boolean literal that is $\True$ if and only if $a$ is greater than or equal to $b$. - \end{itemize} - - \item All of the following apply (\textsc{gt\_real}): - \begin{itemize} - \item $\op$ is $\GT$, $\vlone$ is the literal real for $a$, and $\vltwo$ is the literal real for $b$; - \item define $\vr$ as the Boolean literal that is $\True$ if and only if $a$ is greater than $b$. - \end{itemize} - - \item All of the following apply (\textsc{bitwise\_different\_bitwidths}): - \begin{itemize} - \item $\vvone$ is a bitvector literal for $a$; - \item $\vvtwo$ is a bitvector literal for $b$; - \item the lengths of $a$ and $b$ are different; - \item the result is a type error indicating that the bitvectors must be of the same width. - \end{itemize} - - \item All of the following apply (\textsc{bitwise\_empty}): - \begin{itemize} - \item $\vvone$ is the empty bitvector literal; - \item $\vvtwo$ is the empty bitvector literal; - \item $\op$ is one of $\OR$, $\AND$, $\XOR$, $\PLUS$, or $\MINUS$; - \item define $\vr$ as the empty bitvector literal. - \end{itemize} - - \item All of the following apply (\textsc{eq\_bits\_empty}): - \begin{itemize} - \item $\vvone$ is the empty bitvector literal; - \item $\vvtwo$ is the empty bitvector literal; - \item $\op$ is $\EQOP$; - \item define $\vr$ as the Boolean literal for $\True$. - \end{itemize} - - \item All of the following apply (\textsc{eq\_bits\_not\_empty}): - \begin{itemize} - \item $\vvone$ is a bitvector literal for $a_{1..k}$; - \item $\vvtwo$ is a bitvector literal for $b_{1..k}$; - \item $\op$ is $\EQOP$; - \item define $\vb$ as $\True$ if and only if $a_i$ is equal to $b_i$, for $i=1..k$; - \item define $\vr$ as the Boolean literal for $\vb$. - \end{itemize} - - \item All of the following apply (\textsc{ne\_bits}): - \begin{itemize} - \item $\vvone$ is a bitvector literal for $a$; - \item $\vvtwo$ is a bitvector literal for $b$; - \item $\op$ is $\NEQ$; - \item applying $\binopliterals$ to $\NEQ$ for $\vvone$ and $\vvtwo$ yields the Boolean literal for $\vb$\ProseOrTypeError; - \item define $\vr$ as the Boolean literal for $\neg\vb$. - \end{itemize} - - \item All of the following apply (\textsc{or\_bits}): - \begin{itemize} - \item $\vvone$ is a bitvector literal for $a_{1..k}$; - \item $\vvtwo$ is a bitvector literal for $b_{1..k}$; - \item $\op$ is $\OR$; - \item define $c_i$ as the maximum of $a_i$ and $b_i$ for $i=1..k$; - \item define $\vr$ as the bitvector literal for $c_{1..k}$. - \end{itemize} - - \item All of the following apply (\textsc{and\_bits}): - \begin{itemize} - \item $\vvone$ is a bitvector literal for $a_{1..k}$; - \item $\vvtwo$ is a bitvector literal for $b_{1..k}$; - \item $\op$ is $\AND$; - \item define $c_i$ as the minimum of $a_i$ and $b_i$ for $i=1..k$; - \item define $\vr$ as the bitvector literal for $c_{1..k}$. - \end{itemize} - - \item All of the following apply (\textsc{xor\_bits}): - \begin{itemize} - \item $\vvone$ is a bitvector literal for $a_{1..k}$; - \item $\vvtwo$ is a bitvector literal for $b_{1..k}$; - \item $\op$ is $\XOR$; - \item define $c_i$ as $1$ if $a_i$ is different from $b_i$ and $0$ otherwise, for $i=1..k$; - \item define $\vr$ as the bitvector literal for $c_{1..k}$. - \end{itemize} - - \item All of the following apply (\textsc{add\_bits}): - \begin{itemize} - \item $\vvone$ is a bitvector literal for $a_{1..k}$; - \item $\vvtwo$ is a bitvector literal for $b_{1..k}$; - \item $\op$ is $\PLUS$; - \item define $a$ as the natural number represented by $a_{1..k}$; - \item define $b$ as the natural number represented by $b_{1..k}$; - \item define $c$ as the two's complement little endian representation of $a+b$ in $k$ bits; - \item define $\vr$ as the bitvector literal for $c$. - \end{itemize} - - \item All of the following apply (\textsc{sub\_bits}): - \begin{itemize} - \item $\vvone$ is a bitvector literal for $a_{1..k}$; - \item $\vvtwo$ is a bitvector literal for $b_{1..k}$; - \item $\op$ is $\MINUS$; - \item define $a$ as the natural number represented by $a_{1..k}$; - \item define $b$ as the natural number represented by $b_{1..k}$; - \item define $c$ as the two's complement little endian representation of $a-b$ in $k$ bits; - \item define $\vr$ as the bitvector literal for $c$. - \end{itemize} - - \item All of the following apply (\textsc{add\_bits\_int}): - \begin{itemize} - \item $\vvone$ is a bitvector literal for $a$; - \item $\vvtwo$ is an integer literal for $b$; - \item $\op$ is $\PLUS$; - \item define $y$ as the natural number represented by $a$; - \item define $c$ as the two's complement little endian representation of $y+b$ in $\listlen{a}$ bits; - \item define $\vr$ as the bitvector literal for $c$. - \end{itemize} - - \item All of the following apply (\textsc{sub\_bits\_int}): - \begin{itemize} - \item $\vvone$ is a bitvector literal for $a$; - \item $\vvtwo$ is an integer literal for $b$; - \item $\op$ is $\MINUS$; - \item define $y$ as the natural number represented by $a$; - \item define $c$ as the two's complement little endian representation of $y-b$ in $\listlen{a}$ bits; - \item define $\vr$ as the bitvector literal for $c$. - \end{itemize} -\end{itemize} - -\subsection{Formally} - -\begin{mathpar} -\inferrule[error]{ - (\op, \astlabel(\vlone), \astlabel(\vltwo)) \not\in \binopsignatures -}{ - \binopliterals(\op, \overname{\vlone}{\vvone}, \overname{\vltwo}{\vvtwo}) \typearrow \TypeErrorVal{TypeMismatch} -} -\end{mathpar} - -\subsubsection{Arithmetic Operators Over Integer Values \label{sec:AthimeticOverInt}} -\begin{mathpar} -\inferrule[add\_int]{}{ - \binopliterals(\overname{\PLUS}{\op}, \overname{\lint(a)}{\vvone}, \overname{\lint(b)}{\vvtwo}) \typearrow \overname{\lint(a + b)}{\vr} -} -\end{mathpar} - -\begin{mathpar} -\inferrule[sub\_int]{}{ - \binopliterals(\overname{\MINUS}{\op}, \overname{\lint(a)}{\vvone}, \overname{\lint(b)}{\vvtwo}) \typearrow \overname{\lint(a - b)}{\vr} -} -\end{mathpar} - -\begin{mathpar} -\inferrule[mul\_int]{}{ - \binopliterals(\overname{\MUL}{\op}, \overname{\lint(a)}{\vvone}, \overname{\lint(b)}{\vvtwo}) \typearrow \overname{\lint(a \times b)}{\vr} -} -\end{mathpar} - -\begin{mathpar} -\inferrule[div\_int]{ - \checktrans{b > 0}{DIV\_DenominatorNegative} \checktransarrow \True \OrTypeError\\\\ - n \eqdef a \div b \\\\ - \checktrans{n \in \Z}{\DivIntIndivisible} \checktransarrow \True \OrTypeError -}{ - \binopliterals(\overname{\DIV}{\op}, \overname{\lint(a)}{\vvone}, \overname{\lint(b)}{\vvtwo}) \typearrow \overname{\lint(n)}{\vr} -} -\and -\inferrule[fdiv\_int]{ - \checktrans{b > 0}{FDIV\_DenominatorNegative} \checktransarrow \True \OrTypeError\\\\ - n \eqdef \choice{a \geq 0}{\lfloor a \div b \rfloor}{-(\lceil (-a) \div b \rceil)} -}{ - \binopliterals(\overname{\DIVRM}{\op}, \overname{\lint(a)}{\vvone}, \overname{\lint(b)}{\vvtwo}) \typearrow \overname{\lint(n)}{\vr} -} -\end{mathpar} - -\begin{mathpar} -\inferrule[frem\_int]{ - \binopliterals(\DIVRM, \lint(a), \lint(b)) \typearrow \lint(c) \OrTypeError -}{ - \binopliterals(\overname{\MOD}{\op}, \overname{\lint(a)}{\vvone}, \overname{\lint(b)}{\vvtwo}) \typearrow \overname{\lint(a - (c \times b))}{\vr} -} -\end{mathpar} - -\begin{mathpar} -\inferrule[exp\_int]{ - \checktrans{b \geq 0}{ExponentNegative} \checktransarrow \True \OrTypeError -}{ - \binopliterals(\overname{\POW}{\op}, \overname{\lint(a)}{\vvone}, \overname{\lint(b)}{\vvtwo}) \typearrow \overname{\lint(a^b)}{\vr} -} -\end{mathpar} - -\begin{mathpar} -\inferrule[shl]{ - \checktrans{b \geq 0}{ShifterNegative} \checktransarrow \True \OrTypeError\\\\ - \binopliterals(\POW, \lint(2), \lint(b)) \typearrow \lint(e)\\ - \binopliterals(\MUL, \lint(a), \lint(e)) \typearrow \vr -}{ - \binopliterals(\overname{\SHL}{\op}, \overname{\lint(a)}{\vvone}, \overname{\lint(b)}{\vvtwo}) \typearrow \vr -} -\end{mathpar} - -\begin{mathpar} -\inferrule[shr]{ - \checktrans{b \geq 0}{ShifterNegative} \checktransarrow \True \OrTypeError\\\\ - \binopliterals(\POW, \lint(2), \lint(b)) \typearrow \lint(e)\\ - \binopliterals(\DIVRM, \lint(a), \lint(e)) \typearrow \vr -}{ - \binopliterals(\overname{\SHR}{\op}, \overname{\lint(a)}{\vvone}, \overname{\lint(b)}{\vvtwo}) \typearrow \vr -} -\end{mathpar} - -\subsubsection{Relational Operators Over Integer Values \label{sec:RelationalOverInt}} -\begin{mathpar} -\inferrule[eq\_int]{}{ - \binopliterals(\overname{\EQOP}{\op}, \overname{\lint(a)}{\vvone}, \overname{\lint(b)}{\vvtwo}) \typearrow \overname{\lbool(a = b)}{\vr} -} -\end{mathpar} - -\begin{mathpar} -\inferrule[ne\_int]{}{ - \binopliterals(\overname{\NEQ}{\op}, \overname{\lint(a)}{\vvone}, \overname{\lint(b)}{\vvtwo}) \typearrow \overname{\lbool(a \neq b)}{\vr} -} -\end{mathpar} - -\begin{mathpar} -\inferrule[le\_int]{}{ - \binopliterals(\overname{\LEQ}{\op}, \overname{\lint(a)}{\vvone}, \overname{\lint(b)}{\vvtwo}) \typearrow \overname{\lbool(a \leq b)}{\vr} -} -\end{mathpar} - -\begin{mathpar} -\inferrule[lt\_int]{}{ - \binopliterals(\overname{\LT}{\op}, \overname{\lint(a)}{\vvone}, \overname{\lint(b)}{\vvtwo}) \typearrow \overname{\lbool(a < b)}{\vr} -} -\end{mathpar} - -\begin{mathpar} -\inferrule[ge\_int]{}{ - \binopliterals(\overname{\GEQ}{\op}, \overname{\lint(a)}{\vvone}, \overname{\lint(b)}{\vvtwo}) \typearrow \overname{\lbool(a \geq b)}{\vr} -} -\end{mathpar} - -\begin{mathpar} -\inferrule[gt\_int]{}{ - \binopliterals(\overname{\GT}{\op}, \overname{\lint(a)}{\vvone}, \overname{\lint(b)}{\vvtwo}) \typearrow \overname{\lbool(a > b)}{\vr} -} -\end{mathpar} - -\subsubsection{Boolean Operators Over Boolean Values \label{sec:BooleanOverBoolean}} -\begin{mathpar} -\inferrule[and\_bool]{}{ - \binopliterals(\overname{\BAND}{\op}, \overname{\lbool(a)}{\vvone}, \overname{\lbool(b)}{\vvtwo}) \typearrow \overname{\lbool(a \wedge b)}{\vr} -} -\end{mathpar} - -\begin{mathpar} -\inferrule[or\_bool]{}{ - \binopliterals(\overname{\BOR}{\op}, \overname{\lbool(a)}{\vvone}, \overname{\lbool(b)}{\vvtwo}) \typearrow \overname{\lbool(a \lor b)}{\vr} -} -\end{mathpar} - -\begin{mathpar} -\inferrule[implies\_bool]{}{ - \binopliterals(\overname{\IMPL}{\op}, \overname{\lbool(a)}{\vvone}, \overname{\lbool(b)}{\vvtwo}) \typearrow \overname{\lbool(\neg a \lor b)}{\vr} -} -\end{mathpar} - -\begin{mathpar} -\inferrule[eq\_bool]{}{ - \binopliterals(\overname{\EQOP}{\op}, \overname{\lbool(a)}{\vvone}, \overname{\lbool(b)}{\vvtwo}) \typearrow \overname{\lbool(a = b)}{\vr} -} -\end{mathpar} - -\begin{mathpar} -\inferrule[ne\_bool]{}{ - \binopliterals(\overname{\NEQ}{\op}, \overname{\lbool(a)}{\vvone}, \overname{\lbool(b)}{\vvtwo}) \typearrow \overname{\lbool(a \neq b)}{\vr} -} -\end{mathpar} - -\subsubsection{Arithmetic Operators Over Real Values \label{sec:AthimeticOverReal}} -\begin{mathpar} -\inferrule[add\_real]{}{ - \binopliterals(\overname{\PLUS}{\op}, \overname{\lreal(a)}{\vvone}, \overname{\lreal(b)}{\vvtwo}) \typearrow \overname{\lreal(a+b)}{\vr} -} -\end{mathpar} - -\begin{mathpar} -\inferrule[sub\_real]{}{ - \binopliterals(\overname{\MINUS}{\op}, \overname{\lreal(a)}{\vvone}, \overname{\lreal(b)}{\vvtwo}) \typearrow \overname{\lreal(a-b)}{\vr} -} -\end{mathpar} - -\begin{mathpar} -\inferrule[mul\_real]{}{ - \binopliterals(\overname{\MUL}{\op}, \overname{\lreal(a)}{\vvone}, \overname{\lreal(b)}{\vvtwo}) \typearrow \overname{\lreal(a\times b)}{\vr} -} -\end{mathpar} - -\begin{mathpar} -\inferrule[div\_real]{ - \checktrans{b \neq 0}{RDIV\_DenominatorZero} \checktransarrow \True \OrTypeError -}{ - \binopliterals(\overname{\RDIV}{\op}, \overname{\lreal(a)}{\vvone}, \overname{\lreal(b)}{\vvtwo}) \typearrow \overname{\lreal(a\div b)}{\vr} -} -\end{mathpar} - -\begin{mathpar} -\inferrule[exp\_real]{}{ - \binopliterals(\overname{\POW}{\op}, \overname{\lreal(a)}{\vvone}, \overname{\lint(b)}{\vvtwo}) \typearrow \overname{\lreal(a^b)}{\vr} -} -\end{mathpar} - -\subsubsection{Relational Operators Over Real Values \label{sec:RealtionalOverReal}} -\begin{mathpar} -\inferrule[eq\_real]{}{ - \binopliterals(\overname{\EQOP}{\op}, \overname{\lreal(a)}{\vvone}, \overname{\lreal(b)}{\vvtwo}) \typearrow \overname{\lbool(a = b)}{\vr} -} -\end{mathpar} - -\begin{mathpar} -\inferrule[ne\_real]{}{ - \binopliterals(\overname{\NEQ}{\op}, \overname{\lreal(a)}{\vvone}, \overname{\lreal(b)}{\vvtwo}) \typearrow \overname{\lbool(a \neq b)}{\vr} -} -\end{mathpar} - -\begin{mathpar} -\inferrule[le\_real]{}{ - \binopliterals(\overname{\LEQ}{\op}, \overname{\lreal(a)}{\vvone}, \overname{\lreal(b)}{\vvtwo}) \typearrow \overname{\lbool(a \leq b)}{\vr} -} -\end{mathpar} - -\begin{mathpar} -\inferrule[lt\_real]{}{ - \binopliterals(\overname{\LT}{\op}, \overname{\lreal(a)}{\vvone}, \overname{\lreal(b)}{\vvtwo}) \typearrow \overname{\lbool(a < b)}{\vr} -} -\end{mathpar} - -\begin{mathpar} -\inferrule[ge\_real]{}{ - \binopliterals(\overname{\GEQ}{\op}, \overname{\lreal(a)}{\vvone}, \overname{\lreal(b)}{\vvtwo}) \typearrow \overname{\lbool(a \geq b)}{\vr} -} -\end{mathpar} - -\begin{mathpar} -\inferrule[gt\_real]{}{ - \binopliterals(\overname{\GT}{\op}, \overname{\lreal(a)}{\vvone}, \overname{\lreal(b)}{\vvtwo}) \typearrow \overname{\lbool(a > b)}{\vr} -} -\end{mathpar} - -\subsection{Operators Over Bitvectors \label{sec:BitvectorOperations}} -\hypertarget{def-bintounsigned}{} -The function $\bintounsigned : \{0,1\}^* \rightarrow \N$ converts a non-empty sequence of bits -into a natural number: -\[ - \bintounsigned(a_{n..1}) \triangleq \sum_{i=1}^n a_i \cdot 2^{a_i} -\] -and an empty sequence of bits into $0$: -\[ - \bintounsigned(\emptylist) \triangleq 0 \enspace. -\] - -\hypertarget{def-inttobits}{} -The function $\inttobits : \overname{\Z}{\texttt{val}} \times \overname{\Z}{\texttt{width}} \rightarrow \{0,1\}^*$ -converts an integer \texttt{val} to its two's complement little endian representation -of \texttt{width} bits. - -\begin{mathpar} -\inferrule[bitwise\_different\_bitwidths]{ - \listlen{a} \neq \listlen{b} -}{ - \binopliterals(\op, \overname{\lbitvector(a)}{\vvone}, \overname{\lbitvector(b)}{\vvtwo}) \typearrow - \TypeErrorVal{\RequireSameBitwidths} -} -\and -\inferrule[bitwise\_empty]{ - \op \in \{\OR, \AND, \XOR, \PLUS, \MINUS\} -}{ - \binopliterals(\op, \overname{\lbitvector(\emptylist)}{\vvone}, \overname{\lbitvector(\emptylist)}{\vvtwo}) \typearrow - \overname{\lbitvector(\emptylist)}{\vr} -} -\end{mathpar} - -\begin{mathpar} -\inferrule[eq\_bits\_empty]{}{ - \binopliterals(\overname{\EQOP}{\op}, \overname{\lbitvector(\emptylist)}{\vvone}, \overname{\lbitvector(\emptylist)}{\vvtwo}) \typearrow - \overname{\lbool(\True)}{\vr} -} -\and -\inferrule[eq\_bits\_not\_empty]{ - \vb \eqdef \bigwedge_{i=1}^k a_i = b_i -}{ - \binopliterals(\overname{\EQOP}{\op}, \overname{\lbitvector(a_{1..k})}{\vvone}, \overname{\lbitvector(b_{1..k})}{\vvtwo}) \typearrow - \overname{\lbool(\vb)}{\vr} -} -\end{mathpar} - -\begin{mathpar} -\inferrule[ne\_bits]{ - \binopliterals(\EQOP, \lbitvector(a), \lbitvector(b)) \typearrow \lbool(\vb) \OrTypeError -}{ - \binopliterals(\overname{\NEQ}{\op}, \overname{\lbitvector(a)}{\vvone}, \overname{\lbitvector(b)}{\vvtwo}) \typearrow \lbool(\neg\vb) -} -\end{mathpar} - -\begin{mathpar} -\inferrule[or\_bits]{ - i=1..k: c_i = \max(a_i, b_i) -}{ - \binopliterals(\overname{\OR}{\op}, \overname{\lbitvector(a_{1..k})}{\vvone}, \overname{\lbitvector(b_{1..k})}{\vvtwo}) \typearrow \lbitvector(c_{1..k}) -} -\end{mathpar} - -\begin{mathpar} -\inferrule[and\_bits]{ - i=1..k: c_i = \min(a_i, b_i) -}{ - \binopliterals(\overname{\AND}{\op}, \overname{\lbitvector(a_{1..k})}{\vvone}, \overname{\lbitvector(b_{1..k})}{\vvtwo}) \typearrow \lbitvector(c_{1..k}) -} -\end{mathpar} - -\begin{mathpar} -\inferrule[xor\_bits]{ - { - \textit{xor\_bit} = \lambda a,b\in\{0,1\}.\ \left\{ - \begin{array}{ll} - 0 & \text{ if } a = b\\ - 1 & \text{ otherwise} - \end{array} - \right. - }\\ - i=1..k: c_i=\textit{xor\_bit}(a_i, b_i) -}{ - \binopliterals(\overname{\XOR}{\op}, \overname{\lbitvector(a_{1..k})}{\vvone}, \overname{\lbitvector(b_{1..k})}{\vvtwo}) \typearrow \lbitvector(c_{1..k}) -} -\end{mathpar} - -\begin{mathpar} -\inferrule[add\_bits]{ - a \eqdef \bintounsigned(a_{1..k})\\ - b \eqdef \bintounsigned(b_{1..k})\\ - c \eqdef \inttobits(a + b, k) -}{ - \binopliterals(\overname{\PLUS}{\op}, \overname{\lbitvector(a_{1..k})}{\vvone}, \overname{\lbitvector(b_{1..k})}{\vvtwo}) \typearrow \overname{\lbitvector(c)}{\vr} -} -\end{mathpar} - -\begin{mathpar} -\inferrule[sub\_bits]{ - a \eqdef \bintounsigned(a_{1..k})\\ - b \eqdef \bintounsigned(b_{1..k})\\ - c \eqdef \inttobits(a - b, k) -}{ - \binopliterals(\overname{\MINUS}{\op}, \overname{\lbitvector(a_{1..k})}{\vvone}, \overname{\lbitvector(b_{1..k})}{\vvtwo}) \typearrow \overname{\lbitvector(c)}{\vr} -} -\end{mathpar} - -\begin{mathpar} -\inferrule[add\_bits\_int]{ - y \eqdef \bintounsigned(a)\\ - c \eqdef \inttobits(y + b, \listlen{a}) -}{ - \binopliterals(\overname{\PLUS}{\op}, \overname{\lbitvector(a)}{\vvone}, \overname{\lint(b)}{\vvtwo}) \typearrow \overname{\lbitvector(c)}{\vr} -} -\end{mathpar} - -\begin{mathpar} -\inferrule[sub\_bits\_int]{ - y \eqdef \bintounsigned(a)\\ - c \eqdef \inttobits(y - b, \listlen{a}) -}{ - \binopliterals(\overname{\MINUS}{\op}, \overname{\lbitvector(a)}{\vvone}, \overname{\lint(b)}{\vvtwo}) \typearrow \overname{\lbitvector(c)}{\vr} -} -\end{mathpar} - -\section{TypingRule.SlicesToPositions \label{sec:TypingRule.SlicesToPositions}} -\hypertarget{def-typingslicestopositions}{} -The function -\[ - \typingslicestopositions(\overname{\staticenvs}{\tenv} \aslsep \overname{\slice^*}{\slices}) \aslto - \overname{\Z^*}{\positions} \cup \{\CannotBeTransformed\} \cup \overname{\TTypeError}{\TypeErrorConfig} -\] -transforms the list of slices $\slices$ in $\tenv$ into a list of indices $\positions$. -The result is $\CannotBeTransformed$ if $\slices$ cannot be statically evaluated to -a list of positions. -\ProseOtherwiseTypeError - -\subsection{Prose} -One of the following applies: -\begin{itemize} - \item All of the following apply (\textsc{empty}): - \begin{itemize} - \item $\slices$ is the empty list; - \item $\positions$ is the empty list. - \end{itemize} - - \item All of the following apply (\textsc{non\_empty}): - \begin{itemize} - \item \view\ $\slices$ as the list with $\vs$ as its \head\ and $\slicesone$ as its \tail; - \item applying $\slicetopositions$ to $\vs$ in $\tenv$ yields the list of positions \\ - $\positionsone$\ProseTerminateAs{\CannotBeTransformed, \TypeErrorConfig}; - \item transforming $\slicesone$ to a list of positions in $\tenv$ via $\typingslicestopositions$ yields - $\positionstwo$\ProseTerminateAs{\CannotBeTransformed, \TypeErrorConfig}; - \item $\positions$ is the concatenation of $\positionsone$ and $\positionstwo$. - \end{itemize} -\end{itemize} - -\subsection{Formally} -\begin{mathpar} -\inferrule[empty]{} -{ - \typingslicestopositions(\tenv, \overname{\emptylist}{\slices}) \typearrow \overname{\emptylist}{\positions} -} -\and -\inferrule[non\_empty]{ - \slicetopositions(\tenv, \vs) \typearrow \positionsone \terminateas \CannotBeTransformed,\TypeErrorConfig\\\\ - \typingslicestopositions(\tenv, \slicesone) \typearrow \positionstwo \terminateas \CannotBeTransformed,\TypeErrorConfig -}{ - \typingslicestopositions(\tenv, \overname{[\vs] \concat \slicesone}{\slices}) \typearrow \overname{\positionsone \concat \positionstwo}{\positions} -} -\end{mathpar} - -\section{TypingRule.SliceToPositions \label{sec:TypingRule.SliceToPositions}} -\hypertarget{def-slicetopositions}{} -The function -\[ - \slicetopositions(\overname{\staticenvs}{\tenv} \aslsep \overname{\slice}{\vs}) \aslto - \overname{\Z^+}{\positions} \cup \{\CannotBeTransformed\} \cup \overname{\TTypeError}{\TypeErrorConfig} -\] -transforms a slice $\vs$ in $\tenv$ into a list of indices $\positions$. -The result is $\CannotBeTransformed$ if $\slices$ cannot be statically evaluated to -a list of positions. -\ProseOtherwiseTypeError - -\subsection{Prose} -One of the following applies: -\begin{itemize} - \item All of the following apply (\textsc{single}): - \begin{itemize} - \item $\vs$ is a slice for a single position given by the expression $\ve$, that is, \\ $\SliceSingle(\ve)$; - \item applying $\evaltoint$ to $\ve$ in $\tenv$ yields the integer $n$\ProseOrTypeError; - \item checking that $n$ is non-negative yields $\True$\ProseOrTypeError; - \item $\positions$ is the list containing the single element $n$. - \end{itemize} - - \item All of the following apply (\textsc{range}): - \begin{itemize} - \item $\vs$ is a slice for a range given by the expression $\etop$ - for the top position and $\ebot$ for the bottom position, that is, \\ $\SliceRange(\etop, \ebot)$; - \item applying $\evaltoint$ to $\ebot$ in $\tenv$ yields the integer $b$\ProseOrTypeError; - \item applying $\evaltoint$ to $\etop$ in $\tenv$ yields the integer $t$\ProseOrTypeError; - \item checking that $t$ is greater or equal to $b$ and that $b$ is greater or equal to $0$ yields $\True$\ProseOrTypeError; - \item $\positions$ is the list of integers from $t$ down to $b$, inclusive. - \end{itemize} - - \item All of the following apply (\textsc{length}): - \begin{itemize} - \item $\vs$ is a slice for a length slice given by the expression $\ebot$ - for the bottom position and $\elength$ for the length of the slice, that is, \\ $\SliceLength(\ebot, \elength)$; - \item applying $\evaltoint$ to $\ebot$ in $\tenv$ to an integer yields the integer $b$\ProseOrTypeError; - \item applying $\evaltoint$ to $\elength$ in $\tenv$ to an integer yields the integer $l$\ProseOrTypeError; - \item $t$ is $b + l - 1$; - \item checking that $t$ is greater or equal to $b$ and that $b$ is greater or equal to $0$ yields $\True$\ProseOrTypeError; - \item $\positions$ is the list of integers from $t$ down to $b$, inclusive. - \end{itemize} - - \item All of the following apply (\textsc{star}): - \begin{itemize} - \item $\vs$ is a slice for a scaled slice given by the expression $\efactor$ - for the factor and $\elength$ for the length of the slice (\texttt{$\elength$*:$\efactor$}), - that is, \\ $\SliceStar(\efactor, \elength)$; - \item applying $\evaltoint$ to $\efactor$ in $\tenv$ to an integer yields the integer $f$\ProseOrTypeError; - \item applying $\evaltoint$ to $\elength$ in $\tenv$ to an integer yields the integer $l$\ProseOrTypeError; - \item $t$ is $(f \times l) + l - 1$; - \item $b$ is $t - l + 1$; - \item checking that $t$ is greater or equal to $b$ and that $b$ is greater or equal to $0$ yields $\True$\ProseOrTypeError; - \item $\positions$ is the list of integers from $t$ down to $b$, inclusive. - \end{itemize} -\end{itemize} - -\subsection{Formally} - -\begin{mathpar} -\inferrule[single]{ - \evaltoint(\tenv, \ve) \typearrow n \terminateas \CannotBeTransformed,\TypeErrorConfig\\\\ - \checktrans{n \geq 0}{BadSlice} \checktransarrow \True \OrTypeError -}{ - \slicetopositions(\tenv, \overname{\SliceSingle(\ve)}{\vs}) \typearrow [ n ] -} -\and -\inferrule[range]{ - \evaltoint(\tenv, \ebot) \typearrow b \terminateas \CannotBeTransformed,\TypeErrorConfig\\\\ - \evaltoint(\tenv, \etop) \typearrow t \terminateas \CannotBeTransformed,\TypeErrorConfig\\\\ - \checktrans{t \geq b \geq 0}{BadSlice} \checktransarrow \True \OrTypeError -}{ - \slicetopositions(\tenv, \overname{\SliceRange(\etop, \ebot)}{\vs}) \typearrow [ t..b ] -} -\and -\inferrule[length]{ - \evaltoint(\tenv, \ebot) \typearrow b \terminateas \CannotBeTransformed,\TypeErrorConfig\\\\ - \evaltoint(\tenv, \elength) \typearrow l \terminateas \CannotBeTransformed,\TypeErrorConfig\\\\ - t \eqdef b + l - 1\\ - \checktrans{t \geq b \geq 0}{BadSlice} \checktransarrow \True \OrTypeError -}{ - \slicetopositions(\tenv, \overname{\SliceLength(\ebot, \elength)}{\vs}) \typearrow [ t..b ] -} -\and -\inferrule[star]{ - \evaltoint(\tenv, \efactor) \typearrow f \terminateas \CannotBeTransformed,\TypeErrorConfig\\\\ - \evaltoint(\tenv, \elength) \typearrow l \terminateas \CannotBeTransformed,\TypeErrorConfig\\\\ - t \eqdef (f \times l) + l - 1\\ - b \eqdef t - l\\ - \checktrans{t \geq b \geq 0}{BadSlice} \checktransarrow \True \OrTypeError -}{ - \slicetopositions(\tenv, \overname{\SliceStar(\efactor, \elength)}{\vs}) \typearrow [ t..b ] -} -\end{mathpar} - -\section{TypingRule.EvalToInt \label{sec:TypingRule.EvalToInt}} -\hypertarget{def-evaltoint}{} -The function -\[ -\evaltoint(\overname{\staticenvs}{\tenv} \aslsep \overname{\expr}{\ve}) -\aslto \overname{\Z}{n} \cup \{\CannotBeTransformed\} \cup \overname{\TTypeError}{\TypeErrorConfig} -\] -statically evaluates the expression $\ve$ to the integer $n$. -The result is $\CannotBeTransformed$ if $\ve$ cannot be statically evaluated -to an integer. -\ProseOtherwiseTypeError - -\subsection{Prose} -All of the following apply: -\begin{itemize} - \item applying $\staticeval$ to $\ve$ in $\tenv$ has one of three outcomes: - \begin{itemize} - \item a literal $\vl$, which satisfies the premise; - \item $\CannotBeTransformed$ (which means the expression could not be evaluated to a literal), - which short-circuits the entire rule; - or - \item $\TypeErrorConfig$ (indicating a type error was detected), which short-circuits the entire rule; - \end{itemize} - \item checking that $\vl$ is an integer literal yields $\True$\ProseOrTypeError; - \item define $\vl$ as the literal integer for $n$. -\end{itemize} - -\subsection{Formally} -\begin{mathpar} -\inferrule{ - \staticeval(\tenv, \ve) \typearrow \vl \terminateas \CannotBeTransformed, \TypeErrorConfig\\\\ - \checktrans{\astlabel(\vl) = \lint}{ExpectedIntegerType} \checktransarrow \True \OrTypeError\\\\ - \vl \eqname \lint(n) -}{ - \evaltoint(\tenv, \ve) \typearrow n -} -\end{mathpar} - -\section{TypingRule.ExtractSlice \label{sec:TypingRule.ExtractSlice}} -\hypertarget{def-extractslice}{} -The function -\[ - \extractslice(\overname{\{0,1\}^*}{\bits} \aslsep \overname{\Z^*}{\positions}) \aslto - \overname{\{0,1\}^*}{\vr} \cup\ \TTypeError -\] -extracts from the list of bits $\bits$ the sublist $\vr$ of bits appearing at the positions given by $\positions$. -\ProseOtherwiseTypeError - -\subsection{Prose} -Define $\vr$ the sublist of $\bits$ given by taking $\bits[\vi]$, for every value given in $\positions$ (in the order they appear). - -\subsection{Formally} -\begin{mathpar} -\inferrule{}{ - \extractslice(\tenv, \bits, \positions) \typearrow \overname{[ \vi\in\positions: \bits[\vi] ]}{\vr} -} -\end{mathpar} - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -\chapter{Symbolic Subsumption Testing \label{chap:symbolicsubsumptiontesting}} -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -This chapter is concerned with implementing a \hyperlink{def-soundsubsumptiontest}{sound subsumption test} for integer types, as defined in \secref{subsumptiontesting} and employed by -TypingRule.SubtypeSatisfaction (see \secref{TypingRule.SubtypeSatisfaction}). - -\hypertarget{def-symbolicdomain}{} -The symbolic reasoning operates by first transforming types into expressions in a \emph{symbolic domain} AST -(defined next, reusing $\intconstraint$ from the untyped AST) over which it then operates: -\hypertarget{def-symdom}{} -\hypertarget{def-finite}{} -\[ - \begin{array}{rcl} - \symdom &::=& \Finite(\powfin{\Z} \setminus \emptyset) \hypertarget{def-top}{}\\ - &| & \Top \hypertarget{def-fromsymtax}{}\\ - &| & \FromSyntax(\syntax) \hypertarget{def-syntax}{}\\ - \syntax &::=& \intconstraint^* - \end{array} -\] - -\begin{itemize} - \item We refer to an element of the form $\Finite(S)$ as a \emph{symbolic finite set integer domain}, - which represents the set of integers $S$; - \item We refer to an element of the form $\FromSyntax(\vcs)$ as a \emph{symbolic constrained integer domain}, - which represents the set of integers given by the list of constraints $\vcs$; and - \item We refer to an element of the form $\Top$ as a \emph{symbolic unconstrained integer domain}, - which represents the set of all integers. -\end{itemize} - -The main rule is of this chapter is TypingRule.SymSubsumes (see \secref{TypingRule.SymSubsumes}), which defines the function -$\symsubsumes$. - -Other helper rules are as follows: -\begin{itemize} - \item TypingRule.SymDomOfType (see \secref{TypingRule.SymDomOfType}) - \item TypingRule.SymDomOfExpr (see \secref{TypingRule.SymDomOfExpr}) - \item TypingRule.SymDomOfWidth (see \secref{TypingRule.SymDomOfWidth}) - \item TypingRule.IntSetOp (see \secref{TypingRule.IntSetOp}) - \item TypingRule.IntSetToIntConstraints (see \secref{TypingRule.IntSetToIntConstraints}) - \item TypingRule.SymDomOfLiteral (see \secref{TypingRule.SymDomOfLiteral}) - \item TypingRule.SymIntSetOfConstraints (see \secref{TypingRule.SymIntSetOfConstraints}) - \item TypingRule.ConstraintToIntSet (see \secref{TypingRule.ConstraintToIntSet}) - \item TypingRule.NormalizeToInt (see \secref{TypingRule.NormalizeToInt}) - \item TypingRule.SymDomIsSubset (see \secref{TypingRule.SymDomIsSubset}) - \item TypingRule.SymIntSetSubset (see \secref{TypingRule.SymIntSetSubset}) - \item TypingRule.ConstraintBinop (see \secref{TypingRule.ConstraintBinop}) - \item TypingRule.IsRightIncreasing (see \secref{TypingRule.IsRightIncreasing}) - \item TypingRule.IsRightDecreasing (see \secref{TypingRule.IsRightDecreasing}) - \item TypingRule.IsLeftIncreasing (see \secref{TypingRule.IsLeftIncreasing}) -\end{itemize} - -\section{TypingRule.SymSubsumes \label{sec:TypingRule.SymSubsumes}} -\hypertarget{def-symsubsumes}{} -The predicate -\[ - \symsubsumes(\overname{\staticenvs}{\tenv} \aslsep \overname{\ty}{\vt} \aslsep \overname{\ty}{\vs}) - \aslto \overname{\Bool}{\vb} -\] -soundly approximates $\subsumes(\tenv, \vt, \vs)$ for integer types. -\ProseOtherwiseTypeError - -We assume that both $\vt$ and $\vs$ have been successfully annotated to integer types as per \chapref{typingoftypes} -(otherwise a typing error prevents us from applying this function). - -\subsection{Prose} -All of the following apply: -\begin{itemize} - \item applying $\symdomoftype$ to $\vt$ in $\tenv$ yields $\dt$; - \item applying $\symdomoftype$ to $\vs$ in $\tenv$ yields $\ds$; - \item applying $\symdomissubset$ to $\dt$ and $\ds$ in $\tenv$ yields $\vb$. -\end{itemize} - -\subsection{Formally} -\begin{mathpar} -\inferrule{ - \symdomoftype(\tenv, \vt) \typearrow \dt\\ - \symdomoftype(\tenv, \vs) \typearrow \ds\\ - \symdomissubset(\tenv, \dt, \ds) \typearrow \vb -}{ - \symsubsumes(\tenv, \vt, \vs) \typearrow \vb -} -\end{mathpar} - -\section{TypingRule.SymDomOfType \label{sec:TypingRule.SymDomOfType}} -\hypertarget{def-symdomoftype}{} -The function -\[ - \symdomoftype(\overname{\staticenvs}{\tenv} \aslsep \overname{\ty}{\vt}) \aslto \overname{\symdom}{\vd} -\] -transforms a type $\vt$ in a static environment $\tenv$ into a symbolic domain $\vd$. -It assumes its input type has an \underlyingtype{} which is an integer. -\subsection{Prose} -One of the following applies: -\begin{itemize} - \item All of the following apply (\textsc{int\_unconstrained}): - \begin{itemize} - \item $\vt$ is the unconstrained integer type; - \item define $\vd$ as $\Top$, which intuitively represents the entire set of integers. - \end{itemize} - - \item All of the following apply (\textsc{int\_parameterized}): - \begin{itemize} - \item $\vt$ is the \parameterizedintegertype\ for the identifier $\id$; - \item define $\vd$ as the symbolic constrained integer domain with a single constraint for the variable expression for $\id$, - that is, \\ $\FromSyntax([\ConstraintExact(\EVar(\id))])$. - \end{itemize} - - \item All of the following apply (\textsc{int\_well\_constrained\_finite}): - \begin{itemize} - \item $\vt$ is the well-constrained integer type for the list of constraints $\vcs$; - \item applying $\intsetofintconstraints$ to $\vcs$ in $\tenv$ yields $\vis$; - \item $\vis$ is a set of integers, that is, $\astlabel(\vis)$ is $\Finite$; - \item define $\vd$ as the symbolic finite set integer domain for $\vis$. - \end{itemize} - - \item All of the following apply (\textsc{int\_well\_constrained\_symbolic}): - \begin{itemize} - \item $\vt$ is the well-constrained integer type for the list of constraints $\vcs$; - \item applying $\intsetofintconstraints$ to $\vcs$ in $\tenv$ yields $\vis$; - \item $\vis$ is not a set of integers, that is, $\astlabel(\vis)$ is not $\Finite$; - \item define $\vd$ as the symbolic constrained integer domain for the list of constraints $\vcs$, that is, $\FromSyntax(\vcs)$. - \end{itemize} - - \item All of the following apply (\textsc{t\_named}): - \begin{itemize} - \item $\vt$ is the named type for identifier $\id$; - \item applying $\makeanonymous$ to $\vt$ in $\tenv$ yields $\vtone$; - \item applying $\symdomoftype$ to $\vtone$ in $\tenv$ yields $\vd$. - \end{itemize} -\end{itemize} - -\subsection{Formally} -\begin{mathpar} -\inferrule[int\_unconstrained]{}{ \symdomoftype(\tenv, \overname{\unconstrainedinteger}{\vt}) \typearrow \overname{\Top}{\vd} } -\end{mathpar} - -\begin{mathpar} -\inferrule[int\_parameterized]{}{ - \symdomoftype(\tenv, \overname{\TInt(\parameterized(\id))}{\vt}) \typearrow \\ - \overname{\FromSyntax([\ConstraintExact(\EVar(\id))])}{\vd} -} -\end{mathpar} - -\begin{mathpar} -\inferrule[int\_well\_constrained\_finite]{ - \intsetofintconstraints(\tenv, \vcs) \typearrow \vis\\ - \astlabel(\vis) = \Finite -}{ - \symdomoftype(\tenv, \overname{\TInt(\wellconstrained(\vcs))}{\vt}) \typearrow \overname{\vis}{\vd} -} -\end{mathpar} - -\begin{mathpar} -\inferrule[int\_well\_constrained\_symbolic]{ - \intsetofintconstraints(\tenv, \vcs) \typearrow \vis\\ - \astlabel(\vis) \neq \Finite -}{ - \symdomoftype(\tenv, \overname{\TInt(\wellconstrained(\vcs))}{\vt}) \typearrow \overname{\FromSyntax(\vcs)}{\vd} -} -\end{mathpar} - -\begin{mathpar} -\inferrule[t\_named]{ - \vt = \TNamed(\id)\\ - \makeanonymous(\vt) \typearrow \vtone\\ - \symdomoftype(\tenv, \vtone) \typearrow \vd -}{ - \symdomoftype(\tenv, \vt) \typearrow \vd -} -\end{mathpar} - -\section{TypingRule.SymDomOfExpr \label{sec:TypingRule.SymDomOfExpr}} -\hypertarget{def-symdomofexpr}{} -The function -\[ -\symdomofexpr( - \overname{\staticenvs}{\tenv} \aslsep - \overname{\expr}{\ve} -) \aslto -\overname{\symdom}{\vd} -\] -assigns a symbolic domain $\vd$ to an \underline{integer typed} expression $\ve$ in the static environment $\tenv$. - -\subsection{Prose} -One of the following applies: -\begin{itemize} - \item All of the following apply (\textsc{e\_literal}): - \begin{itemize} - \item $\ve$ is a literal expression for the literal $\vv$; - \item applying $\symdomofliteral$ to $\vv$ yields $\vd$. - \end{itemize} - - \item All of the following apply (\textsc{e\_var\_constant}): - \begin{itemize} - \item $\ve$ is a variable expression for the identifier $\vx$; - \item applying $\lookupconstant$ to $\vx$ in $\tenv$ yields the literal $\vv$; - \item applying $\symdomofliteral$ to $\vv$ yields $\vd$. - \end{itemize} - - \item All of the following apply (\textsc{e\_var\_type}): - \begin{itemize} - \item $\ve$ is a variable expression for the identifier $\vx$; - \item applying $\lookupconstant$ to $\vx$ in $\tenv$ yields $\bot$; - \item applying $\typeof$ to $\vx$ in $\tenv$ yields $\vtone$; - \item applying $\symdomoftype$ to $\vtone$ yields $\vd$. - \end{itemize} - - \item All of the following apply (\textsc{e\_unop\_minus}): - \begin{itemize} - \item $\ve$ is a unary operation expression for the operation $\MINUS$ and subexpression $\veone$; - \item applying $\symdomofexpr$ to the binary operation expression with the operation $\MINUS$ - and the literal expression for $0$ and $\veone$ in $\tenv$ yields $\vd$. - \end{itemize} - - \item All of the following apply (\textsc{e\_unop\_unknown}): - \begin{itemize} - \item $\ve$ is a unary operation expression for an operation that is not $\MINUS$; - \item define $\vd$ as $\FromSyntax([\ConstraintExact(\ve)])$ - \end{itemize} - - \item All of the following apply (\textsc{e\_binop\_supported}): - \begin{itemize} - \item $\ve$ is a binary operation expression for an operation that is one of $\PLUS$, $\MINUS$, or $\MUL$ - and subexpressions $\veone$ and $\vetwo$; - \item applying $\symdomofexpr$ to $\veone$ in $\tenv$ yields a symbolic domain $\visone$; - \item applying $\symdomofexpr$ to $\vetwo$ in $\tenv$ yields a symbolic domain $\vistwo$; - \item applying $\intsetop$ to $\op$ and $\visone$ and $\vistwo$ yields $\vis$; - \item define $\vd$ as $\vis$. - \end{itemize} - - \item All of the following apply (\textsc{e\_binop\_unsupported}): - \begin{itemize} - \item $\ve$ is a binary operation expression for an operation that is not one of $\PLUS$, $\MINUS$, or $\MUL$; - \item define $\vd$ as $\FromSyntax([\ConstraintExact(\ve)])$ - \end{itemize} - - \item All of the following apply (\textsc{unsupported}): - \begin{itemize} - \item $\ve$ is not one of the following expression types a literal expression, a variable expression, a unary operation - expression, or a binary operation expression; - \item define $\vd$ as $\FromSyntax([\ConstraintExact(\ve)])$ - \end{itemize} -\end{itemize} - -\subsection{Formally} -\begin{mathpar} -\inferrule[e\_literal]{ - \symdomofliteral(\vv) \typearrow \vd -}{ - \symdomofexpr(\tenv, \overname{\ELiteral(\vv)}{\ve}) \typearrow \vd -} -\end{mathpar} - -\begin{mathpar} -\inferrule[e\_var\_constant]{ - \lookupconstant(\tenv, \vx) \typearrow \vv\\ - \symdomofliteral(\vv) \typearrow \vd -}{ - \symdomofexpr(\tenv, \overname{\EVar(\vx)}{\ve}) \typearrow \vd -} -\end{mathpar} - -\begin{mathpar} -\inferrule[e\_var\_type]{ - \lookupconstant(\tenv, \vx) \typearrow \bot\\ - \typeof(\tenv, \vx) \typearrow \vtone\\ - \symdomoftype(\vtone) \typearrow \vd -}{ - \symdomofexpr(\tenv, \overname{\EVar(\vx)}{\ve}) \typearrow \vd -} -\end{mathpar} - -\begin{mathpar} -\inferrule[e\_unop\_minus]{ - \symdomofexpr(\EBinop(\MINUS, \ELiteral(\lint(0)), \veone)) \typearrow \vd -}{ - \symdomofexpr(\tenv, \overname{\EUnop(\MINUS, \veone)}{\ve}) \typearrow \vd -} -\end{mathpar} - -\begin{mathpar} -\inferrule[e\_unop\_unknown]{ - \op \neq \MINUS -}{ - \symdomofexpr(\tenv, \overname{\EUnop(\op, \veone)}{\ve}) \typearrow \overname{\FromSyntax([\ConstraintExact(\ve)])}{\vd} -} -\end{mathpar} - -\begin{mathpar} -\inferrule[e\_binop\_supported]{ - \op \in \{\PLUS, \MINUS, \MUL\}\\ - \symdomofexpr(\tenv, \veone) \typearrow \visone\\ - \symdomofexpr(\tenv, \vetwo) \typearrow \vistwo\\ - \intsetop(\op, \visone, \vistwo) \typearrow \vis -}{ - \symdomofexpr(\tenv, \overname{\EBinop(\op, \veone, \vetwo)}{\ve}) \typearrow \overname{\vis}{\vd} -} -\end{mathpar} - -\begin{mathpar} -\inferrule[e\_binop\_unsupported]{ - \op \not\in \{\PLUS, \MINUS, \MUL\}\\ -}{ - \symdomofexpr(\tenv, \overname{\EBinop(\op, \Ignore, \Ignore)}{\ve}) \typearrow \overname{\FromSyntax([\ConstraintExact(\ve)])}{\vd} -} -\end{mathpar} - -\begin{mathpar} -\inferrule[unsupported]{ - \astlabel(\ve) \not\in \{\ELiteral, \EVar, \EUnop, \EBinop\} -}{ - \symdomofexpr(\tenv, \ve) \typearrow \overname{\FromSyntax([\ConstraintExact(\ve)])}{\vd} -} -\end{mathpar} - -\section{TypingRule.SymDomOfWidth \label{sec:TypingRule.SymDomOfWidth}} -\hypertarget{def-symdomofwidth}{} -The function -\[ -\symdomofwidth( - \overname{\staticenvs}{\tenv} \aslsep - \overname{\expr}{\ve} -) \aslto -\overname{\symdom}{\vd} -\] -assigns a symbolic domain $\vd$ to an \underline{integer typed} expression $\ve$ in the static environment $\tenv$. -In contrast to $\symdomofexpr$, $\symdomofwidth$ should be applied to expressions that represent a bit vector width. - -\subsection{Prose} -One of the following applies: -\begin{itemize} - \item All of the following apply (\textsc{finite\_one\_width}): - \begin{itemize} - \item applying $\symdomofexpr$ to $\ve$ in $\tenv$ yields $\vdone$; - \item $\vdone$ is a set of integers, that is, $\Finite(s)$; - \item the cardinality of $s$ is one; - \item $\vd$ is $\vdone$. - \end{itemize} - - \item All of the following apply (\textsc{finite\_multiple\_widths}): - \begin{itemize} - \item applying $\symdomofexpr$ to $\ve$ in $\tenv$ yields $\vdone$; - \item $\vdone$ is a set of integers, that is, $\Finite(s)$; - \item the cardinality of $s$ is \emph{not} one; - \item define $\vd$ as $\FromSyntax([\ConstraintExact(\ve)])$. - \end{itemize} - - \item All of the following apply (\textsc{non\_finite}): - \begin{itemize} - \item applying $\symdomofexpr$ to $\ve$ in $\tenv$ yields $\vdone$; - \item $\vdone$ is not a set of integers, that is, $\astlabel(\vdone)$ is not $\Finite$; - \item define $\vd$ as $\FromSyntax([\ConstraintExact(\ve)])$. - \end{itemize} -\end{itemize} - -\subsection{Formally} -\begin{mathpar} -\inferrule[finite\_one\_width]{ - \symdomofexpr(\tenv, \ve) \typearrow \vdone \\ - \vdone = \Finite(s) \\ - \cardinality{s} = 1 -}{ - \symdomofwidth(\tenv, \ve) \typearrow \overname{\vdone}{\vd} -} -\end{mathpar} - -\begin{mathpar} -\inferrule[finite\_multiple\_widths]{ - \symdomofexpr(\tenv, \ve) \typearrow \vdone \\ - \vdone = \Finite(s) \\ - \cardinality{s} \neq 1 -}{ - \symdomofwidth(\tenv, \ve) \typearrow \overname{\FromSyntax([\ConstraintExact(\ve)])}{\vd} -} -\end{mathpar} - -\begin{mathpar} -\inferrule[non\_finite]{ - \symdomofexpr(\tenv, \ve) \typearrow \vdone \\ - \astlabel(\vdone) \neq \Finite -}{ - \symdomofwidth(\tenv, \ve) \typearrow \overname{\FromSyntax([\ConstraintExact(\ve)])}{\vd} -} -\end{mathpar} - -\section{TypingRule.IntSetOp \label{sec:TypingRule.IntSetOp}} -\hypertarget{def-intsetop}{} -The function -\[ -\intsetop(\overname{\binop}{\op} \aslsep \overname{\symdom}{\visone} \aslsep \overname{\symdom}{\vistwo}) -\aslto \overname{\symdom}{\vis} -\] -applies the binary operation $\op$ to the symbolic domains $\visone$ and $\vistwo$, -yielding the symbolic domain $\vis$. - -\subsection{Prose} -One of the following applies: -\begin{itemize} - \item All of the following apply (\textsc{top}): - \begin{itemize} - \item at least one of $\visone$ and $\vistwo$ is $\Top$; - \item define $\vis$ as $\Top$. - \end{itemize} - - \item All of the following apply (\textsc{finite\_finite}): - \begin{itemize} - \item $\visone$ is the symbolic finite set integer domain for $\vsone$; - \item $\vistwo$ is the symbolic finite set integer domain for $\vstwo$; - \item define $\vis$ as the symbolic finite set domain for the set obtained - by applying $\op$ to each element of $\vsone$ and each element of $\vstwo$. - \end{itemize} - - \item All of the following apply (\textsc{finite\_syntax}): - \begin{itemize} - \item $\visone$ is the symbolic finite set integer domain for $\vsone$; - \item $\vistwo$ is the symbolic constrained integer domain for $\vstwo$; - \item applying $\intsettointconstraints$ to $\vsone$ yields the list of constraints $\csone$; - \item applying $\intsetop$ to $\op$, the symbolic constrained integer domain for $\csone$, - and $\vistwo$ yields $\vis$. - \end{itemize} - - \item All of the following apply (\textsc{syntax\_finite}): - \begin{itemize} - \item $\visone$ is the symbolic constrained integer domain for $\csone$; - \item $\vistwo$ is the symbolic finite set integer domain for $\vstwo$; - \item applying $\intsettointconstraints$ to $\vstwo$ yields the list of constraints $\cstwo$; - \item applying $\intsetop$ to $\op$, $\visone$, and the symbolic constrained integer domain - for $\cstwo$, yields $\vis$. - \end{itemize} - - \item All of the following apply (\textsc{syntax\_syntax\_well\_constrained}): - \begin{itemize} - \item $\visone$ is the symbolic constrained integer domain for $\csone$; - \item $\vistwo$ is the symbolic constrained integer domain for $\cstwo$; - \item applying $\constraintbinop$ to $\op$, $\csone$, and $\cstwo$ yields - a list of constraints $\vcs$; - \item define $\vis$ as the symbolic constrained integer domain for $\vcs$. - \end{itemize} - - \item All of the following apply (\textsc{syntax\_syntax\_top}): - \begin{itemize} - \item $\visone$ is the symbolic constrained integer domain for $\csone$; - \item $\vistwo$ is the symbolic constrained integer domain for $\cstwo$; - \item applying $\constraintbinop$ to $\op$, $\csone$, and $\cstwo$ yields $\top$; - \item define $\vis$ as $\Top$. - \end{itemize} -\end{itemize} - -\subsection{Formally} -\begin{mathpar} -\inferrule[top]{ - \visone = \Top \lor \vistwo = \Top -}{ - \intsetop(\op, \visone, \vistwo) \typearrow \overname{\Top}{\vis} -} -\and -\inferrule[finite\_finite]{ - \vis \eqdef \Finite(\{ \op(a, b) \;|\; a \in \vsone, b \in \vstwo \}) -}{ - \intsetop(\op, \overname{\Finite(\vsone)}{\visone}, \overname{\Finite(\vstwo)}{\vistwo}) \typearrow \vis -} -\end{mathpar} - -\begin{mathpar} -\inferrule[finite\_syntax]{ - \intsettointconstraints(\vsone) \typearrow \vcsone\\ - \intsetop(\op, \FromSyntax(\vcsone), \FromSyntax(\vcstwo)) \typearrow \vis -}{ - \intsetop(\op, \overname{\Finite(\vsone)}{\visone}, \overname{\FromSyntax(\vcstwo)}{\vistwo}) \typearrow \vis -} -\end{mathpar} - -\begin{mathpar} -\inferrule[syntax\_finite]{ - \intsettointconstraints(\vstwo) \typearrow \vcstwo\\ - \intsetop(\op, \FromSyntax(\vcsone), \FromSyntax(\vcstwo)) \typearrow \vis -}{ - \intsetop(\op, \overname{\FromSyntax(\vcsone)}{\visone}, \overname{\Finite(\vstwo)}{\vistwo}) \typearrow \vis -} -\end{mathpar} - -\begin{mathpar} -\inferrule[syntax\_syntax\_well\_constrained]{ - \constraintbinop(\op, \vcsone, \vcstwo) \typearrow \wellconstrained(\vcs) -}{ - \intsetop(\op, \overname{\FromSyntax(\vcsone)}{\visone}, \overname{\FromSyntax(\vcstwo)}{\vistwo}) \typearrow \overname{\FromSyntax(\vcs)}{\vis} -} -\end{mathpar} - -\begin{mathpar} -\inferrule[syntax\_syntax\_top]{ - \constraintbinop(\op, \vcsone, \vcstwo) \typearrow \top -}{ - \intsetop(\op, \overname{\FromSyntax(\vcsone)}{\visone}, \overname{\FromSyntax(\vcstwo)}{\vistwo}) \typearrow \overname{\Top}{\vis} -} -\end{mathpar} - -\section{TypingRule.IntSetToIntConstraints \label{sec:TypingRule.IntSetToIntConstraints}} -\hypertarget{def-intsettointconstraints}{} -The function -\[ -\intsettointconstraints(\overname{\powfin{\Z}}{\vs}) -\aslto \overname{\intconstraint^*}{\cs} -\] -transforms a finite set of integers into the equivalent list of integer constraints. - -\subsection{Prose} -One of the following applies: -\begin{itemize} - \item All of the following apply (\textsc{empty}): - \begin{itemize} - \item $\vs$ is the empty set; - \item define $\cs$ as the empty list. - \end{itemize} - - \item All of the following apply (\textsc{singleton}): - \begin{itemize} - \item $\vs$ is the singleton set for $a$; - \item define $\cs$ as the list containing the single range constraint for the interval starting from $a$ - and ending at $a$, that is, $\ConstraintRange(\ELInt{a}, \ELInt{a})$. - \end{itemize} - - \item All of the following apply (\textsc{new\_interval}): - \begin{itemize} - \item define $a$ as the minimal element of $\vs$; - \item define $\vsone$ as the set $\vs$ with $a$ removed from it; - \item applying $\intsettointconstraints$ to $\vsone$ yields the list of constraints $\csone$; - \item $\csone$ is a list where its \head\ is a range constraint for the interval starting from $b$ and ending at $c$ - and \tail\ $\cstwo$; - \item $b$ is greater than $a+1$; - \item define $\cs$ as the list with first element a range constraint for the interval from $a$ to $a$, - second element a range constraint for the interval from $b$ to $c$, and remaining elements given by $\cstwo$. - \end{itemize} - - \item All of the following apply (\textsc{merge\_interval}): - \begin{itemize} - \item define $a$ as the minimal element of $\vs$; - \item define $\vsone$ as the set $\vs$ with $a$ removed from it; - \item applying $\intsettointconstraints$ to $\vsone$ yields the list of constraints $\csone$; - \item $\csone$ is a list where its \head\ is a range constraint for the interval starting from $b$ and ending at $c$ - and \tail\ $\cstwo$; - \item $b$ is equal to $a+1$; - \item define $\cs$ as the list with \head\ a range constraint for the interval from $a$ to $c$ - and \tail\ $\cstwo$. - \end{itemize} -\end{itemize} - -\subsection{Formally} -\begin{mathpar} -\inferrule[empty]{}{ - \intsettointconstraints(\overname{\emptyset}{\vs}) \typearrow \overname{\emptylist}{\cs} -} -\end{mathpar} - -\begin{mathpar} -\inferrule[singleton]{}{ - \intsettointconstraints(\overname{\{a\}}{\vs}) \typearrow \overname{[\ConstraintRange(\ELInt{a}, \ELInt{a})]}{\cs} -} -\end{mathpar} - -\begin{mathpar} -\inferrule[new\_interval]{ - a = \min(\vs)\\ - \vsone \eqdef \vs \setminus \{a\}\\ - \intsettointconstraints(\vsone) \typearrow \csone\\ - \csone = [\ConstraintRange(\ELInt{b}, \ELInt{c})] \concat \cstwo\\ - b > a + 1\\\\ - { - \begin{array}{rcl} - \cs &\eqdef & [\ConstraintRange(\ELInt{a}, \ELInt{a})]\ \concat\\ - & & [\ConstraintRange(\ELInt{b}, \ELInt{c})]\ \concat \\ - & & \cstwo - \end{array} - } -}{ - \intsettointconstraints(\vs) \typearrow \cs -} -\end{mathpar} - -\begin{mathpar} -\inferrule[merge\_interval]{ - a = \min(\vs)\\ - \vsone \eqdef \vs \setminus \{a\}\\ - \intsettointconstraints(\vsone) \typearrow \csone\\ - \csone = [\ConstraintRange(\ELInt{b}, \ELInt{c})] \concat \cstwo\\ - b = a + 1\\ - \cs \eqdef [\ConstraintRange(\ELInt{a}, \ELInt{c})] \concat \cstwo -}{ - \intsettointconstraints(\vs) \typearrow \cs -} -\end{mathpar} - -\section{TypingRule.SymDomOfLiteral \label{sec:TypingRule.SymDomOfLiteral}} -\hypertarget{def-symdomofliteral}{} -The function -\[ -\symdomofliteral(\overname{\literal}{\vv}) \typearrow \overname{\symdom}{\vd} -\] -returns the symbolic domain $\vd$ that corresponds to the literal $\vv$. - -\subsection{Prose} -All of the following apply: -\begin{itemize} - \item $\vv$ is an integer literal for $n$; - \item define $\vd$ as the symbolic finite set integer domain for the singleton set for $n$, that is, $\Finite(\{n\})$. -\end{itemize} - -\subsection{Formally} -\begin{mathpar} -\inferrule{}{ - \symdomofliteral(\overname{\lint(n)}{\vv}) \typearrow \overname{\Finite(\{n\})}{\vd} -} -\end{mathpar} - -\section{TypingRule.SymIntSetOfConstraints \label{sec:TypingRule.SymIntSetOfConstraints}} -\hypertarget{def-intsetofintconstraintse}{} -The function -\[ - \intsetofintconstraints( - \overname{\staticenvs}{\tenv} \aslsep - \overname{\constraints}{\vcs} - ) \aslto - \overname{\symdom}{\vis} -\] -returns the symbolic domain $\vis$ for the list of constraints $\vcs$ -in the static environment $\tenv$. - -\subsection{Prose} -One of the following applies: -\begin{itemize} - \item All of the following apply (\textsc{finite}): - \begin{itemize} - \item applying $\constrainttointset$ to every constraint $\vcs[\vi]$ in $\tenv$, for $\vi$ in \\ $\listrange(\vcs)$, - yields a finite set of integers $C_\vi$, that is, $\Finite(C_\vi)$; - \item define $\vis$ as the union of $C_\vi$ for all $\vi$ in $\listrange(\vcs)$. - \end{itemize} - - \item All of the following apply (\textsc{symbolic}): - \begin{itemize} - \item there exists a constraint $\vc$ in $\vcs$ such that applying $\constrainttointset$ to $\vc$ - in $\tenv$ does not yield a finite set of integers; - \item define $\vis$ as the symbolic constrained integer domain for $\vcs$, that is, \\ - $\FromSyntax(\vcs)$. - \end{itemize} -\end{itemize} - -\subsection{Formally} -\begin{mathpar} -\inferrule[finite]{ - \vi\in\listrange(\vcs): \constrainttointset(\tenv, \vcs[\vi]) \typearrow \Finite(C_\vi)\\ - C \eqdef \bigcup_{\vi\in\listrange(\vcs)} C_\vi -}{ - \intsetofintconstraints(\tenv, \vcs) \typearrow \overname{\Finite(C)}{\vis} -} -\end{mathpar} - -\begin{mathpar} -\inferrule[symbolic]{ - { - \begin{array}{r} - \exists \vi\in\listrange(\vcs): \constrainttointset(\tenv, \vcs[\vi]) \typearrow \\ - \visone \land \astlabel(\visone) \neq \Finite - \end{array} - } -}{ - \intsetofintconstraints(\tenv, \vcs) \typearrow \overname{\FromSyntax(\vcs)}{\vis} -} -\end{mathpar} - -\section{TypingRule.ConstraintToIntSet \label{sec:TypingRule.ConstraintToIntSet}} -\hypertarget{def-constrainttointset}{} -The function -\[ - \constrainttointset( - \overname{\staticenvs}{\tenv} \aslsep - \overname{\intconstraint}{\vc} - ) \aslto - \overname{\symdom}{\vis} -\] -transforms an integer constraint $\vc$ into a symbolic domain $\vis$. -It produces $\Top$ when the expressions involved in the integer constraints cannot be simplified -to integers. - -\subsection{Prose} -One of the following applies: -\begin{itemize} - \item All of the following apply (\textsc{exact}): - \begin{itemize} - \item $\vc$ is a single expression constraint for $\ve$, that is, $\ConstraintExact(\ve)$; - \item applying $\normalizetoint$ to $\ve$ in $\tenv$ yields the integer $n$\ProseTerminateAs{\Top}; - \item define $\vis$ as the singleton set for $n$, that is, $\Finite(\{n\})$. - \end{itemize} - - \item All of the following apply (\textsc{range}): - \begin{itemize} - \item $\vc$ is a range constraint for $\veone$ and $\vetwo$, that is, $\ConstraintRange(\veone, \vetwo)$; - \item applying $\normalizetoint$ to $\veone$ in $\tenv$ yields the integer $b$\ProseTerminateAs{\Top}; - \item applying $\normalizetoint$ to $\vetwo$ in $\tenv$ yields the integer $t$\ProseTerminateAs{\Top}; - \item define $\vis$ as the set integers that are both greater or equal to $b$ and less than or equal to $t$. - \end{itemize} -\end{itemize} - -\subsection{Formally} -\begin{mathpar} -\inferrule[exact]{ - \normalizetoint(\tenv, \ve) \typearrow n \terminateas \Top -}{ - \constrainttointset(\tenv, \overname{\ConstraintExact(\ve)}{\vc}) \typearrow \overname{\Finite(\{n\})}{\vis} -} -\and -\inferrule[range]{ - \normalizetoint(\tenv, \veone) \typearrow b \terminateas \Top\\\\ - \normalizetoint(\tenv, \vetwo) \typearrow t \terminateas \Top\\\\ - \vis \eqdef \Finite(\{ n \;|\; b \leq n \leq t\}) -}{ - \constrainttointset(\tenv, \overname{\ConstraintRange(\veone, \vetwo)}{\vc}) \typearrow \vis -} -\end{mathpar} - -\section{TypingRule.NormalizeToInt \label{sec:TypingRule.NormalizeToInt}} -\hypertarget{def-normalizetoint}{} -The function -\[ -\normalizetoint( - \overname{\staticenvs}{\tenv} \aslsep - \overname{\expr}{\ve} -) \aslto \overname{\Z}{n} \cup \{\Top\} -\] -\symbolicallysimplifies\ the \underline{integer-typed} expression $\ve$ and returns the resulting integer or $\Top$ if -the result of the simplification is not an integer. - -\subsection{Prose} -One of the following applies: -\begin{itemize} - \item All of the following apply (\textsc{integer}): - \begin{itemize} - \item applying $\staticeval$ to $\veone$ in $\tenv$ yields the integer literal for $n$. - \end{itemize} - - \item All of the following apply (\textsc{top}): - \begin{itemize} - \item applying $\staticeval$ to $\veone$ in $\tenv$ yields $\top$; - \item the result is $\Top$. - \end{itemize} -\end{itemize} - -\subsection{Formally} -\begin{mathpar} -\inferrule[integer]{ - \staticeval(\tenv, \ve) \typearrow \lint(n) -}{ - \normalizetoint(\tenv, \ve) \typearrow n -} -\and -\inferrule[top]{ - \staticeval(\tenv, \ve) \typearrow \top -}{ - \normalizetoint(\tenv, \ve) \typearrow \Top -} -\end{mathpar} - -\section{TypingRule.SymDomIsSubset \label{sec:TypingRule.SymDomIsSubset}} -\hypertarget{def-symdomissubset}{} -The function -\[ - \symdomissubset( - \overname{\staticenvs}{\tenv} \aslsep - \overname{\symdom}{\vdone} \aslsep - \overname{\symdom}{\vdtwo} - ) \aslto - \overname{\Bool}{\vb} -\] -conservatively tests whether the symbolic domain $\vdone$ is subsumed by the symbolic domain $\vdtwo$, -yielding the result $\vb$. - -\subsection{Prose} -All of the following apply: -\begin{itemize} - \item applying $\symintsetsubset$ to $\vdone$ and $\vdtwo$ in $\tenv$ yields $\vb$. -\end{itemize} - -\subsection{Formally} -\begin{mathpar} -\inferrule[int]{ - \symintsetsubset(\tenv, \vdone, \vdtwo) \typearrow \vb -}{ - \symdomissubset(\tenv, \vdone, \vdtwo) \typearrow \vb -} -\end{mathpar} - -\section{TypingRule.SymIntSetSubset \label{sec:TypingRule.SymIntSetSubset}} -\hypertarget{def-symintsetsubset}{} -The function -\[ -\symintsetsubset(\overname{\staticenvs}{\tenv} \aslsep \overname{\symdom}{\visone} \aslsep \overname{\symdom}{\vistwo}) \aslto \overname{\Bool}{\vb} -\] - -\subsection{Prose} -One of the following applies: -\begin{itemize} - \item All of the following apply (\textsc{right\_top}): - \begin{itemize} - \item $\vistwo$ is $\Top$; - \item define $\vb$ as $\True$. - \end{itemize} - - \item All of the following apply (\textsc{left\_top\_right\_not\_top}): - \begin{itemize} - \item $\visone$ is $\Top$; - \item $\vistwo$ is not $\Top$; - \item define $\vb$ as $\False$. - \end{itemize} - - \item All of the following apply (\textsc{finite}): - \begin{itemize} - \item $\visone$ is a finite set of integers for $\vsone$, that is, $\Finite(\vsone)$; - \item $\vistwo$ is a finite set of integers for $\vstwo$, that is, $\Finite(\vstwo)$; - \item define $\vb$ as $\True$ if and only if $\vsone$ is a subset of $\vstwo$ or both sets are equal. - \end{itemize} - - \item All of the following apply (\textsc{syntax}): - \begin{itemize} - \item $\visone$ is a set of integers given by the list of constraints $\csone$, that is, \\ $\FromSyntax(\vsone)$; - \item $\vistwo$ is a set of integers given by the list of constraints $\cstwo$, that is, \\ $\FromSyntax(\vstwo)$; - \item applying $\constraintsequal$ to $\csone$ and $\cstwo$ in $\tenv$ yields $\vb$. - \end{itemize} - - \item All of the following apply (\textsc{other}): - \begin{itemize} - \item both $\visone$ and $\vistwo$ are not $\Top$; - \item the AST labels of $\visone$ and $\vistwo$ are different; - \item define $\vb$ as $\False$. - \end{itemize} -\end{itemize} - -\subsection{Formally} -\begin{mathpar} -\inferrule[right\_top]{}{ - \symintsetsubset(\tenv, \visone, \overname{\Top}{\vistwo}) \typearrow \overname{\True}{\vb} -} -\end{mathpar} - -\begin{mathpar} -\inferrule[left\_top\_right\_not\_top]{ - \vistwo \neq \Top -}{ - \symintsetsubset(\tenv, \overname{\Top}{\visone}, \vistwo) \typearrow \overname{\False}{\vb} -} -\end{mathpar} - -\begin{mathpar} -\inferrule[finite]{}{ - \symintsetsubset(\tenv, \overname{\Finite(\vsone)}{\visone}, \overname{\Finite(\vstwo)}{\vistwo}) \typearrow \overname{\vsone \subseteq \vstwo}{\vb} -} -\end{mathpar} - -\begin{mathpar} -\inferrule[syntax]{ - \constraintsequal(\tenv, \csone, \cstwo) \typearrow \vb -}{ - \symintsetsubset(\tenv, \overname{\FromSyntax(\csone)}{\visone}, \overname{\FromSyntax(\cstwo)}{\vistwo}) \typearrow \vb -} -\end{mathpar} - -\begin{mathpar} -\inferrule[other]{ - \visone \neq \Top \and \vistwo \neq \Top\\ - \astlabel(\visone) \neq \astlabel(\vistwo) -}{ - \symintsetsubset(\tenv, \visone, \vistwo) \typearrow \overname{\False}{\vb} -} -\end{mathpar} - -\section{TypingRule.ConstraintBinop \label{sec:TypingRule.ConstraintBinop}} -\hypertarget{def-constraintbinop}{} -The function -\[ -\constraintbinop( - \overname{\binop}{\op} \aslsep - \overname{\intconstraint^*}{\csone} \aslsep - \overname{\intconstraint^*}{\cstwo} -) -\aslto \overname{\intconstraints}{\vics} -\] -symbolically applies the binary operation $\op$ to the lists of integer constraints $\csone$ and $\cstwo$, -yielding the integer constraints $\vics$. - -\subsection{Prose} -One of the following applies: -\begin{itemize} - \item All of the following apply (\textsc{well\_constrained}): - \begin{itemize} - \item for every $\vi$ in $\listrange(\csone)$ and every $\vj$ in $\listrange(\cstwo)$, - applying \\ - $\constraintbinoppair$ to $\op$, $\csone[\vi]$, and $\cstwo[\vj]$, - yields the constraint $\vc_{(\vi,\vj)}$; - \item define $\cs$ as the list consisting of constraints $\vc_{(\vi,\vj)}$, - for every $\vi$ in $\listrange(\csone)$ and every $\vj$ in $\listrange(\cstwo)$; - \item $\vics$ is the well-constrained list of constrains $\cs$. - \end{itemize} - - \item All of the following apply (\textsc{unconstrained}): - \begin{itemize} - \item there exist $\vi$ in $\listrange(\csone)$ and $\vj$ in $\listrange(\cstwo)$, - such that applying - $\constraintbinoppair$ to $\op$, $\csone[\vi]$, and $\cstwo[\vj]$, - yields $\top$; - \item $\vics$ is $\unconstrained$. - \end{itemize} -\end{itemize} - -\subsection{Formally} -\begin{mathpar} -\inferrule[well\_constrained]{ - { - \begin{array}{l} - \vi\in\listrange(\csone), \vj\in\listrange(\cstwo): \\ - \constraintbinoppair(\op, \csone[\vi], \cstwo[\vj]) \typearrow \vc_{(\vi,\vj)} - \end{array} - }\\ - \cs \eqdef [\vi\in\listrange(\csone), \vj\in\listrange(\cstwo): \vc_{(\vi,\vj)}] -}{ - \constraintbinop(\op, \csone, \cstwo) \typearrow \overname{\wellconstrained(\cs)}{\vics} -} -\end{mathpar} - -\begin{mathpar} -\inferrule[unconstrained]{ - { - \begin{array}{l} - \exists \vi\in\listrange(\csone).\ \exists \vj\in\listrange(\cstwo).\ \\ - \constraintbinoppair(\op, \csone[\vi], \cstwo[\vj]) \typearrow \top - \end{array} - } -}{ - \constraintbinop(\op, \csone, \cstwo) \typearrow \overname{\unconstrained}{\vics} -} -\end{mathpar} - -\section{TypingRule.ConstraintBinopPair \label{sec:TypingRule.ConstraintBinopPair}} -\hypertarget{def-constraintbinoppair}{} -The function -\[ -\constraintbinoppair( - \overname{\binop}{\op} \aslsep - \overname{\intconstraint}{\vcone} \aslsep - \overname{\intconstraint}{\vctwo} -) -\aslto \overname{\overname{\intconstraint}{\vc} \cup \{\top\}}{\vres} -\] -symbolically applies the binary operation $\op$ to the pair of integer constraints $\vcone$ and $\vctwo$, -yielding $\vres$ which is an integer constraint $\vc$ or -$\top$, which indicates a failure in representing the result as an integer constraint. - -\subsection{Prose} -One of the following applies: -\begin{itemize} - \item All of the following apply (\textsc{exact\_exact}): - \begin{itemize} - \item $\vcone$ is an exact constraint for the expression $\veone$, that is, \ConstraintExact(\veone); - \item $\vctwo$ is an exact constraint for the expression $\vetwo$, that is, \ConstraintExact(\vetwo); - \item define $\vc$ as the exact constraint for the binary operation expression with $\op$, $\veone$, and $\vetwo$, - that is, $\ConstraintExact(\EBinop(\op, \veone, \vetwo))$; - \end{itemize} - - \item All of the following apply (\textsc{exact\_range}): - \begin{itemize} - \item $\vcone$ is an exact constraint for the expression $\veone$, that is, $\ConstraintExact(\veone)$; - \item $\vctwo$ is an range constraint for the expressions $\vetwoone$ and $\vetwotwo$, that is, \\ $\ConstraintRange(\vetwoone, \vetwotwo)$; - \item One of the following applies: - \begin{itemize} - \item All of the following apply: - \begin{itemize} - \item applying $\isrightincreasing$ to $\op$ yields $\True$; - \item define $\vc$ as the range constraint for the following two expressions: - the binary operation expression for $\op$ $\veone$ and $\vetwoone$, and - the binary operation expression for $\op$ $\veone$ and $\vetwotwo$; - \end{itemize} - - \item All of the following apply: - \begin{itemize} - \item applying $\isrightdecreasing$ to $\op$ yields $\True$; - \item define $\vc$ as the range constraint for the following two expressions: - the binary operation expression for $\op$ $\veone$ and $\vetwotwo$, and - the binary operation expression for $\op$ $\veone$ and $\vetwoone$; - \end{itemize} - - \item Otherwise, the result is $\Top$; - \end{itemize} - \end{itemize} - - \item All of the following apply (\textsc{range\_exact}): - \begin{itemize} - \item $\vcone$ is an range constraint for the expressions $\veoneone$ and $\veonetwo$, that is, \\ $\ConstraintRange(\veoneone, \veonetwo)$; - \item $\vctwo$ is an exact constraint for the expression $\vetwo$, that is, $\ConstraintExact(\vetwo)$; - \item One of the following applies: - \begin{itemize} - \item All of the following apply: - \begin{itemize} - \item applying $\isleftincreasing$ to $\op$ yields $\True$; - \item define $\vc$ as the range constraint for the following two expressions: - the binary operation expression for $\op$ $\veoneone$ and $\vetwo$, and - the binary operation expression for $\op$ $\veonetwo$ and $\vetwo$; - \end{itemize} - \item Otherwise, the result is $\Top$. - \end{itemize} - \end{itemize} - - \item All of the following apply (\textsc{range\_range}): - \begin{itemize} - \item $\vcone$ is an range constraint for the expressions $\veoneone$ and $\veonetwo$, that is, \\ $\ConstraintRange(\veoneone, \veonetwo)$; - \item $\vctwo$ is an range constraint for the expressions $\vetwoone$ and $\vetwotwo$, that is, \\ $\ConstraintRange(\vetwoone, \vetwotwo)$; - \item One of the following applies: - \begin{itemize} - \item All of the following apply: - \begin{itemize} - \item applying $\isleftincreasing$ to $\op$ yields $\True$; - \item applying $\isrightincreasing$ to $\op$ yields $\True$; - \item define $\vc$ as the range constraint for the following two expressions: - the binary operation expression for $\op$ $\veoneone$ and $\vetwoone$, and - the binary operation expression for $\op$ $\veonetwo$ and $\vetwotwo$; - \end{itemize} - \item All of the following apply: - \begin{itemize} - \item applying $\isleftincreasing$ to $\op$ yields $\True$; - \item applying $\isrightdecreasing$ to $\op$ yields $\True$; - \item define $\vc$ as the range constraint for the following two expressions: - the binary operation expression for $\op$ $\veoneone$ and $\vetwotwo$, and - the binary operation expression for $\op$ $\veonetwo$ and $\vetwoone$; - \end{itemize} - \item Otherwise, the result is $\Top$. - \end{itemize} - \end{itemize} -\end{itemize} - -\subsection{Formally} -\begin{mathpar} -\inferrule[exact\_exact]{}{ - \constraintbinoppair(\op, \overname{\AbbrevConstraintExact{\veone}}{\vcone}, \overname{\AbbrevConstraintExact{\vetwo}}{\vctwo}) \typearrow - \overname{\AbbrevConstraintExact{\AbbrevEBinop{\op}{\veone}{\vetwo}}}{\vc} -} -\end{mathpar} - -\begin{mathpar} -\inferrule[exact\_range]{ - \vres \eqdef - { - \begin{cases} - % 2 - \AbbrevConstraintRange{\AbbrevEBinop{\op}{\veone}{\vetwoone}}{\AbbrevEBinop{\op}{\veone}{\vetwotwo}} & \textbf{if } - (\isrightincreasing(\op) \typearrow \True) \\ - % 3 - \AbbrevConstraintRange{\AbbrevEBinop{\op}{\veone}{\vetwotwo}}{\AbbrevEBinop{\op}{\veone}{\vetwoone}} & \textbf{if } - (\isrightdecreasing(\op) \typearrow \True) \\ - % - \Top & \textbf{else} - \end{cases} - } -}{ - \constraintbinoppair(\op, \overname{\AbbrevConstraintExact{\veone}}{\vcone}, \overname{\AbbrevConstraintRange{\vetwoone}{\vetwotwo}}{\vctwo}) \typearrow \vres -} -\end{mathpar} - -\begin{mathpar} -\inferrule[range\_exact]{ - \vres \eqdef - { - \begin{cases} - % 4 - \AbbrevConstraintRange{\AbbrevEBinop{\op}{\veoneone}{\vetwo}}{\AbbrevEBinop{\op}{\veonetwo}{\vetwo}} & \textbf{if } - (\isleftincreasing(\op) \typearrow \True)\\ - % - \Top & \textbf{else} - \end{cases} - } -}{ - \constraintbinoppair(\op, \overname{\AbbrevConstraintRange{\veoneone}{\veonetwo}}{\vcone}, \overname{\AbbrevConstraintExact{\vetwo}}{\vctwo}) \typearrow \vres -} -\end{mathpar} - -\begin{mathpar} -\inferrule[range\_range]{ - \vres \eqdef - { - \begin{cases} - % 5 - \AbbrevConstraintRange{\AbbrevEBinop{\op}{\veoneone}{\vetwoone}}{\AbbrevEBinop{\op}{\veonetwo}{\vetwotwo}} & \textbf{if } - \left(\begin{array}{ll} - \isleftincreasing(\op) \typearrow \True\ \land\\ - \isrightincreasing(\op) \typearrow \True\\ - \end{array}\right)\\ - % 6 - \AbbrevConstraintRange{\AbbrevEBinop{\op}{\veoneone}{\vetwotwo}}{\AbbrevEBinop{\op}{\veonetwo}{\vetwoone}} & \textbf{if } - \left(\begin{array}{ll} - \isleftincreasing(\op) \typearrow \True\ \land\\ - \isrightdecreasing(\op) \typearrow \True - \end{array}\right)\\ - % - \Top & \textbf{else} - \end{cases} - } -}{ - \constraintbinoppair(\op, \overname{\AbbrevConstraintRange{\veoneone}{\veonetwo}}{\vcone}, \overname{\AbbrevConstraintRange{\vetwoone}{\vetwotwo}}{\vctwo}) \typearrow \vres -} -\end{mathpar} - -\section{TypingRule.IsRightIncreasing \label{sec:TypingRule.IsRightIncreasing}} -\hypertarget{def-isrightincreasing}{} -The function -\[ -\isrightincreasing(\overname{\binop}{\op}) \aslto \overname{\Bool}{\vb} \cup \{\top\} -\] -tests whether the value of binary operation $\op$ increases along with its right-hand-side operand, -yielding the result in $\vb$. -Otherwise, the result is $\top$, which indicates that the answer is not always $\True$ or $\False$. - -\subsection{Prose} -One of the following applies: -\begin{itemize} - \item All of the following (\textsc{true}): - \begin{itemize} - \item $\op$ is one of $\MUL, \SHL, \SHR, \POW, \PLUS$; - \item define $\vb$ as $\True$. - \end{itemize} - - \item All of the following (\textsc{false}): - \begin{itemize} - \item $\op$ is one of $\DIV, \DIVRM, \MOD, \MINUS$; - \item define $\vb$ as $\False$. - \end{itemize} - - \item All of the following (\textsc{top}): - \begin{itemize} - \item $\op$ is $\RDIV$; - \item define $\vb$ as $\top$. - \end{itemize} -\end{itemize} - -\subsection{Formally} -\begin{mathpar} -\inferrule[true]{ - \op \in \{\MUL, \SHL, \SHR, \POW, \PLUS\} -}{ - \isrightincreasing(\op) \typearrow \overname{\True}{\vb} -} -\and -\inferrule[false]{ - \op \in \{\DIV, \DIVRM, \MOD, \MINUS\} -}{ - \isrightincreasing(\op) \typearrow \overname{\False}{\vb} -} -\and -\inferrule[top]{}{ - \isrightincreasing(\overname{\RDIV}{\op}) \typearrow \top -} -\end{mathpar} - -\section{TypingRule.IsRightDecreasing \label{sec:TypingRule.IsRightDecreasing}} -\hypertarget{def-isrightdecreasing}{} -The function -\[ -\isrightdecreasing(\overname{\binop}{\op}) \aslto \overname{\Bool}{\vb} \cup \{\top\} -\] -tests whether the value of binary operation $\op$ decreases along with its right-hand-side operand, -yielding the result in $\vb$. -Otherwise, the result is $\top$, which indicates that the answer is not always $\True$ or $\False$. - -\subsection{Prose} -One of the following applies: -\begin{itemize} - \item All of the following (\textsc{true}): - \begin{itemize} - \item $\op$ is $\MINUS$; - \item define $\vb$ as $\True$. - \end{itemize} - - \item All of the following (\textsc{false}): - \begin{itemize} - \item $\op$ is one of $\DIV, \DIVRM, \MUL, \SHL, \SHR, \POW, \PLUS, \MOD$; - \item define $\vb$ as $\False$. - \end{itemize} - - \item All of the following (\textsc{top}): - \begin{itemize} - \item $\op$ is one of $\AND ,\BAND ,\BEQ ,\BOR ,\XOR ,\EQOP ,\GT ,\GEQ ,\IMPL ,\LT ,\LEQ ,\NEQ ,\OR, \RDIV$; - \item define $\vb$ as $\top$. - \end{itemize} -\end{itemize} - -\subsection{Formally} -\begin{mathpar} -\inferrule[true]{}{ - \isrightdecreasing(\overname{\MINUS}{\op}) \typearrow \overname{\True}{\vb} -} -\and -\inferrule[false]{ - \op \in \{\DIV, \DIVRM, \MUL, \SHL, \SHR, \POW, \PLUS, \MOD\} -}{ - \isrightdecreasing(\op) \typearrow \overname{\False}{\vb} -} -\and -\inferrule[top]{ - \op \in \{\AND ,\BAND ,\BEQ ,\BOR ,\XOR ,\EQOP ,\GT ,\GEQ ,\IMPL ,\LT ,\LEQ ,\NEQ ,\OR, \RDIV\} -}{ - \isrightdecreasing(\op) \typearrow \top -} -\end{mathpar} - -\section{TypingRule.IsLeftIncreasing \label{sec:TypingRule.IsLeftIncreasing}} -\hypertarget{def-isleftincreasing}{} -The function -\[ -\isleftincreasing(\overname{\binop}{\op}) \aslto \overname{\Bool}{\vb} \cup \{\top\} -\] -tests whether the value of binary operation $\op$ increases along with its left-hand-side operand, -yielding $\True$ or $\top$, which indicates that the answer is not always $\True$ or $\False$. - -\subsection{Prose} -One of the following applies: -\begin{itemize} - \item All of the following (\textsc{true}): - \begin{itemize} - \item $\op$ is one of $\MUL, \DIV, \DIVRM, \MOD, \SHL, \SHR, \POW, \PLUS, \MINUS$; - \item define $\vb$ as $\True$. - \end{itemize} - - \item All of the following (\textsc{top}): - \begin{itemize} - \item $\op$ is one of $\AND ,\BAND ,\BEQ ,\BOR ,\XOR ,\EQOP ,\GT ,\GEQ ,\IMPL ,\LT ,\LEQ ,\NEQ ,\OR, \RDIV$; - \item define $\vb$ as $\top$. - \end{itemize} -\end{itemize} - -\subsection{Formally} -\begin{mathpar} -\inferrule[true]{ - \op \in \{\MUL, \DIV, \DIVRM, \MOD, \SHL, \SHR, \POW, \PLUS, \MINUS\} -}{ - \isleftincreasing(\op) \typearrow \overname{\True}{\vb} -} -\and -\inferrule[top]{ - \op \in \{\AND ,\BAND ,\BEQ ,\BOR ,\XOR ,\EQOP ,\GT ,\GEQ ,\IMPL ,\LT ,\LEQ ,\NEQ ,\OR, \RDIV\} -}{ - \isleftincreasing(\op) \typearrow \top -} -\end{mathpar} - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -\chapter{Symbolic Reduction and Equivalence Testing \label{chap:symbolicequivalencetesting}} -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - -In this chapter, we define two forms of symbolic reasoning --- -\emph{symbolic reduction} and \emph{symbolic equivalence testing}. -Symbolic reduction simplifies expressions into \emph{equivalent} expressions -that are simpler to reason about. -In our context, equivalence means that we can substitute one expression for another without -affecting the semantics of the overall specification. -% -Symbolic equivalence is a \emph{conservative} test. -By conservative, we mean that if a test for equivalence returns $\True$ then the expressions -being compared are indeed equivalent, but if the test returns $\False$ then -there are two possibilities: -\begin{itemize} - \item the expressions are not equivalent; - \item the expressions are equivalent, but the reasoning power of our rules - is not enough to prove it, and so we conservatively answer negatively. -\end{itemize} -In proof-theoretic terms, we can say that our equivalence tests are \emph{sound} but \emph{incomplete}. - -Notice that for a conservative test, it is always correct to return $\False$. - -We first define symbolic expressions and operations over symbolic expressions (\secref{symbolicexpressions}) -and then we define the following rules: -\begin{itemize} - \item TypingRule.Normalize (see \secref{TypingRule.Normalize}) - \item TypingRule.ReduceConstants (see \secref{TypingRule.ReduceConstants}) - \item TypingRule.ReduceConstraint (see \secref{TypingRule.ReduceConstraint}) - \item TypingRule.ReduceConstraints (see \secref{TypingRule.ReduceConstraints}) - \item TypingRule.ToIR (see \secref{TypingRule.ToIR}) - \item TypingRule.ExprEqualNorm (see \secref{TypingRule.ExprEqualNorm}) - \item TypingRule.ExprEqual (see \secref{TypingRule.ExprEqual}) - \item TypingRule.ExprEqualCase (see \secref{TypingRule.ExprEqualCase}) - \item TypingRule.TypeEqual (see \secref{TypingRule.TypeEqual}) - \item TypingRule.BitwidthEqual (see \secref{TypingRule.BitwidthEqual}) - \item TypingRule.BitFieldsEqual (see \secref{TypingRule.BitFieldsEqual}) - \item TypingRule.BitFieldEqual (see \secref{TypingRule.BitFieldEqual}) - \item TypingRule.ConstraintsEqual (see \secref{TypingRule.ConstraintsEqual}) - \item TypingRule.ConstraintEqual (see \secref{TypingRule.ConstraintEqual}) - \item TypingRule.SlicesEqual (see \secref{TypingRule.SlicesEqual}) - \item TypingRule.SliceEqual (see \secref{TypingRule.SliceEqual}) - \item TypingRule.ArrayLengthEqual (see \secref{TypingRule.ArrayLengthEqual}) - \item TypingRule.LiteralEqual (see \secref{TypingRule.LiteralEqual}) -\end{itemize} - -\section{Symbolic Expressions \label{sec:symbolicexpressions}} -Our symbolic reduction and equivalence testing rules use \emph{symbolic expressions}, defined below: -\hypertarget{def-sum}{} -\[ - \begin{array}{rcl} - \polynomial &\triangleq& \unitarymonomial \partialto \Q \setminus \{0\}\\ - \unitarymonomial &\triangleq& \Identifiers \partialto \Npos\\ - \end{array} -\] - -We now explain each component of a symbolic expression and how it can be interpreted as a mathematical formula -via the interpretation function $\alpha$. -We also define operations over symbolic expressions. - -\hypertarget{def-unitarymonomial}{} -\begin{definition}[Unitary Monomial] -A \emph{Unitary Monomial} is a partial function from identifiers to positive integers\footnote{A unitary monomial has a unit factor, -for example $x^3$, whereas a non-unitary monomial has a non-unit factor, for example, $2 x^3$.}. - -A non-empty unitary monomial, $\vm\in\unitarymonomial$ where $\vm \neq \emptyfunc$, can be interpreted as follows: -\[ - \alpha(\vm) \triangleq \prod_{\vx \in \dom(\vm)} \vx^{\vm(\vx)} \enspace. -\] - -An empty unitary monomial is interpreted as the constant $1$: -\[ - \alpha(\emptyfunc) \triangleq 1 \enspace. -\] -\end{definition} -For example, -\[ - \alpha(\ \{\vx\mapsto 3, \vy\mapsto 1, \vz\mapsto2\}\ ) = x^3 \cdot y \cdot z^2 \enspace. -\] - -\hypertarget{def-mulmonomials}{} -The function -\[ - \mulmonomials(\overname{\unitarymonomial}{\vmone} \aslsep \overname{\unitarymonomial}{\vmtwo}) \rightarrow - \overname{\unitarymonomial}{\vm} -\] -multiplies two unitary monomials and returns a unitary monomial -\begin{mathpar} - \inferrule{ - { - \vf \eqdef \lambda \vx\in\identifier.\ - \left\{ - \begin{array}{ll} - \vfone(\vx) & \text{if } \vx \in \dom(\vfone) \setminus \dom(\vftwo)\\ - \vftwo(\vx) & \text{if } \vx \in \dom(\vftwo) \setminus \dom(\vfone)\\ - \vfone(\vx)+\vftwo(\vx) & \text{else } \vx \in \dom(\vfone) \cap \dom(\vftwo)\\ - \end{array} - \right. - } - } - { - \mulmonomials(\overname{\vfone}{\vmone}, \overname{\vftwo}{\vmtwo}) \typearrow \overname{\vf}{\vm} - } -\end{mathpar} -For example, -\[ - \begin{array}{ll} - \mulmonomials( & \{\vx\mapsto 3, \vy\mapsto 1, \vz\mapsto2\}, \{\vx\mapsto 1, \vw\mapsto 2\}\ ) =\\ - & \{\vx\mapsto 4, \vy\mapsto 1, \vz\mapsto2, \vw\mapsto2\} - \end{array} -\] - -\hypertarget{def-polynomial}{} -\begin{definition}[Polynomial] - \emph{Polynomials} are partial functions from monomials to rationals other than zero. - Intuitively, each unitary monomial is mapped to its factor in the polynomial. - A polynomial $\vp$ can be interpreted as follows: - % -\[ - \alpha(\vp) \triangleq \sum_{\vm \in \dom(\vp)} \vp(\vm)\cdot\alpha(\vm) -\] -\end{definition} -For example, -\[ - \left(\left\{ - \begin{array}{lcl} - \{\vx\mapsto 3, \vy\mapsto 1, \vz\mapsto2\} &\mapsto& -1,\\ - \{\vx\mapsto 2, \vy\mapsto 1\} &\mapsto& \frac{3}{4} - \end{array} \right\}\right) = - -1\cdot x^3 \cdot y \cdot z^2 + \frac{3}{4} \cdot \vx^2\cdot \vy \enspace. -\] - -\hypertarget{def-addpolynomials}{} -The function -\[ - \addpolynomials : \polynomial \times \polynomial \rightarrow \polynomial -\] -adds two polynomials: -\begin{mathpar} -\inferrule{ - { - \vf \eqdef \lambda \vm\in\unitarymonomial.\ - \left\{ - \begin{array}{ll} - \vfone(\vm) & \text{if } \vm \in \dom(\vfone) \setminus \dom(\vftwo)\\ - \vftwo(\vm) & \text{if } \vm \in \dom(\vftwo) \setminus \dom(\vfone)\\ - \bot & \text{if } \vm \in \dom(\vfone) \cap \dom(\vftwo) \text{ and } \vfone(\vm)+\vftwo(\vm) = 0\\ - \vfone(\vm)+\vftwo(\vm) & \text{else } \vm \in \dom(\vfone) \cap \dom(\vftwo) \text{ and } \vfone(\vm)+\vftwo(\vm) \neq 0\\ - \end{array} - \right. - } -}{ - \addpolynomials(\overname{\vfone}{\vpone}, \overname{\vftwo}{\vptwo}) \typearrow \overname{\vf}{\vp} -} -\end{mathpar} - -The overloaded function -\[ - \addpolynomials : \polynomial^* \rightarrow \polynomial -\] -adds a list of polynomials: -\begin{mathpar} -\inferrule[empty]{}{ \addpolynomials(\emptylist) \typearrow \emptyfunc } -\and -\inferrule[one]{}{ \addpolynomials([ \vp ]) \typearrow \vp } -\and -\inferrule[two\_or\_more]{ - \addpolynomials(\vp_{2..k}) \typearrow \vpp\\ - \addpolynomials(\vp_1, \vpp) \typearrow \vp -}{ - \addpolynomials(\vp_{1..k}) \typearrow \vp -} -\end{mathpar} - -The function -\[ - \mulpolynomials : \overname{\polynomial}{\vpone} \times \overname{\polynomial}{\vptwo} \rightarrow \overname{\polynomial}{\vp} -\] -multiplies two polynomials. -\begin{mathpar} -\inferrule{ - { - \vps \eqdef \left\{ - \begin{array}{l} - \{\mulmonomials(\vmone, \vmtwo) \mapsto \vfone(\vmone)\times\vftwo(\vmtwo)\} \;|\; \\ - \vmone\in\dom(\vfone)\ \land\ \vmtwo\in\dom(\vgtwo) - \end{array} - \right\} - }\\ - \orderedps \eqdef [i=1..k: \vp_i ] \text{ such that }\{\vp_i \;|\; i=1..k\} = \vps\\ - \addpolynomials(i=1..k: \orderedps) \typearrow \vp\\ -}{ - \mulpolynomials(\overname{\vfone}{\vpone}, \overname{\vftwo}{\vptwo}) \typearrow \vp -} -\end{mathpar} - -\section{TypingRule.Normalize \label{sec:TypingRule.Normalize}} -\hypertarget{def-normalize}{} -The function -\[ -\normalize(\overname{\staticenvs}{\tenv} \aslsep \overname{\expr}{\ve}) \aslto \overname{\expr}{\newe} \cup \overname{\TTypeError}{\TypeErrorConfig} -\] -\hypertarget{def-symbolicallysimplifies}{symbolically simplifies} an expression $\ve$ in the static environment $\tenv$, -yielding an expression $\newe$. -\ProseOtherwiseTypeError - -\subsection{Prose} -One of the following applies: -\begin{itemize} - \item All of the following apply (\textsc{normalizable}) - \begin{itemize} - \item applying $\toir$ to $\ve$ in $\tenv$ to obtain a symbolic expression yields a symbolic expression $\vpone$\ProseOrTypeError; - \item applying $\reduceir$ to $\vpone$ to symbolically simplify $\vpone$ yields $\vptwo$; - \item applying $\polynomialtoexpr$ to $\vptwo$ to transform it into an expression yields $\newe$. - \end{itemize} - - \item All of the following apply (\textsc{not\_normalizable}) - \begin{itemize} - \item applying $\toir$ to $\ve$ in $\tenv$ to obtain a symbolic expression yields $\CannotBeTransformed$, - indicating it cannot be transformed to a corresponding symbolic expression; - \item define $\newe$ as $\ve$. - \end{itemize} -\end{itemize} -\subsection{Formally} -\begin{mathpar} -\inferrule[normalizable]{ - \toir(\tenv, \ve) \typearrow \vpone \OrTypeError\\\\ - \vpone \neq \CannotBeTransformed\\ - \reduceir(\vpone) \typearrow \vptwo\\ - \polynomialtoexpr(\vptwo) \typearrow \newe -}{ - \normalize(\tenv, \ve) \typearrow \newe -} -\and -\inferrule[not\_normalizable]{ - \toir(\tenv, \ve) \typearrow \CannotBeTransformed -}{ - \normalize(\tenv, \ve) \typearrow \overname{\ve}{\newe} -} -\end{mathpar} - -\CodeSubsection{\NormalizeBegin}{\NormalizeEnd}{../StaticModel.ml} - -\section{TypingRule.ReduceConstants \label{sec:TypingRule.ReduceConstants}} -\hypertarget{def-reduceconstants}{} -The function -\[ -\reduceconstants(\overname{\staticenvs}{\tenv} \aslsep \overname{\expr}{\ve}) -\aslto -\overname{\literal}{\vl} \cup \overname{\TTypeError}{\TypeErrorConfig} -\] -\symbolicallysimplifies\ an expression $\ve$ into the literal $\vl$. -\ProseOtherwiseTypeError - -\subsection{Prose} -One of the following applies: -\begin{itemize} - \item All of the following apply (\textsc{eval\_literal}): - \begin{itemize} - \item applying $\staticeval$ to $\ve$ in $\tenv$ yields the literal $\vl$\ProseOrTypeError. - \end{itemize} - - \item All of the following apply (\textsc{eval\_failure}): - \begin{itemize} - \item applying $\staticeval$ to $\ve$ in $\tenv$ yields $\CannotBeTransformed$; - \item the result is a type error indicating that $\ve$ cannot be reduced to a constant in $\tenv$. - \end{itemize} -\end{itemize} - -\CodeSubsection{\ReduceConstantsBegin}{\ReduceConstantsEnd}{../Typing.ml} - -\subsection{Formally} -\begin{mathpar} -\inferrule[eval\_literal]{ - \staticeval(\tenv, \ve) \typearrow \vl \OrTypeError\\\\ - \vl \neq \CannotBeTransformed -}{ - \reduceconstants(\tenv, \ve) \typearrow \vl -} -\and -\inferrule[eval\_failure]{ - \staticeval(\tenv, \ve) \typearrow \CannotBeTransformed -}{ - \reduceconstants(\tenv, \ve) \typearrow \TypeErrorVal{CannotBeReducedToAConstant} -} -\end{mathpar} - -\section{TypingRule.ReduceConstraint \label{sec:TypingRule.ReduceConstraint}} -\hypertarget{def-reduceconstraint}{} -The function -\[ -\reduceconstraint( - \overname{\staticenvs}{\tenv} \aslsep - \overname{\intconstraint}{\vc} -) \aslto -\overname{\intconstraint}{\newc} -\] -\symbolicallysimplifies\ an integer constraint $\vc$, yielding the integer constraint $\newc$ - -\subsection{Prose} -One of the following applies: -\begin{itemize} - \item All of the following apply (\textsc{exact}): - \begin{itemize} - \item $\vc$ is an exact integer constraint for $\ve$, that is, $\ConstraintExact(\ve)$; - \item applying $\normalize$ to $\ve$ in $\tenv$ yields $\vep$; - \item define $\newc$ as the exact integer constraint for $\vep$, that is, $\ConstraintExact(\ve)$. - \end{itemize} - - \item All of the following apply (\textsc{range}): - \begin{itemize} - \item $\vc$ is an range integer constraint for $\veone$ and $\vetwo$, that is, $\ConstraintRange(\veone, \vetwo)$; - \item applying $\normalize$ to $\veone$ in $\tenv$ yields $\veonep$; - \item applying $\normalize$ to $\vetwo$ in $\tenv$ yields $\vetwop$; - \item define $\newc$ as the exact integer constraint for $\vep$, that is, \\ $\ConstraintRange(\veonep, \vetwop)$. - \end{itemize} -\end{itemize} - -\CodeSubsection{\ReduceConstraintBegin}{\ReduceConstraintEnd}{../Typing.ml} - -\subsection{Formally} -\begin{mathpar} -\inferrule[exact]{ - \normalize(\tenv, \ve) \typearrow \vep -}{ - \reduceconstraint(\tenv, \overname{\ConstraintExact(\ve)}{\vc}) \typearrow \overname{\ConstraintExact(\vep)}{\newc} -} -\end{mathpar} - -\begin{mathpar} -\inferrule[range]{ - \normalize(\tenv, \veone) \typearrow \veonep\\ - \normalize(\tenv, \vetwo) \typearrow \vetwop\\ -}{ - \reduceconstraint(\tenv, \overname{\ConstraintRange(\veone, \vetwo)}{\vc}) \typearrow \overname{\ConstraintRange(\veonep, \vetwop)}{\newc} -} -\end{mathpar} - -\section{TypingRule.ReduceConstraints \label{sec:TypingRule.ReduceConstraints}} -\hypertarget{def-reduceconstraints}{} -The function -\[ -\reduceconstraints( - \overname{\staticenvs}{\tenv} \aslsep - \overname{\intconstraints}{\vc} -) \aslto -\overname{\intconstraints}{\newc} -\] -\symbolicallysimplifies\ an integer constraints AST node $\vc$, yielding the integer constraints AST node $\newc$ - -\subsection{Prose} -One of the following applies: -\begin{itemize} - \item All of the following apply (\textsc{unconstrained\_parameterized}): - \begin{itemize} - \item the AST label of $\vc$ is either $\unconstrained$ or $\parameterized$; - \item define $\newc$ as $\vc$. - \end{itemize} - - \item All of the following apply (\textsc{well\_constrained}): - \begin{itemize} - \item $\vc$ is a list of constraints, that is, $\wellconstrained(\cs)$; - \item applying $\reduceconstraint$ to every constraint $\cs[\vi]$ in $\tenv$ for every $\vi$ in $\listrange(\cs)$ - yields $\vc_\vi$; - \item define $\newcs$ as the list containing $\vc_\vi$ for every $\vi$ in $\listrange(\cs)$; - \item $\newc$ is $\wellconstrained(\newcs)$. - \end{itemize} -\end{itemize} - -\CodeSubsection{\ReduceConstraintsBegin}{\ReduceConstraintsEnd}{../Typing.ml} - -\subsection{Formally} -\begin{mathpar} -\inferrule[unconstrained\_parameterized]{ - \astlabel(\vc) \in \{\unconstrained, \parameterized\} -}{ - \reduceconstraints(\tenv, \vc) \typearrow \overname{\vc}{\newc} -} -\end{mathpar} - -\begin{mathpar} -\inferrule[well\_constrained]{ - \vi\in\listrange(\cs): \reduceconstraint(\tenv, \cs[\vi]) \typearrow \vc_\vi\\ - \newcs \eqdef [\vi\in\listrange(\cs): \vc_\vi] -}{ - \reduceconstraints(\tenv, \overname{\wellconstrained(\cs)}{\vc}) \typearrow \overname{\wellconstrained(\newcs)}{\newc} -} -\end{mathpar} - -\section{TypingRule.ToIR \label{sec:TypingRule.ToIR}} -\hypertarget{def-toir}{} -The function -\[ - \toir(\overname{\staticenvs}{\tenv} \aslsep \overname{\expr}{\ve}) \aslto - \overname{\polynomial}{\vp}\ \cup\ \{\CannotBeTransformed\}\ \cup\ \overname{\TTypeError}{\TypeErrorConfig} -\] -transforms a subset of ASL expressions into symbolic expressions. If an ASL expression cannot be represented -by a symbolic expression (because, for example, it contains operations that are not available in symbolic expressions), -the special value $\CannotBeTransformed$ is returned. - -\subsection{Prose} -Intuitively, $\toir$ conducts a case analysis to determine whether the ASL expression corresponds to a polynomial. - -\newcommand\ProseOrTypeErrorOrBot[0]{\ProseTerminateAs{\CannotBeTransformed,\TypeErrorConfig}} - -One of the following applies: -\begin{itemize} - \item All of the following apply (\textsc{literal\_int}): - \begin{itemize} - \item $\ve$ is an integer literal expression for $\vi$, that is, $\ELiteral(\lint(\vi))$; - \item $\vp$ is the symbolic expression for $\vi$. - \end{itemize} - - \item All of the following apply (\textsc{literal\_other}): - \begin{itemize} - \item $\ve$ is a variable expression other than an integer literal; - \item $\vp$ is $\bot$. - \end{itemize} - - \item All of the following apply (\textsc{int\_constant}): - \begin{itemize} - \item $\ve$ is a variable expression with identifier $\vs$, that is, $\EVar(\vs)$; - \item looking up the constant associated with $\vs$ in $\tenv$ yields the literal expression for $\vv$, that is, $\ELiteral(\vv)$; - \item checking whether $\vv$ is an integer literal yields $\True$\ProseOrTypeError; - \item $\vv$ is an integer literal for $\vi$; - \item $\vp$ is the symbolic expression for $\vi$, that is, $\{ \emptyfunc\mapsto \vi \}$. - \end{itemize} - - \item All of the following apply (\textsc{int\_exact\_constant}): - \begin{itemize} - \item $\ve$ is a variable expression with identifier $\vs$, that is, $\EVar(\vs)$; - \item looking up the constant associated with $\vs$ in $\tenv$ yields $\bot$; - \item determining the type of $\vs$ yields $\vt$\ProseOrTypeError; - \item the \underlyingtype\ of $\vt$ is $\ttyone$\ProseOrTypeError; - \item checking whether $\ttyone$ is an integer type yields $\True$\ProseOrTypeError; - \item $\ttyone$ is a well-constrained integer with the exact constraint $\ve$, that is, \\ $\TInt(\wellconstrained([\ConstraintExact(\ve)]))$; - \item converting $\ve$ to a symbolic expression yields $\vp$ (which may possibly be $\bot$). - \end{itemize} - - \item All of the following apply (\textsc{int\_var}): - \begin{itemize} - \item $\ve$ is a variable expression with identifier $\vs$, that is, $\EVar(\vs)$; - \item looking up the constant associated with $\vs$ in $\tenv$ yields $\bot$; - \item determining the type of $\vs$ yields $\vt$\ProseOrTypeError; - \item the \underlyingtype\ of $\vt$ is $\ttyone$\ProseOrTypeError; - \item checking whether $\ttyone$ is an integer type yields $\True$\ProseOrTypeError; - \item $\ttyone$ is not a well-constrained integer with a single exact constraint; - \item $\vp$ is the symbolic expression for the variable $\vs$, that is, $\{ \{\vs\mapsto 1\}\mapsto 1 \}$. - \end{itemize} - - \item All of the following apply (\textsc{ebinop\_plus}): - \begin{itemize} - \item $\ve$ is a binary addition expression with operands $\veone$ and $\vetwo$, that is, \\ $\EBinop(\PLUS, \veone, \vetwo)$; - \item converting $\veone$ to a symbolic expression in $\tenv$ yields $\irone$\ProseOrTypeErrorOrBot; - \item converting $\vetwo$ to a symbolic expression in $\tenv$ yields $\irtwo$\ProseOrTypeErrorOrBot; - \item $\vp$ is the symbolic expression adding up $\irone$ and $\irtwo$. - \end{itemize} - - \item All of the following apply (\textsc{ebinop\_minus}): - \begin{itemize} - \item $\ve$ is a binary subtraction expression with operands $\veone$ and $\vetwo$, that is, \\ $\EBinop(\MINUS, \veone, \vetwo)$; - \item $\vep$ is the addition expression with operands $\veone$ and the negation of $\vetwo$, that is, \\ $\EBinop(\PLUS, \veone, \EUnop(\MINUS, \vetwo))$; - \item converting $\vep$ into a symbolic expression in $\tenv$ yields $\vp$\ProseOrTypeErrorOrBot. - \end{itemize} - - \item All of the following apply (\textsc{ebinop\_mul}): - \begin{itemize} - \item $\ve$ is a binary multiplication expression with operands $\veone$ and $\vetwo$, that is, \\ $\EBinop(\MUL, \veone, \vetwo)$; - \item converting $\veone$ to a symbolic expression in $\tenv$ yields $\irone$\ProseOrTypeErrorOrBot; - \item converting $\vetwo$ to a symbolic expression in $\tenv$ yields $\irtwo$\ProseOrTypeErrorOrBot; - \item $\vp$ is the symbolic expression multiplying $\irone$ and $\irtwo$. - \end{itemize} - - \item All of the following apply (\textsc{ebinop\_div\_non\_int\_denominator}): - \begin{itemize} - \item $\ve$ is a binary division expression with operands $\veone$ and $\vetwo$, that is, \\ $\EBinop(\DIV, \veone, \vetwo)$; - \item $\vetwo$ is not an integer literal expression; - \item $\vp$ is $\bot$. - \end{itemize} - - \item All of the following apply (\textsc{ebinop\_div\_int\_denominator}): - \begin{itemize} - \item $\ve$ is a binary division expression with operands $\veone$ and $\vetwo$, that is, \\ $\EBinop(\DIV, \veone, \vetwo)$; - \item $\vetwo$ is an integer literal expression for $\vitwo$; - \item converting $\veone$ to a symbolic expression in $\tenv$ yields $\irone$\ProseOrTypeErrorOrBot; - \item $\vftwo$ is $\frac{1}{\vitwo}$ (testing against $\vitwo = 0$ is done dynamically); - \item $\vp$ is the polynomial $\irone$ with each monomial multiplied by $\vftwo$. - \end{itemize} - - \item All of the following apply (\textsc{ebinop\_shl\_non\_lint\_exponent}): - \begin{itemize} - \item $\ve$ is a binary shift-left expression with operands $\veone$ and $\vetwo$, that is, \\ $\EBinop(\SHL, \veone, \vetwo)$; - \item $\vetwo$ is not an integer literal expression; - \item $\vp$ is $\bot$. - \end{itemize} - - \item All of the following apply (\textsc{ebinop\_shl\_non\_neg\_shift}): - \begin{itemize} - \item $\ve$ is a binary shift-left expression with operands $\veone$ and $\vetwo$, that is, \\ $\EBinop(\SHL, \veone, \vetwo)$; - \item $\vetwo$ is an integer literal expression for $\vitwo$; - \item $\vitwo$ is negative; - \item $\vp$ is $\bot$. - \end{itemize} - - \item All of the following apply (\textsc{ebinop\_shl\_okay}): - \begin{itemize} - \item $\ve$ is a binary shift-left expression with operands $\veone$ and $\vetwo$, that is, \\ $\EBinop(\SHL, \veone, \vetwo)$; - \item $\vetwo$ is an integer literal expression for $\vitwo$; - \item converting $\veone$ to a symbolic expression in $\tenv$ yields $\irone$\ProseOrTypeErrorOrBot; - \item $\vitwo$ is non-negative; - \item $\vftwo$ is $2^{\vitwo}$; - \item $\vp$ is the polynomial $\irone$ with each monomial multiplied by $\vftwo$. - \end{itemize} - - \item All of the following apply (\textsc{ebinop\_other\_non\_literals}): - \begin{itemize} - \item $\ve$ is a binary expression with an operator $\op$ that is other than $\PLUS$, $\MINUS$, $\MUL$, or $\SHL$, - applied to the operand expressions $\veone$ and $\vetwo$; - \item at least one of $\veone$ and $\vetwo$ is not a literal expression; - \item $\vp$ is $\bot$. - \end{itemize} - - \item All of the following apply (\textsc{ebinop\_other\_literals\_non\_int\_result}): - \begin{itemize} - \item $\ve$ is a binary expression with an operator $\op$ that is other than $\PLUS$, $\MINUS$, $\MUL$, $\DIV$, or $\SHL$, - applied to the operand expressions $\veone$ and $\vetwo$; - \item $\veone$ is the literal expression for literal $\vlone$; - \item $\vetwo$ is the literal expression for literal $\vltwo$; - \item statically applying $\op$ to $\vlone$ and $\vltwo$ yields the literal $\vl$, which is not an integer literal; - \item $\vp$ is $\bot$. - \end{itemize} - - \item All of the following apply (\textsc{ebinop\_other\_literals\_int\_result}): - \begin{itemize} - \item $\ve$ is a binary expression with an operator $\op$ that is other than $\PLUS$, $\MINUS$, $\MUL$, or $\SHL$, - applied to the operand expressions $\veone$ and $\vetwo$; - \item $\veone$ is the literal expression for literal $\vlone$; - \item $\vetwo$ is the literal expression for literal $\vltwo$; - \item statically applying $\op$ to $\vlone$ and $\vltwo$ yields the integer literal for $k$; - \item $\vp$ is the symbolic expression for the integer $k$, that is, $\{ \emptyfunc\mapsto k \}$. - \end{itemize} - - \item All of the following apply (\textsc{eunop\_neg}): - \begin{itemize} - \item $\ve$ is a unary expression with the negation operator $\NEG$ and operand $\veone$; - \item converting the binary expression with operator $\MUL$ and left-hand-side operand for the integer literal $-1$ and - right-hand-side operand $\veone$ in $\tenv$ yields $\vp$\ProseOrTypeErrorOrBot. - \end{itemize} - - \item All of the following apply (\textsc{eunop\_other}): - \begin{itemize} - \item $\ve$ is a unary expression with an operator other than $\NEG$; - \item $\vp$ is $\CannotBeTransformed$. - \end{itemize} - - \item All of the following apply (\textsc{other}): - \begin{itemize} - \item $\ve$ is an expression with a label other than $\ELiteral$, $\EVar$, $\EBinop$, and $\EUnop$; - \item $\vp$ is $\CannotBeTransformed$. - \end{itemize} -\end{itemize} - -\subsection{Formally} -\begin{mathpar} -\inferrule[literal\_int]{} -{ - \toir(\tenv, \overname{\ELiteral(\lint(\vi))}{\ve}) \typearrow \overname{\{ \emptyfunc\mapsto \vi \}}{\vp} -} -\and -\inferrule[literal\_other]{ - \astlabel(\vv) \neq \lint -}{ - \toir(\tenv, \overname{\ELiteral(\vv)}{\ve}) \typearrow \CannotBeTransformed -} -\and -\inferrule[int\_constant]{ - \lookupconstant(\tenv, \vs) \typearrow \ELiteral(\vv)\\ - \checktrans{\astlabel(\vv) = \lint}{ExpectedIntegerLiteral} \typearrow \True \OrTypeError\\\\ - \vv \eqname \lint(\vi) -}{ - \toir(\tenv, \overname{\EVar(\vs)}{\ve}) \typearrow \overname{\{ \emptyfunc\mapsto \vi \}}{\vp} -} -\and -\inferrule[int\_exact\_constraint]{ - \lookupconstant(\tenv, \vs) \typearrow \CannotBeTransformed\\ - \typeof(\vs) \typearrow \vt \OrTypeError\\\\ - \makeanonymous(\vt) \typearrow \ttyone \OrTypeError\\\\ - \checktrans{\astlabel(\ttyone) = \TInt}{ExpectedIntegerType} \typearrow \True \OrTypeError\\\\ - \ttyone = \TInt(\wellconstrained([\ConstraintExact(\ve)]))\\ - \toir(\ve) \typearrow \vp -}{ - \toir(\tenv, \overname{\EVar(\vs)}{\ve}) \typearrow \vp -} -\and -\inferrule[int\_var]{ - \lookupconstant(\tenv, \vs) \typearrow \CannotBeTransformed\\ - \typeof(\vs) \typearrow \vt\\ - \makeanonymous(\vt) \typearrow \ttyone\\ - \checktrans{\astlabel(\ttyone) = \TInt}{ExpectedIntegerType} \typearrow \True\\ - \ttyone \neq \TInt(\wellconstrained([\ConstraintExact(\Ignore)])) -}{ - \toir(\tenv, \overname{\EVar(\vs)}{\ve}) \typearrow \overname{\{ \{\vs\mapsto 1\}\mapsto 1 \}}{\vp} -} -\end{mathpar} - -\begin{mathpar} -\inferrule[ebinop\_plus]{ - \toir(\tenv, \veone) \typearrow \irone \OrTypeError, \CannotBeTransformed\\\\ - \toir(\tenv, \vetwo) \typearrow \irtwo \OrTypeError, \CannotBeTransformed\\\\ - \vp \eqdef \addpolynomials(\irone, \irtwo) -}{ - \toir(\tenv, \overname{\EBinop(\PLUS, \veone, \vetwo)}{\ve}) \typearrow \vp -} -\end{mathpar} - -\begin{mathpar} -\inferrule[ebinop\_minus]{ - \vep \eqdef \EBinop(\PLUS, \veone, \EUnop(\MINUS, \vetwo))\\ - \toir(\tenv, \vep) \typearrow \vp \OrTypeError, \CannotBeTransformed\\\\ -}{ - \toir(\tenv, \overname{\EBinop(\MINUS, \veone, \vetwo)}{\ve}) \typearrow \vp -} -\end{mathpar} - -\begin{mathpar} -\inferrule[ebinop\_mul]{ - \toir(\tenv, \veone) \typearrow \irone \OrTypeError, \CannotBeTransformed\\\\ - \toir(\tenv, \vetwo) \typearrow \irtwo \OrTypeError, \CannotBeTransformed\\\\ - \vp \eqdef \mulpolynomials(\irone, \irtwo) -}{ - \toir(\tenv, \overname{\EBinop(\MUL, \veone, \vetwo)}{\ve}) \typearrow \vp -} -\end{mathpar} - -\begin{mathpar} -\inferrule[ebinop\_div\_non\_int\_denominator]{ - \vetwo \neq \ELiteral(\lint(\Ignore)) -}{ - \toir(\tenv, \overname{\EBinop(\DIV, \veone, \vetwo)}{\ve}) \typearrow \CannotBeTransformed -} -\and -\inferrule[ebinop\_div\_int\_denominator]{ - \toir(\tenv, \veone) \typearrow \irone \OrTypeError, \CannotBeTransformed\\\\ - \vftwo \eqdef \frac{1}{\vitwo}\\ - \irone \eqname [i=1..k: \vm_\vi \mapsto \vc_\vi]\\ - \vp \eqdef [i=1..k: \vm_\vi \mapsto \vc_\vi \times \vftwo]\\ -}{ - \toir(\tenv, \overname{\EBinop(\DIV, \veone, \overname{\ELiteral(\lint(\vitwo))}{\vetwo})}{\ve}) \typearrow \vp -} -\end{mathpar} - -\begin{mathpar} -\inferrule[ebinop\_shl\_non\_lint\_exponent]{ - \vetwo \neq \ELiteral(\lint(\Ignore)) -}{ - \toir(\tenv, \overname{\EBinop(\SHL, \Ignore, \vetwo)}{\ve}) \typearrow \CannotBeTransformed -} -\end{mathpar} - -\begin{mathpar} -\inferrule[ebinop\_shl\_neg\_shift]{ - \vitwo < 0 -}{ - \toir(\tenv, \overname{\EBinop(\SHL, \veone, \ELiteral(\lint(\vitwo)))}{\ve}) \typearrow \CannotBeTransformed -} -\and - \inferrule[ebinop\_shl\_okay]{ - \toir(\tenv, \veone) \typearrow \irone \OrTypeError, \CannotBeTransformed\\\\ - \vitwo \geq 0\\ - \vftwo \eqdef 2^{\vitwo}\\ - \irone \eqname [i=1..k: \vm_\vi \mapsto \vc_\vi]\\ - \vp \eqdef [i=1..k: \vm_\vi \mapsto \vc_\vi \times \vftwo]\\ -}{ - \toir(\tenv, \overname{\EBinop(\SHL, \veone, \ELiteral(\lint(\vitwo)))}{\ve}) \typearrow \vp -} -\end{mathpar} - -\begin{mathpar} -\inferrule[ebinop\_other\_non\_literals]{ - \op \not\in \{\PLUS, \MINUS, \MUL, \DIV, \SHL\}\\ - (\veone \neq \ELiteral(\Ignore) \lor \vetwo \neq \ELiteral(\Ignore)) -}{ - \toir(\tenv, \overname{\EBinop(\op, \veone, \vetwo)}{\ve}) \typearrow \CannotBeTransformed -} -\and -\inferrule[ebinop\_other\_literals\_non\_int\_result]{ - \op \not\in \{\PLUS, \MINUS, \MUL, \SHL\}\\ - \binopliterals(\op, \vlone, \vltwo) \typearrow \vl\\ - \vl \neq \lint(\Ignore) -}{ - \toir(\tenv, \overname{\EBinop(\op, \ELiteral(\vlone), \ELiteral(\vltwo))}{\ve}) \typearrow \CannotBeTransformed -} -\and -\inferrule[ebinop\_other\_literals\_int\_result]{ - \op \not\in \{\PLUS, \MINUS, \MUL, \SHL\}\\ - \binopliterals(\op, \vlone, \vltwo) \typearrow \lint(k)\\ - \vp \eqdef \{ \emptyfunc\mapsto k \} -}{ - \toir(\tenv, \overname{\EBinop(\op, \ELiteral(\vlone), \ELiteral(\vltwo))}{\ve}) \typearrow \vp -} -\end{mathpar} - -\begin{mathpar} -\inferrule[eunop\_neg]{ - \toir(\tenv, \EBinop(\MUL, \ELiteral(\lint(-1)),\veone )) \typearrow \vp \OrTypeError, \CannotBeTransformed\\\\ -}{ - \toir(\tenv, \overname{\EUnop(\NEG, \veone)}{\ve}) \typearrow \vp -} -\and -\inferrule[eunop\_other]{ - \op \neq \NEG -}{ - \toir(\tenv, \overname{\EUnop(\op, \Ignore)}{\ve}) \typearrow \CannotBeTransformed -} -\end{mathpar} - -\begin{mathpar} -\inferrule[other]{ - \astlabel(\ve) \not\in \{\ELiteral, \EVar, \EBinop, \EUnop\} -}{ - \toir(\tenv, \ve) \typearrow \CannotBeTransformed -} -\end{mathpar} - -\section{TypingRule.ExprEqualNorm \label{sec:TypingRule.ExprEqualNorm}} -\hypertarget{def-exprequalnorm}{} -The function -\[ - \exprequalnorm(\overname{\staticenvs}{\tenv} \aslsep \overname{\expr}{\veone} \aslsep \overname{\expr}{\vetwo}) - \aslto \overname{\{\True, \False\}}{\vb} \cup \overname{\TTypeError}{\TypeErrorConfig} -\] -conservatively tests whether the expression $\veone$ is equivalent to the expression $\vetwo$ in environment $\tenv$ -by attempting to transform both expressions to their symbolic expression form -and, if successful, comparing the resulting normal forms for equality. -The result is given in $\vb$ or a type error, if one is detected. - -\subsection{Prose} -One of the following applies: -\begin{itemize} - \item All of the following apply (\textsc{all\_supported}): - \begin{itemize} - \item transforming $\veone$ into a symbolic expression in $\tenv$ yields $\irone$\ProseOrTypeError; - \item transforming $\vetwo$ into a symbolic expression in $\tenv$ yields $\irtwo$\ProseOrTypeError; - \item $\vb$ is the result of equating $\irone$ and $\irtwo$. - \end{itemize} - - \item All of the following apply (\textsc{unsupported1}): - \begin{itemize} - \item transforming $\veone$ into a symbolic expression in $\tenv$ yields $\CannotBeTransformed$; - \item $\vb$ is $\False$; - \end{itemize} - - \item All of the following apply (\textsc{unsupported2}): - \begin{itemize} - \item transforming $\veone$ into a symbolic expression in $\tenv$ yields $\irone$; - \item transforming $\vetwo$ into a symbolic expression in $\tenv$ yields $\CannotBeTransformed$; - \item $\vb$ is $\False$; - \end{itemize} -\end{itemize} - -\subsection{Formally} -\begin{mathpar} -\inferrule[all\_supported]{ - \toir(\veone) \typearrow \irone \OrTypeError\\\\ - \toir(\vetwo) \typearrow \irtwo \OrTypeError -}{ - \exprequalnorm(\tenv, \veone, \vetwo) \typearrow \overname{\irone = \irtwo}{\vb} -} -\and -\inferrule[unsupported1]{ - \toir(\veone) \typearrow \CannotBeTransformed -}{ - \exprequalnorm(\tenv, \veone, \vetwo) \typearrow \overname{\False}{\vb} -} -\and -\inferrule[unsupported2]{ - \toir(\veone) \typearrow \irone\\ - \toir(\vetwo) \typearrow \CannotBeTransformed -}{ - \exprequalnorm(\tenv, \veone, \vetwo) \typearrow \overname{\False}{\vb} -} -\end{mathpar} - -\section{TypingRule.ExprEqual \label{sec:TypingRule.ExprEqual}} -\hypertarget{def-exprequal}{} -The function -\[ - \exprequal(\overname{\staticenvs}{\tenv} \aslsep \overname{\expr}{\veone} \aslsep \overname{\expr}{\vetwo}) \aslto - \overname{\{\True, \False\}}{\vb} \cup \overname{\TTypeError}{\TypeErrorConfig} -\] -conservatively checks whether the expression $\veone$ is equivalent to the expression $\vetwo$ in environment $\tenv$. -The result is given in $\vb$ or a type error, if one is detected. - -\subsection{Prose} -One of the following applies: -\begin{itemize} - \item All of the following apply (\textsc{norm\_true}): - \begin{itemize} - \item comparing $\veone$ to $\vetwo$ in $\tenv$ via $\exprequalnorm$ yields $\True$\ProseOrTypeError; - \item $\vb$ is $\True$. - \end{itemize} - - \item All of the following apply (\textsc{norm\_false}): - \begin{itemize} - \item comparing $\veone$ to $\vetwo$ in $\tenv$ via $\exprequalnorm$ yields $\False$; - \item comparing $\veone$ to $\vetwo$ by case analysis via $\exprequalcase$ yields $\vb$\ProseOrTypeError. - \end{itemize} -\end{itemize} - -\subsection{Formally} -\begin{mathpar} -\inferrule[norm\_true]{ - \exprequalnorm(\tenv, \veone, \vetwo) \typearrow \True \OrTypeError -}{ - \exprequal(\tenv, \veone, \vetwo) \typearrow \True -} -\and -\inferrule[norm\_false]{ - \exprequalnorm(\tenv, \veone, \vetwo) \typearrow \False\\ - \exprequalcase(\tenv, \veone, \vetwo) \typearrow \vb \OrTypeError -}{ - \exprequal(\tenv, \veone, \vetwo) \typearrow \vb -} -\end{mathpar} - -\section{TypingRule.ExprEqualCase \label{sec:TypingRule.ExprEqualCase}} -\hypertarget{def-exprequalcase}{} -The function -\[ - \exprequalcase(\overname{\staticenvs}{\tenv} \aslsep \overname{\expr}{\veone} \aslsep \overname{\expr}{\vetwo}) - \aslto \overname{\{\True, \False\}}{\vb} \cup \overname{\TTypeError}{\TypeErrorConfig} -\] -specializes the equivalence test for expressions $\veone$ and $\vetwo$ in $\tenv$ -for the different types of expressions. -The result is given in $\vb$ or a type error, if one is detected. - -\subsection{Prose} -One of the following applies: -\begin{itemize} - \item All of the following apply (\textsc{different\_labels}): - \begin{itemize} - \item the AST labels of $\veone$ and $\vetwo$ are different; - \item $\vb$ is $\False$. - \end{itemize} - - \item All of the following apply (\textsc{e\_binop}): - \begin{itemize} - \item $\veone$ is a binary expression with operator $\opone$ and operands $\veoneone$ and $\veonetwo$, - that is, $\EBinop(\opone, \veoneone, \veonetwo)$; - \item $\vetwo$ is a binary expression with operator $\optwo$ and operands $\vetwoone$ and $\vetwotwo$, - that is, $\EBinop(\optwo, \vetwoone, \vetwotwo)$; - \item testing the equivalence of $\veoneone$ and $\vetwoone$ in $\tenv$ yields $\vbone$\ProseOrTypeError; - \item testing the equivalence of $\veonetwo$ and $\vetwotwo$ in $\tenv$ yields $\vbtwo$\ProseOrTypeError; - \item $\vb$ is $\True$ if and only if $\opone$ is equal to $\optwo$ and both $\vbone$ and $\vbtwo$ are $\True$. - \end{itemize} - - \item All of the following apply (\textsc{e\_call}): - \begin{itemize} - \item $\veone$ is a call expression with subprogram name $\nameone$ and list of arguments $\vargsone$, - that is, $\ECall(\nameone, \vargsone, \Ignore)$; - \item $\vetwo$ is a call expression with subprogram name $\nametwo$ and list of arguments $\vargstwo$, - that is, $\ECall(\nametwo, \vargstwo, \Ignore)$; - \item checking whether $\nameone$ is equal to $\nametwo$ either yields $\True$ or $\False$, which short-circuits the entire rule; - \item checking whether the lists of arguments $\vargsone$ and $\vargstwo$ have the same length yields - $\True$ or $\False$, which short-circuits the entire rule; - \item for each index $i$ in the list of indices for $\vargsone$, testing whether $\vargsone[i]$ is equivalent to $\vargstwo[i]$ - in $\tenv$ yields $\vb_i$\ProseOrTypeError; - \item $\vb$ is $\True$ if and only if $\vb_i$ is $\True$ for each index $i$ in the list of indices for $\vargsone$. - \end{itemize} - - \item All of the following apply (\textsc{e\_concat}): - \begin{itemize} - \item $\veone$ is a concatenation expression with $\vlone$, that is, $\EConcat(\vlone)$; - \item $\vetwo$ is a concatenation expression with $\vltwo$, that is, $\EConcat(\vltwo)$; - \item checking whether the lists of expressions $\vlone$ and $\vltwo$ have the same length yields - $\True$ or $\False$, which short-circuits the entire rule; - \item for each index $i$ in the list of indices for $\vlone$, testing whether $\vlone[i]$ is equivalent to $\vltwo[i]$ - in $\tenv$ yields $\vb_i$\ProseOrTypeError; - \item $\vb$ is $\True$ if and only if $\vb_i$ is $\True$ for each index $i$ in the list of indices for $\vlone$. - \end{itemize} - - \item All of the following apply (\textsc{e\_cond}): - \begin{itemize} - \item $\veone$ is a conditional expression with expressions $\veoneone$, $\veonetwo$, and $\veonethree$, - that is, $\ECond(\veoneone, \veonetwo, \veonethree)$; - \item $\vetwo$ is a conditional expression with expressions $\vetwoone$, $\vetwotwo$, and $\vetwothree$, - that is, $\ECond(\vetwoone, \vetwotwo, \vetwothree)$; - \item testing whether $\veoneone$ is equivalent to $\vetwoone$ yields $\vbone$\ProseOrTypeError; - \item testing whether $\veonetwo$ is equivalent to $\vetwotwo$ yields $\vbtwo$\ProseOrTypeError; - \item testing whether $\veonethree$ is equivalent to $\vetwothree$ yields $\vbthree$\ProseOrTypeError; - \item $\vb$ is $\True$ if and only if all of $\vbone$, $\vbtwo$, and $\vbthree$ are $\True$. - \end{itemize} - - \item All of the following apply (\textsc{e\_slice}): - \begin{itemize} - \item $\veone$ is a slicing expression with expression $\veoneone$ and list of slices $\slicesone$, - that is, $\ESlice(\veoneone, \slicesone)$; - \item $\veone$ is a slicing expression with expression $\vetwoone$ and list of slices $\slicestwo$, - that is, $\ESlice(\vetwoone, \slicestwo)$; - \item testing whether $\veoneone$ is equivalent to $\vetwoone$ yields $\vbone$\ProseOrTypeError; - \item testing whether the lists of slices $\slicesone$ and $\slicestwo$ are equivalent in $\tenv$ yields $\vbtwo$\ProseOrTypeError; - \item $\vb$ is $\True$ if and only both $\vbone$ and $\vbtwo$ are $\True$. - \end{itemize} - - \item All of the following apply (\textsc{e\_getarray}): - \begin{itemize} - \item $\veone$ is an \arrayaccess\ expression with array expression $\veoneone$ and position expression $\veonetwo$, - that is, $\EGetArray(\veoneone, \veonetwo)$; - \item $\vetwo$ is an \arrayaccess\ expression with array expression $\vetwoone$ and position expression $\vetwotwo$, - that is, $\EGetArray(\vetwoone, \vetwotwo)$; - \item testing whether $\veoneone$ is equivalent to $\vetwoone$ yields $\vbone$\ProseOrTypeError; - \item testing whether $\veonetwo$ is equivalent to $\vetwotwo$ yields $\vbtwo$\ProseOrTypeError; - \item $\vb$ is $\True$ if and only both $\vbone$ and $\vbtwo$ are $\True$. - \end{itemize} - - \item All of the following apply (\textsc{e\_getfield}): - \begin{itemize} - \item $\veone$ is a field access expression with subexpression $\veoneone$ and field name $\vfieldone$, - that is, $\EGetField(\veoneone, \vfieldone)$; - \item $\vetwo$ is a field access expression with subexpression $\vetwoone$ and field name $\vfieldtwo$, - that is, $\EGetField(\vetwoone, \vfieldtwo)$; - \item $\vbone$ is $\True$ if and only if $\vfieldone$ is equal to $\vfieldtwo$; - \item testing whether $\veoneone$ is equivalent to $\vetwoone$ yields $\vbtwo$\ProseOrTypeError; - \item $\vb$ is $\True$ if and only both $\vbone$ and $\vbtwo$ are $\True$. - \end{itemize} - - \item All of the following apply (\textsc{e\_getfields}): - \begin{itemize} - \item $\veone$ is a fields access expression with subexpression $\veoneone$ and list of field names $\vfieldsone$, - that is, $\EGetFields(\veoneone, \vfieldsone)$; - \item $\vetwo$ is a fields access expression with subexpression $\vetwoone$ and list of field names $\vfieldstwo$, - that is, $\EGetFields(\vetwoone, \vfieldstwo)$; - \item $\vbone$ is $\True$ if and only if $\vfieldsone$ is equal to $\vfieldstwo$; - \item testing whether $\veoneone$ is equivalent to $\vetwoone$ yields $\vbtwo$\ProseOrTypeError; - \item $\vb$ is $\True$ if and only both $\vbone$ and $\vbtwo$ are $\True$. - \end{itemize} - - \item All of the following apply (\textsc{e\_getitem}): - \begin{itemize} - \item $\veone$ is a tuple access expression with subexpression $\veoneone$ and position $\vione$, - that is, $\EGetItem(\veoneone, \vione)$; - \item $\vetwo$ is a tuple access expression with subexpression $\vetwoone$ and position $\vitwo$, - that is, $\EGetItem(\vetwoone, \vitwo)$; - \item $\vbone$ is $\True$ if and only if $\vione$ is equal to $\vitwo$; - \item testing whether $\veoneone$ is equivalent to $\vetwoone$ yields $\vbtwo$\ProseOrTypeError; - \item $\vb$ is $\True$ if and only both $\vbone$ and $\vbtwo$ are $\True$. - \end{itemize} - - \item All of the following apply (\textsc{e\_literal}): - \begin{itemize} - \item $\veone$ is the literal expression with literal $\vvone$; - \item $\vetwo$ is the literal expression with literal $\vvtwo$; - \item $\vb$ is $\True$ if and only if $\vvone$ is equivalent to $\vvtwo$ in $\tenv$. - \end{itemize} - - \item All of the following apply (\textsc{e\_pattern}): - \begin{itemize} - \item both $\veone$ and $\vetwo$ are pattern expressions; - \item $\vb$ is $\False$. - \end{itemize} - - \item All of the following apply (\textsc{e\_record}): - \begin{itemize} - \item both $\veone$ and $\vetwo$ are record expressions; - \item $\vb$ is $\False$. - \end{itemize} - - \item All of the following apply (\textsc{e\_tuple}): - \begin{itemize} - \item $\veone$ is a tuple expression with subexpression list $\vlone$, - that is, $\ETuple(\vlone)$; - \item $\vetwo$ is a tuple expression with subexpression list $\vltwo$, - that is, $\ETuple(\vltwo)$; - \item checking whether the lengths of $\vlone$ and $\vltwo$ are equal yields either $\True$ or $\False$, which short-circuits - the entire rule; - \item for each index $i$ in the list of indices for $\vlone$, testing whether $\vlone[i]$ is equivalent to $\vltwo[i]$ - in $\tenv$ yields $\vb_i$\ProseOrTypeError; - \item $\vb$ is $\True$ if and only if $\vb_i$ is $\True$ for each index $i$ in the list of indices for $\vlone$. - \end{itemize} - - \item All of the following apply (\textsc{e\_unop}): - \begin{itemize} - \item $\veone$ is a unary operator expression with operator $\opone$ and operand expressions $\veoneone$, - that is, $\EUnop(\opone, \veoneone)$; - \item $\vetwo$ is a unary operator expression with operator $\optwo$ and operand expressions $\vetwoone$, - that is, $\EUnop(\optwo, \vetwoone)$; - \item testing whether $\veoneone$ is equivalent to $\vetwoone$ in $\tenv$ yields $\vbone$; - \item $\vb$ is $\True$ if and only if $\opone$ is equal to $\optwo$ and $\vbone$ is $\True$. - \end{itemize} - - \item All of the following apply (\textsc{e\_unknown}): - \begin{itemize} - \item both $\veone$ and $\vetwo$ are $\UNKNOWN$ expressions; - \item $\vb$ is $\False$. - \end{itemize} - - \item All of the following apply (\textsc{e\_atc}): - \begin{itemize} - \item $\veone$ is a type assertion with subexpression with operator $\veoneone$ and type $\vtone$, - that is, $\EATC(\veoneone, \vtone)$; - \item $\vetwo$ is a type assertion with subexpression with operator $\vetwoone$ and type $\vttwo$, - that is, $\EATC(\vetwoone, \vttwo)$; - \item testing whether $\veoneone$ is equivalent to $\vetwoone$ in $\tenv$ yields $\vbone$; - \item testing whether $\vtone$ is equivalent to $\vttwo$ in $\tenv$ yields $\vbtwo$; - \item $\vb$ is $\True$ if and only if both $\vbone$ and $\vbtwo$ are $\True$. - \end{itemize} - - \item All of the following apply (\textsc{e\_var}): - \begin{itemize} - \item $\veone$ is a variable expression with identifier $\nameone$, that is, $\EVar(\nameone)$; - \item $\vetwo$ is a variable expression with identifier $\nametwo$, that is, $\EVar(\nametwo)$; - \item $\vb$ is $\True$ if and only if both $\nameone$ is equal to $\nametwo$. - \end{itemize} -\end{itemize} - -\subsection{Formally} -\begin{mathpar} -\inferrule[different\_labels]{ - \astlabel(\veone) \neq \astlabel(\vetwo) -}{ - \exprequalcase(\tenv, \veone, \vetwo) \typearrow \False -} -\end{mathpar} - -\begin{mathpar} -\inferrule[e\_binop]{ - \veone \eqname \EBinop(\opone, \veoneone, \veonetwo)\\ - \vetwo \eqname \EBinop(\optwo, \vetwoone, \vetwotwo)\\ - \exprequal(\veoneone, \vetwoone) \typearrow \vbone \OrTypeError\\\\ - \exprequal(\veonetwo, \vetwotwo) \typearrow \vbtwo \OrTypeError\\\\ - \vb \eqdef (\opone = \optwo) \land \vbone \land \vbtwo -}{ - \exprequalcase(\tenv, \veone, \vetwo) \typearrow \vb -} -\end{mathpar} - -(Recall that a conjunction over an empty set equals $\True$.) -\begin{mathpar} -\inferrule[e\_call]{ - \veone \eqname \ECall(\nameone, \vargsone, \Ignore)\\ - \vetwo \eqname \ECall(\nametwo, \vargstwo, \Ignore)\\\\ - \booltrans{\nameone = \nametwo} \booltransarrow \True \terminateas \False\\\\ - \equallength(\vargsone, \vargstwo) \typearrow \True \terminateas \False\\\\ - i \in \listrange(\vargsone): \exprequal(\tenv, \vargsone[i], \vargstwo[i]) \typearrow \vb_i \OrTypeError\\\\ - \vb \eqdef \bigwedge_{i \in \listrange(\vargsone)} \vb_i -}{ - \exprequalcase(\tenv, \veone, \vetwo) \typearrow \vb -} -\end{mathpar} - -\begin{mathpar} - \inferrule[e\_concat]{ - \veone \eqname \EConcat(\vlone)\\ - \vetwo \eqname \EConcat(\vltwo)\\\\ - \equallength(\vlone, \vltwo) \typearrow \True \terminateas \False\\\\ - i \in \listrange(\vlone): \exprequal(\tenv, \vlone[i], \vltwo[i]) \typearrow \vb_i \OrTypeError\\\\ - \vb \eqdef \bigwedge_{i \in \listrange(\vlone)} \vb_i -}{ - \exprequalcase(\tenv, \veone, \vetwo) \typearrow \vb -} -\end{mathpar} - -\begin{mathpar} -\inferrule[e\_cond]{ - \veone \eqname \ECond(\veoneone, \veonetwo, \veonethree)\\ - \vetwo \eqname \ECond(\vetwoone, \vetwotwo, \vetwothree)\\\\ - \exprequal(\tenv, \veoneone, \vetwoone) \typearrow \vbone \OrTypeError\\\\ - \exprequal(\tenv, \veonetwo, \vetwotwo) \typearrow \vbtwo \OrTypeError\\\\ - \exprequal(\tenv, \veonethree, \vetwothree) \typearrow \vbthree \OrTypeError\\\\ - \vb \eqdef \vbone \land \vbtwo \land \vbthree -}{ - \exprequalcase(\tenv, \veone, \vetwo) \typearrow \True -} -\end{mathpar} - -\begin{mathpar} - \inferrule[e\_slice]{ - \veone \eqname \ESlice(\veoneone, \slicesone)\\ - \vetwo \eqname \ESlice(\vetwoone, \slicestwo)\\\\ - \exprequal(\tenv, \veoneone, \vetwoone) \typearrow \vbone \OrTypeError\\\\ - \slicesequal(\tenv, \slicesone, \slicestwo) \typearrow \vbtwo \OrTypeError\\\\ - \vb \eqdef \vbone \land \vbtwo -}{ - \exprequalcase(\tenv, \veone, \vetwo) \typearrow \vb -} -\end{mathpar} - -\begin{mathpar} - \inferrule[e\_getarray]{ - \veone \eqname \EGetArray(\veoneone, \veonetwo)\\ - \vetwo \eqname \EGetArray(\vetwoone, \vetwotwo)\\\\ - \exprequal(\tenv, \veoneone, \vetwoone) \typearrow \vbone \OrTypeError\\\\ - \exprequal(\tenv, \veonetwo, \vetwotwo) \typearrow \vbtwo \OrTypeError\\\\ - \vb \eqdef \vbone \land \vbtwo -}{ - \exprequalcase(\tenv, \veone, \vetwo) \typearrow \vb -} -\end{mathpar} - -\begin{mathpar} - \inferrule[e\_getfield]{ - \veone \eqname \EGetField(\veoneone, \vfieldone)\\ - \vetwo \eqname \EGetField(\vetwoone, \vfieldtwo)\\\\ - \vbone \eqdef \vfieldone = \vfieldtwo\\ - \exprequal(\tenv, \veoneone, \vetwoone) \typearrow \vbtwo \OrTypeError\\\\ - \vb \eqdef \vbone \land \vbtwo -}{ - \exprequalcase(\tenv, \veone, \vetwo) \typearrow \vb -} -\end{mathpar} - -\begin{mathpar} - \inferrule[e\_getfields]{ - \veone \eqname \EGetFields(\veoneone, \vfieldsone)\\ - \vetwo \eqname \EGetFields(\vetwoone, \vfieldstwo)\\\\ - \vbone \eqdef \vfieldsone = \vfieldstwo\\ - \exprequal(\tenv, \veoneone, \vetwoone) \typearrow \vbtwo \OrTypeError\\\\ - \vb \eqdef \vbone \land \vbtwo -}{ - \exprequalcase(\tenv, \veone, \vetwo) \typearrow \vb -} -\end{mathpar} - -\begin{mathpar} - \inferrule[e\_getitem]{ - \veone \eqname \EGetItem(\veoneone, \vione)\\ - \vetwo \eqname \EGetItem(\vetwoone, \vitwo)\\\\ - \vbone \eqdef \vione = \vitwo\\ - \exprequal(\tenv, \veoneone, \vetwoone) \typearrow \vbtwo \OrTypeError\\\\ - \vb \eqdef \vbone \land \vbtwo -}{ - \exprequalcase(\tenv, \veone, \vetwo) \typearrow \vb -} -\end{mathpar} - -\begin{mathpar} - \inferrule[e\_literal]{ - \veone \eqname \ELiteral(\vvone)\\ - \vetwo \eqname \ELiteral(\vvtwo)\\\\ - \literalequal(\vvone, \vvtwo) \typearrow \vb -}{ - \exprequalcase(\tenv, \veone, \vetwo) \typearrow \vb -} -\end{mathpar} - -\begin{mathpar} -\inferrule[e\_pattern]{ - \astlabel(\veone) = \EPattern \land \astlabel(\vetwo) = \EPattern -}{ - \exprequalcase(\tenv, \veone, \vetwo) \typearrow \False -} -\end{mathpar} - -\begin{mathpar} -\inferrule[e\_record]{ - \astlabel(\veone) = \ERecord \land \astlabel(\vetwo) = \ERecord -}{ - \exprequalcase(\tenv, \veone, \vetwo) \typearrow \False -} -\end{mathpar} - -\begin{mathpar} -\inferrule[e\_tuple]{ - \veone \eqname \ETuple(\vlone)\\ - \vetwo \eqname \ETuple(\vltwo)\\ - \equallength(\vlone, \vltwo) \typearrow \True \terminateas \False\\\\ - i \in \listrange(\vlone): \exprequal(\tenv, \vlone[i], \vltwo[i]) \typearrow \vb_i \OrTypeError\\\\ - \vb \eqdef \bigwedge_{i \in \listrange(\vlone)} \vb_i -}{ - \exprequalcase(\tenv, \veone, \vetwo) \typearrow \vb -} -\end{mathpar} - -\begin{mathpar} -\inferrule[e\_unop]{ - \veone \eqname \EUnop(\opone, \veoneone)\\ - \vetwo \eqname \EUnop(\optwo, \vetwoone)\\\\ - \exprequal(\veoneone, \vetwoone) \typearrow \vbone \OrTypeError\\\\ - \vb \eqdef (\opone = \optwo) \land \vbone -}{ - \exprequalcase(\tenv, \veone, \vetwo) \typearrow \vb -} -\end{mathpar} - -\begin{mathpar} -\inferrule[e\_unknown]{ - (\astlabel(\veone) = \EUnknown \land \astlabel(\vetwo) = \EUnknown) -}{ - \exprequalcase(\tenv, \veone, \vetwo) \typearrow \False -} -\end{mathpar} - -\begin{mathpar} -\inferrule[e\_atc]{ - \veone \eqname \EATC(\veoneone, \vtone)\\ - \vetwo \eqname \EATC(\vetwoone, \vttwo)\\ - \exprequal(\tenv, \veoneone, \vetwoone) \typearrow \vbone \OrTypeError\\\\ - \typeequal(\tenv, \vtone, \vttwo) \typearrow \vbtwo \OrTypeError\\\\ - \vb \eqdef \vbone \land \vbtwo -}{ - \exprequalcase(\tenv, \veone, \vetwo) \typearrow \vb -} -\end{mathpar} - -\begin{mathpar} -\inferrule[e\_var]{ - \veone \eqname \EVar(\nameone)\\ - \vetwo \eqname \EVar(\nametwo)\\\\ - \vb \eqdef \nameone = \nametwo -}{ - \exprequalcase(\tenv, \veone, \vetwo) \typearrow \vb -} -\end{mathpar} - -% | E_Pattern _, _ | E_Record _, _ -> assert false - -\section{TypingRule.TypeEqual \label{sec:TypingRule.TypeEqual}} -\hypertarget{def-typeequal}{} -The function -\[ - \typeequal(\overname{\ty}{\vtone} \aslsep \overname{\ty}{\vttwo}) \aslto - \overname{\{\True, \False\}}{\vb} \cup \overname{\TTypeError}{\TypeErrorConfig} -\] -conservatively tests whether the type $\vtone$ is equivalent to the type $\vttwo$ in environment $\tenv$ -and yields the result in $\vb$. \ProseOtherwiseTypeError - -\subsection{Prose} -One of the following applies: -\begin{itemize} - \item All of the following apply (\textsc{different\_labels}): - \begin{itemize} - \item the AST labels of $\vtone$ and $\vttwo$ are different; - \item $\vb$ is $\False$. - \end{itemize} - - \item All of the following apply (\textsc{tbool\_treal\_tstring}): - \begin{itemize} - \item both $\vtone$ and $\vttwo$ are both either $\TBool$, $\TReal$, or $\TString$; - \item $\vb$ is $\True$. - \end{itemize} - - \item All of the following apply (\textsc{tint\_unconstrained}): - \begin{itemize} - \item both $\vtone$ and $\vttwo$ are the unconstrained integer type $\unconstrainedinteger$; - \item $\vb$ is $\True$. - \end{itemize} - - \item All of the following apply (\textsc{tint\_parameterized}): - \begin{itemize} - \item $\vtone$ is the \parameterizedintegertype\ with identifier $\vione$, that is, \\ $\TInt(\parameterized(\vione))$; - \item $\vttwo$ is the \parameterizedintegertype\ with identifier $\vitwo$, that is, \\ $\TInt(\parameterized(\vitwo))$; - \item $\vb$ is $\True$ if and only if $\vione$ is equal to $\vitwo$. - \end{itemize} - - \item All of the following apply (\textsc{tint\_wellconstrained}): - \begin{itemize} - \item $\vtone$ is the well-constrained integer type with list of constraints $\vcone$, that is, \\ $\TInt(\wellconstrained(\vcone))$; - \item $\vttwo$ is the well-constrained integer type with list of constraints $\vctwo$, that is, \\ $\TInt(\wellconstrained(\vctwo))$; - \item testing whether $\vcone$ and $\vctwo$ are equivalent in $\tenv$ yields $\vb$\ProseOrTypeError. - \end{itemize} - - \item All of the following apply (\textsc{tbits}): - \begin{itemize} - \item $\vtone$ is the bitvector type with width expression $\vwone$ and list of bitfields $\bfone$, that is, $\TBits(\vwone, \bfone)$; - \item $\vttwo$ is the bitvector type with width expression $\vwtwo$ and list of bitfields $\bftwo$, that is, $\TBits(\vwtwo, \bftwo)$; - \item testing whether $\vwone$ and $\vwtwo$ are equivalent bitwidths in $\tenv$ yields $\vbone$\ProseOrTypeError; - \item testing whether $\bfone$ and $\bftwo$ are equivalent lists of bitfields in $\tenv$ yields $\vbtwo$\ProseOrTypeError; - \item $\vb$ is $\True$ if and only if both $\vbone$ and $\vbtwo$ are $\True$. - \end{itemize} - - \item All of the following apply (\textsc{tarray}): - \begin{itemize} - \item $\vtone$ is an array type with index $\vlone$ and element type $\vtone$, that is, $\TArray(\vlone, \vtone)$; - \item $\vttwo$ is an array type with index $\vltwo$ and element type $\vttwo$, that is, $\TArray(\vltwo, \vttwo)$; - \item testing whether $\vlone$ is equivalent to $\vltwo$ in $\tenv$ yields $\vbone$\ProseOrTypeError; - \item testing whether $\vtone$ is equivalent to $\vttwo$ in $\tenv$ yields $\vbtwo$\ProseOrTypeError; - \item $\vb$ is $\True$ if and only if both $\vbone$ and $\vbtwo$ are $\True$. - \end{itemize} - - \item All of the following apply (\textsc{tnamed}): - \begin{itemize} - \item $\vtone$ is a named type with identifier $\vsone$, that is $\TNamed(\vsone)$; - \item $\vttwo$ is a named type with identifier $\vstwo$, that is $\TNamed(\vstwo)$; - \item $\vb$ is $\True$ if and only if $\vsone$ is equal to $\vstwo$. - \end{itemize} - - \item All of the following apply (\textsc{tenum}): - \begin{itemize} - \item $\vtone$ is an enumeration type with identifier $\vlone$, that is $\TEnum(\vlone)$; - \item $\vttwo$ is an enumeration type with identifier $\vltwo$, that is $\TEnum(\vltwo)$; - \item $\vb$ is $\True$ if and only if $\vlone$ is equal to $\vltwo$. - \end{itemize} - - \item All of the following apply (\textsc{tstructured}): - \begin{itemize} - \item $L$ is either $\TRecord$ or $\TException$; - \item $\vtone$ is a \structuredtype\ with list of fields $\vfieldsone$, that is $L(\vfieldsone)$; - \item $\vttwo$ is a \structuredtype\ with list of fields $\vfieldstwo$, that is $L(\vfieldstwo)$; - \item checking whether the set of field names in $\vfieldsone$ is equal to the set of field names in $\vfieldstwo$ - yields $\True$ or $\False$, which short-circuits the entire rule; - \item for each field $\vf$ in the set of fields of $\vfieldsone$, testing whether the type associated with - $\vf$ in $\vfieldsone$ is equivalent to the type associated with - $\vf$ in $\vfieldstwo$ in $\tenv$ yields $\vb_\vf$\ProseOrTypeError; - \item $\vb$ is $\True$ if and only if $\vb_\vf$ is $\True$ for each field $\vf$ in the set of fields of $\vfieldsone$. - \end{itemize} - - \item All of the following apply (\textsc{ttuple}): - \begin{itemize} - \item $\vtone$ is a tuple type with list of types $\vtsone$, that is $\TTuple(\vtsone)$; - \item $\vttwo$ is a tuple type with list of types $\vtstwo$, that is $\TTuple(\vtstwo)$; - \item checking whether the list of types $\vtsone$ has the same length as the list of types $\vtstwo$ yields $\True$ - or $\False$, which short-circuits the entire rule; - \item for each index $i$ in the list $\vtsone$, testing whether $\vtsone[i]$ is equivalent to $\vtstwo[i]$ in $\tenv$ - yields $\vb_i$\ProseOrTypeError; - \item $\vb$ is $\True$ if and only if $\vb_i$ is $\True$ for each index $i$ in the list $\vtsone$. - \end{itemize} -\end{itemize} - -\subsection{Formally} -\begin{mathpar} -\inferrule[different\_labels]{ - \astlabel(\vtone) \neq \astlabel(\vttwo) -}{ - \typeequal(\tenv, \vtone, \vttwo) \typearrow \False -} -\end{mathpar} - -\begin{mathpar} -\inferrule[TBool\_TReal\_TString]{ - \astlabel(\vtone) = \astlabel(\vttwo)\\ - \astlabel(\vtone) \in \{\TBool, \TReal, \TString\} -}{ - \typeequal(\tenv, \vtone, \vttwo) \typearrow \True -} -\and -\end{mathpar} - -\begin{mathpar} -\inferrule[tint\_unconstrained]{} -{ - \typeequal(\tenv, \unconstrainedinteger, \unconstrainedinteger) \typearrow \True -} -\and -\inferrule[tint\_parameterized]{ - \vb \eqdef \vione = \vitwo -}{ - \typeequal(\tenv, \TInt(\parameterized(\vione)), \TInt(\parameterized(\vitwo))) \typearrow \vb -} -\and -\inferrule[tint\_wellconstrained]{ - \constraintsequal(\tenv, \vcone, \vctwo) \typearrow \vb \OrTypeError -}{ - \typeequal(\tenv, \TInt(\wellconstrained(\vcone)), \TInt(\wellconstrained(\vctwo))) \typearrow \vb -} -\end{mathpar} - -\begin{mathpar} -\inferrule[tbits]{ - \bitwidthequal(\tenv, \vwone, \vwtwo) \typearrow \vbone \OrTypeError\\\\ - \bitfieldsequal(\tenv, \bfone, \bftwo) \typearrow \vbtwo \OrTypeError\\\\ - \vb \eqdef \vbone \land \vbtwo -}{ - \typeequal(\tenv, \TBits(\vwone, \bfone), \TBits(\vwtwo, \bftwo)) \typearrow \vb -} -\end{mathpar} - -\begin{mathpar} -\inferrule[tarray]{ - \exprequal(\tenv, \vlone, \vltwo) \typearrow \vbone \OrTypeError\\\\ - \typeequal(\tenv, \vtone, \vttwo) \typearrow \vbtwo \OrTypeError\\\\ - \vb \eqdef \vbone \land \vbtwo -}{ - \typeequal(\tenv, \TArray(\vlone, \vtone), \TArray(\vltwo, \vttwo)) \typearrow \vb -} -\end{mathpar} - -\begin{mathpar} -\inferrule[tnamed]{ - \vb \eqdef \vsone = \vstwo -}{ - \typeequal(\tenv, \TNamed(\vsone), \TNamed(\vstwo)) \typearrow \vb -} -\end{mathpar} - -\begin{mathpar} -\inferrule[tenum]{ - \vb \eqdef \vlone = \vltwo -}{ - \typeequal(\tenv, \TEnum(\vlone), \TEnum(\vltwo)) \typearrow \vb -} -\end{mathpar} - -\begin{mathpar} -\inferrule[tstructured]{ - L \in \{\TRecord, \TException\}\\ - \booltrans{\fieldnames(\vfieldsone) = \fieldnames(\vfieldstwo)} \booltransarrow \True \terminateas \False\\\\ - { - \begin{array}{l} - \vf \in \fieldnames(\vfieldsone): \\ \typeequal(\tenv, \fieldtype(\vfieldsone, \vf), \fieldtype(\vfieldstwo, \vf)) \typearrow \vb_\vf \OrTypeError - \end{array} - }\\\\ - \vb \eqdef \bigwedge_{\vf \in \fieldnames(\vfieldsone)} \vb_\vf -}{ - \typeequal(\tenv, L(\vfieldsone), L(\vfieldstwo)) \typearrow \vb -} -\end{mathpar} - -\begin{mathpar} -\inferrule[ttuple]{ - \equallength(\vtsone, \vtstwo) \typearrow \True \terminateas \False\\ - i \in \listrange(\vtsone): \typeequal(\tenv, \vtsone[i], \vtstwo[i]) \typearrow \vb_i \OrTypeError\\\\ - \vb \eqdef \bigwedge_{i \in \listrange(\vtsone)} \vb_i -}{ - \typeequal(\tenv, \TTuple(\vtsone), \TTuple(\vtstwo)) \typearrow \vb -} -\end{mathpar} - -\section{TypingRule.BitwidthEqual \label{sec:TypingRule.BitwidthEqual}} -\hypertarget{def-bitwidthequal}{} -The function -\[ - \bitwidthequal(\overname{\staticenvs}{\tenv} \aslsep \overname{\expr}{\vwone} \aslsep \overname{\expr}{\vwtwo}) - \aslto \overname{\{\True, \False\}}{\vb} \cup \overname{\TTypeError}{\TypeErrorConfig} -\] -conservatively tests whether the bitwidth expression $\vwone$ is equivalent to the bitwidth expression $\vwtwo$ -in environment $\tenv$ and yields the result in $\vb$. \ProseOtherwiseTypeError - -\subsection{Prose} -Testing whether the expressions $\vwone$ and $\vwtwo$ are equivalent in $\tenv$ yields $\vb$\ProseOrTypeError. - -\subsection{Formally} -\begin{mathpar} -\inferrule{ - \exprequal(\tenv, \vwone, \vwtwo) \typearrow \vb \OrTypeError -}{ - \bitwidthequal(\tenv, \vwone, \vwtwo) \typearrow \vb -} -\end{mathpar} - -\section{TypingRule.BitFieldsEqual \label{sec:TypingRule.BitFieldsEqual}} -\hypertarget{def-bitfieldsequal}{} -The function -\[ - \bitfieldsequal(\overname{\staticenvs}{\tenv} \aslsep \overname{\bitfield^*}{\bfone} \aslsep \overname{\bitfield^*}{\bftwo}) - \aslto \overname{\{\True, \False\}}{\vb} \cup \overname{\TTypeError}{\TypeErrorConfig} -\] -conservatively tests whether the list of bitfields $\bfone$ is equivalent to the list of bitfields $\bftwo$ -in environment $\tenv$ and yields the result in $\vb$. \ProseOtherwiseTypeError - -\subsection{Prose} -One of the following applies: -\begin{itemize} - \item All of the following apply (\textsc{different\_lengths}): - \begin{itemize} - \item the number of bitfields in $\bfone$ is different from the number of bitfields in $\bftwo$; - \item $\vb$ is $\False$. - \end{itemize} - - \item All of the following apply (\textsc{same\_lengths}): - \begin{itemize} - \item the number of bitfields in $\bfone$ is the same as the number of bitfields in $\bftwo$; - \item testing whether the bitfield $\bfone[i]$ is equivalent to $\bftwo[i]$ in $\tenv$ for every index - of $\bfone$ yields $\vb_i$\ProseOrTypeError; - \item $\vb$ is $\True$ if and only if $\vb_i$ is $\True$ for every index of $\bfone$. - \end{itemize} -\end{itemize} - -\subsection{Formally} -\begin{mathpar} -\inferrule[different\_lengths]{ - \equallength(\bfone, \bftwo) \typearrow \False -}{ - \bitfieldsequal(\tenv, \bfone, \bftwo) \typearrow \False -} -\and -\inferrule[same\_lengths]{ - \equallength(\bfone, \bftwo) \typearrow \True\\ - i\in\listrange(\bfone): \bitfieldequal(\tenv, \bfone[i], \bftwo[i]) \typearrow \vb_i\\\\ - \vb \eqdef \bigwedge_{i\in\listrange(\bfone)} \vb_i -}{ - \bitfieldsequal(\tenv, \bfone, \bftwo) \typearrow \vb -} -\end{mathpar} - -\section{TypingRule.BitFieldEqual \label{sec:TypingRule.BitFieldEqual}} -The function -\[ - \bitfieldequal(\overname{\staticenvs}{\tenv} \aslsep \overname{\bitfield}{\bfone} \aslsep \overname{\bitfield}{\bftwo}) - \aslto \overname{\{\True, \False\}}{\vb} \cup \overname{\TTypeError}{\TypeErrorConfig} -\] -conservatively tests whether the bitfield $\bfone$ is equivalent to the bitfield $\bftwo$ in environment $\tenv$ -and yields the result in $\vb$. \ProseOtherwiseTypeError - -One of the following applies: -\begin{itemize} - \item All of the following apply (\textsc{different\_labels}): - \begin{itemize} - \item the AST labels of $\bfone$ and $\bftwo$ are different; - \item $\vb$ is $\False$. - \end{itemize} - - \item All of the following apply (\textsc{bitfield\_simple}): - \begin{itemize} - \item $\bfone$ is a simple bitfield with name $\nameone$ and list of slices $\slicesone$, that is, \\ $\BitFieldSimple(\nameone, \slicesone)$; - \item $\bftwo$ is a simple bitfield with name $\nametwo$ and list of slices $\slicestwo$, that is, \\ $\BitFieldSimple(\nametwo, \slicestwo)$; - \item checking whether $\nameone$ is equal to $\nametwo$ yields $\vbone$; - \item testing whether $\slicesone$ and $\slicestwo$ are equivalent in $\tenv$ yields $\vbtwo$\ProseOrTypeError; - \item $\vb$ is $\True$ if and only if both $\vbone$ and $\vbtwo$ are $\True$. - \end{itemize} - - \item All of the following apply (\textsc{bitfield\_nested}): - \begin{itemize} - \item $\bfone$ is a nested bitfield with name $\nameone$, list of slices $\slicesone$, and nested bitfields $\bfoneone$, that is, - $\BitFieldNested(\nameone, \slicesone, \bfoneone)$; - \item $\bftwo$ is a nested bitfield with name $\nametwo$, list of slices $\slicestwo$, and nested bitfields $\bftwoone$, that is, - $\BitFieldNested(\nametwo, \slicestwo, \bftwoone)$; - \item checking whether $\nameone$ is equal to $\nametwo$ yields $\vbone$; - \item testing whether $\slicesone$ and $\slicestwo$ are equivalent in $\tenv$ yields $\vbtwo$\ProseOrTypeError; - \item testing whether the bitfields $\bfoneone$ and $\bftwoone$ are equivalent in $\tenv$ yields $\vbtwo$\ProseOrTypeError; - \item $\vb$ is $\True$ if and only if both $\vbone$ and $\vbtwo$ are $\True$. - \end{itemize} - - \item All of the following apply (\textsc{bitfield\_typed}): - \begin{itemize} - \item $\bfone$ is a typed bitfield with name $\nameone$, list of slices $\slicesone$, and type $\vtone$, that is, - $\BitFieldType(\nameone, \slicesone, \vtone)$; - \item $\bftwo$ is a typed bitfield with name $\nametwo$, list of slices $\slicestwo$, and type $\vttwo$, that is, - $\BitFieldType(\nametwo, \slicestwo, \vttwo)$; - \item checking whether $\nameone$ is equal to $\nametwo$ yields $\True$\ProseTerminateAs{\False}; - \item testing whether $\slicesone$ and $\slicestwo$ are equivalent in $\tenv$ yields $\vbone$\ProseOrTypeError; - \item testing whether the types $\vtone$ and $\vttwo$ are equivalent in $\tenv$ yields $\vbtwo$\ProseOrTypeError; - \item $\vb$ is $\True$ if and only if both $\vbone$ and $\vbtwo$ are $\True$. - \end{itemize} -\end{itemize} - -\subsection{Formally} -\begin{mathpar} -\inferrule[different\_labels]{ - \astlabel(\bfone) \neq \astlabel(\bftwo) -}{ - \bitfieldequal(\tenv, \bfone, \bftwo) \typearrow \False -} -\and -\inferrule[bitfield\_simple]{ - \bfone \eqname \BitFieldSimple(\nameone, \slicesone)\\ - \bftwo \eqname \BitFieldSimple(\nametwo, \slicestwo)\\ - \booltrans{\nameone = \nametwo} \booltransarrow \vbone\\ - \slicesequal(\tenv, \slicesone, \slicestwo) \typearrow \vbtwo \OrTypeError\\\\ - \vb \eqdef \vbone \land \vbtwo -}{ - \bitfieldequal(\tenv, \bfone, \bftwo) \typearrow \vb -} -\and -\inferrule[bitfield\_nested]{ - \bfone \eqname \BitFieldNested(\nameone, \slicesone, \bfoneone)\\ - \bftwo \eqname \BitFieldNested(\nametwo, \slicestwo, \bftwoone)\\ - \booltrans{\nameone = \nametwo} \booltransarrow \True \terminateas \False\\\\ - \slicesequal(\tenv, \slicesone, \slicestwo) \typearrow \vbone \terminateas \TypeErrorConfig,\\\\ - \bitfieldsequal(\tenv, \bfoneone, \bftwoone) \typearrow \vbtwo -}{ - \bitfieldequal(\tenv, \bfone, \bftwo) \typearrow \vb -} -\and -\inferrule[bitfield\_typed]{ - \bfone \eqname \BitFieldType(\nameone, \slicesone, \vtone)\\ - \bftwo \eqname \BitFieldType(\nametwo, \slicestwo, \vttwo)\\ - \booltrans{\nameone = \nametwo} \booltransarrow \True \terminateas \False \\\\ - \slicesequal(\tenv, \slicesone, \slicestwo) \typearrow \vbone \OrTypeError\\\\ - \typeequal(\tenv, \vtone, \vttwo) \typearrow \vbtwo \OrTypeError\\\\ - \vb \eqdef \vbone \land \vbtwo -}{ - \bitfieldequal(\tenv, \bfone, \bftwo) \typearrow \vb -} -\end{mathpar} - -\section{TypingRule.ConstraintsEqual \label{sec:TypingRule.ConstraintsEqual}} -\hypertarget{def-constraintsequal}{} -The function -\[ - \constraintsequal(\overname{\staticenvs}{\tenv} \aslsep \overname{\intconstraint^*}{\csone} \aslsep \overname{\intconstraint^*}{\cstwo}) - \aslto \overname{\{\True, \False\}}{\vb} \cup \overname{\TTypeError}{\TypeErrorConfig} -\] -conservatively tests whether the constraint list $\csone$ is equivalent to the constraint list $\cstwo$ in environment $\tenv$ -and yields the result in $\vb$. \ProseOtherwiseTypeError - -\subsection{Prose} -All of the following apply: -\begin{itemize} - \item checking whether the number of constraints in $\csone$ is the same as the number of constraints in $\cstwo$ - yields $\True$\ProseTerminateAs{\False}; - \item testing whether the constraint $\csone[i]$ is equivalent to the constraint $\cstwo[i]$ in $\tenv$ - yields $\vb_i$ for each index in the index in the indices for $\csone$ ($i\in\listrange(\csone)$)\ProseOrTypeError; - \item $\vb$ is $\True$ if and only if all $\vb_i$ are $\True$ for each index in the indices for $\csone$. -\end{itemize} - -\subsection{Formally} -\begin{mathpar} -\inferrule{ - \equallength(\csone, \cstwo) \typearrow \True \terminateas \False\\ - i\in\listrange(\csone): \constraintequal(\tenv, \csone[i], \cstwo[i]) \typearrow \vb_i \OrTypeError\\\\ - \vb \eqdef \bigwedge_{i\in\listrange(\csone)} \vb_i -}{ - \constraintsequal(\tenv, \csone, \cstwo) \typearrow \vb -} -\end{mathpar} - -\section{TypingRule.ConstraintEqual \label{sec:TypingRule.ConstraintEqual}} -\hypertarget{def-constraintequal}{} -The function -\[ - \constraintequal(\overname{\staticenvs}{\tenv} \aslsep \overname{\intconstraint}{\vcone} \aslsep \overname{\intconstraint}{\vstwo}) - \aslto \overname{\{\True, \False\}}{\vb} \cup \overname{\TTypeError}{\TypeErrorConfig} -\] -conservatively tests whether the constraint $\vcone$ is equivalent to the constraint $\vctwo$ in environment $\tenv$ -and yields the result in $\vb$. \ProseOtherwiseTypeError - -\subsection{Prose} -One of the following applies: -\begin{itemize} - \item All of the following apply (\textsc{different\_labels}): - \begin{itemize} - \item the AST labels of $\vcone$ and $\vctwo$ are different; - \item define $\vb$ as $\False$. - \end{itemize} - - \item All of the following apply (\textsc{constraint\_exact}): - \begin{itemize} - \item $\vcone$ is an exact constraint with subexpression $\veone$, that is, $\ConstraintExact(\veone)$; - \item $\vctwo$ is an exact constraint with subexpression $\vetwo$, that is, $\ConstraintExact(\vetwo)$; - \item applying $\exprequal$ to $\veone$ and $\vetwo$ yields $\vb$\ProseOrTypeError. - \end{itemize} - - \item All of the following apply (\textsc{constraint\_range}): - \begin{itemize} - \item $\vcone$ is a range constraint with subexpressions $\veoneone$ and $\veonetwo$, that is, \\ $\ConstraintRange(\veoneone, \veonetwo)$; - \item $\vctwo$ is a range constraint with subexpressions $\vetwoone$ and $\vetwotwo$, that is, \\ $\ConstraintRange(\vetwoone, \vetwotwo)$; - \item applying $\exprequal$ to $\veoneone$ and $\vetwoone$ yields $\vbone$\ProseOrTypeError; - \item applying $\exprequal$ to $\veonetwo$ and $\vetwotwo$ yields $\vbtwo$\ProseOrTypeError; - \item define $\vb$ as $\True$ if and only if both $\vbone$ and $\vbtwo$ are $\True$. - \end{itemize} -\end{itemize} - -\subsection{Formally} -\begin{mathpar} -\inferrule[different\_labels]{ - \astlabel(\vcone) \neq \astlabel(\vctwo) -}{ - \constraintequal(\tenv, \vcone, \vctwo) \typearrow \False -} -\and -\inferrule[constraint\_exact]{ - \vcone \eqname \ConstraintExact(\veone)\\ - \vctwo \eqname \ConstraintExact(\vetwo)\\ - \exprequal(\tenv, \veone, \vetwo) \typearrow \vb \OrTypeError -}{ - \constraintequal(\tenv, \vcone, \vctwo) \typearrow \vb -} -\and -\inferrule[constraint\_range]{ - \bfone \eqname \ConstraintRange(\veoneone, \veonetwo)\\ - \bftwo \eqname \ConstraintRange(\vetwoone, \vetwotwo)\\ - \exprequal(\tenv, \veoneone, \vetwoone) \typearrow \vbone \OrTypeError\\\\ - \exprequal(\tenv, \veonetwo, \vetwotwo) \typearrow \vbtwo \OrTypeError\\\\ - \vb \eqdef \vbone \land \vbtwo -}{ - \constraintequal(\tenv, \bfone, \bftwo) \typearrow \vb -} -\end{mathpar} - -\section{TypingRule.SlicesEqual \label{sec:TypingRule.SlicesEqual}} -\hypertarget{def-slicesequal}{} -The function -\[ - \slicesequal(\overname{\staticenvs}{\tenv} \aslsep \overname{\slice^*}{\slicesone} \aslsep \overname{\slice^*}{\slicestwo}) - \aslto \overname{\{\True, \False\}}{\vb} \cup \overname{\TTypeError}{\TypeErrorConfig} -\] -conservatively tests whether the list of slices $\slicesone$ is equivalent to the list of slices $\slicestwo$ -in environment $\tenv$ and yields the result in $\vb$. \ProseOtherwiseTypeError - -\subsection{Formally} -One of the following applies: -\begin{itemize} - \item All of the following apply (\textsc{different\_lengths}): - \begin{itemize} - \item checking whether the number of slices in $\slicesone$ is equal to the number of slice in $\slicestwo$ yields $\False$; - \item $\vb$ is $\False$. - \end{itemize} - - \item All of the following apply (\textsc{same\_lengths}): - \begin{itemize} - \item checking whether the number of slices in $\slicesone$ is equal to the number of slice in $\slicestwo$ yields $\True$; - \item determining whether the expression $\slicesone[i]$ is equivalent to $\slicestwo[i]$ in $\tenv$ - for each index in the indices for $\slicesone$ ($i \in \listrange(\slicesone$) yields $\vb_i$\ProseOrTypeError; - \item $\vb$ is $\True$ if and only if all $\vb_i$ are $\True$ for each index in the indices for $\slicesone$. - \end{itemize} -\end{itemize} - -\subsection{Formally} -\begin{mathpar} -\inferrule[different\_lengths]{ - \equallength(\slicesone, \slicestwo) \typearrow \False -}{ - \slicesequal(\tenv, \slicesone, \slicestwo) \typearrow \False -} -\and -\inferrule[same\_lengths]{ - \equallength(\slicesone, \slicestwo) \typearrow \True\\ - i\in\listrange(\slicesone): \sliceequal(\tenv, \slicesone[i], \slicestwo[i]) \typearrow \vb_i \OrTypeError\\\\ - \vb \eqdef \bigwedge_{i\in\listrange(\slicesone)} \vb_i -}{ - \slicesequal(\tenv, \slicesone, \slicestwo) \typearrow \vb -} -\end{mathpar} - -\section{TypingRule.SliceEqual \label{sec:TypingRule.SliceEqual}} -\hypertarget{def-sliceequal}{} -The function -\[ - \sliceequal(\overname{\staticenvs}{\tenv} \aslsep \overname{\slice}{\sliceone} \aslsep \overname{\slice}{\slicetwo}) - \aslto \overname{\{\True, \False\}}{\vb} \cup \overname{\TTypeError}{\TypeErrorConfig} -\] -conservatively tests whether the slice $\sliceone$ is equivalent to the slice $\slicetwo$ -in environment $\tenv$ and yields the result in $\vb$. \ProseOtherwiseTypeError - -\subsection{Prose} -One of the following applies: -\begin{itemize} - \item All of the following apply (\textsc{different\_labels}): - \begin{itemize} - \item $\sliceone$ and $\slicetwo$ have different AST labels; - \item $\vb$ is $\False$. - \end{itemize} - - \item All of the following apply (\textsc{slice\_single}): - \begin{itemize} - \item $\sliceone$ is a slice for a single position, given by the expression $\veone$, that is, $\SliceSingle(\veone)$; - \item $\slicetwo$ is a slice for a single position, given by the expression $\vetwo$, that is, $\SliceSingle(\vetwo)$; - \item testing $\veone$ and $\vetwo$ for equivalence yields $\vb$\ProseOrTypeError. - \end{itemize} - - \item All of the following apply (\textsc{slice\_range}): - \begin{itemize} - \item $\sliceone$ is a slice for a range of positions, given by the expressions $\veoneone$ and $\veonetwo$, that is, $\SliceRange(\veoneone, \veonetwo)$; - \item $\slicetwo$ is a slice for a range of positions, given by the expressions $\vetwoone$ and $\vetwotwo$, that is, $\SliceRange(\vetwoone, \vetwotwo)$; - \item testing $\veoneone$ and $\vetwoone$ for equivalence yields $\vbone$\ProseOrTypeError; - \item testing $\veonetwo$ and $\vetwotwo$ for equivalence yields $\vbtwo$\ProseOrTypeError; - \item $\vb$ is $\True$ if and only if both $\vbone$ and $\vbtwo$ are $\True$. - \end{itemize} - - \item All of the following apply (\textsc{slice\_length}): - \begin{itemize} - \item $\sliceone$ is a slice for a range of positions, given by the start expression $\veoneone$ and length expression $\veonetwo$, that is, $\SliceLength(\veoneone, \veonetwo)$; - \item $\slicetwo$ is a slice for a range of positions, given by the start expression $\vetwoone$ and length expression $\vetwotwo$, that is, $\SliceLength(\vetwoone, \vetwotwo)$; - \item testing $\veoneone$ and $\vetwoone$ for equivalence yields $\vbone$\ProseOrTypeError; - \item testing $\veonetwo$ and $\vetwotwo$ for equivalence yields $\vbtwo$\ProseOrTypeError; - \item $\vb$ is $\True$ if and only if both $\vbone$ and $\vbtwo$ are $\True$. - \end{itemize} -\end{itemize} - -\subsection{Formally} -\begin{mathpar} -\inferrule[different\_label]{ - \astlabel(\sliceone) \neq \astlabel(\slicetwo) -}{ - \slicesequal(\tenv, \sliceone, \slicetwo) \typearrow \False -} -\and -\inferrule[slice\_single]{ - \exprequal(\tenv, \veone, \vetwo) \typearrow \vb \OrTypeError -}{ - \slicesequal(\tenv, \SliceSingle(\veone), \SliceSingle(\vetwo)) \typearrow \vb -} -\and -\inferrule[slice\_range]{ - \exprequal(\tenv, \veoneone, \vetwoone) \typearrow \vbone \OrTypeError\\\\ - \exprequal(\tenv, \vetwoone, \vetwotwo) \typearrow \vbtwo \OrTypeError\\\\ - \vb \eqdef \vbone \land \vbtwo -}{ - \slicesequal(\tenv, \SliceRange(\veoneone, \veonetwo), \SliceRange(\vetwoone, \vetwotwo)) \typearrow \vb -} -\and -\inferrule[slice\_length]{ - \exprequal(\tenv, \veoneone, \vetwoone) \typearrow \vbone \OrTypeError\\\\ - \exprequal(\tenv, \vetwoone, \vetwotwo) \typearrow \vbtwo \OrTypeError\\\\ - \vb \eqdef \vbone \land \vbtwo -}{ - \slicesequal(\tenv, \SliceLength(\veoneone, \veonetwo), \SliceLength(\vetwoone, \vetwotwo)) \typearrow \vb -} -\end{mathpar} - -\section{TypingRule.ArrayLengthEqual \label{sec:TypingRule.ArrayLengthEqual}} -\hypertarget{def-arraylengthequal}{} -The function -\[ - \arraylengthequal(\overname{\arrayindex}{\vlone} \aslsep \overname{\arrayindex}{\vltwo}) - \aslto \overname{\{\True, \False\}}{\vb} \cup \overname{\TTypeError}{\TypeErrorConfig} -\] -tests whether the array lengths $\vlone$ and $\vltwo$ are equivalent and yields the result -in $\vb$. \ProseOtherwiseTypeError - -\subsection{Prose} -One of the following applies: -\begin{itemize} - \item All of the following apply (\textsc{different\_labels}): - \begin{itemize} - \item $\vlone$ and $\vltwo$ have different AST labels; - \item $\vb$ is $\False$. - \end{itemize} - - \item All of the following apply (\textsc{expr\_expr}): - \begin{itemize} - \item $\vlone$ is an integer type length expression with subexpression $\veoneone$, that is, \\ $\ArrayLengthExpr(\veoneone)$; - \item $\vltwo$ is an integer type length expression with subexpression $\vetwoone$, that is, \\ $\ArrayLengthExpr(\vetwoone)$; - \item testing whether $\veoneone$ and $\vetwoone$ are equivalent in $\tenv$ yields $\vb$\ProseOrTypeError. - \end{itemize} - - \item All of the following apply (\textsc{enum\_enum}): - \begin{itemize} - \item $\vlone$ is an enumeration type length expression over the enumeration $\vsone$, that is, $\ArrayLengthEnum(\vsone, \Ignore)$; - \item $\vltwo$ is an enumeration type length expression over the enumeration $\vstwo$, that is, $\ArrayLengthEnum(\vstwo, \Ignore)$; - \item $\vb$ is $\True$ if and only if $\vsone$ is equal to $\vstwo$. - \end{itemize} -\end{itemize} - -\subsection{Formally} -\begin{mathpar} -\inferrule[different\_labels]{ - \astlabel(\vlone) \neq \astlabel(\vltwo) -}{ - \arraylengthequal(\vlone, \vltwo) \typearrow \False -} -\and - \inferrule[expr\_expr]{ - \exprequal(\veoneone, \vetwoone) \typearrow \vb \OrTypeError -}{ - \arraylengthequal(\ArrayLengthExpr(\veoneone), \ArrayLengthExpr(\vetwoone)) \typearrow \vb -} -\and -\inferrule[enum\_enum]{ - \vb \eqdef \vsone = \vstwo -}{ - \arraylengthequal(\ArrayLengthEnum(\vsone, \Ignore), \ArrayLengthEnum(\vstwo, \Ignore)) \typearrow \vb -} -\end{mathpar} - -\section{TypingRule.LiteralEqual \label{sec:TypingRule.LiteralEqual}} -\hypertarget{def-literalequal}{} -The function -\[ - \literalequal(\overname{\literal}{\vvone} \aslsep \overname{\literal}{\vvtwo}) \rightarrow \overname{\{\True, \False\}}{\vb} -\] -tests whether literal $\vvone$ is $\vvtwo$ by equating them. - -\subsection{Prose} -$\vb$ is $\True$ if and only if $\vvone$ is equal to $\vvtwo$. - -\subsection{Formally} -\begin{mathpar} -\inferrule{ - \vb \eqdef \vvone = \vvtwo -}{ - \literalequal(\vvone, \vvtwo) \typearrow \vb -} -\end{mathpar} - -\section{TypingRule.ReduceIR \label{sec:TypingRule.ReduceIR}} -\hypertarget{def-reduceir}{} -The function -\[ -\reduceir(\overname{\polynomial}{\vp}) \aslto \overname{\polynomial}{\newp} -\] -simplifies the polynomial $\vp$, yielding the simplified polynomial $\newp$. - -\subsection{Prose} -\subsection{Formally} -\section{TypingRule.PolynomialToExpr \label{sec:TypingRule.PolynomialToExpr}} -\hypertarget{def-polynomialtoexpr}{} -The function -\[ -\polynomialtoexpr(\overname{\polynomial}{\vp}) \typearrow \overname{\expr}{\ve} -\] -transforms a polynomial $\vp$ into the corresponding expression $\ve$. - -\subsection{Prose} -One of the following applies: -\begin{itemize} - \item All of the following apply (\textsc{empty}): - \begin{itemize} - \item $\vp$ is the polynomial with an empty list of monomials, that is, $\emptyfunc$; - \item define $\ve$ as the literal expression for $0$. - \end{itemize} - - \item All of the following apply (\textsc{non\_empty}): - \begin{itemize} - \item $\vp$ is the polynomial $f$; - \item sorting (see $\sort$ for details) the graph of $f$ (see $\funcgraph$ for details) - yields $\monoms$ --- a list consisting of pairs of unitary monomials and rationals. - In principle, any total order of the graph of $f$ is acceptable for sorting. - The function $\comparemonomialbindings$ provides one such way of ordering - the graph of $f$; - \item transforming $\monoms$ to an expression and sign via $\monomialstoexpr$ yields the expression $\veone$ - and sign $\vsone$; - \item define $\ve$ as $\veone$ if $\vsone$ is $1$, the integer literal expression for $0$ if $\vsone$ is $0$, - and the unary expression negating $\veone$, that is, - $\EUnop(\NEG, \veone)$, if $\vsone$ is $-1$. - \end{itemize} -\end{itemize} - -\subsection{Formally} -\begin{mathpar} -\inferrule[empty]{} -{ - \polynomialtoexpr(\overname{\emptyfunc}{\vp}) \typearrow \overname{\ELiteral(\lint(0))}{\ve} -} -\and -\inferrule[non\_empty]{ - \sort(\funcgraph(f), \comparemonomialbindings) = \monoms\\ - \monomialstoexpr(\monoms) \typearrow (\veone, \vsone)\\ - { - \ve \eqdef \begin{cases} - \ELiteral(\lint(0)) & \text{if }\vsone = 0\\ - \veone & \text{if }\vsone = 1\\ - \EUnop(\NEG, \veone) & \text{if }\vsone = -1 - \end{cases} - } -}{ - \polynomialtoexpr(\overname{f}{\vp}) \typearrow \ve -} -\end{mathpar} - -\section{TypingRule.CompareMonomialBindings \label{sec:TypingRule.CompareMonomialBindings}} -\hypertarget{def-comparemonomialbindings}{} -The function -\[ -\comparemonomialbindings( - (\overname{\monomial}{\vmone}\times\overname{\Q}{\vqone}) \aslsep - (\overname{\monomial}{\vmtwo}\times\overname{\Q}{\vqtwo}) -) \aslto \overname{\{-1,0,1\}}{\vs} -\] -compares two monomial bindings given by $(\vmone, \vqone)$ and $(\vmtwo, \vqtwo)$ -and yields in $\vs$ $-1$ to mean that the first monomial binding should be ordered before the second, -$0$ to mean that any ordering of the monomial bindings is acceptable, -and $1$ to mean that the second monomial binding should be ordered before the first. - -\subsection{Prose} -One of the following applies: -\begin{itemize} - \item All of the following apply (\textsc{equal\_monomials}): - \begin{itemize} - \item $\vmone$ is $f$ and $\vmtwo$ is $g$; - \item $f$ is equal to $g$; - \item $\vs$ is the sign of $\vqtwo - \vqone$. - \end{itemize} - - \item All of the following apply (\textsc{different\_monomials}): - \begin{itemize} - \item $\vmone$ is $f$ and $\vmtwo$ is $g$; - \item $f$ is different from to $g$; - \item $\ids$ is the list obtained by taking the set of identifiers in the domain of $f$ and in the domain of $g$, - and sorting them according to the lexical order for identifiers (ASCII string order); - \item $\vv$ is the first identifier in $\ids$ for which $f$ and $g$ behave differently (either one of them is defined - for $\vv$ and the other is not, or they both bind $\vv$ to a different value); - \item $s$ is determined as follows: $1$ if $\vv$ is not in the domain of $f$ and is in the domain of $g$; - $-1$ if $\vv$ is not in the domain of $f$ and is in the domain of $g$; - otherwise it is the sign of $g(\vv)-f(\vv)$. - \end{itemize} -\end{itemize} - -\subsection{Formally} -\hypertarget{def-compareidentifier}{} -The function $\compareidentifier$ compares two identifiers, which are lists of ASCII characters, -via the lexicographic ordering. - -\begin{mathpar} -\inferrule[equal\_monomials]{ - f = g\\ - \vs \eqdef \sign(\vqtwo - \vqone) -}{ - \comparemonomialbindings((\overname{f}{\vmone}, \vqone), (\overname{g}{\vmtwo}, \vqtwo)) \typearrow \vs -} -\and -\inferrule[different\_monomials]{ - f \neq g\\ - \ids \eqdef \sort(\dom(f) \cup \dom(g), \compareidentifier)\\ - \ids \eqname \idsone \concat \idstwo\\ - \vi\in\listrange(\idsone): f(\idsone[\vi]) = g(\idsone[\vi])\\ - \vv \eqdef \idstwo[1]\\ - \vs \eqdef { - \begin{cases} - 1 & f(\vv) = \bot \land g(\vv) \neq \bot\\ - -1 & f(\vv) \neq \bot \land g(\vv) = \bot\\ - \sign(g(\vv) - f(\vv)) & f(\vv) \neq \bot \land g(\vv) \neq \bot\\ - \end{cases} -} -}{ - \comparemonomialbindings((\overname{f}{\vmone}, \vqone), (\overname{g}{\vmtwo}, \vqtwo)) \typearrow \vs -} -\end{mathpar} - -\section{TypingRule.MonomialsToExpr \label{sec:TypingRule.MonomialsToExpr}} -\hypertarget{def-monomialstoexpr}{} -The function -\[ -\monomialstoexpr(\overname{(\overname{\unitarymonomial}{\vm}\times\overname{\Q}{q})^*}{\monoms}) \aslto -(\overname{\expr}{\ve},\overname{\{-1,0,1\}}{\vs}) -\] -transforms a list consisting of pairs of unitary monomials and rational factors $\monoms$ (so, general monomials), -into an expression $\ve$, which represents the absolute value of the sum of all the monomials, -and a sign value $\vs$, which indicates the sign of the resulting sum. - -\subsection{Prose} -One of the following applies: -\begin{itemize} - \item All of the following apply (\textsc{empty}): - \begin{itemize} - \item $\monoms$ is an empty list; - \item $\ve$ is the literal expression for the integer $0$ and $\vs$ is $0$. - \end{itemize} - - \item All of the following apply (\textsc{non\_empty}): - \begin{itemize} - \item $\monoms$ is a list with $(\vm,q)$ as its \head\ and $\monomsone$ as its \tail; - \item transforming the unitary monomial $\vm$ to an expression via \\ $\unitarymonomialstoexpr$ yields $\veonep$; - \item transforming $\veonep$ and $q$ via $\monomialtoexpr$ yields the expression $\veone$ and sign $\vsone$; - \item transforming $\monoms$ to an expression and sign via $\monomialstoexpr$ yields $(\vetwo, \vstwo)$; - \item symbolically adding $\veone, \vsone, \vetwo, \vstwo$ via $\symaddexpr$ yields $(\ve, \vs)$. - \end{itemize} -\end{itemize} - -\subsection{Formally} -\begin{mathpar} -\inferrule[empty]{} -{ - \monomialstoexpr(\overname{\emptylist}{\monoms}) \typearrow (\overname{\ELiteral(\lint(0))}{\ve}, \overname{0}{\vs}) -} -\and -\inferrule[non\_empty]{ - \unitarymonomialstoexpr(\vm) \typearrow \veonep\\ - \monomialtoexpr(\veonep, q) \typearrow (\veone,\vsone)\\ - \monomialstoexpr(\monoms) \typearrow (\vetwo, \vstwo)\\ - \symaddexpr(\veone, \vsone, \vetwo, \vstwo) \typearrow (\ve, \vs) -}{ - \monomialstoexpr(\overname{[(\vm,q)] \concat \monomsone}{\monoms}) \typearrow (\ve, \vs) -} -\end{mathpar} - -\section{TypingRule.MonomialToExpr \label{sec:TypingRule.MonomialToExpr}} -\hypertarget{def-monomialtoexpr}{} -The function -\[ -\monomialtoexpr(\overname{\expr}{\ve} \aslsep \overname{\Q}{q}) -\aslto (\overname{\expr}{\newe} \times \overname{\{-1,0,1\}}{\vs}) -\] -transforms an expression $\ve$ and rational $q$ into the expression $\newe$, -which represents the absolute value of $\ve$ multiplied by $q$, and the sign of $q$ as $\vs$. - -\subsection{Prose} -One of the following applies: -\begin{itemize} - \item All of the following apply (\textsc{q\_zero}): - \begin{itemize} - \item $q$ is $0$; - \item $\newe$ is the literal expression for $0$; - \item $\vs$ is $0$. - \end{itemize} - - \item All of the following apply (\textsc{q\_natural}): - \begin{itemize} - \item $q$ a strictly positive; - \item symbolically multiplying the literal expression for $q$ and $\ve$ via $\symmulexpr$ yields $\newe$; - \item $\vs$ is $1$. - \end{itemize} - - \item All of the following apply (\textsc{q\_positive\_fraction}): - \begin{itemize} - \item $q$ a strictly positive fraction, that is, not an integer; - \item the reduced representation of the fraction $q$ is $\frac{d}{n}$; - \item symbolically multiplying the literal expression for $q$ and $\ve$ via $\symmulexpr$ yields $\vetwo$; - \item $\ve$ is the binary expression with operator $\DIV$ and operands $\vetwo$ and the literal expression for $n$; - \item $\vs$ is $1$. - \end{itemize} - - \item All of the following apply (\textsc{q\_negative}): - \begin{itemize} - \item $q$ a strictly negative; - \item transforming $\ve$ with $-q$ to an expression and a sign via $\monomialtoexpr$ yields $(\newe, 1)$; - \item $\vs$ is $-1$. - \end{itemize} -\end{itemize} - -\subsection{Formally} -\begin{mathpar} -\inferrule[q\_zero]{ - q = 0\\ -}{ - \monomialtoexpr(\ve, q) \typearrow (\overname{\ELiteral(\lint(0))}{\newe}, \overname{0}{\vs}) -} -\and -\inferrule[q\_natural]{ - q > 0\\ - q \in \N\\ - \symmulexpr(\ELiteral(\lint(q)), \ve) \typearrow \newe -}{ - \monomialtoexpr(\ve, q) \typearrow (\newe, \overname{1}{\vs}) -} -\and -\inferrule[q\_positive\_fraction]{ - q > 0\\ - q \not\in \N\\\\ - q \eqname \frac{d}{n} \;\;\;\;\text{ is the reduced fraction for }q\\\\ - \symmulexpr(\ELiteral(\lint(d)), \ve) \typearrow \vetwo\\ - \newe \eqdef \EBinop(\DIV, \vetwo, \ELiteral(\lint(n))) -}{ - \monomialtoexpr(\ve, q) \typearrow (\newe, \overname{1}{\vs}) -} -\and -\inferrule[q\_negative]{ - q < 0\\ - \monomialtoexpr(\ve, -q) \typearrow (\newe, 1) -}{ - \monomialtoexpr(\ve, q) \typearrow (\newe, \overname{-1}{\vs}) -} -\end{mathpar} - -\section{TypingRule.SymAddExpr \label{sec:TypingRule.SymAddExpr}} -\hypertarget{def-symaddexpr}{} -The function -\[ -\symaddexpr( - \overname{\expr}{\veone} \aslsep - \overname{\{-1,0,1\}}{\vsone} \aslsep - \overname{\expr}{\vetwo} \aslsep - \overname{\{-1,0,1\}}{\vstwo} - ) - \typearrow (\overname{\expr}{\ve}, \overname{\{-1,0,1\}}{\vs}) -\] -symbolically sums the expressions $\veone$ and $\vetwo$ -with respective signs $\vsone$ and $\vstwo$ -yielding the expression $\ve$ and sign $\vs$. - -The effect of the function can be summarized by the following table: -\begin{center} -\begin{tabular}{|c|c|c|c|} -\hline -& \multicolumn{3}{c|}{$\vsone$}\\ -\hline -$\vstwo$ & -1 & 0 & 1\\ -\hline --1 & $(\veone+\vetwo, \vsone)$ & (\vetwo,\vstwo) & $(\veone-\vetwo, \vsone)$ \\ -\hline - 0 & $(\veone, \vsone)$ & (\veone,\vsone) & $(\veone, \vsone)$ \\ - \hline - 1 & $(\veone-\vetwo, \vsone)$ & (\vetwo,\vstwo) & $(\veone+\vetwo, \vsone)$ \\ -\hline -\end{tabular} -\end{center} - -\subsection{Prose} -One of the following applies: -\begin{itemize} - \item All of the following apply (\textsc{zero}): - \begin{itemize} - \item either $\vsone$ is $0$ or $\vstwo$ is $0$; - \item the result is $(\vetwo, \vstwo)$ if $\vsone$ is $0$ and $(\veone, \vsone)$, otherwise. - \end{itemize} - - \item All of the following apply (\textsc{same\_sign}): - \begin{itemize} - \item both $\vsone$ and $\vstwo$ are not $0$; - \item $\vsone$ is equal to $\vstwo$; - \item $\ve$ is the binary expression with operator $\PLUS$ and operands $\veone$ and $\vetwo$, - that is, $\EBinop(\PLUS, \veone, \vetwo)$; - \item $\vs$ is $\vsone$; - \end{itemize} - - \item All of the following apply (\textsc{same\_sign}): - \begin{itemize} - \item both $\vsone$ and $\vstwo$ are not $0$; - \item $\vsone$ is different from $\vstwo$; - \item $\ve$ is the binary expression with operator $\MINUS$ and operands $\veone$ and $\vetwo$, - that is, $\EBinop(\MINUS, \veone, \vetwo)$; - \item $\vs$ is $\vsone$; - \end{itemize} -\end{itemize} - -\subsection{Formally} -\begin{mathpar} -\inferrule[zero]{ - (\vsone = 0 \lor \vstwo = 0)\\ - (\ve, \vs) \eqdef \choice{\vsone = 0}{(\vetwo, \vstwo)}{(\veone, \vsone)} -}{ - \symaddexpr(\veone, \vsone, \vetwo, \vstwo) \typearrow (\ve, \vs) -} -\and -\inferrule[same\_sign]{ - \vsone \neq 0 \land \vstwo \neq 0\\ - \vsone = \vstwo -}{ - \symaddexpr(\veone, \vetwo) \typearrow (\overname{\EBinop(\PLUS, \veone, \vetwo)}{\ve}, \overname{\vsone}{\vs}) -} -\and -\inferrule[different\_signs]{ - \vsone \neq 0 \land \vstwo \neq 0\\ - \vsone \neq \vstwo -}{ - \symaddexpr(\veone, \vetwo) \typearrow (\overname{\EBinop(\MINUS, \veone, \vetwo)}{\ve}, \overname{\vsone}{\vs}) -} -\end{mathpar} - -\section{TypingRule.UnitaryMonomialsToExpr \label{sec:TypingRule.UnitaryMonomialsToExpr}} -\hypertarget{def-unitarymonomialstoexpr}{} -The function -\[ -\unitarymonomialstoexpr(\overname{(\identifier\times\N)^*}{\monoms}) \aslto \overname{\expr}{\ve} -\] -transforms a list of single-variable unitary monomials $\monoms$ into an expression $\ve$. -Intuitively, $\monoms$ represented a multiplication of the single-variable unitary monomials. - -\subsection{Prose} -One of the following applies: -\begin{itemize} - \item All of the following apply (\textsc{empty}): - \begin{itemize} - \item $\monoms$ is the empty list; - \item $\ve$ is the literal expression for $1$. - \end{itemize} - - \item All of the following apply (\textsc{exp\_zero}): - \begin{itemize} - \item $\monoms$ is a list where the first element is $(\vv, 0)$ and its tail is $\monoms$; - \item transforming $\monomsone$ to an expression yields $\ve$. - \end{itemize} - - \item All of the following apply (\textsc{exp\_one}): - \begin{itemize} - \item $\monoms$ is a list where the first element is $(\vv, 1)$ and its tail is $\monoms$; - \item $\veone$ is the variable expression for $\vv$; - \item transforming $\monomsone$ to an expression yields $\vetwo$; - \item symbolically multiplying $\veone$ and $\vetwo$ via $\symmulexpr$ yields $\ve$. - \end{itemize} - - \item All of the following apply (\textsc{exp\_two}): - \begin{itemize} - \item $\monoms$ is a list where the first element is $(\vv, 2)$ and its tail is $\monoms$; - \item $\veone$ is the binary expression with operator $\MUL$ and operands $\EVar(\vv)$ and $\EVar(\vv)$ - (that is, $\vv$ squared); - \item transforming $\monomsone$ to an expression yields $\vetwo$; - \item symbolically multiplying $\veone$ and $\vetwo$ via $\symmulexpr$ yields $\ve$. - \end{itemize} - - \item All of the following apply (\textsc{exp\_gt\_two}): - \begin{itemize} - \item $\monoms$ is a list where the first element is $(\vv, n)$ and its tail is $\monoms$; - \item $n$ is greater than $1$; - \item $\veone$ is the binary expression with operator $\POW$ and base operand being the variable expression for $\vv$ - and the exponent operand being the variable expression for $n$; - \item transforming $\monomsone$ to an expression yields $\vetwo$; - \item symbolically multiplying $\veone$ and $\vetwo$ via $\symmulexpr$ yields $\ve$. - \end{itemize} -\end{itemize} - -\subsection{Formally} -\begin{mathpar} -\inferrule[empty]{} -{ - \unitarymonomialstoexpr(\overname{\emptylist}{\monoms}) \typearrow \overname{\ELiteral(\lint(1))}{\ve} -} -\end{mathpar} - -\begin{mathpar} -\inferrule[exp\_zero]{ - \unitarymonomialstoexpr(\monomsone) \typearrow \ve -}{ - \unitarymonomialstoexpr(\overname{[(\vv, 0)] \concat \monomsone}{\monoms}) \typearrow \ve -} -\end{mathpar} - -\begin{mathpar} -\inferrule[exp\_one]{ - \veone \eqdef \EVar(\vv)\\ - \unitarymonomialstoexpr(\monomsone) \typearrow \vetwo\\ - \symmulexpr(\veone, \vetwo) \typearrow \ve -}{ - \unitarymonomialstoexpr(\overname{[(\vv, 1)] \concat \monomsone}{\monoms}) \typearrow \ve -} -\end{mathpar} - -\begin{mathpar} -\inferrule[exp\_two]{ - \veone \eqdef \AbbrevEBinop{\MUL}{\EVar(\vv)}{\EVar(\vv)}\\ - \unitarymonomialstoexpr(\monomsone) \typearrow \vetwo\\ - \symmulexpr(\veone, \vetwo) \typearrow \ve -}{ - \unitarymonomialstoexpr(\overname{[(\vv, 2)] \concat \monomsone}{\monoms}) \typearrow \ve -} -\end{mathpar} - -\begin{mathpar} -\inferrule[exp\_gt\_two]{ - n \geq 2\\ - \veone \eqdef \AbbrevEBinop{\POW}{\EVar(\vv)}{\ELiteral(n)}\\ - \unitarymonomialstoexpr(\monomsone) \typearrow \vetwo\\ - \symmulexpr(\veone, \vetwo) \typearrow \ve -}{ - \unitarymonomialstoexpr(\overname{[(\vv, n)] \concat \monomsone}{\monoms}) \typearrow \ve -} -\end{mathpar} - -\section{TypingRule.SymMulExpr \label{sec:TypingRule.SymMulExpr}} -\hypertarget{def-symmulexpr}{} -The function -$ -\symmulexpr(\overname{\expr}{\veone} \aslsep \overname{\expr}{\vetwo}) \typearrow \overname{\expr}{\ve} -$ -produces an expression representing the multiplication of expressions $\veone$ and $\vetwo$, -simplifying away the case where one of the operands is the literal one. - -\subsection{Prose} -One of the following applies: -\begin{itemize} - \item All of the following apply (\textsc{one\_operand}): - \begin{itemize} - \item either $\veone$ or $\vetwo$ is the literal expression for $1$; - \item $\ve$ is $\vetwo$ if $\veone$ is the literal expression for $1$ and $\veone$, otherwise. - \end{itemize} -\end{itemize} - -\subsection{Formally} -\begin{mathpar} -\inferrule[one\_operand]{ - (\veone = \ELiteral(\lint(1)) \lor \vetwo = \ELiteral(\lint(1)))\\ - \ve \eqdef \choice{\veone = \ELiteral(\lint(1))}{\vetwo}{\veone} -}{ - \symmulexpr(\EBinop(\MUL, \veone, \vetwo)) \typearrow \ve -} -\and -\inferrule[no\_one\_operand]{ - (\veone \neq \ELiteral(\lint(1)) \land \vetwo \neq \ELiteral(\lint(1)))\\ - \ve \eqdef \EBinop(\MUL, \veone, \vetwo) -}{ - \symmulexpr(\EBinop(\MUL, \veone, \vetwo)) \typearrow \ve -} -\end{mathpar} - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -\chapter{Utility Rules} -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - -\section{Checked Transitions} -\hypertarget{def-checktrans}{} -We define the following rules to allow us asserting that a condition holds, -returning a type error otherwise: -\begin{mathpar} - \inferrule[check\_trans\_true]{}{ \checktrans{\True}{} \checktransarrow \True } - \and - \inferrule[check\_trans\_false]{}{ \checktrans{\False}{} \checktransarrow \TypeErrorVal{\texttt{}} } -\end{mathpar} - -\hypertarget{def-pairstomap}{} -\section{Converting a List of Pairs to a Map \label{sec:PairsToMap}} -The parametric function -\[ - \pairstomap(\overname{(\identifier\times T)^*}{\pairs}) \aslto \overname{(\identifier\partialto T)}{f} \cup \TTypeError -\] -converts a list of pairs --- $\pairs$ --- where each pair consists of an identifier and a value -of type $T$ into a function mapping each identifier to its respective value in the list. -If a duplicate identifier exists in $\pairs$ then a type error is returned. - -\subsection{Prose} -One of the following applies: -\begin{itemize} - \item All of the following apply (\textsc{empty}): - \begin{itemize} - \item $\pairs$ is empty; - \item $f$ is the empty function. - \end{itemize} - - \item All of the following apply (\textsc{error}): - \begin{itemize} - \item there exist two different positions in the list where the identifier is the same; - \item the result is a type error indicating the existence of a duplicate identifier. - \end{itemize} - - \item All of the following apply (\textsc{okay}): - \begin{itemize} - \item all identifiers occurring in the list are unique; - \item $f$ is a function that associates to each identifier the value appearing with it in $\pairs$. - \end{itemize} -\end{itemize} - -\begin{mathpar} -\inferrule[empty]{}{ \pairstomap(\emptylist) \typearrow \emptyfunc } -\and -\inferrule[error]{ - i,j \in 1..k\\ - i \neq j\\ - \id_i = \id_j -} -{ - \pairstomap([i=1..k: (\id_i,t_i)]) \typearrow \TypeErrorVal{DuplicateIdentifier} -} -\and -\inferrule[okay]{ - \forall i,j \in 1..k. \id_i \neq \id_j\\ - { - f \eqdef \lambda \id.\ \begin{cases} - t_i & \text{ if }i\in1..k \land \id = \id_i\\ - \bot & \text{ otherwise} - \end{cases} - } -} -{ - \pairstomap([i=1..k: (\id_i,t_i)]) \typearrow f -} -\end{mathpar} - -\hypertarget{def-checknoduplicates}{} -\section{TypingRule.CheckNoDuplicates \label{sec:TypingRule.CheckNoDuplicates}} -The function -\[ - \checknoduplicates(\overname{\identifier^*}{\id_{1..k}}) \aslto \{\True\} \cup \TTypeError -\] -checks whether a non-empty list of identifiers contains a duplicate identifier. If it does not, the result -is $\True$ and otherwise the result is a type error. - -\subsection{Prose} -One of the following applies: -\begin{itemize} - \item All of the following apply (\textsc{okay}): - \begin{itemize} - \item the set containing all identifiers in the list has the same cardinality as the length of the list; - \item the result is $\True$. - \end{itemize} - - \item All of the following apply (\textsc{error}): - \begin{itemize} - \item there exist two different positions in the list where the identifier is the same; - \item the result is a type error indicating the existence of a duplicate identifier. - \end{itemize} -\end{itemize} - -\begin{mathpar} - \inferrule[okay]{ - \cardinality{\{\id_{1..k}\}} = k - } - { - \checknoduplicates(\id_{1..k}) \typearrow \True - } -\and -\inferrule[error]{ - i,j \in 1..k\\ - i \neq j\\ - \id_i = \id_j -} -{ - \checknoduplicates(\id_{1..k}) \typearrow \TypeErrorVal{DuplicateIdentifier} -} -\end{mathpar} - -\hypertarget{def-annotatefieldinit}{} -\section{Annotating Field Initializers} -The function -\[ - \annotatefieldinit( - \overname{\staticenvs}{\tenv} \aslsep - \overname{(\identifier\times\expr)}{(\name, \vep)} \aslsep - \overname{\field^*}{\fieldtypes} - ) \aslto - \overname{(\identifier\times\expr)}{(\name, \vepp)} -\] -annotates a field initializers $(\name, \vep)$ in a record expression -with list of fields \\ $\fieldtypes$ and returns the annotated field initializer -$(\name, \vepp)$. \ProseOtherwiseTypeError - -\subsection{Prose} -All of the following apply: -\begin{itemize} - \item annotating the expression $\vep$ in $\tenv$ yields $(\vtp, \vepp)$\ProseOrTypeError; - \item One of the following applies: - \begin{itemize} - \item All of the following apply (\textsc{okay}): - \begin{itemize} - \item the unique type associated with $\name$ in $\fieldtypes$ is $\tspecp$; - \item determining whether $\vtp$ \typesatisfies\ $\tspecp$ in $\tenv$ yields $\True$\ProseOrTypeError; - \end{itemize} - - \item All of the following apply (\textsc{error}): - \begin{itemize} - \item there is no type associated with $\name$ in $\fieldtypes$; - \item the result is a type error indicating that the field $\name$ does not exist. - \end{itemize} - \end{itemize} -\end{itemize} - -\subsection{Formally} -\begin{mathpar} -\inferrule[okay]{ - \annotateexpr{\tenv, \vep} \typearrow (\vtp, \vepp) \OrTypeError\\\\ - \fieldtype(\fieldtypes, \name) = \tspecp\\ - \checktypesat(\tenv, \vtp, \tspecp) \typearrow \True \OrTypeError -}{ - \annotatefieldinit(\tenv, (\name, \vep), \fieldtypes) \typearrow (\name, \vepp) -} -\and -\inferrule[error]{ - \annotateexpr{\tenv, \vep} \typearrow (\vtp, \vepp) \OrTypeError\\\\ - \fieldtype(\fieldtypes, \name) = \bot -}{ - \annotatefieldinit(\tenv, (\name, \vep), \fieldtypes) \typearrow \\ - \TypeErrorVal{FieldDoesNotExist} -} -\end{mathpar} - -\section{TypingRule.BitFieldGetName \label{sec:TypingRule.BitFieldGetName}} -\hypertarget{def-bitfieldgetname}{} -The function -\[ - \bitfieldgetname : \overname{\bitfield}{\vbf} \aslto \overname{\identifier}{\name} -\] -returns the name of a bitfield --- $\name$, given a bitfield $\vbf$. - -\subsection{Prose} -One of the following applies: -\begin{itemize} - \item $\vb$ is a simple bitfield with name $\name$, that is, $\BitFieldSimple(\name, \Ignore)$; - \item $\vb$ is a nested bitfield with name $\name$, that is, $\BitFieldNested(\name, \Ignore, \Ignore)$; - \item $\vb$ is a typed bitfield with name $\name$, that is, $\BitFieldType(\name, \Ignore, \Ignore)$. -\end{itemize} - -\subsection{Formally} -\begin{mathpar} - \inferrule[simple]{}{ - \bitfieldgetname(\BitFieldSimple(\name, \Ignore)) \typearrow \name - } - \and - \inferrule[nested]{}{ - \bitfieldgetname(\BitFieldNested(\name, \Ignore, \Ignore)) \typearrow \name - } - \and - \inferrule[type]{}{ - \bitfieldgetname(\BitFieldType(\name, \Ignore, \Ignore)) \typearrow \name - } -\end{mathpar} - -\section{TypingRule.CheckVarNotInGEnv} -\hypertarget{def-checkvarnotingenv}{} -The function -\[ - \checkvarnotingenv{\overname{\staticenvs}{\tenv} \aslsep \overname{\Strings}{\id}} - \aslto \{\True\} \cup \overname{\TTypeError}{\TypeErrorConfig} -\] -checks whether $\id$ is already declared in the global environment of $\tenv$. -If it is, the result is a type error, and otherwise the result is $\True$. - -\subsection{Prose} -All of the following apply: -\begin{itemize} - \item $\vb$ is $\True$ if and only if one of the following applies: - \begin{itemize} - \item $\id$ is declared as a global identifier in $\tenv$; - \item $\id$ is declared as a subprogram in $\tenv$; - \item $\id$ is declared as a type in $\tenv$. - \end{itemize} - - \item checking whether $\vb$ is $\False$ yields $\True$ or a type error indicating - that $\id$ has already been declared, thereby short-circuiting the rule. -\end{itemize} - -\subsection{Formally} -\begin{mathpar} -\inferrule{ -{ - \begin{array}{rl} - \vb \eqdef & G^\tenv.\globalstoragetypes(\id) \neq \bot \lor\\ - & G^\tenv.\subprograms(\id) \neq \bot\ \lor\\ - & G^\tenv.\declaredtypes(\id) \neq \bot - \end{array} -}\\ -\checktrans{\neg\vb}{IdentifierAlreadyDeclared} \checktransarrow \True \OrTypeError -}{ - \checkvarnotingenv{\tenv, \id} \typearrow \True -} -\end{mathpar} - -\hypertarget{def-checkvarnotinenv}{} -\hypertarget{def-varinenv}{} -\section{TypingRule.CheckVarNotInEnv} -The function -\[ - \varinenv{\overname{\staticenvs}{\tenv} \aslsep \overname{\identifier}{\id}} - \aslto \overname{\Bool}{\vb} -\] -determines whether an identifier $\id$ is declared in the static environment $\tenv$. - -The function -\[ - \checkvarnotinenv{\overname{\staticenvs}{\tenv} \aslsep \overname{\Strings}{\id}} - \aslto \{\True\} \cup \TTypeError -\] -checks whether $\id$ is already declared in $\tenv$. If it is, the result is a type error, -and otherwise the result is $\True$. - -\subsection{Prose} -$\varinenv{\tenv, \id}$ is true if and only if one of the following applies: -\begin{itemize} - \item $\id$ is declared as a local identifier in $\tenv$; - \item $\id$ is declared as a global identifier in $\tenv$; - \item $\id$ is declared as a subprogram in $\tenv$; - \item $\id$ is declared as a type in $\tenv$. -\end{itemize} - -\subsection{Formally} -\begin{mathpar} -\inferrule{ - { - \begin{array}{rl} - \vb \eqdef & L^\tenv.\localstoragetypes(\id) \neq \bot\ \lor\\ - & G^\tenv.\globalstoragetypes(\id) \neq \bot \lor\\ - & G^\tenv.\subprograms(\id) \neq \bot\ \lor\\ - & G^\tenv.\declaredtypes(\id) \neq \bot - \end{array} -} -}{ - \varinenv{\tenv, \id} \typearrow \vb -} -\end{mathpar} - -\begin{mathpar} -\inferrule[okay]{ - \varinenv{\tenv, \id} \typearrow \False -}{ - \checkvarnotinenv{\tenv, \id} \typearrow \True -} -\and - \inferrule[error]{ - \varinenv{\tenv, \id} \typearrow \True -}{ - \checkvarnotinenv{\tenv, \id} \typearrow \TypeErrorVal{AlreadyDeclared} -} -\end{mathpar} - -\hypertarget{def-addlocal}{} -\section{TypingRule.AddLocal \label{sec:TypingRule.AddLocal}} -The function -\[ - \addlocal( - \overname{\staticenvs}{\tenv} \aslsep - \overname{\identifier}{\id} \aslsep - \overname{\ty}{\tty} \aslsep - \overname{\localdeclkeyword}{\ldk}) - \aslto - \overname{\staticenvs}{\newtenv} -\] -adds the identifier $\id$ as a local storage element with type $\tty$ and local declaration keyword $\ldk$ -to the local environment of $\tenv$, resulting in the static environment $\newtenv$. - -\subsection{Prose} -All of the following apply: -\begin{itemize} - \item the map $\newlocalstoragetypes$ is defined by updating the map \\ - $\localstoragetypes$ of $\tenv$ - with the binding $\id$ to the type $\tty$ and local declaration keyword $\ldk$, that is, $(\tty,\ldk)$; - \item $\newtenv$ is defined by updating the local environment with the binding of \\ - $\localstoragetypes$ to $\newlocalstoragetypes$. -\end{itemize} - -\subsection{Formally} -\begin{mathpar} -\inferrule{ - \newlocalstoragetypes \eqdef L^\tenv.\localstoragetypes[\id \mapsto (\tty, \ldk)]\\ - \newtenv \eqdef (G^\tenv, L^\tenv[\localstoragetypes \mapsto \newlocalstoragetypes]) -} -{ - \addlocal(\tenv, \id, \tty, \ldk) \typearrow \newtenv -} -\end{mathpar} - -\hypertarget{def-declaredtype}{} -\section{TypingRule.DeclaredType \label{sec:TypingRule.DeclaredType}} - -The function -\[ - \declaredtype(\overname{\staticenvs}{\tenv} \aslsep \overname{\identifier}{\id}) \aslto \overname{\ty}{\vt} \cup \TTypeError -\] -retrieves the type associated with the identifier $\id$ in the static environment $\tenv$. -If the identifier is not associated with a declared type, a type error is returned. - -\subsection{Prose} -One of the following applies: -\begin{itemize} - \item All of the following apply (\textsc{exists}): - \begin{itemize} - \item $\id$ is bound in the global environment to the type $\vt$. - \end{itemize} - - \item All of the following apply (\textsc{type\_not\_declared}): - \begin{itemize} - \item $\id$ is not bound in the global environment to any type; - \item the result is a type error indicating the lack of a type declaration for $\id$. - \end{itemize} -\end{itemize} - -\subsection{Formally} -\begin{mathpar} -\inferrule[exists]{ - G^\tenv.\declaredtypes(\id) = \vt -} -{ - \declaredtype(\tenv, \id) \typearrow \vt -} -\and -\inferrule[type\_not\_declared]{ - G^\tenv.\declaredtypes(\id) = \bot -} -{ - \declaredtype(\tenv, \id) \typearrow \TypeErrorVal{TypeNotDeclared} -} -\end{mathpar} - -\section{TypingRule.FindBitfieldOpt} -\hypertarget{def-findbitfieldopt}{} -The function -\[ - \findbitfieldopt(\overname{\identifier}{\name} \aslsep \overname{\bitfield^*}{\bitfields}) - \aslto \overname{\langle\bitfield\rangle}{\vr} -\] -returns the bitfield associated with the name $\name$ in the list of bitfields $\bitfields$, -if there is one. Otherwise, the result is $\None$. - -\subsection{Prose} -One of the following applies: -\begin{itemize} - \item All of the following apply (\textsc{match}): - \begin{itemize} - \item $\bitfields$ starts with a bitfield $\vbf$; - \item obtaining the name associated with $\vbf$ yields $\name$; - \item the result if $\vbf$. - \end{itemize} - - \item All of the following apply (\textsc{tail}): - \begin{itemize} - \item $\bitfields$ starts with a bitfield $\vbf$ and continues with the tail list $\bitfieldsp$; - \item obtaining the name associated with $\vbf$ yields $\namep$, which is different than $\name$; - \item finding the bitfield associated with $\name$ in $\bitfieldsp$ yields the result $\vr$. - \end{itemize} - - \item All of the following apply (\textsc{empty}): - \begin{itemize} - \item $\bitfields$ is an empty list; - \item the result is $\None$. - \end{itemize} -\end{itemize} - -\begin{mathpar} -\inferrule[match]{ - \bitfieldgetname(\vbf) \typearrow \name -}{ - \findbitfieldopt(\name, \overname{\vbf \concat \bitfieldsp}{\bitfields}) \typearrow \overname{\langle\vbf\rangle}{\vr} -} -\and -\inferrule[tail]{ - \bitfieldgetname(\vbf) \typearrow \namep\\ - \name \neq \namep\\ - \findbitfieldopt(\name, \bitfieldsp) \typearrow \vr -}{ - \findbitfieldopt(\name, \overname{\vbf \concat \bitfieldsp}{\bitfields}) \typearrow \vr -} -\and -\inferrule[empty]{}{ - \findbitfieldopt(\name, \overname{\emptylist}{\bitfields}) \typearrow \None -} -\end{mathpar} - -\section{TypingRule.MemBfs} -\hypertarget{def-membfs}{} -The function -\[ - \membfs(\overname{\staticenvs}{\tenv} \aslsep \overname{\bitfield^+}{\bfstwo} \aslsep \overname{\bitfield}{\vbfone}) - \aslto \overname{\Bool}{\vb} -\] -checks whether the bitfield $\vbf$ exists in $\bfstwo$ in the context of $\tenv$, returning the result in $\vb$. - -\subsection{Prose} -One of the following applies: -\begin{itemize} - \item All of the following apply (\textsc{none}): - \begin{itemize} - \item the name associated with the bitfield $\vbfone$ is $\name$; - \item finding the bitfield associated with $\name$ in $\bfstwo$ yields $\None$; - \item $\vb$ is $\False$. - \end{itemize} - - \item All of the following apply (\textsc{simple\_any}): - \begin{itemize} - \item the name associated with the bitfield $\vbfone$ is $\name$; - \item finding the bitfield associated with $\name$ in $\bfstwo$ yields $\vbftwo$; - \item $\vbftwo$ is a simple bitfield; - \item symbolically checking whether $\vbfone$ is equivalent to $\vbftwo$ in $\tenv$ yields $\vb$. - \end{itemize} - - \item All of the following apply (\textsc{nested\_simple}): - \begin{itemize} - \item the name associated with the bitfield $\vbfone$ is $\name$; - \item finding the bitfield associated with $\name$ in $\bfstwo$ yields $\vbftwo$; - \item $\vbftwo$ is a nested bitfield with name $\nametwo$, slices $\slicestwo$, and bitfields $\bfstwop$; - \item $\vbfone$ is a simple bitfield; - \item symbolically checking whether $\vbfone$ is equivalent to $\vbftwo$ in $\tenv$ yields $\vb$. - \end{itemize} - - \item All of the following apply (\textsc{nested\_nested}): - \begin{itemize} - \item the name associated with the bitfield $\vbfone$ is $\name$; - \item finding the bitfield associated with $\name$ in $\bfstwo$ yields $\vbftwo$; - \item $\vbftwo$ is a nested bitfield with name $\nametwo$, slices $\slicestwo$, and bitfields $\bfstwop$; - \item $\vbfone$ is a nested bitfield with name $\nameone$, slices $\sliceone$, and $\bfsone$; - \item $\vbone$ is true if and only if $\nameone$ is equal to $\nametwo$; - \item symbolically equating the slices $\slicesone$ and $\slicestwo$ in $\tenv$ yields $\vbtwo$; - \item checking $\bfsone$ is included in $\bfstwop$ in the context of $\tenv$ yields $\vbthree$; - \item $\vb$ is defined as the conjunction of $\vbone$, $\vbtwo$, and $\vbthree$. - \end{itemize} - - \item All of the following apply (\textsc{nested\_typed}): - \begin{itemize} - \item the name associated with the bitfield $\vbfone$ is $\name$; - \item finding the bitfield associated with $\name$ in $\bfstwo$ yields $\vbftwo$; - \item $\vbftwo$ is a nested bitfield with name $\nametwo$, slices $\slicestwo$, and bitfields $\bfstwop$; - \item $\vbfone$ is a typed bitfield; - \item $\vb$ is $\False$. - \end{itemize} - - \item All of the following apply (\textsc{typed\_simple}): - \begin{itemize} - \item the name associated with the bitfield $\vbfone$ is $\name$; - \item finding the bitfield associated with $\name$ in $\bfstwo$ yields $\vbftwo$; - \item $\vbftwo$ is a typed bitfield with name $\nametwo$, slices $\slicestwo$, and type $\ttytwo$; - \item $\vbfone$ is a simple bitfield; - \item symbolically checking whether $\vbfone$ is equivalent to $\vbftwo$ in $\tenv$ yields $\vb$. - \end{itemize} - - \item All of the following apply (\textsc{typed\_nested}): - \begin{itemize} - \item the name associated with the bitfield $\vbfone$ is $\name$; - \item finding the bitfield associated with $\name$ in $\bfstwo$ yields $\vbftwo$; - \item $\vbftwo$ is a typed bitfield with name $\nametwo$, slices $\slicestwo$, and type $\ttytwo$; - \item $\vbfone$ is a nested bitfield; - \item $\vb$ is $\False$. - \end{itemize} - - \item All of the following apply (\textsc{typed\_typed}): - \begin{itemize} - \item the name associated with the bitfield $\vbfone$ is $\name$; - \item finding the bitfield associated with $\name$ in $\bfstwo$ yields $\vbftwo$; - \item $\vbftwo$ is a typed bitfield with name $\nametwo$, slices $\slicestwo$, and type $\ttytwo$; - \item $\vbfone$ is a typed bitfield with name $\nameone$, slices $\slicesone$, and type $\ttyone$; - \item $\vbone$ is true if and only if $\nameone$ is equal to $\nametwo$; - \item symbolically equating the slices $\slicesone$ and $\slicestwo$ in $\tenv$ yields $\vbtwo$; - \item checking whether $\ttyone$ subtypes $\ttytwo$ in $\tenv$ yields $\vbthree$; - \item $\vb$ is defined as the conjunction of $\vbone$, $\vbtwo$, and $\vbthree$. - \end{itemize} -\end{itemize} - -\begin{mathpar} -\inferrule[none]{ - \bitfieldgetname(\vbfone) \typearrow \name\\ - \findbitfieldopt(\name, \bfstwo) \typearrow \None -}{ - \membfs(\tenv, \bfstwo, \vbfone) \typearrow \False -} -\and -\inferrule[simple\_any]{ - \bitfieldgetname(\vbf) \typearrow \name\\ - \findbitfieldopt(\name, \bfstwo) \typearrow \langle \vbftwo \rangle\\ - \astlabel(\vbftwo) = \BitFieldSimple\\ - \bitfieldsequal(\tenv, \vbfone, \vbftwo) \typearrow \vb -}{ - \membfs(\tenv, \bfstwo, \vbfone) \typearrow \vb -} -\end{mathpar} - -\begin{mathpar} -\inferrule[nested\_simple]{ - \bitfieldgetname(\vbf) \typearrow \name\\ - \findbitfieldopt(\name, \bfstwo) \typearrow \langle \vbftwo \rangle\\ - \vbftwo = \BitFieldNested(\nametwo, \slicestwo, \bfstwop)\\ - \vbfone = \BitFieldSimple(\Ignore)\\ - \bitfieldsequal(\tenv, \vbfone, \vbftwo) \typearrow \vb -}{ - \membfs(\tenv, \bfstwo, \vbfone) \typearrow \overname{\False}{\vb} -} -\and -\inferrule[nested\_nested]{ - \bitfieldgetname(\vbf) \typearrow \name\\ - \findbitfieldopt(\name, \bfstwo) \typearrow \langle \vbftwo \rangle\\ - \vbftwo = \BitFieldNested(\nametwo, \slicestwo, \bfstwop)\\ - \vbfone = \BitFieldNested(\nameone, \slicesone, \bfsone)\\ - \vbone \eqdef \nameone = \nametwo\\ - \slicesequal(\tenv, \slicesone, \slicestwo) \typearrow \vbtwo\\ - \bitfieldsincluded(\tenv, \bfsone, \bfstwop) \typearrow \vbthree\\ - \vb \eqdef \vbone \land \vbtwo \land \vbthree -}{ - \membfs(\tenv, \bfstwo, \vbfone) \typearrow \vb -} -\and -\inferrule[nested\_typed]{ - \bitfieldgetname(\vbf) \typearrow \name\\ - \findbitfieldopt(\name, \bfstwo) \typearrow \langle \vbftwo \rangle\\ - \vbftwo = \BitFieldNested(\nametwo, \slicestwo, \bfstwop)\\ - \astlabel(\vbfone) = \BitFieldType -}{ - \membfs(\tenv, \bfstwo, \vbfone) \typearrow \overname{\False}{\vb} -} -\end{mathpar} - -\begin{mathpar} -\inferrule[typed\_simple]{ - \bitfieldgetname(\vbf) \typearrow \name\\ - \findbitfieldopt(\name, \bfstwo) \typearrow \langle \vbftwo \rangle\\ - \vbftwo = \BitFieldType(\nametwo, \slicestwo, \ttytwo)\\ - \vbfone = \BitFieldSimple(\Ignore)\\ - \bitfieldsequal(\tenv, \vbfone, \vbftwo) \typearrow \vb -}{ - \membfs(\tenv, \bfstwo, \vbfone) \typearrow \vb -} -\and -\inferrule[typed\_nested]{ - \bitfieldgetname(\vbf) \typearrow \name\\ - \findbitfieldopt(\name, \bfstwo) \typearrow \langle \vbftwo \rangle\\ - \vbftwo = \BitFieldType(\nametwo, \slicestwo, \ttytwo)\\ - \astlabel(\vbfone) = \BitFieldNested -}{ - \membfs(\tenv, \bfstwo, \vbfone) \typearrow \overname{\False}{\vb} -} -\and -\inferrule[typed\_typed]{ - \bitfieldgetname(\vbf) \typearrow \name\\ - \findbitfieldopt(\name, \bfstwo) \typearrow \langle \vbftwo \rangle\\ - \vbftwo = \BitFieldType(\nametwo, \slicestwo, \ttytwo)\\ - \vbfone = \BitFieldType(\nameone, \slicesone, \ttyone)\\ - \vbone \eqdef \nameone = \nametwo\\ - \slicesequal(\tenv, \slicesone, \slicestwo) \typearrow \vbtwo\\ - \subtypesat(\tenv, \ttyone, \ttytwo) \typearrow \vbthree \OrTypeError\\\\ - \vb \eqdef \vbone \land \vbtwo \land \vbthree -}{ - \membfs(\tenv, \bfstwo, \vbfone) \typearrow \vb -} -\end{mathpar} - -\section{TypingRule.BitFieldsIncluded} -\hypertarget{def-bitfieldsincluded}{} -The predicate -\[ - \bitfieldsincluded(\overname{\staticenvs}{\tenv}, \overname{\bitfield^*}{\bfsone} \aslsep \overname{\bitfield^*}{\bfstwo}) - \aslto \overname{\Bool}{\vb} \cup \overname{\TTypeError}{\TypeErrorConfig} -\] -tests whether the set of bit fields $\bfsone$ is included in the set of bit fields $\bfstwo$ in environment $\tenv$, -returning a type error, if one is detected. - -\subsection{Prose} -All of the following apply: -\begin{itemize} - \item checking whether each field $\vbf$ in $\bfsone$ exists in $\bfstwo$ via $\membfs$ yields $\vb_\vbf$\ProseOrTypeError; - \item the result --- $\vb$ --- is the conjunction of $\vb_\vbf$ for all bitfields $\vbf$ in $\bfsone$. -\end{itemize} - -\begin{mathpar} -\inferrule{ - \vbf \in \bfsone: \membfs(\bfstwo, \vbf) \typearrow \vb_\vbf \OrTypeError\\\\ - \vbf \eqdef \bigwedge_{\bf \in \bfsone} \vb_\vbf -}{ - \bitfieldsincluded(\tenv, \bfsone, \bfstwo) \typearrow \vb -} -\end{mathpar} - -\hypertarget{def-typeofarraylength}{} -\section{TypingRule.TypeOfArrayLength \label{sec:TypingRule.TypeOfArrayLength}} -The function -\[ - \typeofarraylength(\overname{\staticenvs}{\tenv} \aslsep \overname{\arrayindex}{\size}) \aslto - \overname{\ty}{\vt} -\] -returns the type for the array index $\size$ in the static environment $\tenv$. - -\subsection{Prose} -One of the following applies: -\begin{itemize} - \item All of the following apply (\textsc{enum}): - \begin{itemize} - \item $\size$ is an enumeration index over the enumeration $\vs$, that is, \\ $\ArrayLengthEnum(\vs, \Ignore)$; - \item $\vt$ is the named type for $\vs$, that is, $\TNamed(\vs)$. - \end{itemize} - - \item All of the following apply (\textsc{expr}): - \begin{itemize} - \item $\size$ is an expression index for $\ve$, that is, $\ArrayLengthExpr(\ve)$; - \item applying $\normalize$ to simplify the expression corresponding to $\ve - 1$ in $\tenv$ - yields the expression $\vm$; - \item $\vc$ is the range constraint for $0..\vm$, that is, $\ConstraintRange(\eliteral{0}, \vm)$; - \item $\vt$ is the well-constrained integer with the single constraint $\vc$. - \end{itemize} -\end{itemize} - -\CodeSubsection{\TypeOfArrayLengthBegin}{\TypeOfArrayLengthEnd}{../types.ml} -\subsection{Formally} -\begin{mathpar} -\inferrule[enum]{} -{ - \typeofarraylength(\tenv, \ArrayLengthEnum(\vs, \Ignore)) \typearrow \TNamed(\vs) -} -\and -\inferrule[expr]{ - \normalize(\tenv, \EBinop(\MINUS, \ve, \eliteral{1})) \typearrow \vm\\ - \vc \eqdef \ConstraintRange(\eliteral{0}, \vm) -}{ - \typeofarraylength(\tenv, \ArrayLengthExpr(\ve)) \typearrow \TInt(\wellconstrained([\vc])) -} -\end{mathpar} - -\hypertarget{def-checkstructureinteger}{} -\section{TypingRule.CheckStructureInteger \label{sec:TypingRule.CheckStructureInteger}} -The function -\[ - \checkstructureinteger(\overname{\staticenvs}{\tenv} \aslsep \overname{\ty}{\vt}) \aslto - \{\True\} \cup \TTypeError -\] -returns $\True$ is $\vt$ is has the \structure\ an integer type and a type error otherwise. - -\subsection{Prose} -One of the following applies: -\begin{itemize} - \item All of the following apply (\textsc{okay}): - \begin{itemize} - \item determining the \structure\ of $\vt$ yields $\vtp$\ProseOrTypeError; - \item $\vtp$ is an integer type; - \item the result is $\True$; - \end{itemize} - - \item All of the following apply (\textsc{error}): - \begin{itemize} - \item determining the \structure\ of $\vt$ yields $\vtp$\ProseOrTypeError; - \item $\vtp$ is not an integer type; - \item the result is a type error indicating that $\vt$ was expected to have the \structure\ of an integer. - \end{itemize} -\end{itemize} - -\CodeSubsection{\CheckStructureIntegerBegin}{\CheckStructureIntegerEnd}{../Typing.ml} - -\subsection{Formally} -\begin{mathpar} -\inferrule[okay]{ - \tstruct(\vt) \typearrow \vtp \OrTypeError\\\\ - \astlabel(\vtp) = \TInt -} -{ - \checkstructureinteger(\tenv, \vt) \typearrow \True -} -\and -\inferrule[error]{ - \tstruct(\vt) \typearrow \vtp\\ - \astlabel(\vtp) \neq \TInt -} -{ - \checkstructureinteger(\tenv, \vt) \typearrow \TypeErrorVal{ExpectedIntegerStructure} -} -\end{mathpar} - -\hypertarget{def-checkstructurelabel}{} -\section{TypingRule.CheckStructure \label{sec:TypingRule.CheckStructure}} -The function -\[ - \checkstructurelabel(\overname{\staticenvs}{\tenv} \aslsep \overname{\ty}{\vt} \aslsep \overname{\astlabels}{\vl}) \aslto - \{\True\} \cup \TTypeError -\] -returns $\True$ is $\vt$ is has the \structure\ a of type corresponding to the AST label $\vl$ and a type error otherwise. - -\subsection{Prose} -One of the following applies: -\begin{itemize} - \item All of the following apply (\textsc{okay}): - \begin{itemize} - \item determining the \structure\ of $\vt$ yields $\vtp$\ProseOrTypeError; - \item $\vtp$ has the label $\vl$; - \item the result is $\True$; - \end{itemize} - - \item All of the following apply (\textsc{error}): - \begin{itemize} - \item determining the \structure\ of $\vt$ yields $\vtp$\ProseOrTypeError; - \item $\vtp$ does not have the label $\vl$; - \item the result is a type error indicating that $\vt$ was expected to have the \structure\ of a type with the AST label $\vl$. - \end{itemize} -\end{itemize} - -\subsection{Formally} -\begin{mathpar} -\inferrule[okay]{ - \tstruct(\vt) \typearrow \vtp \OrTypeError\\\\ - \astlabel(\vtp) = \vl -} -{ - \checkstructurelabel(\tenv, \vt, \vl) \typearrow \True -} -\and -\inferrule[error]{ - \tstruct(\vt) \typearrow \vtp\\ - \astlabel(\vtp) \neq \vl -} -{ - \checkstructurelabel(\tenv, \vt, \vl) \typearrow \TypeErrorVal{UnexpectedTypeStructure} -} -\end{mathpar} - -\hypertarget{def-storageispure}{} -\section{TypingRule.StorageIsPure \label{sec:TypingRule.StorageIsPure}} -The function -\[ - \storageispure(\overname{\staticenvs}{\tenv} \aslsep \overname{\identifier}{\vs}) \aslto - \overname{\Bool}{\vb} \cup \TTypeError -\] -$\vb$ is true if and only if the identifier $\vs$ corresponds to a \pure\ storage element -in the static environment $\tenv$. - -\subsection{Prose} -One of the following applies: -\begin{itemize} - \item All of the following apply (\textsc{local}): - \begin{itemize} - \item $\vs$ is a locally declared storage element; - \item $\vb$ is true if and only if $\vs$ is declared as a constant or as an immutable variable (\texttt{let}). - \end{itemize} - - \item All of the following apply (\textsc{global}): - \begin{itemize} - \item $\vs$ is a globally declared storage element; - \item $\vb$ is true if and only if $\vs$ is declared as a constant, a configuration variable, or an immutable variable. - \end{itemize} - - \item All of the following apply (\textsc{error}): - \begin{itemize} - \item $\vs$ is not defined in the environment as a storage element; - \item the result is a type error indicating that $\vs$ is not defined as a storage element. - \end{itemize} -\end{itemize} - -\CodeSubsection{\StorageIsPureBegin}{\StorageIsPureEnd}{../Typing.ml} - -\subsection{Formally} -\begin{mathpar} -\inferrule[local]{ - L^\tenv.\localstoragetypes(\vs) = (\Ignore, \ldk)\\ - \vb \eqdef \ldk \in \{\LDKConstant, \LDKLet\} -} -{ - \storageispure(\tenv, \vs) \typearrow \vb -} -\and -\inferrule[global]{ - L^\tenv.\localstoragetypes(\vs) = \bot\\ - G^\tenv.\globalstoragetypes(\vs) = (\Ignore, \gdk)\\ - \vb \eqdef \gdk \in \{\GDKConstant, \GDKConfig, \GDKLet\} -} -{ - \storageispure(\tenv, \vs) \typearrow \vb -} -\and -\inferrule[error]{ - L^\tenv.\localstoragetypes(\vs) = \bot\\ - G^\tenv.\globalstoragetypes(\vs) = \bot -} -{ - \storageispure(\tenv, \vs) \typearrow \TypeErrorVal{UndefinedIdentifier} -} -\end{mathpar} - -\hypertarget{def-checkstaticallyevaluable}{} -\hypertarget{def-staticallyevaluable}{} -\section{TypingRule.CheckStaticallyEvaluable \label{sec:TypingRule.CheckStaticallyEvaluable}} -The function -\[ - \checkstaticallyevaluable(\overname{\staticenvs}{\tenv} \aslsep \overname{\expr}{\ve}) \aslto - \{\True\} \cup \TTypeError -\] -returns $\True$ if $\ve$ is a \staticallyevaluable\ expression in the static environment $\tenv$ and a type error otherwise. - -\subsection{Prose} -All of the following applies: -\begin{itemize} - \item symbolically simplifying $\ve$ in $\tenv$ via $\normalize$ yields $\veone$; - \item determining the set of used identifiers in $\veone$ yields $\useset$; - \item $\vb$ is true if and only if every identifier in $\useset$ is pure; - \item the result is $\True$ is $\vb$ is $\True$, otherwise it is a type error indicating that the expression - is not statically evaluable. -\end{itemize} - -\CodeSubsection{\CheckStaticallyEvaluableBegin}{\CheckStaticallyEvaluableEnd}{../Typing.ml} - -\subsection{Formally} -\begin{mathpar} -\inferrule{ - \normalize(\tenv, \ve) \typearrow \veone\\ - \useexpr(\veone) \typearrow \useset\\ - \id\in\useset: \storageispure(\tenv, \id) \typearrow \vb_\id\\ - \vb \eqdef \bigwedge_{\id\in\useset} \vb_\id\\ - \checktrans{\vb}{NotStaticallyEvaluable} \checktransarrow \True \OrTypeError -} -{ - \checkstaticallyevaluable(\tenv, \ve) \typearrow \True -} -\end{mathpar} - -\section{TypingRule.ToWellConstrained} -\hypertarget{def-towellconstrained}{} -The function -\[ - \towellconstrained(\overname{\ty}{\vt}) \aslto \overname{\ty}{\vtp} -\] -returns the \wellconstrainedversion\ of a type $\vt$ --- $\vtp$, which is defined as follows. - -One of the following applies: -\begin{itemize} - \item All of the following apply (\textsc{t\_int\_parameterized}): - \begin{itemize} - \item $\vt$ is a \parameterizedintegertype\ for the variable $\vv$; - \item $\vtp$ is the well-constrained integer constrained by the variable expression for $\vv$, - that is, $\TInt(\wellconstrained(\constraintexact(\EVar(\vv))))$. - \end{itemize} - - \item All of the following apply (\textsc{t\_int\_other, other}): - \begin{itemize} - \item $\vt$ is not a \parameterizedintegertype\ for the variable $\vv$; - \item $\vtp$ is $\vt$. - \end{itemize} -\end{itemize} - -\subsection{Formally} -\begin{mathpar} -\inferrule[t\_int\_parameterized]{} -{ - \towellconstrained(\TInt(\parameterized(\vv))) \typearrow\\ \TInt(\wellconstrained(\constraintexact(\EVar(\vv)))) -} -\and -\inferrule[t\_int\_other]{ - \astlabel(\vi) \neq \parameterized -}{ - \towellconstrained(\TInt(\vi)) \typearrow \vt -} -\and -\inferrule[other]{ - \astlabel(\vt) \neq \TInt -}{ - \towellconstrained(\vt) \typearrow \vt -} -\end{mathpar} - -\section{TypingRule.GetWellConstrainedStructure} -\hypertarget{def-getwellconstrainedstructure}{} -The function -\[ - \getwellconstrainedstructure(\overname{\staticenvs}{\tenv} \aslsep \overname{\ty}{\vt}) - \aslto \overname{\ty}{\vtp} \cup \overname{\TTypeError}{\TypeErrorConfig} -\] -returns the \wellconstrainedstructure\ of a type $\vt$ in the static environment $\tenv$ --- $\vtp$, which is defined as follows. -\ProseOtherwiseTypeError - -\subsection{Prose} -All of the following apply: -\begin{itemize} - \item the \structure\ of $\vt$ in $\tenv$ is $\vtone$\ProseOrTypeError; - \item the well-constrained version of $\vtone$ is $\vtp$. -\end{itemize} - -\subsection{Formally} -\begin{mathpar} -\inferrule{ - \tstruct(\tenv, \vt) \typearrow \vtone \OrTypeError\\\\ - \towellconstrained(\vtone) \typearrow \vtp -}{ - \getwellconstrainedstructure(\tenv, \vt) \typearrow \vtp -} -\end{mathpar} - -\section{TypingRule.GetBitvectorWidth} -\hypertarget{def-getbitvectorwidth}{} -The function -\[ - \getbitvectorwidth(\overname{\staticenvs}{\tenv} \aslsep \overname{\ty}{\vt}) \aslto - \overname{\expr}{\ve} \cup \TTypeError -\] -returns the expression $\ve$, which represents the width of the bitvector type $\vt$, -or a type error if $\vt$ is not a bitvector type or another type error is detected. - -\subsection{Prose} -One of the following applies: -\begin{itemize} - \item All of the following apply (\textsc{okay}): - \begin{itemize} - \item obtaining the \structure\ of $\vt$ in $\tenv$ yields a bitvector type with width expression $\ve$, - that is, $\TBits(\ve, \Ignore)$\ProseOrTypeError; - \item the result is $\ve$. - \end{itemize} - - \item All of the following apply (\textsc{error}): - \begin{itemize} - \item obtaining the \structure\ of $\vt$ in $\tenv$ yields a type that is not a bitvector type; - \item the result is a type error indicating that a bitvector type was expected. - \end{itemize} -\end{itemize} - -\subsection{Formally} -\begin{mathpar} -\inferrule[okay]{ - \tstruct(\tenv, \vt) \typearrow \TBits(\ve, \Ignore) \OrTypeError -}{ - \getbitvectorwidth(\tenv, \vt) \typearrow \ve -} -\and -\inferrule[error]{ - \tstruct(\tenv, \vt) \typearrow \vtp\\ - \astlabel(\vtp) \neq \TBits -}{ - \getbitvectorwidth(\tenv, \vt) \typearrow \TypeErrorVal{\ExpectedBitvectorType} -} -\end{mathpar} - -\section{TypingRule.CheckBitsEqualWidth} -\hypertarget{def-checkbitsequalwidth}{} -The function -\[ - \checkbitsequalwidth( - \overname{\staticenvs}{\tenv} \aslsep - \overname{\ty}{\vtone}) \aslsep - \overname{\ty}{\vttwo})\aslto - \{\True\} \cup \TTypeError -\] -tests whether the types $\vtone$ and $\vttwo$ are bitvector types of the same width. -If the answer is positive, the result is $\True$. \ProseOtherwiseTypeError - -\subsection{Prose} -All of the following apply: -\begin{itemize} - \item obtaining the width of $\vtone$ in $\tenv$ (via $\getbitvectorwidth$) yields the expression $\vn$\ProseOrTypeError; - \item obtaining the width of $\vttwo$ in $\tenv$ (via $\getbitvectorwidth$) yields the expression $\vm$\ProseOrTypeError; - \item One of the following applies: - \begin{itemize} - \item All of the following apply (\textsc{true}): - \begin{itemize} - \item symbolically checking whether the bitwidth expressions $\vn$ and $\vm$ are equal (via $\bitwidthequal$) yields $\True$; - \item the result is $\True$. - \end{itemize} - - \item All of the following apply (\textsc{error}): - \begin{itemize} - \item symbolically checking whether the bitwidth expressions $\vn$ and $\vm$ are equal (via $\bitwidthequal$) yields $\False$; - \item the result is a type error indicating that the bitwidths are different. - \end{itemize} - \end{itemize} -\end{itemize} - -\subsection{Formally} -\begin{mathpar} -\inferrule[true]{ - \getbitvectorwidth(\tenv, \vtone) \typearrow \vn \OrTypeError\\\\ - \getbitvectorwidth(\tenv, \vttwo) \typearrow \vm \OrTypeError\\\\ - \bitwidthequal(\tenv, \vn, \vm) \typearrow \True -}{ - \checkbitsequalwidth(\tenv, \vtone, \vttwo) \typearrow \True -} -\and -\inferrule[error]{ - \getbitvectorwidth(\tenv, \vtone) \typearrow \vn \OrTypeError\\\\ - \getbitvectorwidth(\tenv, \vttwo) \typearrow \vm \OrTypeError\\\\ - \bitwidthequal(\tenv, \vn, \vm) \typearrow \False -}{ - \checkbitsequalwidth(\tenv, \vtone, \vttwo) \typearrow \TypeErrorVal{DifferentBitwidths} -} -\end{mathpar} - -\section{AssocOpt} -\hypertarget{def-assocopt}{} -The function -\[ - \assocopt(\overname{(\identifier\times T)^*}{\vli} \aslsep \overname{\identifier}{\id}) \typearrow \langle \overname{T}{\vv} \rangle -\] -returns the value $\vv$ associated with the identifier $\id$ in the list of pairs $\vli$ or $\None$, if no such association exists. - -\subsection{Prose} -One of the following applies: -\begin{itemize} - \item All of the following apply (\textsc{member}): - \begin{itemize} - \item a pair $(\id,\vv)$ exists in the list $\vli$; - \item the result is $\langle\vv\rangle$. - \end{itemize} - - \item All of the following apply (\textsc{not\_member}): - \begin{itemize} - \item every pair $(\vx,\Ignore)$ in the list $\vli$ has $\vx\neq\id$; - \item the result is $\None$. - \end{itemize} -\end{itemize} - -\subsection{Formally} -\begin{mathpar} -\inferrule[not\_member]{ - (\vx, \vv) \in \vli: \vx \neq \id -}{ - \assocopt(\vli, \id) \typearrow \None -} -\and -\inferrule[member]{ - (\id, \vv) \in \vli -}{ - \assocopt(\vli, \id) \typearrow \langle \vv \rangle -} -\end{mathpar} - -\section{LookupConstant} -\hypertarget{def-lookupconstant}{} -The function -\[ - \lookupconstant(\overname{\staticenvs}{\tenv} \aslsep \overname{\identifier}{\vs}) - \;\aslto\; \overname{\literal}{\vv}\ \cup\ \{\bot\} -\] -looks up the environment $\tenv$ for a constant $\vv$ associated with an identifier -$\vs$. The result is $\bot$ if $\vs$ is not associated with any constant. - -\subsection{Prose} -One of the following applies: -\begin{itemize} - \item All of the following apply (\textsc{local}): - \begin{itemize} - \item $\vs$ is associated with a constant $\vv$ in the local environment of $\tenv$; - \end{itemize} - - \item All of the following apply (\textsc{global}): - \begin{itemize} - \item $\vs$ is not associated with a constant in the local environment of $\tenv$; - \item $\vs$ is associated with a constant $\vv$ in the global environment of $\tenv$; - \end{itemize} - - \item All of the following apply (\textsc{none}): - \begin{itemize} - \item $\vs$ is not associated with a constant in the local environment of $\tenv$; - \item $\vs$ is not associated with a constant in the global environment of $\tenv$; - \item the result is $\bot$. - \end{itemize} -\end{itemize} - -\subsection{Formally} -\begin{mathpar} -\inferrule[local]{ - L^\tenv.\constantvalues(\vs) = \vv -}{ - \lookupconstant(\tenv, \vs) \typearrow \vv -} -\and -\inferrule[global]{ - L^\tenv.\constantvalues(\vs) = \bot\\ - G^\tenv.\constantvalues(\vs) = \vv -}{ - \lookupconstant(\tenv, \vs) \typearrow \vv -} -\and -\inferrule[none]{ - L^\tenv.\constantvalues(\vs) = \bot\\ - G^\tenv.\constantvalues(\vs) = \bot -}{ - \lookupconstant(\tenv, \vs) \typearrow \bot -} -\end{mathpar} - -\section{TypeOf} -\hypertarget{def-typeof}{} -The function -\[ - \typeof(\overname{\staticenvs}{\tenv} \aslsep \overname{\identifier}{\vs}) - \;\aslto\; \overname{\ty}{\tty}\ \cup\ \overname{\TTypeError}{\TypeErrorConfig} -\] -looks up the environment $\tenv$ for a type $\tty$ associated with an identifier -$\vs$. The result is type error if $\vs$ is not associated with any type. - -\subsection{Prose} -One of the following applies: -\begin{itemize} - \item All of the following apply (\textsc{local}): - \begin{itemize} - \item $\vs$ is associated with a type $\tty$ in the local environment of $\tenv$; - \end{itemize} - - \item All of the following apply (\textsc{global}): - \begin{itemize} - \item $\vs$ is not associated with a type in the local environment of $\tenv$; - \item $\vs$ is associated with a type $\tty$ in the global environment of $\tenv$; - \end{itemize} - - \item All of the following apply (\textsc{error}): - \begin{itemize} - \item $\vs$ is not associated with a type in the local environment of $\tenv$; - \item $\vs$ is not associated with a type in the global environment of $\tenv$; - \item the result is a type error indicating that $\vs$ was expected to be associated - with a type. - \end{itemize} -\end{itemize} - -\subsection{Formally} -\begin{mathpar} -\inferrule[local]{ - L^\tenv.\localstoragetypes(\vs) = \tty -}{ - \typeof(\tenv, \vs) \typearrow \tty -} -\and -\inferrule[global]{ - L^\tenv.\localstoragetypes(\vs) = \bot\\ - G^\tenv.\globalstoragetypes(\vs) = \tty -}{ - \typeof(\tenv, \vs) \typearrow \tty -} -\and -\inferrule[none]{ - L^\tenv.\localstoragetypes(\vs) = \bot\\ - G^\tenv.\globalstoragetypes(\vs) = \bot -}{ - \typeof(\tenv, \vs) \typearrow \TypeErrorVal{\UndefinedIdentifier} -} -\end{mathpar} - -\section{TypingRule.IsUndefined \label{sec:TypingRule.IsUndefined}} -\hypertarget{def-isundefined}{} -The function -\[ -\isundefined(\overname{\staticenvs}{\tenv} \aslsep \overname{\identifier}{\vx}) -\aslto \overname{\Bool}{\vb} -\] -checks whether the identifier $\vx$ is defined as a storage element in the static environment $\tenv$. - -\subsection{Prose} -$\vb$ is $\True$ if and only if $\vx$ is not bound in to a global storage in $\tenv$ and -$\vx$ is not bound to a local storage in $\tenv$. - -\subsection{Formally} -\begin{mathpar} -\inferrule{ - \vb \eqdef G^\tenv.\globalstoragetypes(\vx) = \bot \land L^\tenv.\localstoragetypes(\vx) = \bot -}{ - \isundefined(\tenv, \vx) \typearrow \vb -} -\end{mathpar} - -\section{Sorting Lists \label{sec:sortinglists}} -\hypertarget{def-sort}{} -The parametric function -\[ -\sort(\overname{T^*}{\vlone}, \overname{(T\times T)\rightarrow \{-1,0,1\}}{\compare}) \typearrow \overname{T^*}{\vltwo} -\] -sorts a list of elements of type $T$ --- $\vlone$ --- using the comparison function $\compare$, -resulting in the sorted list $\vltwo$. -$\compare(a, b)$ returns $1$ to mean that $a$ should be ordered before $b$, -$0$ to mean that $a$ and $b$ can be ordered in any way, -and $-1$ to mean that $b$ should be ordered before $a$. - -\subsection{Prose} -One of the following applies: -\begin{itemize} - \item All of the following apply (\textsc{empty\_or\_single}): - \begin{itemize} - \item $\vlone$ is either empty or contains a single element; - \item $\vltwo$ is $\vlone$. - \end{itemize} - - \item All of the following apply (\textsc{two\_or\_more}): - \begin{itemize} - \item $\vlone$ contains at least two elements; - \item $f$ is a permutation of $1..n$; - \item $\vltwo$ is the application of the permutation $f$ to $\vlone$; - \item applying $\compare$ to every pair of consecutive elements in $\vltwo$ yields either $0$ or $1$. - \end{itemize} -\end{itemize} - -\subsection{Formally} -\begin{mathpar} -\inferrule[empty\_or\_single]{ - \listlen{\vlone} = n\\ - n < 2 -}{ - \sort(\vlone, \compare) \typearrow \overname{\vlone}{\vltwo} -} -\and -\inferrule[two\_or\_more]{ - \listlen{\vlone} = n\\ - f : 1..n \rightarrow 1..n \text{ is a bijection}\\ - \vltwo \eqdef [\ i=1..n: \vlone[f(i)]\ ]\\ - i=1..n-1: \compare(\vltwo[i], \vltwo[i+1]) \geq 0 -}{ - \sort(\vlone, \compare) \typearrow \vltwo -} -\end{mathpar} - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -\chapter{Type Error Codes} - -\begin{description} -\hypertarget{def-expectedbitvectortype}{} -\item[$\ExpectedBitvectorType$] -This error indicates that a bitvector type was expected where a non-bitvector type was given. -See \typingrulecasename{CheckBinop}{plus\_minus\_bits\_bits} (\secref{TypingRule.CheckBinop}) for an example. - -\hypertarget{def-expectedenumerationtype}{} -\item[$\ExpectedEnumerationType$] -This error indicates that an enumeration type was expected where a \\ -non-enumeration type was given. -See \secref{TypingRule.TArray} for an example. - -\hypertarget{def-expectedstructuredtype}{} -\item[$\ExpectedStructuredType$] -This error indicates that a \structuredtype\ was expected where a non-\structuredtype\ was given. -See \secref{TypingRule.ERecord} for an example. - -\hypertarget{def-expectedtupletype}{} -\item[$\ExpectedTupleType$] -This error indicates that a tuple type was expected where a non-tuple type was given. -See \secref{TypingRule.LEDestructuring} for an example. - -\hypertarget{def-setterwithoutgetter}{} -\item[$\SetterWithoutGetter$:] -ASL requires each setter for a given identifier to have a corresponding getter for the same -identifier. -The specification either does not contain a getter for the same identifier -or a getter for the same identifier exists, but it does not have the expected -signature (see \secref{TypingRule.CheckSetterHasGetter}). - -\hypertarget{def-undefinedidentifier}{} -\item[$\UndefinedIdentifier$] -An identifier that is missing a definition of the appropriate kind. -See TypingRule.SubprogramForName (\secref{TypingRule.SubprogramForName}) for an example. - -\hypertarget{def-lengthsmismatch}{} -\item[$\LengthsMismatch$] -This error indicates that two lists that are expected to have the same length have different lengths. -See \secref{TypingRule.LEDestructuring} for an example. - -\hypertarget{def-subprogramdeclaredmultipletimes}{} -\item[$\SubrogramDeclaredMultipleTimes$] -At least two subprograms in the specification clash. -See \secref{TypingRule.AddNewFunc} for an example. - -\hypertarget{def-nocallcandidates}{} -\item[$\NoCallCandidates$] -A function call, given by its name and list of formal argument types, does not match any defined subprogram. -See \secref{TypingRule.SubprogramForName} for an example. - -\hypertarget{def-toomanycandidates}{} -\item[$\TooManyCandidates$] -A function call, given by its name and list of formal argument types, matches more than one subprogram, -which does not allow the type-checker to decide which subprogram the call refers to. -See \secref{TypingRule.SubprogramForName} for an example. - -\hypertarget{def-parameterwithoutdecl}{} -\item[$\ParameterWithoutDecl$] -A subprogram includes a parameter that is not associated with any variable appearing in one of the arguments. -See \secref{TypingRule.AnnotateParams} for an example. - -\hypertarget{def-nolca}{} -\item[$\NoLCA$] -A conditional expressions results in two types that have no common ancestor type that can represent both. -See \secref{TypingRule.LowestCommonAncestor} for an example. - -\hypertarget{def-mrv}{} -\item[$\MismatchedReturnValue$] -A call to a function must result in a returned value, -whereas a call to a procedure must not. -This error occurs when a call to a function or a getter is inferred to refer to a procedure or a setter, -or a call to a procedure or a setter is inferred to refer to a function or a getter. -See \secref{TypingRule.AnnotateCallArgTyped} for an example. - -\hypertarget{def-cba}{} -\item[$\CallBadArity$] -A call to a subprogram must have the same number of arguments as the list of formal arguments -declared for the subprogram. -This error indicates that the number of arguments is different to the number of declared formal arguments. -See \secref{TypingRule.AnnotateCallArgTyped} for an example. - -\hypertarget{def-brd}{} -\item[$\BadRecursiveDecls$] -Only subprogram declarations may be mutually recursive. -This error indicates that at least one declaration in a given list of mutually recursive declarations -is not a subprogram. -See \secref{TypingRule.TypeCheckMutuallyRec} for an example. - -\hypertarget{def-lbi}{} -\item[$\RequireIntegerForLoopBounds$] -The expressions defining the bounds of a \texttt{for} loop are required to have the \structure\ of -an integer type. -This error indicates that at least one of the start expression and end expression violate this -requirement. -See \secref{TypingRule.TypeCheckMutuallyRec} for an example. - -\hypertarget{def-mfi}{} -\item[$\MissingFieldInitializer$] -This error indicates that an initialization of a \structuredtype\ is missing an expression to initialize -one of its fields. -See \secref{TypingRule.ERecord} for an example. - -\hypertarget{def-rsb}{} -\item[$\RequireSameBitwidths$] -This error indicates that two bitvector types are required to have the same bitwidths but the type-checker -was not able to prove it. -See \secref{BitvectorOperations} for an example. - -\hypertarget{def-taf}{} -\item[$\TypeAsssertionFails$] -This error indicates that a given at type assertion expression will always fail. -See \secref{TypingRule.CheckATC} for an example. - -\hypertarget{def-ofc}{} -\item[$\BinaryOperationFailsAllConstraints$] -This error indicates that a binary expression appearing in a constraint will always fail dynamically. -This means that the set of values that the type containing -the constraint can take is empty. -See \secref{TypingRule.BinopFilterRhs} for an example. - -\hypertarget{def-otb}{} -\item[$\InvalidOperandTypesForBinop$] -This error indicates that the operator of a binary expression cannot be applied to its operand expressions -due to their types. -See \secref{TypingRule.CheckBinop} for an example. - -\hypertarget{def-iaf}{} -\item[$\AnnonymousFormNotAllowedHere$] -This error indicates that an anonymous type is being used as a type annotation in a context -where anonymous types are not allowed. -See \secref{TypingRule.TNonDecl} for an example. - -\hypertarget{def-aim}{} -\item[$\AssignmentToImmutable$] -This error indicates that an assignment has a left-hand-side storage element that is immutable. -See \secref{TypingRule.LEVar} for an example. - -\hypertarget{def-mf}{} -\item[$\MissingField$] -This error indicates that an access is made (for either reading or writing) to a field that is -not declared by the respective \structuredtype\ or a bitfield that is not declared by the respective -bitvector type. -See \secref{TypingRule.LESetStructuredField} for an example. - -\hypertarget{def-dii}{} -\item[$\DivIntIndivisible$] -This error indicates that a \staticallyevaluable\ expression contain an integer division expression where -the denominator does not divide the numerator. -See \textsc{TypingRule.BinopLiterals.DIV\_INT} (\secref{TypingRule.BinopLiterals}) for an example. - -\end{description} - -% \bibliographystyle{plain} -% \bibliography{ASL} - -% \end{document} diff --git a/asllib/doc/ASLmacros.tex b/asllib/doc/ASLmacros.tex index 435a2146a..93992ee0b 100644 --- a/asllib/doc/ASLmacros.tex +++ b/asllib/doc/ASLmacros.tex @@ -53,14 +53,14 @@ using, var, watch, when, where, while, with, ztype, _}, keywordstyle=\color{red}, - morecomment=[l]{//}, + morecomment=[l][\color{blue}]{//}, morecomment=[s][\color{blue}]{/*}{*/}, morestring=[b][\color{cyan}]", morestring=[d][\color{cyan}]', } \lstset{ language=ASL, - basicstyle=\small\ttfamily, + basicstyle=\ttfamily\scriptsize, showspaces=false, showstringspaces=false, backgroundcolor=\color{yellow!10} @@ -167,11 +167,14 @@ \newtheorem{definition}{Definition} \newtheorem{example}{Example} \newcommand\figref[1]{Figure.~\ref{fi:#1}} +\newcommand\taref[1]{Table.~\ref{ta:#1}} \newcommand\defref[1]{Definition~\ref{def:#1}} \newcommand\secref[1]{Section~\ref{sec:#1}} \newcommand\chapref[1]{Chapter~\ref{chap:#1}} \newcommand\partref[1]{Part~\ref{part:#1}} \newcommand\appendixref[1]{Appenfix~\ref{appendix:#1}} +\newcommand\secreflink[1]{\small\nameref{sec:#1}} +\newcommand\prosesection[0]{\subsubsection{Prose}} \newcommand\ie{i.\,e.} \newcommand\eg{e.\,g.} \newcommand\wrappedline[0]{{\hyperlink{def-wrapline}{\color{red}\hookrightarrow}}} @@ -418,7 +421,7 @@ \newcommand\Nuntypeddeclitem[0]{\hyperlink{def-nuntypeddeclitem}{\nonterminal{untyped\_decl\_item}}} \newcommand\Nslice[0]{\hyperlink{def-nslice}{\nonterminal{slice}}} \newcommand\Nslices[0]{\hyperlink{def-nslices}{\nonterminal{slices}}} -\newcommand\Nnslices[0]{\hyperlink{def-nnslice}{\nonterminal{nslices}}} +\newcommand\Nnamedslices[0]{\hyperlink{def-nnslices}{\nonterminal{named\_slices}}} \newcommand\Nintconstraints[0]{\hyperlink{def-nintconstraints}{\nonterminal{int\_constraints}}} \newcommand\Nintconstraintsopt[0]{\hyperlink{def-nintconstraintsopt}{\nonterminal{int\_constraints\_opt}}} \newcommand\Nintconstraint[0]{\hyperlink{def-nintconstraint}{\nonterminal{int\_constraint}}} @@ -709,7 +712,7 @@ \newcommand\buildpattern[0]{\hyperlink{build-pattern}{\textfunc{build\_pattern}}} \newcommand\buildfields[0]{\hyperlink{build-fields}{\textfunc{build\_fields}}} \newcommand\buildfieldsopt[0]{\hyperlink{build-fieldsopt}{\textfunc{build\_fields\_opt}}} -\newcommand\buildnslices[0]{\hyperlink{build-nslices}{\textfunc{build\_nslices}}} +\newcommand\buildnamedslices[0]{\hyperlink{build-nslices}{\textfunc{build\_named\_slices}}} \newcommand\buildslices[0]{\hyperlink{build-slices}{\textfunc{build\_slices}}} \newcommand\buildslice[0]{\hyperlink{build-slice}{\textfunc{build\_slice}}} \newcommand\buildbitfields[0]{\hyperlink{build-bitfields}{\textfunc{build\_bitfields}}} @@ -834,9 +837,9 @@ \newcommand\aslto[0]{\longrightarrow} \newcommand\staticenvs[0]{\hyperlink{def-staticenvs}{\mathbb{SE}}} -\newcommand\localstaticenvs[0]{\hyperlink{def-localstaticenvs}{\mathbb{L}}} -\newcommand\globalstaticenvs[0]{\hyperlink{def-globalstaticenvs}{\mathbb{G}}} -\newcommand\emptytenv[0]{\hyperlink{def-emptytenv}{\emptyset_{\tenv}}} +\newcommand\localstaticenvs[0]{\hyperlink{def-localstaticenvs}{\mathbb{LSE}}} +\newcommand\globalstaticenvs[0]{\hyperlink{def-globalstaticenvs}{\mathbb{GSE}}} +\newcommand\emptytenv[0]{\hyperlink{def-emptytenv}{\emptyset_{\mathbb{SE}}}} \newcommand\tstruct[0]{\hyperlink{def-tstruct}{\textfunc{get\_structure}}} \newcommand\astlabel[0]{\hyperlink{def-astlabel}{\textfunc{ast\_label}}} \newcommand\typesat[0]{\hyperlink{def-typesatisfies}{\textfunc{type\_satisfies}}} @@ -849,6 +852,7 @@ \newcommand\subtypes[0]{\hyperlink{def-subtypes}{\textsf{subtypes}}} \newcommand\subprograms[0]{\hyperlink{def-subprograms}{\textsf{subprograms}}} \newcommand\subprogramrenamings[0]{\hyperlink{def-subprogramrenamings}{\textsf{subprogram\_renamings}}} +\newcommand\exprequiv[0]{\hyperlink{def-exprequiv}{\textsf{expr\_equiv}}} \newcommand\parameters[0]{\hyperlink{def-parameters}{\textsf{parameters}}} \newcommand\unopliterals[0]{\hyperlink{def-unopliterals}{\textfunc{unop\_literals}}} @@ -879,6 +883,8 @@ \newcommand\evalarrow[0]{\xrightarrow{\evalrel}} \newcommand\envs[0]{\hyperlink{def-envs}{\mathbb{E}}} \newcommand\dynamicenvs[0]{\hyperlink{def-dynamicenvs}{\mathbb{DE}}} +\newcommand\localdynamicenvs[0]{\hyperlink{def-localdynamicenvs}{\mathbb{LDE}}} +\newcommand\globaldynamicenvs[0]{\hyperlink{def-globaldynamicenvs}{\mathbb{GDE}}} \newcommand\xgraph[0]{\textsf{g}} \newcommand\emptygraph[0]{{\hyperlink{def-emptygraph}{\emptyset_\xgraph}}} \newcommand\asldata[0]{\hyperlink{def-asldata}{\mathtt{asl\_data}}} @@ -923,11 +929,13 @@ \newcommand\evalexprsef[1]{\hyperlink{def-evalexprsef}{\textfunc{eval\_expr\_sef}}(#1)} \newcommand\evallexpr[1]{\hyperlink{def-evallexpr}{\textfunc{eval\_lexpr}}(#1)} \newcommand\evalexprlist[1]{\hyperlink{def-evalexprlist}{\textfunc{eval\_expr\_list}}(#1)} -\newcommand\evalexprlistm[1]{\hyperlink{def-evalexprlistm}{\textfunc{eval\_expr\_list\_m}}(#1)} +\newcommand\evalexprlistm[0]{\hyperlink{def-evalexprlistm}{\textfunc{eval\_expr\_list\_m}}} \newcommand\evalpattern[1]{\hyperlink{def-evalpattern}{\textfunc{eval\_pattern}}(#1)} \newcommand\evallocaldecl[1]{\hyperlink{def-evallocaldecl}{\textfunc{eval\_local\_decl}}(#1)} -\newcommand\evalslices[1]{\hyperlink{def-evalslices}{\textfunc{eval\_slices}}(#1)} -\newcommand\evalslice[1]{\hyperlink{def-evalslice}{\textfunc{eval\_slice}}(#1)} +\newcommand\ldituplefolder[0]{\hyperlink{def-ldituplefolder}{\textfunc{ldi\_tuple\_folder}}} +\newcommand\writefolder[0]{\hyperlink{def-writefolder}{\textfunc{write\_folder}}} +\newcommand\evalslices[0]{\hyperlink{def-evalslices}{\textfunc{eval\_slices}}} +\newcommand\evalslice[0]{\hyperlink{def-evalslice}{\textfunc{eval\_slice}}} \newcommand\evalstmt[1]{\hyperlink{def-evalstmt}{\textfunc{eval\_stmt}}(#1)} \newcommand\evalblock[1]{\hyperlink{def-evalblock}{\textfunc{eval\_block}}(#1)} \newcommand\evalloop[1]{\hyperlink{def-evalloop}{\textfunc{eval\_loop}}(#1)} @@ -936,7 +944,7 @@ \newcommand\evalsubprogram[1]{\hyperlink{def-evalsubprogram}{\textfunc{eval\_subprogram}}(#1)} \newcommand\evalcall[1]{\hyperlink{def-evalcall}{\textfunc{eval\_call}}(#1)} \newcommand\evalprimitive[1]{\hyperlink{def-evalprimitive}{\textfunc{eval\_primitive}}(#1)} -\newcommand\evalmultiassignment[1]{\hyperlink{def-evalmultiassign}{\textfunc{multi\_assign}}(#1)} +\newcommand\evalmultiassignment[0]{\hyperlink{def-evalmultiassign}{\textfunc{multi\_assign}}} \newcommand\rethrowimplicit[0]{\hyperlink{def-rethrowimplicit}{\textfunc{rethrow\_implicit}}} \newcommand\assignargs[0]{\hyperlink{def-assignargs}{\textfunc{assign\_args}}} \newcommand\assignnamedargs[0]{\hyperlink{def-assignnamedargs}{\textfunc{assign\_named\_args}}} @@ -944,7 +952,7 @@ \newcommand\buildgenv[0]{\hyperlink{def-buildgenv}{\textfunc{build\_genv}}} \newcommand\topologicaldecls[0]{\hyperlink{def-topologicaldecls}{\textfunc{topological\_decls}}} \newcommand\evalglobals[0]{\hyperlink{def-evalglobals}{\textfunc{eval\_globals}}} -\newcommand\evalspec[1]{\hyperlink{def-evalspec}{\textfunc{eval\_spec}}(#1)} +\newcommand\evalspec[0]{\hyperlink{def-evalspec}{\textfunc{eval\_spec}}} \newcommand\lexprisvar[0]{\hyperlink{def-lexprisvar}{\textfunc{lexpr\_is\_var}}} \newcommand\casetoconds[0]{\hyperlink{def-casetoconds}{\textfunc{case\_to\_conds}}} \newcommand\findcatcher[0]{\hyperlink{def-findcatcher}{\textfunc{find\_catcher}}} @@ -952,6 +960,7 @@ \newcommand\declarelocalidentifier[0]{\hyperlink{def-declarelocalidentifier}{\textfunc{declare\_local\_identifier}}} \newcommand\declarelocalidentifierm[0]{\hyperlink{def-declarelocalidentifierm}{\textfunc{declare\_local\_identifier\_m}}} \newcommand\declarelocalidentifiermm[0]{\hyperlink{def-declarelocalidentifermm}{\textfunc{declare\_local\_identifier\_mm}}} +%\newcommand\envfind[0]{\hyperlink{def-envfind}{\textfunc{env\_find}}} \newcommand\removelocal[0]{\hyperlink{def-removelocal}{\textfunc{remove\_local}}} \newcommand\readidentifier[0]{\hyperlink{def-readidentifier}{\textfunc{read\_identifier}}} \newcommand\writeidentifier[0]{\hyperlink{def-writeidentifier}{\textfunc{write\_identifier}}} @@ -1073,6 +1082,7 @@ \newcommand\addnewfunc[0]{\hyperlink{def-addnewfunc}{\textfunc{add\_new\_func}}} \newcommand\addsubprogram[0]{\hyperlink{def-addsubprogram}{\textfunc{add\_subprogram}}} \newcommand\isundefined[0]{\hyperlink{def-isundefined}{\textfunc{is\_undefined}}} +\newcommand\lookupimmutableexpr[0]{\hyperlink{def-lookupimmutableexpr}{\textfunc{lookup\_immutable\_expr}}} \newcommand\scanforparams[0]{\hyperlink{def-scanforparams}{\textfunc{scan\_for\_params}}} \newcommand\annotateparams[0]{\hyperlink{def-annotateparams}{\textfunc{annotate\_params}}} \newcommand\annotateoneparam[0]{\hyperlink{def-annotateoneparam}{\textfunc{annotate\_one\_param}}} @@ -1162,9 +1172,66 @@ % An expression that we do not statically evaluate. \newcommand\CannotBeTransformed[0]{\hyperlink{def-unsupportedexpression}{\top}} +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% Primitive Operations macros \newcommand\unopsignatures[0]{\hyperlink{def-unopsignatures}{\textfunc{unop\_signatures}}} \newcommand\binopsignatures[0]{\hyperlink{def-binopsignatures}{\textfunc{binop\_signatures}}} +\newcommand\notbool[0]{\hyperlink{def-notbool}{\text{not\_bool}}} +\newcommand\andbool[0]{\hyperlink{def-andbool}{\text{and\_bool}}} +\newcommand\orbool[0]{\hyperlink{def-orbool}{\text{or\_bool}}} +\newcommand\eqbool[0]{\hyperlink{def-eqbool}{\text{eq\_bool}}} +\newcommand\nebool[0]{\hyperlink{def-nebool}{\text{ne\_bool}}} +\newcommand\impliesbool[0]{\hyperlink{def-impliesbool}{\text{implies\_bool}}} +\newcommand\equivbool[0]{\hyperlink{def-equivbool}{\text{equiv\_bool}}} + +\newcommand\addbits[0]{\hyperlink{def-addbits}{\text{add\_bits}}} +\newcommand\addbitsint[0]{\hyperlink{def-addbitsint}{\text{add\_bits\_int}}} +\newcommand\subbits[0]{\hyperlink{def-subbits}{\text{sub\_bits}}} +\newcommand\subbitsint[0]{\hyperlink{def-subbitsint}{\text{sub\_bits\_int}}} +\newcommand\notbits[0]{\hyperlink{def-notbits}{\text{not\_bits}}} +\newcommand\andbits[0]{\hyperlink{def-andbits}{\text{and\_bits}}} +\newcommand\orbits[0]{\hyperlink{def-orbits}{\text{or\_bits}}} +\newcommand\xorbits[0]{\hyperlink{def-xorbits}{\text{xor\_bits}}} +\newcommand\eqbits[0]{\hyperlink{def-eqbits}{\text{eq\_bits}}} +\newcommand\nebits[0]{\hyperlink{def-nebits}{\text{ne\_bits}}} + +\newcommand\negateint[0]{\hyperlink{def-negateint}{\text{negate\_int}}} +\newcommand\addint[0]{\hyperlink{def-addint}{\text{add\_int}}} +\newcommand\subint[0]{\hyperlink{def-subint}{\text{sub\_int}}} +\newcommand\mulint[0]{\hyperlink{def-mulint}{\text{mul\_int}}} +\newcommand\expint[0]{\hyperlink{def-expint}{\text{exp\_int}}} +\newcommand\shiftleftint[0]{\hyperlink{def-shiftleftint}{\text{shiftleft\_int}}} +\newcommand\shiftrightint[0]{\hyperlink{def-shiftrightint}{\text{shiftright\_int}}} +\newcommand\divint[0]{\hyperlink{def-divint}{\text{div\_int}}} +\newcommand\fdivint[0]{\hyperlink{def-fdivint}{\text{fdiv\_int}}} +\newcommand\fremint[0]{\hyperlink{def-fremint}{\text{frem\_int}}} +\newcommand\eqint[0]{\hyperlink{def-eqint}{\text{eq\_int}}} +\newcommand\neint[0]{\hyperlink{def-neint}{\text{ne\_int}}} +\newcommand\leint[0]{\hyperlink{def-leint}{\text{le\_int}}} +\newcommand\ltint[0]{\hyperlink{def-ltint}{\text{lt\_int}}} +\newcommand\gtint[0]{\hyperlink{def-gtint}{\text{gt\_int}}} +\newcommand\geint[0]{\hyperlink{def-geint}{\text{ge\_int}}} + +\newcommand\negatereal[0]{\hyperlink{def-negatereal}{\text{negate\_real}}} +\newcommand\addreal[0]{\hyperlink{def-addreal}{\text{add\_real}}} +\newcommand\subreal[0]{\hyperlink{def-subreal}{\text{sub\_real}}} +\newcommand\mulreal[0]{\hyperlink{def-mulreal}{\text{mul\_real}}} +\newcommand\expreal[0]{\hyperlink{def-expreal}{\text{exp\_real}}} +\newcommand\divreal[0]{\hyperlink{def-divreal}{\text{div\_real}}} +\newcommand\eqreal[0]{\hyperlink{def-eqreal}{\text{eq\_real}}} +\newcommand\nereal[0]{\hyperlink{def-nereal}{\text{ne\_real}}} +\newcommand\lereal[0]{\hyperlink{def-lereal}{\text{le\_real}}} +\newcommand\ltreal[0]{\hyperlink{def-ltreal}{\text{lt\_real}}} +\newcommand\gtreal[0]{\hyperlink{def-gtreal}{\text{gt\_real}}} +\newcommand\gereal[0]{\hyperlink{def-gereal}{\text{ge\_real}}} + +\newcommand\eqstring[0]{\hyperlink{def-eqstring}{\text{eq\_string}}} +\newcommand\nestring[0]{\hyperlink{def-nestring}{\text{ne\_string}}} + +\newcommand\eqenum[0]{\hyperlink{def-eqenum}{\text{eq\_enum}}} +\newcommand\neenum[0]{\hyperlink{def-neenum}{\text{ne\_enum}}} + % AST abbreviations %\newcommand\ELInt[1]{\hyperlink{def-elint}{\texttt{ELInt}}(#1)} \newcommand\ELInt[1]{\overbracket{#1}^{\hyperlink{def-elint}{\ELiteral(\lint)}}} @@ -1178,6 +1245,17 @@ \newcommand\AbbrevTArrayLengthEnum[3]{\overbracket{\texttt{array }[#1 \# #2]\texttt{ of }#3}^{\hyperlink{def-abbrevtarraylengthenum}{\scriptscriptstyle{\TArray(\ArrayLengthEnum)}}}} % Glossary +\newcommand\head[0]{\hyperlink{def-head}{\texttt{head}}} +\newcommand\tail[0]{\hyperlink{def-tail}{\texttt{tail}}} +\newcommand\optional[0]{\hyperlink{def-optional}{optional}} + +\newcommand\typedast[0]{\hyperlink{def-typedast}{typed AST}} +\newcommand\untypedast[0]{\hyperlink{def-untypedast}{untyped AST}} +\newcommand\anonymoustype[0]{\hyperlink{def-isanonymous}{anonymous type}} +\newcommand\Anonymoustypes[0]{\hyperlink{def-isanonymous}{Anonymous types}} +\newcommand\namedtype[0]{\hyperlink{def-isnamed}{named type}} +\newcommand\namedtypes[0]{\hyperlink{def-isnamed}{named types}} + \newcommand\parameterizedintegertype[0]{\hyperlink{def-parameterizedintegertype}{parameterized integer type}} \newcommand\structuredtype[0]{\hyperlink{def-structuredtype}{structured type}} \newcommand\structure[0]{\hyperlink{def-structure}{structure}} @@ -1200,9 +1278,23 @@ \newcommand\namedlowestcommonancestor[0]{\hyperlink{def-namedlowestcommonancestor}{named lowest common ancestor}} \newcommand\arrayaccess[0]{\hyperlink{def-arrayaccess}{array access}} \newcommand\symbolicallysimplifies[0]{\hyperlink{def-symbolicallysimplifies}{symbolically simplifies}} -\newcommand\nativevalue[0]{\hyperlink{def-nativevalue}{native values}} +\newcommand\nativevalue[0]{\hyperlink{def-nativevalue}{native value}} \newcommand\nativevalues[0]{\hyperlink{def-nativevalues}{native values}} +\newcommand\singleslice[0]{\hyperlink{def-singleslice}{single slice}} +\newcommand\rangeslice[0]{\hyperlink{def-rangeslice}{range slice}} +\newcommand\lengthslice[0]{\hyperlink{def-lengthslice}{length slice}} +\newcommand\scaledslice[0]{\hyperlink{def-scaledslice}{scaled slice}} + +\newcommand\rhsexpression[0]{\hyperlink{def-rhsexpression}{right-hand-side expression}} +\newcommand\rhsexpressions[0]{\hyperlink{def-rhsexpressions}{right-hand-side expressions}} +\newcommand\assignableexpression[0]{\hyperlink{def-assignableexpression}{assignable expression}} +\newcommand\assignableexpressions[0]{\hyperlink{def-assignableexpressions}{assignable expressions}} +\newcommand\localdeclarationkeyword[0]{\hyperlink{def-localdeclarationkeyword}{local declaration keyword}} +\newcommand\localdeclarationitem[0]{\hyperlink{def-localdeclarationitem}{local declaration item}} +\newcommand\localdeclaration[0]{\hyperlink{def-localdeclaration}{local declaration}} +\newcommand\localdeclarations[0]{\hyperlink{def-localdeclarations}{local declarations}} + %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% Type functions \newcommand\CheckUnop[0]{\hyperlink{def-checkunop}{\textfunc{check\_unop}}} @@ -1223,10 +1315,12 @@ \newcommand\refineconstraints[0]{\hyperlink{def-refineconstraints}{\textfunc{refine\_constraints}}} \newcommand\filterreduceconstraintdiv[0]{\hyperlink{def-filterreduceconstraintdiv}{\textfunc{filter\_reduce\_constraint\_div}}} \newcommand\getliteraldivopt[0]{\hyperlink{def-getliteraldivopt}{\textfunc{get\_literal\_div\_opt}}} -\newcommand\checkslicesinwidth[0]{\tododefine{check\_slices\_in\_width}} -\newcommand\disjointslicestopositions[0]{\tododefine{disjoint\_slices\_to\_positions}} -\newcommand\checkpositionsinwidth[0]{\tododefine{check\_positions\_in\_width}} +\newcommand\checkslicesinwidth[0]{\hyperlink{def-checkslicesinwidth}{\textfunc{check\_slices\_in\_width}}} +\newcommand\disjointslicestopositions[0]{\hyperlink{def-disjointslicestopositions}{\textfunc{disjoint\_slices\_to\_positions}}} +\newcommand\bitfieldslicetopositions[0]{\hyperlink{bitfieldslicetopositions}{\textfunc{bitfield\_slice\_to\_positions}}} +\newcommand\checkpositionsinwidth[0]{\hyperlink{def-checkpositionsinwidth}{\textfunc{check\_positions\_in\_width}}} \newcommand\shouldslicesreducetocall[0]{\tododefine{should\_slices\_reduce\_to\_call}} +\newcommand\shouldreducetocall[0]{\tododefine{should\_reduce\_to\_call}} \newcommand\checkdisjointslices[0]{\tododefine{check\_disjoint\_slices}} \newcommand\annotatetype[1]{\hyperlink{def-annotatetype}{\textfunc{annotate\_type}}(#1)} \newcommand\annotateconstraint[0]{\hyperlink{def-annotateconstraint}{\textfunc{annotate\_constraint}}} @@ -1338,6 +1432,10 @@ \newcommand\AssignmentToImmutable[0]{\hyperlink{def-aim}{\TypeErrorCode{AIM}}} \newcommand\MissingField[0]{\hyperlink{def-mf}{\TypeErrorCode{MF}}} \newcommand\DivIntIndivisible[0]{\hyperlink{def-dii}{\TypeErrorCode{DII}}} +\newcommand\BitfieldsOutOfRange[0]{\hyperlink{def-bor}{\TypeErrorCode{BOT}}} +\newcommand\BitfieldSlicesOverlap[0]{\hyperlink{def-bso}{\TypeErrorCode{BSO}}} +\newcommand\BitfieldSliceReversed[0]{\hyperlink{def-bsr}{\TypeErrorCode{BSR}}} +\newcommand\IntConstantExpected[0]{\hyperlink{def-icc}{\TypeErrorCode{ICC}}} %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % Semantics/Typing Shared macros @@ -1348,11 +1446,6 @@ \newcommand\env[0]{\hyperlink{def-env}{\texttt{env}}} -% Glossary -\newcommand\head[0]{\hyperlink{def-head}{\texttt{head}}} -\newcommand\tail[0]{\hyperlink{def-tail}{\texttt{tail}}} -\newcommand\optional[0]{\hyperlink{def-optional}{optional}} - %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % LRM Ident info \newcommand\ident[2]{\texttt{#1}\textsubscript{\texttt{\MakeUppercase{#2}}}} @@ -1589,17 +1682,20 @@ \newcommand\matches[0]{\texttt{matches}} \newcommand\matchesone[0]{\texttt{matches1}} \newcommand\matchingrenamings[0]{\texttt{matching\_renamings}} +\newcommand\maxpos[0]{\texttt{max\_pos}} \newcommand\mbv[0]{\texttt{m\_bv}} \newcommand\mcond[0]{\texttt{m\_cond}} \newcommand\mfactor[0]{\texttt{m\_factor}} \newcommand\mindex[0]{\texttt{m\_index}} \newcommand\minitopt[0]{\texttt{m\_init\_opt}} +\newcommand\minpos[0]{\texttt{min\_pos}} \newcommand\mlength[0]{\texttt{m\_length}} \newcommand\monome[0]{\texttt{monome}} \newcommand\monoms[0]{\texttt{monoms}} \newcommand\monomsone[0]{\texttt{monoms1}} \newcommand\mpositions[0]{\texttt{m\_positions}} \newcommand\ms[0]{\texttt{ms}} +\newcommand\msout[0]{\texttt{ms\_out}} \newcommand\mstart[0]{\texttt{m\_start}} \newcommand\mtop[0]{\texttt{m\_top}} \newcommand\name[0]{\texttt{name}} @@ -1986,6 +2082,7 @@ \newcommand\vmstwo[0]{\texttt{vms2}} \newcommand\vmtwo[0]{\texttt{m2}} \newcommand\vn[0]{\texttt{n}} +\newcommand\vnamedslices[0]{\texttt{named\_slices}} \newcommand\vnames[0]{\texttt{name\_s}} \newcommand\vnamess[0]{\texttt{names\_s}} \newcommand\vnamest[0]{\texttt{names\_t}} @@ -2031,6 +2128,7 @@ \newcommand\vsliceasts[0]{\texttt{slice\_asts}} \newcommand\vsliceone[0]{\texttt{slice1}} \newcommand\vslices[0]{\texttt{slices}} +\newcommand\vslicesone[0]{\texttt{slices1}} \newcommand\vsone[0]{\texttt{s1}} \newcommand\vsonep[0]{\texttt{s1'}} \newcommand\vsp[0]{\texttt{s'}} @@ -2125,6 +2223,7 @@ \newcommand\vwhereast[0]{\texttt{where\_ast}} \newcommand\vwhereopt[0]{\texttt{where\_opt}} \newcommand\vwidth[0]{\texttt{width}} +\newcommand\vwidths[0]{\texttt{widths}} \newcommand\vwone[0]{\texttt{w1}} \newcommand\vwtwo[0]{\texttt{w2}} \newcommand\vwzero[0]{\texttt{w0}} @@ -2149,6 +2248,5 @@ \newcommand\ws[0]{\texttt{w\_s}} \newcommand\wt[0]{\texttt{w\_t}} \newcommand\xs[0]{\texttt{xs}} - \newcommand\vEs[0]{\texttt{es}} \newcommand\vesone[0]{\texttt{es1}} diff --git a/asllib/doc/AbstractSyntax.tex b/asllib/doc/AbstractSyntax.tex new file mode 100644 index 000000000..2444a6011 --- /dev/null +++ b/asllib/doc/AbstractSyntax.tex @@ -0,0 +1,924 @@ +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +\chapter{Abstract Syntax\label{chap:AbstractSyntax}} +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +An abstract syntax is a form of context-free grammar over structured trees. +Compilers and interpreters typically start by parsing the text of a program and producing an abstract syntax tree (AST, for short), +and then continue to operate over that tree. +% +The reason for this is that abstract syntax trees abstract away details that are irrelevant to the semantics of the program, +such as punctuation and scoping syntax, which are useful for readability and parsing. + +\hypertarget{def-typedast}{} +\hypertarget{def-untypedast}{} +\paragraph{Untyped AST vs. Typed AST:} +Technically, there are two abstract syntaxes: +an \emph{untyped abstract syntax} and a \emph{typed abstract syntax}. +The first syntax results from parsing the text of an ASL specification. +The type checker checks whether the untyped AST is valid and if so produces +a typed AST where some nodes in the untyped AST have been transformed to +more explicit representation. For example, the untyped AST may contain +what looks like a slicing expression, which turns out to be a call to a getter. +The typed AST represents that call directly, making it simpler for an interpreter +to evaluate that expression. + +\paragraph{Outline:} +The outline of this chapter is as follows, +We first define the type of Abstract Syntax Trees used by ASL (\secref{AbstractSyntaxTrees}). +We then define the notations for defining the AST grammar used by ASL (\secref{AbstractSyntaxGrammar}) +Finally, we define the AST grammar rules for the different ASL constructs along with examples: +\begin{itemize} + \item Identifiers (\secref{Identifiers}) + \item Literal values (\secref{ASTLiterals}) + \item Basic Operations (\secref{BasicOperations}) + \item Expressions (\secref{Expressions}) + \item Patterns (\secref{Patterns}) + \item Slices (\secref{Slices}) + \item Types (\secref{Types}) + \item Constraints (\secref{Constraints}) + \item Bit Fields (\secref{BitFields}) + \item Array Indices (\secref{ArrayIndices}) + \item Fields and Typed Identifiers (\secref{FieldsAndTypedIdentifiers}) + \item Left-hand Side Expressions (\secref{LeftHandSideExpressions}) + \item Local Declarations (\secref{LocalDeclarations}) + \item Statements (\secref{Statements}) + \item Case Alternatives (\secref{CaseAlternatives}) + \item Exception Catchers (\secref{ExceptionCatchers}) + \item Subprograms (\secref{Subprograms}) + \item Global Declarations (\secref{GlobalDeclarations}) + \item Specifications (\secref{Specifications}) +\end{itemize} +We then define the following: +\begin{itemize} +\item the grammar rules for the \untypedast\ (\secref{UntypedAbstractGrammar}) +\item the grammar rules for the \typedast\ (\secref{TypedAbstractSyntaxGrammar}) +\item how we use inference rules to define the transformation from a parse tree into an \untypedast\ (\secref{BuildingAbstractSyntaxTrees}) +\item rules for building ASTs from parameterized productions (\secref{BuildingParameterizedProductions}) +\item how \assignableexpressions\ can be viewed as corresponding right hand side expressions (\secref{LeftToRight}) +\item finally, we define some useful abbreviations for denoting abstract syntax trees in rules (\secref{AbstractSyntaxAbreviations}) +\end{itemize} + +\section{Abstract Syntax Trees\label{sec:AbstractSyntaxTrees}} + +In an ASL abstract syntax tree, a node is one the following data types: +\begin{description} +\item[Token Node.] A lexical token, denoted as in the lexical description of ASL; +\item[Label Node.] A label +\item[Unlabelled Tuple Node.] A tuple of children nodes, denoted as $(n_1,\ldots,n_k)$; +\item[Labelled Tuple Node.] A tuple labelled~$L$, denoted as~$L(n_1,\ldots,n_k)$; +\item[List Node.] A list of~$0$ or more children nodes, denoted as~$\emptylist$ + when the list is empty and~$[n_1,\ldots,n_k]$ for non-empty lists; +\item[Optional.] An optional node stands for a list of 0 or 1 occurrences of a sub-node $n$. We denote an empty optional by $\langle\rangle$ and the non-empty optional by $\langle n \rangle$; +\item[Record Node.] A record node, denoted as $\{\text{name}_1 : n_1,\ldots,\text{name}_k : n_k\}$, where \\ + $\text{name}_1 \ldots \text{name}_k$ are names, which associates names with corresponding nodes. +\end{description} + +\section{Abstract Syntax Grammar\label{sec:AbstractSyntaxGrammar}} + +An abstract syntax is defined in terms of derivation rules containing variables (also referred to as non-terminals). +% +A \emph{derivation rule} has the form $v \derives \textit{rhs}$ where $v$ is a non-terminal variable and \textit{rhs} is a \emph{node type}. We write $n$, $n_1,\ldots,n_k$ to denote node types. +% +Node types are defined recursively as follows: +\begin{description} +\item[Non-terminal.] A non-terminal variable; +\item[Terminal.] A lexical token $t$ or a label $L$; +\item[Unlabelled Tuple.] A tuple of node types, denoted as~$(n_1,\ldots,n_k)$; +\item[Labelled Tuple.] A tuple labelled~$L$, denoted as~$L(n_1,\ldots,n_k)$; +\item[List.] A list node type, denoted as $n^{*}$; +\item[Optional.] An optional node type, denoted as $n?$; +\item[Record.] A record, denoted as $\{\text{name}_1 : n_1,\ldots,\text{name}_k : n_k\}$ where $\text{name}_i$, which associates names with corresponding node types. +\end{description} + +\newpage + +An abstract syntax consists of a set of derivation rules and a start non-terminal. + +\newcommand\ASTComment[1]{//\quad\textit{#1}\ } + +\section{Untyped Abstract Grammar\label{sec:UntypedAbstractGrammar}} + +The abstract syntax of ASL is given in terms of the derivation rules below and the start non-terminal $\specification$. +% +Some extra details are given by using the notation $\overname{\textit{symbol}}{\text{detail}}$. + +\subsection{Identifiers \label{sec:Identifiers}} +\hypertarget{ast-identifier}{} +Identifiers in the AST, denoted $\identifier$ are simply strings representing ASL identifiers. +Those are obtained directly from the values of identifier tokens, $\Tidentifier(s)$. + +\subsection{Literal Values \label{sec:ASTLiterals}} +The following rules correspond to literal values of the following ASL data types: +integers, Booleans, real numbers, bitvectors, and strings. + +\hypertarget{ast-literal}{} \hypertarget{ast-lint}{} +\begin{flalign*} +\literal \derives\ & \lint(\overname{n}{\Z}) +& \hypertarget{ast-lbool}{} +\\ + |\ & \lbool(\overname{b}{\{\True, \False\}}) + & \hypertarget{ast-lreal}{} +\\ + |\ & \lreal(\overname{q}{\Q}) + & \hypertarget{ast-lbitvector}{} +\\ + |\ & \lbitvector(\overname{B}{B \in \{0, 1\}^*}) + & \hypertarget{ast-lstring}{} +\\ + |\ & \lstring(\overname{S}{S \in \{C \;|\; \texttt{"$C$"}\ \in\ \Strings\}}) & +\end{flalign*} + +\subsection{Basic Operations\label{sec:BasicOperations}} +The following rules correspond to unary operations and binary operations that can be applied to expressions. + +\hypertarget{ast-unop}{} \hypertarget{ast-bnot}{} \hypertarget{ast-neg}{} \hypertarget{ast-not}{} +\begin{flalign*} +\unop \derives\ & \overname{\BNOT}{\texttt{"!"}} \;|\; \overname{\NEG}{\texttt{"-"}} \;|\; \overname{\NOT}{\texttt{"NOT"}} +& \hypertarget{ast-binop}{} \hypertarget{ast-bor}{} \hypertarget{ast-impl}{} \hypertarget{ast-beq}{} \hypertarget{ast-band}{} +\\ +\binop \derives\ & \overname{\BAND}{\texttt{"\&\&"}} \;|\; \overname{\BOR}{\texttt{"||"}} \;|\; \overname{\IMPL}{\texttt{"-->"}} + \;|\; \overname{\BEQ}{\texttt{"<->"}} + & \hypertarget{ast-eqop}{} \hypertarget{ast-neq}{} \hypertarget{ast-gt}{} \hypertarget{ast-geq}{} \hypertarget{ast-lt}{} \hypertarget{ast-leq}{} +\\ + |\ & \overname{\EQOP}{\texttt{"=="}} \;|\; \overname{\NEQ}{\texttt{"!="}} \;|\; \overname{\GT}{\texttt{"<"}} + \;|\; \overname{\GEQ}{\texttt{">="}} \;|\; \overname{\LT}{\texttt{"<"}} \;|\; \overname{\LEQ}{\texttt{"<="}} + & \hypertarget{ast-plus}{} \hypertarget{ast-minus}{} \hypertarget{ast-or}{} \hypertarget{ast-xor}{} \hypertarget{ast-and}{} +\\ + |\ & \overname{\PLUS}{\texttt{"+"}} \;|\; \overname{\MINUS}{\texttt{"-"}} \;|\; \overname{\OR}{\texttt{"OR"}} + \;|\; \overname{\XOR}{\texttt{"XOR"}} \;|\; \overname{\AND}{\texttt{"AND"}} + & \hypertarget{ast-mul}{} \hypertarget{ast-div}{} \hypertarget{ast-divrm}{} \hypertarget{ast-mod}{} \hypertarget{ast-shl}{} \hypertarget{ast-shr}{} +\\ + |\ & \overname{\MUL}{\texttt{"*"}} \;|\; \overname{\DIV}{\texttt{"DIV"}} \;|\; \overname{\DIVRM}{\texttt{"DIVRM"}} + \;|\; \overname{\MOD}{\texttt{"MOD"}} \;|\; \overname{\SHL}{\texttt{"<<"}} \;|\; \overname{\SHR}{\texttt{">>"}} + & \hypertarget{ast-rdiv}{} \hypertarget{ast-pow}{} +\\ + |\ & \overname{\RDIV}{\texttt{"/"}} \;|\; \overname{\POW}{\texttt{"\^{}"}} + & +\end{flalign*} + +\subsection{Expressions \label{sec:Expressions}} +The following rules correspond to various types of expressions: +literal expressions, variable expressions, typing assertions, binary operation expressions, unary operation expressions, +call expressions, slicing expressions, conditional expressions, single-field access expressions, multiple-field access expressions, +record and exception construction expressions, concatenation expressions, tuple expressions, unknown-value expressions, +and pattern matching expressions. + +\hypertarget{ast-expr}{} \hypertarget{ast-eliteral}{} +\begin{flalign*} +\expr \derives\ & \ELiteral(\literal) +& \hypertarget{ast-evar}{} \hypertarget{ast-identifier}{}\\ + |\ & \EVar(\overtext{\identifier}{variable name}) + &\hypertarget{ast-eatc}{}\\ + |\ & \overtext{\EATC}{Type assertion}(\expr, \overtext{\ty}{asserted type}) + &\hypertarget{ast-ebinop}{}\\ + |\ & \EBinop(\binop, \expr, \expr) + &\hypertarget{ast-eunop}{}\\ + |\ & \EUnop(\unop, \expr) + &\hypertarget{ast-ecall}{}\\ + |\ & \ECall(\overtext{\identifier}{subprogram name}, \overtext{\expr^{*}}{actual arguments}) + &\hypertarget{ast-eslice}{}\\ + |\ & \ESlice(\expr, \slice^{*}) + &\hypertarget{ast-econd}{}\\ + |\ & \ECond(\overtext{\expr}{condition}, \overtext{\expr}{then}, \overtext{\expr}{else}) + &\hypertarget{ast-egetfield}{}\\ + |\ & \EGetField(\overtext{\expr}{record}, \overtext{\identifier}{field name}) + &\hypertarget{ast-egetfields}{}\\ + |\ & \EGetFields(\overtext{\expr}{record}, \overtext{\identifier^{*}}{field names}) + &\hypertarget{ast-erecord}{}\\ + |\ & \ERecord(\overtext{\ty}{record type}, \overtext{(\identifier, \expr)^{*}}{field initializers}) + &\hypertarget{ast-econcat}{}\\ + |\ & \EConcat(\expr^{+}) + &\hypertarget{ast-etuple}{}\\ + |\ & \ETuple(\expr^{+}) + &\hypertarget{ast-eunknown}{}\\ + |\ & \EUnknown(\ty) + &\hypertarget{ast-epattern}{}\\ + |\ & \EPattern(\expr, \pattern) +\end{flalign*} + +\figref{expr1} and \figref{expr2} exemplify the different kinds of expressions, +as indicated by respective comments. +\begin{figure} +\ASLExample{\syntaxtests/expr1.asl} +\caption{Examples of expressions \label{fi:expr1}} +\end{figure} + +\begin{figure} +\ASLExample{\syntaxtests/expr2.asl} +\caption{Examples of expressions\label{fi:expr2}} +\end{figure} + +\begin{itemize} + \item $\EVar(\vx)$ represents variables (\texttt{E\_Var 1}) + as well as getters declared without a list of arguments (\texttt{E\_Var 2}). + + \item $\EATC(\ve, \vt)$ represents typing assertions. For example: \texttt{x as integer}. + Here $\ve$ corresponds to \texttt{x} and $\vt$ corresponds to \texttt{integer}. + + \item $\ESlice(\ve, \vslices)$ represents slices of bitvectors (\texttt{E\_Slice 1}), + slices of integers \\ + (\texttt{E\_Slice 2}), + calls to getters (\texttt{E\_Slice 3} and \texttt{E\_Slice 4}), + and access to array elements (\texttt{E\_Slice 5}). + + \item $\EGetField(\ve, \id)$ represents an access to a record (\texttt{E\_GetField 1}) + or exception field + as well as an access to a tuple component (\texttt{E\_GetField 2}). + + \item $\EGetFields(\ve, \ids)$ represents an access to multiple record fields (\texttt{E\_GetFields 1}). +\end{itemize} + +\subsection{Patterns \label{sec:Patterns}} + +\hypertarget{ast-pattern}{} \hypertarget{ast-patternall}{} +\begin{flalign*} +\pattern \derives\ & \PatternAll + & \hypertarget{ast-patternany}{}\\ + |\ & \PatternAny(\pattern^{*}) + & \hypertarget{ast-patterngeq}{}\\ + |\ & \PatternGeq(\expr) + & \hypertarget{ast-patternleq}{}\\ + |\ & \PatternLeq(\expr) + & \hypertarget{ast-patternmask}{}\\ + |\ & \PatternMask(\overtext{\{0,1,x\}^*}{mask constant}) + & \hypertarget{ast-patternnot}{}\\ + |\ & \PatternNot(\pattern) + & \hypertarget{ast-patternrange}{}\\ + |\ & \PatternRange(\overtext{\expr}{lower}, \overtext{\expr}{upper}) + & \hypertarget{ast-patternsingle}{}\\ + |\ & \PatternSingle(\expr) + & \hypertarget{ast-patterntuple}{}\\ + |\ & \PatternTuple(\pattern^{*}) & +\end{flalign*} + +\subsection{Slices \label{sec:Slices}} + +\hypertarget{ast-slice}{} \hypertarget{ast-slicesingle}{} +\begin{flalign*} +% &&\ASTComment{Indexes an array or a bitvector.}\\ +% &&\ASTComment{All positions mentioned below are inclusive}\\ +\slice \derives\ & \SliceSingle(\overname{\expr}{\vi}) + & \hypertarget{ast-slicerange}{}\\ + % & & \ASTComment{the slice of length \texttt{1} at position \vi.}\\ + |\ & \SliceRange(\overname{\expr}{\vj}, \overname{\expr}{\vi}) + & \hypertarget{ast-slicelength}{}\\ + % & & \ASTComment{the slice from \vi\ to \texttt{j - 1}.}\\ + |\ & \SliceLength(\overname{\expr}{\vi}, \overname{\expr}{\vn}) + & \hypertarget{ast-slicestar}{}\\ + % & & \ASTComment{the slice starting at \vi\ of length \vn.}\\ + |\ & \SliceStar(\overname{\expr}{\vi}, \overname{\expr}{\vn}) & + % & & \ASTComment{the slice starting at \texttt{i*n} of length \vn} +\end{flalign*} + +\subsection{Types \label{sec:Types}} + +\hypertarget{ast-ty}{} \hypertarget{ast-tint}{} +\begin{flalign*} +\ty \derives\ & \TInt(\intconstraints) +\hypertarget{ast-treal}{}\\ + |\ & \TReal + & \hypertarget{ast-tstring}{}\\ + |\ & \TString + & \hypertarget{ast-tbool}{}\\ + |\ & \TBool + & \hypertarget{ast-tbits}{}\\ + |\ & \TBits(\overtext{\expr}{width}, \bitfield^{*}) + & \hypertarget{ast-ttuple}{}\\ + |\ & \TTuple(\ty^{*}) + & \hypertarget{ast-tarray}{}\\ + |\ & \TArray(\arrayindex, \ty) + & \hypertarget{ast-tnamed}{}\\ + |\ & \TNamed(\overtext{\identifier}{type name}) & + & \hypertarget{ast-tenum}{}\\ + |\ & \TEnum(\overtext{\identifier^{*}}{labels})\\ + & \hypertarget{ast-trecord}{}\\ + |\ & \TRecord(\Field^{*}) + & \hypertarget{ast-texception}{}\\ + |\ & \TException(\Field^{*}) +% & & & \ASTComment{This is related to \identi{LDNP}} +\end{flalign*} + +\subsection{Constraints \label{sec:Constraints}} + +\hypertarget{ast-intconstraints}{} \hypertarget{ast-unconstrained}{} +\begin{flalign*} + % & & \ASTComment{Constraints that may be assigned to integer types.} \\ + \intconstraints \derives\ & \unconstrained + % & & \ASTComment{The unconstrained integer type.} + & \hypertarget{ast-wellconstrained}{}\\ + |\ & \wellconstrained(\intconstraint^{+}) + % & & \ASTComment{An integer type with explicit constraints.} + & \hypertarget{ast-parameterized}{}\\ + |\ & \parameterized(\overtext{\identifier}{parameter}) & + % & & \ASTComment{Implicitly constrained integer from function declaration.} \\ + % & & \ASTComment{Attributes are:} \\ + % & & \ASTComment{- a unique integer identifier and the variable} \\ + % & & \ASTComment{- the type was implicitly constructed from.} \\ +\end{flalign*} + +\hypertarget{ast-intconstraint}{} \hypertarget{ast-constraintexact}{} +\begin{flalign*} +% & & \ASTComment{A constraint on an integer part.}\\ +\intconstraint \derives\ & \ConstraintExact(\expr) + % & & \ASTComment{A single value, given by a statically evaluable expression.} + & \hypertarget{ast-constraintrange}{}\\ + |\ & \ConstraintRange(\overtext{\expr}{start}, \overtext{\expr}{end})& + % & & \ASTComment{An interval between two statically evaluable expression.}\\ +\end{flalign*} + +\subsection{Bit Fields \label{sec:BitFields}} + +\hypertarget{ast-bitfield}{} \hypertarget{ast-bitfieldsimple}{} +\begin{flalign*} +% & & \ASTComment{Represent static slices on a given bitvector type.}\\ +\bitfield \derives\ & \BitFieldSimple(\identifier, \slice^{*}) + % & & \ASTComment{A name and its corresponding slice.} + & \hypertarget{ast-bitfieldnested}{}\\ + |\ & \BitFieldNested(\identifier, \slice^{*}, \bitfield^{*}) + % & & \ASTComment{A name, its corresponding slice and some nested bitfields.} + & \hypertarget{ast-bitfieldtype}{}\\ + |\ & \BitFieldType(\identifier, \slice^{*}, \ty) & + % & & \ASTComment{A name, its corresponding slice, and the type of the bitfield.}\\ +\end{flalign*} + +\subsection{Array Indices \label{sec:ArrayIndices}} + +\hypertarget{ast-arrayindex}{} \hypertarget{ast-arraylengthexpr}{} +The type of array indices is given by the following AST type: +\begin{flalign*} +\arrayindex \derives\ & \ArrayLengthExpr(\overtext{\expr}{array length}) & +\end{flalign*} + +% \[ +% \begin{array}{rcl} +% & & \ASTComment{The type of indexes for an array.} \\ +% \hline +% \arrayindex & \derives +% & \ArrayLengthExpr(\overtext{\expr}{array length}) +% \hypertarget{ast-arraylengthenum}{}\\ +% &|& \ArrayLengthEnum(\overtext{\identifier}{name of enumeration}, \overtext{\Z}{length}) \\ +% \end{array} +% \] + +\subsection{Fields and Typed Identifiers \label{sec:FieldsAndTypedIdentifiers}} + +The following rule corresponds to a field of a record-like structure: +\hypertarget{ast-field}{} +\begin{flalign*} +\Field \derives\ & (\identifier, \ty) & \hypertarget{ast-typedidentifier}{} +\end{flalign*} + +The following rule corresponds to an identifier with its associated type: +\hypertarget{ast-typedidentifier}{} +\begin{flalign*} +\typedidentifier \derives\ & (\identifier, \ty) & +\end{flalign*} + +\subsection{Left-hand Side Expressions \label{sec:LeftHandSideExpressions}} + +The following rules define the types of left-hand side of assignments: +\hypertarget{ast-lexpr}{} \hypertarget{ast-lediscard}{} +\begin{flalign*} +\lexpr \derives\ & \overtext{\LEDiscard}{\texttt{"-"}} &\\ + |\ & \LEVar(\identifier) & \hypertarget{ast-leslice}{}\\ + |\ & \LESlice(\lexpr, \slice^*) & \hypertarget{ast-lesetarray}{}\\ + |\ & \LESetArray(\lexpr, \expr) & \hypertarget{ast-lesetfield}{}\\ + |\ & \LESetField(\lexpr, \identifier) & \hypertarget{ast-lesetfields}{}\\ + |\ & \LESetFields(\lexpr, \identifier^*) & \hypertarget{ast-ledestructuring}{}\\ + |\ & \LEDestructuring(\lexpr^*) & \hypertarget{ast-leconcat}{}\\ + |\ & \LEConcat(\lexpr^+) &\\ +\end{flalign*} + +$\LEConcat(\texttt{les})$ represents the left-hand-side list of expressions for simultaneous assignments. + +\subsection{Local Declarations \label{sec:LocalDeclarations}} + +\hypertarget{ast-localdeclkeyword}{} \hypertarget{ast-ldkvar}{} \hypertarget{ast-ldkconstant}{} \hypertarget{ast-ldklet}{} +\begin{flalign*} +\localdeclkeyword \derives\ & \LDKVar \;|\; \LDKConstant \;|\; \LDKLet & +\end{flalign*} + +A local declaration item is the left-hand side of a declaration statements. +In the following example of a declaration statement: +\begin{verbatim} +let (x, -, z): (integer, integer, integer {0..32}) = (2, 3, 4); +\end{verbatim} +the local declaration item is +\Verb|(x, -, z): (integer, integer, integer {0..32})|. + +\hypertarget{ast-localdeclitem}{} \hypertarget{ast-ldidiscard}{} +\begin{flalign*} +\localdeclitem \derives\ & \LDIDiscard + % & & \ASTComment{The ignored local declaration item, for example used in: \Verb!let - = 42;!.} + & \hypertarget{ast-ldivar}{}\\ + |\ & \LDIVar(\identifier) + % & & \ASTComment{\texttt{LDI\_Var x} is the variable declaration of the variable \texttt{x}, used for example in:}\\ + % & & \ASTComment{\texttt{let x = 42;}.} + & \hypertarget{ast-ldituple}{}\\ + |\ & \LDITuple(\localdeclitem^*) + % & & \ASTComment{\texttt{LDI\_Tuple ldis} is the tuple declarations of the items in \texttt{ldis},}\\ + % & & \ASTComment{used for example in: \texttt{let (x, y, -, z) = (1, 2, 3, 4);}}\\ + % & & \ASTComment{Note that a the list here must be at least 2 items long.} + & \hypertarget{ast-ldityped}{}\\ + |\ & \LDITyped(\localdeclitem, \ty) & + % & & \ASTComment{\texttt{LDI\_Typed (ldi, t)} declares the item \texttt{ldi} with type \texttt{t}, used for example in:} \\ + % & & \ASTComment{\texttt{let x: integer = 4;}} +\end{flalign*} + +\subsection{Statements \label{sec:Statements}} + +\hypertarget{ast-fordirection}{} \hypertarget{ast-up}{} \hypertarget{ast-down}{} +\begin{flalign*} +\fordirection \derives\ & \UP \;|\; \DOWN &\\ +\hypertarget{ast-stmt}{} \hypertarget{ast-spass}{}\\ +\stmt \derives\ & \SPass +\hypertarget{ast-sseq}{} &\\ + |\ & \SSeq(\stmt, \stmt) + \hypertarget{ast-sdecl}{} &\\ + |\ & \SDecl(\localdeclkeyword, \localdeclitem, \expr?) + \hypertarget{ast-sassign}{} &\\ + |\ & \SAssign(\lexpr, \expr) + \hypertarget{ast-scall}{} &\\ + |\ & \SCall(\overtext{\identifier}{subprogram name}, \overtext{\expr^{*}}{actual arguments}) + \hypertarget{ast-sreturn}{} &\\ + |\ & \SReturn(\expr?) + \hypertarget{ast-scond}{} &\\ + |\ & \SCond(\expr, \stmt, \stmt) + \hypertarget{ast-scase}{} &\\ + |\ & \SCase(\expr, \casealt^*) + \hypertarget{ast-sassert}{} &\\ + |\ & \SAssert(\expr) + \hypertarget{ast-sfor}{} &\\ + |\ & \SFor\left\{ + \begin{array}{rcl} + \Forindexname &:& \identifier,\\ + \Forstarte &:& \expr,\\ + \Fordir &:& \fordirection,\\ + \Forende &:& \expr,\\ + \Forbody &:& \stmt,\\ + \Forlimit &:& \expr? + \end{array} + \right\} + \hypertarget{ast-swhile}{} &\\ + |\ & \SWhile(\overtext{\expr}{condition}, \overtext{\expr?}{loop limit}, \overtext{\stmt}{loop body}) + \hypertarget{ast-srepeat}{} &\\ + |\ & \SRepeat(\overtext{\stmt}{loop body}, \overtext{\expr}{condition}, \overtext{\expr?}{loop limit}) + \hypertarget{ast-sthrow}{} &\\ + & \ASTComment{The option represents an implicit throw: \texttt{throw;}.}\\ + |\ & \SThrow(\expr?) &\\ + \hypertarget{ast-stry}{} &\\ + |\ & \STry(\stmt, \catcher^*, \overtext{\stmt?}{otherwise}) + \hypertarget{ast-sprint}{} &\\ + |\ & \SPrint(\overtext{\expr^*}{args}, \overtext{\Bool}{debug}) +\end{flalign*} + +\subsection{Case Alternatives \label{sec:CaseAlternatives}} + +\hypertarget{ast-casealt}{} +\begin{flalign*} +\casealt \derives\ & \{ \CasePattern : \pattern, \CaseWhere : \expr?, \CaseStmt : \stmt \} & +\end{flalign*} + +\subsection{Exception Catchers \label{sec:ExceptionCatchers}} +\hypertarget{ast-catcher}{} +\begin{flalign*} +\catcher \derives\ & (\overtext{\identifier?}{exception to match}, \overtext{\ty}{guard type}, \overtext{\stmt}{statement to execute on match}) & +\end{flalign*} + +\subsection{Subprograms \label{sec:Subprograms}} +\hypertarget{ast-subprogramtype}{} \hypertarget{ast-stprocedure}{} \hypertarget{ast-stfunction}{} +\begin{flalign*} +\subprogramtype \derives\ & \STProcedure \;|\; \STFunction +\hypertarget{ast-stgetter}{} \hypertarget{ast-stemptygetter}{} &\\ + |\ & \STGetter \;|\; \STEmptyGetter + \hypertarget{ast-stsetter}{} \hypertarget{ast-stemptysetter}{} &\\ + |\ & \STSetter \;|\; \STEmptySetter & +\end{flalign*} + +\hypertarget{ast-subprogrambody}{} \hypertarget{ast-sbasl}{} +\begin{flalign*} +\subprogrambody \derives\ & \SBASL(\stmt) \hypertarget{ast-sbprimitive}{} \;|\; \SBPrimitive & +\end{flalign*} + +\hypertarget{ast-func}{} +\begin{flalign*} +\func \derives\ & +{ +\left\{ + \begin{array}{rcl} + \funcname &:& \Strings, \\ + \funcparameters &:& (\identifier, \ty?)^*,\\ + \funcargs &:& \typedidentifier^*,\\ + \funcbody &:& \subprogrambody,\\ + \funcreturntype &:& \ty?,\\ + \funcsubprogramtype &:& \subprogramtype +\end{array} +\right\} +} & +\end{flalign*} + +\subsection{Global Declarations \label{sec:GlobalDeclarations}} +Declaration keyword for global storage elements: +\hypertarget{ast-globaldeclkeyword}{} \hypertarget{ast-gdkconstant}{} \hypertarget{ast-gdkconfig}{} \hypertarget{ast-gdklet}{} \hypertarget{ast-gdkvar}{} +\begin{flalign*} +\globaldeclkeyword \derives\ & \GDKConstant \;|\; \GDKConfig \;|\; \GDKLet \;|\; \GDKVar & +\end{flalign*} + +\hypertarget{ast-globaldecl}{} +\begin{flalign*} +\globaldecl \derives\ & +{\left\{ + \begin{array}{rcl} + \GDkeyword &:& \globaldeclkeyword, \\ + \GDname &:& \identifier,\\ + \GDty &:& \ty?,\\ + \GDinitialvalue &:& \expr? + \end{array} + \right\} + } & +\end{flalign*} + +\hypertarget{ast-decl}{} +\hypertarget{ast-dfunc}{} +\begin{flalign*} +\decl \derives\ & \DFunc(\func) & \hypertarget{ast-dglobalstorage}{}\\ + |\ & \DGlobalStorage(\globaldecl) & \hypertarget{ast-dtypedecl}{}\\ + |\ & \DTypeDecl(\identifier, \ty, (\identifier, \overtext{\Field^*}{with fields})?) & +\end{flalign*} + +\subsection{Specifications \label{sec:Specifications}} +\hypertarget{ast-specification}{} +\begin{flalign*} +\specification \derives\ & \decl^* & +\end{flalign*} + +\section{Typed Abstract Syntax Grammar\label{sec:TypedAbstractSyntaxGrammar}} + +The derivation rules for the typed abstract syntax are the same as the rules for the untyped abstract syntax, +except for the following differences. + +The rules for expressions have the extra derivation rule: +\hypertarget{ast-egetarray}{} +\begin{flalign*} +\expr \derives\ & \EGetArray(\overtext{\expr}{base}, \overtext{\expr}{index}) & +\end{flalign*} + +The AST node for call expressions includes an extra component that explicitly associates expressions +with parameters: +\begin{flalign*} +\expr \derives\ & \ECall(\overtext{\identifier}{subprogram name}, \overtext{\expr^{*}}{actual arguments}, \overtext{(\identifier, \expr)^{*}}{parameters with initializers}) & +\end{flalign*} + +The AST node for a left-hand-side tuple of expressions contains a second component $\vwidths$ whose elements +are expressions corresponding to the lengths of the corresponding slices in $\vles$: +\begin{flalign*} +\lexpr \derives\ & \LEConcat(\overname{\lexpr^+}{\vles}, \overname{\expr^+}{\vwidths}) & +\end{flalign*} + +The rules for statements refine the throw statement by annotating it with +the type of the thrown exception. +\begin{flalign*} +\stmt \derives\ & \SThrow((\expr, \overtext{\ty}{exception type})?) & +\end{flalign*} + +Similar to expressions, the AST node for call statements includes an extra component that explicitly associates expressions +with parameters: +\begin{flalign*} +\stmt \derives\ & \SCall(\overtext{\identifier}{subprogram name}, \overtext{\expr^{*}}{actual arguments}, \overtext{(\identifier, \expr)^{*}}{parameters with initializers}) & +\end{flalign*} + +The rules for slices is replaced by the following: +\begin{flalign*} +\slice \derives\ & \SliceLength(\expr, \expr) & +\end{flalign*} +This reflects the fact that all other slicing constructs are syntactic sugar +for \SliceLength. + +The following extra rule enables expressing array indices based on enumeration: +\hypertarget{ast-arraylengthenum}{} +\begin{flalign*} +\arrayindex \derives\ & \ArrayLengthEnum(\overtext{\identifier}{name of enumeration}, \overtext{\Z}{length}) & +\end{flalign*} + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +\section{Building Abstract Syntax Trees\label{sec:BuildingAbstractSyntaxTrees}} +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +We now define how to transform a parse tree into the corresponding AST +via recursively traversing the parse tree and applying a \emph{builder} function +for each non-terminal node. + +(Some of the builders are relations due to non-determinism induced by naming global variables +for assignments whose left-hand-side variable is discarded ($\Tminus$).) + +For each non-terminal $N \derives R_1 \;|\; \ldots R_k$, we define a builder function +$\textsf{build\_}N $ which takes a parse tree $\parsenode{N}$ and returns the corresponding +AST. The builder function is defined in terms of one inference rule per alternative $R_i$. +The input for the builder for an alternative $R = S_{1..m}$ is a parse node +$N(S_{1..m})$. To allow the builder to refer to the children nodes of $N$, +we use the notation $\namednode{n_i}{S_i}$, which names the child node $S_i$ as $n_i$. + +\subsection{Example} +Consider the derivation for while loops: +\[ +\Nstmt \derives \Twhile \parsesep \Nexpr \parsesep \Tdo \parsesep \Nstmtlist \parsesep \Tend +\] + +The parse node for a while statement has the form +\[ +\Nstmt(\Twhile, \namednode{\ve}{\Nexpr}, \Tdo, \namednode{\vstmtlist}{\Nstmtlist}, \Tend) +\] +where $\ve$ names the node representing the condition of the loop and $\vstmtlist$ names +the list of statements that form the body of the loop. + +To build the corresponding AST, we employ the builder function $\buildstmt$, since +the non-terminal labelling the parse node is $\Nstmt$. + +We also employ the following rule: +\begin{mathpar} +\inferrule{ + \buildexpr(\ve) \astarrow \astversion{\ve}\\ + \buildstmtlist(\vstmtlist) \astarrow \astversion{\vstmtlist} +}{ +{ +\begin{array}{r} + \buildstmt(\Nstmt(\Twhile, \namednode{\ve}{\Nexpr}, \Tdo, \namednode{\vstmtlist}{\Nstmtlist}, \Tend)) + \astarrow\\ + \SWhile(\astversion{\ve}, \None, \astversion{\vstmtlist}) +\end{array} +} +} +\end{mathpar} +That is, we apply the $\buildexpr$ to transform the condition parse node $\ve$ into the corresponding AST node, +we apply $\buildstmtlist$ to transform the parse node $\vstmtlist$ for the body of the list into the corresponding AST node, +and finally return the AST node for \texttt{while} loops --- $\SWhile$ --- with the two nodes as its children. + +We define some builders as relations rather than functions. This is due to the non-determinism +in creating identifiers for auxiliary variables that stand in for instances of \texttt{-} on the left-hand-side +of assignments and declarations. +For example, \texttt{- = 5;} will effectively create some auxiliary variable, which will result in +an AST node such as $\SAssign(\EVar(\texttt{aux-1}), \ELiteral(\lint(5)))$. +Recall that hyphens are not legal characters in ASL identifiers, which avoids potential clashes with +user-supplied identifiers. An implementation is free however to choose other naming schemes that +avoid name clashes, for example, by employing counters. + +\subsection{Abbreviated Rule Notation for AST Builders} +Notice that there is only one instance of $\Nexpr$ and one instance of $\Nstmtlist$ in this production. +This is very common and we therefore use the following shorthand notation for such cases, as explained next. + +In a non-terminal $N$ appears only once in the right-hand-side of a derivation, +we use the name $\texttt{N}$ to name the corresponding child parse node. +For example, $\namednode{\vexpr}{\Nexpr}$ and $\namednode{\vstmtlist}{\Nstmtlist}$. +In such cases, we always have the premise $\textsf{build\_}N(\texttt{N}) \astarrow \astversion{N}$ +to obtain the corresponding AST node. +We therefore make this premise implicit, by dropping it entirely and using $\astof{N}$ to mean that +the parse node $N$ is named $\texttt{N}$, the premise $\textsf{build\_}N(\texttt{N}) \astarrow \astversion{N}$ +is considered part of the rule and $\astversion{N}$ itself stands for $\astversion{N}$. + +In our example, this results in the abbreviated rule notation +\begin{mathpar} +\inferrule{}{ +{ +\begin{array}{r} + \buildstmt(\Nstmt(\Twhile, \punnode{\Nexpr}, \Tdo, \punnode{\Nstmtlist}, \Tend)) + \astarrow\\ + \SWhile(\astof{\vexpr}, \None, \astof{\vstmtlist}) + \end{array} +} +} +\end{mathpar} + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +\section{Building Parameterized Productions\label{sec:BuildingParameterizedProductions}} +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +This section defines builder relations for the +subset of macro productions in \secref{ParametricProductions} +that are not inlined: +\begin{itemize} + \item ASTRule.List (see \secref{ASTRule.List}) + \item ASTRule.CList (see \secref{ASTRule.CList}) + \item ASTRule.NTCList (see \secref{ASTRule.NTCList}) + \item ASTRule.Option (see \secref{ASTRule.Option}) +\end{itemize} + +We also define ASTRule.Identity (see \secref{ASTRule.Identity}), +which can be used in conjunction with the rules above in application +to terminals. + +\subsubsection{ASTRule.List \label{sec:ASTRule.List}} +\hypertarget{build-list}{} +The meta relation +\[ +\buildlist[b](\overname{N}{\vsyms}) \;\aslrel\; \overname{A}{\vsymasts} +\] +which is parameterized by an AST building relation $b : E \aslrel A$, +takes a parse node that represents a possibly-empty list of $E$ values --- $\vsyms$ --- and returns the result of applying $b$ +to each of them --- $\vsymasts$. + +\begin{mathpar} +\inferrule[empty]{}{ + \buildlist[b](\overname{\emptysentence}{\vsyms}) \astarrow \overname{\emptylist}{\vsymasts} +} +\end{mathpar} + +\begin{mathpar} +\inferrule[non\_empty]{ + b(\vv) \astarrow \astversion{\vv}\\ + \buildlist[b](\vsymsone) \astarrow \vsymastsone +}{ + \buildlist[b](\overname{ + \maybeemptylist{N}(\namednode{\vv}{E}, \namednode{\vsymsone}{\maybeemptylist{N}}) + }{\vsyms}) \astarrow + \overname{[\astversion{\vv}] \concat \vsymastsone}{\vsymasts} +} +\end{mathpar} + +\subsubsection{ASTRule.CList \label{sec:ASTRule.CList}} +\hypertarget{build-clist}{} +The meta relation +\[ +\buildclist[b](\overname{N}{\vsyms}) \;\aslrel\; \overname{A}{\vsymasts} +\] +which is parameterized by an AST building relation $b : E \aslrel A$, +takes a parse node that represents a possibly-empty comma-separated list of $E$ values --- $\vsyms$ --- and returns the result of applying $b$ +to each of them --- $\vsymasts$. + +\begin{mathpar} +\inferrule[empty]{}{ + \buildclist[b](\overname{\emptysentence}{\vsyms}) \astarrow \overname{\emptylist}{\vsymasts} +} +\end{mathpar} + +\begin{mathpar} +\inferrule[non\_empty]{ + b(\vv) \astarrow \astversion{\vv}\\ + \buildclist[b](\vsymsone) \astarrow \vsymastsone +}{ + \buildclist[b](\overname{ + \Clist{N}(\namednode{\vv}{E}, \Tcomma, \namednode{\vsymsone}{\NClist{N}}) + }{\vsyms}) \astarrow \overname{[\astversion{\vv}] \concat \vsymastsone}{\vsymasts} +} +\end{mathpar} + +\subsubsection{ASTRule.NTCList \label{sec:ASTRule.NTCList}} +\hypertarget{build-ntclist}{} +The meta relation +\[ +\buildntclist[b](\overname{N}{\vsyms}) \;\aslrel\; \overname{A}{\vsymasts} +\] +which is parameterized by an AST building relation $b : E \aslrel A$, +takes a parse node that represents a non-empty comma-separated trailing list of $E$ values --- $\vsyms$ --- and returns the result of applying $b$ +to each of them --- $\vsymasts$. + +\begin{mathpar} +\inferrule[empty]{ + b(\vv) \astarrow \astversion{\vv} +}{ + \buildntclist[b](\overname{\vv \parsesep \option{\Tcomma}}{\vsyms}) \astarrow \overname{[\astversion{\vv}]}{\vsymasts} +} +\end{mathpar} + +\begin{mathpar} +\inferrule[non\_empty]{ + b(\vv) \astarrow \astversion{\vv}\\ + \buildntclist[b](\vsymsone) \astarrow \vsymastsone +}{ + \buildntclist[b](\overname{\namednode{\vv}{E}, \Tcomma, \namednode{\vsymsone}{\NTClist{N}}}{\vsyms}) \astarrow \overname{[\astversion{\vv}] \concat \vsymastsone}{\vsymasts} +} +\end{mathpar} + +\subsubsection{ASTRule.Option \label{sec:ASTRule.Option}} +\hypertarget{build-option}{} +The meta relation +\[ +\buildoption[b](\overname{N}{\vsym}) \;\aslrel\; \overname{\langle A \rangle}{\vsymast} +\] +which is parameterized by an AST building relation $b : E \aslrel A$, +takes a parse node that represents an optional $E$ value --- $\vsym$ --- and returns the result of applying $b$ +to the value if it exists --- $\vsymasts$. + +\begin{mathpar} +\inferrule[none]{}{ + \buildoption[b](\overname{\emptysentence}{\vsym}) \astarrow \overname{\None}{\vsymast} +} +\end{mathpar} + +\begin{mathpar} +\inferrule[some]{ + b(\vv) \astarrow \astversion{\vv} +}{ + \buildoption[b](\overname{\namednode{\vv}{E}}{\vsym}) \astarrow \overname{\langle\astversion{\vv}\rangle}{\vsymast} +} +\end{mathpar} + +When this relation is applied to a sentence consisting of a prefix of terminals $t_{1..k}$, ending with a non-terminal $\vv$, +it ignore the terminals and returns the result for the non-terminal. +\begin{mathpar} +\inferrule[last]{ + \buildoption[b](\vv) \astarrow \vsymast +}{ + \buildoption[b](t_{1..k}, \namednode{\vv}{E}) \astarrow \vsymast +} +\end{mathpar} + +\subsubsection{ASTRule.Identity \label{sec:ASTRule.Identity}} +\hypertarget{build-identity}{} +The meta function +\[ +\buildidentity(\overname{T}{x}) \aslto \overname{T}{x} +\] +is the identity function, which can be used as an argument to meta functions such as $\buildlist$ when they are applied +to terminals. + +\begin{mathpar} +\inferrule{}{ + \buildidentity(x) \astarrow x +} +\end{mathpar} + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +\section{Correspondence Between Left-hand-side Expressions and Right-hand-side Expressions +\label{sec:LeftToRight}} + +The recursive function $\torexpr : \lexpr \rightarrow \expr$ transforms +left-hand-side expressions to corresponding right-hand-side expressions, +which is utilized both for the type system and semantics: +\[ +\begin{array}{lcl} + \textbf{Left hand side expression} & & \textbf{Right hand side expression}\\ + \hline + \torexpr(\LEVar(\vx)) &=& \EVar(\vx)\\ + \torexpr(\LESlice(\vle, \vargs)) &=& \ESlice(\torexpr(\vle), \vargs)\\ + \torexpr(\LESetArray(\vle, \ve)) &=& \EGetArray(\torexpr(\vle), \ve)\\ + \torexpr(\LESetField(\vle, \vx)) &=& \EGetField(\torexpr(\vle), \vx)\\ + \torexpr(\LESetFields(\vle, \vx)) &=& \EGetFields(\torexpr(\vle), \vx)\\ + \torexpr(\LEDiscard) &=& \EVar(\texttt{-})\\ + \torexpr(\LEDestructuring([\vle_{1..k}])) &=& \ETuple([i=1..k: \torexpr(\vle_i)])\\ + \torexpr(\LEConcat([\vle_{1..k}], \Ignore)) &=& \EConcat([i=1..k: \torexpr(\vle_i)])\\ +\end{array} +\] + +\section{Abstract Syntax Abbreviations\label{sec:AbstractSyntaxAbreviations}} +We employ the following abbreviations for various AST nodes: +\begin{center} +\begin{tabular}{ll} +\hline +\textbf{Abbreviation} & \textbf{Meaning} +\hypertarget{def-elint}{}\\ +\hline +$\ELInt{n}$ & literal integer expression: $\ELiteral(\lint(n))$ +\hypertarget{def-abbrevconstraintexact}{}\\ +$\AbbrevConstraintExact{\ve}$ & $\ConstraintExact(\ve)$ +\hypertarget{def-abbrevconstraintrange}{}\\ +$\AbbrevConstraintRange{\veone}{\vetwo}$ & $\ConstraintRange(\veone, \vetwo)$ \hypertarget{def-abbrevebinop}{}\\ +$\AbbrevEBinop{\op}{\veone}{\vetwo}$ & $\EBinop(\op, \veone, \vetwo)$ \hypertarget{def-abbrevtarraylengthexpr}{}\\ +$\AbbrevTArray{\vi}{\vt}$ & $\TArray(\ArrayLengthExpr(\vi), \vt)$ \hypertarget{def-abbrevtarray}{}\\ +$\AbbrevTArrayLengthExpr{\ve}{\vt}$ & $\TArray(\ArrayLengthExpr(\ve), \vt)$ \hypertarget{def-abbrevtarraylengthenum}{}\\ +$\AbbrevTArrayLengthEnum{\ve}{\vs}{\vt}$ & $\TArray(\ArrayLengthEnum(\ve, \vs), \vt)$\\ +\hline +\end{tabular} +\end{center} + +% \subsection{AST Builder Functions and Relations} +% We define the following rules for transforming the various non-terminal parse nodes into +% the corresponding AST nodes: +% \begin{itemize} +% \item ASTRule.AST (see \secref{ASTRule.AST}) +% \item ASTRule.GlobalDecl (see \secref{ASTRule.GlobalDecl}) +% \item ASTRule.Subtype (see \secref{ASTRule.Subtype}) +% \item ASTRule.Subtypeopt (see \secref{ASTRule.Subtypeopt}) +% \item ASTRule.TypedIdentifier (see \secref{ASTRule.TypedIdentifier}) +% \item ASTRule.OptTypedIdentifier (see \secref{ASTRule.OptTypedIdentifier}) +% \item ASTRule.ReturnType (see \secref{ASTRule.ReturnType}) +% \item ASTRule.ParamsOpt (see \secref{ASTRule.ParamsOpt}) +% \item ASTRule.AccessArgs (see \secref{ASTRule.AccessArgs}) +% \item ASTRule.FuncArgs (see \secref{ASTRule.FuncArgs}) +% \item ASTRule.MaybeEmptyStmtList (see \secref{ASTRule.MaybeEmptyStmtList}) +% \item ASTRule.FuncBody (see \secref{ASTRule.FuncBody}) +% \item ASTRule.IgnoredOrIdentifier (see \secref{ASTRule.IgnoredOrIdentifier}) +% \item ASTRule.LocalDeclKeyword (see \secref{ASTRule.LocalDeclKeyword}) +% \item ASTRule.StorageKeyword (see \secref{ASTRule.StorageKeyword}) +% \item ASTRule.Direction (see \secref{ASTRule.Direction}) +% \item ASTRule.Alt (see \secref{ASTRule.Alt}) +% \item ASTRule.OtherwiseOpt (see \secref{ASTRule.OtherwiseOpt}) +% \item ASTRule.Catcher (see \secref{ASTRule.Catcher}) +% \item ASTRule.Stmt (see \secref{ASTRule.Stmt}) +% \item ASTRule.StmtList (see \secref{ASTRule.StmtList}) +% \item ASTRule.SElse (see \secref{ASTRule.SElse}) +% \item ASTRule.LExpr (see \secref{ASTRule.LExpr}) +% \item ASTRule.LExprAtom (see \secref{ASTRule.LExprAtom}) +% \item ASTRule.DeclItem (see \secref{ASTRule.DeclItem}) +% \item ASTRule.UntypedDeclItem (see \secref{ASTRule.UntypedDeclItem}) +% \item ASTRule.ExprPattern (see \secref{ASTRule.ExprPattern}) +% \item ASTRule.Pattern (see \secref{ASTRule.Pattern}) +% \item ASTRule.Fields (see \secref{ASTRule.Fields}) +% \item ASTRule.FieldsOpt (see \secref{ASTRule.FieldsOpt}) +% \item ASTRule.Slices (see \secref{ASTRule.Slices}) +% \item ASTRule.Slice (see \secref{ASTRule.Slice}) +% \item ASTRule.TyDecl (see \secref{ASTRule.TyDecl}) +% \item ASTRule.FieldAssign (see \secref{ASTRule.FieldAssign}) +% \end{itemize} + +% We also define the following helper functions: +% \begin{itemize} +% \item ASTRule.StmtFromList (see \secref{ASTRule.StmtFromList}) +% \item ASTRule.SequenceStmts (see \secref{ASTRule.SequenceStmts}) +% \end{itemize} \ No newline at end of file diff --git a/asllib/doc/AssignableExpressions.tex b/asllib/doc/AssignableExpressions.tex new file mode 100644 index 000000000..f85d90fe5 --- /dev/null +++ b/asllib/doc/AssignableExpressions.tex @@ -0,0 +1,1020 @@ +\chapter{Assignable Expressions\label{chap:AssignableExpressions}} + +\hypertarget{def-assignableexpression}{} +\hypertarget{def-assignableexpressions}{} +We refer to expressions that may appear on the left hand side of an assignment statement as \assignableexpressions. +An \assignableexpression\ is grammatically derived from $\Nlexpr$ and is represented as an AST +by $\lexpr$. + +We show the syntax relevant to \assignableexpressions\ in \secref{AssignableExpressionsSyntax} and +the rules need to build the AST for \assignableexpressions\ in \secref{AssignableExpressionsAbstractSyntaxBuilders}. +We then define the abstract syntax, typing, and semantics of the different kinds of \assignableexpressions: +\begin{itemize} +\item Discarding assignment expressions (see \secref{DiscardingAssignmentExpressions}) +\item Variable assignment expressions (see \secref{VariableAssignmentExpressions}) +\item Multi-assignment expressions (see \secref{MultiAssignmentExpressions}) +\item Array assignment expressions (see \secref{ArrayAssignmentExpressions}) +\item Bitvector slice assignment expressions (see \secref{BitvectorSliceAssignmentExpressions}) +\item Bitfield assignment expressions (see \secref{BitfieldAssignmentExpressions}) +\item Structured type field assignment Expressions (see \secref{StructuredTypeFieldAssignmentExpressions}) +\item Multi-slice assignment expressions (see \secref{MultiSliceAssignmentExpressions}) +\end{itemize} + +\hypertarget{def-annotatelexpr}{} +The function +\[ + \annotatelexpr{ + \overname{\staticenvs}{\tenv} \aslsep + \overname{\lexpr}{\vle} \aslsep + \overname{\ty}{\vte}} \aslto + \overname{\lexpr}{\newle} \cup \TTypeError +\] +annotates a left-hand side expression $\vle$ in an environment $\tenv$, assuming $\vte$ +to be the type of the corresponding right-hand-side expression, +resulting in an annotated expression $\newle$. +\ProseOtherwiseTypeError + +The relation +\hypertarget{def-evallexpr}{} +\[ + \evallexpr{\overname{\envs}{\env} \aslsep \overname{\lexpr}{\vle} \aslsep (\overname{\vals}{\vv} \times \overname{\XGraphs}{\vg})} \;\aslrel\; + \Normal(\overname{\XGraphs}{\newg},\overname{\envs}{\newenv}) \cup + \overname{\TThrowing}{\ThrowingConfig} \cup \overname{\TError}{\ErrorConfig} +\] +evaluates the assignment of a value $\vv$ +to the left-hand-side expression $\vle$ in an environment $\env$, +resulting in either a configuration $\Normal(\newg, \env)$ or an abnormal configuration. + +\paragraph{Semantics Rules Naming Convention:} +In this chapter, variables containing $\vm$ range over $\vals\times\XGraphs$ +while variables where the $\vm$ is replaced with $\vv$ correspond to their value component. +For example, $\rmarray\eqname(\rvarray,\vgtwo)$ and $\mindex\eqname(\vindex, \vgone)$. + +\paragraph{Viewing Assignable Expressions as Right-hand-side Expressions:} +Some of the typing rules and semantics rules require viewing \assignableexpressions\ +as \rhsexpressions. +The correspondence is given by the function $\torexpr : \lexpr \rightarrow \expr$., defined in \secref{LeftToRight}. +% +For example, \hyperlink{SemanticsRule.LESetField}{SemanticsRule.LESetField} +needs to evaluate the record subexpression $\rerecord$, which is an \assignableexpression. +To achieve this, $\torexpr(\record)$ is used to obtain an \rhsexpression, which then allows +using $\texttt{eval\_expr}$ to evaluate it. + +\section{Syntax\label{sec:AssignableExpressionsSyntax}} +\begin{flalign*} +\Nlexpr \derivesinline\ & \Nlexpratom &\\ +|\ & \Tminus &\\ +|\ & \Tlpar \parsesep \NClist{\Nlexpr} \parsesep \Trpar &\\ +\Nlexpratom \derives\ & \Tidentifier &\\ +|\ & \Nlexpratom \parsesep \Nslices &\\ +|\ & \Nlexpratom \parsesep \Tdot \parsesep \Tidentifier{\field} &\\ +|\ & \Nlexpratom \parsesep \Tdot \parsesep \Tlbracket \parsesep \Clist{{\Tidentifier}} \parsesep \Trbracket &\\ +|\ & \Tlbracket \parsesep \NClist{{\Nlexpratom}} \parsesep \Trbracket & +\end{flalign*} + +\subsection{Abstract Syntax Builders\label{sec:AssignableExpressionsAbstractSyntaxBuilders}} +\subsubsection{ASTRule.LExpr \label{sec:ASTRule.LExpr}} +\hypertarget{build-lexpr}{} +The function +\[ + \buildlexpr(\overname{\parsenode{\Nlexpr}}{\vparsednode}) \;\aslto\; \overname{\lexpr}{\vastnode} +\] +transforms a parse node $\vparsednode$ into an AST node $\vastnode$. + +\begin{mathpar} +\inferrule[lexpr\_atom]{}{ + \buildlexpr(\Nlexpr(\punnode{\Nlexpratom})) \astarrow \overname{\astof{\vlexpratom}}{\vastnode} +} +\end{mathpar} + +\begin{mathpar} +\inferrule[discard]{}{ + \buildlexpr(\Nlexpr(\Tminus)) \astarrow \overname{\LEDiscard}{\vastnode} +} +\end{mathpar} + +\begin{mathpar} +\inferrule[multi\_lexpr]{ + \buildclist[\Nlexpr](\vlexprs) \astarrow \vlexprasts +}{ + \buildlexpr(\Nlexpr(\Tlpar, \namednode{\vlexprs}{\NClist{\Nlexpr}}, \Trpar)) \astarrow + \overname{\LEDestructuring(\vlexprasts)}{\vastnode} +} +\end{mathpar} + +\subsubsection{ASTRule.LExprAtom \label{sec:ASTRule.LExprAtom}} +\hypertarget{build-lexpratom}{} +The function +\[ + \buildlexpratom(\overname{\parsenode{\Nlexpratom}}{\vparsednode}) \;\aslto\; \overname{\lexpr}{\vastnode} +\] +transforms a parse node $\vparsednode$ into an AST node $\vastnode$. + +\begin{mathpar} +\inferrule[var]{}{ + \buildlexpratom(\Nlexpr(\Tidentifier(\id))) \astarrow + \overname{\LEVar(\id)}{\vastnode} +} +\end{mathpar} + +\begin{mathpar} +\inferrule[slice]{}{ + \buildlexpratom(\Nlexpr(\punnode{\Nlexpratom}, \punnode{\Nslices})) \astarrow + \overname{\LESlice(\astof{\vlexpratom}, \astof{\vslices})}{\vastnode} +} +\end{mathpar} + +\begin{mathpar} +\inferrule[set\_field]{}{ + \buildlexpratom(\Nlexpr(\punnode{\Nlexpratom}, \Tdot, \Tidentifier(\id))) \astarrow + \overname{\LESetField(\astof{\vlexpratom}, \id)}{\vastnode} +} +\end{mathpar} + +\begin{mathpar} +\inferrule[set\_fields]{ + \buildclist[\buildidentity](\vfields) \astarrow \vfieldasts +}{ + { + \begin{array}{r} + \buildlexpratom(\Nlexpr(\punnode{\Nlexpratom}, \Tdot, \Tlbracket, \namednode{\vfields}{\Clist{\Tidentifier}}, \Trbracket)) \astarrow\\ + \overname{\LESetFields(\astof{\vlexpratom}, \vfieldasts)}{\vastnode} + \end{array} + } +} +\end{mathpar} + +\begin{mathpar} +\inferrule[concat]{ + \buildclist[\buildlexpratom](\vlexprs) \astarrow \vlexprasts +}{ + { + \begin{array}{r} + \buildlexpratom(\Nlexpr(\Tlbracket, \namednode{\vlexprs}{\NClist{{\Nlexpratom}}}, \Trbracket)) \astarrow\\ + \overname{\LEConcat(\vlexprasts)}{\vastnode} + \end{array} + } +} +\end{mathpar} + +\section{Discarding Assignment Expressions\label{sec:DiscardingAssignmentExpressions}} +\subsection{Abstract Syntax} +\begin{flalign*} +\lexpr \derives\ & \overtext{\LEDiscard}{\texttt{"-"}} & +\end{flalign*} + +\subsection{Typing} +\subsubsection{TypingRule.LEDiscard\label{sec:TypingRule.LEDiscard}} +\subsubsection{Prose} +All of the following apply: +\begin{itemize} + \item $\vle$ denotes an expression that can be discarded, that is, $\LEDiscard$; + \item $\newle$ is $\vle$. +\end{itemize}\CodeSubsection{\LEDiscardBegin}{\LEDiscardEnd}{../Typing.ml} +\subsubsection{Formally} +\begin{mathpar} +\inferrule{}{ + \annotatelexpr{\tenv, \overname{\LEDiscard}{\vle}, \vte} \typearrow \overname{\LEDiscard}{\newle} +} +\end{mathpar} + +\subsection{Semantics} +\subsubsection{SemanticsRule.LEDiscard\label{sec:SemanticsRule.LEDiscard}} +\subsubsection{Example} +In the specification: +\VerbatimInput{../tests/ASLSemanticsReference.t/SemanticsRule.LEDiscard.asl} +\texttt{- = 42;} does not affect the environment. + +\subsubsection{Prose} +All of the following apply: +\begin{itemize} + \item $\vle$ is a discarding expression, $\LEDiscard$; + \item $\newg$ is $\vg$; + \item $\newenv$ is $\env$. +\end{itemize} +\subsubsection{Formally} +\begin{mathpar} +\inferrule{ + \newg\eqdef\vg\\ + \newenv\eqdef\env +}{ + \evallexpr{\env, \LEDiscard, (\vv, \vg)} \evalarrow \Normal(\newg, \newenv) +} +\end{mathpar} +\CodeSubsection{\EvalLEDiscardBegin}{\EvalLEDiscardEnd}{../Interpreter.ml} + +\section{Variable Assignment Expressions\label{sec:VariableAssignmentExpressions}} +\subsection{Abstract Syntax} +\begin{flalign*} +\lexpr \derives\ & \LEVar(\identifier) & +\end{flalign*} + +\subsection{Typing} +\subsubsection{TypingRule.LEVar\label{sec:TypingRule.LEVar}} +\subsubsection{Prose} +All of the following apply: +\begin{itemize} + \item $\vle$ denotes a left-hand-side variable expression for $\vx$, that is, $\LEVar(\vx)$; + \item One of the following applies (\textsc{local}): + \begin{itemize} + \item $\vx$ is declared in $\tenv$ as a local storage element with type $\tty$ and local declaration keyword $k$; + \item checking that $k$ corresponds to a mutable variable, that is, $\LDKVar$, yields $\True$\ProseTerminateAs{\AssignmentToImmutable}; + \item determining whether $\tty$ \typesatisfies\ $\vte$ in $\tenv$ yields $\True$\ProseOrTypeError; + \item $\newle$ is $\vle$. + \end{itemize} + + \item One of the following applies (\textsc{global}): + \begin{itemize} + \item $\vx$ is declared in $\tenv$ as a global storage element with type $\tty$ and global declaration keyword $k$; + \item checking that $k$ corresponds to a mutable variable, that is, $\GDKVar$, yields $\True$\ProseTerminateAs{\AssignmentToImmutable}; + \item determining whether $\tty$ \typesatisfies\ $\vte$ in $\tenv$ yields $\True$\ProseOrTypeError; + \item $\newle$ is $\vle$. + \end{itemize} + + \item One of the following applies (\textsc{error\_undefined}): + \begin{itemize} + \item $\vx$ is not declared in $\tenv$ as a local storage element nor as a global storage element; + \item the result is a type error $\UndefinedIdentifier$. + \end{itemize} +\end{itemize} +\subsubsection{Formally} +\begin{mathpar} +\inferrule[local]{ + L^\tenv.\localstoragetypes(\id) = (\tty, k)\\ + \checktrans{k = \LDKVar}{\AssignmentToImmutable} \checktransarrow \True \OrTypeError\\\\ + \checktypesat(\tenv, \vte, \tty) \typearrow \True \OrTypeError +}{ + \annotatelexpr{\tenv, \overname{\LEVar(\vx)}{\vle}, \vte} \typearrow \overname{\vle}{\newle} +} +\end{mathpar} + +\begin{mathpar} +\inferrule[global]{ + L^\tenv.\globalstoragetypes(\id) = (\tty, k)\\ + \checktrans{k = \GDKVar}{AssignToImmutable} \checktransarrow \True \OrTypeError\\\\ + \checktypesat(\tenv, \vte, \tty) \typearrow \True \OrTypeError +}{ + \annotatelexpr{\tenv, \overname{\LEVar(\vx)}{\vle}, \vte} \typearrow \overname{\vle}{\newle} +} +\end{mathpar} + +\begin{mathpar} +\inferrule[error\_undefined]{ + L^\tenv.\localstoragetypes(\id) = \bot\\ + L^\tenv.\globalstoragetypes(\id) = \bot +}{ + \annotatelexpr{\tenv, \overname{\LEVar(\vx)}{\vle}, \vte} \typearrow \TypeErrorVal{\UndefinedIdentifier} +} +\end{mathpar}\lrmcomment{ + This is related to \identr{WDGQ}, \identr{GNTS}, \identi{MMKF}, + \identi{DGWJ}, \identi{KKCC} and \identr{LXQZ}. +} +\CodeSubsection{\LEVarBegin}{\LEVarEnd}{../Typing.ml} + +\subsection{Semantics} +\subsubsection{SemanticsRule.LEVar\label{sec:SemanticsRule.LEVar}} +\subsubsection{Example (Local Variable)} +In the specification: +\VerbatimInput{../tests/ASLSemanticsReference.t/SemanticsRule.LELocalVar.asl} +SemanticsRule.LELocalVar is (only) used to assign the value $42$ to the left-hand-side expression +\texttt{x} within \texttt{x = 42;}. + +\subsubsection{Example (Global Variable)} +In the specification: +\VerbatimInput{../tests/ASLSemanticsReference.t/SemanticsRule.LEGlobalVar.asl} +SemanticsRule.LEGlobalVar is (only) used to assign the value $42$ to the left-hand-side expression +\texttt{x} within \texttt{x = 42;}. + +\subsubsection{Prose} +All of the following apply: +\begin{itemize} + \item $\vle$ denotes a variable, $\LEVar(\vx)$; + \item One of the following applies: + \begin{itemize} + \item All of the following apply (\textsc{local}): + \begin{itemize} + \item $\vx$ is locally bound in $\env$; + \item $\newenv$ is $\env$ where $\vx$ is bound to $\vv$ in the local component of the environment. + \end{itemize} + + \item All of the following apply (\textsc{global}): + \begin{itemize} + \item $\vx$ is globally bound in $\env$; + \item $\newenv$ is $\env$ where $\vx$ is bound to $\vv$ in the global component of the environment. + \end{itemize} + \end{itemize} + \item $\newg$ is the ordered composition of $\vg$ and a Write Effect for $\vx$ with the $\asldata$ edge; +\end{itemize} + +\subsubsection{Formally} +\begin{mathpar} +\inferrule[local]{ + \env \eqname (\tenv, \denv)\\ + \vx \in \dom(L^\denv)\\ + \newenv \eqdef (\tenv, (G^\denv, L^\denv[\vx \mapsto \vv]))\\ + \newg \eqdef \ordered{\vg}{\asldata}{\WriteEffect(\vx)} +}{ + \evallexpr{\env, \LEVar(\vx), (\vv, \vg)} \evalarrow \Normal(\newg,\newenv) +} +\end{mathpar} + +\begin{mathpar} +\inferrule[global]{ + \env \eqname (\tenv, \denv)\\ + \vx \in \dom(G^\denv)\\ + \newenv \eqdef(\tenv, (G^\denv[\vx \mapsto \vv], L^\denv))\\ + \newg \eqdef \ordered{\vg}{\asldata}{\WriteEffect(\vx)} +}{ + \evallexpr{\env, \LEVar(\vx), (\vv, \vg)} \evalarrow \Normal(\newg,\newenv) +} +\end{mathpar} +\CodeSubsection{\EvalLEVarBegin}{\EvalLEVarEnd}{../Interpreter.ml} + +\section{Multi-assignment Expressions\label{sec:MultiAssignmentExpressions}} +\subsection{Abstract Syntax} +\begin{flalign*} +\lexpr \derives\ & \LEDestructuring(\lexpr^*) & +\end{flalign*} + +\subsection{Typing} +\subsubsection{TypingRule.LEDestructuring\label{sec:TypingRule.LEDestructuring}} +\subsubsection{Prose} +All of the following apply: +\begin{itemize} + \item $\vle$ denotes a tuple of left-hand-side expressions $\les$, that is, $\LEDestructuring(\les)$; + \item $\les$ is a list $\ve_{1..k}$; + \item checking whether $\vte$ is a tuple type yields $\True$\ProseTerminateAs{\ExpectedTupleType}; + \item $\vte$ is a tuple type over the list of types $\tys$, that is, $\TTuple(\tys)$; + \item determining whether $\les$ and $\subtys$ have the same length yields $\True$\ProseTerminateAs{\LengthsMismatch}; + \item $\subtys$ is the list of types $\vt_{1..k}$; + \item annotating the left-hand-side expression $\ve_i$ with the type $\vt_i$, for $i=1..k$, yields $\vep_i$\ProseOrTypeError; + \item the list of expressions $\lesp$ is $\vep_i$, for $i=1..k$; + \item $\newle$ is the list of left-hand-side expressions $\lesp$, that is, $\LEDestructuring(\lesp)$. +\end{itemize} +\subsubsection{Formally} +\begin{mathpar} +\inferrule{ + \les \eqname [\ve_{1..k}]\\ + \checktrans{\astlabel(\vte) = \TTuple}{\ExpectedTupleType} \checktransarrow \True \OrTypeError\\\\ + \vte \eqname \TTuple(\tys)\\ + \equallength(\les, \tys) \typearrow \vb\\ + \checktrans{\vb}{\LengthsMismatch} \checktransarrow \True \OrTypeError\\\\ + \tys \eqname [\vt_{1..k}]\\ + i=1..k: \annotatelexpr{\tenv, \ve_i,\vt_i} \typearrow \vep_i \OrTypeError\\\\ + \lesp \eqname [i=1..k: \vep_i] +}{ + \annotatelexpr{\tenv, \overname{\LEDestructuring(\les)}{\vle}, \vte} \typearrow \overname{\LEDestructuring(\lesp)}{\newle} +} +\end{mathpar} +\CodeSubsection{\LEDestructuringBegin}{\LEDestructuringEnd}{../Typing.ml} + +\subsection{Semantics} +\subsubsection{SemanticsRule.LEDestructuring\label{sec:SemanticsRule.LEDestructuring}} +\subsubsection{Example} +In the specification: +\VerbatimInput{../tests/ASLSemanticsReference.t/SemanticsRule.LEDestructuring.asl} +\texttt{(x, y) = (3, 42)} binds \texttt{x} to $\nvint(3)$ and \texttt{y} to +$\nvint(42)$ in the environment where \texttt{x} is bound to $\nvint(42)$ and \texttt{y} is bound to $\nvint(3)$. + +\subsubsection{Prose} +All of the following apply: +\begin{itemize} + \item $\vle$ denotes a list of left-hand-side expressions, $\LEDestructuring(\vlelist)$; + \item $\vlelist$ is the list of expressions $\vle_{1..k}$; + \item getting the values from the native vector $\vv$ at each index $i=1..k$ + results in $\vv_{i=1..k}$; + \item $\nmonads$ is the list of pairs consisting of $\vv_i$ and $\vg$ for $i=1..k$; + \item evaluating the multi-assignment between $\vlelist$ and the list $\nmonads$ + in $\env$ achieves the effects of assigning each value to the respective + subexpressions, resulting in the output configuration $C$. +\end{itemize} +\subsubsection{Formally} +\begin{mathpar} +\inferrule{ + \vlelist \eqname [\vle_{1..k}]\\ + i=1..k: \getindex(i, \vv) \evalarrow \vv_i\\ + \nmonads \eqdef [i=1..k: (\vv_i, \vg)]\\ + \evalmultiassignment(\env, \vlelist, \nmonads) \evalarrow C +}{ + \evallexpr{\env, \LEDestructuring(\vlelist), (\vv, \vg)} \evalarrow C +} +\end{mathpar} +\CodeSubsection{\EvalLEDestructuringBegin}{\EvalLEDestructuringEnd}{../Interpreter.ml} + +\subsubsection{SemanticsRule.LEMultiAssign\label{sec:SemanticsRuleLEMultiAssign}} +\subsubsection{Prose} +The helper relation +\hypertarget{def-evalmultiassign}{} +\[ + \evalmultiassignment(\overname{\envs}{\env} \aslsep \overname{\expr^*}{\vlelist} \aslsep \overname{(\vals \times \XGraphs)^*}{\vmlist}) \;\aslrel\; + \Normal(\overname{\XGraphs}{\newg} \aslsep \overname{\envs}{\newenv}) \cup + \overname{\TThrowing}{\ThrowingConfig} \cup \overname{\TError}{\ErrorConfig} +\] +evaluates multi-assignments. +That is, the simultaneous assignment of the list of value-execution graph pairs $\vmlist$ +to the corresponding list of left-hand side expressions $\vlelist$, in the environment $\env$. +The result is either the execution graph $\vg$ and new environment $\newenv$ or an abnormal configuration. + +\subsubsection{Formally} +\begin{mathpar} +\inferrule[empty]{} +{ + \evalmultiassignment(\env, \emptylist, \emptylist) \evalarrow \Normal(\emptygraph, \env) +} +\and +\inferrule[nonempty]{ + \vlelist \eqname [\vle] \concat \vlelistone\\ + \vmlist \eqname [\vm] \concat \vmlistone\\ + \evallexpr{\env, \vle, \vm} \evalarrow \Normal(\envone, \vgone) \OrAbnormal\\ + \evalmultiassignment(\envone, \vlelistone, \vmlistone) \evalarrow \Normal(\newenv, \vgtwo) \OrAbnormal\\ + \newg \eqdef \ordered{\vgone}{\aslpo}{\vgtwo} +}{ + \evalmultiassignment(\env, \vlelist, \vmlist) \evalarrow \Normal(\newg, \newenv) +} +\end{mathpar} +Notice that this rule is only defined when the lists $\vlelist$ and $\vmlist$ have the same length. +To see this, notice that +to form a derivation tree, we must employ the \textsc{nonempty} case, which ensures both lists +have at least one element and shortens the lengths of both lists by one, +until both lists become empty +which is when the \textsc{empty} axiom case is used. + +\section{Array Assignment Expressions\label{sec:ArrayAssignmentExpressions}} +\subsection{Abstract Syntax} +\begin{flalign*} +\lexpr \derives\ & \LESetArray(\lexpr, \expr) & +\end{flalign*} + +\subsection{Typing} +\subsubsection{TypingRule.LESetArray\label{sec:TypingRule.LESetArray}} +\subsubsection{Prose} +All of the following apply: +\begin{itemize} + \item $\vle$ denotes the slicing of a left-hand-side expression $\vleone$ by the slices $\slices$, that is, $\LESlice(\vleone, \slices)$; + \item annotating the right-hand-side expression corresponding to $\vleone$ in $\tenv$ yields \\ $(\vtleone, \Ignore)$\ProseOrTypeError; + \item obtaining the \structure\ of $\vtleone$ in $\tenv$ yields an array type of size $\size$ and element type $\vt$, that is, $\TArray(\size, \vt)$\ProseOrTypeError; + \item annotating the left-hand-side expression $\vleone$ with type $\vtleone$ in $\tenv$ yields $\vletwo$\ProseOrTypeError; + \item determining that $\vte$ \typesatisfies\ $\vt$ in $\tenv$ yields $\True$\ProseOrTypeError; + \item determining whether $\slices$ is a single slice with index expression $\eindex$ yields $\True$\ProseOrTypeError; + \item annotating the index expression $\eindex$ in $\tenv$ yields $(\tindexp, \eindexp)$\ProseOrTypeError; + \item determining the array length type of $\size$ in $\tenv$ (via $\typeofarraylength$) yields $\wantedtindex$; + \item determining whether $\tindexp$ \typesatisfies\ $\wantedtindex$ in $\tenv$ yields \\ + $\True$\ProseOrTypeError; + \item $\newle$ is an access to array $\vletwo$ at index $\eindexp$, that is, \\ $\LESetArray(\vletwo, \eindexp)$. +\end{itemize} +\subsubsection{Formally} +\begin{mathpar} +\inferrule{ + \annotateexpr{\tenv, \torexpr(\vleone)} \typearrow (\vtleone, \Ignore) \OrTypeError\\\\ + \tstruct(\tenv, \vtleone) \typearrow \TArray(\size, \vt) \OrTypeError\\\\ + \annotatelexpr{\tenv, \vleone, \vtleone} \typearrow \vletwo \OrTypeError\\\\ + \checktypesat(\tenv, \vte, \vt) \typearrow \True \OrTypeError\\\\ + \checktrans{\listlen{\slices} = 1}{ArraySliceShouldBeSingleIndex} \checktransarrow \True \OrTypeError\\\\ + \slices \eqname [\vs]\\ + \checktrans{\astlabel(\vs) = \SliceSingle}{ArraySliceShouldBeSingleIndex} \checktransarrow \True \OrTypeError\\\\ + \vs \eqname \SliceSingle(\eindex)\\ + \annotateexpr{\tenv, \eindex} \typearrow (\tindexp, \eindexp) \OrTypeError\\\\ + \typeofarraylength(\tenv, \size) \typearrow \wantedtindex\\ + \checktypesat(\tenv, \tindexp, \wantedtindex) \typearrow \True \OrTypeError\\\\ + \newle \eqdef \LESetArray(\vletwo, \eindexp) +}{ + \annotatelexpr{\tenv, \overname{\LESlice(\vleone, \slices)}{\vle}, \vte} \typearrow \newle +} +\end{mathpar} +\CodeSubsection{\LESetArrayBegin}{\LESetArrayEnd}{../Typing.ml} + +\subsection{Semantics} +\subsubsection{SemanticsRule.LESetArray\label{sec:SemanticsRule.LESetArray}} +\subsubsection{Example} +The specification: +\VerbatimInput{../tests/ASLSemanticsReference.t/SemanticsRule.LESetArray.asl} +binds the third element of \texttt{my\_array} to the value \texttt{53}. + +\subsubsection{Prose} +All of the following apply: +\begin{itemize} + \item $\vle$ denotes an array update expression, $\LESetArray(\rearray, \eindex)$; + \item evaluating the right-hand-side expression corresponding to $\rearray$ in $\env$ + is \Normal(\rmarray, \envone)\ProseOrAbnormal; + \item evaluating $\eindex$ in $\envone$ is \Normal(\mindex, \envtwo)\ProseOrAbnormal; + \item $\mindex$ consists of the native integer $\vindex$ and the execution graph $\vgone$; + \item $\vindex$ is the native integer for $\vi$; + \item $\rmarray$ consists of the native vector $\rvarray$ and the execution graph $\vgtwo$; + \item setting the value $\vv$ at index $\vi$ of $\rvarray$ is the native vector $\vvone$; + \item $\vmone$ is the pair consisting of $\vvone$ and the parallel composition of $\vgone$ and $\vgtwo$; + \item the steps so far computed the updated array, but have not assigned it to the variable + bound to the array given by $\rearray$, which is achieved next. + Evaluating the left-hand-side expression $\rearray$ in an environment $\envtwo$ with $\vmone$ + is the output configuration $C$. +\end{itemize} +\subsubsection{Formally} +\begin{mathpar} +\inferrule{ + \evalexpr{\env, \torexpr(\rearray)} \evalarrow \Normal(\rmarray, \envone) \OrAbnormal\\ + \evalexpr{\envone, \eindex} \evalarrow \Normal(\mindex, \envtwo) \OrAbnormal\\ + \mindex \eqname (\vindex, \vgone)\\ + \vindex \eqname \nvint(\vi)\\ + \rmarray \eqname (\rvarray, \vgtwo)\\ + \setindex(\vi, \vv, \rvarray) \evalarrow \vvone\\ + \vmone \eqdef (\vvone, \vgone \parallelcomp \vgtwo)\\ + \evallexpr{\envtwo, \rearray, \vmone} \evalarrow C +}{ + \evallexpr{\env, \LESetArray(\rearray, \eindex), (\vv, \vg)} \evalarrow C +} +\end{mathpar} +\CodeSubsection{\EvalLESetArrayBegin}{\EvalLESetArrayEnd}{../Interpreter.ml} + +\subsubsection{Comments} +\lrmcomment{This is related to \identr{WHRS}:} +If the declared type of the \rhsexpression\ of a setter has the structure of a +bitvector or a type with fields, then if a bitslice or field selection is +applied to a setter invocation, then the assignment to that bitslice is +implemented using the following Read-Modify-Write (RMW) behavior: +\begin{itemize} +\item invoking the getter of the same name as the setter, with the same actual +arguments as the setter invocation +\item performing the assignment to the bitslice or field of the result of the +getter invocation +\item invoking the setter to assign the resulting value +\end{itemize} + +We note that the index is guaranteed by the type-checker to be within the array bounds +via \secref{TypingRule.LESetArray}. + +\section{Bitvector Slice Assignment Expressions\label{sec:BitvectorSliceAssignmentExpressions}} +\subsection{Abstract Syntax} +\begin{flalign*} +\lexpr \derives\ & \LESlice(\lexpr, \slice^*) & +\end{flalign*} + +\subsection{Typing} +\subsubsection{TypingRule.LESlice\label{sec:TypingRule.LESlice}} +\subsubsection{Prose} +All of the following apply: +\begin{itemize} + \item $\vle$ denotes the slicing of a left-hand-side expression $\vleone$ by the slices $\slices$, that is, $\LESlice(\vleone, \slices)$; + \item annotating the right-hand-side expression corresponding to $\vleone$ in $\tenv$ yields \\ + $(\vtleone, \Ignore)$\ProseOrTypeError; + \item $\vtleone$ is a bitvector type; + \item annotating the left-hand-side expression $\vleone$ in $\tenv$ yields $\vletwo$\ProseOrTypeError; + \item obtaining the width of the slices $\slices$ in $\tenv$ and simplifying them yields $\vwidth$; + \item $\vt$ is the bitvector type of width $\width$ and empty list of bitfields; + \item checking whether $\vte$ \typesatisfies\ $\vt$ yields $\True$\ProseOrTypeError; + \item annotating $\slices$ in $\tenv$ yields $\slicestwo$\ProseOrTypeError; + \item checking that the slices $\slicestwo$ are all disjoint yields $\True$\ProseOrTypeError; + \item $\newle$ is the slicing of $\vletwo$ by $\slicestwo$, that is, $\LESlice(\vletwo, \slicestwo)$. +\end{itemize} +\subsubsection{Formally} +\begin{mathpar} +\inferrule{ + \annotateexpr{\tenv, \torexpr(\vleone)} \typearrow (\vtleone, \Ignore)\\ + \tstruct(\tenv, \vtleone) \typearrow \structtleone \OrTypeError\\\\ + \astlabel(\structtleone) = \TBits\\ + \annotatelexpr{\tenv, \vleone, \vtleone} \typearrow \vletwo\\ + \sliceswidth(\tenv, \slices) \typearrow \widthp\\ + \normalize(\tenv, \widthp) \typearrow \vwidth\\ + \vt \eqdef \TBits(\vwidth, \emptylist)\\ + \checktypesat(\tenv, \vte, \vt) \typearrow \True \OrTypeError\\\\ + \annotateslices(\tenv, \slices) \typearrow \slicestwo \OrTypeError\\\\ + \checkdisjointslices(\tenv, \slicestwo) \typearrow \True \OrTypeError\\\\ + \newle \eqdef \LESlice(\vletwo, \slicestwo) +}{ + \annotatelexpr{\tenv, \overname{\LESlice(\vleone, \slices)}{\vle}, \vte} \typearrow \newle +} +\end{mathpar} +\CodeSubsection{\LESliceBegin}{\LESliceEnd}{../Typing.ml} + +\subsection{Semantics} +\subsubsection{SemanticsRule.LESlice\label{sec:SemanticsRule.LESlice}} +\subsubsection{Example} +In the specification: +\VerbatimInput{../tests/ASLSemanticsReference.t/SemanticsRule.LESlice.asl} +The assignment \texttt{x[3:0] = '0000'} binds \texttt{x} to $\nvbitvector(11110000)$ +via the rule SemanticsRule.LESlice.asl +in the environment where \texttt{x} is bound to $\nvbitvector(11111111)$. + +\subsubsection{Prose} +All of the following apply: +\begin{itemize} + \item $\vle$ denotes a left-hand-side slicing expression, $\LESlice(\ebv, \slices)$; + \item evaluating the right-hand-side expression that corresponds to $\ebv$ + (given by applying $\torexpr$ to $\ebv$) in $\env$ + is $\Normal(\mbv,\envone)$\ProseOrAbnormal; + \item evaluating $\slices$ in $\envone$ is $\Normal(\mpositions, \envtwo)$\ProseOrAbnormal; + \item $\mpositions$ consists of the execution graph $\vgone$ and the list of indices $\positions$; + \item $\mbv$ consists of the native bitvector $\vbv$ and the execution graph $\vgtwo$; + \item writing to the bitvector $\vbv$ at indices $\positions$ using the values from $\vv$ + results in the updated native bitvector $\vvone$\ProseOrError; + \item $\vgthree$ is the parallel composition of $\vg$, $\vgone$, and $\vgtwo$; + \item $\newmbv$ is a pair consisting of $\vvone$ and the execution graph $\vgthree$; + \item the steps so far computed the updated bitvector, but have not assigned it to the + variable bound to the bitvector given by $\ebv$, which is achieved next. + Evaluating the left-hand-side expression $\ebv$ with + $\newmbv$ in an environment $\envtwo$ is the output configuration $C$, +\end{itemize} +\subsubsection{Formally} +\begin{mathpar} +\inferrule{ + \evalexpr{\env, \torexpr(\ebv)} \evalarrow \Normal(\mbv,\envone) \OrAbnormal\\ + \evalslices(\envone, \slices) \evalarrow \Normal(\mpositions, \envtwo) \OrAbnormal\\ + \mpositions \eqname (\positions, \vgone)\\ + \mbv \eqname (\vbv, \vgtwo)\\\\ + \writetobitvector(\positions, \vv, \vbv) \evalarrow \vvone \OrDynError\\\\ + \vgthree \eqdef \vg \parallelcomp \vgone \parallelcomp \vgtwo\\ + \newmbv \eqdef (\vvone, \vgthree)\\ + \evallexpr{\envtwo, \ebv, \newmbv} \evalarrow C +}{ + \evallexpr{\envtwo, \LESlice(\ebv, \slices), (\vv, \vg)} \evalarrow C +} +\end{mathpar} +\CodeSubsection{\EvalLESliceBegin}{\EvalLESliceEnd}{../Interpreter.ml} +\subsubsection{Comments} +\lrmcomment{This is related to \identr{WHRS}:} + +If the declared type of the \rhsexpression\ of a setter has the structure of a +bitvector or a type with fields, then if a bitslice or field selection is +applied to a setter invocation, then the assignment to that bitslice is +implemented using the following Read-Modify-Write (RMW) behavior: +\begin{itemize} +\item invoking the getter of the same name as the setter, with the same actual +arguments as the setter invocation +\item performing the assignment to the bitslice or field of the result of the +getter invocation +\item invoking the setter to assign the resulting value +\end{itemize} + +\section{Structured Type Field Assignment Expressions\label{sec:StructuredTypeFieldAssignmentExpressions}} +\subsection{Abstract Syntax} +\begin{flalign*} +\lexpr \derives\ & \LESetField(\lexpr, \identifier) & \\ + |\ & \LESetFields(\lexpr, \identifier^*) & +\end{flalign*} + +\subsection{Typing} +\subsubsection{TypingRule.LESetBadField\label{sec:TypingRule.LESetBadField}} +\subsubsection{Prose} +All of the following apply: +\begin{itemize} + \item $\vle$ denotes the access to the field named $\field$ in $\vleone$, that is, \\ $\LESetField(\vleone, \field)$; + \item annotating the right-hand-side expression corresponding to $\vleone$ in $\tenv$ yields \\ $(\vtleone, \Ignore)$\ProseOrTypeError; + \item annotating the left-hand-side expression $\vleone$ in $\tenv$ yields $\vletwo$\ProseOrTypeError; + \item obtaining the \structure\ of $\vtleone$ in $\tenv$ yields a type $\vt$\ProseOrTypeError; + \item $\vt$ is neither a \structuredtype\ nor a bitvector type; + \item the result is an error indicating that the type of $\vle$ conflicts with the requirements of a field access expression. +\end{itemize} +\subsubsection{Formally} +\begin{mathpar} +\inferrule{ + \annotateexpr{\tenv, \torexpr(\vleone)} \typearrow (\vtleone, \Ignore) \OrTypeError\\\\ + \annotatelexpr{\tenv, \vleone, \vtleone} \typearrow \vletwo \OrTypeError\\\\ + \tstruct(\tenv, \vtleone) \typearrow \vt \OrTypeError\\\\ + \astlabel(\vt) \not\in \{\TException, \TRecord, \TBits\} +}{ + \annotatelexpr{\tenv, \overname{\LESetField(\vleone, \field)}{\vle}, \vte} \typearrow \TypeErrorVal{TypeConflict} +} +\end{mathpar} +\CodeSubsection{\LESetBadFieldBegin}{\LESetBadFieldEnd}{../Typing.ml} + +\section{Bitfield Assignment Expressions\label{sec:BitfieldAssignmentExpressions}} +\subsection{Abstract Syntax} +\begin{flalign*} +\lexpr \derives\ & \LESlice(\lexpr, \slice^*) & +\end{flalign*} + +\subsection{Typing} +\subsubsection{TypingRule.LESetBitField\label{sec:TypingRule.LESetBitField}} +\subsubsection{Prose} +All of the following apply: +\begin{itemize} + \item $\vle$ denotes the access to the field named $\field$ in $\vleone$, that is, \\ $\LESetField(\vleone, \field)$; + \item annotating the right-hand-side expression corresponding to $\vleone$ in $\tenv$ yields \\ $(\vtleone, \Ignore)$\ProseOrTypeError; + \item annotating the left-hand-side expression $\vleone$ in $\tenv$ yields $\vletwo$\ProseOrTypeError; + \item obtaining the \structure\ of $\vtleone$ in $\tenv$ yields a bitvector type with with bitfields $\bitfields$\ProseOrTypeError; + \item One of the following applies: + \begin{itemize} + \item All of the following applies (\textsc{error\_missing\_field}): + \begin{itemize} + \item applying $\findbitfieldopt$ to $\bitfields$ and $\vfield$ yields $\None$, meaning the field is not declared + in $\vtleone$; + \item the result is a type error $\MissingField$. + \end{itemize} + + \item All of the following applies (\textsc{field\_simple}): + \begin{itemize} + \item applying $\findbitfieldopt$ to $\bitfields$ and $\vfield$ yields a bitfield with corresponding slices $\slices$, + that is, $\BitFieldSimple(\Ignore, \slices)$; + \item $\vw$ is the width of $\slices$; + \item $\vt$ is defined as the bitvector type of width $\vw$ and empty list of bitfields, that is, $\TBits(\vw, \emptylist)$; + \item checking whether$\vte$ \typesatisfies\ $\vt$ in $\tenv$ yields $\True$\ProseOrTypeError; + \item $\vletwo$ is defined as the slicing of $\vleone$ by $\slices$, that is, \\ $\LESlice(\vleone, \slices)$; + \item annotating the left-hand-side expression $\vletwo$ in $\tenv$ yields $\newle$\ProseOrTypeError. + \end{itemize} + + \item All of the following applies (\textsc{field\_nested}): + \begin{itemize} + \item applying $\findbitfieldopt$ to $\bitfields$ and $\vfield$ yields a nested bitfield with corresponding + slices $\slices$ and list of bitfields $\bitfieldsp$, that is, \\ $\BitFieldNested(\Ignore, \slices, \bitfieldsp)$; + \item $\vw$ is the width of $\slices$; + \item $\vt$ is defined as the bitvector type of width $\vw$ and list of bitfields $\bitfieldsp$, that is, $\TBits(\vw, \bitfieldsp)$; + \item checking whether$\vte$ \typesatisfies\ $\vt$ in $\tenv$ yields $\True$\ProseOrTypeError; + \item $\vlethree$ is defined as the slicing of $\vleone$ by $\slices$, that is, \\ $\LESlice(\vleone, \slices)$; + \item annotating the left-hand-side expression $\vlethree$ in $\tenv$ yields $\newle$\ProseOrTypeError. + \end{itemize} + + \item All of the following applies (\textsc{field\_typed}): + \begin{itemize} + \item applying $\findbitfieldopt$ to $\bitfields$ and $\vfield$ yields a typed bitfield with corresponding + slices $\slices$ and a type $\vt$, that is, \\ $\BitFieldType(\Ignore, \vslices, \vt)$; + \item $\vw$ is the width of $\slices$; + \item $\vtp$ is defined as the bitvector type of width $\vw$ and an empty list of bitfields, that is, $\TBits(\vw , \emptylist)$; + \item checking whether $\vtp$ \typesatisfies\ $\vt$ in $\tenv$ yields $\True$\ProseOrTypeError; + \item checking whether$\vte$ \typesatisfies\ $\vt$ in $\tenv$ yields $\True$\ProseOrTypeError; + \item $\vletwo$ is defined as the slicing of $\vleone$ by $\slices$, that is, \\ $\LESlice(\vleone, \slices)$; + \item annotating the left-hand-side expression $\vletwo$ in $\tenv$ yields $\newle$\ProseOrTypeError. + \end{itemize} + \end{itemize} +\end{itemize} +\subsubsection{Formally} +\begin{mathpar} +\inferrule[error\_missing\_field]{ + \annotateexpr{\tenv, \torexpr(\vleone)} \typearrow (\vtleone, \Ignore) \OrTypeError\\\\ + \annotatelexpr{\tenv, \vleone, \vtleone} \typearrow \vletwo \OrTypeError\\\\ + \tstruct(\tenv, \vtleone) \typearrow \TBits(\Ignore, \bitfields) \OrTypeError\\\\ + \commonprefixline\\\\ + \findbitfieldopt(\bitfields, \field) \typearrow \None\ +}{ + \annotatelexpr{\tenv, \overname{\LESetField(\vleone, \field)}{\vle}, \vte} \typearrow \TypeErrorVal{\MissingField} +} +\end{mathpar} + +\begin{mathpar} +\inferrule[field\_simple]{ + \annotateexpr{\tenv, \torexpr(\vleone)} \typearrow (\vtleone, \Ignore) \OrTypeError\\\\ + \annotatelexpr{\tenv, \vleone, \vtleone} \typearrow \vletwo \OrTypeError\\\\ + \tstruct(\tenv, \vtleone) \typearrow \TBits(\Ignore, \bitfields) \OrTypeError\\\\ + \commonprefixline\\\\ + \findbitfieldopt(\bitfields, \field) \typearrow \langle \BitFieldSimple(\Ignore, \slices) \rangle\\ + \sliceswidth(\tenv, \vslices) \typearrow \vw\\ + \vt \eqdef \TBits(\vw, \emptylist)\\\\ + \commonsuffixline\\\\ + \checktypesat(\tenv, \vte, \vt) \typearrow \True \OrTypeError\\\\ + \vletwo \eqdef \LESlice(\vleone, \slices)\\ + \annotatelexpr{\tenv, \vletwo, \vte} \typearrow \newle \OrTypeError +}{ + \annotatelexpr{\tenv, \overname{\LESetField(\vleone, \field)}{\vle}, \vte} \typearrow \newle +} +\end{mathpar} + +\begin{mathpar} +\inferrule[field\_nested]{ + \annotateexpr{\tenv, \torexpr(\vleone)} \typearrow (\vtleone, \Ignore) \OrTypeError\\\\ + \annotatelexpr{\tenv, \vleone, \vtleone} \typearrow \vletwo \OrTypeError\\\\ + \tstruct(\tenv, \vtleone) \typearrow \TBits(\Ignore, \bitfields) \OrTypeError\\\\ + \commonprefixline\\\\ + \findbitfieldopt(\bitfields, \field) \typearrow \langle \BitFieldNested(\Ignore, \slices, \bitfieldsp) \rangle\\ + \sliceswidth(\tenv, \vslices) \typearrow \vw\\ + \vt \eqdef \TBits(\vw, \bitfieldsp)\\\\ + \commonsuffixline\\\\ + \checktypesat(\tenv, \vte, \vt) \typearrow \True \OrTypeError\\\\ + \vletwo \eqdef \LESlice(\vleone, \slices)\\ + \annotatelexpr{\tenv, \vletwo, \vte} \typearrow \newle \OrTypeError +}{ + \annotatelexpr{\tenv, \overname{\LESetField(\vleone, \field)}{\vle}, \vte} \typearrow \newle +} +\end{mathpar} + +\begin{mathpar} +\inferrule[field\_typed]{ + \annotateexpr{\tenv, \torexpr(\vleone)} \typearrow (\vtleone, \Ignore) \OrTypeError\\\\ + \annotatelexpr{\tenv, \vleone, \vtleone} \typearrow \vletwo \OrTypeError\\\\ + \tstruct(\tenv, \vtleone) \typearrow \TBits(\Ignore, \bitfields) \OrTypeError\\\\ + \commonprefixline\\\\ + \findbitfieldopt(\bitfields, \field) \typearrow \langle \BitFieldType(\Ignore, \vslices, \vt) \rangle\\ + \sliceswidth(\tenv, \vslices) \typearrow \vw\\ + \vtp \eqdef \TBits(\vw , \emptylist)\\ + \checktypesat(\tenv, \vtp, \vt) \typearrow \True \OrTypeError\\\\ + \commonsuffixline\\\\ + \checktypesat(\tenv, \vte, \vt) \typearrow \True \OrTypeError\\\\ + \vletwo \eqdef \LESlice(\vleone, \slices)\\ + \annotatelexpr{\tenv, \vletwo, \vte} \typearrow \newle \OrTypeError +}{ + \annotatelexpr{\tenv, \overname{\LESetField(\vleone, \field)}{\vle}, \vte} \typearrow \newle +} +\end{mathpar} + +\subsubsection{Semantics} +The semantics for assigning to individual bitvector bitfields is covered by \nameref{sec:SemanticsRule.LESlice} +as the type system transforms the \untypedast\ for assigning to an individual bitfield into an $\LESlice$ \typedast. + +\subsubsection{TypingRule.LESetStructuredField\label{sec:TypingRule.LESetStructuredField}} +\subsubsection{Prose} +All of the following apply: +\begin{itemize} + \item $\vle$ denotes the access to the field named \texttt{field} in $\vleone$; + \item annotating the right-hand-side expression corresponding to $\vleone$ in $\tenv$ yields \\ $(\vtleone, \Ignore)$\ProseOrTypeError; + \item annotating the left-hand-side expression $\vleone$ with type $\vtleone$ in $\tenv$ yields $\vletwo$\ProseOrTypeError; + \item obtaining the \structure\ of $\vtleone$ in $\tenv$ yields a \structuredtype\ with fields \\ + $\fields$\ProseOrTypeError; + \item checking that there exists a type associated with the field $\field$ in $\fields$ $\True$ \ProseTerminateAs{\MissingField}; + \item the type associated with the field $\field$ in $\fields$ is $\vt$; + \item determining whether $\vte$ \typesatisfies\ $\vt$ yields $\True$\ProseOrTypeError; + \item $\newle$ is the access to the field $\field$ in $\vletwo$, that is, $\LESetField(\vletwo, \field)$. +\end{itemize} +\subsubsection{Formally} +\begin{mathpar} +\inferrule{ + \annotateexpr{\tenv, \torexpr(\vleone)} \typearrow (\vtleone, \Ignore) \OrTypeError\\\\ + \annotatelexpr{\tenv, \vleone, \vtleone} \typearrow \vletwo \OrTypeError\\\\ + \tstruct(\tenv, \vtleone) \typearrow L(\fields) \OrTypeError\\\\ + L \in \{\TException, \TRecord\}\\ + \assocopt(\fields, \field) \typearrow \tyopt\\ + \checktrans{\tyopt \neq \None}{\MissingField} \checktransarrow \True \OrTypeError\\\\ + \tyopt \eqname \langle\vt\rangle\\ + \checktypesat(\tenv, \vte, \vt) \typearrow \True \OrTypeError\\\\ + \newle \eqdef \LESetField(\vletwo, \field) +}{ + \annotatelexpr{\tenv, \overname{\LESetField(\vleone, \field)}{\vle}, \vte} \typearrow \newle +} +\end{mathpar} +\CodeSubsection{\LESetStructuredFieldBegin}{\LESetStructuredFieldEnd}{../Typing.ml} + +\subsection{Semantics} +\hypertarget{SemanticsRule.LESetField}{} +\subsubsection{SemanticsRule.LESetField\label{sec:SemanticsRule.LESetField}} +\subsubsection{Example} +In the specification: +\VerbatimInput{../tests/ASLSemanticsReference.t/SemanticsRule.LESetField.asl} +\texttt{my\_record.a = 42;} binds \texttt{my\_record} to \texttt{\{a: 42, b: 100\}} in the environment where \texttt{my\_record} is bound to \texttt{\{a: 3, b: 100\}}. + +\subsubsection{Prose} +All of the following apply: +\begin{itemize} + \item $\vle$ denotes a field update expression, $\LESetField(\rerecord, \fieldname)$; + \item evaluating the right-hand-side expression corresponding to $\rerecord$ + in $\env$ is $\Normal(\rmrecord, \envone)$\ProseOrAbnormal; + \item $\rmrecord$ is a pair consisting of the native record $\rvrecord$ and + the execution graph $\vgone$; + \item setting the field $\fieldname$ in the native record $\rvrecord$ to $\vv$ + is the updated native record $\vvone$; + \item $\vmone$ is the pair consisting of the native vector $\vvone$ and the + execution graph that is, the parallel composition of $\vg$ and $\vgone$; + \item the steps so far computed the updated record, but have not assigned it to + the variable holding the record given by $\record$, which is achieved next. + Evaluating the left-hand-side expression $\rerecord$ in an environment $\envone$ with $\vmone$ + is the output configuration $C$. +\end{itemize} +\subsubsection{Formally} +\begin{mathpar} +\inferrule{ + \evalexpr{\env, \torexpr(\rerecord)} \evalarrow \Normal(\rmrecord, \envone) \OrAbnormal\\ + \rmrecord \eqname (\rvrecord, \vgone)\\ + \setfield(\fieldname, \vv, \rvrecord) \evalarrow \vvone\\ + \vmone \eqdef (\vvone, \vg \parallelcomp \vgone)\\ + \evallexpr{\env1, \rerecord, \vmone} \evalarrow C +}{ + \evallexpr{\env, \LESetField(\rerecord, \fieldname), (\vv, \vg)} \evalarrow C +} +\end{mathpar} +\CodeSubsection{\EvalLESetFieldBegin}{\EvalLESetFieldEnd}{../Interpreter.ml} + +\subsubsection{Comments} +We note that the type-checker guarantees that $\fieldname$ exists in the record given by $\record$ +via \nameref{sec:TypingRule.LESetStructuredField}. + +\lrmcomment{This is related to \identr{WHRS}:} +If the declared type of the \rhsexpression\ of a setter has the structure of a +bitvector or a type with fields, then if a bitslice or field selection is +applied to a setter invocation, then the assignment to that bitslice is +implemented using the following Read-Modify-Write (RMW) behavior: +\begin{itemize} + \item invoking the getter of the same name as the setter, with the same actual + arguments as the setter invocation + \item performing the assignment to the bitslice or field of the result of the + getter invocation + \item invoking the setter to assign the resulting value +\end{itemize} + +\section{Multi-slice Assignment Expressions\label{sec:MultiSliceAssignmentExpressions}} +\subsection{Abstract Syntax} +\begin{flalign*} +\lexpr \derives\ & \LEConcat(\lexpr^+) & +\end{flalign*} + +\subsection{Typing} +\subsubsection{TypingRule.LEConcat\label{sec:TypingRule.LEConcat}} +\subsubsection{Prose} +All of the following apply: +\begin{itemize} + \item $\vle$ denotes the concatenation of left-hand-side expressions $\les$, that is, \\ $\LEConcat(\les, \Ignore)$; + \item annotating the right-hand-side expression corresponding to $\vle$ in $\tenv$ yields \\ $(\vteeq, \Ignore)$\ProseOrTypeError; + \item checking whether the bitwidth of $\vteeq$ equals the bitwidth of $\vte$ in $\tenv$ yields $\True$\ProseOrTypeError; + \item $\les$ is the list of left-hand-side expressions $\vle_i$, for $i=1..k$; + \item annotating each left-hand-side expression $\vle_i$ as a bitvector-typed expression (via $\annotatelebits$) + yields the annotated left-hand-side expression $\vleone_i$ and corresponding bitwidth $\width_i$, for $i=1..k$; + \item $\lesone$ is defined as the list $\vleone_{1..k}$; + \item $\widths$ is defined as the list $\width_{1..k}$; + \item $\newle$ is the concatenation of left-hand-side expressions $\lesone$ with corresponding list of widths $\widths$. +\end{itemize} +\subsubsection{Formally} +\begin{mathpar} +\inferrule{ + \vle \eqname \LEConcat(\les, \Ignore)\\ + \annotateexpr{\tenv, \torexpr(\vle)} \typearrow (\vteeq, \Ignore) \OrTypeError\\\\ + \checkbitsequalwidth(\tenv, \vteeq, \vte) \typearrow \True \OrTypeError\\\\ + \les \eqname \vle_{1..k}\\ + i=1..k: \annotatelebits(\tenv, \vle_i) \typearrow (\vleone_i, \width_i) \OrTypeError\\\\ + \lesone \eqdef \vleone_{1..k}\\ + \widths \eqdef \width_{1..k} +}{ + \annotatelexpr{\tenv, \vle, \vte} \typearrow \overname{\LEConcat(\lesone, \widths)}{\newle} +} +\end{mathpar} +\CodeSubsection{\LEConcatBegin}{\LEConcatEnd}{../Typing.ml} + +\subsubsection{TypingRule.LEBits\label{sec:TypingRule.LEBits}} +\hypertarget{def-annotatelebits}{} +The helper function +\[ + \annotatelebits(\overname{\staticenvs}{\tenv} \aslsep \overname{\lexpr}{\vle}) + \aslto \overname{\lexpr}{\vleone} \times \overname{\N}{\width} +\] +annotates a left-hand-side expression $\vle$, which is checked to be of bitvector type +with width $\width$, +resulting in the annotated expression and $\width$, or a type error, if one is detected. + +All of the following apply: +\begin{itemize} + \item annotating the right-hand-side expression corresponding to $\vle$ in $\tenv$ yields \\ $(\vteone, \Ignore)$\ProseOrTypeError; + \item obtaining the \structure\ of $\vteone$ in $\tenv$ yields $\vteonestruct$\ProseOrTypeError; + \item checking whether $\vteonestruct$ is a bitvector type yields $\True$\ProseOrTypeError; + \item $\vteonestruct$ is a bitvector type with width $\ewidth$; + \item applying $\reduceconstants$ to $\ewidth$ yields the literal $\vl$\ProseOrTypeError; + \item checking whether $\vl$ is an integer literal yields $\True$\ProseOrTypeError; + \item $\vl$ is the integer literal for the integer $\width$; + \item $\vtetwo$ is defined as the bitvector type of width given by $\width$ and an empty list of bitfields, that is, + $\TBits(\ELInt{\width}, \emptylist)$; + \item annotating the left-hand-side expression $\vtetwo$ in $\tenv$ yields $\vleone$\ProseOrTypeError. +\end{itemize} +\subsubsection{Formally} +\begin{mathpar} +\inferrule{ + \annotateexpr{\tenv, \torexpr(\vleone)} \typearrow (\vteone, \Ignore) \OrTypeError\\\\ + \tstruct(\tenv, \vteone) \typearrow \vteonestruct \OrTypeError\\\\ + \checktrans{\astlabel(\vteonestruct) = \TBits}{BitvectorTypeExpected} \checktransarrow \True \OrTypeError\\\\ + \vteonestruct \eqname \TBits(\ewidth, \Ignore)\\ + \reduceconstants(\tenv, \ewidth) \typearrow \vl\\ + \checktrans{\astlabel(\vl) = \lint}{IntegerLiteralExpected} \checktransarrow \True \OrTypeError\\\\ + \vl \eqname \lint(\width)\\ + \vtetwo \eqdef \TBits(\ELInt{\width}, \emptylist)\\ + \annotatelexpr{\tenv, \vtetwo} \typearrow \vleone \OrTypeError +}{ + \annotatelebits(\tenv, \vle) \typearrow (\vleone, \width) +} +\end{mathpar} + +\subsection{Semantics} +\subsubsection{SemanticsRule.LEConcat\label{sec:emanticsRule.LEConcat}} +\newcommand\extractslices[0]{\hyperlink{def-extractslices}{\textfunc{extract\_slices}}} +\subsubsection{Prose} +All of the following apply: +\begin{itemize} + \item applying $\extractslices$ to $\vwidths$, the literal expression for $0$, and $(\vv, \vg)$, in $\env$ to + extract a list of native bitvector values that correspond to the slices in $\vv$ + yields $(\ms, \Ignore)$\ProseOrError; + \item applying $\evalmultiassignment$ to $\vles$ and $\ms$ in $\env$ to assign from the slices in + $\ms$ to the \assignableexpressions\ in $\vles$ yields the resulting configuration $C$. +\end{itemize} +\subsubsection{Formally} +\begin{mathpar} +\inferrule{ + \extractslices(\env, \vwidths, \elint{0}, (\vv, \vg)) \evalarrow (\ms, \Ignore) \OrDynError\\\\ + \evalmultiassignment(\env, \vles, \ms) \evalarrow C +}{ + \evallexpr{\env, \overname{\LEConcat(\vles, \vwidths)}{\vle}, (\vv, \vg)} \evalarrow C +} +\end{mathpar} + +\subsubsection{SemanticsRule.ExtractSlices\label{sec:emanticsRule.ExtractSlices}} +The helper relation +\[ + \extractslices(\overname{\dynamicenvs}{\env}, \overname{\expr^*}{\vwidths}, \overname{((\vals \times \XGraphs)^*)^*}{\ms}, \overname{(\vals \times \XGraphs)}{\vm}) + \;\aslrel\; + \overname{((\vals \times \XGraphs)^*)^*}{\msout} + \cup \overname{\TError}{\ErrorConfig} +\] + +\subsubsection{Prose} +\subsubsection{Formally} + +% | LE_Concat (les, Some widths) -> +% let extract_one e_width ms = +% let m' = +% let* v = m +% and* width = eval_expr_sef env e_width +% and* start = eval_expr_sef env e_start in +% B.read_from_bitvector [ (start, width) ] v +% in +% m' :: ms +% in +% let ms = List.fold_right extract_one widths [] in +% multi_assign V1 env les ms diff --git a/asllib/doc/Bitfields.tex b/asllib/doc/Bitfields.tex new file mode 100644 index 000000000..ce14a43ee --- /dev/null +++ b/asllib/doc/Bitfields.tex @@ -0,0 +1,516 @@ +\chapter{Bitfields\label{chap:Bitfields}} + +Bitvector types allow defining bitslices of bitvectors, to be treated as named +fields, which can be read or written. \lrmcomment{\identi{KGMC}} + +Individual bitfields are grammatically derived from $\Nbitfield$ and represented as ASTs by $\bitfield$. +Bitfields are not associated with a semantic relation. + +\subsection{Example} +The following code declares a global variable whose type is a bitvector with bitfields. +\ASLExample{\definitiontests/Bitfields.asl} +\begin{itemize} + \item The expression \texttt{myData.flag} evaluates to the value \texttt{myData[4]} of type \texttt{bits(1)}; + \item The expression \texttt{myData.data} evaluates to the value \texttt{[myData[3:0], myData[8:5]]} of type \texttt{bits(8)}; + \item There is no bitfield which accesses \texttt{myData[15:10]}; + \item The value field overlaps with the other fields; + \item The slices \texttt{3:0} and \texttt{8:5} which define \texttt{data} do not overlap. +\end{itemize} +Note that in the \texttt{data} bitfield, bits \texttt{3:0} come before bits \texttt{8:5}, +which is a different order from their occurrence in \texttt{myData}. + +\hypertarget{def-singleslice}{} +\hypertarget{def-rangeslice}{} +\hypertarget{def-lengthslice}{} +\hypertarget{def-scaledslice}{} +We refer to a slice of the form \texttt{[$\ve$]} as a \singleslice, +a slice of the form \texttt{[$\veone$:$\vetwo$]} as a \rangeslice, +a slice of the form \texttt{[$\veone$+:$\vetwo$]} as a \lengthslice, +and slice of the form \texttt{[$\veone$*:$\vetwo$]} as a \scaledslice. + +\section{Nested Bitfields} +Bitfields may have nested bitfields. This can have several uses, one of which being being able to define two +different views of a register. + +\subsection{Example} +\ASLExample{\definitiontests/Bitfields_nested.asl} + +\subsection{Syntax} +\begin{flalign*} +\Nbitfields \derivesinline\ & \Tlbrace \parsesep \TClist{\Nbitfield} \parsesep \Trbrace &\\ +\Nbitfield \derivesinline\ & \Nnamedslices \parsesep \Tidentifier &\\ + |\ & \Nnamedslices \parsesep \Tidentifier \parsesep \Nbitfields &\\ + |\ & \Nnamedslices \parsesep \Tidentifier \parsesep \Tcolon \parsesep \Nty &\\ +\Nnamedslices \derivesinline\ & \Tlbracket \parsesep \NClist{\Nslice} \parsesep \Trbracket & +\end{flalign*} + +\subsection{Abstract Syntax} +\begin{flalign*} +\bitfield \derives\ & \BitFieldSimple(\identifier, \slice^{*}) + & \hypertarget{ast-bitfieldnested}{}\\ + |\ & \BitFieldNested(\identifier, \slice^{*}, \bitfield^{*}) + & \hypertarget{ast-bitfieldtype}{}\\ + |\ & \BitFieldType(\identifier, \slice^{*}, \ty) & +\end{flalign*} + +\subsubsection{ASTRule.Bitfields\label{sec:ASTRule.Bitfields}} +\hypertarget{build-bitfields}{} +The function +\[ + \buildbitfields(\overname{\parsenode{\Nbitfields}}{\vparsednode}) \;\aslto\; \overname{\bitfield^*}{\vastnode} +\] +transforms a parse node $\vparsednode$ into an AST node $\vastnode$. + +\begin{mathpar} +\inferrule{ + \buildtclist[\buildbitfield](\vbitfields) \astarrow \vbitfieldasts +}{ + \buildbitfields(\Nbitfields(\Tlbrace, \namednode{\vbitfields}{\TClist{\Nbitfield}}, \Trbrace)) \astarrow + \overname{\vbitfieldasts}{\vastnode} +} +\end{mathpar} + +\subsubsection{ASTRule.Bitfield\label{sec:ASTRule.Bitfield}} +\hypertarget{build-bitfield}{} +The function +\[ + \buildbitfield(\overname{\parsenode{\Nbitfield}}{\vparsednode}) \;\aslto\; \overname{\bitfield}{\vastnode} +\] +transforms a parse node $\vparsednode$ into an AST node $\vastnode$. + +\begin{mathpar} +\inferrule[simple]{}{ + \buildbitfields(\Nbitfield(\punnode{\Nnamedslices}, \Tidentifier(\vx))) \astarrow + \overname{\BitFieldSimple(\vx, \astof{\vnamedslices})}{\vastnode} +} +\end{mathpar} + +\begin{mathpar} +\inferrule[nested]{}{ + { + \begin{array}{r} + \buildbitfields(\Nbitfield(\punnode{\Nnamedslices}, \Tidentifier(\vx), \punnode{\Nbitfields})) \astarrow\\ + \overname{\BitFieldNested(\vx, \astof{\vnamedslices}, \astof{\vbitfields})}{\vastnode} + \end{array} + } +} +\end{mathpar} + +\begin{mathpar} +\inferrule[type]{}{ + { + \begin{array}{r} + \buildbitfields(\Nbitfield(\punnode{\Nnamedslices}, \Tidentifier(\vx), \Tcolon, \punnode{\Nty})) \astarrow\\ + \overname{\BitFieldType(\vx, \astof{\vnamedslices}, \astof{\tty})}{\vastnode} + \end{array} + } +} +\end{mathpar} + +\subsubsection{ASTRule.NamedSlices\label{sec:ASTRule.NamedSlices}} +\hypertarget{build-namedslices}{} +The function +\[ + \buildnamedslices(\overname{\parsenode{\Nnamedslices}}{\vparsednode}) \;\aslto\; \overname{\slice^+}{\vastnode} +\] +transforms a parse node $\vparsednode$ into an AST node $\vastnode$. + +\begin{mathpar} +\inferrule{ + \buildclist[\buildslice](\vslices) \astarrow \vsliceasts +}{ + \buildnamedslices(\Nnamedslices(\Tlbracket, \namednode{\vslices}{\NClist{\Nslice}}, \Trbracket)) \astarrow + \overname{\vsliceasts}{\vastnode} +} +\end{mathpar} + +\section{Typing Bitfields} +\subsubsection{TypingRule.TBitFields\label{sec:TypingRule.TBitFields}} +\hypertarget{def-annotatebitfields}{} +The function +\[ + \annotatebitfields(\overname{\staticenvs}{\tenv} \aslsep \overname{\expr}{\ewidth} \aslsep \overname{\bitfield^*}{\fields}) + \aslto \overname{\bitfield^*}{\newfields} \cup \overname{\TTypeError}{\TypeErrorConfig} +\] +annotates a list of bitfields --- $\fields$ --- with an expression denoting the overall number of bits in the containing +bitvector type --- $\ewidth$, +in an environment $\tenv$, +resulting in $\newfields$ --- the \typedast\ for $\fields$ and $\ewidth$. \ProseOtherwiseTypeError + +\subsubsection{Prose} +All of the following apply: +\begin{itemize} + \item checking that the list of bitfield names in $\bitfields$ does not contain duplicates yields $\True$\ProseOrTypeError; + \item symbolically simplifying $\ewidth$ in $\tenv$ via $\reduceconstants$ yields the literal integer for $\width$\ProseOrTypeError; + \item annotating each bitfield $\field$ in $\fields$ with width $\width$ in $\tenv$ yields the corresponding annotated + bitfield $\newfield$\ProseOrTypeError; + \item $\newfields$ is the list of annotated bitfields. +\end{itemize} + +\subsubsection{Formally} +\begin{mathpar} +\inferrule{ + \names \eqdef [\field\in\fields: \bitfieldgetname(\field)]\\ + \checknoduplicates(\names) \typearrow \True \OrTypeError\\\\ + \reduceconstants(\tenv, \ewidth) \typearrow \lint(\width) \OrTypeError\\\\ + \field\in\fields: \annotatebitfield(\tenv, \width, \field) \typearrow \newfield \OrTypeError\\\\ + \newfields \eqdef [\field\in\fields: \newfield] +}{ + \annotatebitfields(\tenv, \ewidth, \fields) \typearrow \newfields +} +\end{mathpar} + +\CodeSubsection{\TBitFieldsBegin}{\TBitFieldsEnd}{../Typing.ml} + +\subsubsection{TypingRule.BitFieldGetName \label{sec:TypingRule.BitFieldGetName}} +\hypertarget{def-bitfieldgetname}{} +The function +\[ + \bitfieldgetname : \overname{\bitfield}{\vbf} \aslto \overname{\identifier}{\name} +\] +returns the name of a bitfield --- $\name$, given a bitfield $\vbf$. + +\subsubsection{Prose} +One of the following applies: +\begin{itemize} + \item $\vb$ is a simple bitfield with name $\name$, that is, $\BitFieldSimple(\name, \Ignore)$; + \item $\vb$ is a nested bitfield with name $\name$, that is, $\BitFieldNested(\name, \Ignore, \Ignore)$; + \item $\vb$ is a typed bitfield with name $\name$, that is, $\BitFieldType(\name, \Ignore, \Ignore)$. +\end{itemize} + +\subsubsection{Formally} +\begin{mathpar} + \inferrule[simple]{}{ + \bitfieldgetname(\BitFieldSimple(\name, \Ignore)) \typearrow \name + } + \and + \inferrule[nested]{}{ + \bitfieldgetname(\BitFieldNested(\name, \Ignore, \Ignore)) \typearrow \name + } + \and + \inferrule[type]{}{ + \bitfieldgetname(\BitFieldType(\name, \Ignore, \Ignore)) \typearrow \name + } +\end{mathpar} + +\subsubsection{TypingRule.TBitField\label{sec:TypingRule.TBitField}} +\hypertarget{def-annotatebitfield}{} +The function +\[ + \annotatebitfield(\overname{\staticenvs}{\tenv} \aslsep \overname{\Z}{\width} \aslsep \overname{\bitfield}{\vfield}) + \aslto \overname{\bitfield}{\newfield} \cup \overname{\TTypeError}{\TypeErrorConfig} +\] +annotates a bitfield --- $\vfield$ --- with an integer --- $\width$ --- indicating the number of bits in +the bitvector type that contains $\field$, +in an environment $\tenv$, resulting in an +annotated bitfield --- $\newfield$ --- or a type error, if one is detected. + +\subsubsection{Prose} +\begin{itemize} + \item $\vfield$ is a bitfield with list of slices $\vslices$; + \item annotating the slices $\vslices$ yields $\slicesone$\ProseOrTypeError; + \item One of the following applies: + \begin{itemize} + \item All of the following apply (\textsc{simple}): + \begin{itemize} + \item checking whether the range of positions in $\slicesone$ fits inside $0..\width-1$ yields $\True$\ProseOrTypeError; + \item $\newfield$ is a bitfield named $\name$ with list of slices $\slicesone$, that is, $\BitFieldSimple(\name, \slicesone)$. + \end{itemize} + + \item All of the following apply (\textsc{nested}): + \begin{itemize} + \item converting the $\slicesone$ into a list of positions with $\width$ and static environment $\tenv$ + yields $\positions$\ProseOrTypeError; + \item checking that all positions in $\positions$ fit inside $0..\width$ yields \\ + $\True$\ProseOrTypeError; + \item let $\widthp$ be the length of the list $\positions$; + \item annotating the bitfields $\bitfieldsp$ with $\widthp$ in static environment $\tenv$ yields $\bitfieldspp$\ProseOrTypeError; + \item $\newfields$ is the nested bitfield with $\slicesone$ and bitfields $\bitfieldspp$, that is, $\BitFieldNested(\slicesone, \bitfieldspp)$. + \end{itemize} + + \item All of the following apply (\textsc{type}): + \begin{itemize} + \item Annotating the type $\vt$ yields $\vtp$\ProseOrTypeError; + \item checking whether the range of positions in $\slicesone$ fit inside $0..\width$ yields $\True$\ProseOrTypeError; + \item converting the list of slices $\slicesone$ into a list of positions in $\tenv$ yields $\positions$\ProseOrTypeError; + \item checking that all positions in $\positions$ fit inside $0..\width$ yields $\True$\ProseOrTypeError; + \item let $\widthp$ be the length of the list $\positions$; + \item checking whether the $\vt$ and the bitvector with $\widthp$ bits have the same width yields $\True$\ProseOrTypeError + \item $\newfield$ is the typed-bitfield with name $\name$, list of slices $\slicesone$ and type $\vtp$, that is, \BitFieldType(\name, \slicesone, \vtp). + \end{itemize} + \end{itemize} +\end{itemize} + +\subsubsection{Formally} +\begin{mathpar} +\inferrule[simple]{ + \annotateslices(\tenv, \vslices) \typearrow \slicesone \OrTypeError\\\\ + \commonprefixline\\\\ + \checkslicesinwidth(\tenv, \width, \slicesone) \typearrow \True \OrTypeError +}{ + \annotatebitfield(\tenv, \width, \BitFieldSimple(\name, \vslices)) \typearrow \\ + \BitFieldSimple(\name, \slicesone) +} +\end{mathpar} + +\begin{mathpar} +\inferrule[nested]{ + \annotateslices(\tenv, \vslices) \typearrow \slicesone \OrTypeError\\\\ + \commonprefixline\\\\ + \disjointslicestopositions(\tenv, \slicesone) \typearrow \positions \OrTypeError\\\\ + \checkpositionsinwidth(\tenv, \width, \positions) \typearrow \True \OrTypeError\\\\ + \widthp \eqdef \listlen{\positions}\\ + \annotatebitfields(\tenv, \widthp, \bitfieldsp) \typearrow \bitfieldspp \OrTypeError\\ +}{ + \annotatebitfield(\tenv, \width, \BitFieldNested(\name, \vslices, \bitfieldsp)) \typearrow \\ + \BitFieldNested(\slicesone, \bitfieldspp) +} +\end{mathpar} + +\begin{mathpar} +\inferrule[type]{ + \annotateslices(\tenv, \vslices) \typearrow \slicesone \OrTypeError\\\\ + \commonprefixline\\\\ + \annotatetype{\tenv, \vt} \typearrow \vtp \OrTypeError\\\\ + \checkslicesinwidth(\tenv, \width, \slicesone) \typearrow \True \OrTypeError\\\\ + \disjointslicestopositions(\tenv, \slicesone) \typearrow \positions \OrTypeError\\\\ + \checkpositionsinwidth(\tenv, \slicesone, \width, \positions) \typearrow \True \OrTypeError\\\\ + \widthp \eqdef \listlen{\positions}\\ + \checkbitsequalwidth(\TBits(\widthp, \emptylist), \vt) \typearrow \True \OrTypeError +}{ + \annotatebitfield(\tenv, \width, \BitFieldType(\name, \vslices, \vt)) \typearrow \\ + \BitFieldType(\name, \slicesone, \vtp) +} +\end{mathpar} + +\subsubsection{Example} +In the following example, all the uses of bitvector types with bitfields are well-typed: +\ASLExample{\typingtests/TypingRule.TBitField.asl} + +\CodeSubsection{\TBitFieldBegin}{\TBitFieldEnd}{../Typing.ml} + +\subsubsection{TypingRule.CheckSlicesInWidth\label{sec:TypingRule.CheckSlicesInWidth}} +\hypertarget{def-checkslicesinwidth}{} +The function +\[ + \checkslicesinwidth(\overname{\staticenvs}{\tenv} \aslsep \overname{\Z}{\vwidth} \aslsep \overname{\slice^*}{\vslices}) + \aslto \{\True\} \cup \overname{\TTypeError}{\TypeErrorConfig} +\] +checks whether the slices in $\vslices$ fit within the bitvector width given by $\vwidth$ in $\tenv$, +yielding $\True$. \ProseOtherwiseTypeError + +\subsubsection{Prose} +All of the following apply: +\begin{itemize} + \item applying $\disjointslicestopositions$ to $\vslices$ in $\tenv$ checks whether the + slices in $\vslices$ are disjoint and yields the set of their positions\ProseOrTypeError; + \item applying $\checkpositionsinwidth$ to $\vwidth$ and $\positions$ to check that + all of the positions fit with the width given by $\vwidth$ yields $\True$\ProseOrError. +\end{itemize} + +\subsubsection{Formally} +\begin{mathpar} +\inferrule{ + \disjointslicestopositions(\tenv, \vslices) \typearrow \positions \OrTypeError\\\\ + \checkpositionsinwidth(\vwidth, \positions) \typearrow \True \OrTypeError +}{ + \checkslicesinwidth(\tenv, \vwidth, \vslices) \typearrow \True +} +\end{mathpar} +\CodeSubsection{\CheckSlicesInWidthBegin}{\CheckSlicesInWidthEnd}{../Typing.ml} + +\subsubsection{TypingRule.CheckPositionsInWidth\label{sec:TypingRule.CheckPositionsInWidth}} +\hypertarget{def-checkpositionsinwidth}{} +The function +\[ + \checkpositionsinwidth(\overname{\Z}{\vwidth} \aslsep \overname{\pow{\Z}}{\positions}) + \aslto \{\True\} \cup \overname{\TTypeError}{\TypeErrorConfig} +\] +checks whether the set of positions in $\positions$ fit within the bitvector width given by $\vwidth$, +yielding $\True$. \ProseOtherwiseTypeError + +\subsubsection{Prose} +All of the following apply: +\begin{itemize} + \item define $\minpos$ as the minimal position in $\positions$; + \item define $\maxpos$ as the maximal position in $\positions$; + \item checking that $\minpos$ is non-negative and that $\maxpos$ is less than or equal to $\vwidth$ + yields $\True$\ProseTerminateAs{\BitfieldsOutOfRange}. + \item the result is $\True$. +\end{itemize} + +\subsubsection{Formally} +\begin{mathpar} +\inferrule{ + \minpos \eqdef \min(\positions)\\ + \maxpos \eqdef \max(\positions)\\ + \checktrans{0 \leq \minpos \land \maxpos \leq \vwidth}{\BitfieldsOutOfRange} \typearrow \True \OrTypeError +}{ + \checkpositionsinwidth(\vwidth, \positions) \typearrow \True +} +\end{mathpar} + +\subsubsection{TypingRule.DisjointSlicesToPositions\label{sec:TypingRule.DisjointSlicesToPositions}} +\hypertarget{def-disjointslicestopositions}{} +The function +\[ + \disjointslicestopositions(\overname{\staticenvs}{\tenv}, \overname{\slice^*}{\vslices}) + \aslto \overname{\powfin{\Z}}{\positions} \cup \overname{\TTypeError}{\TypeErrorConfig} +\] +returns the set of integers defined by the list of slices in $\vslices$ in $\positions$. +In particular, this rule checks that the bitfield slices do not overlap and that they are not defined in reverse +(e.g., \texttt{0:1} rather than \texttt{1:0}) +\ProseOtherwiseTypeError + +\subsubsection{Prose} +One of the following applies: +\begin{itemize} + \item All of the following apply (\textsc{empty}): + \begin{itemize} + \item $\vslices$ is the empty list; + \item $\positions$ is the empty set. + \end{itemize} + + \item All of the following apply (\textsc{non\_empty}): + \begin{itemize} + \item $\vslices$ is the list with $\vs$ as its \head\ and $\vslicesone$ as its \tail; + \item applying $\bitfieldslicetopositions$ to $\vs$ in $\tenv$ yields the set of positions \\ + $\positionsone$\ProseOrTypeError; + \item applying $\disjointslicestopositions$ to $\vslicesone$ in $\tenv$ yields the set of positions $\positionsone$\ProseOrTypeError; + \item checking that $\positionsone$ is disjoint from $\positionstwo$ yields $\True$\ProseTerminateAs{\BitfieldSlicesOverlap} + \item $\positions$ is the union of $\positionsone$ and $\positionstwo$. + \end{itemize} +\end{itemize} +\subsubsection{Formally} +\begin{mathpar} +\inferrule[empty]{}{ + \disjointslicestopositions(\tenv, \overname{\emptylist}{\vslices}) \typearrow \overname{\emptyset}{\positions} +} +\end{mathpar} + +\begin{mathpar} +\inferrule[non\_empty]{ + \bitfieldslicetopositions(\tenv, \vs) \typearrow \positionsone \OrTypeError\\\\ + \disjointslicestopositions(\tenv, \vslicesone) \typearrow \positionstwo \OrTypeError\\\\ + \checktrans{\positionsone \cap \positionstwo = \emptyset}{\BitfieldSlicesOverlap} \checktransarrow \True \OrTypeError +}{ + \disjointslicestopositions(\tenv, \overname{\vs \concat \vslicesone}{\vslices}) \typearrow \overname{\positionsone \cup \positionstwo}{\positions} +} +\end{mathpar} + +\subsubsection{TypingRule.BitfieldSliceToPositions\label{sec:TypingRule.BitfieldSliceToPositions}} +\hypertarget{def-bitfieldslicetopositions}{} +The function +\[ + \bitfieldslicetopositions(\overname{\staticenvs}{\tenv}, \overname{\vslice}{\vslices}) + \aslto \overname{\powfin{\Z}}{\positions} \cup \overname{\TTypeError}{\TypeErrorConfig} +\] +returns the set of integers defined by the bitfield slice $\vslice$ in $\positions$. \ProseOtherwiseTypeError + +\subsubsection{Prose} +One of the following applies: +\begin{itemize} + \item All of the following apply (\textsc{single}): + \begin{itemize} + \item $\vslice$ is a \singleslice\ defined by the expression $\ve$, that is, $\SliceSingle(\ve)$; + \item applying $\reduceconstants$ to $\ve$ in $\tenv$ yields the literal $\vl$\ProseOrTypeError; + \item checking that $\vl$ is an integer literal yields $\True$\ProseTerminateAs{\IntConstantExpected}; + \item $\vl$ is the integer literal for $\vx$; + \item $\positions$ is the singleton set for $\vx$. + \end{itemize} + + \item All of the following apply (\textsc{range}): + \begin{itemize} + \item $\vslice$ is \rangeslice\ defined by expressions $\veone$ and $\vetwo$, that is, \\ + $\SliceRange(\veone, \vetwo)$; + \item applying $\reduceconstants$ to $\veone$ in $\tenv$ yields the literal $\vlone$\ProseOrTypeError; + \item checking that $\vlone$ is an integer literal yields $\True$\ProseTerminateAs{\IntConstantExpected}; + \item $\vlone$ is the integer literal for $\vx$; + \item applying $\reduceconstants$ to $\vetwo$ in $\tenv$ yields the literal $\vltwo$\ProseOrTypeError; + \item checking that $\vltwo$ is an integer literal yields $\True$\ProseTerminateAs{\IntConstantExpected}; + \item $\vltwo$ is the integer literal for $\vy$; + \item checking that $\vx$ is less than or equal to $\vy$ yields $\True$\ProseTerminateAs{\BitfieldSliceReversed}; + \item $\positions$ is the set of integers between $\vx$ and $\vy$, inclusive. + \end{itemize} + + \item All of the following apply (\textsc{length}): + \begin{itemize} + \item $\vslice$ is \lengthslice\ defined by expressions $\veone$ and $\vetwo$, that is, \\ + $\SliceLength(\veone, \vetwo)$; + \item applying $\reduceconstants$ to $\veone$ in $\tenv$ yields the literal $\vlone$\ProseOrTypeError; + \item checking that $\vlone$ is an integer literal yields $\True$\ProseTerminateAs{\IntConstantExpected}; + \item $\vlone$ is the integer literal for $\vx$; + \item applying $\reduceconstants$ to $\vetwo$ in $\tenv$ yields the literal $\vltwo$\ProseOrTypeError; + \item checking that $\vltwo$ is an integer literal yields $\True$\ProseTerminateAs{\IntConstantExpected}; + \item $\vltwo$ is the integer literal for $\vy$; + \item checking that $\vx$ is less than or equal to $\vy$ yields $\True$\ProseTerminateAs{\BitfieldSliceReversed}; + \item $\positions$ is the set of integers between $\vx$ and $\vx+\vy-1$, inclusive. + \end{itemize} + + \item All of the following apply (\textsc{scaled}): + \begin{itemize} + \item $\vslice$ is \scaledslice\ defined by expressions $\veone$ and $\vetwo$, that is, \\ + $\SliceStar(\veone, \vetwo)$; + \item applying $\reduceconstants$ to $\veone$ in $\tenv$ yields the literal $\vlone$\ProseOrTypeError; + \item checking that $\vlone$ is an integer literal yields $\True$\ProseTerminateAs{\IntConstantExpected}; + \item $\vlone$ is the integer literal for $\vx$; + \item applying $\reduceconstants$ to $\vetwo$ in $\tenv$ yields the literal $\vltwo$\ProseOrTypeError; + \item checking that $\vltwo$ is an integer literal yields $\True$\ProseTerminateAs{\IntConstantExpected}; + \item $\vltwo$ is the integer literal for $\vy$; + \item checking that $\vx$ is less than or equal to $\vy$ yields $\True$\ProseTerminateAs{\BitfieldSliceReversed}; + \item $\positions$ is the set of integers between $\vx \times \vy$ and $\vx \times (\vy + 1) - 1$, inclusive. + \end{itemize} +\end{itemize} +\subsubsection{Formally} +\begin{mathpar} +\inferrule[single]{ + \reduceconstants(\tenv, \ve) \typearrow \vl \OrTypeError\\\\ + \checktrans{\astlabel(\vl) = \lint}{\IntConstantExpected} \checktransarrow \True \OrTypeError\\\\ + \vl \eqname \lint(\vx) +}{ + \bitfieldslicetopositions(\tenv, \overname{\SliceSingle(\ve)}{\vslice}) \typearrow \overname{\{\vx\}}{\positions} +} +\end{mathpar} + +\begin{mathpar} +\inferrule[range]{ + \reduceconstants(\tenv, \veone) \typearrow \vlone \OrTypeError\\\\ + \checktrans{\astlabel(\vlone) = \lint}{\IntConstantExpected} \checktransarrow \True \OrTypeError\\\\ + \vlone \eqname \lint(\vx)\\ + \reduceconstants(\tenv, \vetwo) \typearrow \vltwo \OrTypeError\\\\ + \checktrans{\astlabel(\vltwo) = \lint}{\IntConstantExpected} \checktransarrow \True \OrTypeError\\\\ + \vltwo \eqname \lint(\vy)\\ + \checktrans{\vx \leq \vy}{\BitfieldSliceReversed} \checktransarrow \True \OrTypeError\\\\ +}{ + \bitfieldslicetopositions(\tenv, \overname{\SliceRange(\veone, \vetwo)}{\vslice}) \typearrow \overname{\{n \;|\; \vx \leq n \leq \vy\}}{\positions} +} +\end{mathpar} + +\begin{mathpar} +\inferrule[length]{ + \reduceconstants(\tenv, \veone) \typearrow \vlone \OrTypeError\\\\ + \checktrans{\astlabel(\vlone) = \lint}{\IntConstantExpected} \checktransarrow \True \OrTypeError\\\\ + \vlone \eqname \lint(\vx)\\ + \reduceconstants(\tenv, \vetwo) \typearrow \vltwo \OrTypeError\\\\ + \checktrans{\astlabel(\vltwo) = \lint}{\IntConstantExpected} \checktransarrow \True \OrTypeError\\\\ + \vltwo \eqname \lint(\vy)\\ + \checktrans{\vx \leq \vy}{\BitfieldSliceReversed} \checktransarrow \True \OrTypeError\\\\ +}{ + \bitfieldslicetopositions(\tenv, \overname{\SliceRange(\veone, \vetwo)}{\vslice}) \typearrow \overname{\{n \;|\; \vx \leq n \leq \vx+\vy-1\}}{\positions} +} +\end{mathpar} +\begin{mathpar} + +\inferrule[scaled]{ + \reduceconstants(\tenv, \veone) \typearrow \vlone \OrTypeError\\\\ + \checktrans{\astlabel(\vlone) = \lint}{\IntConstantExpected} \checktransarrow \True \OrTypeError\\\\ + \vlone \eqname \lint(\vx)\\ + \reduceconstants(\tenv, \vetwo) \typearrow \vltwo \OrTypeError\\\\ + \checktrans{\astlabel(\vltwo) = \lint}{\IntConstantExpected} \checktransarrow \True \OrTypeError\\\\ + \vltwo \eqname \lint(\vy)\\ + \checktrans{\vx \leq \vy}{\BitfieldSliceReversed} \checktransarrow \True \OrTypeError\\\\ +}{ + \bitfieldslicetopositions(\tenv, \overname{\SliceStar(\veone, \vetwo)}{\vslice}) \typearrow + \overname{\{n \;|\; \vx \times \vy \leq n \leq \vx \times (\vy + 1) - 1\}}{\positions} +} +\end{mathpar} diff --git a/asllib/doc/BlockStatements.tex b/asllib/doc/BlockStatements.tex new file mode 100644 index 000000000..6d3b53517 --- /dev/null +++ b/asllib/doc/BlockStatements.tex @@ -0,0 +1,95 @@ +\chapter{Block Statements\label{chap:BlockStatements}} +Block statements are statements executing in their own scope within the scope of their enclosing subprogram. + +\section{Typing\label{sec:BlockStatementsTyping}} +\hypertarget{def-annotateblock}{} +The function +\[ + \annotateblock{\overname{\staticenvs}{\tenv} \aslsep \overname{\stmt}{\vs}} \aslto + \overname{\stmt}{\newstmt} \cup \overname{\TTypeError}{\TypeErrorConfig} +\] +annotates a block statement $\vs$ in static environment $\tenv$ and returns the annotated +statement $\newstmt$ or a type error, if one is detected. + +\subsubsection{TypingRule.Block\label{sec:TypingRule.Block}} +\subsubsection{Example} +\VerbatimInput{../tests/ASLTypingReference.t/TypingRule.Block0.asl} + +\subsubsection{Prose} +All of the following apply: +\begin{itemize} + \item annotating the statement $\vs$ in $\tenv$ yields $(\newstmt, \newtenv)$\ProseOrTypeError; + \item the modified environment $\newtenv$ is dropped. +\end{itemize} +\subsubsection{Formally} +\begin{mathpar} +\inferrule{ + \annotatestmt(\tenv, \vs) \typearrow (\newstmt, \Ignore) \OrTypeError +}{ + \annotateblock{\tenv, \vs} \typearrow \newstmt +} +\end{mathpar} +\CodeSubsection{\BlockBegin}{\BlockEnd}{../Typing.ml} + +\subsection{Comments} +A local identifier declared in a block statement (with \texttt{var}, \texttt{let}, or \texttt{constant}) +is in scope from the point immediately after its declaration until the end of the +immediately enclosing block. This means, we can discard the environment at the end of +an enclosing block, which has the effect of dropping bindings of the identifiers declared inside the block. + +\lrmcomment{This is related to \identr{JBXQ}.} + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +\section{Semantics\label{sec:BlockStatementsSemantics}} +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +The relation +\hypertarget{def-evalblock}{} +\[ + \evalblock{\overname{\envs}{\env} \times \overname{\stmt}{\stm}} \;\aslrel\; + \overname{\TContinuing}{\Continuing(\newg, \newenv)} \cup + \overname{\TReturning}{\ReturningConfig} \cup + \overname{\TThrowing}{\ThrowingConfig} \cup + \overname{\TError}{\ErrorConfig} +\] +evaluates a statement $\stm$ as a \emph{block}. That is, $\stm$ is evaluated in a fresh local environment, +which drops back to the original local environment of $\env$ when the evaluation terminates. + +\subsubsection{SemanticsRule.Block\label{sec:SemanticsRule.Block}} +\subsubsection{Example} +In the specification: +\VerbatimInput{\semanticstests/SemanticsRule.Block.asl} +the conditional statement \texttt{if TRUE then\ldots{} end;} defines a +block structure. Thus, the scope of the declaration \texttt{let y = 2;} is +limited to its declaring block---or the binding for \texttt{y} no longer exists +once the block is exited. As a consequence, the subsequent declaration +\texttt{let y = 1} is valid. By contrast, the assignment of the mutable +variable~\texttt{x} persists after block end. However, observe that \texttt{x} +is defined before the block and hence still exists after the block. + +\subsubsection{Prose} +All of the following apply: +\begin{itemize} + \item $\blockenv$ is the environment $\env$ modified by replacing the local component + (of the inner dynamic environment) by an empty one; + \item evaluating $\stm$ in $\blockenv$, as per \chapref{eval_stmt}, + is \\ $\Continuing(\newg, \blockenvone)$\ProseTerminateAs{\ReturningConfig}; + \item $\newenv$ is formed from $\blockenvone$ after restoring the + variable bindings of $\env$ with the updated values of $\blockenv$. + The effect is that of discarding the bindings for variables declared inside $\stm$; + \item the result of the entire evaluation is $\Continuing(\newg, \newenv)$. +\end{itemize} +\subsubsection{Formally} +\begin{mathpar} +\inferrule{ + \env \eqname (\tenv,\denv)\\ + \blockenv \eqdef (\tenv, (G^\denv, \emptyfunc))\\ + \evalstmt{\blockenv, \stm} \evalarrow \Continuing(\newg, \blockenvone) \terminateas \ReturningConfig,\ThrowingConfig,\ErrorConfig\\\\ + \blockenvone\eqname(\tenv, \denvone)\\ + \newenv \eqdef(\tenv, (G^{\denvone}, \restrictfunc{L^{\denvone}}{{\dom(L^\denv)}})) +}{ + \evalblock{\env, \stm} \evalarrow \Continuing(\newg, \newenv) +} +\end{mathpar} +\CodeSubsection{\EvalBlockBegin}{\EvalBlockEnd}{../Interpreter.ml} + +That is, evaluating a block discards the bindings for variables declared inside $\stm$. diff --git a/asllib/doc/CatchingExceptions.tex b/asllib/doc/CatchingExceptions.tex new file mode 100644 index 000000000..ae240eb57 --- /dev/null +++ b/asllib/doc/CatchingExceptions.tex @@ -0,0 +1,513 @@ +\chapter{Catching Exceptions\label{chap:CatchingExceptions}} + +Exception catchers are grammatically derived from $\Ncatcher$ and represented as ASTs by $\catcher$. + +\hypertarget{def-annotatecatcher}{} +The function +\[ +\begin{array}{r} + \annotatecatcher{ + \overname{\staticenvs}{\tenv} \aslsep + (\overname{\langle\identifier\rangle}{\nameopt} \times \overname{\ty}{\tty} \times \overname{\stmt}{\vstmt}) + } \aslto \\ + (\overname{\langle\identifier\rangle}{\nameopt} \times \overname{\ty}{\ttyp} \times \overname{\stmt}{\newstmt}) + \cup \overname{\TTypeError}{\TypeErrorConfig} +\end{array} +\] +annotates a catcher given by the \optional\ name of the matched exception --- $\nameopt$ --- +the exception type --- $\tty$ --- and the statement to execute upon catching the exception --- $\vstmt$. +The result is the catcher with the same \optional\ name --- $\nameopt$, an annotated type $\ttyp$, and annotated statement $\newstmt$. +\ProseOtherwiseTypeError + +The semantic relation for evaluating catchers employs an argument +that is an output configuration. This argument corresponds to the result +of evaluating a \texttt{try} statement and its type is defined as follows: +\hypertarget{def-toutconfig}{} +\[ + \TOutConfig \triangleq \TNormal \cup \TThrowing \cup \TContinuing \cup \TReturning \enspace. +\] + +The relation +\hypertarget{def-evalcatchers}{} +\[ + \evalcatchers{\overname{\envs}{\env} \aslsep \overname{\catcher^*}{\catchers} \aslsep \overname{\langle\stmt\rangle}{\otherwiseopt} + \aslsep \overname{\TOutConfig}{\sm}} \;\aslrel\; + \left( + \begin{array}{cl} + \TReturning & \cup\\ + \TContinuing & \cup\\ + \TThrowing & \cup \\ + \TError & + \end{array} + \right) +\] +evaluates a list of \texttt{catch} clauses $\catchers$, an \texttt{otherwise} clause, +and a configuration $\sm$ resulting from the evaluation of the throwing expression, +in the environment $\env$. The result is either a continuation configuration, +an early return configuration, or an abnormal configuration. + +When the statement in a \texttt{try} block, which we will refer to as the try-block statement, +is evaluated, it may call a function that updates +the global environment. If evaluation of the \texttt{try} block raises an exception that is caught, +either by a \texttt{catch} clause or an \texttt{otherwise} clause, +the statement associated with that clause, which we will refer to as the clause statement, is evaluated. +It is important to evaluate the clause statement in an environment that includes any updates +to the global environment made by evaluating the try-block statement. +% +We demonstrate this with the following example. + +Consider the following specification: +\VerbatimInput{../tests/ASLSemanticsReference.t/EvalCatchers.asl} + +Here, the try-block statement consists of the single statement \texttt{update\_and\_throw();}. +Evaluating the call to \texttt{update\_and\_throw} employs an environment $\env$ where +\texttt{g} is bound to $0$. +Notice that the call to \texttt{update\_and\_throw} binds \texttt{g} to $1$ before raising an exception. +Therefore, evaluating the call to \texttt{update\_and\_throw} returns a configuration +of the form +$\Throwing(\Ignore, \envthrow)$ where $\envthrow$ binds \texttt{g} to $1$. +When the catch clause is evaluated the semantics takes the global environment from $\envthrow$ +to account for the update to \texttt{g} and the local environment from $\env$ to account for the +updates to the local environment in \texttt{main}, which binds \texttt{x} to $2$, and use this +environment to evaluate \texttt{print(x, g)}, resulting in the output \texttt{2 1}. + +\section{Syntax} +\begin{flalign*} +\Ncatcher \derivesinline\ & \Twhen \parsesep \Tidentifier \parsesep \Tcolon \parsesep \Nty \parsesep \Tarrow \parsesep \Nstmtlist &\\ + |\ & \Twhen \parsesep \Nty \parsesep \Tarrow \parsesep \Nstmtlist &\\ +\end{flalign*} + +\section{Abstract Syntax} +\begin{flalign*} +\catcher \derives\ & (\overtext{\identifier?}{exception to match}, \overtext{\ty}{guard type}, \overtext{\stmt}{statement to execute on match}) & +\end{flalign*} + +\subsubsection{ASTRule.Catcher\label{sec:ASTRule.Catcher}} +\hypertarget{build-catcher}{} +The function +\[ +\buildcatcher(\overname{\parsenode{\Ncatcher}}{\vparsednode}) \;\aslto\; \overname{\catcher}{\vastnode} +\] +transforms a parse node $\vparsednode$ into an AST node $\vastnode$. + +\begin{mathpar} +\inferrule[named]{}{ + { + \begin{array}{r} + \buildcatcher(\overname{\Ncatcher(\Twhen, \Tidentifier(\id), \Tcolon, \Nty, \Tarrow, \Nstmtlist)}{\vparsednode}) + \astarrow \\ + \overname{(\langle\id\rangle, \astof{\tty}, \astof{\vstmtlist})}{\vastnode} + \end{array} + } +} +\end{mathpar} + +\begin{mathpar} +\inferrule[unnamed]{}{ + { + \begin{array}{r} + \buildcatcher(\overname{\Ncatcher(\Twhen, \Nty, \Tarrow, \Nstmtlist)}{\vparsednode}) + \astarrow \\ + \overname{(\None, \astof{\tty}, \astof{\vstmtlist})}{\vastnode} + \end{array} + } +} +\end{mathpar} + +\section{Typing} +\subsubsection{TypingRule.Catcher\label{sec:TypingRule.Catcher}} +\subsubsection{Prose} +One of the following applies: +\begin{itemize} + \item All of the following apply (\textsc{none}): + \begin{itemize} + \item the catcher has no named identifier, that is, $(\None, \tty, \vstmt)$; + \item annotating the type $\tty$ in $\tenv$ yields $\ttyp$\ProseOrTypeError; + \item determining whether $\ttyp$ has the \structure\ of an exception type yields $\True$\ProseOrTypeError; + \item annotating the block $\vstmt$ in $\tenv$ yields $\newstmt$. + \end{itemize} + + \item All of the following apply: + \begin{itemize} + \item the catcher has a named identifier, that is, $(\langle\name\rangle, \tty, \vstmt)$; + \item annotating the type $\tty$ in $\tenv$ yields $\ttyp$\ProseOrTypeError; + \item determining whether $\ttyp$ has the \structure\ of an exception type yields $\True$\ProseOrTypeError; + \item the identifier $\name$ is not bound in $\tenv$; + \item binding $\name$ in the local environment of $\tenv$ with the type $\ttyp$ as an immutable variable + (that is, with the local declaration keyword $\LDKLet$), yields the static environment $\tenvp$; + \item annotating the block $\vstmt$ in $\tenvp$ yields $\newstmt$. + \end{itemize} +\end{itemize} +\CodeSubsection{\CatcherNoneBegin}{\CatcherNoneEnd}{../Typing.ml} + +\subsubsection{Formally} +\begin{mathpar} +\inferrule[none]{ + \annotatetype{\tenv, \vt} \typearrow \ttyp \OrTypeError\\\\ + \checkstructurelabel(\tenv, \ttyp, \TException) \typearrow \True \OrTypeError\\\\ + \annotateblock{\tenv, \vstmt} \typearrow \newstmt \OrTypeError +}{ + \annotatecatcher{\tenv, (\overname{\None}{\nameopt}, \tty, \vstmt)} \typearrow (\overname{\None}{\nameopt}, \ttyp, \newstmt) +} +\end{mathpar} +\lrmcomment{This is related to \identr{SDJK}.} + +\begin{mathpar} +\inferrule[some]{ + \annotatetype{\tenv, \vt} \typearrow \ttyp \OrTypeError\\\\ + \checkstructurelabel(\tenv, \ttyp, \TException) \typearrow \True \OrTypeError\\\\ + \checkvarnotinenv{\tenv, \name} \typearrow \True \OrTypeError\\\\ + \addlocal(\tenv, \name, \ttyp, \LDKLet) \typearrow \tenvp\\ + \annotateblock{\tenvp, \vstmt} \typearrow \newstmt \OrTypeError +}{ + \annotatecatcher{\tenv, (\overname{\langle\name\rangle}{\nameopt}, \tty, \vstmt)} \typearrow + (\overname{\langle\name\rangle}{\nameopt}, \ttyp, \newstmt) +} +\end{mathpar} +\lrmcomment{This is related to \identr{SDJK}, \identr{WVXS}, \identi{FCGK}.} +\CodeSubsection{\CatcherBegin}{\CatcherEnd}{../Typing.ml} + +\section{Semantics} +\subsubsection{SemanticsRule.Catch\label{sec:SemanticsRule.Catch}} +\subsubsection{Prose} +All of the following apply: +\begin{itemize} + \item $\sm$ is $\Throwing((\langle \valuereadfrom(\vv, \eid), \vvty \rangle, \sg), \envthrow)$; + \item $\env$ consists of the static environment $\tenv$ and dynamic environment $\denv$; + \item $\envthrow$ consists of the static environment $\tenv$ and dynamic environment \\ $\denvthrow$; + \item $\envone$ is defined by taking the static environment $\tenv$, the global component of the dynamic + environment from $\denvthrow$ and the local component of the dynamic environment from $\denv$; + \item finding the first catcher with the static environment $\tenv$, the exception type $\vvty$, + and the list of catchers $\catchers$ gives a catcher that does not declare a name ($\None$) and gives a statement $\vs$; + \item evaluating $\vs$ in $\envone$ as a block (\chapref{eval_block}) is not an error + configuration $C$\ProseOrError; + \item editing potential implicit throwing configurations via $\rethrowimplicit(\vv, \vvty, C)$ + gives the configuration $D$; + \item $\newg$ is the ordered composition of $\sg$ and the graph of $D$; + \item the result of the entire evaluation is $D$ with its graph substituted with $\newg$. +\end{itemize} + +\subsubsection{Example} +The specification: +\VerbatimInput{../tests/ASLSemanticsReference.t/SemanticsRule.Catch.asl} +terminates successfully. That is, no dynamic error occurs. + +\CodeSubsection{\EvalCatchBegin}{\EvalCatchEnd}{../Interpreter.ml} + +\subsubsection{Formally} +\begin{mathpar} +\inferrule{ + \sm \eqname \Throwing((\langle \valuereadfrom(\vv, \eid), \vvty \rangle, \sg), \envthrow)\\ + \env \eqname (\tenv, (G^\denv, L^\denv))\\ + \envthrow \eqname (\tenv, (G^{\denvthrow}, L^{\denvthrow}))\\ + \envone \eqdef (\tenv, (G^{\denvthrow}, L^{\denv}))\\ + \findcatcher(\tenv, \vvty, \catchers) \eqname \langle (\None, \Ignore, \vs) \rangle\\ + \evalblock{\envone, \vs} \evalarrow C \OrDynError\\\\ + D \eqdef \rethrowimplicit(\vv, \vvty, C)\\ + \newg \eqdef \ordered{\sg}{\aslpo}{\graphof{D}} +}{ + \evalcatchers{\env, \catchers, \otherwiseopt, \sm} \evalarrow \withgraph{D}{\newg} +} +\end{mathpar} + +\subsubsection{SemanticsRule.CatchNamed\label{sec:SemanticsRule.CatchNamed}} +\subsubsection{Example} +The specification: +\VerbatimInput{../tests/ASLSemanticsReference.t/SemanticsRule.CatchNamed.asl} +prints \texttt{My exception with my message}. + +\subsubsection{Prose} +All of the following apply: +\begin{itemize} + \item $\sm$ is $\Throwing((\langle \valuereadfrom(\vv, \eid), \vvty \rangle, \sg), \envthrow)$; + \item $\env$ consists of the static environment $\tenv$ and dynamic environment $\denv$; + \item $\envthrow$ consists of the static environment $\tenv$ and dynamic environment \\ $\denvthrow$; + \item $\envone$ is defined by taking the static environment $\tenv$, the global component of the dynamic + environment from $\denvthrow$ and the local component of the dynamic environment from $\denv$; + \item finding the first catcher with the static environment $\tenv$, the exception type $\vvty$, + and the list of catchers $\catchers$ gives a catcher that declares the name $\name$ and gives a statement $\vs$; + \item $\vgone$ is the execution graph resulting from reading $\vv$ into the identifier $\eid$; + \item declaring a local identifier $\name$ with $(\veone, \vgone)$ in $\envone$ gives $(\envtwo, \vgtwo)$; + \item evaluating $\vs$ in $\envtwo$ as a block (\chapref{eval_block}) is not an error + configuration $C$\ProseOrError; + \item $\envthree$ is the environment of the configuration $C$; + \item removing the binding for $\name$ from the local component of the dynamic environment in $\envthree$ + gives $\envfour$; + \item substituting the environment of $C$ with $\envfour$ gives $D$; + \item editing potential implicit throwing configurations via $\rethrowimplicit(\vv, \vvty, D)$ + gives the configuration $E$; + \item $\newg$ is the ordered composition of $\sg$, $\vgone$, $\vgtwo$, and the graph of $E$, + with the $\aslpo$ edges; + \item the result of the entire evaluation is $E$ with its graph substituted with $\newg$. +\end{itemize} +\subsubsection{Formally} +\begin{mathpar} + \inferrule{ + \sm \eqname \Throwing((\langle \valuereadfrom(\vv, \eid), \vvty \rangle, \sg), \envthrow)\\ + \env \eqname (\tenv, (G^\denv, L^\denv))\\ + \envthrow \eqname (\tenv, (G^{\denvthrow}, L^{\denvthrow}))\\ + \envone \eqdef (\tenv, (G^{\denvthrow}, L^{\denv}))\\ + \findcatcher(\tenv, \vvty, \catchers) \eqname \langle (\langle\name\rangle, \Ignore, \vs) \rangle\\ + \vgone \eqdef \readidentifier(\eid, \vv)\\ + \declarelocalidentifierm(\envone, \name, (\veone, \vgone)) \evalarrow (\envtwo, \vgtwo)\\ + \evalblock{\envtwo, \vs} \evalarrow C \OrDynError\\\\ + \envthree \eqdef \environof{C}\\ + \removelocal(\envthree, \name) \evalarrow \envfour\\ + D \eqdef \withenviron{C}{\envfour}\\ + E \eqdef \rethrowimplicit(\vv, \vvty, D)\\ + \newg \eqdef \ordered{\sg}{\aslpo}{ \ordered{\ordered{\vgone}{\aslpo}{\vgtwo}}{\aslpo}{\graphof{E}} } + } + { + \evalcatchers{\env, \catchers, \otherwiseopt, \sm} \evalarrow \withgraph{E}{\newg} + } +\end{mathpar} +\CodeSubsection{\EvalCatchNamedBegin}{\EvalCatchNamedEnd}{../Interpreter.ml} + +\subsubsection{SemanticsRule.CatchOtherwise\label{sec:SemanticsRule.CatchOtherwise}} + \subsubsection{Prose} + All of the following apply: + \begin{itemize} + \item $\sm$ is $\Throwing((\langle \valuereadfrom(\vv, \eid), \vvty \rangle, \sg), \envthrow)$; + \item $\env$ consists of the static environment $\tenv$ and dynamic environment $\denv$; + \item $\envthrow$ consists of the static environment $\tenv$ and dynamic environment \\ $\denvthrow$; + \item $\envone$ is defined by taking the static environment $\tenv$, the global component of the dynamic + environment from $\denvthrow$ and the local component of the dynamic environment from $\denv$; + \item finding the first catcher with the static environment $\tenv$, the exception type $\vvty$, + and the list of catchers $\catchers$ gives a catcher that declares the name $\name$ and gives $\None$ + (that is, neither of the \texttt{catch} clauses matches the raised exception); + \item evaluating the \texttt{otherwise} statement $\vs$ in $\envtwo$ as a block (\chapref{eval_block}) + is not an error configuration $C$\ProseOrError; + \item editing potential implicit throwing configurations via $\rethrowimplicit(\vv, \vvty, C)$ + gives the configuration $D$; + \item $\newg$ is the ordered composition of $\sg$ and the graph of $D$, + with the $\aslpo$ edge; + \item the result of the entire evaluation is $D$ with its graph substituted with $\newg$. + \end{itemize} + + \subsubsection{Example} + The specification: + \VerbatimInput{../tests/ASLSemanticsReference.t/SemanticsRule.CatchOtherwise.asl} + prints \texttt{Otherwise}. + + \CodeSubsection{\EvalCatchOtherwiseBegin}{\EvalCatchOtherwiseEnd}{../Interpreter.ml} + +\subsubsection{Formally} +\begin{mathpar} +\inferrule{ + \sm \eqname \Throwing((\langle \valuereadfrom(\vv, \eid), \vvty \rangle, \sg), \envthrow)\\ + \env \eqname (\tenv, (G^\denv, L^\denv))\\ + \envthrow \eqname (\tenv, (G^{\denvthrow}, L^{\denvthrow}))\\ + \envone \eqdef (\tenv, (G^{\denvthrow}, L^{\denv}))\\ + \findcatcher(\tenv, \vvty, \catchers) = \None\\ + \evalblock{\envone, \vs} \evalarrow C \OrDynError\\\\ + D \eqdef \rethrowimplicit(\vv, \vvty, C)\\ + \vg \eqdef \ordered{\sg}{\aslpo}{\graphof{D}} +}{ + \evalcatchers{\env, \catchers, \langle\vs\rangle, \sm} \evalarrow \withgraph{D}{\vg} +} +\end{mathpar} + +\subsubsection{SemanticsRule.CatchNone\label{sec:SemanticsRule.CatchNone}} +\subsubsection{Example} +The specification: +\VerbatimInput{../tests/ASLSemanticsReference.t/SemanticsRule.CatchNone.asl} +does not print anything. + +\subsubsection{Prose} +All of the following apply: +\begin{itemize} + \item $\sm$ is $\Throwing((\langle \valuereadfrom(\vv, \eid), \vvty \rangle, \sg), \envthrow)$; + \item $\env$ consists of the static environment $\tenv$ and dynamic environment $\denv$; + \item $\envthrow$ consists of the static environment $\tenv$ and dynamic environment \\ $\denvthrow$; + \item finding the first catcher with the static environment $\tenv$, the exception type $\vvty$, + and the list of catchers $\catchers$ gives a catcher that declares the name $\name$ and gives $\None$ + (that is, neither of the \texttt{catch} clauses matches the raised exception); + \item since there no \texttt{otherwise} clause, the result is $\sm$. +\end{itemize} +\subsubsection{Formally} +\begin{mathpar} +\inferrule{ + \sm \eqname \Throwing((\langle \valuereadfrom(\vv, \eid), \vvty \rangle, \sg), \envthrow)\\ + \env \eqname (\tenv, \denv)\\ + \findcatcher(\tenv, \vvty, \catchers) = \None +}{ + \evalcatchers{\env, \catchers, \None, \sm} \evalarrow \sm +} +\end{mathpar} +\CodeSubsection{\EvalCatchNoneBegin}{\EvalCatchNoneEnd}{../Interpreter.ml} + +\subsubsection{SemanticsRule.CatchNoThrow\label{sec:SemanticsRule.CatchNoThrow}} +\subsubsection{Example} +The specification: +\VerbatimInput{../tests/ASLSemanticsReference.t/SemanticsRule.CatchNoThrow.asl} +prints \texttt{No exception raised}. + +\subsubsection{Prose} +all of the following apply: +\begin{itemize} + \item One of the following holds: + \begin{itemize} + \item (\textsc{implicit\_throw}) $\sm$ is $\Throwing((\None, \sg), \envthrow)$ (that is, an implicit throw); + \item (\textsc{non\_throwing}) $\sm$ is a normal configuration (that is, the domain of $\sm$ is $\Normal$); + \end{itemize} + \item the result is $\sm$. +\end{itemize} + +\subsubsection{Formally} +\begin{mathpar} +\inferrule[implicit\_throw]{ + \sm \eqname \Throwing((\None, \sg), \envthrow) +}{ + \evalcatchers{\env, \catchers, \Ignore, \sm} \evalarrow \sm +} +\end{mathpar} + +\begin{mathpar} +\inferrule[non\_throwing]{ + \configdomain{\sm} = \Normal +}{ + \evalcatchers{\env, \catchers, \Ignore, \sm} \evalarrow \sm +} +\end{mathpar} +\CodeSubsection{\EvalCatchNoThrowBegin}{\EvalCatchNoThrowEnd}{../Interpreter.ml} + +\subsubsection{SemanticsRule.FindCatcher\label{sec:SemanticsRule.FindCatcher}} +\hypertarget{def-findcatcher}{} +The (recursively-defined) helper relation +\[ + \findcatcher(\overname{\staticenvs}{\tenv} \aslsep \overname{\ty}{\vvty}, \overname{\catcher^*}{\catchers}) + \;\aslrel\; \langle \catcher \rangle \enspace, +\] +returns the first catcher clause in $\catchers$ that matches the type $\vvty$ (as a singleton set), or an empty set ($\None$), +by invoking $\typesat$ with the static environment $\tenv$. + +\subsubsection{Prose} +One of the following applies: +\begin{itemize} + \item All of the following apply (\textsc{empty}): + \begin{itemize} + \item $\catchers$ is an empty list; + \item the result is $\None$. + \end{itemize} + + \item All of the following apply (\textsc{match}): + \begin{itemize} + \item $\catchers$ has $\vc$ as its head and $\catchersone$ as its tail; + \item $\vc$ consists of $(\nameopt, \ety, \vs)$; + \item $\vvty$ type-satisfies $\ety$ in the static environment $\tenv$; + \item the result is the singleton set for $\vc$. + \end{itemize} + + \item All of the following apply (\textsc{no\_match}): + \begin{itemize} + \item $\catchers$ has $\vc$ as its head and $\catchersone$ as its tail; + \item $\vc$ consists of $(\nameopt, \ety, \vs)$; + \item $\vvty$ does not type-satisfy $\ety$ in the static environment $\tenv$; + \item the result of finding a catcher for $\vvty$ with the type environment $\tenv$ in the tail list $\catchersone$ + is $d$; + \item the result is $d$. + \end{itemize} +\end{itemize} + +\subsubsection{Formally} +\begin{mathpar} +\inferrule[empty]{}{\findcatcher(\tenv, \vvty, \emptylist) \evalarrow \None} +\end{mathpar} + +\begin{mathpar} +\inferrule[match]{ + \catchers \eqname [\vc] \concat \catchersone\\ + \vc \eqname (\nameopt, \ety, \vs) \\ + \typesat(\tenv, \vvty, \ety) +}{ + \findcatcher(\tenv, \vvty, \catchers) \evalarrow \langle\vc\rangle +} +\end{mathpar} + +\begin{mathpar} +\inferrule[no\_match]{ + \catchers \eqname [\vc] \concat \catchersone\\ + \vc \eqname (\nameopt, \ety, \vs) \\ + \neg\typesat(\tenv, \vvty, \ety)\\ + d \eqdef \findcatcher(\tenv, \vvty, \catchersone) +}{ + \findcatcher(\tenv, \vvty, \catchers) \evalarrow d +} +\end{mathpar} +\CodeSubsection{\EvalFindCatcherBegin}{\EvalFindCatcherEnd}{../Interpreter.ml} + +\subsubsection{Comments} +\lrmcomment{This is related to \identr{SPNM}:} +When the \texttt{catch} of a \texttt{try} statement is executed, then the +thrown exception is caught by the first catcher in that \texttt{catch} which it +type-satisfies or the \texttt{otherwise\_opt} in that catch if it exists. + +\subsubsection{SemanticsRule.RethrowImplicit\label{sec:SemanticsRule.RethrowImplicit}} + +The helper relation +\hypertarget{def-rethrowimplicit}{} +\[ + \rethrowimplicit(\overname{\valuereadfrom(\vals,\Identifiers)}{\vv} \aslsep \overname{\ty}{\vvty} \aslsep \overname{\TOutConfig}{\vres}) \;\aslrel\; \TOutConfig +\] + +changes \emph{implicit throwing configurations} into \emph{explicit throwing configurations}. +That is, configurations of the form $\Throwing((\None, \vg), \envthrowone))$. + +$\rethrowimplicit$ leaves non-throwing configurations, and \emph{explicit throwing configurations}, +which have the form $\Throwing(\langle(\valuereadfrom(\vv', \eid), \vvty')\rangle, \vg)$, as is. +Implicit throwing configurations are changed by substituting the optional $\valuereadfrom$ configuration-exception type +pair with $\vv$ and $\vvty$, respectively. + +\subsubsection{Prose} +One of the following applies: +\begin{itemize} + \item All of the following apply (\textsc{implicit\_throwing}): + \begin{itemize} + \item $\vres$ is $\Throwing((\None, \vg), \envthrowone)$, which is an implicit throwing configuration; + \item the result is $\Throwing((\langle(\vv, \vvty)\rangle, \vg), \envthrowone)$. + \end{itemize} + + \item All of the following apply (\textsc{explicit\_throwing}): + \begin{itemize} + \item $\vres$ is $\Throwing(\langle(\vv', \vvty')\rangle, \vg)$, which is an explicit throwing configuration + (due to $(\vv', \vvty')$); + \item the result is $\Throwing((\langle(\vv', \vvty')\rangle, \vg), \envthrowone)$. \\ + That is, the same throwing configuration is returned. + \end{itemize} + + \item All of the following apply (\textsc{non\_throwing}): + \begin{itemize} + \item the configuration, $C$, domain is non-throwing; + \item the result is $C$. + \end{itemize} +\end{itemize} +\subsubsection{Formally} +\begin{mathpar} +\inferrule[implicit\_throwing]{} +{ + \rethrowimplicit(\vv, \vvty, \Throwing((\None, \vg), \envthrowone)) \evalarrow \\ + \Throwing((\langle(\valuereadfrom(\vv, \eid), \vvty)\rangle, \vg), \envthrowone) +} +\end{mathpar} + +\begin{mathpar} +\inferrule[explicit\_throwing]{} +{ + \rethrowimplicit(\vv, \vvty, \Throwing((\langle(\vv', \vvty')\rangle, \vg), \envthrowone)) \evalarrow \\ + \Throwing((\langle(\vv', \vvty')\rangle, \vg), \envthrowone) +} +\end{mathpar} + +\begin{mathpar} +\inferrule[non\_throwing]{ + \configdomain{C} \neq \Throwing +}{ + \rethrowimplicit(\Ignore, \Ignore, C, \Ignore) \evalarrow C +} +\end{mathpar} +\CodeSubsection{\EvalRethrowImplicitBegin}{\EvalRethrowImplicitEnd}{../Interpreter.ml} + +\subsubsection{Comments} +\lrmcomment{This is related to \identr{GVKS}:} +An expressionless \texttt{throw} statement causes the exception which the +currently executing catcher caught to be thrown. \ No newline at end of file diff --git a/asllib/doc/ErrorCodes.tex b/asllib/doc/ErrorCodes.tex new file mode 100644 index 000000000..716d4ff1d --- /dev/null +++ b/asllib/doc/ErrorCodes.tex @@ -0,0 +1,179 @@ +\chapter{Error Codes} + +\section{Static Error Codes} +\begin{description} +\hypertarget{def-expectedbitvectortype}{} +\item[$\ExpectedBitvectorType$] +This error indicates that a bitvector type was expected where a non-bitvector type was given. +See \typingrulecasename{CheckBinop}{plus\_minus\_bits\_bits} (\secref{TypingRule.CheckBinop}) for an example. + +\hypertarget{def-expectedenumerationtype}{} +\item[$\ExpectedEnumerationType$] +This error indicates that an enumeration type was expected where a \\ +non-enumeration type was given. +See \secref{TypingRule.TArray} for an example. + +\hypertarget{def-expectedstructuredtype}{} +\item[$\ExpectedStructuredType$] +This error indicates that a \structuredtype\ was expected where a non-\structuredtype\ was given. +See \secref{TypingRule.ERecord} for an example. + +\hypertarget{def-expectedtupletype}{} +\item[$\ExpectedTupleType$] +This error indicates that a tuple type was expected where a non-tuple type was given. +See \secref{TypingRule.LEDestructuring} for an example. + +\hypertarget{def-setterwithoutgetter}{} +\item[$\SetterWithoutGetter$:] +ASL requires each setter for a given identifier to have a corresponding getter for the same +identifier. +The specification either does not contain a getter for the same identifier +or a getter for the same identifier exists, but it does not have the expected +signature (see \secref{TypingRule.CheckSetterHasGetter}). + +\hypertarget{def-undefinedidentifier}{} +\item[$\UndefinedIdentifier$] +An identifier that is missing a definition of the appropriate kind. +See TypingRule.SubprogramForName (\secref{TypingRule.SubprogramForName}) for an example. + +\hypertarget{def-lengthsmismatch}{} +\item[$\LengthsMismatch$] +This error indicates that two lists that are expected to have the same length have different lengths. +See \secref{TypingRule.LEDestructuring} for an example. + +\hypertarget{def-subprogramdeclaredmultipletimes}{} +\item[$\SubrogramDeclaredMultipleTimes$] +At least two subprograms in the specification clash. +See \secref{TypingRule.AddNewFunc} for an example. + +\hypertarget{def-nocallcandidates}{} +\item[$\NoCallCandidates$] +A function call, given by its name and list of formal argument types, does not match any defined subprogram. +See \secref{TypingRule.SubprogramForName} for an example. + +\hypertarget{def-toomanycandidates}{} +\item[$\TooManyCandidates$] +A function call, given by its name and list of formal argument types, matches more than one subprogram, +which does not allow the type-checker to decide which subprogram the call refers to. +See \secref{TypingRule.SubprogramForName} for an example. + +\hypertarget{def-parameterwithoutdecl}{} +\item[$\ParameterWithoutDecl$] +A subprogram includes a parameter that is not associated with any variable appearing in one of the arguments. +See \secref{TypingRule.AnnotateParams} for an example. + +\hypertarget{def-nolca}{} +\item[$\NoLCA$] +A conditional expressions results in two types that have no common ancestor type that can represent both. +See \secref{TypingRule.LowestCommonAncestor} for an example. + +\hypertarget{def-mrv}{} +\item[$\MismatchedReturnValue$] +A call to a function must result in a returned value, +whereas a call to a procedure must not. +This error occurs when a call to a function or a getter is inferred to refer to a procedure or a setter, +or a call to a procedure or a setter is inferred to refer to a function or a getter. +See \secref{TypingRule.AnnotateCallArgTyped} for an example. + +\hypertarget{def-cba}{} +\item[$\CallBadArity$] +A call to a subprogram must have the same number of arguments as the list of formal arguments +declared for the subprogram. +This error indicates that the number of arguments is different to the number of declared formal arguments. +See \secref{TypingRule.AnnotateCallArgTyped} for an example. + +\hypertarget{def-brd}{} +\item[$\BadRecursiveDecls$] +Only subprogram declarations may be mutually recursive. +This error indicates that at least one declaration in a given list of mutually recursive declarations +is not a subprogram. +See \secref{TypingRule.TypeCheckMutuallyRec} for an example. + +\hypertarget{def-lbi}{} +\item[$\RequireIntegerForLoopBounds$] +The expressions defining the bounds of a \texttt{for} loop are required to have the \structure\ of +an integer type. +This error indicates that at least one of the start expression and end expression violate this +requirement. +See \secref{TypingRule.TypeCheckMutuallyRec} for an example. + +\hypertarget{def-mfi}{} +\item[$\MissingFieldInitializer$] +This error indicates that an initialization of a \structuredtype\ is missing an expression to initialize +one of its fields. +See \secref{TypingRule.ERecord} for an example. + +\hypertarget{def-rsb}{} +\item[$\RequireSameBitwidths$] +This error indicates that two bitvector types are required to have the same bitwidths but the type-checker +was not able to prove it. +See \secref{BitvectorOperations} for an example. + +\hypertarget{def-taf}{} +\item[$\TypeAsssertionFails$] +This error indicates that a given at type assertion expression will always fail. +See \secref{TypingRule.CheckATC} for an example. + +\hypertarget{def-ofc}{} +\item[$\BinaryOperationFailsAllConstraints$] +This error indicates that a binary expression appearing in a constraint will always fail dynamically. +This means that the set of values that the type containing +the constraint can take is empty. +See \secref{TypingRule.BinopFilterRhs} for an example. + +\hypertarget{def-otb}{} +\item[$\InvalidOperandTypesForBinop$] +This error indicates that the operator of a binary expression cannot be applied to its operand expressions +due to their types. +See \secref{TypingRule.CheckBinop} for an example. + +\hypertarget{def-iaf}{} +\item[$\AnnonymousFormNotAllowedHere$] +This error indicates that an anonymous type is being used as a type annotation in a context +where anonymous types are not allowed. +See \secref{TypingRule.TNonDecl} for an example. + +\hypertarget{def-aim}{} +\item[$\AssignmentToImmutable$] +This error indicates that an assignment has a left-hand-side storage element that is immutable. +See \secref{TypingRule.LEVar} for an example. + +\hypertarget{def-mf}{} +\item[$\MissingField$] +This error indicates that an access is made (for either reading or writing) to a field that is +not declared by the respective \structuredtype\ or a bitfield that is not declared by the respective +bitvector type. +See \secref{TypingRule.LESetStructuredField} for an example. + +\hypertarget{def-dii}{} +\item[$\DivIntIndivisible$] +This error indicates that a \staticallyevaluable\ expression contain an integer division expression where +the denominator does not divide the numerator. +See \textsc{TypingRule.BinopLiterals.DIV\_INT} (\secref{TypingRule.BinopLiterals}) for an example. + +\hypertarget{def-bot}{} +\item[$\BitfieldsOutOfRange$] +This error indicates that at least one bitfield is declared with indices that go out of the range +$[0, \vwidth]$ where $\vwidth$ is the width of the enclosing bitvector type. +See \textsc{TypingRule.CheckPositionsInWidth} (\secref{TypingRule.CheckPositionsInWidth}). + +\hypertarget{def-bso}{} +\item[$\BitfieldSlicesOverlap$] +This error indicates that two bitfield slices defined for a bitvector type have overlapping ranges. +This is checked by \nameref{sec:TypingRule.DisjointSlicesToPositions}. + +\hypertarget{def-bsr}{} +\item[$\BitfieldSliceReversed$] +This error indicates that a bitfield slice is defined such that its upper position is less than its lower position. +This is checked by \nameref{sec:TypingRule.BitfieldSliceToPositions}. + +\hypertarget{def-icc}{} +\item[$\IntConstantExpected$] +This error indicates that a given expression was expected to statically evaluate +to an integer-typed literal but either evaluated to a literal of a different type +or could not be statically evaluated to a literal. +This is checked by \nameref{sec:TypingRule.BitfieldSliceToPositions}. + +\end{description} + +\section{Dynamic Error Codes} diff --git a/asllib/doc/Expressions.tex b/asllib/doc/Expressions.tex new file mode 100644 index 000000000..18c665702 --- /dev/null +++ b/asllib/doc/Expressions.tex @@ -0,0 +1,2669 @@ +\chapter{Expressions\label{chap:Expressions}} + +Expressions calculate values. +Expressions can have side effects and can raise exceptions and, therefore, there are constraints on the evaluation +order and on the side-effects/exceptions to avoid surprising or unpredictable behavior (see \secref{PriorityAndAssociativity}). + +Expressions are grammatically derived from $\Nexpr$ and represented as ASTs by $\expr$. +We will often refer to expressions defined in this chapter as \rhsexpressions\ to distinguish them +from \assignableexpressions, which are defined in \chapref{AssignableExpressions}. + +\hypertarget{build-expr}{} +The function +\[ + \buildexpr(\overname{\parsenode{\Nexpr}}{\vparsednode}) \;\aslto\; \overname{\expr}{\vastnode} +\] +transforms an expression parse node $\vparsednode$ into an expression AST node $\vastnode$. + +All expressions have a unique type (which can be a tuple type). +\hypertarget{def-annotateexpr}{} +The function +\[ + \annotateexpr{\overname{\staticenvs}{\tenv} \aslsep \overname{\expr}{\ve}} + \aslto (\overname{\ty}{\vt} \times \overname{\expr}{\newe}) + \cup \overname{\TTypeError}{\TypeErrorConfig} +\] +specifies how to annotate an expression $\ve$ in +an environment \tenv. The result of annotating the expression +$\ve$ in \tenv\ is the pair $(\vt, \newe)$, where $\vt$ is the type inferred +for $\ve$ and +$\newe$ is the \typedast\ for $\ve$, also known as the \emph{annotated expression}. \ProseOtherwiseTypeError + +The annotation rewrites the input expression in the following cases, making the annotation of statements simpler: +\begin{itemize} + \item Variables with constant values are substituted by their constant values. + \item Slicing expressions that correspond to calling a getter are replaced with respective call expressions. + \item Slicing expressions that correspond to \arrayaccess\ expressions are replaced by \arrayaccess\ expressions. +\end{itemize} + +The relation +\hypertarget{def-evalexpr}{} +\[ + \evalexpr{\overname{\envs}{\env} \aslsep \overname{\expr}{\ve}} \;\aslrel\; + \Normal((\overname{\vals}{\vv} \times \overname{\XGraphs}{\vg}) \aslsep \overname{\envs}{\newenv}) \cup + \overname{\TThrowing}{\ThrowingConfig} \cup \overname{\TError}{\ErrorConfig} +\] +evaluates the expression $\ve$ in an environment $\env$ and one of the following applies: +\begin{itemize} + \item the evaluation terminates normally, returning a \nativevalue\ $\vv$, a concurrent execution graph $\vg$, + and a modified environment $\newenv$; + \item the evaluation terminates abnormally. +\end{itemize} + +\section{Evaluation Order} +It is an error for an expression’s meaning to rely on evaluation order except that conditional expressions, and uses +of the boolean operators $\Tband$, $\Tbor$, $\Timpl$, are guaranteed to evaluate from left to right. +\lrmcomment{\identr{XKGC}} + +An implementation could enforce this rule by performing a global analysis of all functions to determine whether a +function can throw an exception and the set of global variables read and written by a function. +\lrmcomment{\identi{YMRT}} + +For any function call $F(e_1,\ldots,e_m)$, tuple $(e_1,\ldots, e_m)$, or operation $e_1 \op e_2$ +(with the exception of $\Tband$, $\Tbor$, and$\Timpl$), +it is an error if the subexpressions conflict with each other by: +\begin{itemize} + \item both writing to the same variable. + \item one writing to a variable and the other reading from that same variable. + \item one writing to a variable and the other throwing an exception. + \item both throwing exceptions. +\end{itemize} +\lrmcomment{\identi{QJTN}} + +These conditions are sufficient but not necessary to ensure that evaluation order does not affect the result of an +expression, including any side-effects. +\lrmcomment{\identi{GFZT}} + +Conditional expressions and the operations $\Tband$, $\Tbor$, and$\Timpl$ have short-circuit evaluation. +\lrmcomment{\identi{QRXP}} + +We now define the syntax, abstract syntax, typing, and semantics of the following kinds of expressions: +\begin{itemize} + \item Literal expressions (see \secref{LiteralExpressions}) + \item Variable expressions (see \secref{VariablExpressions}) + \item Binary expressions (see \secref{BinaryExpressions}) + \item Unary expressions (see \secref{UnaryExpressions}) + \item Conditional expressions (see \secref{ConditionalExpressions}) + \item Call expressions (see \secref{CallExpressions}) + \item Slicing expressions (see \secref{SlicingExpressions}) + \item Field reading expressions (see \secref{FieldReadingExpressions}) + \item Bitvector concatenation expressions (see \secref{BitvectorConcatenationExpressions}) + \item Asserting type conversion expressions (see \secref{AssertingTypeConversionExpressions}) + \item Pattern matching expressions (see \secref{PatternMatchingExpressions}) + \item Arbitrary value expressions (see \secref{ArbitraryValueExpressions}) + \item Structured type construction expressions (see \secref{StructuredTypeConstructionExpressions}) + \item Tuple expressions (see \secref{TupleExpressions}) + \item Parenthesized expressions (see \secref{ParenthesizedExpressions}) +\end{itemize} + +Finally, we define side-effect-free expressions (see \secref{SideEffectFreeExpressions}) + +\section{Literal Expressions\label{sec:LiteralExpressions}} +A literal expression represents a literal as an expression. + +\subsection{Syntax} +\begin{flalign*} +\Nexpr \derives\ & \Nvalue &\ +\end{flalign*} + +\subsection{Abstract Syntax} +\begin{flalign*} +\expr \derives\ & \ELiteral(\literal) & +\end{flalign*} + +\subsubsection{ASTRule.ELit\label{sec:ASTRule.ELit}} +\begin{mathpar} +\inferrule{}{ + \buildexpr(\overname{\Nexpr(\punnode{\Nvalue})}{\vparsednode}) \astarrow + \overname{\ELiteral(\astof{\vvalue})}{\vastnode} +} +\end{mathpar} + +\subsection{Typing} +\subsubsection{TypingRule.ELit\label{sec:TypingRule.ELit}} +\subsubsection{Prose} +All of the following apply: +\begin{itemize} +\item $\ve$ is the literal expression $\vv$; +\item $\vt$ is the type of the literal $\vv$; +\item $\newe$ is $\ve$. +\end{itemize} +\subsubsection{Formally} +\begin{mathpar} +\inferrule{ + \annotateliteral{\vv} \typearrow \vt +}{ + \annotateexpr{\tenv, \overname{\ELiteral(\vv)}{\ve}} \typearrow (\vt, \overname{\ELiteral(\vv)}{\newe}) +} +\end{mathpar} +\CodeSubsection{\ELitBegin}{\ELitEnd}{../Typing.ml} + +\subsection{Semantics} +\subsubsection{Example} +In the specification: +\ASLExample{\semanticstests/SemanticsRule.Lit.asl} +each of the expressions \texttt{3} evaluates to the \nativevalue\ $\nvint(3)$. + +\subsubsection{SemanticsRule.ELit \label{sec:SemanticsRule.ELit}} +\subsubsection{Prose} +All of the following apply: +\begin{itemize} +\item $\ve$ is the literal expression for $\vl$, that is, $\ELiteral(\vl)$ +\item $\vv$ is the \nativevalue\ corresponding to $\vl$; +\item $\vg$ is the empty graph, as literals do not yield any Read and Write Effects; +\item $\newenv$ is $\env$. +\end{itemize} +\subsubsection{Formally} +\begin{mathpar} +\inferrule{}{ + \evalexpr{\env, \overname{\ELiteral(\vl)}{\ve}} \evalarrow \Normal((\overname{\nvliteral{\vl}}{\vv},\overname{\emptygraph}{\vg}), \overname{\env}{\newenv}) +} +\end{mathpar} +\CodeSubsection{\EvalELitBegin}{\EvalELitEnd}{../Interpreter.ml} + +\section{Variable Expressions\label{sec:VariablExpressions}} +A variable expression represents consists of an identifier. +The identifier stands for either a storage element or the name of a getter with no arguments. + +\subsection{Syntax} +\begin{flalign*} +\Nexpr \derives\ & \Tidentifier & +\end{flalign*} + +\subsection{Abstract Syntax} +\begin{flalign*} +\expr \derives\ & \EVar(\overtext{\identifier}{variable name}) & +\end{flalign*} + +\subsubsection{ASTRule.EVAR} +\begin{mathpar} + \inferrule{}{ + \buildexpr(\overname{\Nexpr(\Tidentifier(\id))}{\vparsednode}) \astarrow + \overname{\EVar(\id)}{\vastnode} +} +\end{mathpar} + +\subsection{Typing} +\subsubsection{TypingRule.EVar \label{sec:TypingRule.EVar}} +\subsubsection{Prose} +One of the following applies: +\begin{itemize} + \item All of the following apply (\textsc{local\_constant}): + \begin{itemize} + \item $\ve$ denotes a local variable $\vx$; + \item $\vx$ is bound to a local constant $\vv$ of type $\vt$ in the local environment given by $\tenv$; + \item $\newe$ is the Literal $\vv$. + \end{itemize} + + \item All of the following apply (\textsc{local\_non\_constant}): + \begin{itemize} + \item $\ve$ denotes a local variable $\vx$; + \item $\vx$ is not bound to a constant in the local environment given by $\tenv$; + \item $\vx$ has type $\vt$ in the local environment given by $\tenv$; + \item $\newe$ is $\ve$. + \end{itemize} + + \item All of the following apply (\textsc{global\_constant\_val}): + \begin{itemize} + \item $\ve$ denotes a global variable $\vx$; + \item $\vx$ is bound to a constant $\vv$ of type $\tty$ in the global environment given by $\tenv$; + \item $\vt$ is $\tty$; + \item $\newe$ is the Literal for $\vv$. + \end{itemize} + + \item All of the following apply (\textsc{global\_constant\_no\_val}): + \begin{itemize} + \item $\ve$ denotes a global variable $\vx$; + \item $\vx$ is not bound to constant in the global environment given by $\tenv$; + \item $\vt$ is $\tty$; + \item $\newe$ is $\ve$. + \end{itemize} + + \item All of the following apply (\textsc{global\_var}): + \begin{itemize} + \item $\ve$ denotes a global variable $\vx$; + \item $\vx$ is not bound to a global constant; + \item $\vx$ has type $\tty$ in the global environment given by $\tenv$; + \item $\vt$ is $\tty$; + \item $\newe$ is $\ve$. + \end{itemize} + + \item All of the following apply (\textsc{error\_undefined}): + \begin{itemize} + \item $\ve$ is a variable $\vx$; + \item $\vx$ is not bound to a type in $\tenv$; + \item the result is a type error indicating that $\vx$ is an undefined identifier. + \end{itemize} +\end{itemize} + +\subsubsection{Formally} +\begin{mathpar} +\inferrule[empty\_getter]{ + \shouldreducetocall(\tenv, \vx, \STEmptyGetter) \typearrow \True\\ + \annotatecall(\tenv, \vx, \emptylist, \STEmptyGetter) \typearrow (\name, \vargs, \eqs, \langle\vt\rangle) \OrTypeError\\ +}{ + \annotateexpr{\tenv, \overname{\EVar(\vx)}{\ve}} \typearrow (\vt, \overname{\ECall(\name, \vargs, \eqs)}{\newe}) +} +\end{mathpar} + +\begin{mathpar} +\inferrule[local\_constant]{ + \shouldreducetocall(\tenv, \vx, \STEmptyGetter) \typearrow \False\\ + L^\tenv.\constantvalues(\vx) = \vv\\ + L^\tenv.\localstoragetypes(\vx) = (\vt, \LDKConstant) +}{ + \annotateexpr{\tenv, \overname{\EVar(\vx)}{\ve}} \typearrow (\vt, \overname{\eliteral{\vv}}{\newe}) +} +\end{mathpar} + +\begin{mathpar} +\inferrule[local\_non\_constant]{ + \shouldreducetocall(\tenv, \vx, \STEmptyGetter) \typearrow \False\\ + L^\tenv.\constantvalues(\vx) = \bot\\ + L^\tenv.\localstoragetypes(\vx) = (\vt, k) \\ + k \in \{\LDKVar, \LDKLet\} +}{ + \annotateexpr{\tenv, \overname{\EVar(\vx)}{\ve}} \typearrow (\vt, \overname{\EVar(\vx)}{\newe}) +} +\end{mathpar} + +\begin{mathpar} +\inferrule[global\_constant\_val]{ + \shouldreducetocall(\tenv, \vx, \STEmptyGetter) \typearrow \False\\ + G^\tenv.\globalstoragetypes(\vx) = (\tty, \GDKConstant)\\ + G^\tenv.\constantvalues(\vx) = \vv +}{ + \annotateexpr{\tenv, \EVar(\vx)} \typearrow (\tty, \eliteral{\vv}) +} +\end{mathpar} + +\begin{mathpar} +\inferrule[global\_constant\_no\_val]{ + \shouldreducetocall(\tenv, \vx, \STEmptyGetter) \typearrow \False\\ + G^\tenv.\globalstoragetypes(\vx) = (\tty, \GDKConstant)\\ + G^\tenv.\constantvalues(\vx) = \bot +}{ + \annotateexpr{\tenv, \EVar(\vx)} \typearrow (\tty, \EVar(\vx)) +} +\end{mathpar} + +\begin{mathpar} +\inferrule[global\_var]{ + \shouldreducetocall(\tenv, \vx, \STEmptyGetter) \typearrow \False\\ + G^\tenv.\constantvalues(\vx) = \bot\\ + G^\tenv.\globalstoragetypes(\vx) = (\tty, k)\\ + k \neq \GDKConstant +}{ + \annotateexpr{\tenv, \EVar(\vx)} \typearrow (\tty, \EVar(\vx)) +} +\end{mathpar} + +\begin{mathpar} +\inferrule[error\_undefined]{ + \shouldreducetocall(\tenv, \vx, \STEmptyGetter) \typearrow \False\\ + G^\tenv.\globalstoragetypes(\vx) = \bot\\ + L^\tenv.\globalstoragetypes(\vx) = \bot\\ +}{ + \annotateexpr{\tenv,\overname{\EVar(\vx)}{\ve}} \typearrow \TypeErrorVal{\UndefinedIdentifier} +} +\end{mathpar} + +\subsubsection{Comments} +Our type system does not currently address assignments of non-constant expressions (for example, +function calls) to global constant variables. +\CodeSubsection{\EUndefIdentBegin}{\EUndefIdentEnd}{../Typing.ml} + +\subsection{Semantics} +\subsubsection{SemanticsRule.EVar \label{sec:SemanticsRule.EVar}} +\subsubsection{Prose} +All of the following apply: +\begin{itemize} + \item $\ve$ denotes a variable expression, that is, $\EVar(\vx)$; + \item One of the following applies: + \begin{itemize} + \item All of the following apply (\textsc{local}): + \begin{itemize} + \item $\vx$ is bound locally in $\env$; + \item $\vv$ is the value of $\vx$ in the local component of $\env$; + \end{itemize} + + \item All of the following apply (\textsc{global}): + \begin{itemize} + \item $\vx$ is bound globally in $\env$; + \item $\vv$ is the value of $\vx$ in the global component of $\env$; + \end{itemize} + \end{itemize} + \item $\newenv$ is $\env$; + \item $\vg$ is the graph containing a single Read Effect for $\vx$. +\end{itemize} + +\subsubsection{Formally} +\begin{mathpar} +\inferrule[local]{ + \env \eqname (\Ignore, \denv)\\ + \vx \in \dom(L^\denv) +}{ + \evalexpr{\env, \EVar(\vx)} \evalarrow \Normal((\overname{L^\denv(\vx)}{\vv}, \overname{\ReadEffect(\vx)}{\vg}), \overname{\env}{\newenv}) +} +\end{mathpar} + +\begin{mathpar} +\inferrule[global]{ + \env \eqname (\Ignore, \denv)\\ + \vx \in \dom(G^\denv) +}{ + \evalexpr{\env, \EVar(\vx)} \evalarrow \Normal((\overname{G^\denv(\vx)}{\vv}, \overname{\ReadEffect(\vx)}{\vg}), \overname{\env}{\newenv}) +} +\end{mathpar} +\CodeSubsection{\EvalEVarBegin}{\EvalEVarEnd}{../Interpreter.ml} + +\subsubsection{Comments} +When there exists a global variable $\vx$, the type system +forbids having $\vx$ as a local variable. +This is enforced by \nameref{sec:TypingRule.LDVar} in the Chapter ``Typing of Local Declarations'', +and +\nameref{sec:TypingRule.DeclareGlobalStorage} and \nameref{sec:TypingRule.DeclareOneFunc}, +both in the Chapter ``Typing of Global Declarations''. + +\subsubsection{Example} +In the specification: +\ASLExample{\semanticstests/SemanticsRule.ELocalVar.asl} +the evaluation of \texttt{x} within \texttt{assert x == 3;} uses SemanticsRule.EVar.LOCAL. + +\subsubsection{Example} +In the specification: +\ASLExample{\semanticstests/SemanticsRule.EGlobalVar.asl} +the evaluation of~\texttt{global\_x} within~\texttt{assert global\_x == 3;} +uses the rule \\ SemanticsRule.EVar.GLOBAL. + +\section{Binary Expressions\label{sec:BinaryExpressions}} +\subsection{Syntax} +\begin{flalign*} +\Nexpr \derives\ & \Nexpr \parsesep \Nbinop \parsesep \Nexpr &\ +\end{flalign*} + +\subsection{Abstract Syntax} +\begin{flalign*} +\expr \derives\ & \EBinop(\binop, \expr, \expr) & +\end{flalign*} + +\subsubsection{ASTRule.Binop} +\begin{mathpar} + \inferrule{ + \buildexpr(\veone) \astarrow \astversion{\veone}\\ + \buildexpr(\vetwo) \astarrow \astversion{\vetwo} + }{ + { + \begin{array}{r} + \buildexpr(\overname{\Nexpr(\namednode{\veone}{\Nexpr}, \punnode{\Nbinop}, \namednode{\vetwo}{\Nexpr})}{\vparsednode}) \astarrow\\ + \overname{\EBinop(\astversion{\veone}, \astof{\vbinop}, \astversion{\vetwo})}{\vastnode} + \end{array} + } +} +\end{mathpar} + +\subsection{Typing} +\subsubsection{TypingRule.Binop\label{sec:TypingRule.Binop}} +\subsubsection{Prose} +All of the following apply: +\begin{itemize} + \item $\ve$ denotes a binary operation $\op$ over two expressions $\veone$ and $\vetwo$, that is, \\ $\EBinop(\op, \veone, \vetwo)$; + \item the result of annotating $\veone$ in $\tenv$ is $(\vtone, \veonep)$\ProseOrTypeError; + \item the result of annotating $\vetwo$ in $\tenv$ is $(\vttwo, \vetwop)$\ProseOrTypeError; + \item the result of checking compatibility of $\op$ with $\vtone$ and $\vttwo$ as per \secref{TypingRule.CheckBinop} + is $\vt$\ProseOrTypeError; + \item $\newenv$ denotes $\op$ over $\veonep$ and $\vetwop$. +\end{itemize} +\subsubsection{Formally} +\begin{mathpar} +\inferrule{ + \annotateexpr{\tenv, \veone} \typearrow (\vtone, \veone') \OrTypeError\\\\ + \annotateexpr{\tenv, \vetwo} \typearrow (\vttwo, \vetwo') \OrTypeError\\\\ + \CheckBinop(\tenv, \op, \vtone, \vttwo) \typearrow \vt \OrTypeError +}{ + \annotateexpr{\tenv, \overname{\EBinop(\op, \veone, \vetwo)}{\ve}} \typearrow (\vt, \overname{\EBinop(\op, \veone', \vetwo')}{\newe}) +} +\end{mathpar} +\CodeSubsection{\BinopBegin}{\BinopEnd}{../Typing.ml} + +\subsection{Semantics} +\subsubsection{SemanticsRule.BinopAnd \label{sec:SemanticsRule.BinopAnd}} +\subsubsection{Prose} +All of the following apply: +\begin{itemize} +\item $\ve$ denotes a conjunction over two expressions, + $\EBinop(\BAND, \veone, \vetwo)$; +\item $C$ is the result of the evaluation of the expression + \texttt{if e1 then e2 else false} (see \secref{SemanticsRule.ECond}). +\end{itemize} + +\subsubsection{Example} +\ASLExample{\semanticstests/SemanticsRule.EBinopAndFalse.asl} +the expression \texttt{FALSE \&\& fail()} evaluates to the value \texttt{FALSE}. Notice that the function \texttt{fail} is never called. + +\CodeSubsection{\EvalBinopAndBegin}{\EvalBinopAndEnd}{../Interpreter.ml} + +\subsubsection{Formally} +\begin{mathpar} +\inferrule{ + \falsep \eqdef \ELiteral(\lbool(\False))\\ + \evalexpr{\env, \ECond(\veone, \vetwo, \falsep)} \evalarrow C +}{ +\evalexpr{\env, \EBinop(\BAND, \veone, \vetwo)} \evalarrow C +} +\end{mathpar} + +\subsubsection{Comments} +The evaluation via the rule above ensures that $\veone$ is evaluated first and +only if it evaluates to $\True$ is $\vetwo$ evaluated. + +\lrmcomment{This is related to \identr{BKNT}: add table} + +\lrmcomment{This is related to \identr{XKGC}:} + +It is an error for an expression’s meaning to rely on evaluation order except +that conditional expressions, and uses of the boolean operators \texttt{\&\&}, +\texttt{||},\texttt{-->}, are guaranteed to evaluate from left to right. + +\lrmcomment{This is related to \identi{YMRT}:} + +An implementation could enforce this rule by performing a global analysis of +all functions to determine whether a function can throw an exception and the +set of global variables read and written by a function. + +\lrmcomment{This is related to \identi{QRXP}:} +Conditional expressions and the operations \texttt{\&\&}, \texttt{||}, +\texttt{-->} provide a short-circuit evaluation mechanism: + +\lrmcomment{This is related to the note under \identr{LRHD}:} +\begin{itemize} +\item the first operand of \texttt{if} is always evaluated but only one of the +remaining operands is evaluated; +\item if the first operand of \texttt{and\_bool} is $\False$, then the second operand is not evaluated; +\item if the first operand of \texttt{or\_bool} is $\True$, then the second operand is not evaluated; and, +\item if the first operand of \texttt{implies\_bool} is $\False$, then the +second operand is not evaluated. +\end{itemize} + +However, note that relying on this short-circuit evaluation can be confusing +for readers of ASL specifications and as a consequence it is recommended that +an if-statement is used to achieve the same effect. + +\subsubsection{SemanticsRule.BinopOr \label{sec:SemanticsRule.BinopOr}} +\subsubsection{Prose} +All of the following apply: +\begin{itemize} +\item $\ve$ denotes a disjunction of two expressions, $\EBinop(\BOR, \veone, \vetwo)$; +\item $C$ is the result of the evaluation of + \texttt{if e1 then true else e2} (see \secref{SemanticsRule.ECond}). +\end{itemize} + +\subsubsection{Example} +\ASLExample{\semanticstests/SemanticsRule.EBinopOrTrue.asl} +The expression \texttt{(0 == 1) || (1 == 1)} evaluates to the value \True. + +\CodeSubsection{\EvalBinopOrBegin}{\EvalBinopOrEnd}{../Interpreter.ml} + +\begin{mathpar} +\inferrule{ + \truep \eqdef \ELiteral(\lbool(\True))\\ + \evalexpr{\env, \ECond(\veone, \truep, \vetwo)} \evalarrow C +}{ +\evalexpr{\env, \EBinop(\BOR, \veone, \vetwo)} \evalarrow C +} +\end{mathpar} +The evaluation via the rule above ensures that $\veone$ is evaluated first and only if +it evaluates to $\False$, is $\vetwo$ evaluated. + +\subsubsection{Comments} +\lrmcomment{This is related to \identr{BKNT}: add table} + +\lrmcomment{This is related to \identr{XKGC}:} + +It is an error for an expression’s meaning to rely on +evaluation order except that conditional expressions, and uses of the boolean +operators \texttt{\&\&}, \texttt{||}, \texttt{-->}, are guaranteed to evaluate +from left to right. + +\lrmcomment{This is related to \identi{YMRT}:} + +An implementation could enforce this rule by performing a global analysis of +all functions to determine whether a function can throw an exception and the +set of global variables read and written by a function. + +\lrmcomment{This is related to \identi{QRXP}:} +Conditional expressions and the operations \texttt{\&\&}, \texttt{||}, +\texttt{-->} provide a short-circuit evaluation mechanism: + +\lrmcomment{This is related to the note under \identr{LRHD}:} +\begin{itemize} +\item the first operand of \texttt{if} is always evaluated but only one of the +remaining operands is evaluated; +\item if the first operand of \texttt{and\_bool} is $\False$, then the second operand is not evaluated; +\item if the first operand of \texttt{or\_bool} is $\True$, then the second operand is not evaluated; and, +\item if the first operand of \texttt{implies\_bool} is $\False$, then the +second operand is not evaluated. +\end{itemize} + +However, note that relying on this short-circuit evaluation can be confusing +for readers of ASL specifications and as a consequence it is recommended that +an if-statement is used to achieve the same effect. + +\subsubsection{SemanticsRule.BinopImpl \label{sec:SemanticsRule.BinopImpl}} +\subsubsection{Prose} +All of the following apply: +\begin{itemize} + \item $\ve$ denotes an implication over two expressions, $\EBinop(\IMPL, \veone, \vetwo)$; + \item $\ve$ is evaluated as \texttt{if e1 then e2 else true}. +\end{itemize} + +\subsubsection{Example} +\ASLExample{\semanticstests/SemanticsRule.EBinopImplExFalso.asl} +the expression \texttt{(0 == 1) --> (1 == 0)} evaluates to the value \True, according to the definition of implication. + + \CodeSubsection{\EvalBinopImplBegin}{\EvalBinopImplEnd}{../Interpreter.ml} + + \begin{mathpar} + \inferrule{ + \truep \eqdef \ELiteral(\lbool(\True))\\ + \evalexpr{\env, \ECond(\veone, \vetwo, \truep)} \evalarrow C + } + { + \evalexpr{\env, \EBinop(\IMPL, \veone, \vetwo)} \evalarrow C + } + \end{mathpar} + The evaluation via the rule above ensures that $\veone$ is evaluated first and only if + it evaluates to \True, is $\vetwo$ evaluated. + + +\lrmcomment{This is related to \identr{BKNT}: add table} + +\lrmcomment{This is related to \identi{QRXP}:} +Conditional expressions and the operations \texttt{\&\&}, \texttt{||}, +\texttt{-->} provide a short-circuit evaluation mechanism: + +\lrmcomment{This is related to the note under \identr{LRHD}:} +\begin{itemize} +\item the first operand of \texttt{if} is always evaluated but only one of the +remaining operands is evaluated; +\item if the first operand of \texttt{and\_bool} is $\False$, then the second operand is not evaluated; +\item if the first operand of \texttt{or\_bool} is $\True$, then the second operand is not evaluated; and, +\item if the first operand of \texttt{implies\_bool} is $\False$, then the +second operand is not evaluated. +\end{itemize} + +However, note that relying on this short-circuit evaluation can be confusing +for readers of ASL specifications and as a consequence it is recommended that +an if-statement is used to achieve the same effect. + +\subsubsection{SemanticsRule.Binop \label{sec:SemanticsRule.Binop}} +\subsubsection{Prose} +All of the following apply: +\begin{itemize} + \item $\ve$ denotes a Binary Operator $\op$ over two expressions, $\EBinop(\op, \veone, \vetwo)$; + \item the operator $\op$ is not one of $\BAND$, $\BOR$, or $\IMPL$. + These operators are handled by rules + SemanticsRule.BinopAnd (\secref{SemanticsRule.BinopAnd}), + SemanticsRule.BinopOr \\ (\secref{SemanticsRule.BinopOr}), and + SemanticsRule.BinopImpl (\secref{SemanticsRule.BinopImpl}); + \item the evaluation of the expression $\veone$ in $\env$ is the configuration \\ + $\Normal(\vmone, \envone)$\ProseOrAbnormal; + \item the evaluation of the expression $\vetwo$ in $\envone$ is the configuration \\ + $\Normal(\vmtwo, \newenv)$\ProseOrAbnormal; + \item $\vmone$ consists of the value $\vvone$ and the execution graph $\vgone$; + \item $\vmtwo$ consists of the value $\vvtwo$ and the execution graph $\vgtwo$; + \item applying the Binary Operator $\op$ to $\vvone$ and $\vvtwo$ results in $\vv$\ProseOrError; + \item $\vg$ is the parallel composition of $\vgone$ and $\vgtwo$. +\end{itemize} + +\subsubsection{Example} +In this specification: +\ASLExample{\semanticstests/SemanticsRule.EBinopPlusAssert.asl} +the expression \texttt{3 + 2} evaluates to the value \texttt{5}. + +\subsubsection{Example} +In the specification: +\ASLExample{\semanticstests/SemanticsRule.EBinopDIVBackendDefinedError.asl} +the expression \texttt{3 DIV 0} results in a type error. + +\CodeSubsection{\EvalBinopBegin}{\EvalBinopEnd}{../Interpreter.ml} + +\subsubsection{Formally} +\begin{mathpar} +\inferrule{\op \not\in \{\BAND, \BOR, \IMPL\}\\ + \evalexpr{ \env, \veone} \evalarrow \Normal(\vmone, \envone) \OrAbnormal \\\\ + \evalexpr{ \envone, \vetwo } \evalarrow \Normal(\vmtwo, \newenv) \OrAbnormal \\\\ + \vmone \eqname (\vvone, \vgone) \\ + \vmtwo \eqname (\vvtwo, \vgtwo) \\ + \binoprel(\op, \vvone, \vvtwo) \evalarrow \vv \OrDynError\\\\ + \vg \eqdef \vgone \parallelcomp \vgtwo +}{ + \evalexpr{ \env, \overname{\EBinop(\op, \veone, \vetwo)}{\ve} } \evalarrow + \Normal((\vv, \vg), \newenv) +} +\end{mathpar} + +The rule above applies to many binary operators, including $\EQOP$ (which is used for \texttt{<->} +as well as \texttt{==}). + +\subsubsection{Comments} +\lrmcomment{This is related to \identr{BKNT}: add table} + +\lrmcomment{This is related to \identr{XKGC}:} + +The semantics takes a semantic transition over the left subexpression before +the right subexpression. + +This is an arbitrary choice as the type-checker must ensure that either order +of evaluation of the operands yields the same result. + +In other words, it it is an error for an expression’s meaning to rely on +evaluation order except that conditional expressions, and uses of the boolean +operators \texttt{\&\&}, \texttt{||}, \texttt{-->}, are guaranteed to evaluate +from left to right. + +\lrmcomment{This is related to \identi{YMRT}:} + +An implementation could enforce this rule by performing a global analysis of +all functions to determine whether a function can throw an exception and the +set of global variables read and written by a function. + +\lrmcomment{This is related to \identi{QJTN}:} + +Notice that when one of the subexpressions terminates exceptionally, +the other expression must be side effect-free and non-throwing. + +In other words, for any function call \texttt{F (e1, ..., em)}, tuple +\texttt{(e1, ..., em)}, or operation \texttt{e1 op e2} (with the exception of +\texttt{\&\&}, \texttt{||} and \texttt{-->}), it is an error if the +subexpressions conflict with each other by: +\begin{itemize} +\item both writing to the same variable. +\item one writing to a variable and the other reading from that same variable +\item one writing to a variable and the other throwing an exception +\item both throwing exceptions +\end{itemize} + +\lrmcomment{This is related to \identi{GFZT}:} +These conditions are sufficient but not necessary to ensure that evaluation +order does not affect the result of an expression, including any side-effects. + +\section{Unary Expressions\label{sec:UnaryExpressions}} +\subsection{Syntax} +\begin{flalign*} +\Nexpr \derives\ & \Nunop \parsesep \Nexpr & +\end{flalign*} + +\subsection{Abstract Syntax} +\begin{flalign*} +\expr \derives\ & \EUnop(\unop, \expr) & +\end{flalign*} + +\subsubsection{ASTRule.Unop} +\begin{mathpar} + \inferrule{}{ + \buildexpr(\overname{\Nexpr(\punnode{\Nunop}, \punnode{\Nexpr})}{\vparsednode}) \astarrow + \overname{\EUnop(\astof{\vunop}, \astof{\vexpr})}{\vastnode} +} +\end{mathpar} + +\subsection{Typing} +\subsubsection{TypingRule.Unop\label{sec:TypingRule.Unop}} +\subsubsection{Prose} +All of the following apply: +\begin{itemize} + \item $\ve$ denotes a unary operation $\op$ over an expression $\vep$, that is $\EUnop(\op, \vep)$; + \item annotating $\vep$ in $\tenv$ yields $(\vtpp, \vepp)$\ProseOrTypeError; + \item checking compatibility of $\op$ with $\vtpp$ as per \secref{TypingRule.CheckUnop} yields $\vt$\ProseOrTypeError; + \item $\newe$ denotes $\op$ over $\vepp$, that is, $\EUnop(\op, \vepp)$. +\end{itemize} +\subsubsection{Formally} +\begin{mathpar} +\inferrule{ + \annotateexpr{\tenv, \vep} \typearrow (\vtpp, \vepp) \OrTypeError\\\\ + \CheckUnop(\tenv, \op, \vtpp) \typearrow \vt \OrTypeError +}{ + \annotateexpr{\tenv, \EUnop(\op, \vep)} \typearrow (\vt, \EUnop(\op, \vepp)) +} +\end{mathpar} +\CodeSubsection{\UnopBegin}{\UnopEnd}{../Typing.ml} + +\subsection{Semantics} +\subsubsection{Example} +In the specification: +\ASLExample{\semanticstests/SemanticsRule.EUnopAssert.asl} +the expression \texttt{NOT '1010'} evaluates to the value \texttt{'0101'}. + +\subsubsection{SemanticsRule.Unop\label{sec:SemanticsRule.Unop}} + +\subsubsection{Prose} +All of the following apply: +\begin{itemize} +\item $\ve$ denotes a unary operator $\op$ over an expression, $\EUnop(\op, \veone)$; +\item the evaluation of the expression $\veone$ in $\env$ yields \\ $\Normal((\vvone, \vg), \newenv)$\ProseOrAbnormal; +\item applying the unary operator $\op$ to $\vvone$ is $\vv$. +\end{itemize} +\subsubsection{Formally} +\begin{mathpar} +\inferrule{ + \evalexpr{ \env, \veone} \evalarrow \Normal((\vvone,\vg), \newenv) \OrAbnormal\\\\ + \unoprel(\op, \vvone) \evalarrow \vv +} +{ + \evalexpr{ \env, \EUnop(\op, \veone) } \evalarrow + \Normal((\vv, \vg), \newenv) +} +\end{mathpar} +\CodeSubsection{\EvalUnopBegin}{\EvalUnopEnd}{../Interpreter.ml} + +\section{Conditional Expressions\label{sec:ConditionalExpressions}} +\subsection{Syntax} +\begin{flalign*} +\Nexpr \derives\ & \Tif \parsesep \Nexpr \parsesep \Tthen \parsesep \Nexpr \parsesep \Neelse &\\ +\Neelse \derives\ & \Telse \parsesep \Nexpr &\\ +|\ & \Telseif \parsesep \Nexpr \parsesep \Tthen \parsesep \Nexpr \parsesep \Neelse & +\end{flalign*} + +\subsection{Abstract Syntax} +\begin{flalign*} +\expr \derives\ & \ECond(\overtext{\expr}{condition}, \overtext{\expr}{then}, \overtext{\expr}{else}) +\end{flalign*} + +\subsubsection{ASTRule.ECond} +\begin{mathpar} + \inferrule{ + \buildexpr(\vcondexpr) \astarrow \astversion{\vcondexpr}\\ + \buildexpr(\vthenexpr) \astarrow \astversion{\vthenexpr} + }{ + { + \begin{array}{r} + \buildexpr\left(\overname{\Nexpr\left( + \begin{array}{l} + \Tif, \namednode{\vcondexpr}{\Nexpr}, \Tthen, \\ + \wrappedline\ \namednode{\vthenexpr}{\Nexpr}, \punnode{\Neelse} + \end{array} + \right)}{\vparsednode}\right) \astarrow\\ + \overname{\ECond(\astversion{\vcondexpr}, \astversion{\vthenexpr}, \astof{\veelse})}{\vastnode} + \end{array} + } +} +\end{mathpar} + +\subsubsection{ASTRule.EElse \label{sec:ASTRule.EElse}} +\hypertarget{build-eelse}{} +The function +\[ + \buildeelse(\overname{\parsenode{\Nfieldassign}}{\vparsednode}) \;\aslto\; \overname{\expr}{\vastnode} +\] +transforms a parse node $\vparsednode$ into an AST node $\vastnode$. + +\begin{mathpar} +\inferrule[else]{}{ + \buildeelse(\Neelse(\Telse, \punnode{\Nexpr})) \astarrow + \overname{\astof{\vexpr}}{\vastnode} +} +\end{mathpar} + +\begin{mathpar} +\inferrule[else\_if]{ + \buildexpr(\vcondexpr) \astarrow \astversion{\vcondexpr}\\ + \buildexpr(\vthenexpr) \astarrow \astversion{\vthenexpr} +}{ + { + \begin{array}{r} + \buildeelse\left(\Neelse\left( + \begin{array}{l} + \Telseif, \namednode{\vcondexpr}{\Nexpr}, \\ + \wrappedline\ \Tthen, \namednode{\vthenexpr}{\Nexpr}, \punnode{\Neelse} + \end{array} + \right)\right) \astarrow\\ + \overname{\ECond(\astversion{\vcondexpr}, \astversion{\vthenexpr}, \astof{\veelse})}{\vastnode} +\end{array} + } +} +\end{mathpar} + +\subsection{Typing} +\subsubsection{TypingRule.ECond \label{sec:TypingRule.ECond}} +\subsubsection{Prose} +All of the following apply: +\begin{itemize} + \item $\ve$ denotes a conditional expression with condition $\econd$ with two options $\etrue$ and $\efalse$; + \item annotating $\econd$ in $\tenv$ results in $(\tcond, \econdp)$\ProseOrTypeError; + \item annotating $\etrue$ in $\tenv$ results in $(\ttrue, \etruep)$\ProseOrTypeError; + \item annotating $\efalse$ in $\tenv$ results in $(\tfalse, \efalsep)$; + \item obtaining the lowest common ancestor of $\ttrue$ and $\tfalse$ results in $\vt$\ProseOrTypeError; + \item $\newe$ is the condition $\econdp$ with two options $\etruep$ and $\efalsep$, that is, $\ECond(\econdp, \etruep, \efalsep)$. +\end{itemize} +\subsubsection{Formally} +\begin{mathpar} +\inferrule{ + \annotateexpr{\tenv, \econd} \typearrow (\tcond, \econd') \OrTypeError\\\\ + \annotateexpr{\tenv, \etrue} \typearrow (\ttrue, \etrue') \OrTypeError\\\\ + \annotateexpr{\tenv, \efalse} \typearrow (\tfalse, \efalse') \OrTypeError\\\\ + \lca(\ttrue, \tfalse) \typearrow \vt \OrTypeError +}{ + { + \begin{array}{r} + \annotateexpr{\ECond(\econd, \etrue, \efalse)} \typearrow \\ + (\vt, \ECond(\econdp, \etruep, \efalsep)) + \end{array} + } +} +\end{mathpar} +\CodeSubsection{\ECondBegin}{\ECondEnd}{../Typing.ml} +\lrmcomment{This is related to \identr{XZVT}.} + +\subsection{Semantics} +\subsubsection{Example} +In the specification: +\ASLExample{\semanticstests/SemanticsRule.ECondFalse.asl} +the expression \texttt{if FALSE then Return42() else 3} evaluates to the value \texttt{3}. + +\subsubsection{Example} +In the specification: +\ASLExample{\semanticstests/SemanticsRule.ECondUNKNOWN3or42.asl} +the expression \texttt{if UNKNOWN: boolean then 3 else Return42()} will +evaluate either \texttt{3} or \texttt{Return42()} depending on how +\texttt{UNKNOWN} is implemented. + +\subsubsection{SemanticsRule.ECond \label{sec:SemanticsRule.ECond}} +\subsubsection{Prose} +All of the following apply: +\begin{itemize} + \item $\ve$ denotes a conditional expression $\econd$ with two options $\veone$ and $\vetwo$, + that is, $\ECond(\econd, \veone, \vetwo)$; + \item the evaluation of the conditional expression $\econd$ in $\env$ yields \\ + $\Normal(\mcond, \envone)$\ProseOrAbnormal; + \item $\mcond$ consists of a native Boolean for $\vb$ and execution graph $\vgone$; + \item $\vep$ is $\veone$ if $\vb$ is $\True$ and $\vetwo$ otherwise; + \item the evaluation of $\vep$ in $\envone$ yields $\Normal((\vvtwo, \vgtwo), \newenv)$\ProseOrAbnormal; + \item $\vg$ is the parallel composition of $\vgone$ and $\vgtwo$. +\end{itemize} +\subsubsection{Formally} +\begin{mathpar} + \inferrule{ + \evalexpr{\env, \econd} \evalarrow \Normal(\mcond, \envone) \OrAbnormal\\\\ + \mcond \eqname (\nvbool(\vb), \vgone)\\ + \vep \eqdef \choice{\vb}{\veone}{\vetwo}\\\\ + \evalexpr{\envone, \vep} \evalarrow \Normal((\vv, \vgtwo), \newenv) \OrAbnormal\\\\ + \vg \eqdef \ordered{\vgone}{\aslctrl}{\vgtwo} + } + { + \evalexpr{\env, \overname{\ECond(\econd, \veone, \vetwo)}{\ve}} \evalarrow + \Normal((\vv, \vg), \newenv) + } +\end{mathpar} +\CodeSubsection{\EvalECondBegin}{\EvalECondEnd}{../Interpreter.ml} + +\subsubsection{Comments} +\lrmcomment{This is related to \identr{YCDB}:} + +A conditional expression evaluates to its \texttt{then} expression if the +condition expression evaluates to $\True$. If the condition expression +evaluates to $\False$ each \texttt{elsif} condition expression is evaluated +sequentially until an \texttt{elsif} condition expression evaluates to $\True$; +the conditional expression evaluates to the corresponding \texttt{elsif} +expression. If no \texttt{elsif} expression evaluates to $\True$ the +conditional expression evaluates to the \texttt{else} expression. + +\section{Call Expressions\label{sec:CallExpressions}} +\subsection{Syntax} +\begin{flalign*} +\Nexpr \derives\ & \Tidentifier \parsesep \Plist{\Nexpr} & +\end{flalign*} + +\subsection{Abstract Syntax} +\begin{flalign*} +\expr \derives\ & \ECall(\overtext{\identifier}{subprogram name}, \overtext{\expr^{*}}{actual arguments}) & +\end{flalign*} + +\subsubsection{ASTRule.ECall} +\begin{mathpar} +\inferrule{ + \buildplist[\buildexpr](\vargs) \astarrow \vexprasts +}{ + \buildexpr(\overname{\Nexpr(\Tidentifier(\id), \namednode{\vargs}{\Plist{\Nexpr}})}{\vparsednode}) \astarrow + \overname{\ECall(\id, \vexprasts)}{\vastnode} +} +\end{mathpar} + +\subsection{Typing} +\subsubsection{TypingRule.ECall\label{sec:TypingRule.ECall}} +\subsubsection{Prose} +All of the following apply: +\begin{itemize} + \item $\ve$ denotes a call to a subprogram named $\name$ with arguments $\vargs$, that is, \\ $\ECall(\name, \vargs)$; + \item applying $\annotatecall$ to $\name$, $\vargs$, and $\STFunction$ in $\tenv$ + annotates the call of that subprogram in $\tenv$ as a function (annotating calls is defined in Chapter~\ref{chap:TypingSubprogramCalls}) + and yields $(\namep, \vargsp, \eqsp, \langle \vt \rangle)$\ProseOrTypeError. + Notice that passing $\STFunction$ to $\annotatecall$ checks that $\name$ is not a procedure and that a value is indeed returned; + \item $\newe$ is the call to the subprogram named $\namep$ with arguments $\vargsp$ + and parameters $\eqsp$, that is, $\ECall(\namep, \vargsp, \eqsp)$. +\end{itemize} +\subsubsection{Formally} +\begin{mathpar} +\inferrule{ + \annotatecall(\tenv, \name, \vargs, \STFunction) \typearrow (\namep, \vargsp, \eqsp, \langle \vt \rangle) \OrTypeError +}{ + \annotateexpr{\tenv, \overname{\ECall(\name, \vargs)}{\ve}} \typearrow (\vt, \overname{\ECall(\namep, \vargsp, \eqsp)}{\newe}) +} +\end{mathpar} +\CodeSubsection{\ECallBegin}{\ECallEnd}{../Typing.ml} +\lrmcomment{This is related to \identd{CFYP}, \identr{BQJG}.} + +\subsection{Semantics} +\subsubsection{Example} +In the specification: +\ASLExample{\semanticstests/SemanticsRule.ECall.asl} +the expression \texttt{Return42()} evaluates to the value \texttt{42} because the +subprogram \texttt{Return42()} is implemented to return the value \texttt{42}. + +\subsubsection{SemanticsRule.ECall \label{sec:SemanticsRule.ECall}} +All of the following apply: +\begin{itemize} + \item $\ve$ denotes a subprogram call, $\ECall(\name, \actualargs, \params)$; + \item the evaluation of that subprogram call in $\env$ is either + $\Normal(\vms, \newenv)$\ProseOrAbnormal; + \item one of the following applies: + \begin{itemize} + \item all of the following apply (\textsc{single\_returned\_value}): + \begin{itemize} + \item $\vms$ consists of a single returned value $(\vv,\vg)$, + which goes into the output configuration $\Normal((\vv, \vg), \newenv)$. + \end{itemize} + + \item all of the following apply (\textsc{multiple\_returned\_values}): + \begin{itemize} + \item $\vms$ consists of a list of returned value $(\vv_i,\vg_i)$, for $i=1..k$; + \item $\vg$ is the parallel composition of $\vg_i$, for $i=1..k$; + \item $\vv$ is the \nativevalue\ vector of values $\vv_i$, for $i=1..k$; + \item the resulting configuration is $\Normal((\vv, \vg), \newenv)$. + \end{itemize} + \end{itemize} +\end{itemize} + +\subsubsection{Formally} +\begin{mathpar} +\inferrule[single\_returned\_value]{ + \evalcall{\env, \name, \actualargs, \params} \evalarrow \Normal(\vms, \newenv) \OrAbnormal\\ + \vms \eqname [(\vv, \vg)] +}{ + \evalexpr{\env, \ECall(\name, \actualargs, \params)} \evalarrow \Normal((\vv, \vg), \newenv) +} +\end{mathpar} + +\begin{mathpar} +\inferrule[multiple\_returned\_values]{ + \evalcall{\env, \name, \actualargs, \params} \evalarrow \Normal(\vms, \newenv) \OrAbnormal\\ + \vms \eqname [i=1..k: (\vv_i, \vg_i)]\\ + \vg \eqdef \vg_1 \parallelcomp \ldots \parallelcomp \vg_k \\ + \vv \eqdef \nvvector{\vv_{1..k}} +}{ + \evalexpr{\env, \ECall(\name, \actualargs, \params)} \evalarrow \Normal((\vv, \vg), \newenv) +} +\end{mathpar} +\CodeSubsection{\EvalECallBegin}{\EvalECallEnd}{../Interpreter.ml} + +\section{Slicing Expressions\label{sec:SlicingExpressions}} +Slicing expressions stand for one of the following: +\begin{itemize} + \item A call to a setter subprogram; + \item A bitvector slice; or + \item A read access to an array index. +\end{itemize} +This section details the high-level form of the syntax and abstract syntax of slicing expressions, +explains how the type system differentiates between the different types of slicing expressions, +and defines the semantics of bitvector slices and array access. +The details of the various types of bitvector slices is deferred to \chapref{BitvectorSlicing}. + +\subsection{Syntax} +\begin{flalign*} +\Nexpr \derives\ & \Nexpr \parsesep \Nslices & +\end{flalign*} + +\subsection{Abstract Syntax} +\begin{flalign*} +\expr \derives\ & \ESlice(\expr, \slice^{*}) & +\end{flalign*} + +\subsubsection{ASTRule.ESlice} +\begin{mathpar} +\inferrule{}{ + \buildexpr(\overname{\Nexpr(\punnode{\Nexpr}, \punnode{\Nslice})}{\vparsednode}) \astarrow + \overname{\ESlice(\astof{\vexpr}, \astof{\vslice})}{\vastnode} +} +\end{mathpar} + +\subsection{Typing} +\subsubsection{TypingRule.ESetter \label{sec:TypingRule.ESetter}} +\subsubsection{Prose} +All of the following apply: +\begin{itemize} + \item $\ve$ denotes the slicing of expression $\vep$ by the slices $\slices$, that is, \\ + $\ESlice(\vep, \slices)$; + \item determining whether $\vep$ together with $\slices$ corresponds to a subprogram call + in $\tenv$ via $\reduceslicestocall$ yields a positive answer --- $\langle (\name, \vargs)\rangle$\ProseOrTypeError; + \item applying $\annotatecall$ to annotate the call with $(\tenv, \name, \vargs, \STSetter)$ + yields $(\nameone, \vargsone, \eqs, \langle\tty\rangle)$\ProseOrTypeError; + \item $\vt$ is $\tty$; + \item $\newe$ is the call expression $\ECall(\nameone, \vargsone, \eqs)$. +\end{itemize} +\subsubsection{Formally} +\begin{mathpar} +\inferrule{ + \reduceslicestocall(\tenv, \vep, \slices) \typearrow \langle(\name, \vargs)\rangle \OrTypeError\\\\ + \annotatecall(\tenv, \name, \vargs, \STSetter) \typearrow (\nameone, \vargsone, \eqs, \langle\tty\rangle) \OrTypeError\\ +}{ + \annotateexpr{\tenv, \overname{\ESlice(\vep, \slices)}{\ve}} \typearrow (\overname{\tty}{\vt}, \overname{\ECall(\nameone, \vargsone, \eqs)}{\newe}) +} +\end{mathpar} +\CodeSubsection{\ReduceSlicesToCallBegin}{\ReduceSlicesToCallEnd}{../Typing.ml} + +\subsubsection{TypingRule.ESlice \label{sec:TypingRule.ESlice}} +\subsubsection{Prose} +All of the following apply: +\begin{itemize} + \item $\ve$ denotes the slicing of expression $\vep$ by the slices $\slices$, that is, \\ + $\ESlice(\vep, \slices)$; + \item determining whether $\vep$ together with $\slices$ corresponds to a subprogram call + in $\tenv$ via $\reduceslicestocall$ yields a negative answer --- $\None$\ProseOrTypeError; + \item annotating the expression $\vep$ in $\tenv$ yields $(\tep,\vepp)$\ProseOrTypeError; + \item obtaining the \structure\ of $\tep$ in $\tenv$ yields $\structtep$\ProseOrTypeError; + \item $\structtep$ is either a bitvector or an integer; + \item obtaining the width of $\slices$ in $\tenv$ via $\sliceswidth$ yields $\vw$\ProseOrTypeError; + \item $\slicesp$ is the result of annotating $\slices$ in $\tenv$; + \item $\vt$ is the bitvector type of width $\vw$, that is, $\TBits(\vw, \emptylist)$; + \item $\newe$ is the slicing of expression $\vepp$ by the slices $\slicesp$, that is, \\ + $\ESlice(\vepp, \slicesp)$. +\end{itemize} +\subsubsection{Formally} +\begin{mathpar} +\inferrule{ + \reduceslicestocall(\tenv, \vep, \slices) \typearrow \None \OrTypeError\\\\ + \annotateexpr{\tenv, \vep} \typearrow (\tep, \vepp) \OrTypeError\\\\ + \tstruct(\tenv, \tep) \typearrow \structtep \OrTypeError\\\\ + \astlabel(\structtep) \in \{\TInt, \TBits\}\\ + \sliceswidth(\tenv, \slices) \typearrow \vw \OrTypeError\\\\ + \annotateslices(\tenv, \slices) \typearrow \slicesp \OrTypeError +}{ + \annotateexpr{\tenv, \overname{\ESlice(\vep, \slices)}{\ve}} \typearrow (\overname{\TBits(\vw, \emptylist)}{\vt}, \overname{\ESlice(\vepp, \slicesp)}{\newe}) +} +\end{mathpar} +\CodeSubsection{\ESliceBegin}{\ESliceEnd}{../Typing.ml} +\subsubsection{Comments} +The width of \slices\ might be a symbolic expression if one of the +widths references a \texttt{let} identifier with a non-compile-time-constant +initializer expression. +\lrmcomment{This is related to \identi{MJWM}.} + +\subsubsection{TypingRule.ESliceOrEGetArrayError\label{sec:TypingRule.ESliceOrEGetArrayError}} +\subsubsection{Prose} +All of the following apply: +\begin{itemize} + \item $\ve$ denotes the slicing of expression $\vep$ by the slices $\slices$; + \item determining whether $\vep$ together with $\slices$ corresponds to a subprogram call + in $\tenv$ via $\reduceslicestocall$ yields a negative answer --- $\None$\ProseOrTypeError; + \item $(\tep,\vepp)$ is the result of annotating the expression $\vep$ in $\tenv$; + \item $\tep$ has the structure $\vtp$; + \item $\vtp$ is neither an integer type, a bitvector type, or an array type; + \item the result is an error indicating that the type of $\vep$ is inappropriate for slicing. +\end{itemize} +\subsubsection{Formally} +\begin{mathpar} +\inferrule{ + \reduceslicestocall(\tenv, \vep, \slices) \typearrow \None \OrTypeError\\\\ + \annotateexpr{\tenv, \vep} \typearrow (\tep, \vepp) \OrTypeError\\\\ + \tstruct(\tenv, \tep) \typearrow \vtp\\ + \astlabel(\vtp) \not\in \{\TInt, \TBits, \TArray\} +}{ + \annotateexpr{\tenv, \overname{\ESlice(\vep, \slices)}{\ve}} \typearrow \TypeErrorVal{IllegalSliceType} +} +\end{mathpar} +\CodeSubsection{\ESliceOrEGetArrayErrorBegin}{\ESliceOrEGetArrayErrorEnd}{../Typing.ml} + +\subsubsection{TypingRule.EGetArray \label{sec:TypingRule.EGetArray}} +\hypertarget{def-arrayaccess}{} +\begin{definition}[Array Access] +We refer to a right-hand-side expression of the form $b[i]$, +where $b, i$ are subexpressions, as an \arrayaccess\ expression. +We refer to $b$ and $i$ as the \emph{base} +and the $\emph{index}$ subexpressions, respectively. + +In the untyped AST, an \arrayaccess\ expression is represented by \\ +$\ESlice(\vbase, [\vindex])$, whereas in the typed AST, +it is represented by \\ +$\EGetArray(\vbase, \vindex)$ +\end{definition} + +\subsubsection{Prose} +All of the following apply: +\begin{itemize} + \item $\ve$ denotes the slicing of expression $\vep$ by the slices $\slices$; + \item determining whether $\vep$ together with $\slices$ corresponds to a subprogram call + in $\tenv$ via $\reduceslicestocall$ yields a negative answer --- $\None$\ProseOrTypeError; + \item $(\tep,\vepp)$ is the result of annotating the expression $\vep$ in $\tenv$; + \item $\tep$ has the structure of an array with index $\size$ and element type $\tty$'; + \item One of the following applies: + \begin{itemize} + \item All of the following apply (\textsc{okay}): + \begin{itemize} + \item $\slices$ is a list containing a single slice for an expression $\eindex$, that is, $[\SliceSingle(\eindex)]$; + \item annotating the expression $\eindex$ in $\tenv$ yields $(\tindexp, \eindexp)$\ProseOrTypeError; + \item determining the type of the array index for $\size$ in $\tenv$ via \\ $\typeofarraylength$ + yields $\wantedtindex$; + \item determining whether $\tindexp$ \typesatisfies\ $\wantedtindex$ yields \\ + $\True$\ProseOrTypeError; + \item $\vt$ is $\ttyp$; + \item $\newe$ is the \arrayaccess\ expression for $\vepp$ and index $\eindexp$, that is, $\EGetArray(\vepp, \eindexp)$. + \end{itemize} + + \item All of the following apply (\textsc{error}): + \begin{itemize} + \item $\slices$ is not a list containing a single slice for an expression $\eindex$; + \item the result is a type error indicating that an array must be accessed with a slice corresponding + to a single index expression. + \end{itemize} + \end{itemize} +\end{itemize} +\subsubsection{Formally} +\begin{mathpar} +\inferrule[okay]{ + \reduceslicestocall(\tenv, \vep, \slices) \typearrow \None \OrTypeError\\\\ + \annotateexpr{\tenv, \ve} \typearrow (\tep, \vepp) \OrTypeError\\\\ + \tstruct(\tenv, \tep) \typearrow \TArray(\size, \ttyp) \OrTypeError\\\\ + \commonprefixline\\\\ + \slices = [ \SliceSingle(\eindex) ]\\ + \annotateexpr{\tenv, \eindex} \typearrow (\tindexp, \eindexp) \OrTypeError\\\\ + \typeofarraylength(\tenv, \size) \typearrow \wantedtindex\\ + \checktypesat(\tenv, \tindexp, \wantedtindex) \typearrow \True \OrTypeError\\ +}{ + \annotateexpr{\tenv, \overname{\ESlice(\vep, \slices)}{\ve}} \typearrow (\overname{\ttyp}{\vt}, \overname{\EGetArray(\vepp, \eindexp)}{\newe}) +} +\and +\inferrule[error]{ + \reduceslicestocall(\tenv, \vep, \slices) \typearrow \None \OrTypeError\\\\ + \annotateexpr{\tenv, \ve} \typearrow (\tep, \vepp) \OrTypeError\\\\ + \tstruct(\tenv, \tep) \typearrow \TArray(\size, \ttyp) \OrTypeError\\\\ + \commonprefixline\\\\ + \slices \neq [ \SliceSingle(\Ignore) ]\\ +}{ + \annotateexpr{\tenv, \overname{\ESlice(\vep, \slices)}{\ve}} \typearrow \TypeErrorVal{IllegalArraySlice} +} +\end{mathpar} +\CodeSubsection{\EGetArrayBegin}{\EGetArrayEnd}{../Typing.ml} + +\subsubsection{TypingRule.ReduceSlicesToCall \label{sec:TypingRule.ReduceSlicesToCall}} +\hypertarget{def-reduceslicestocall}{} +The helper function +\[ + \reduceslicestocall(\overname{\staticenvs}{\tenv} \aslsep \overname{\expr}{\ve} \aslsep \overname{\slice^*}{\slices}) + \aslto + \langle (\overname{\identifier}{\name} \times \overname{\expr^*}{\vargs})\rangle + \cup \overname{\TTypeError}{\TypeErrorConfig} +\] +checks whether the expression $\ve$ together with the list of slices $\slices$ constitute +a call to a subprogram in $\tenv$. +If so, it returns a pair consisting of the name of the called subprogram --- $\name$ --- +and the list of actual arguments --- $\vargs$. Otherwise, it returns $\None$. +\ProseOtherwiseTypeError + +\subsubsection{Prose} +One of the following applies: +\begin{itemize} + \item All of the following apply (\textsc{yes}): + \begin{itemize} + \item $\ve$ is a variable expression for $\vx$, that is, $\EVar(\vx)$; + \item determining whether $\vx$ is a subprogram name with $\slices$ as its actual arguments + via $\shouldslicesreducetocall$ + yields a list of actual argument expressions $\vargs$\ProseOrTypeError; + \item the result is $\langle (\vx, \vargs)\rangle$. + \end{itemize} + + \item All of the following apply (\textsc{no}): + \begin{itemize} + \item $\ve$ is a variable expression for $\vx$, that is, $\EVar(\vx)$; + \item determining whether $\vx$ is a subprogram name with $\slices$ as its actual arguments + via $\shouldslicesreducetocall$ + yields $\None$; + \item the result is $\None$. + \end{itemize} + + \item All of the following apply (\textsc{non\_var}): + \begin{itemize} + \item $\ve$ is not a variable expression; + \item the result is $\None$. + \end{itemize} +\end{itemize} +\subsubsection{Formally} +\begin{mathpar} +\inferrule[yes]{ + \shouldslicesreducetocall(\tenv, \vx, \slices) \typearrow \langle \vargs \rangle\\ +}{ + \reduceslicestocall(\tenv, \EVar(\vx), \slices) \typearrow \langle (\vx, \vargs)\rangle +} +\end{mathpar} + +\begin{mathpar} +\inferrule[no]{ + \shouldslicesreducetocall(\tenv, \vx, \slices) \typearrow \None +}{ + \reduceslicestocall(\tenv, \EVar(\vx), \slices) \typearrow \None +} +\end{mathpar} + +\begin{mathpar} +\inferrule[non\_var]{ + \astlabel(\ve) \neq \EVar +}{ + \reduceslicestocall(\tenv, \ve, \slices) \typearrow \None +} +\end{mathpar} +\CodeSubsection{\ReduceSlicesToCallBegin}{\ReduceSlicesToCallEnd}{../Typing.ml} + +\subsection{Semantics} +\subsubsection{SemanticsRule.ESlice \label{sec:SemanticsRule.ESlice}} +\subsubsection{Example} +In the specification: +\ASLExample{\semanticstests/SemanticsRule.ESlice.asl} +the expression \texttt{'11110000'[6:3]} evaluates to the value \texttt{'1110'}. + +\subsubsection{Prose} +All of the following apply: +\begin{itemize} +\item $\ve$ denotes a slicing expression, $\ESlice(\ebv, \slices)$; +\item the evaluation of $\ebv$ in $\env$ yields $\Normal(\mbv, \envone)$\ProseOrAbnormal; +\item the evaluation of $\slices$ in $\env$ yields $\Normal(\mpositions, \newenv)$\ProseOrAbnormal; +\item $\mpositions$ consists of $\positions$ --- all the indices that need to be added to the +resulting bitvector --- and the execution graph $\vgone$; +\item reading from $\vbv$ as a bitvector at the indices indicated by $\positions$ + (see \secref{SemanticsRule.ReadFromBitvector}) results in the bitvector $\vv$, + which concatenates all of the values from the indicates indices\ProseOrError; +\item $\vg$ is the parallel composition of $\vgone$ and $\vgtwo$. +\end{itemize} +\subsubsection{Formally} +\begin{mathpar} +\inferrule{ + \evalexpr{\env, \ebv} \evalarrow \Normal(\mbv, \envone) \OrAbnormal\\\\ + \mbv \eqname (\vbv,\vgone) \\ + \evalslices{\envone, \slices} \evalarrow \Normal(\mpositions, \newenv) \OrAbnormal \\ + \mpositions \eqname (\positions, \vgtwo) \\ + \readfrombitvector(\vbv, \positions) \evalarrow \vv \OrDynError\\\\ + \vg \eqdef \vgone \parallelcomp \vgtwo +}{ + \evalexpr{\env, \ESlice(\ebv, \slices)} \evalarrow \Normal((\vv, \vg), \newenv) +} +\end{mathpar} +\CodeSubsection{\EvalESliceBegin}{\EvalESliceEnd}{../Interpreter.ml} + +\subsubsection{SemanticsRule.EGetArray \label{sec:SemanticsRule.EGetArray}} +\subsubsection{Example} +In the specification: +\ASLExample{\semanticstests/SemanticsRule.EGetArray.asl} +the expression \texttt{my\_array[2]} appearing in the assertion evaluates to the value \texttt{42} since the element +indexed by \texttt{2} in \texttt{my\_array} is \texttt{42}. + +\subsubsection{Example} +The specification: +\ASLExample{\semanticstests/SemanticsRule.EGetArrayTooSmall.asl} +results in a typing error since we are trying to access index \texttt{3} of an array +which has indexes \texttt{0}, \texttt{1} and \texttt{2} only. + +\subsubsection{Prose} +All of the following apply: +\begin{itemize} + \item $\ve$ denotes an array access expression, $\EGetArray(\earray, \eindex)$; + \item the evaluation of $\earray$ in $\env$ is $\Normal(\marray, \envone)$\ProseOrAbnormal; + \item the evaluation of $\eindex$ in $\env$ is $\Normal(\mindex, \newenv)$\ProseOrAbnormal + \item $\marray$ consists of the native vector $\varray$ and execution graph $\vgone$; + \item $\mindex$ consists of the native integer $\vindex$ and execution graph $\vgtwo$; + \item $\vindex$ is the native integer for $\vi$; + \item evaluating the value at index $\vi$ of $\varray$ is $\vv$; + \item $\vg$ is the parallel composition of $\vgone$ and $\vgtwo$. +\end{itemize} +\subsubsection{Formally} +\begin{mathpar} +\inferrule{ + \evalexpr{\env, \earray} \evalarrow \Normal(\marray, \envone) \OrAbnormal\\ + \evalexpr{\envone, \eindex} \evalarrow \Normal(\mindex, \newenv) \OrAbnormal\\ + \marray \eqname (\varray, \vgone)\\ + \mindex \eqname (\vindex, \vgtwo)\\ + \vindex \eqname \nvint(\vi)\\ + \getindex(\vi, \varray) \evalarrow \vv\\ + \vg \eqdef \vgone \parallelcomp \vgtwo\\ +}{ + \evalexpr{\env, \EGetArray(\earray, \eindex)} \evalarrow \Normal((\vv, \vg), \newenv) +} +\end{mathpar} +\CodeSubsection{\EvalEGetArrayBegin}{\EvalEGetArrayEnd}{../Interpreter.ml} + +\section{Field Reading Expressions\label{sec:FieldReadingExpressions}} +\subsection{Syntax} +\begin{flalign*} +\Nexpr \derives\ & \Nexpr \parsesep \Tdot \parsesep \Tidentifier&\\ + |\ & \Nexpr \parsesep \Tdot \parsesep \Tlbracket \parsesep \NClist{\Tidentifier} \parsesep \Trbracket & +\end{flalign*} + +\subsection{Abstract Syntax} +\begin{flalign*} +\expr \derives\ & \EGetField(\overtext{\expr}{record}, \overtext{\identifier}{field name}) + |\ & \EGetFields(\overtext{\expr}{record}, \overtext{\identifier^{*}}{field names}) & +\end{flalign*} + +\subsubsection{ASTRule.EGetField} +\begin{mathpar} + \inferrule{}{ + \buildexpr(\overname{\Nexpr(\Nexpr, \Tdot, \Tidentifier(\id))}{\vparsednode}) \astarrow + \overname{\EGetField(\astof{\vexpr}, \id)}{\vastnode} +} +\end{mathpar} + +\subsubsection{ASTRule.EGetFields} +\begin{mathpar} + \inferrule{ + \buildclist[\buildidentity](\vids) \astarrow \vidasts + }{ + { + \begin{array}{r} + \buildexpr(\overname{\Nexpr(\punnode{\Nexpr}, \Tdot, \Tlbracket, \namednode{\vids}{\NClist{\Tidentifier}}, \Trbracket)}{\vparsednode}) \astarrow\\ + \overname{\EGetFields(\astof{\vexpr}, \vidasts)}{\vastnode} + \end{array} + } +} +\end{mathpar} + +\subsection{Typing} +\subsubsection{TypingRule.EGetRecordField \label{sec:TypingRule.EGetRecordField}} +\subsubsection{Prose} +All of the following apply: +\begin{itemize} + \item $\ve$ denotes the access of field $\fieldname$ in the value represented by the expression $\veone$, that is, $\EGetField(\veone, \fieldname)$; + \item annotating the expression $\veone$ in $\tenv$ yields $(\vteone, \vetwo)$\ProseOrTypeError; + \item obtaining the \underlyingtype\ of $\vteone$ yields $\vtetwo$\ProseOrTypeError; + % \item checking whether the field access with expression $\vtetwo$ and $\fieldname$ represents a call yields $\None$\ProseOrTypeError; + \item $\vtetwo$ is a \structuredtype\ with fields $\fields$; + \item the field $\fieldname$ is associated with the type $\vt$ in $\fields$ + \item $\newe$ is the access of field $\fieldname$ on the record or exception object $\vetwo$, that is, $\EGetField(\vetwo, \fieldname)$. +\end{itemize} +\subsubsection{Formally} +\begin{mathpar} +\inferrule{ + \annotateexpr{\tenv, \veone} \typearrow (\vteone, \vetwo) \OrTypeError\\\\ + \makeanonymous(\tenv, \vteone) \typearrow \vtetwo \OrTypeError\\\\ + % \tododefine{reduce\_field\_to\_call}(\tenv, \vtetwo, \fieldname) \typearrow \None \OrTypeError\\\\ + \vtetwo \eqname L(\fields)\\ + L \in \{\TRecord, \TException\}\\ + \assocopt(\fields, \fieldname) \typearrow \langle \vt\rangle +}{ + \annotateexpr{\tenv, \EGetField(\veone, \fieldname)} \typearrow (\vt, \EGetField(\vetwo, \fieldname)) +} +\end{mathpar} +\CodeSubsection{\EGetRecordFieldBegin}{\EGetRecordFieldEnd}{../Typing.ml} + +\subsubsection{TypingRule.EGetBadRecordField \label{sec:TypingRule.EGetBadRecordField}} +\subsubsection{Prose} +All of the following apply: +\begin{itemize} + \item $\ve$ denotes the access of field $\fieldname$ in the value represented by the expression $\veone$, that is, $\EGetField(\veone, \fieldname)$; + \item annotating the expression $\veone$ in $\tenv$ yields $(\vteone, \vetwo)$\ProseOrTypeError; + \item obtaining the \underlyingtype\ of $\vteone$ yields $\vtetwo$\ProseOrTypeError; + % \item checking whether the field access with expression $\vtetwo$ and $\fieldname$ represents a call yields $\None$\ProseOrTypeError; + \item $\vtetwo$ is a \structuredtype\ with fields $\fields$; + \item the field $\fieldname$ is not associated with any type in $\fields$ + \item the result is a type error indicating the missing field. +\end{itemize} +\subsubsection{Formally} +\begin{mathpar} +\inferrule{ + \annotateexpr{\tenv, \veone} \typearrow (\vteone, \vetwo) \OrTypeError\\\\ + \makeanonymous(\tenv, \vteone) \typearrow \vtetwo \OrTypeError\\\\ + % \tododefine{reduce\_field\_to\_call}(\tenv, \vtetwo, \fieldname) \typearrow \None \OrTypeError\\\\ + \vtetwo \eqname L(\fields)\\ + L \in \{\TRecord, \TException\}\\ + \assocopt(\fields, \fieldname) \typearrow \None +}{ + \annotateexpr{\tenv, \EGetField(\veone, \fieldname)} \typearrow \TypeErrorVal{FieldDoesNotExist} +} +\end{mathpar} +\CodeSubsection{\EGetBadRecordFieldBegin}{\EGetBadRecordFieldEnd}{../Typing.ml} + +\subsubsection{TypingRule.EGetBadBitField \label{sec:TypingRule.EGetBadBitField}} +\subsubsection{Prose} +All of the following apply: +\begin{itemize} + \item $\ve$ denotes the access of field $\fieldname$ in the value represented by the expression $\veone$, that is, $\EGetField(\veone, \fieldname)$; + \item annotating the expression $\veone$ in $\tenv$ yields $(\vteone, \vetwo)$\ProseOrTypeError; + \item obtaining the \underlyingtype\ of $\vteone$ yields $\vtetwo$\ProseOrTypeError; + % \item checking whether the field access with expression $\vtetwo$ and $\fieldname$ represents a call yields $\None$\ProseOrTypeError; + \item $\vtetwo$ is a bitvector type with bit fields $\bitfields$; + \item the field $\fieldname$ is not found in $\bitfields$ + \item the result is a type error indicating the missing field. +\end{itemize} +\begin{mathpar} +\inferrule{ + \annotateexpr{\tenv, \veone} \typearrow (\vteone, \vetwo) \OrTypeError\\\\ + \makeanonymous(\tenv, \vteone) \typearrow \vtetwo \OrTypeError\\\\ + % \tododefine{reduce\_field\_to\_call}(\tenv, \vtetwo, \fieldname) \typearrow \None \OrTypeError\\\\ + \vtetwo \eqname \TBits(\Ignore, \bitfields)\\ + \findbitfieldopt(\bitfields, \fieldname) \typearrow \None +}{ + \annotateexpr{\tenv, \overname{\EGetField(\veone, \fieldname)}{\ve}} \typearrow \TypeErrorVal{FieldDoesNotExist} +} +\end{mathpar} +\CodeSubsection{\EGetBadBitFieldBegin}{\EGetBadBitFieldEnd}{../Typing.ml} + +\subsubsection{TypingRule.EGetBitField \label{sec:TypingRule.EGetBitField}} +\subsubsection{Prose} +All of the following apply: +\begin{itemize} + \item $\ve$ denotes the access of field $\fieldname$ in the value represented by the expression $\veone$, that is, $\EGetField(\veone, \fieldname)$; + \item annotating the expression $\veone$ in $\tenv$ yields $(\vteone, \vetwo)$\ProseOrTypeError; + \item obtaining the \underlyingtype\ of $\vteone$ yields $\vtetwo$\ProseOrTypeError; + % \item checking whether the field access with expression $\vtetwo$ and $\fieldname$ represents a call yields $\None$\ProseOrTypeError; + \item $\vtetwo$ is a bitvector type with bit fields $\bitfields$; + \item $\fieldname$ is declared in $\bitfields$ with a slice list $\slices$, that is, \\ $\BitFieldSimple(\Ignore, \slices)$; + \item $\vethree$ denotes the slicing of the expression \vetwo\ by the slices $\slices$, that is, \\ $\ESlice(\vetwo, \slices)$; + \item annotating $\vethree$ in $\tenv$ yields $(\vt, \newe)$\ProseOrTypeError. +\end{itemize} +\subsubsection{Formally} +\begin{mathpar} +\inferrule{ + \annotateexpr{\tenv, \veone} \typearrow (\vteone, \vetwo) \OrTypeError\\\\ + \makeanonymous(\tenv, \vteone) \typearrow \vtetwo \OrTypeError\\\\ + % \tododefine{reduce\_field\_to\_call}(\tenv, \vtetwo, \fieldname) \typearrow \None \OrTypeError\\\\ + \vtetwo \eqname \TBits(\Ignore, \bitfields)\\ + \findbitfieldopt(\bitfields, \fieldname) \typearrow \langle \BitFieldSimple(\Ignore, \slices)\rangle\\ + \vethree \eqdef \ESlice(\vetwo, \slices)\\ + \annotateexpr{\tenv, \vethree} \typearrow (\vt, \newe) \OrTypeError +}{ + \annotateexpr{\tenv, \overname{\EGetField(\veone, \fieldname)}{\ve}} \typearrow (\vt, \newe) +} +\end{mathpar} +\CodeSubsection{\EGetBitFieldBegin}{\EGetBitFieldEnd}{../Typing.ml} + +\subsubsection{TypingRule.EGetBitFieldNested \label{sec:TypingRule.EGetBitFieldNested}} +\subsubsection{Prose} +All of the following apply: +\begin{itemize} + \item $\ve$ denotes the access of field $\fieldname$ in the value represented by the expression $\veone$, that is, $\EGetField(\veone, \fieldname)$; + \item annotating the expression $\veone$ in $\tenv$ yields $(\vteone, \vetwo)$\ProseOrTypeError; + \item obtaining the \underlyingtype\ of $\vteone$ yields $\vtetwo$\ProseOrTypeError; + % \item checking whether the field access with expression $\vtetwo$ and $\fieldname$ represents a call yields $\None$\ProseOrTypeError; + \item $\vtetwo$ is a bitvector type with bit fields $\bitfields$; + \item $\fieldname$ is declared in $\bitfields$ with a slice list $\slices$ and nested bitfields $\bitfieldsp$, that is, + $\BitFieldNested(\Ignore, \slices, \bitfieldsp)$; + \item $\vethree$ denotes the slicing of the expression \vetwo\ by the slices $\slices$, that is, \\ $\ESlice(\vetwo, \slices)$; + \item annotating $\vethree$ in $\tenv$ yields $(\vtefour, \newe)$\ProseOrTypeError; + \item $\vtefour$ is a bitvector type with length expression $\width$, that is, $\TBits(\width, \Ignore)$; + \item $\vt$ is a bitvector type with length expression $\width$ and bitfields $\bitfieldsp$. +\end{itemize} +\subsubsection{Formally} +\begin{mathpar} +\inferrule{ + \annotateexpr{\tenv, \veone} \typearrow (\vteone, \vetwo) \OrTypeError\\\\ + \makeanonymous(\tenv, \vteone) \typearrow \vtetwo \OrTypeError\\\\ + % \tododefine{reduce\_field\_to\_call}(\tenv, \vtetwo, \fieldname) \typearrow \None \OrTypeError\\\\ + \vtetwo \eqname \TBits(\Ignore, \bitfields)\\ + { + \begin{array}{r} + \findbitfieldopt(\bitfields, \fieldname) \typearrow \\ \langle \BitFieldNested(\Ignore, \slices, \bitfieldsp)\rangle + \end{array} + }\\ + \vethree \eqdef \ESlice(\vetwo, \slices)\\ + \annotateexpr{\tenv, \vethree} \typearrow (\vtefour, \newe) \OrTypeError\\\\ + \vtefour \eqname \TBits(\width, \Ignore)\\ + \vt \eqdef \TBits(\width, \bitfieldsp) +}{ + \annotateexpr{\tenv, \overname{\EGetField(\veone, \fieldname)}{\ve}} \typearrow (\vt, \newe) +} +\end{mathpar} +\CodeSubsection{\EGetBitFieldNestedBegin}{\EGetBitFieldNestedEnd}{../Typing.ml} + +\subsubsection{TypingRule.EGetBitFieldTyped \label{sec:TypingRule.EGetBitFieldTyped}} +\subsubsection{Prose} +All of the following apply: +\begin{itemize} + \item $\ve$ denotes the access of field $\fieldname$ in the value represented by the expression $\veone$, that is, $\EGetField(\veone, \fieldname)$; + \item annotating the expression $\veone$ in $\tenv$ yields $(\vteone, \vetwo)$\ProseOrTypeError; + \item obtaining the \underlyingtype\ of $\vteone$ yields $\vtetwo$\ProseOrTypeError; + % \item checking whether the field access with expression $\vtetwo$ and $\fieldname$ represents a call yields $\None$\ProseOrTypeError; + \item $\vtetwo$ is a bitvector type with bit fields $\bitfields$; + \item $\fieldname$ is declared in $\bitfields$ with a slice list $\slices$ and typed-bitfield with type $\vt$ that is, + $\BitFieldType(\Ignore, \slices, \vt)$; + \item $\vethree$ denotes the slicing of the expression \vetwo\ by the slices $\slices$, that is, \\ $\ESlice(\vetwo, \slices)$; + \item annotating $\vethree$ in $\tenv$ yields $(\vtefour, \newe)$\ProseOrTypeError; + \item determining whether $\vtefour$ \typesatisfies\ $\vt$ yields $\True$\ProseOrTypeError. +\end{itemize} +\subsubsection{Formally} +\begin{mathpar} +\inferrule{ + \annotateexpr{\tenv, \veone} \typearrow (\vteone, \vetwo) \OrTypeError\\\\ + \makeanonymous(\tenv, \vteone) \typearrow \vtetwo \OrTypeError\\\\ + % \tododefine{reduce\_field\_to\_call}(\tenv, \vtetwo, \fieldname) \typearrow \None \OrTypeError\\\\ + \vtetwo \eqname \TBits(\Ignore, \bitfields)\\ + \findbitfieldopt(\bitfields, \fieldname) \typearrow \langle \BitFieldType(\Ignore, \slices, \vt)\rangle\\ + \vethree \eqdef \ESlice(\vetwo, \slices)\\ + \annotateexpr{\tenv, \vethree} \typearrow (\vtefour, \newe) \OrTypeError\\\\ + \checktypesat(\tenv, \vtefour, \vt) \typearrow \True \OrTypeError +}{ + \annotateexpr{\tenv, \overname{\EGetField(\veone, \fieldname)}{\ve}} \typearrow (\vt, \newe) +} +\end{mathpar} +\CodeSubsection{\EGetBitFieldTypedBegin}{\EGetBitFieldTypedEnd}{../Typing.ml} + +\subsubsection{TypingRule.EGetTupleItem \label{sec:TypingRule.EGetTupleItem}} +\subsubsection{Prose} +All of the following apply: +\begin{itemize} + \item $\ve$ denotes the access of field $\fieldname$ in the value represented by the expression $\veone$, that is, $\EGetField(\veone, \fieldname)$; + \item annotating the expression $\veone$ in $\tenv$ yields $(\vteone, \vetwo)$\ProseOrTypeError; + \item obtaining the \underlyingtype\ of $\vteone$ yields $\vtetwo$\ProseOrTypeError; + % \item checking whether the field access with expression $\vtetwo$ and $\fieldname$ represents a call yields $\None$\ProseOrTypeError; + \item $\vtetwo$ is tuple type with list of types $\tys$, that is, $\TTuple(\tys)$; + \item $\fieldname$ is an identifier with the prefix \texttt{item} and the constant $\vindex$; + \item determining whether $\vindex$ is between $0$ and the number of types in $\tys$, inclusive, yields $\True$\ProseOrTypeError; + \item $\vt$ is the type at position $\vindex$ of $\tys$; + \item $\newe$ is the expression for obtaining the item at index $\vindex$ from the expression $\vetwo$, that is, $\EGetItem(\vetwo, \vindex)$. +\end{itemize} +\subsubsection{Formally} +\begin{mathpar} +\inferrule{ + \annotateexpr{\tenv, \veone} \typearrow (\vteone, \vetwo) \OrTypeError\\\\ + \makeanonymous(\tenv, \vteone) \typearrow \vtetwo \OrTypeError\\\\ + % \tododefine{reduce\_field\_to\_call}(\tenv, \vtetwo, \fieldname) \typearrow \None \OrTypeError\\\\ + \vtetwo \eqname \TTuple(\tys)\\ + \fieldname \eqname \texttt{"item"}\\ + \checktrans{0 \leq \vindex \leq \listlen{\tys}}{IndexOutOfRange} \checktransarrow \True \OrTypeError\\\\ + \vt \eqdef \tys[\vindex]\\ + \newe \eqdef \EGetItem(\vetwo, \vindex) +}{ + \annotateexpr{\tenv, \overname{\EGetField(\veone, \fieldname)}{\ve}} \typearrow (\vt, \newe) +} +\end{mathpar} +\CodeSubsection{\EGetTupleItemBegin}{\EGetTupleItemEnd}{../Typing.ml} + +\subsubsection{TypingRule.EGetBadField \label{sec:TypingRule.EGetBadField}} +\subsubsection{Prose} +All of the following apply: +\begin{itemize} + \item $\ve$ denotes the access of field $\fieldname$ in the value represented by the expression $\veone$, that is, $\EGetField(\veone, \fieldname)$; + \item annotating the expression $\veone$ in $\tenv$ yields $(\vteone, \vetwo)$\ProseOrTypeError; + \item obtaining the \underlyingtype\ of $\vteone$ yields $\vtetwo$\ProseOrTypeError; + % \item checking whether the field access with expression $\vtetwo$ and $\fieldname$ represents a call yields $\None$\ProseOrTypeError; + \item $\vtetwo$ is neither one of the following types: record, exception, bitvector, or tuple; + \item the result is an error indicating that the type of $\veone$ is inappropriate for accessing the field $\fieldname$. +\end{itemize} +\subsubsection{Formally} +\begin{mathpar} +\inferrule{ + \annotateexpr{\tenv, \veone} \typearrow (\vteone, \vetwo) \OrTypeError\\\\ + \makeanonymous(\tenv, \vteone) \typearrow \vtetwo \OrTypeError\\\\ + % \tododefine{reduce\_field\_to\_call}(\tenv, \vtetwo, \fieldname) \typearrow \None \OrTypeError\\\\ + \astlabel(\vtetwo) \not\in \{\TRecord, \TException, \TBits, \TTuple\} +}{ + \annotateexpr{\tenv, \overname{\EGetField(\veone, \fieldname)}{\ve}} \typearrow \TypeErrorVal{ConflictingTypes} +} +\end{mathpar} +\CodeSubsection{\EGetBadFieldBegin}{\EGetBadFieldEnd}{../Typing.ml} + +\subsection{Semantics} +\subsubsection{SemanticsRule.EGetField \label{sec:SemanticsRule.EGetField}} +\subsubsection{Example} +In the specification: +\ASLExample{\semanticstests/SemanticsRule.ERecord.asl} +the expression \texttt{my\_record.a} evaluates to the value \texttt{3}. + +\subsubsection{Prose} +All of the following apply: +\begin{itemize} +\item $\ve$ denotes a field access expression, $\EGetField(\erecord, \fieldname)$; +\item the evaluation of $\erecord$ in $\env$ is $\Normal((\vrecord, \vg), \newenv)$\ProseOrAbnormal; +\item $\vv$ is the value mapped by $\fieldname$ in the native record $\vrecord$. +\end{itemize} +\subsubsection{Formally} +\begin{mathpar} +\inferrule{ + \evalexpr{\env, \erecord} \evalarrow \Normal((\vrecord, \vg), \newenv) \OrAbnormal\\ + \getfield(\fieldname, \vrecord) \evalarrow \vv +}{ + \evalexpr{\env, \EGetField(\erecord, \fieldname)} \evalarrow \Normal((\vv, \vg), \newenv) +} +\end{mathpar} +\CodeSubsection{\EvalEGetFieldBegin}{\EvalEGetFieldEnd}{../Interpreter.ml} + +\section{Bitvector Concatenation Expressions\label{sec:BitvectorConcatenationExpressions}} +\subsection{Syntax} +Concatenation of multiple bitvectors is done using a comma separated list +surrounded with square brackets. + +\begin{flalign*} +\Nexpr \derives\ & \Tlbracket \parsesep \NClist{\Nexpr} \parsesep \Trbracket & +\end{flalign*} + +\subsection{Abstract Syntax} +\begin{flalign*} +\expr \derives\ & \EConcat(\expr^{+}) & +\end{flalign*} + +\subsubsection{ASTRule.EConcat} +\begin{mathpar} + \inferrule{ + \buildclist[\buildexpr](\vexprs) \astarrow \vexprasts + }{ + \buildexpr(\overname{\Nexpr(\Tlbracket, \namednode{\vexprs}{\NClist{\Nexpr}}, \Trbracket)}{\vparsednode}) \astarrow + \overname{\EConcat(\vexprasts)}{\vastnode} +} +\end{mathpar} + +\subsection{Typing} +\subsubsection{TypingRule.EConcat \label{sec:TypingRule.EConcat}} +\subsubsection{Prose} +All of the following apply: +\begin{itemize} + \item $\ve$ denotes the concatenation of a non-empty list of expressions $\vli$, that is, \\ $\EConcat(\vli)$; + \item annotating each expression $\vle[i]$ in $\tenv$, for $i=1..k$, yields $(\vt_i, \ve_i$)\ProseOrTypeError; + \item $\ves$ is the list of expressions $\ve_i$, for $i=1..k$; + \item obtaining the bitvector width of $\vt_i$ in $\tenv$ (which also checks that $\vt_i$ is a bitvector type), + for $i=1..k$, yields $\vw_i$\ProseOrTypeError; + \item to obtain the (symbolic) width of the resulting bitvector, first define $\widthsum_1$ to be $\vw_1$; + \item then define $\widthsum_i$, for $i=2..k$, to be obtained by reducing the expression that sums \\ $\widthsum_{i-1}$ with the width $\vw_i$; + \item $\vt$ is the bitvector of length $\widthsum_k$ and the empty bitfield list, that is, \\ $\TBits(\widthsum_k, \emptylist)$; + \item $\newe$ is the concatenation expression for $\ves$, that is, $\EConcat(\ves)$. +\end{itemize} +\subsubsection{Formally} +\begin{mathpar} +\inferrule{ + i=1..k: \annotateexpr{\tenv, \vli[i]} \typearrow (\vt_i, \ve_i) \OrTypeError\\\\ + \vts \eqdef [i=1..k: \vt_i]\\ + \ves \eqdef [i=1..k: \ve_i]\\ + i=1..k: \getbitvectorwidth(\tenv, \vt_i) \typearrow \vw_i \OrTypeError\\\\ + \widthsum_1 \eqdef \vw_1\\ + i=2..k: \normalize(\tenv, \EBinop(\PLUS, \widthsum_{i-1}, \vw_i)) \typearrow \widthsum_i +}{ + \annotateexpr{\tenv, \EConcat(\vli)} \typearrow (\TBits(\widthsum_k, \emptylist), \EConcat(\ves)) +} +\end{mathpar} +\CodeSubsection{\EConcatBegin}{\EConcatEnd}{../Typing.ml} + +\subsubsection{Comments} +The sum of the widths of the bitvector types~\texttt{ts} might be a symbolic +expression that is unresolvable to an integer. For example: +\ASLExample{\typingtests/TypingRule.EConcatUnresolvableToInteger.asl} +\lrmcomment{This is related to \identr{NYNK} and \identr{KCZS}.} + +\subsection{Semantics} +\subsubsection{SemanticsRule.EConcat\label{sec:SemanticsRule.EConcat}} +\subsubsection{Example} +In the specification: +\ASLExample{\semanticstests/SemanticsRule.EConcat.asl} +the expression \texttt{['10', '11']} evaluates to the value \texttt{'1011'}. + +\subsubsection{Example} +In the specification: +\ASLExample{\semanticstests/SemanticsRule.EConcat2.asl} +the expression \texttt{['1111', '0000']} evaluates to the value \texttt{'11110000'}. + +\subsubsection{Prose} +All of the following apply: +\begin{itemize} +\item $\ve$ denotes a concatenation of bitvector expressions, $\EConcat(\elist)$; +\item the evaluation of $\elist$ in $\env$ is $\Normal((\vlist, \vg), \newenv)$\ProseOrAbnormal; +\item $\vv$ is the bitvector constructed from the concatenation of $\vlist$. +\end{itemize} +\subsubsection{Formally} +\begin{mathpar} +\inferrule{ + \evalexprlist{\env, \elist} \evalarrow \Normal((\vlist, \vg), \newenv) \OrAbnormal\\ + \concatbitvectors(\vlist) \evalarrow \vv +}{ + \evalexpr{\env, \EConcat(\elist)} \evalarrow \Normal((\vv, \vg), \newenv) +} +\end{mathpar} +\CodeSubsection{\EvalEConcatBegin}{\EvalEConcatEnd}{../Interpreter.ml} + +\subsubsection{Comments} +\lrmcomment{This is related to \identr{BRCM}:} + +\subsubsection{SemanticsRule.EExprList \label{sec:SemanticsRule.EExprList}} +\subsubsection{Prose} +The relation +\hypertarget{def-evalexprlist}{} +\[ + \evalexprlist{\overname{\envs}{\env} \aslsep \overname{\expr^*}{\vle}} \;\aslrel\; + \Normal((\overname{\vals^*}{\vv} \times \overname{\XGraphs}{\vg})\aslsep \overname{\envs}{\newenv}) \cup + \overname{\TThrowing}{\ThrowingConfig} \cup \overname{\TError}{\ErrorConfig} +\] +evaluates the list of expressions $\vle$ in left-to-right order in the initial environment $\env$ +and returns the resulting value $\vv$, the parallel composition of the execution graphs +generated from evaluating each expression, and the new environment $\newenv$. +If the evaluation of any expression terminates abnormally then the abnormal configuration is returned. + +\subsubsection{Formally} +\begin{mathpar} + \inferrule[empty]{} + { + \evalexprlist{\env, \emptylist} \evalarrow \Normal((\emptylist, \emptygraph), \env) + } +\and + \inferrule[nonempty]{ + \texttt{le} \eqname [\ve] \concat \vle1\\ + \evalexpr{\env, \ve} \evalarrow \Normal((\vvone, \vgone), \envone) \OrAbnormal\\ + \evalexprlist{\envone, \vle1} \evalarrow \Normal((\vvs, \vgtwo), \newenv) \OrAbnormal\\ + \vg \eqdef \vgone \parallelcomp \vgtwo \\ + \vv \eqdef [\vvone] \concat \vvs + } + { + \evalexprlist{\env, \vle} \evalarrow \Normal((\vv, \vg), \newenv) + } +\end{mathpar} + +\section{Asserting Type Conversion Expressions\label{sec:AssertingTypeConversionExpressions}} +\lrmcomment{This is related to \identi{TCST}:} +The rule about domains in the definitions of subtype-satisfaction and +type-satisfaction means that it is illegal to use the unconstrained integer +where a constrained integer is expected. An asserting type conversion (ATC) can +be used to overcome this. + +\lrmcomment{This is related to \identi{CGRH}:} +An ATC allows code to explicitly mark places where uses of constrained types +would otherwise be a static type-checking error. The intent is to reduce the +incidence of unintended errors by making such uses fail type-checking unless +the asserting type conversion is provided. + +\lrmcomment{This is related to \identr{WZVX}:} +Note that ATCs are execution-time checks. An execution-time check is a +condition that is evaluated during the evaluation of an execution-time +initializer expression or subprogram. If the condition evaluates to $\False$ it +is a dynamic error. + +\subsection{Syntax} +\begin{flalign*} +\Nexpr \derives\ & \Nexpr \parsesep \Tas \parsesep \Nty &\\ + |\ & \Nexpr \parsesep \Tas \parsesep \Nintconstraints & +\end{flalign*} + +\subsection{Abstract Syntax} +\begin{flalign*} +\expr \derives\ & \overtext{\EATC}{Type assertion}(\expr, \overtext{\ty}{asserted type}) & +\end{flalign*} + +\subsubsection{ASTRule.ATC} +\begin{mathpar} +\inferrule[type]{}{ + \buildexpr(\overname{\Nexpr(\punnode{\Nexpr}, \Tas, \punnode{\Nty})}{\vparsednode}) \astarrow + \overname{\EATC(\astof{\vexpr}, \astof{\tty})}{\vastnode} +} +\end{mathpar} + +\begin{mathpar} +\inferrule[int\_constraints]{}{ + { + \begin{array}{r} + \buildexpr(\overname{\Nexpr(\punnode{\Nexpr}, \Tas, \punnode{\Nintconstraints})}{\vparsednode}) \astarrow\\ + \overname{\EATC(\astof{\vexpr}, \TInt(\astof{\vintconstraints}))}{\vastnode} + \end{array} + } +} +\end{mathpar} + +\subsection{Typing} +\subsubsection{TypingRule.ATC\label{sec:TypingRule.ATC}} +\subsubsection{Prose} +All of the following apply: +\begin{itemize} + \item $\ve$ denotes an asserting type conversion with expression $\vep$ and type $\tty$, that is $\EATC(\vep, \tty)$; + \item annotating the expression $\vep$ in $\tenv$ yields $(\vt, \vepp)$\ProseOrTypeError; + \item obtaining the \structure\ of $\vt$ in $\tenv$ yields $\vtstruct$\ProseOrTypeError; + \item annotating the type $\tty$ in $\tenv$ yields $\tty'$\ProseOrTypeError; + \item obtaining the \structure\ of $\tty'$ in $\tenv$ yields $\vtystruct$\ProseOrTypeError; + \item applying $\checkatc$ to $\vtstruct$ and $\vtystruct$ in $\tenv$ to check whether the type assertion + will always fail yields $\True$\ProseOrTypeError; + \item checking whether $\vt$ \subtypesatisfies\ $\ttyp$ in $\tenv$ yields $\vb$\ProseOrTypeError; + \item $\newe$ is $\EATC(\ttyp, \vepp)$ if $\vb$ is $\True$ and $\vepp$ otherwise; + \item $\vt$ is $\ttyp$. +\end{itemize} +\subsubsection{Formally} +\begin{mathpar} +\inferrule[type\_equal]{ + \annotateexpr{\tenv, \vep} \typearrow (\vt, \vepp) \OrTypeError\\\\ + \tstruct(\tenv, \vt) \typearrow \vtstruct \OrTypeError\\\\ + \annotatetype{\tenv, \tty} \typearrow \ttyp \OrTypeError\\\\ + \tstruct(\tenv, \ttyp) \typearrow \vtystruct \OrTypeError\\\\ + \checkatc(\tenv, \vtstruct, \vtystruct) \typearrow \True \OrTypeError\\\\ + \subtypesat(\tenv, \vt, \ttyp) \typearrow \vb \OrTypeError\\\\ + \newe \eqdef \choice{\vb}{\EATC(\ttyp, \vepp)}{\vepp} +}{ + \annotateexpr{\tenv, \overname{\EATC(\vep, \tty)}{\ve}} \typearrow (\overname{\ttyp}{\vt}, \newe) +} +\end{mathpar} +\CodeSubsection{\ATCBegin}{\ATCEnd}{../Typing.ml} +\lrmcomment{ + This is related to \identr{VBLL}, \identi{KRLL}, \identg{PFRQ}, \identi{XVBG}, + \identr{GYJZ}, \identi{SZVF}, \identr{PZZJ}, \identr{YCPX}, \identi{ZLBW}, + \identi{TCST}, \identi{CGRH}, \identi{YJBB}. +} + +\subsubsection{TypingRule.CheckATC \label{sec:TypingRule.CheckATC}} +\hypertarget{def-checkatc}{} +The helper function +\[ + \checkatc(\overname{\staticenvs}{\tenv} \aslsep \overname{\ty}{\vtone} \aslsep \overname{\ty}{\vttwo}) \aslto + \{\True\} \cup \overname{\TTypeError}{\TypeErrorConfig} +\] +checks whether the types $\vtone$ and $\vttwo$, which are assumed to not be named types, +are compatible for a typing assertion in the static environment $\tenv$, yielding $\True$. +\ProseOtherwiseTypeError + +\subsubsection{Prose} +One of the following applies: +\begin{itemize} + \item All of the following apply (\textsc{equal}): + \begin{itemize} + \item determining whether $\vtone$ is \typeequivalent\ to $\vttwo$ in $\tenv$ yields $\True$\ProseOrTypeError; + \item the result is $\True$. + \end{itemize} + + \item All of the following apply (\textsc{different\_labels\_error}): + \begin{itemize} + \item determining whether $\vtone$ is \typeequivalent\ to $\vttwo$ in $\tenv$ yields $\False$; + \item the AST labels of $\vtone$ and $\vttwo$ are different; + \item the result is a type error indicating that the type assertion will always fail. + \end{itemize} + + \item All of the following apply (\textsc{int\_bits}): + \begin{itemize} + \item determining whether $\vtone$ is \typeequivalent\ to $\vttwo$ in $\tenv$ yields $\False$; + \item the AST labels of $\vtone$ and $\vttwo$ are the same; + \item the AST label of $\vtone$ is either $\TInt$ or $\TBits$; + \item the result is $\True$. + \end{itemize} + + \item All of the following apply (\textsc{tuple}): + \begin{itemize} + \item determining whether $\vtone$ is \typeequivalent\ to $\vttwo$ in $\tenv$ yields $\False$; + \item $\vtone$ is a tuple type with list of tuples $\vlone$, that is, $\TTuple(\vlone)$; + \item $\vtone$ is a tuple type with list of tuples $\vltwo$, that is, $\TTuple(\vltwo)$; + \item checking whether $\vlone$ and $\vltwo$ have the same length yields $\True$\ProseTerminateAs{\TypeErrorVal{\TypeAsssertionFails}}; + \item applying $\checkatc$ to $\vlone[\vi]$ and $\vltwo[\vi]$ in $\tenv$ for every $\vi\in\listrange(\vlone)$ yields $\True$\ProseOrTypeError; + \item the result is $\True$; + \end{itemize} + + \item All of the following apply (\textsc{other\_error}): + \begin{itemize} + \item determining whether $\vtone$ is \typeequivalent\ to $\vttwo$ in $\tenv$ yields $\False$; + \item the AST labels of $\vtone$ and $\vttwo$ are the same; + \item the AST label of $\vtone$ is neither $\TInt$, nor $\TBits$, nor $\TTuple$; + \item the result is a type error indicating that the type assertion will always fail. + \end{itemize} +\end{itemize} +\subsubsection{Formally} +\begin{mathpar} +\inferrule[equal]{ + \typeequal(\tenv, \vtone, \vttwo) \typearrow \True \OrTypeError +}{ + \checkatc(\tenv, \vtone, \vttwo) \typearrow \True +} +\end{mathpar} + +\begin{mathpar} +\inferrule[different\_labels\_error]{ + \typeequal(\tenv, \vtone, \vttwo) \typearrow \False\\\\ + \astlabel(\vtone) \neq \astlabel(\vttwo) +}{ + \checkatc(\tenv, \vtone, \vttwo) \typearrow \TypeErrorVal{\TypeAsssertionFails} +} +\end{mathpar} + +\begin{mathpar} +\inferrule[int\_bits]{ + \typeequal(\tenv, \vtone, \vttwo) \typearrow \False\\\\ + \astlabel(\vtone) = \astlabel(\vttwo)\\ + \astlabel(\vtone) \in \{\TInt, \TBits\} +}{ + \checkatc(\tenv, \vtone, \vttwo) \typearrow \True +} +\end{mathpar} + +\begin{mathpar} +\inferrule[tuple]{ + \typeequal(\tenv, \vtone, \vttwo) \typearrow \False\\\\ + \vtone = \TTuple(\vlone)\\ + \vttwo = \TTuple(\vltwo)\\ + \checktrans{|\vlone|=|\vltwo|}{\TypeAsssertionFails} \typearrow \True\OrTypeError\\\\ + \vi\in\listrange(\vlone): \checkatc(\vlone[\vi], \vltwo[\vi]) \typearrow \True\OrTypeError +}{ + \checkatc(\tenv, \vtone, \vttwo) \typearrow \True +} +\end{mathpar} + +\begin{mathpar} +\inferrule[other\_error]{ + \typeequal(\tenv, \vtone, \vttwo) \typearrow \False\\\\ + \astlabel(\vtone) = \astlabel(\vttwo)\\ + \astlabel(\vtone) \not\in \{\TInt, \TBits, \TTuple\} +}{ + \checkatc(\tenv, \vtone, \vttwo) \typearrow \True +} +\end{mathpar} + +\subsection{Semantics} +\subsubsection{SemanticsRule.ATC \label{sec:SemanticsRule.ATC}} +\subsubsection{Example} +\ASLExample{\semanticstests/SemanticsRule.ATCValue.asl} + +\subsubsection{Example} +\ASLExample{\semanticstests/SemanticsRule.ATCError.asl} + +\subsubsection{Example} +\lrmcomment{This is related to \identr{YCPX}:} + +Dynamic error conditions only hold if the asserting type conversion is +evaluated. + +In the example below, the asserting type conversion on \texttt{y} is +not a dynamic error if the invocation of \texttt{f1} returns $\False$ when +evaluated: +\ASLExample{\semanticstests/SemanticsRule.ATCNotDynamicErrorIfFalse.asl} + +\subsubsection{Example} +The following excerpts indicates several points where various static and +dynamic errors can occur: +\ASLExample{\semanticstests/SemanticsRule.ATCVariousErrors.asl} + +\subsubsection{Prose} +All of the following apply: +\begin{itemize} +\item $\ve$ denotes an asserted type conversion expression, $\EATC(\veone, \vt)$; +\item evaluating $\veone$ in $\env$ results in $\Normal((\vv, \vgone), \newenv)$\ProseOrAbnormal; +\item evaluating whether $\vv$ has type $\vt$ in $\env$ results in $(\vb, \vgtwo)$\ProseTerminateAs{\ErrorConfig}; +\item one of the following applies: + \begin{itemize} + \item all of the following apply (\textsc{okay}): + \begin{itemize} + \item $\vb$ is the native Boolean for \True; + \item $\vg$ is the ordered composition of $\vgone$ and $\vgtwo$ with the $\asldata$ edge. + \end{itemize} + \item all of the following apply (\textsc{error}): + \begin{itemize} + \item $\vb$ is the native Boolean for \True; + \item an asserted type conversion error is returned. + \end{itemize} + \end{itemize} +\end{itemize} +\subsubsection{Formally} +\begin{mathpar} +\inferrule[okay]{ + \evalexpr{\env, \veone} \evalarrow \Normal((\vv, \vgone), \newenv) \OrAbnormal\\\\ + \isvaloftype(\env, \vv, \vt) \evalarrow (\vb, \vgtwo) \OrDynError\\\\ + \vb \eqname \nvbool(\True)\\ + \vg \eqdef \ordered{\vgone}{\asldata}{\vgtwo} +}{ + \evalexpr{\env, \EATC(\veone, \vt)} \evalarrow \Normal((\vv, \vg), \newenv) +} +\and +\inferrule[error]{ + \evalexpr{\env, \veone} \evalarrow \Normal((\vv, \Ignore), \Ignore)\\ + \neg\isvaloftype(\env, \vv, \vt) \evalarrow (\vb, \Ignore)\\ + \vb \eqname \nvbool(\False) +}{ + \evalexpr{\env, \EATC(\veone, \vt)} \evalarrow \ErrorVal{ATC\_TypeMismatch} +} +\end{mathpar} +\CodeSubsection{\EvalATCBegin}{\EvalATCEnd}{../Interpreter.ml} + +\subsubsection{SemanticsRule.IsValOfType} +\subsubsection{Prose} +\hypertarget{def-isvaloftype}{} +The relation +\[ + \isvaloftype(\overname{\envs}{\env} \aslsep \overname{\vals}{\vv} \aslsep \overname{\ty}{\vt}) \;\aslrel\; + (\overname{\Bool}{\vb} \times \overname{\XGraphs}{\vg}) \cup \overname{\TError}{\ErrorConfig} +\] +checks whether the value $\vv$ can be stored in a variable of type $\vt$ in the environment $\env$, +resulting in a Boolean value $\vb$ and execution graph $\vg$ or a dynamic error. + +This relation is used in the context of a asserted type conversion, +which means the type-checker rule \nameref{sec:TypingRule.ATC} was already applied, +thus filtering cases where the type inferred for the converted expression +does not type-satisfy $\vt$. The semantics takes this into account and +only returns \False\ in cases where dynamic information is required. + +One of the following applies: +\begin{itemize} + \item All of the following apply (\textsc{type\_equal}): + \begin{itemize} + \item the AST label of $\vt$ is not $\TInt$, $\TBits$, or $\TTuple$; + \item $\vb$ is \True (since \nameref{sec:TypingRule.ATC} + succeeds in these cases only if the \structure\ of the type of the expression and the \structure\ of the type asserted against are \typeequivalent); + \item $\vg$ is the empty graph. + \end{itemize} + + \item All of the following apply (\textsc{int\_unconstrained}): + \begin{itemize} + \item $\vt$ has the structure of the unconstrained integer; + \item $\vb$ is \True; + \item $\vg$ is the empty graph. + \end{itemize} + + \item All of the following apply (\textsc{int\_wellconstrained}): + \begin{itemize} + \item $\vt$ has the structure of a well-constrained integer with constraints $\vc_{1..k}$; + \item $\vv$ is the \nativevalue\ integer for $n$; + \item the evaluation of every constraint $\vc_i$ with $n$ in environment $\env$ + yields a Boolean value $\vb_i$ and an execution graph $\vg_i$\ProseOrError; + \item $\vb$ is the Boolean disjunction of all Boolean values $\vb_i$, for $i=1..k$; + \item $\vg$ is the parallel composition of all execution graphs $\vg_i$, for $i=1..k$; + \end{itemize} + + \item All of the following apply (\textsc{tuple}): + \begin{itemize} + \item $\vt$ is a tuple with types $\vt_i$, for $i=1..k$; + \item the value at every index $i=1..k$ of $\vv$ is $\vu_i$, for $i=1..k$, + \item the evaluation of $\isvaloftype$ for every value $\vu_i$ + and corresponding type $\vt_i$, for $i=1..k$, + results in a Boolean $\vb_i$ and execution graph $\vg_i$\ProseOrError; + \item $\vb$ is the Boolean conjunction of all Boolean values $\vb_i$, for $i=1..k$; + \item $\vg$ is the parallel composition of all execution graphs $\vg_i$, for $i=1..k$; + of the constraints. + \end{itemize} +\end{itemize} +\subsubsection{Formally} +\begin{mathpar} +\inferrule[type\_equal]{ + \astlabel(\vt) \not\in \{\TInt, \TBits\} +}{ + \isvaloftype(\env, \vv, \vt) \evalarrow (\overname{\True}{\vb}, \overname{\emptygraph}{\vg}) +} +\end{mathpar} + +\begin{mathpar} +\inferrule[int\_unconstrained]{}{ + \isvaloftype(\env, \vv, \overname{\TInt(\unconstrained)}{\vt}) \evalarrow (\overname{\True}{\vb}, \overname{\emptygraph}{\vg}) +} +\end{mathpar} + +\hypertarget{def-integerconstraintsatisfied}{} +To handle \emph{well-constrained integers} (integers with a non-empty list of constraints), +we introduce the helper relation +\[ + \integerconstraintsatisfied(\overname{\envs}{\env} \aslsep \overname{\intconstraint}{\vc} \aslsep \overname{\Z}{n}) \;\aslrel\; + (\overname{\Bool}{\vb} \times \overname{\XGraphs}{\vg}) +\] +which checks whether the integer value $n$ \emph{meets the constraint} $\vc$ +(that is, whether $n$ is within the range of values defined by $\vc$) in the environment $\env$ +and returns a Boolean answer $\vb$ and the execution graph $\vg$ resulting from evaluating +the expressions appearing in $\vc$: +\begin{mathpar} +\inferrule[Constraint\_Exact\_Sat]{ + \evalexprsef{\env, \ve} \evalarrow (\nvint(m), \vg) \OrDynError\\\\ + \vb \eqdef m = n +} +{ + \integerconstraintsatisfied(\env, \constraintexact(\ve), n) \evalarrow (\vb, \vg) +} +\and +\inferrule[Constraint\_Range\_Sat]{ + \evalexprsef{\env, \veone} \evalarrow (\nvint(a), \vgone) \OrDynError\\\\ + \evalexprsef{\env, \vetwo} \evalarrow (\nvint(b), \vgtwo) \OrDynError\\\\ + \vb \eqdef \choice{a \leq n \wedge n \leq b}{\True}{\False}\\ + \vg \eqdef \vgone \parallelcomp \vgtwo +} +{ + \integerconstraintsatisfied(\env, \constraintrange(\veone, \vetwo), n) \evalarrow (\vb, \vg) +} +\end{mathpar} + +Finally, we can check whether an integer value satisfies any of the constraints: +\begin{mathpar} +\inferrule[int\_wellconstrained]{ + \vv \eqname \nvint(n)\\ + i=1..k: \integerconstraintsatisfied(\env, \vc_i, n) \evalarrow (\vb_i, \vg_i) \OrDynError\\\\ + \vb \eqdef \bigvee_{i=1}^k \vb_i\\ + \vg \eqdef \parallel_{i=1}^k \vg_i +}{ + \isvaloftype(\env, \vv, \overname{\TInt(\wellconstrained(\vc_{1..k}))}{\vt}) \evalarrow (\vb, \vg) +} +\end{mathpar} + +\begin{mathpar} +\inferrule[tuple]{ + i=1..k: \getindex(i, \vv) \evalarrow \vu_i\\ + i=1..k: \isvaloftype(\env, \vu_i, \vt_i) \evalarrow (\vb_i, \vg_i) \OrDynError\\\\ + \vb \eqdef \bigwedge_{i=1}^k \vb_i \\ + \vg \eqdef \parallel_{i=1}^k \vg_i +}{ + \isvaloftype(\env, \vv, \overname{\TTuple(i=1..k: \vt_i)}{\vt}) \evalarrow (\vb, \vg) +} +\end{mathpar} +\CodeSubsection{\EvalValOfTypeBegin}{\EvalValOfTypeEnd}{../Interpreter.ml} + +Notice that these rules cover all types, including named types ($\TNamed$), +since the \typedast\ returned from \nameref{sec:TypingRule.ATC} is the \structure\ of the type +given in the specification. +% +Parameterized integers (integers with an empty set of constraints) +cannot appear as a type, since ASL syntax does not allow the following: +\begin{itemize} +\item Declaring an parameterized integer as a variable, +\item Declaring an alias to an parameterized integer type, and +\item Declaring an parameterized integer in a compound type. +\end{itemize} + +\section{Pattern Matching Expressions\label{sec:PatternMatchingExpressions}} +The binary operator $\Tin$ tests whether a value (referred to as the discriminant) matches any item from a $\Npatternset$. +Lists of patterns are also used in case statements. +% +\chapref{PatternMatching} goes into the details of the various types of patterns that can be matched against. + +\subsection{Syntax} +\begin{flalign*} +\Nexpr \derives\ & \Nexpr \parsesep \Tin \parsesep \Npatternset &\\ + |\ & \Nexpr \parsesep \Tin \parsesep \Tmasklit &\\ +\Npatternset \derivesinline\ & \Tbnot \parsesep \Tlbrace \parsesep \Npatternlist \parsesep \Trbrace &\\ + |\ & \Tlbrace \parsesep \Npatternlist \parsesep \Trbrace &\\ +\Npatternlist \derivesinline\ & \NClist{\Npattern} & +\end{flalign*} + +\subsection{Abstract Syntax} +\begin{flalign*} +\expr \derives\ & \EPattern(\expr, \pattern) & +\end{flalign*} + +\subsubsection{ASTRule.EPattern} +\begin{mathpar} +\inferrule[pattern\_set]{}{ + { + \begin{array}{r} + \buildexpr(\overname{\Nexpr(\punnode{\Nexpr}, \Tin, \punnode{\Npatternset})}{\vparsednode}) \astarrow\\ + \overname{\EPattern(\astof{\vexpr}, \astof{\vpatternset})}{\vastnode} + \end{array} + } +} +\end{mathpar} + +\begin{mathpar} +\inferrule[pattern\_mask]{}{ + { + \begin{array}{r} + \buildexpr(\overname{\Nexpr(\punnode{\Nexpr}, \Tin, \Tmasklit(\vm))}{\vparsednode}) \astarrow\\ + \overname{\EPattern(\astof{\vexpr}, \PatternMask(\vm))}{\vastnode} + \end{array} + } +} +\end{mathpar} + +\subsubsection{ASTRule.PatternSet\label{sec:ASTRule.PatternSet}} +\hypertarget{build-patternset}{} +The function +\[ + \buildpatternset(\overname{\parsenode{\Npatternset}}{\vparsednode}) \;\aslto\; \overname{\pattern}{\vastnode} +\] +transforms a parse node $\vparsednode$ into an AST node $\vastnode$. + +\begin{mathpar} +\inferrule[not]{}{ + { + \begin{array}{r} + \buildpatternset(\Npatternset(\Tbnot, \Tlbrace, \punnode{\Npatternlist}, \Trbrace)) \astarrow\\ + \overname{\PatternNot(\astof{\vpatternlist})}{\vastnode} + \end{array} + } +} +\end{mathpar} + +\begin{mathpar} +\inferrule[list]{}{ + \buildpatternset(\Npatternset(\Tlbrace, \punnode{\Npatternlist}, \Trbrace)) \astarrow + \overname{\astof{\vpatternlist}}{\vastnode} +} +\end{mathpar} + +\subsubsection{ASTRule.PatternList \label{sec:ASTRule.PatternList}} +\hypertarget{build-patternlist}{} +The function +\[ + \buildpatternlist(\overname{\parsenode{\Npatternlist}}{\vparsednode}) \;\aslto\; \overname{\pattern}{\vastnode} +\] +transforms a parse node $\vparsednode$ into an AST node $\vastnode$. + +\begin{mathpar} +\inferrule{ + \buildclist[\buildpattern](\vpatterns) \astarrow \vpatternasts +}{ + { + \begin{array}{r} + \buildpatternlist(\Npatternlist(\namednode{\vpatterns}{\NClist{\Npattern}})) \astarrow\\ + \overname{\PatternAny(\vpatternasts)}{\vastnode} + \end{array} + } +} +\end{mathpar} + +\subsection{Typing} +\subsubsection{TypingRule.EPattern \label{sec:TypingRule.EPattern}} +\subsubsection{Prose} +All of the following apply: +\begin{itemize} + \item $\ve$ denotes a pattern expression to test whether $\veone$ matches the pattern $\vpat$, that is, \\ $\EPattern(\veone, \vpat)$; + \item annotating the expression $\veone$ in $\tenv$ yields $(\vtetwo, \vetwo)$\ProseOrTypeError; + \item applying $\annotatepattern$ to $\vtetwo$ and $\vpat$ in $\tenv$ yields $\vpatp$\ProseOrTypeError; + \item $\vt$ is $\TBool$; + \item $\newe$ denotes whether the expression $\vetwo$ matches $\vpatp$, that is, $\EPattern(\vetwo, \vpatp)$. +\end{itemize} +\subsubsection{Formally} +\begin{mathpar} +\inferrule{ + \annotateexpr{\tenv, \veone} \typearrow (\vtetwo, \vetwo) \OrTypeError\\\\ + \annotatepattern(\tenv, \vtetwo, \vpat) \typearrow \vpatp \OrTypeError +}{ + \annotateexpr{\tenv, \overname{\EPattern(\veone, \vpat)}{\ve}} \typearrow (\overname{\TBool}{\vt}, \overname{\EPattern(\vetwo, \vpatp)}{\newe}) +} +\end{mathpar} +\CodeSubsection{\EPatternBegin}{\EPatternEnd}{../Typing.ml} + +\subsection{Semantics} +\subsubsection{SemanticsRule.EPattern \label{sec:SemanticsRule.EPattern}} +\subsubsection{Example} +In the specification: +\ASLExample{\semanticstests/SemanticsRule.EPatternFALSE.asl} +the expression \texttt{42 IN \{0..3, -4\}} evaluates to the value $\nvbool(\False)$. + +\subsubsection{Example} +In the specification: +\ASLExample{\semanticstests/SemanticsRule.EPatternTRUE.asl} +the expression \texttt{42 IN \{0..3, 42\}} evaluates to $\nvbool(\True)$. + +\subsubsection{Prose} +All of the following apply: +\begin{itemize} + \item $\ve$ denotes a pattern expression, $\EPattern(\ve, \vp)$; + \item evaluating the expression $\ve$ in an environment $\env$ results in \\ + $\Normal((\vvone, \vgone), \newenv)$\ProseOrAbnormal; + \item evaluating whether the pattern $\vp$ matches the value $\vvone$ in $\env$ + results in $\Normal(\vv, \vgtwo)$ where is a native Boolean that determines + whether the is indeed a match; + \item $\vg$ is the ordered composition of $\vgone$ and $\vgtwo$ with the $\asldata$ edge. +\end{itemize} +\subsubsection{Formally} +\begin{mathpar} +\inferrule{ + \evalexpr{\env, \ve} \evalarrow \Normal((\vvone, \vgone), \newenv) \OrAbnormal\\ + \evalpattern{\env, \vvone, \vp} \evalarrow \Normal(\vv, \vgtwo)\\ + \vg \eqdef \ordered{\vgone}{\asldata}{\vgtwo} +}{ + \evalexpr{\env, \EPattern(\ve, \vp)} \evalarrow \Normal((\vv, \vg), \newenv) +} +\end{mathpar} +\CodeSubsection{\EvalEPatternBegin}{\EvalEPatternEnd}{../Interpreter.ml} + +\section{Arbitrary Value Expressions\label{sec:ArbitraryValueExpressions}} +An expression of the form \texttt{UNKNOWN: ty} evaluates to an arbitrary value in the +domain of \texttt{ty}. + +\subsection{Syntax} +\begin{flalign*} +\Nexpr \derives\ & \Tunknown \parsesep \Tcolon \parsesep \Nty & +\end{flalign*} + +\subsection{Abstract Syntax} +\begin{flalign*} +\expr \derives\ & \EUnknown(\ty) & +\end{flalign*} + +\subsubsection{ASTRule.EUnknown} +\begin{mathpar} + \inferrule{}{ + \buildexpr(\overname{\Nexpr(\Tunknown, \Tcolon, \punnode{\Nty})}{\vparsednode}) \astarrow + \overname{\EUnknown(\astof{\tty})}{\vastnode} +} +\end{mathpar} + +\subsection{Typing} +\subsubsection{TypingRule.EUnknown \label{sec:TypingRule.EUnknown}} +\subsubsection{Prose} +All of the following apply: +\begin{itemize} + \item $\ve$ denotes an expression \UNKNOWN\ of type $\tty$, that is, $\EUnknown(\tty)$; + \item annotating the type $\tty$ in $\tenv$ yields $\ttyone$\ProseOrTypeError; + \item obtaining the \structure\ of $\ttyone$ in $\tenv$ yields $\ttytwo$\ProseOrTypeError; + \item $\vt$ is $\ttyone$; + \item $\newe$ is an expression \UNKNOWN\ of type $\ttytwo$, that is, $\EUnknown(\ttytwo)$. +\end{itemize} +\subsubsection{Formally} +\begin{mathpar} +\inferrule{ + \annotatetype{\tenv, \tty} \typearrow \ttyone \OrTypeError\\\\ + \tstruct(\tenv, \ttyone) \typearrow \ttytwo \OrTypeError +}{ + \annotateexpr{\tenv, \EUnknown(\tty)} \typearrow (\ttyone, \EUnknown(\ttytwo)) +} +\end{mathpar} +\CodeSubsection{\EUnknownBegin}{\EUnknownEnd}{../Typing.ml} + +\subsection{Semantics} +\subsubsection{SemanticsRule.EUnknown\label{sec:SemanticsRule.EUnknown}} +\subsubsection{Example} +In the specification: +\ASLExample{\semanticstests/SemanticsRule.EUnknownInteger3.asl} +the expression \texttt{[UNKNOWN : integer]} evaluates to an integer value. + +\subsubsection{Example} +In the specification: +\ASLExample{\semanticstests/SemanticsRule.EUnknownIntegerRange3-42-3.asl} +the expression \verb|UNKNOWN : integer {3, 42}| evaluates to either $\nvint(3)$ or $\nvint(42)$. + +\subsubsection{Prose} +All of the following apply: +\begin{itemize} + \item $\ve$ denotes the \texttt{UNKNOWN} expression annotated with type $\vt$; + \item $\vv$ is an arbitrary value in the domain of $\vt$ in $\env$ (see \secref{DynDomain}); + \item $\newenv$ is $\env$. + \item $\vg$ is the empty execution graph. +\end{itemize} +\subsubsection{Formally} +\begin{mathpar} +\inferrule{\env \eqname (\tenv, \denv)\\ + \vv \in \dynamicdomain(\tenv, \env, \vt) +}{ + \evalexpr{\env, \overname{\EUnknown(\vt)}{\ve}} \evalarrow \Normal((\vv, \overname{\emptygraph}{\vg}), \overname{\env}{\newenv}) +} +\end{mathpar} +\CodeSubsection{\EvalEUnknownBegin}{\EvalEUnknownEnd}{../Interpreter.ml} + +\subsubsection{Comments} +Notice that this rule introduces non-determinism. +\lrmcomment{This is related to \identr{WLCH}:} + +\section{Structured Type Construction Expressions\label{sec:StructuredTypeConstructionExpressions}} +\subsection{Syntax} +\begin{flalign*} +\Nexpr \derives\ & \Tidentifier \parsesep \Tlbrace \parsesep \Clist{\Nfieldassign} \parsesep \Trbrace &\\ +\Nfieldassign \derivesinline\ & \Tidentifier \parsesep \Teq \parsesep \Nexpr & +\end{flalign*} + +\subsection{Abstract Syntax} +\begin{flalign*} +\expr \derives\ & \ERecord(\overtext{\ty}{record type}, \overtext{(\identifier, \expr)^{*}}{field initializers}) & +\end{flalign*} + +\subsubsection{ASTRule.ERecord} +\begin{mathpar} + \inferrule{ + \buildclist[\buildfieldassign](\vfieldassigns) \astarrow \vfieldassignasts + }{ + { + \begin{array}{r} + \buildexpr\left(\overname{\Nexpr\left( + \begin{array}{l} + \Tidentifier(\vt), \Tlbrace, \\ + \wrappedline\ \namednode{\vfieldassigns}{\Clist{\Nfieldassign}}, \\ + \wrappedline\ \Trbrace + \end{array} + \right)}{\vparsednode}\right) \\ + \astarrow\ \overname{\ERecord(\TNamed(\vt), \vfieldassignasts)}{\vastnode} +\end{array} +} +} +\end{mathpar} + +\subsubsection{ASTRule.FieldAssign\label{sec:ASTRule.FieldAssign}} +\hypertarget{build-fieldassign}{} +The function +\[ + \buildfieldassign(\overname{\parsenode{\Nfieldassign}}{\vparsednode}) \;\aslto\; \overname{(\identifier\times\expr)}{\vastnode} +\] +transforms a parse node $\vparsednode$ into an AST node $\vastnode$. + +\begin{mathpar} +\inferrule{}{ + \buildfieldassign(\Nfieldassign(\Tidentifier(\id), \Teq, \punnode{\Nexpr})) \astarrow + \overname{(\id, \astof{\vexpr})}{\vastnode} +} +\end{mathpar} + +\subsection{Typing} +\subsubsection{TypingRule.ERecord \label{sec:TypingRule.ERecord}} +\subsubsection{Prose} +All of the following apply: +\begin{itemize} + \item $\ve$ denotes the record construction expression (which is also used for creating exceptions) of type $\tty$ with fields $\fields$, + that is, $\ERecord(\tty, \vfields)$; + \item obtaining the \underlyingtype\ of $\tty$ in $\tenv$ yields $\ttyanon$\ProseOrTypeError; + \item checking that $\ttyanon$ is a \structuredtype\ yields $\True$\ProseOrTypeError;% \ProseTerminateAs{\TypeErrorVal{\ExpectedStructuredType}}; + \item $\ttyanon$ is a \structuredtype\ with a list of $\field$ elements (consisting of a field name and a field type); + \item obtaining the list of field names from $\vfields$ yields the list of identifiers \\ + $\initializedfields$; + \item obtaining the list of field names from $\fieldtypes$ yields the list of identifiers $\names$; + \item checking whether the set of identifiers in $\names$ is equal to the set of identifiers in $\initializedfields$ + yields $\True$\ProseOrTypeError; + \item checking that the list $\initializedfields$ does not contain duplicates yields \\ + $\True$\ProseOrTypeError; + \item applying $\annotatefieldinit$ to annotate each $\field$ element $(\name,\vep)$ of \\ + $\vfields$ in $\tenv$ yields $(\name,\ve_\name)$\ProseOrTypeError; + \item define $\fieldsp$ as the list containing $(\name,\ve_\name)$ for each $\field$ element $(\name,\vep)$ of $\vfields$; + \item $\vt$ is $\tty$; + \item $\newe$ is the record expression with type $\tty$ and field initializers $\fieldsp$, that is, $\ERecord(\tty, \fieldsp)$; +\end{itemize} +\subsubsection{Formally} +\begin{mathpar} +\inferrule{ + \checktrans{\astlabel(\tty) = \TNamed}{NamedTypeExpected} \checktransarrow \True \OrTypeError\\\\ + \makeanonymous(\tenv, \tty) \typearrow \ttyanon \OrTypeError\\\\ + \checktrans{\astlabel(\ttyanon) \in \{\TRecord, \TException\}}{\ExpectedStructuredType} \typearrow \True\OrTypeError\\\\ + \ttyanon \eqname L(\fieldtypes)\\ + \initializedfields \eqdef \{\name \;|\; (\name, \Ignore)\in\vfields\}\\ + \names \eqdef \fieldnames(\fieldtypes)\\ + \checktrans{\{\names\} = \{\initializedfields\}}{\MissingFieldInitializer} \typearrow \True \OrTypeError\\\\ + \checknoduplicates(\initializedfields) \typearrow \True \OrTypeError\\\\ + { + \begin{array}{r} + (\name, \vep) \in \vfields: \annotatefieldinit(\tenv, (\name, \vep), \fieldtypes) \typearrow \\ + (\name, \ve_\name) \OrTypeError + \end{array} + }\\ + \fieldsp \eqdef [(\name, \vep) \in \fields : (\name, \ve_\name)] +}{ + \annotateexpr{\tenv, \overname{\ERecord(\tty, \vfields)}{\ve}} \typearrow (\overname{\tty}{\vt}, \overname{\ERecord(\tty, \fieldsp)}{\newe}) +} +\end{mathpar} +\CodeSubsection{\ERecordBegin}{\ERecordEnd}{../Typing.ml} +\lrmcomment{This is related to \identr{WBCQ}.} + +\hypertarget{def-annotatefieldinit}{} +\subsubsection{TypingRule.AnnotateFieldInit} +The function +\[ + \annotatefieldinit( + \overname{\staticenvs}{\tenv} \aslsep + \overname{(\identifier\times\expr)}{(\name, \vep)} \aslsep + \overname{\field^*}{\fieldtypes} + ) \aslto + \overname{(\identifier\times\expr)}{(\name, \vepp)} +\] +annotates a field initializers $(\name, \vep)$ in a record expression +with list of fields \\ $\fieldtypes$ and returns the annotated field initializer +$(\name, \vepp)$. \ProseOtherwiseTypeError + +\subsubsection{Prose} +All of the following apply: +\begin{itemize} + \item annotating the expression $\vep$ in $\tenv$ yields $(\vtp, \vepp)$\ProseOrTypeError; + \item One of the following applies: + \begin{itemize} + \item All of the following apply (\textsc{okay}): + \begin{itemize} + \item the unique type associated with $\name$ in $\fieldtypes$ is $\tspecp$; + \item determining whether $\vtp$ \typesatisfies\ $\tspecp$ in $\tenv$ yields $\True$\ProseOrTypeError; + \end{itemize} + + \item All of the following apply (\textsc{error}): + \begin{itemize} + \item there is no type associated with $\name$ in $\fieldtypes$; + \item the result is a type error indicating that the field $\name$ does not exist. + \end{itemize} + \end{itemize} +\end{itemize} + +\subsubsection{Formally} +\begin{mathpar} +\inferrule[okay]{ + \annotateexpr{\tenv, \vep} \typearrow (\vtp, \vepp) \OrTypeError\\\\ + \fieldtype(\fieldtypes, \name) = \tspecp\\ + \checktypesat(\tenv, \vtp, \tspecp) \typearrow \True \OrTypeError +}{ + \annotatefieldinit(\tenv, (\name, \vep), \fieldtypes) \typearrow (\name, \vepp) +} +\and +\inferrule[error]{ + \annotateexpr{\tenv, \vep} \typearrow (\vtp, \vepp) \OrTypeError\\\\ + \fieldtype(\fieldtypes, \name) = \bot +}{ + \annotatefieldinit(\tenv, (\name, \vep), \fieldtypes) \typearrow \\ + \TypeErrorVal{FieldDoesNotExist} +} +\end{mathpar} + +\subsection{Semantics} +\subsubsection{SemanticsRule.ERecord \label{sec:SemanticsRule.ERecord}} +\subsubsection{Example} +In the specification: +\ASLExample{\semanticstests/SemanticsRule.ERecord.asl} +the expression \verb|MyRecordType{a=3, b=42}| evaluates to the native record value \\ +$\nvrecord{\va\mapsto\nvint(3), \vb\mapsto\nvint(42)}$. + +\subsubsection{Prose} +All of the following apply: +\begin{itemize} +\item $\ve$ denotes a record creation expression, $\ERecord(\names, \efields)$; +\item the names of the fields are $\id_{1..k}$; +\item the expressions associated with the fields are $\ve_{1..k}$; +\item evaluating the expressions of $\fields$ in order yields \\ + $\Normal((\vvfields,\vg), \newenv)$\ProseOrAbnormal; +\item $\vvfields$ is a list of \nativevalues\ $\vv_{1..k}$; +\item $\vv$ is the native record that maps $\id_i$ to $\vv_i$, for $i=1..k$. +\end{itemize} +\subsubsection{Formally} +\begin{mathpar} +\inferrule{ + \efields \eqname [i=1..k: (\id_i, \ve_i)]\\ + \names \eqdef \id_{1..k} \\ + \fields \eqdef \ve_{1..k} \\ + \evalexprlist{\env, \fields} \evalarrow \Normal((\vvfields,\vg), \newenv) \OrAbnormal\\ + \vvfields \eqname \vv_{1..k}\\ + \vv \eqdef \nvrecord{\{i=1..k: \id_i\mapsto \vv_i\}} +}{ + \evalexpr{\env, \ERecord(\Ignore, \efields)} \evalarrow \Normal((\vv, \vg), \newenv) +} +\end{mathpar} +\CodeSubsection{\EvalERecordBegin}{\EvalERecordEnd}{../Interpreter.ml} + +\section{Tuple Expressions\label{sec:TupleExpressions}} +\subsection{Syntax} +\begin{flalign*} +\Nexpr \derives\ & \Plisttwo{\Nexpr} & +\end{flalign*} + +\subsection{Abstract Syntax} +\begin{flalign*} +\expr \derives\ & \ETuple(\expr^{+}) & +\end{flalign*} + +\subsubsection{ASTRule.ETuple} +\begin{mathpar} +\inferrule[tuple]{ + \buildplist[\buildexpr](\vexprs) \astarrow \vexprasts +}{ + \buildexpr(\overname{\Nexpr(\namednode{\vexprs}{\Plisttwo{\Nexpr}})}{\vparsednode}) \astarrow + \overname{\ETuple(\vexprasts)}{\vastnode} +} +\end{mathpar} + +\subsection{Typing} +\subsubsection{TypingRule.ETuple \label{sec:TypingRule.ETuple}} +\subsubsection{Prose} +All of the following apply: +\begin{itemize} + \item $\ve$ denotes a tuple expression with list of expressions $\vli$, that is, $ \ETuple(\vli)$; + \item annotating each expression $\vle[i]$ in $\tenv$, for $i=1..k$, yields $(\vt_i, \ve_i$)\ProseOrTypeError; + \item $\vt$ is the tuple type with list of types $\vt_i$, for $i=1..k$; + \item $\newe$ is tuple expression over list of expressions $\ve_i$, for $i=1..k$. +\end{itemize} +\subsubsection{Formally} +\begin{mathpar} +\inferrule{ + i=1..k: \annotateexpr{\tenv, \vle[i]} \typearrow (\vt_i, \ve_i) \OrTypeError +}{ + \annotateexpr{\tenv, \ETuple(\vli)} \typearrow (\TTuple(\vt_{1..k}), \ETuple(\ve_{1..k})) +} +\end{mathpar} +\CodeSubsection{\ETupleBegin}{\ETupleEnd}{../Typing.ml} + +\subsection{Semantics} +\subsubsection{SemanticsRule.ETuple \label{sec:SemanticsRule.ETuple}} +\subsubsection{Example} +In the specification: +\ASLExample{\semanticstests/SemanticsRule.ETuple.asl} +the expression \texttt{(3, Return42())} evaluates to the value \texttt{(3, 42)}. + +\subsubsection{Prose} +All of the following apply: +\begin{itemize} + \item $\ve$ denotes a tuple expression, $\ETuple(\elist)$; + \item the evaluation of $\elist$ in $\env$ is $\Normal((\vlist, \vg), \newenv)$\ProseOrAbnormal; + \item $\vv$ is the native vector constructed from the values in $\vlist$. +\end{itemize} +\subsubsection{Formally} +\begin{mathpar} +\inferrule{ + \evalexprlist{\env, \elist} \evalarrow \Normal((\vlist, \vg), \newenv) \OrAbnormal\\ + \vv \eqdef \nvvector{\vlist} +}{ + \evalexpr{\env, \ETuple(\elist)} \evalarrow \Normal((\vv, \vg), \newenv) +} +\end{mathpar} +\CodeSubsection{\EvalETupleBegin}{\EvalETupleEnd}{../Interpreter.ml} + +\section{Parenthesized Expressions\label{sec:ParenthesizedExpressions}} +A single expression inside parentheses is not a tuple. +Parenthesizing an expression can be used to improve readability and enforce an order of evaluation. + +\subsection{Syntax} +\begin{flalign*} +\Nexpr \derives\ & \Tlpar \parsesep \Nexpr \parsesep \Trpar & +\end{flalign*} + +\subsection{Abstract Syntax} +\subsubsection{ASTRule.Expr \label{sec:ASTRule.Expr}} +\begin{mathpar} + \inferrule[sub\_expr]{}{ + \buildexpr(\overname{\Nexpr(\Tlpar, \punnode{\Nexpr}, \Trpar)}{\vparsednode}) \astarrow + \overname{\astof{\vexpr}}{\vastnode} +} +\end{mathpar} + +\section{Side-effect-free Expressions\label{sec:SideEffectFreeExpressions}} +\subsection{Typing} +\subsection{Semantics} +\subsubsection{SemanticsRule.ESideEffectFreeExpr \label{sec:SemanticsRule.ESideEffectFreeExpr}} +\subsubsection{Prose} +The helper relation +\hypertarget{def-evalexprsef}{} +\[ + \evalexprsef{\overname{\envs}{\env} \aslsep \overname{\expr}{\ve}} \;\aslrel\; + \Normal(\overname{\vals}{\vv}\aslsep\overname{\XGraphs}{\vg}) \cup + \overname{\TError}{\ErrorConfig} +\] +specializes the expression evaluation relation for side-effect-free expressions +by omitting throwing configurations as possible output configurations. + +\subsubsection{Formally} +\begin{mathpar} + \inferrule{ + \evalexpr{\env, \ve} \evalarrow \Normal((\vv,\vg), \env) \OrDynError + } + { + \evalexprsef{\env, \ve} \evalarrow \Normal(\vv, \vg) + } +\end{mathpar} +Notice that the output configuration does not contain an environment, +since side-effect-free expressions do not modify the environment. diff --git a/asllib/doc/GlobalDeclarations.tex b/asllib/doc/GlobalDeclarations.tex new file mode 100644 index 000000000..4a4fb1998 --- /dev/null +++ b/asllib/doc/GlobalDeclarations.tex @@ -0,0 +1,210 @@ +\chapter{Global Declarations\label{chap:GlobalDeclarations}} +Global declarations are grammatically derived from $\Ndecl$ and represented as ASTs by $\decl$. + +There are four kinds of global declarations: +\begin{itemize} + \item Subprogram declarations, defined in \chapref{SubprogramDeclarations}; + \item Type declarations, defined in \chapref{TypeDeclarations}; + \item Global storage declarations, defined in \chapref{GlobalStorageDeclarations}; + \item Global pragmas. +\end{itemize} + +The typing of global declarations is defined in \secref{GlobalDeclarationsTyping}. +The semantics of global declarations in defined in \secref{GlobalStorageDeclarationsSemantics}. + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +\section{Syntax} +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +Subprogram declarations: +\begin{flalign*} +\Ndecl \derivesinline\ & \productionname{funcdecl}{func\_decl}\ \Tfunc \parsesep \Tidentifier \parsesep \Nparamsopt \parsesep \Nfuncargs \parsesep \Nreturntype \parsesep \Nfuncbody &\\ +|\ & \productionname{proceduredecl}{procedure\_decl}\ \Tfunc \parsesep \Tidentifier \parsesep \Nparamsopt \parsesep \Nfuncargs \parsesep \Nfuncbody &\\ +|\ & \productionname{getter}{getter}\ \Tgetter \parsesep \Tidentifier \parsesep \Nparamsopt \parsesep \Naccessargs \parsesep \Nreturntype \parsesep \Nfuncbody&\\ +|\ & \productionname{noarggetter}{no\_arg\_getter}\ \Tgetter \parsesep \Tidentifier \parsesep \Nreturntype \parsesep \Nfuncbody &\\ +|\ & \productionname{setter}{setter}\ \Tsetter \parsesep \Tidentifier \parsesep \Nparamsopt \parsesep \Naccessargs \parsesep \Teq \parsesep \Ntypedidentifier & \\ + & \wrappedline\ \parsesep \Nfuncbody &\\ +|\ & \productionname{noargsetter}{no\_arg\_setter}\ \Tsetter \parsesep \Tidentifier \parsesep \Teq \parsesep \Ntypedidentifier \parsesep \Nfuncbody&\\ +\end{flalign*} + +Type declarations: +\begin{flalign*} +\Ndecl \derivesinline\ & \productionname{typedecl}{type\_decl}\ \Ttype \parsesep \Tidentifier \parsesep \Tof \parsesep \Ntydecl \parsesep \Nsubtypeopt \parsesep \Tsemicolon&\\ +|\ & \productionname{subtypedecl}{subtype\_decl}\ \Ttype \parsesep \Tidentifier \parsesep \Nsubtype \parsesep \Tsemicolon&\\ +\end{flalign*} + +Global storage declarations: +\begin{flalign*} +\Ndecl \derivesinline\ & \productionname{globalstorage}{global\_storage}\ \Nstoragekeyword \parsesep \Nignoredoridentifier \parsesep \option{\Tcolon \parsesep \Nty} \parsesep \Teq \parsesep &\\ + & \wrappedline\ \Nexpr \parsesep \Tsemicolon &\\ +|\ & \productionname{globaluninitvar}{global\_uninit\_var}\ \Tvar \parsesep \Nignoredoridentifier \parsesep \Tcolon \parsesep \Nty \parsesep \Tsemicolon&\\ +\end{flalign*} + +Pragmas: +\begin{flalign*} +\Ndecl \derivesinline\ & \productionname{globalpragma}{global\_pragma}\ \Tpragma \parsesep \Tidentifier \parsesep \Clist{\Nexpr} \parsesep \Tsemicolon& +\end{flalign*} + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +\section{Abstract Syntax} +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +\begin{flalign*} +\decl \derives\ & \DFunc(\func) & \\ + |\ & \DGlobalStorage(\globaldecl) & \\ + |\ & \DTypeDecl(\identifier, \ty, (\identifier, \overtext{\Field^*}{with fields})?) & +\end{flalign*} + +\subsubsection{ASTRule.GlobalDecl\label{sec:ASTRule.GlobalDecl}} +\hypertarget{build-decl}{} +The relation +\[ + \builddecl : \overname{\parsenode{\Ndecl}}{\vparsednode} \;\aslrel\; \overname{\decl}{\vastnode} +\] +transforms a parse node $\vparsednode$ into an AST node $\vastnode$. + +\hypertarget{build-globalpragma}{} +\begin{mathpar} +\inferrule[global\_pragma]{} +{ + \builddecl(\overname{\Ndecl(\Tpragma, \Tidentifier(\vx), \Clist{\Nexpr}, \Tsemicolon)}{\vparsednode}) \astarrow \overname{\tododefine{pragma\_node}}{\vastnode} +} +\end{mathpar} + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +\section{Typing\label{sec:GlobalDeclarationsTyping}} +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +\hypertarget{def-typecheckdecl}{} +The function +\[ + \typecheckdecl( + \overname{\staticenvs}{\tenv} \aslsep + \overname{\decl}{\vd} + ) + \aslto (\overname{\decl}{\newd} \times \overname{\staticenvs}{\newtenv}) + \cup \overname{\TTypeError}{\TypeErrorConfig} +\] +annotates a global declaration $\vd$ in the static environment $\tenv$, +yielding an annotated global declaration $\newd$ and modified environment $\newtenv$. +\ProseOtherwiseTypeError + +\subsubsection{TypingRule.TypecheckFunc \label{sec:TypingRule.TypecheckFunc}} +\subsubsection{Prose} +All of the following apply: +\begin{itemize} + \item $\vd$ is a subprogram AST node with a subprogram definition $\vf$, that is, $\DFunc(\vf)$; + \item annotating and declaring the subprogram for $\vf$ in $\tenv$ as per \secref{TypingRule.AnnotateAndDeclareFunc} + yields the new environment $\newtenv$ and a subprogram definition $\vfone$\ProseOrTypeError; + \item annotating the subprogram definition $\vfone$ in $\tenv$ as per \nameref{sec:TypingRule.Subprogram} yields + the annotated subprogram definition $\vftwo$\ProseOrTypeError; + \item define $\newd$ as the subprogram AST node with $\vftwo$, that is, $\DFunc(\vftwo)$. +\end{itemize}\CodeSubsection{\TypecheckFuncBegin}{\TypecheckFuncEnd}{../Typing.ml} + +\subsubsection{Formally} +\begin{mathpar} +\inferrule{ + \vf \eqname \{\text{body}: \SBASL, \ldots\}\\ + \annotateanddeclarefunc(\tenv, \vf) \typearrow (\newtenv, \vfone) \OrTypeError\\\\ + \annotatesubprogram{\newtenv, \vfone} \typearrow \vftwo \OrTypeError +}{ + \typecheckdecl(\tenv, \overname{\DFunc(\vf)}{\vd}) + \typearrow (\overname{\DFunc(\vftwo)}{\newd}, \newtenv) +} +\end{mathpar} + +\subsubsection{TypingRule.Subprogram \label{sec:TypingRule.Subprogram}} +\hypertarget{def-annotatesubprogram}{} +The function +\[ + \annotatesubprogram{\overname{\staticenvs}{\tenv} \aslsep \overname{\func}{\vf}} \aslto \overname{\func}{\vfp} + \cup \overname{\TTypeError}{\TypeErrorConfig} +\] +annotates a subprogram $\vf$ in an environment $\tenv$, resulting in an annotated subprogram $\vfp$. +\ProseOtherwiseTypeError + +Note that the return type in $\vf$ has already been annotated by $\annotatefuncsig$. + +\subsection{Prose} +All of the following apply: +\begin{itemize} + \item $\vf$ is a $\func$ AST node subprogram body $\body$; + \item annotating the block $\body$ in $\tenv$ as per \secref{TypingRule.Block} yields $\newbody$\ProseOrTypeError; + \item $\vfp$ is $\vf$ with the subprogram body substituted with $\newbody$. +\end{itemize} +\subsection{Formally} +\begin{mathpar} +\inferrule{ + { + \begin{array}{rrcl} + \vf \eqname \{ & \funcname &:& \id,\\ + & \funcparameters &:& \vp,\\ + & \funcargs &:& \vargs,\\ + & \funcbody &:& \SBASL(\body),\\ + & \funcreturntype &:& \vt,\\ + & \funcsubprogramtype &:& \subprogramtype \\ + \} &&& + \end{array} + }\\ + \annotateblock{\tenv, \body} \typearrow \newbody \OrTypeError\\\\ + { + \begin{array}{rrcl} + \vfp \eqdef \{ & \funcname &:& \id,\\ + & \funcparameters &:& \vp,\\ + & \funcargs &:& \vargs,\\ + & \funcbody &:& \SBASL(\newbody),\\ + & \funcreturntype &:& \vt,\\ + & \funcsubprogramtype &:& \subprogramtype \\ + \} &&& + \end{array} + }\\ +}{ + \annotatesubprogram{\tenv, \vf} \typearrow \vfp +} +\end{mathpar}\lrmcomment{ +This is related to \identi{GHGK}, \identr{HWTV}, \identr{SCHV}, \identr{VDPC}, +\identr{TJKQ}, \identi{LFJZ}, \identi{BZVB}, \identi{RQQB}. +} +\CodeSubsection{\SubprogramBegin}{\SubprogramEnd}{../Typing.ml} + +\subsubsection{TypingRule.TypecheckGlobalStorage \label{sec:TypingRule.TypecheckGlobalStorage}} +\subsubsection{Prose} +All of the following apply: +\begin{itemize} + \item $\vd$ is a global storage declaration with description $\gsd$, that is, \\ $\DGlobalStorage(\gsd)$; + \item declaring the global storage with description $\gsd$ in $\tenv$ yields the new environment + $\newtenv$ and new global storage description $\gsdp$\ProseOrTypeError; + \item define $\newd$ as the global storage declaration with description $\gsdp$, that is, \\ $\DGlobalStorage(\gsdp)$. +\end{itemize}\CodeSubsection{\TypecheckGlobalStorageBegin}{\TypecheckGlobalStorageEnd}{../Typing.ml} + +\subsubsection{Formally} +\begin{mathpar} +\inferrule{ + \declareglobalstorage(\tenv, \gsd) \typearrow (\newtenv, \gsdp) \OrTypeError +}{ + { + \begin{array}{r} + \typecheckdecl(\tenv, \overname{\DGlobalStorage(\gsd)}{\vd}) + \typearrow \\ (\overname{\DGlobalStorage(\gsdp)}{\newd}, \newtenv) + \end{array} + } +} +\end{mathpar} + +\subsubsection{TypingRule.TypecheckTypeDecl \label{sec:TypingRule.TypecheckTypeDecl}} +\subsubsection{Prose} +All of the following apply: +\begin{itemize} + \item $\vd$ is a type declaration with identifier $\vx$, type $\tty$, + and \optional\ field initializers $\vs$, that is, $\DTypeDecl(\vx, \tty, \vs)$; + \item declaring the type described by $(\vx, \tty, \vs)$ in $\tenv$ + as per \secref{TypingRule.DeclaredType} yields the modified environment $\newtenv$\ProseOrTypeError; + \item define $\newd$ as $\vd$. + \end{itemize} +\CodeSubsection{\TypecheckTypeDeclBegin}{\TypecheckTypeDeclEnd}{../Typing.ml} + +\subsubsection{Formally} +\begin{mathpar} +\inferrule{ + \declaretype(\tenv, \vx, \tty, \vs) \typearrow \newtenv \OrTypeError +}{ + \typecheckdecl(\tenv, \overname{\DTypeDecl(\vx, \tty, \vs)}{\vd}) \typearrow (\overname{\vd}{\newd}, \newtenv) +} +\end{mathpar} diff --git a/asllib/doc/GlobalStorageDeclarations.tex b/asllib/doc/GlobalStorageDeclarations.tex new file mode 100644 index 000000000..4ea2bcd91 --- /dev/null +++ b/asllib/doc/GlobalStorageDeclarations.tex @@ -0,0 +1,756 @@ +\chapter{Global Storage Declarations\label{chap:GlobalStorageDeclarations}} + +Global storage declarations are grammatically derived from $\Ndecl$ via the subset of productions shown in +\secref{GlobalStorageDeclarationsSyntax} and represented as ASTs via the production of $\decl$ +shown in \secref{GlobalStorageDeclarationsAbstractSyntax}. +% +Global storage declarations are typed by $\declareglobalstorage$, which is defined in \nameref{sec:TypingRule.DeclareGlobalStorage}. +% +The semantics of a list of global storage declarations is defined in \nameref{sec:SemanticsRule.EvalGlobals}, +where the list is ordered via \nameref{sec:SemanticsRule.BuildGlobalEnv}. +The semantics of a single global storage declarations is defined in \nameref{sec:SemanticsRule.DeclareGlobal}. + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +\section{Syntax\label{sec:GlobalStorageDeclarationsSyntax}} +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +\begin{flalign*} +\Ndecl \derivesinline\ & \Nstoragekeyword \parsesep \Nignoredoridentifier \parsesep \option{\Tcolon \parsesep \Nty} \parsesep \Teq \parsesep &\\ + & \wrappedline\ \Nexpr \parsesep \Tsemicolon &\\ + |\ & \productionname{globaluninitvar}{global\_uninit\_var}\ \Tvar \parsesep \Nignoredoridentifier \parsesep \Tcolon \parsesep \Nty \parsesep \Tsemicolon&\\ + |\ & \productionname{globalpragma}{global\_pragma}\ \Tpragma \parsesep \Tidentifier \parsesep \Clist{\Nexpr} \parsesep \Tsemicolon& +\end{flalign*} + +\begin{flalign*} +\Nstoragekeyword \derivesinline\ & \Tlet \;|\; \Tconstant \;|\; \Tvar \;|\; \Tconfig&\\ +\Nignoredoridentifier \derivesinline\ & \Tminus \;|\; \Tidentifier & +\end{flalign*} + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +\section{Abstract Syntax\label{sec:GlobalStorageDeclarationsAbstractSyntax}} +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +\begin{flalign*} +\decl \derives\ & \DGlobalStorage(\globaldecl) &\\ +\globaldecl \derives\ & +{\left\{ + \begin{array}{rcl} + \GDkeyword &:& \globaldeclkeyword, \\ + \GDname &:& \identifier,\\ + \GDty &:& \ty?,\\ + \GDinitialvalue &:& \expr? + \end{array} + \right\} + } &\\ + \globaldeclkeyword \derives\ & \GDKConstant \;|\; \GDKConfig \;|\; \GDKLet \;|\; \GDKVar & +\end{flalign*} + +\subsubsection{ASTRule.GlobalDecl} +The relation +\[ + \builddecl : \overname{\parsenode{\Ndecl}}{\vparsednode} \;\aslrel\; \overname{\decl}{\vastnode} +\] +transforms a parse node $\vparsednode$ into an AST node $\vastnode$. + +\hypertarget{build-globalstorage}{} +\begin{mathpar} +\inferrule[global\_storage]{ + \buildstoragekeyword(\keyword) \astarrow \astof{\keyword}\\ + \buildoption[\buildasty](\tty) \astarrow \ttyp\\ + \buildexpr(\vinitialvalue) \typearrow \astof{\vinitialvalue} +} +{ + { + \builddecl\left(\overname{\Ndecl\left( + \begin{array}{r} + \namednode{\vkeyword}{\Nstoragekeyword}, \namednode{\name}{\Nignoredoridentifier}, \\ + \wrappedline\ \namednode{\tty}{\option{\Nasty}}, \Teq, \namednode{\vinitialvalue}{\Nexpr}, \Tsemicolon + \end{array} + \right)}{\vparsednode}\right) + } \astarrow \\ + { + \overname{ + \DGlobalStorage\left(\left\{ + \begin{array}{rcl} + \GDkeyword &:& \astof{\vkeyword},\\ + \GDname &:& \astof{\name},\\ + \GDty &:& \ttyp,\\ + \GDinitialvalue &:& \astof{\vinitialvalue} + \end{array} + \right\}\right) + }{\vastnode} + } +} +\end{mathpar} + +\hypertarget{build-globaluninitvar}{} +\begin{mathpar} +\inferrule[global\_uninit\_var]{ + \buildignoredoridentifier(\cname) \astarrow \name +} +{ + { + \begin{array}{r} + \builddecl(\overname{\Ndecl(\Tvar, \namednode{\cname}{\Nignoredoridentifier}, \Nasty, \Tsemicolon)}{\vparsednode}) \astarrow + \end{array} + } \\ + \overname{\DGlobalStorage(\{\GDkeyword: \GDKVar, \GDname: \name, \GDty: \langle\astof{\Nasty}\rangle, \GDinitialvalue: \None\})}{\vastnode} +} +\end{mathpar} + +\subsubsection{ASTRule.StorageKeyword \label{sec:ASTRule.StorageKeyword}} +\hypertarget{build-storagekeyword}{} +The function +\[ +\buildstoragekeyword(\overname{\parsenode{\Nstoragekeyword}}{\vparsednode}) \;\aslto\; + \overname{\globaldeclkeyword}{\vastnode} +\] +transforms a parse node $\vparsednode$ into an AST node $\vastnode$. + +\begin{mathpar} +\inferrule[let]{}{ + \buildstoragekeyword(\overname{\Nstoragekeyword(\Tlet)}{\vparsednode}) \astarrow \overname{\GDKLet}{\vastnode} +} +\end{mathpar} + +\begin{mathpar} +\inferrule[constant]{}{ + \buildstoragekeyword(\overname{\Nstoragekeyword(\Tconstant)}{\vparsednode}) \astarrow \overname{\GDKConstant}{\vastnode} +} +\end{mathpar} + +\begin{mathpar} +\inferrule[var]{}{ + \buildstoragekeyword(\overname{\Nstoragekeyword(\Tvar)}{\vparsednode}) \astarrow \overname{\GDKVar}{\vastnode} +} +\end{mathpar} + +\begin{mathpar} +\inferrule[config]{}{ + \buildstoragekeyword(\overname{\Nstoragekeyword(\Tconfig)}{\vparsednode}) \astarrow \overname{\GDKConfig}{\vastnode} +} +\end{mathpar} + +\subsubsection{ASTRule.IgnoredOrIdentifier\label{sec:ASTRule.IgnoredOrIdentifier}} +\hypertarget{build-ignoredoridentifier}{} +The relation +\[ +\buildfuncargs(\overname{\parsenode{\Nignoredoridentifier}}{\vparsednode}) \;\aslrel\; + \overname{\identifier}{\vastnode} +\] +transforms a parse node $\vparsednode$ into an AST node $\vastnode$. + +\begin{mathpar} +\inferrule[discard]{ + \id \in \identifier \text{ is fresh} +}{ + \buildignoredoridentifier(\overname{\Nignoredoridentifier(\Tminus)}{\vparsednode}) \astarrow + \overname{\id}{\vastnode} +} +\end{mathpar} + +\begin{mathpar} +\inferrule[id]{}{ + \buildignoredoridentifier(\overname{\Nignoredoridentifier(\Tidentifier(\id))}{\vparsednode}) \astarrow + \overname{\id}{\vastnode} +} +\end{mathpar} + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +\section{Typing} +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +We also define the following helper rules: +\begin{itemize} + \item TypingRule.DeclareGlobalStorage (see \secref{TypingRule.DeclareGlobalStorage}) + \item TypingRule.AnnotateTypeOpt (see \secref{TypingRule.AnnotateTypeOpt}) + \item TypingRule.AnnotateExprOpt (see \secref{TypingRule.AnnotateExprOpt}) + \item TypingRule.AnnotateInitType (see \secref{TypingRule.AnnotateInitType}) + \item TypingRule.AddGlobalStorage (see \secref{TypingRule.AddGlobalStorage}) +\end{itemize} + +\subsubsection{TypingRule.DeclareGlobalStorage \label{sec:TypingRule.DeclareGlobalStorage}} +\hypertarget{def-declareglobalstorage}{} +The function +\[ + \declareglobalstorage(\overname{\staticenvs}{\tenv} \aslsep \overname{\globaldecl}{\gsd}) + \aslto + \overname{\staticenvs}{\newtenv} \aslsep \overname{\globaldecl}{\newgsd} + \cup + \overname{\TTypeError}{\TypeErrorConfig} +\] +annotates the global storage declaration $\gsd$ in the static environment $\tenv$, +yielding a modified static environment $\newtenv$ and annotated global storage declaration $\newgsd$. +\ProseOtherwiseTypeError + +\subsection{Prose} +All of the following apply: +\begin{itemize} + \item $\gsd$ is a global storage declaration with keyword $\keyword$, initial value \\ $\initialvalue$, + \optional\ type $\tyopt$, and name $\name$; + \item checking that $\name$ is not already declared in the global environment of $\tenv$ yields $\True$\ProseOrTypeError; + \item annotating the \optional\ type $\tyopt$ in $\tenv$ via $\annotatetypeopt$ yields \\ + $\tyoptp$\ProseOrTypeError; + \item annotating the \optional\ expression $\initialvalue$ in $\tenv$ via $\annotateexpropt$ yields + $(\initialvaluetype, \initialvaluep)$\ProseOrTypeError; + \item choosing the correct type between $\initialvaluetype$ and $\tyoptp$ in $tenv$ via $\annotateinittype$ yields + $\declaredt$; + \item adding a global storage element with name $\name$, global declaration keyword \\ $\keyword$ and type $\declaredt$ + to $\tenv$ via $\addglobalstorage$ yields $\tenvone$\ProseOrTypeError; + \item One of the following applies: + \begin{itemize} + \item All of the following apply (\textsc{constant}): + \begin{itemize} + \item $\keyword$ is $\GDKConstant$ and therefore $\initialvalue$ is some expression $\ve$ (the ASL parser guarantees + that the expression exists); + \item symbolically simplifying $\ve$ in $\tenvone$ via $\reduceconstants$ yields the literal $\vv$\ProseOrTypeError; + \item $\tenvtwo$ is $\tenvone$ with its $\constantvalues$ component updated by binding $\name$ to $\vv$; + \item $\newgsd$ is $\gsd$ with its type component as $\tyoptp$; + \item $\newtenv$ is $\tenvtwo$. + \end{itemize} + + \item All of the following apply (\textsc{non\_constant}): + \begin{itemize} + \item $\keyword$ is not $\GDKConstant$; + \item $\newtenv$ is $\tenvone$. + \end{itemize} + \end{itemize} + \item $\newgsd$ is $\gsd$ with its type component as $\tyoptp$ and $\initialvalue$ component as $\initialvaluep$; +\end{itemize} +\subsection{Formally} +\begin{mathpar} +\inferrule[constant]{ + \gsd \eqname \{ + \GDkeyword : \keyword, + \GDinitialvalue : \initialvalue, + \GDty : \tyopt, + \GDname: \name + \}\\ +\checkvarnotingenv{\tenv, \name} \typearrow \True \OrTypeError\\\\ +\annotatetypeopt(\tenv, \tyopt) \typearrow \tyoptp \OrTypeError\\\\ +{ + \begin{array}{r} +\annotateexpropt(\tenv, \initialvalue) \typearrow \\ (\initialvaluetype, \initialvaluep) \OrTypeError + \end{array} +}\\ +\annotateinittype(\tenv, \initialvaluetype, \tyoptp) \typearrow \declaredt\\ +\addglobalstorage(\tenv, \name, \keyword, \declaredt) \typearrow \tenvone \OrTypeError\\\\ +\commonprefixline\\\\ +\keyword = \GDKConstant\\ +\initialvaluep \eqname \langle \ve \rangle\\ +\reduceconstants(\tenvone, \ve) \typearrow \vv \OrTypeError\\\\ +\tenvtwo \eqdef (G^\tenvone.\constantvalues[\name\mapsto\vv], L^\tenvone)\\ +{ +\newgsd \eqdef \left\{ + \begin{array}{rcl} + \GDkeyword &:& \keyword, \\ + \GDinitialvalue &:& \initialvalue, \\ + \GDty &:& \tyoptp, \\ + \GDname &:& \name + \end{array} +\right\} +} +}{ + \declareglobalstorage(\tenv, \gsd) \typearrow (\overname{\tenvtwo}{\newtenv}, \newgsd) +} +\end{mathpar} + +\begin{mathpar} +\inferrule[non\_constant]{ + \gsd \eqname \{ + \GDkeyword : \keyword, + \GDinitialvalue : \initialvalue, + \GDty : \tyopt, + \GDname: \name + \}\\ +\checkvarnotingenv{\tenv, \name} \typearrow \True \OrTypeError\\\\ +\annotatetypeopt(\tenv, \tyopt) \typearrow \tyoptp \OrTypeError\\\\ +{ + \begin{array}{r} +\annotateexpropt(\tenv, \initialvalue) \typearrow \\ (\initialvaluetype, \initialvaluep) \OrTypeError + \end{array} +}\\ +\annotateinittype(\tenv, \initialvaluetype, \tyoptp) \typearrow \declaredt\\ +\addglobalstorage(\tenv, \name, \keyword, \declaredt) \typearrow \tenvone \OrTypeError\\\\ +\commonprefixline\\\\ +\keyword \neq \GDKConstant\\ +{ +\newgsd \eqdef \left\{ + \begin{array}{rcl} + \GDkeyword &:& \keyword, \\ + \GDinitialvalue &:& \initialvalue, \\ + \GDty &:& \tyoptp, \\ + \GDname &:& \name + \end{array} +\right\} +} +}{ + \declareglobalstorage(\tenv, \gsd) \typearrow (\overname{\tenvone}{\newtenv}, \newgsd) +} +\end{mathpar}\lrmcomment{This relates to \identr{YSPM} and \identr{FWQM}.} +\CodeSubsection{\DeclareGlobalStorageBegin}{\DeclareGlobalStorageEnd}{../Typing.ml} + +\subsubsection{TypingRuleAddGlobalStorage \label{sec:TypingRule.AddGlobalStorage}} +\hypertarget{def-addglobalstorage}{} +The function +\[ + \addglobalstorage( + \overname{\staticenvs}{\tenv} \aslsep + \overname{\identifier}{\name} \aslsep + \overname{\GDkeyword}{\keyword} \aslsep + \overname{\ty}{\declaredt} + ) + \aslto + \overname{\staticenvs}{\newtenv} \aslsep + \cup \overname{\TTypeError}{\TypeErrorConfig} +\] +modifies the static environment $\tenv$ by adding a global storage +for the identifier $\name$ with global storage keyword $\keyword$ and type $\declaredtypes$, +resulting in the environment $\newtenv$. +\ProseOtherwiseTypeError + +\subsection{Prose} +All of the following apply: +\begin{itemize} + \item checking that $\name$ is not declared in the global environment of $\tenv$ yields $\True$\ProseOrTypeError; + \item $\newtenv$ is $\tenv$ with its $\globalstoragetypes$ component updated by binding $\name$ to + $(\declaredt, \keyword)$. +\end{itemize} + +\subsection{Formally} +\begin{mathpar} +\inferrule{ + \checkvarnotingenv{\tenv, \name} \typearrow \True \OrTypeError\\\\ + \newtenv \eqdef (G^\tenv.\globalstoragetypes[\name \mapsto (\declaredt, \keyword)], L^\tenv) +} +{ + \addglobalstorage(\tenv, \name, \keyword, \declaredt) \typearrow \newtenv +} +\end{mathpar} + +\subsubsection{TypingRule.CheckVarNotInGEnv} +\hypertarget{def-checkvarnotingenv}{} +The function +\[ + \checkvarnotingenv{\overname{\staticenvs}{\tenv} \aslsep \overname{\Strings}{\id}} + \aslto \{\True\} \cup \overname{\TTypeError}{\TypeErrorConfig} +\] +checks whether $\id$ is already declared in the global environment of $\tenv$. +If it is, the result is a type error, and otherwise the result is $\True$. + +\subsubsection{Prose} +All of the following apply: +\begin{itemize} + \item $\vb$ is $\True$ if and only if one of the following applies: + \begin{itemize} + \item $\id$ is declared as a global identifier in $\tenv$; + \item $\id$ is declared as a subprogram in $\tenv$; + \item $\id$ is declared as a type in $\tenv$. + \end{itemize} + + \item checking whether $\vb$ is $\False$ yields $\True$ or a type error indicating + that $\id$ has already been declared, thereby short-circuiting the rule. +\end{itemize} + +\subsubsection{Formally} +\begin{mathpar} +\inferrule{ +{ + \begin{array}{rl} + \vb \eqdef & G^\tenv.\globalstoragetypes(\id) \neq \bot \lor\\ + & G^\tenv.\subprograms(\id) \neq \bot\ \lor\\ + & G^\tenv.\declaredtypes(\id) \neq \bot + \end{array} +}\\ +\checktrans{\neg\vb}{IdentifierAlreadyDeclared} \checktransarrow \True \OrTypeError +}{ + \checkvarnotingenv{\tenv, \id} \typearrow \True +} +\end{mathpar} + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +\section{Semantics\label{sec:GlobalStorageDeclarationsSemantics}} +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +We now define the following relations: +\begin{itemize} + \item SemanticsRule.DeclareGlobal \secref{SemanticsRule.DeclareGlobal}; + \item SemanticsRule.BaseValue \secref{SemanticsRule.BaseValue}; +\end{itemize} + +\subsubsection{SemanticsRule.EvalGlobals \label{sec:SemanticsRule.EvalGlobals}} +The relation +\hypertarget{def-evalglobals}{} +\[ + \evalglobals(\overname{\decl^*}{\vdecls}, (\overname{\overname{\envs}{\env} \times \overname{\XGraphs}{\vgone}}{\envm})) + \;\aslrel\; \overname{(\envs \times \XGraphs)}{C} \cup \overname{\TError}{\ErrorConfig} +\] +updates the input environment and execution graph by initializing the global storage declarations, +either from their initializing expression or from the base value defined for their type as per \secref{SemanticsRule.BaseValue}. + +\subsubsection{Prose} +One of the following applies: +\begin{itemize} + \item All of the following apply (\textsc{empty}): + \begin{itemize} + \item there are no declarations of global variables; + \item the result is $\envm$. + \end{itemize} + + \item All of the following apply (\textsc{with\_initial\_value}): + \begin{itemize} + \item $\vdecls$ has $\vd$ as its head and $\vdecls'$ as its tail; + \item $d$ is the AST node for declaring a global storage element with initial value $\ve$, + name $\name$, and type $\vt$; + \item $\envm$ is the environment-execution graph pair $(\env, \vgone)$; + \item evaluating the side-effect-free expression $\ve$ in $\env$ as per \secref{SemanticsRule.ESideEffectFreeExpr} \\ + is $(\vv, \vgtwo)$\ProseOrError; + \item declaring the global $\name$ with value $\vv$ in $\env$ gives $\envtwo$; + \item evaluating the remaining global declarations $\vdecls'$ with the environment $\envtwo$ and the execution graph + that is the ordered composition of $\vgone$ and $\vgtwo$ with the $\aslpo$ label gives $C$; + \item the result of the entire evaluation is $C$. + \end{itemize} + + \item All of the following apply (\textsc{no\_initial\_value}): + \begin{itemize} + \item $\vdecls$ has $\vd$ as its head and $\vdecls'$ as its tail; + \item $d$ is the AST node for declaring a global storage element with no initial value, + name $\name$, and type $\vt$; + \item $\envm$ is the environment-execution graph pair $(\env, \vgone)$; + \item the base value of type $\vt$ in $\env$ is $(\vv, \vgtwo)$\ProseOrError; + \item declaring the global $\name$ with value $\vv$ in $\env$ gives $\envtwo$; + \item evaluating the remaining global declarations $\vdecls'$ with the environment $\envtwo$ and the execution graph + that is the ordered composition of $\vgone$ and $\vgtwo$ with the $\aslpo$ label gives $C$; + \item the result of the entire evaluation is $C$. + \end{itemize} +\end{itemize} +\subsubsection{Example} + +\subsubsection{Formally} +\begin{mathpar} +\inferrule[empty]{ +\vdecls \eqname \emptylist +}{ +\evalglobals(\vdecls, \envm) \evalarrow \envm +} +\end{mathpar} + +\begin{mathpar} +\inferrule[with\_initial\_value]{ +\vdecls \eqname [\vd] \concat \vdecls'\\ +\vd \eqname \DGlobalStorage(\{ \text{initial\_value}=\langle\ve\rangle, \text{name}:\name, \text{ty}:\vt, \ldots \})\\ +\envm \eqname (\env, \vgone)\\ +\evalexprsef{\env, \ve} \evalarrow (\vv, \vgtwo) \OrDynError\\\\ +\declareglobal(\name, \vv, \env) \evalarrow \envtwo\\ +\evalglobals(\vdecls', (\envtwo, \ordered{\vgone}{\aslpo}{ \vgtwo })) \evalarrow C +}{ +\evalglobals(\vdecls, \envm) \evalarrow C +} +\end{mathpar} + +\begin{mathpar} +\inferrule[no\_initial\_value]{ +\vdecls \eqname [\vd] \concat \vdecls'\\ +\vd \eqname \DGlobalStorage(\{ \text{initial\_value}:\None, \text{name}:\name, \text{ty}:\vt, \ldots \})\\ +\envm \eqname (\env, \vgone)\\ +\basevalue(\env, \vt) \evalarrow (\vv, \vgtwo) \OrDynError\\\\ +\declareglobal(\name, \vv, \env) \evalarrow \envtwo\\ +\evalglobals(\vdecls', (\envtwo, \ordered{\vgone}{\aslpo}{ \vgtwo })) \evalarrow C +}{ +\evalglobals(\vdecls, \envm) \evalarrow C +} +\end{mathpar} +% \CodeSubsection{\EvalGlobalsBegin}{\EvalGlobalsEnd}{../Interpreter.ml} + +\subsubsection{SemanticsRule.DeclareGlobal \label{sec:SemanticsRule.DeclareGlobal}} +\subsubsection{Prose} +The relation +\hypertarget{def-declareglobal}{} +\[ + \declareglobal(\overname{\Identifiers}{\name} \aslsep \overname{\vals}{\vv} \aslsep \overname{\envs}{\env}) \;\aslrel\; \overname{\envs}{\newenv} +\] +updates the environment $\env$ by mapping $\name$ to $\vv$ as a global storage element. + +\subsubsection{Formally} +\begin{mathpar} + \inferrule{ + \env \eqname (\tenv, (G^\denv, L^\denv))\\ + \newenv \eqdef (\tenv, (G^\denv[\name\mapsto \vv], L^\denv)) + } + { \declareglobal(\name, \vv, \env) \evalarrow \newenv } +\end{mathpar} + +\subsubsection{SemanticsRule.BaseValue \label{sec:SemanticsRule.BaseValue}} +The relation +\hypertarget{def-basevalue}{} +\[ + \basevalue(\overname{(\overname{\staticenvs}{\tenv} \times \overname{\dynamicenvs}{\denv})}{\env} \aslsep \overname{\ty}{\vt}) \;\aslrel\; + (\overname{\vals}{\vv} \times \overname{\XGraphs}{\vg}) \cup \overname{\TError}{\ErrorConfig} +\] +returns the \emph{base value} of a type. +The result is an error configuration if a dynamic error is detected. + +\hypertarget{def-tstruct}{} +\paragraph{Type Structure} To obtain the base value of a type, we first obtain its \emph{structure}, using the function +\[ + \tstruct(\overname{\staticenvs}{\tenv} \aslsep \overname{\ty}{\tty}) \aslto \overname{\ty}{\vt} \cup \overname{\TTypeError}{\TypeErrorConfig} +\] +\hypertarget{def-typeerrorconfig}{} +where $\TypeErrorConfig$ stands for a type error. + +The structure of a type is the type that can hold the same set of values, but does not itself +contain any other type names. +This is essentially done by recursively replacing type names by their definition +(see \secref{TypingRule.structure}). +% +Since we assume the specification is well-typed (\secref{MeaningfulASLSpecifications}), +$\tstruct$ returns a valid type. + +\subsubsection{Prose} +The base value of the type $\vt$ in the environment $\env$ is $\vv$, +as well as the execution graph $\vg$ that results +from evaluating any of the side-effect-free expressions appearing in $\vt$, +or an error, and one of the following applies: +\begin{itemize} + \item all of the following apply (\textsc{boolean}): + \begin{itemize} + \item the structure of $\vt$ is the Boolean type; + \item $\vv$ is the native Boolean "true" value; + \item $\vg$ is the empty graph. + \end{itemize} + + \item all of the following apply (\textsc{real}): + \begin{itemize} + \item the structure of $\vt$ is the real type; + \item $\vv$ is the native real value $0$; + \item $\vg$ is the empty graph. + \end{itemize} + + \item all of the following apply (\textsc{string}): + \begin{itemize} + \item the structure of $\vt$ is the string type; + \item $\vv$ is the \nativevalue\ for the empty string; + \item $\vg$ is the empty graph. + \end{itemize} + + \item all of the following apply (\textsc{bitvector}): + \begin{itemize} + \item the structure of $\vt$ is the bitvector with the length expression $\ve$;; + \item evaluating the side-effect-free expression $\ve$ results in the \nativevalue\ $\length$ + and execution graph $\vg$\ProseOrError; + \item $\vv$ is the bitvector of length $\length$ where all bits are $0$. + \end{itemize} + + \item all of the following apply (\textsc{enum}): + \begin{itemize} + \item the structure of $\vt$ is the enumeration type where the first identifier is $\id_1$; + \item $\vl$ is the literal associated with $\id_1$ in the static environment; + \item $\vv$ is the \nativevalue\ literal for $\vl$; + \item $\vg$ is the empty graph. + \end{itemize} + + \item all of the following apply (\textsc{unconstrained\_integer}): + \begin{itemize} + \item the structure of $\vt$ is that of the unconstrained integer; + \item $\vv$ is the \nativevalue\ integer $0$; + \item $\vg$ is the empty graph. + \end{itemize} + + \item all of the following apply (\textsc{well\_constrained\_integer}): + \begin{itemize} + \item the structure of $\vt$ is that of the well-constrained integer where the first constraint + is exact with the expression $\ve$; + \item $(\vv, \vg)$ is the result of evaluating the side-effect-free expression $\ve$. + \end{itemize} + + \item all of the following apply (\textsc{record}): + \begin{itemize} + \item the structure of $\vt$ is that of a record or an exception; + \item the base value of each field is obtained, and if any of the base values results in an error + then the entire rule short-circuits with that error; + \item $\vv$ is the \nativevalue\ record where each identifier in the record is mapped to its + respective base value; + \item $\vg$ is the parallel composition of the graphs resulting from the base value evaluation + of all the fields. + \end{itemize} + + \item all of the following apply (\textsc{tuple}): + \begin{itemize} + \item the structure of $\vt$ is that of a tuple of types; + \item the base value of each type in the tuple is obtained, and if any of the base values results in an error + then the entire rule short-circuits with that error; + \item $\vv$ is the \nativevalue\ vector consisting of the base values in the order of the corresponding types + of the tuple; + \item $\vg$ is the parallel composition of the graphs resulting from the base value evaluation + of all the tuple types. + \end{itemize} + + \item all of the following apply (\textsc{array\_length\_global\_constant}): + \begin{itemize} + \item the structure of $\vt$ is that of an array with length expression $\elength$ and element type $\vvty$; + \item $\elength$ is the value of a declared constant; + \item $\elength$ is a variable expression with the variable name $\vx$; + \item the constant value for $\vx$ in the static environment is the literal integer for $n$; + \item the base value of $\vvty$ in $\env$ is $(\velem, \vg)$\ProseOrError; + \item $\vv$ is the \nativevalue\ vector of length $n$ where each element is $\velem$; + \end{itemize} + + \item all of the following apply (\textsc{array\_length\_expression}): + \begin{itemize} + \item the structure of $\vt$ is that of an array with length expression $\elength$ and element type $\vvty$; + \item $\elength$ is not the value of a declared constant; + \item the base value of $\vvty$ in $\env$ is $(\velem, \vg)$\ProseOrError; + \item evaluating the side-effect-free expression $\elength$ in the environment $\env$ + results in $(\vlength, \vgtwo)$\ProseOrError; + \item $\vlength$ is the \nativevalue\ integer for $n$; + \item $\vv$ is the \nativevalue\ vector of length $n$ where each element is $\velem$; + \item $\vg$ is the ordered composition of $\vgone$ and $\vgtwo$ with the $\asldata$ edge. + \end{itemize} +\end{itemize} + +\subsubsection{Formally} +Evaluating the inner expressions of the type $\vt$ is done via the relation\\ +$\evalexprsef$~\ref{sec:SemanticsRule.ESideEffectFreeExpr}. +If evaluating an inner expression results in an error, there is no base value and an error configuration is returned. + +\begin{mathpar} +\inferrule[bool]{ + \tstruct(\tenv, \vt) \typearrow \TBool +}{ + \basevalue((\tenv, \denv), \vt) \evalarrow (\overname{\nvbool(\True)}{\vv}, \overname{\emptygraph}{\vg}) +} +\and +\inferrule[real]{ + \tstruct(\tenv, \vt) \typearrow \TReal +}{ + \basevalue((\tenv, \denv), \vt) \evalarrow (\overname{\nvreal(0)}{\vv}, \overname{\emptygraph}{\vg}) +} +\and +\inferrule[string]{ + \tstruct(\tenv, \vt) \typearrow \TString +}{ + \basevalue((\tenv, \denv), \vt) \evalarrow (\overname{\nvliteral{\lstring(\emptylist)}}{\vv}, \overname{\emptygraph}{\vg}) +} +\end{mathpar} + +The base value of a bitvector is a bitvector \nativevalue\ consisting of a sequence of zeros +of the length specified by the type (\ve). If the length is $0$, the bitvector consists of an +empty sequence: +\begin{mathpar} +\inferrule[bitvector]{ + \env \eqname (\tenv, \denv)\\ + \tstruct(\tenv, \vt) \typearrow \TBits(\ve, \Ignore)\\ + \evalexprsef{\env, \ve} \evalarrow (\nvint(\length), \vg) \OrDynError +}{ + \basevalue(\env, \vt) \evalarrow (\overname{\nvbitvector(\overbrace{0\ldots 0}^{\length})}{\vv}, \vg) +} +\end{mathpar} + +\hypertarget{def-constantvalues}{} +The base value of an enumeration is obtained from its first declared literal. +Accessing this literal is done via the \constantvalues map in the +global component of the static environment: +\begin{mathpar} +\inferrule[enum]{ + \tstruct(\vt) \typearrow \TEnum(\id_{1..k})\\ + \env \eqname (\tenv, \denv)\\ + \tenv \eqname (G^\tenv, L^\tenv)\\ + G^\tenv.\constantvalues(\id_1) \eqname \vl +}{ + \basevalue(\env, \vt) \evalarrow (\overname{\nvliteral{\vl}}{\vv}, \overname{\emptygraph}{\vg}) +} +\end{mathpar} + +\begin{mathpar} +\inferrule[integer\_unconstrained]{ + \tstruct(\tenv, \vt) \typearrow \TInt(\unconstrained) +}{ + \basevalue((\tenv, \denv), \vt) \evalarrow (\overname{\nvint(0)}{\vv}, \overname{\emptygraph}{\vg}) +} +\and +\inferrule[integer\_constraint\_exact]{ + \env \eqname (\tenv, \denv)\\ + \tstruct(\tenv, \vt) \typearrow \TInt(\wellconstrained([\constraintexact(\ve)] \concat \Ignore))\\ + \evalexprsef{\env, \ve} \evalarrow C +}{ + \basevalue(\env, \vt) \evalarrow C +} +\and +\and +\inferrule[integer\_constraint\_range]{ + \env \eqname (\tenv, \denv)\\ + \tstruct(\tenv, \vt) \typearrow \TInt(\wellconstrained([\constraintrange(\ve, \Ignore)] \concat \Ignore))\\ + \evalexprsef{\env, \ve} \evalarrow C +}{ + \basevalue(\env, \vt) \evalarrow C +} +\end{mathpar} + +\begin{mathpar} +\inferrule[record]{ + \env \eqname (\tenv, \denv)\\ + \tstruct(\tenv, \vt) \typearrow L([i=1..k: (\id_i, \vt_i)])\\ + L \in \{\TRecord, \TException\}\\ + i=1..k: \basevalue(\env, \vt_i) \evalarrow (\vv_i, \vg_i) \OrDynError +}{ + \basevalue(\env, \vt) \evalarrow + (\overname{\nvrecord{\{i=1..k: \id_i\mapsto \vv_i\}}}{\vv}, \overname{\vg_1 \parallelcomp \ldots \parallelcomp \vg_k}{\vg}) +} +\end{mathpar} + +\begin{mathpar} +\inferrule[tuple]{ + \env \eqname (\tenv, \denv)\\ + \tstruct(\tenv, \vt) \typearrow \TTuple([i=1..k: \vt_i])\\ + i=1..k: \basevalue(\env, \vt_i) \evalarrow (\vv_i, \vg_i) \OrDynError +}{ + \basevalue(\env, \vt) \evalarrow (\overname{\nvvector{\vv_{1..k}}}{\vv}, \overname{\vg_1 \parallelcomp \ldots \parallelcomp \vg_k}{\vg}) +} +\end{mathpar} + +\newcommand\isconstant[0]{\hyperlink{def-isconstant}{\texttt{is\_contant}}} +\hypertarget{def-isconstant}{} +The predicate $\isconstant$ checks whether the expression $\ve$ is a variable +declared as a constant. +\begin{mathpar} +\inferrule[NotEVar]{ + \env \eqname (\tenv, \denv)\\ + \tenv \eqname (G^\tenv, L^\tenv)\\ + \astlabel(\ve) \neq \EVar +}{ + \isconstant(\env, \ve) \rightarrow \False +} +\and +\inferrule[EVar]{ + \env \eqname (\tenv, \denv)\\ + \tenv \eqname (G^\tenv, L^\tenv)\\ + \astlabel(\ve) = \EVar\\ + \ve\eqname\EVar(\vx)\\ + \vb \eqdef G^\tenv.\constantvalues(\vx) \neq \bot +}{ + \isconstant(\env, \ve) \rightarrow \vb +} +\end{mathpar} + +\begin{mathpar} +\inferrule[array\_length\_global\_constant]{ + \env \eqname (\tenv, \denv)\\ + \tstruct(\tenv, \vt) \typearrow \TArray(\elength, \vvty)\\ + \basevalue(\env, \vvty) \evalarrow (\velem, \vg) \OrDynError\\\\ + \isconstant(\env, \elength) \rightarrow \True\\ + \elength \eqname \EVar(\vx)\\ + \env \eqname (\tenv, \denv)\\ + \tenv \eqname (G^\tenv, L^\tenv)\\ + G^\tenv.\constantvalues(\vx) \eqname \lint(n) +}{ + \basevalue(\env, \vt) \evalarrow (\overname{\nvvector{i=1..n: \velem}}{\vv}, \vg) +} +\and +\inferrule[array\_length\_expression]{ + \env \eqname (\tenv, \denv)\\ + \tstruct(\tenv, \vt) \typearrow \TArray(\elength, \vvty)\\ + \basevalue(\env, \vvty) \evalarrow (\velem, \vgone) \OrDynError\\\\ + \isconstant(\elength) \rightarrow \False\\ + \evalexprsef{\env, \elength} \evalarrow (\vlength, \vgtwo) \OrDynError\\\\ + \vlength \eqname \nvint(n) +}{ + \basevalue(\env, \vt) \evalarrow (\overname{\nvvector{i=1..n: \velem}}{\vv}, \overname{\ordered{\vgone}{\asldata}{\vgtwo}}{\vg}) +} +\end{mathpar} diff --git a/asllib/doc/LexicalStructure.tex b/asllib/doc/LexicalStructure.tex new file mode 100644 index 000000000..3935757b9 --- /dev/null +++ b/asllib/doc/LexicalStructure.tex @@ -0,0 +1,662 @@ +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +\chapter{Lexical Structure\label{chap:LexicalStructure}} +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +This chapter defines the various elements of an ASL specification text in a high-level way +and then formalizes the lexical analysis as a function that takes a text and returns +a list of \emph{tokens} or a lexical error. + +\section{ASL Specification Text} +An ASL specification is a string --- a list of ASCII characters --- consisting of a \emph{content text} +followed by an \emph{end-of-file}. +The content text is a list of +ASCII characters that have the decimal encoding of 32 through 126 (inclusive), +which includes the space character (decimal encoding 32), +as well as +carriage return (decimal encoding 13) and line feed (decimal encoding 10). +\hypertarget{def-eof}{} +The end of file character is denote by $\eof$. +The content text does not contain an end-of-file character. + +In particular, it is an error to use a tab character in ASL specification text (decimal encoding 9). + +\section{Lexical Regular Expressions} + +\hypertarget{def-regex}{} +Table~\ref{ta:LexicalRegularExpressions} defines the regular expressions $\RegExp$ used to define +\emph{lexemes} --- substrings of the ASL specification text that are used to form \emph{tokens}. + +\begin{table} +\caption{Lexical Regular Expressions \label{ta:LexicalRegularExpressions}} +\begin{center} +\begin{tabular}{ll} +\hline +\textbf{RegExp} & \textbf{Matches}\\ +\hline +$\underbracket{\texttt{a\_string}}$ & Any character in \texttt{a\_string}\\ +$\square$ & The space character (decimal 32)\\ +\ascii{a} & The ASCII with decimal 'a'\\ +\ascii{a-b} & The ASCII range between decimals 'a' and 'b'\\ +(\texttt{$A$}) & $A$\\ +$A$ $B$ & $A$ followed by $B$\\ +\texttt{$A$ | $B$} & A or B\\ +\texttt{$A$ - $B$} & $A$ but not $B$\\ +$A*$ & Zero or more repetitions of A\\ +$A+$ & One or more repetitions of A\\ +%\texttt{["a\_string"]} & Any character in \texttt{a\_string}\\ +\texttt{"a\_string"} & The string \texttt{a\_string} verbatim\\ +\texttt{<}r\texttt{>} & The lexical regular expression defined for \texttt{<}r\texttt{>}\\ +\hline +\end{tabular} +\end{center} +\end{table} + +Let $\REasciichar$ stand for any ASCII character: +\hypertarget{def-reasciichar}{} +\begin{center} +\begin{tabular}{rcl} +$\REasciichar$ &$\triangleq$& \ascii{0-255} +\end{tabular} +\end{center} + +Let $\REchar$ stand for an ASCII character that may appear in the content text: +\hypertarget{def-rechar}{} +\begin{center} +\begin{tabular}{rcl} +$\REchar$ &$\triangleq$& \ascii{10} \texttt{|} \ascii{13} \texttt{|} \ascii{32-126}\\ +\end{tabular} +\end{center} + +\hypertarget{def-lang}{} +The notation $\Lang(e)$ stands for \emph{formal language} of a regular expression $e$. +That is, the set of strings that match that regular expression. + +\section{Whitespace} +Comments, newlines and space characters are treated as whitespace. + +\section{Comments} +ASL supports comments in the style of C++: +\begin{itemize} +\item Single-line comments: the text from \text{//} until the end of the line +is a comment (\ascii{10} is the line feed character \verb|\n|). +\item Multi-line comments: the text between \texttt{/*} and \texttt{*/} is a comment. +\end{itemize} +Comments do not nest and the two styles of comments do not interact with each other. + +\hypertarget{def-recomment}{} +\begin{center} +\begin{tabular}{rcl} +$\RElinecomment$ &$\triangleq$& \texttt{"//"} (\REchar\ \texttt{-} \ascii{10})* \texttt{|} \texttt{"/*"} \REchar* \texttt{"*/"}\\ +\end{tabular} +\end{center} + +\section{Integer Literals} +Integers are written either in decimal using one or more of the characters \texttt{0-9} and underscore, or in hexadecimal +using \texttt{0x} at the start followed by the characters \texttt{0-9, a-f, A-F} and underscore. An integer literal cannot start with +an underscore. + +This is formalized by the following lexical regular expression: +\hypertarget{def-redigit}{} +\hypertarget{def-reintlit}{} +\hypertarget{def-rehexlit}{} +\begin{center} +\begin{tabular}{rcl} +$\REdigit$ &$\triangleq$& \anycharacter{\texttt{0123456789}}\\ +$\REintlit$ &$\triangleq$& \texttt{\REdigit\ (\Underscore\ | \REdigit)*}\\ +$\REhexlit$ &$\triangleq$& \texttt{"0x"} (\REdigit\ \texttt{|} \anycharacter{\texttt{abcdefABCDEF}}) (\Underscore\ \texttt{|} \REdigit\ \texttt{|} \anycharacter{\texttt{abcdefABCDEF}})* +\end{tabular} +\end{center} + +\section{Real Number Literals} +Real numbers are written in decimal and consist of one or more decimal digits, a decimal point and one +or more decimal digits. Underscores can be added between digits to aid readability + +Underscores in numbers are not significant, and their only purpose is to separate groups of digits to make constants +such as \texttt{0xefff\_fffe}, \texttt{1\_000\_000} or \texttt{3.141\_592\_654} easier to read, + +\hypertarget{def-reallit}{} +This is formalized by the following lexical regular expression: +\begin{center} +\begin{tabular}{rcl} +$\REreallit$ &$\triangleq$& \texttt{\REdigit\ (\Underscore\ | \REdigit)* '.' \REdigit\ (\Underscore\ | \REdigit)*} +\end{tabular} +\end{center} + +\section{Boolean Literals} +Boolean literals are written using \texttt{TRUE} or \texttt{FALSE}. + +\section{Bitvector Literals} +Constant bit-vectors are written using 1, 0 and spaces surrounded by single-quotes. +\hypertarget{def-rebitvectorlit}{} +\begin{center} +\begin{tabular}{rcl} +$\REbitvectorlit$ &$\triangleq$& \anycharacter{\texttt{'}} (\anycharacter{\texttt{01}\square})* \anycharacter{\texttt{'}} +\end{tabular} +\end{center} + +The spaces in a bitvector are not significant and are only used to improve readability. +For example, \texttt{'1111 1111 1111 1111'} is the same as \texttt{'1111111111111111'}. + +\section{Bitmasks} +Constant bitmasks are written using \texttt{1}, \texttt{0}, \texttt{x} and spaces surrounded by single-quotes. +The \texttt{x} represents a don’t care character. + +\hypertarget{def-rebitmasklit}{} +\begin{center} +\begin{tabular}{rcl} +$\REbitmasklit$ &$\triangleq$& \anycharacter{\texttt{'}} (\anycharacter{\texttt{01x}\square})* \anycharacter{\texttt{'}} +\end{tabular} +\end{center} + +The spaces in a constant bitmask are not significant and are only used to improve readability. + +\section{String Literals} + +String literals consist of printable characters surrounded by double quotes. +They are used to create string values, which are strings of zero or more characters, +where a character is a printable ASCII character, +tab (ASCII code \texttt{10}), +newline (ASCII code \texttt{10}), +the backslash character (ASCII code \texttt{92}), +and double-quote character (ASCII code \texttt{34}). +Unprintable characters (tabs and newlines) are not permitted in string literals, +so they are represented by treating the backslash character \textbackslash, as an escape character. +Note therefore that string literals cannot span multiple source lines. + +The escape sequences allowed in string literals appear in Table~\ref{ta:SscapeSeuqnces}. +\begin{table} +\caption{Escape Sequences in String Literals\label{ta:SscapeSeuqnces}} +\begin{center} +\begin{tabular}{ll} +\hline +\textbf{Escape sequence} & \textbf{Meaning}\\ +\hline +\verb|\n| & The newline, ASCII code \texttt{10}\\ +\verb|\t| & The tab, ASCII code \texttt{9}\\ +\verb|\\| & The backslash character, \verb|\|, ASCII code \texttt{92}\\ +\verb|\"| & The double-quote character, \texttt{"}, ASCII code \texttt{34}\\ +\hline +\end{tabular} +\end{center} +\end{table} + +\hypertarget{def-restringlit}{} +\hypertarget{def-restrchar}{} +\begin{center} +\begin{tabular}{rcl} +$\REstrchar$ &$\triangleq$& \ascii{32-126}\\ +$\REstringlit$ &$\triangleq$& \anycharacter{\texttt{"}} ( ($\REstrchar$ \texttt{-} $\underbracket{\texttt{"}\ \backslash\ }$) $|$ ($\underbracket{\backslash\ }$ $\underbracket{\texttt{" n t }\backslash\ }$) )* \anycharacter{\texttt{"}} +\end{tabular} +\end{center} + +\section{Identifiers} +Identifiers start with a letter or underscore and continue with zero or more letters, underscores or digits. +Identifiers are case sensitive. To improve readability, it is recommended to avoid the use of identifiers that differ +only by the case of some characters. + +By convention, identifiers that begin with double-underscore are reserved for use in the implementation and should +not be used in specifications. + +\hypertarget{def-reletter}{} +\hypertarget{def-reidentifier}{} +\begin{center} +\begin{tabular}{rcl} +$\REletter$ &$\triangleq$& \texttt{'a-z' $|$ 'A-Z'}\\ +$\REidentifier$ &$\triangleq$& \texttt{($\REletter$ $|$ $\underbracket{\texttt{ \_ } }$) ($\REletter$ $|$ $\underbracket{\texttt{ \_ } }$ $|$ $\REdigit$)*}\\ +\end{tabular} +\end{center} + +% An enumeration literal is also classed as a literal constant, but is syntactically an identifier. + +Tuple element selectors are classed as identifiers. That is, in cases like \texttt{(1, 2).item0}, +the selector \texttt{item0} is classed as an identifier. +\lrmcomment{This is related to \identiTSXL} + +\section{Lexical Analysis} +Lexical analysis, which is also referred to as \emph{scanning}, is defined via the function +\hypertarget{def-aslscan}{} +\[ +\aslscan : \LexSpec \times \REasciichar^* \aslto (\Token^* \cup \{\LexicalError\}) +\] +\hypertarget{def-lexicalerrorresult}{} +which takes a \emph{lexical specification} (explained soon), an ASL specification string +(where characters are simply numbers representing ASCII characters) +and returns a sequence of tokens (tokens are defined below) or a \emph{lexical error} $\LexicalError$. + +Tokens have one of two forms: +\begin{description} + \item[Value-carrying] Tokens that carry value have the form $L(v)$ where $L$ is a token label, + signifying the meaning of the token, and $v$ is a value carried by the token, + which is used to construct the respective Abstract Syntax Tree nodes. + \item[Valueless] Tokens that do not carry values have the form $L$ where $L$ is a token label. +\end{description} + +\hypertarget{def-token}{} +The set of tokens used for the lexical analysis of ASL strings is defined below. +\[ +\begin{array}{rcll} +\Token &\triangleq& \{\ \Tintlit(n) \;|\; n\in\Z\ \} & \cup\\ + & & \{\ \Treallit(q) \;|\; q\in\Q\ \} & \cup\\ + & & \{\ \Tstringlit(s) \;|\; s\in \Lang(\REstringlit) \} & \cup\\ + & & \{\ \Tstringchar(c) \;|\; c \in \Lang(\REchar) \} & \cup\\ + & & \{\ \Tstringend \} & \cup\\ + & & \{\ \Tbitvectorlit(b) \;|\; b\in\{0,1\}^*\ \} & \cup\\ + & & \{\ \Tmasklit(m) \;|\; m\in\{0,1,x\}^*\ \} & \cup\\ + & & \{\ \Tboollit(\True), \Tboollit(\False)\ \} & \cup \\ + & & \{\ \Tidentifier(\id) \;|\; \id\in \Lang(\REidentifier)\ \} & \cup \\ + & & \{\ \Tlexeme(s) \;|\; s\in\Strings\ \} & \cup \\ + & & \{\ \Twhitespace, \Teof, \Terror\ \} & +\end{array} +\] + +\hypertarget{def-tintlit}{} +\begin{itemize} + \item Tokens of the form $\Tintlit(n)$ represent integer literals; \hypertarget{def-treallit}{} + \item Tokens of the form $\Treallit(q)$ represent real literals; \hypertarget{def-tstringlit}{} + \item Tokens of the form $\Tstringlit(s)$ represent string literals; + \hypertarget{def-tstringchar}{} + \item Tokens of the form $\Tstringchar(c)$ represent a single character in a string literal; + \hypertarget{def-tstringend}{} + \item The token $\Tstringend$ represents the closing quotes of a string literal; + \hypertarget{def-tbitvectorlit}{} + \item Tokens of the form $\Tbitvectorlit(b)$ represent bitvector literals; \hypertarget{def-tmasklit} + \item Tokens of the form $\Tmasklit(m)$ represent constant bitmasks; \hypertarget{def-tboollit}{} + \item Tokens of the form $\Tboollit(b)$ represent Boolean literals; \hypertarget{def-tidentifier}{} + \hypertarget{def-tidentifier}{} + \item Tokens of the form $\Tidentifier(i)$ represent identifiers; \hypertarget{def-tlexeme}{} + \item Tokens with the label $\Tlexeme$ are ones where the value $s$ is simply the \emph{lexeme} for that token. + That is, the substring representing that token. Later we will refer to such token by simply quoting + the lexeme of the token and dropping the label, for brevity. For example, instead of $\Tlexeme(\texttt{for})$, + we will write $\Tfor$. \hypertarget{def-twhitespace}{} + \item The valueless token $\Twhitespace$ represents white spaces; \hypertarget{def-terror}{} + \item The valueless token $\Terror$ represents an illegal lexeme such as the use of a reserved keyword; + \hypertarget{def-teof}{} + \item The valueless token $\Teof$ represents $\eof$. +\end{itemize} + +\hypertarget{def-lexspec}{} +\begin{definition}[Lexical Specification] +A \emph{lexical specification} consists of a list of pairs $[(r_1,a_1),\ldots,(r_k,a_k)] \in \LexSpec$ +where each pair $(r_i,a_i)$ consists of a lexical regular expression $r_i$ +and a \emph{lexeme action} $a_i : \Strings\times\Strings \aslto \Token^*$. +\end{definition} + +The function +\[ +\remaxmatch : \overname{\RegExp}{e} \times \overname{\Strings}{s} \aslto (\overname{\Strings}{s_1} \times \overname{\Strings}{s_2}) \cup \{\bot\} +\] +returns the \emph{longest} match of a regular expression $e$ for a prefix of a string $s$. +More precisely: +$\remaxmatch(e, s) = (s_1,s_2)$ means that $s_1\in\Lang(e)$ and $s = s_1 \concat s_2$. +If no match exists, it is indicated by returning $\bot$. + +The function $\maxmatches : \overname{\LexSpec}{R} \times \overname{\Strings}{s} \aslto \overname{\LexSpec}{R'}$ +returns the sublist of $R$ consisting of pairs whose maximal matches for $s$ are equal. Importantly, the result sublist $R'$ maintains +the order of pairs in $R$. If all expressions in $R$ do not match (that is $\remaxmatch$ returns $\bot$ for all pairs in $R$), then $R'$ is the empty list. + +The function $\aslscan$ is constructively defined via the following inference rules: + +\begin{mathpar} +\inferrule[no\_match]{ + \maxmatches(R, s) = \emptylist +}{ + \aslscan(R, s) \scanarrow \LexicalError +} +\end{mathpar} + +\begin{mathpar} +\inferrule[token]{ + \maxmatches(R, s) = [(e_1,a_1),\ldots,(e_n,a_n)]\\ + \remaxmatch(s, e_1) = (s_1, s_2)\\ + a_1(s_1, s_2) \scanarrow \ts \terminateas \LexicalError +}{ + \aslscan(R, s) \scanarrow \ts +} +\end{mathpar} + +This form of scanning is referred to as ``Maximal Munch'' in Compiler Theory +and is the most common form of scanning. +See ``Compilers: Principles, Techniques, and Tools''~\cite{ASU86} for more details. + +While Maximal Munch is a useful policy for scanning of most tokens, +it does not work well for string literals and multi-line comments, which require +identifying the respective tokens via shortest match. +% +For this purpose, most lexical analyzers split the analysis into separate ``states'' --- +one for keywords, symbols, single-line comments, and identifiers, one for string literals, +and one for multi-line comments. The lexical analyzers switches between the states as +needed, and analyzing string literals involves concatenating the individual characters +of the string literal into a single token. + +Lexical analysis of ASL follows this approach by defining three specifications: +\begin{itemize} + \item $\spectoken$: For keywords, symbols, single-line comments, and identifiers; + \item $\speccomment$: For multi-line comments; + \item $\specstring$: For string literals. +\end{itemize} + +Additionally, lexical analysis of string literals carries the extra state --- +the string characters encountered along the way. + +We now define each of the lexical specifications and related lexeme actions. + +Each lexical specification is depicted by a table where the order of elements +of a specification corresponds to the order of rows in the table. + +\subsection{Scanning Regular Tokens} +To scan keywords, symbols, single-line comments, and identifiers, +we define the following lexeme actions: + +\hypertarget{def-actiondiscard}{} +\begin{itemize} +\item +The lexeme action +\[ +\actiondiscard(s_1, s_2) \triangleq \aslscan(\spectoken, s_2) +\] +discards the string $s_1$ and continues scanning $s_2$ with $\spectoken$. +This is used for whitespace. + +\item +\hypertarget{def-actiontoken}{} +The lexeme action +\[ +\begin{array}{l} +\actiontoken(f) \triangleq \lambda (s_1,s_2). \\ +\wrappedline\ +\begin{cases} + \LexicalError & \text{if }f(s_1) = \Terror \text{ or}\\ + & \aslscan(\spectoken, s_2) = \Terror\\ + [f(s_1)] \concat \aslscan(\spectoken, s_2) & \text{else} +\end{cases} +\end{array} +\] + +is parameterized by a function $f$ that converts strings into corresponding tokens. +It applies $f$ to convert $s_1$ into a token and then continues scanning $s_2$ with \\ +$\spectoken$. +If at any point a lexical error is encountered, the entire result is a lexical error. + +\item +\hypertarget{def-actionstartstring}{} +The lexeme action +\[ +\actionstartstring(s_1, s_2) \triangleq \scanstring(\emptylist, s_2) +\] +switches to scanning literal strings via $\scanstring$. + +\item The lexeme action +\hypertarget{def-actionstartcomment}{} +\[ +\actionstartcomment(s_1, s_2) \triangleq \aslscan(\speccomment, s_2) +\] +switches to scanning multi-line comments by changing the lexical specification +to $\speccomment$. + +\hypertarget{def-decimaltolit}{} +\item The function $\decimaltolit(s)$ returns $\Tintlit(n)$ where $n$ is the integer represented by $s$ +by decimal representation. +\hypertarget{def-hextolit}{} +\item The function $\hextolit(s)$ returns $\Tintlit(n)$ where $n$ is the integer represented by $s$ +by hexadecimal representation. +\hypertarget{def-realtolit}{} +\item The function $\realtolit(s)$ returns $\Treallit(q)$ where $q$ is the real value represented by $s$ +by floating point representation. +\hypertarget{def-strtolit}{} +\item The function $\strtolit(s)$ returns $\Tstringlit(s')$ where $s'$ is the string value represented by $s$. +\hypertarget{def-bitstolit}{} +\item The function $\bitstolit(s)$ returns $\Tbitvectorlit(b)$ where $b$ is the sequence of bits +given by $s$. +\hypertarget{def-masktolit}{} +\item The function $\masktolit(s)$ returns $\Tmasklit(m)$ where $m$ is the bitmask given by $s$. +\hypertarget{def-falsetolit}{} +\item The function $\falsetolit(s)$ returns $\Tboollit(\False)$ ($s$ is ensured to be \texttt{FALSE}). +\hypertarget{def-truetolit}{} +\item The function $\truetolit(s)$ returns $\Tboollit(\True)$ ($s$ is ensured to be \texttt{TRUE}). +\hypertarget{def-tokenid}{} +\item The function $\tokenid(s)$ returns $\Tlexeme(s)$. +\hypertarget{def-lexicalerror}{} +\item The function $\lexicalerror$ returns $\Terror$. +\hypertarget{def-toidentifier}{} +\item The function $\toidentifier(s)$ returns $\Tidentifier(s)$. +\hypertarget{def-eoftoken}{} +\item The lexeme action +\[ +\eoftoken(s_1, s_2) \triangleq \begin{cases} + \emptylist & s_2 = \emptylist\\ + \LexicalError & \text{else} +\end{cases} +\] +checks whether $\eof$ is not followed by more characters and returns a lexical error otherwise. +\end{itemize} + +\hypertarget{def-spectoken}{} +The lexical specification $\spectoken$ is given by the following four tables. +Splitting the lexical specification into four tables is done for presentation purposes --- +the ordering between the entries is induced by the order between the tables +and the order of entries in each table. +% +When several regular expressions are listed in a row, it means that they are all associated with the same +token function. + +\begin{center} +\begin{tabular}{ll} +\textbf{Lexical Regular Expressions} & \textbf{Lexeme Action}\\ +\hline +(\ascii{10} $|$ \ascii{13} $|$ \ascii{32})+ & $\discard$ \\ +$\texttt{"/*"}$ & $\actionstartcomment$ \\ +$\underbracket{\texttt{"}}$ & $\actionstartstring$ \\ +$\REintlit$ & $\actiontoken(\decimaltolit)$ \\ +$\REhexlit$ & $\actiontoken(\hextolit)$ \\ +$\REreallit$ & $\actiontoken(\realtolit)$ \\ +$\REstringlit$ & $\actiontoken(\strtolit)$ \\ +$\REbitvectorlit$ & $\actiontoken(\bitstolit)$ \\ +$\REbitmasklit$ & $\actiontoken(\masktolit)$ \\ +\texttt{'!'}, \texttt{','}, \texttt{'<'}, \texttt{">>"}, \texttt{"\&\&"}, \texttt{"-->"}, \texttt{"<<"} & $\actiontoken(\tokenid)$ \\ +\texttt{']'}, \texttt{')'}, \texttt{".."}, \texttt{'='}, \texttt{'\{'}, \texttt{"!="}, \texttt{'-'}, \texttt{"<->"} & $\actiontoken(\tokenid)$ \\ +\texttt{'['}, \texttt{'('}, \texttt{'.'}, \texttt{"<="}, \texttt{'\textasciicircum'}, \texttt{'*'}, \texttt{'/'} & $\actiontoken(\tokenid)$ \\ +\texttt{"=="}, \texttt{"||"}, \texttt{'+'}, \texttt{':'}, \texttt{"=>"}, & $\actiontoken(\tokenid)$ \\ +\texttt{'\}'}, \texttt{"++"}, \texttt{'>'}, \texttt{"+:"}, \texttt{"*:"}, \texttt{';'}, \texttt{">="} & $\actiontoken(\tokenid)$ \\ +\texttt{"@looplimit"} & $\actiontoken(\tokenid)$ \\ +\hline +\end{tabular} +\end{center} + +\begin{center} +\begin{tabular}{ll} +\textbf{Lexical Regular Expressions} & \textbf{Lexeme Action}\\ +\hline +\texttt{"AND"}, \texttt{"array"}, \texttt{"as"}, \texttt{"assert"}, & $\actiontoken(\tokenid)$ \\ +\texttt{"begin"}, \texttt{"bit"}, \texttt{"bits"}, \texttt{"boolean"} & $\actiontoken(\tokenid)$ \\ +\texttt{"case"}, \texttt{"catch"}, \texttt{"config"}, \texttt{"constant"} & $\actiontoken(\tokenid)$ \\ +\texttt{"DIV"}, \texttt{"DIVRM"}, \texttt{"do"},\texttt{"downto"} & $\actiontoken(\tokenid)$ \\ +\texttt{"else"}, \texttt{"elsif"}, \texttt{"end"}, \texttt{"enumeration"} & $\actiontoken(\tokenid)$ \\ +\texttt{"XOR"} & $\actiontoken(\tokenid)$ \\ +\texttt{"exception"} & $\actiontoken(\tokenid)$ \\ +\texttt{"FALSE"} & $\actiontoken(\falsetolit)$ \\ +\texttt{"for"}, \texttt{"func"} & $\actiontoken(\tokenid)$ \\ +\texttt{"getter"} & $\actiontoken(\tokenid)$ \\ +\texttt{"if"}, \texttt{"IN"}, \texttt{"integer"} & $\actiontoken(\tokenid)$ \\ +\texttt{"let"} & $\actiontoken(\tokenid)$ \\ +%"limit"} & LIMIT \\ +\texttt{"MOD"} & $\actiontoken(\tokenid)$ \\ +\texttt{"NOT"} & $\actiontoken(\tokenid)$ \\ +\texttt{"of"}, \texttt{"OR"}, \texttt{"otherwise"} & $\actiontoken(\tokenid)$ \\ +\texttt{"pass"}, \texttt{"pragma"}, \texttt{"print"} & $\actiontoken(\tokenid)$ \\ +\texttt{"real"}, \texttt{"record"}, \texttt{"repeat"}, \texttt{"return"} & $\actiontoken(\tokenid)$ \\ +\texttt{"setter"}, \texttt{"string"}, \texttt{"subtypes"} & $\actiontoken(\tokenid)$ \\ +\texttt{"then"}, \texttt{"throw"}, \texttt{"to"}, \texttt{"try"} & $\actiontoken(\tokenid)$ \\ +\texttt{"TRUE"} & $\actiontoken(\truetolit)$ \\ +\texttt{"type"} & $\actiontoken(\tokenid)$ \\ +\texttt{"UNKNOWN"}, \texttt{"until"} & $\actiontoken(\tokenid)$ \\ +\texttt{"var"} & $\actiontoken(\tokenid)$ \\ +\texttt{"when"}, \texttt{"where"}, \texttt{"while"}, \texttt{"with"} & $\actiontoken(\tokenid)$ \\ +\hline +\end{tabular} +\end{center} + +The following list represents keywords that are reserved for future use. +\begin{center} +\begin{tabular}{ll} +\textbf{Lexical Regular Expressions} & \textbf{Lexeme Action}\\ +\hline +\texttt{"SAMPLE"}, \texttt{"UNSTABLE"} & $\lexicalerror$ \\ +\texttt{"\_"}, \texttt{"access"}, \texttt{"advice"}, \texttt{"after"} & $\lexicalerror$ \\ +\texttt{"any"}, \texttt{"aspect"} & $\lexicalerror$ \\ +\texttt{"assume"}, \texttt{"assumes"}, \texttt{"before"} & $\lexicalerror$ \\ +\texttt{"call"}, \texttt{"cast"} & $\lexicalerror$ \\ +\texttt{"class"}, \texttt{"dict"} & $\lexicalerror$ \\ +\texttt{"endcase"}, \texttt{"endcatch"}, \texttt{"endclass"} & $\lexicalerror$ \\ +\texttt{"endevent"}, \texttt{"endfor"}, \texttt{"endfunc"}, \texttt{"endgetter"} & $\lexicalerror$ \\ +\texttt{"endif"}, \texttt{"endmodule"}, \texttt{"endnamespace"}, \texttt{"endpackage"} & $\lexicalerror$ \\ +\texttt{"endproperty"}, \texttt{"endrule"}, \texttt{"endsetter"}, \texttt{"endtemplate"} & $\lexicalerror$ \\ +\texttt{"endtry"}, \texttt{"endwhile"}, \texttt{"entry"} & $\lexicalerror$ \\ +\texttt{"event"}, \texttt{"export"}, \texttt{"expression"} & $\lexicalerror$ \\ +\texttt{"extends"}, \texttt{"extern"}, \texttt{"feature"} & $\lexicalerror$ \\ +\texttt{"get"}, \texttt{"gives"} & $\lexicalerror$ \\ +\texttt{"iff"}, \texttt{"implies"}, \texttt{"import"} & $\lexicalerror$ \\ +\texttt{"intersect"}, \texttt{"intrinsic"} & $\lexicalerror$ \\ +\texttt{"invariant"}, \texttt{"is"}, \texttt{"list"} & $\lexicalerror$ \\ +\texttt{"map"}, \texttt{"module"}, \texttt{"namespace"}, \texttt{"newevent"} & $\lexicalerror$ \\ +\texttt{"newmap"}, \texttt{"original"} & $\lexicalerror$ \\ +\texttt{"package"}, \texttt{"parallel"} & $\lexicalerror$ \\ +\texttt{"pointcut"}, \texttt{"port"}, \texttt{"private"} & $\lexicalerror$ \\ +\texttt{"profile"}, \texttt{"property"}, \texttt{"protected"}, \texttt{"public"} & $\lexicalerror$ \\ +\texttt{"replace"} & $\lexicalerror$ \\ +\texttt{"requires"}, \texttt{"rethrow"}, \texttt{"rule"} & $\lexicalerror$ \\ +\texttt{"set"}, \texttt{"shared"}, \texttt{"signal"} & $\lexicalerror$ \\ +\texttt{"statements"}, \texttt{"template"} & $\lexicalerror$ \\ +\texttt{"typeof"}, \texttt{"union"} & $\lexicalerror$ \\ +\texttt{"using"}, \texttt{"watch"} & $\lexicalerror$ \\ +\texttt{"ztype"} & $\lexicalerror$ \\ +% "pattern" +\hline +\end{tabular} +\end{center} + +\begin{center} +\begin{tabular}{ll} +\textbf{Lexical Regular Expression} & \textbf{Lexeme Action}\\ +\hline +$\REidentifier$ & $\actiontoken(\toidentifier)$ \\ +$\eof$ & $\eoftoken$ \\ +\hline +\end{tabular} +\end{center} + +\subsection{Scanning Strings} +\hypertarget{def-scanstring}{} +To scan string literals, we define the following specialized scanning function. +The function +\[ +\scanstring : \overname{\REasciichar^*}{\buff} \times \overname{\REasciichar^*}{s} \aslto (\Token^* \cup \{\LexicalError\}) +\] +scans string with the $\specstring$ specification while building the final string literal in $\buff$. +It is defined via the following rules: +\begin{mathpar} +\inferrule[no\_match]{ + \maxmatches(\specstring, s) = \emptylist +}{ + \scanstring(\buff, s) \scanarrow \LexicalError +} +\end{mathpar} + +\begin{mathpar} +\inferrule[char]{ + \maxmatches(R, s) = [(e_1,a_1),\ldots,(e_n,a_n)]\\ + \remaxmatch(s, e_1) = (s_1, s_2)\\ + a_1(s_1, s_2) = \Tstringchar(t)\\ + \scanstring(\buff \concat t, s_2) \scanarrow \tstwo \terminateas \LexicalError +}{ + \scanstring(\buff, s) \scanarrow \tstwo +} +\end{mathpar} + +\begin{mathpar} +\inferrule[end]{ + \maxmatches(R, s) = [(e_1,a_1),\ldots,(e_n,a_n)]\\ + \remaxmatch(s, e_1) = (s_1, s_2)\\ + a_1(s_1, s_2) = \Tstringend\\ + \aslscan(\spectoken, s_2) \scanarrow \tstwo \terminateas \LexicalError +}{ + \scanstring(\buff, s) \scanarrow [\Tstringlit(\buff)] \concat \tstwo +} +\end{mathpar} + +We also employ the following lexeme actions: +\begin{itemize} +\item +\hypertarget{def-stringchar}{} +The lexeme action +\[ +\stringchar(s_1, s_2) \triangleq \Tstringchar(s_1) +\] +returns $s_1$, which is always a single character, as a $\Tstringchar$ +token, which is added to the characters that make up the final string +literal. + +\item +\hypertarget{def-stringescape}{} +The lexeme action +\[ +\stringescape(s_1, s_2) \triangleq \begin{cases} + \Tstringchar(10) & s_1 = \texttt{\textbackslash\;\;n}\\ + \Tstringchar(9) & s_1 = \texttt{\textbackslash\;\;t}\\ + \Tstringchar(34) & s_1 = \texttt{\textbackslash\;\;"}\\ + \Tstringchar(92) & s_1 = \texttt{\textbackslash\;\;\textbackslash}\\ +\end{cases} +\] +returns the ASCII character for the corresponding escape string, in decimal encoding, +as a $\Tstringchar$ token, which is added to the characters that make up the final string +literal. + +\item +\hypertarget{def-stringfinish}{} +The lexeme action +\[ +\stringfinish(s_1, s_2) \triangleq \Tstringend +\] +signals that the string literal has ended, which makes $\scanstring$ +switch to scanning via $\aslscan$ and $\spectoken$. +\end{itemize} + +\hypertarget{def-specstring}{} +The lexical specification for string literals --- $\specstring$ --- is given by the following table: + +\begin{center} +\begin{tabular}{ll} +\textbf{Lexical Regular Expression} & \textbf{Lexeme Action}\\ +\hline +$\underbracket{\backslash\ }$ \anycharacter{{\color{white}\backslash}\texttt{n }} & $\stringescape$\\ +$\underbracket{\backslash\ }$ \anycharacter{{\color{white}\backslash}\texttt{t }} & $\stringescape$\\ +$\underbracket{\backslash\ }$ \anycharacter{{\color{white}\backslash}\texttt{" }} & $\stringescape$\\ +$\underbracket{\backslash\ }$ \anycharacter{\ \backslash\ } & $\stringescape$ \\ +\anycharacter{{\color{white}\backslash}\texttt{" }} & $\stringfinish$\\ +$\REchar$ & $\stringchar$\\ +\hline +\end{tabular} +\end{center} + +\subsection{Scanning Multi-line Comments} +The lexeme action +\hypertarget{def-discardcommentchar}{} +\[ +\discardcommentchar(s_1, s_2) \triangleq \aslscan(\spectoken, s_2) +\] +discards the string $s_1$ (which is always a single character) and continues scanning $s_2$ with $\speccomment$. +This is the same as $\discard$, except that $s_2$ is scanned with $\speccomment$ instead of $\spectoken$. + +\hypertarget{def-speccomment}{} +The lexical specification for multi-line comments --- $\speccomment$ --- is given by the table below. +% +Notice that here, $\actiondiscard$ below is used to discard the closing of the multi-line comment and to switch +to scanning with $\spectoken$. + +\begin{center} +\begin{tabular}{ll} +\textbf{Lexical Regular Expression} & \textbf{Lexeme Action}\\ +\hline +\texttt{"*/"} & $\actiondiscard$ \\ +$\REchar$ & $\discardcommentchar$ \\ +\hline +\end{tabular} +\end{center} \ No newline at end of file diff --git a/asllib/doc/Literals.tex b/asllib/doc/Literals.tex new file mode 100644 index 000000000..a16461a0e --- /dev/null +++ b/asllib/doc/Literals.tex @@ -0,0 +1,124 @@ +\chapter{Literals} +ASL allows specifying literal values for the following types: +integers, Booleans, real numbers, bitvectors, and strings. + +Enumeration labels are also considered literal values but are technically identifiers. + +\section{Syntax} + +\begin{flalign*} +\Nvalue \derivesinline\ & \Tintlit &\\ + |\ & \Tboollit &\\ + |\ & \Treallit &\\ + |\ & \Tbitvectorlit &\\ + |\ & \Tstringlit & +\end{flalign*} + +\section{Abstract Syntax} +\begin{flalign*} +\literal \derives\ & \lint(\overname{n}{\Z}) & \\ + |\ & \lbool(\overname{b}{\{\True, \False\}}) + & \\ + |\ & \lreal(\overname{q}{\Q}) + & \\ + |\ & \lbitvector(\overname{B}{B \in \{0, 1\}^*}) + & \\ + |\ & \lstring(\overname{S}{S \in \{C \;|\; \texttt{"$C$"}\ \in\ \Strings\}}) & +\end{flalign*} + +\subsection{ASTRule.Value \label{sec:ASTRule.Value}} +\hypertarget{build-value}{} +The function +\[ + \buildvalue(\overname{\parsenode{\Nvalue}}{\vparsednode}) \;\aslto\; \overname{\literal}{\vastnode} +\] +transforms a parse node $\vparsednode$ for $\Nvalue$ into an AST node $\vastnode$ for $\literal$. + +\begin{mathpar} +\inferrule[integer]{}{ + \buildvalue(\Nvalue(\Tintlit(\vi))) \astarrow + \overname{\lint(\vi)}{\vastnode} +} +\end{mathpar} + +\begin{mathpar} +\inferrule[boolean]{}{ + \buildvalue(\Nvalue(\Tboollit(\vb))) \astarrow + \overname{\lbool(\vb)}{\vastnode} +} +\end{mathpar} + +\begin{mathpar} +\inferrule[real]{}{ + \buildvalue(\Nvalue(\Treallit(\vr))) \astarrow + \overname{\lreal(\vr)}{\vastnode} +} +\end{mathpar} + +\begin{mathpar} +\inferrule[bitvector]{}{ + \buildvalue(\Nvalue(\Tbitvectorlit(\vb))) \astarrow + \overname{\lbitvector(\vb)}{\vastnode} +} +\end{mathpar} + +\begin{mathpar} +\inferrule[string]{}{ + \buildvalue(\Nvalue(\Tstringlit(\vs))) \astarrow + \overname{\lstring(\vs)}{\vastnode} +} +\end{mathpar} + +\section{Typing} +\subsection{TypingRule.Lit \label{sec:TypingRule.Lit}} +\hypertarget{def-annotateliteral}{} +The function +\[ + \annotateliteral{\overname{\literal}{\vl}} \aslto \overname{\ty}{\vt} +\] +annotates a literal $\vl$, resulting in a type $\vt$. + +\subsection{Prose} +The result of annotating a literal $\vl$ is $\vt$ and one of the following applies: +\begin{itemize} +\item (\texttt{int}): $\vl$ is an integer literal $\vn$ and $\vt$ is the well-constrained integer type, constraining +its set to the single value $\vn$; +\item (\texttt{bool}): $\vl$ is a Boolean literal and $\vt$ is the Boolean type; +\item (\texttt{real}): $\vl$ is a real literal and $\vt$ is the real type; +\item (\texttt{string}): $\vl$ is a string literal and $\vt$ is the string type; +\item (\texttt{bitvector}): $\vl$ is a bitvector literal of length $\vn$ and $\vt$ is the bitvector type of fixed width $\vn$. +\end{itemize} + +\CodeSubsection{\LitBegin}{\LitEnd}{../Typing.ml} + +\subsection{Formally} +\begin{mathpar} +\inferrule[int]{}{\annotateliteral{\lint(n)}\typearrow \TInt(\langle[\ConstraintExact(\ELInt{n})]\rangle)} +\end{mathpar} + +\begin{mathpar} +\inferrule[bool]{}{\annotateliteral{\lbool(\Ignore)}\typearrow \TBool} +\end{mathpar} + +\begin{mathpar} +\inferrule[real]{}{\annotateliteral{\lreal(\Ignore)}\typearrow \TReal} +\end{mathpar} + +\begin{mathpar} +\inferrule[string]{}{\annotateliteral{\lstring(\Ignore)}\typearrow \TString} +\end{mathpar} + +\begin{mathpar} +\inferrule[bitvector]{ + n \eqdef \listlen{\bits} +}{ + \annotateliteral{\lbitvector(\bits)}\typearrow \TBits(\ELInt{n}, \emptylist) +} +\end{mathpar} + +\subsection{Example} +The following example shows literals and their corresponding types in comments: +\ASLExample{\typingtests/TypingRule.Lit.asl} + +\section{Semantics} +A literal $\vl$ can be converted to the \nativevalue\ $\nvliteral{\vl}$. \ No newline at end of file diff --git a/asllib/doc/LocalStorageDeclarations.tex b/asllib/doc/LocalStorageDeclarations.tex new file mode 100644 index 000000000..35cf04882 --- /dev/null +++ b/asllib/doc/LocalStorageDeclarations.tex @@ -0,0 +1,513 @@ +\chapter{Local Storage Declarations\label{chap:LocalStorageDeclarations}} + +Local storage declarations are similar to \assignableexpressions, except that they introduce new variables or constants +into the local static environment. + +\hypertarget{def-localdeclarationkeyword}{} +\hypertarget{def-localdeclarationitem}{} +A \localdeclarationkeyword\ is one of \texttt{var}, \texttt{let}, and \texttt{constant}. +A \localdeclarationitem\ is an element derived from $\Ndeclitem$. +A \localdeclaration\ consists of a \localdeclarationitem\ and a \localdeclarationkeyword. + +We show the syntax relevant to local declarations in \secref{LocalStorageDeclarationsSyntax} and +the AST rule and rules need to build the AST for \assignableexpressions\ in \secref{LocalStorageDeclarationsAbstractSyntax}. +We then define the typing and semantics of the different kinds of local declarations: +\begin{itemize} +\item Discarding declarations (see \secref{DiscardingDeclarations}) +\item Un-annotated variable declarations (see \secref{UnAnnotatedVariableDeclarations}) +\item Type-annotated variable declarations (see \secref{TypeAnnotatedVariableDeclarations}) +\item Tuple declarations (see \secref{TupleDeclarations}) +\end{itemize} + +\hypertarget{def-annotatelocaldeclitem}{} +The function +\[ + \begin{array}{c} + \annotatelocaldeclitem{ + \overname{\ty}{\tty} \aslsep + \overname{\staticenvs}{\tenv} \aslsep + \overname{\localdeclkeyword}{\ldk} \aslsep + \overname{\localdeclitem}{\ldi} + } \aslto\\ + (\overname{\staticenvs}{\newtenv} \aslsep \overname{\localdeclitem}{\newldi}) + \cup \overname{\TTypeError}{\TypeErrorConfig} + \end{array} +\] +annotates a \localdeclarationitem\ $\ldi$ with a \localdeclarationkeyword\ $\ldk$, given a type $\tty$, +in a static environment $\tenv$ results in $(\newenv, \newldi)$ where $\newenv$ is the modified +static environment and $\newldi$ is the annotated local declaration item. +\ProseOtherwiseTypeError + +The relation +\hypertarget{def-evallocaldecl}{} +\[ + \evallocaldecl{ + \overname{\envs}{\env} \aslsep + \overname{\localdeclitem}{\ldi} \aslsep + \overname{\langle\overname{\vals}{\vv}\times\overname{\XGraphs}{\vgone}\rangle}{\minitopt} + } \;\aslrel\; + \Normal(\overname{\XGraphs}{\newg}, \overname{\envs}{\newenv}) +\] +evaluates a \localdeclarationitem\ $\ldi$ in an environment +$\env$ with an optional initialization value $\minitopt$. +That is, the right-hand side of the declaration, if it exists, +has already been evaluated, yielding $\minitopt$ (see, for example, SemanticsRule.SDeclSome in \secref{SemanticsRule.SDeclSome}). +Evaluation of the local variables $\ldi$ +in an environment $\env$ is either $\Normal(\vg, \newenv)$ +or an abnormal configuration. + +While there are three different categories of local storage elements --- +constants, mutable variables (declared via \texttt{var}), and immutable variables (declared via \texttt{let}) --- +from the perspective of the semantics of local storage elements (and local declarations statements +in \chapref{eval_stmt}), they are all treated the same way. + +\section{Syntax\label{sec:LocalStorageDeclarationsSyntax}} +Declaring a local storage element is done via the following grammar rules: +\begin{flalign*} +\Nstmt \derivesinline\ & \Nlocaldeclkeyword \parsesep \Ndeclitem \parsesep \Teq \parsesep \Nexpr \parsesep \Tsemicolon &\\ +|\ & \Tvar \parsesep \Ndeclitem \parsesep \option{\Teq \parsesep \Nexpr} \parsesep \Tsemicolon &\\ +|\ & \Tvar \parsesep \Clisttwo{\Tidentifier} \parsesep \Tcolon \parsesep \Nty \parsesep \Tsemicolon &\\ +\end{flalign*} + +\begin{flalign*} +\Nlocaldeclkeyword \derivesinline\ & \Tlet \;|\; \Tconstant&\\ +\Ndeclitem \derives\ & \Nuntypeddeclitem \parsesep \Nasty&\\ +|\ & \Nuntypeddeclitem &\\ +\Nuntypeddeclitem \derivesinline\ & \Tidentifier &\\ +|\ & \Tminus &\\ +|\ & \Plisttwo{\Ndeclitem} & +\end{flalign*} + +\section{Abstract Syntax\label{sec:LocalStorageDeclarationsAbstractSyntax}} +\begin{flalign*} +\localdeclkeyword \derives\ & \LDKVar \;|\; \LDKConstant \;|\; \LDKLet &\\ +\localdeclitem \derives\ & \LDIDiscard &\\ + |\ & \LDIVar(\identifier) & \\ + |\ & \LDITuple(\localdeclitem^*) &\\ + |\ & \LDITyped(\localdeclitem, \ty) & +\end{flalign*} + +\subsubsection{ASTRule.LocalDeclKeyword\label{sec:ASTRule.LocalDeclKeyword}} +\hypertarget{build-localdeclkeyword}{} +The function +\[ +\buildlocaldeclkeyword(\overname{\parsenode{\Nlocaldeclkeyword}}{\vparsednode}) \;\aslto\; + \overname{\localdeclkeyword}{\vastnode} +\] +transforms a parse node $\vparsednode$ into an AST node $\vastnode$. + +\begin{mathpar} +\inferrule[let]{}{ + \buildlocaldeclkeyword(\overname{\Nlocaldeclkeyword(\Tlet)}{\vparsednode}) \astarrow \overname{\LDKLet}{\vastnode} +} +\end{mathpar} + +\begin{mathpar} +\inferrule[constant]{}{ + \buildlocaldeclkeyword(\overname{\Nlocaldeclkeyword(\Tconstant)}{\vparsednode}) \astarrow \overname{\LDKConstant}{\vastnode} +} +\end{mathpar} + +\subsubsection{ASTRule.DeclItem\label{sec:ASTRule.DeclItem}} +\hypertarget{build-declitem}{} +The function +\[ + \builddeclitem(\overname{\parsenode{\Ndeclitem}}{\vparsednode}) \;\aslto\; \overname{\localdeclitem}{\vastnode} +\] +transforms a parse node $\vparsednode$ into an AST node $\vastnode$. + +\begin{mathpar} +\inferrule[typed]{}{ + { + \begin{array}{r} + \builddeclitem(\Ndeclitem(\punnode{\Nuntypeddeclitem}, \punnode{\Nasty})) \astarrow \\ + \overname{\LDITyped(\astof{\vuntypedlocaldeclitem}, \astof{\vasty})}{\vastnode} + \end{array} + } +} +\end{mathpar} + +\begin{mathpar} +\inferrule[untyped]{}{ + \builddeclitem(\Ndeclitem(\punnode{\Nuntypeddeclitem})) \astarrow + \overname{\astof{\vuntypedlocaldeclitem}}{\vastnode} +} +\end{mathpar} + +\subsubsection{ASTRule.UntypedDeclItem\label{sec:ASTRule.UntypedDeclItem}} +\hypertarget{build-untypeddeclitem}{} +The function +\[ + \builduntypeddeclitem(\overname{\parsenode{\Nuntypeddeclitem}}{\vparsednode}) \;\aslto\; \overname{\localdeclitem}{\vastnode} +\] +transforms a parse node $\vparsednode$ into an AST node $\vastnode$. + +\begin{mathpar} +\inferrule[var]{}{ + \builduntypeddeclitem(\Nuntypeddeclitem(\Tidentifier(\id))) \astarrow + \overname{\LDIVar(\id)}{\vastnode} +} +\end{mathpar} + +\begin{mathpar} +\inferrule[discard]{}{ + \builduntypeddeclitem(\Nuntypeddeclitem(\Tminus)) \astarrow + \overname{\LDIDiscard}{\vastnode} +} +\end{mathpar} + +\begin{mathpar} +\inferrule[tuple]{ + \buildclist[\builddeclitem](\vdeclitems) \astarrow \vdeclitemasts +}{ + { + \begin{array}{r} + \builduntypeddeclitem(\Nuntypeddeclitem(\namednode{\vdeclitems}{\Plisttwo{\Ndeclitem}})) \astarrow \\ + \overname{\LDITuple(\vdeclitemasts)}{\vastnode} + \end{array} + } +} +\end{mathpar} + +\section{Discarding Declarations\label{sec:DiscardingDeclarations}} +\subsection{Typing} +\subsubsection{TypingRule.LDDiscard \label{sec:TypingRule.LDDiscard}} +\subsubsection{Example} +\VerbatimInput{../tests/ASLTypingReference.t/TypingRule.LDDiscard.asl} + +\subsubsection{Prose} +All of the following apply: +\begin{itemize} + \item $\ldi$ is a local declaration which can be discarded, that is, $\LDIDiscard(\None)$; + \item $\newenv$ is $\tenv$; + \item $\newldi$ is $\ldi$. +\end{itemize} +\subsubsection{Formally} +\begin{mathpar} +\inferrule{}{ + \annotatelocaldeclitem{\tenv, \tty, \LDIDiscard(\None), \ldk} \typearrow (\tenv, \ldi) +} +\end{mathpar} +\CodeSubsection{\LDDiscardBegin}{\LDDiscardEnd}{../Typing.ml} + +\subsection{Semantics} +\subsubsection{SemanticsRule.LDDiscard \label{sec:SemanticsRule.LDDiscard}} +\subsubsection{Example} +In the specification: +\VerbatimInput{../tests/ASLSemanticsReference.t/SemanticsRule.LDDiscard.asl} +\texttt{var - : integer;} does not modify the environment. + +\subsubsection{Prose} +All of the following apply: +\begin{itemize} + \item $\ldi$ indicates that the initialization value will be discarded, + $\LDIDiscard$; + \item $\newg$ is the empty graph; + \item $\newenv$ is $\env$. +\end{itemize} +\subsubsection{Formally} +\begin{mathpar} +\inferrule{} +{ + \evallocaldecl{\env, \overname{\LDIDiscard}{\ldi}, \overname{\color{white}{\texttt{xx}\Ignore}\texttt{xx}}{\minitopt}} + \evalarrow \Normal(\overname{\emptygraph}{\newg}, \overname{\env}{\newenv}) +} +\end{mathpar} +\CodeSubsection{\EvalLDDiscardBegin}{\EvalLDDiscardEnd}{../Interpreter.ml} + +\section{Un-annotated Variable Declarations\label{sec:UnAnnotatedVariableDeclarations}} +\subsection{Typing} +\subsubsection{TypingRule.LDVar \label{sec:TypingRule.LDVar}} +\subsubsection{Example} +\VerbatimInput{../tests/ASLTypingReference.t/TypingRule.LDVar.asl} + +\subsubsection{Prose} +All of the following apply: +\begin{itemize} + \item $\ldi$ denotes a variable $\vx$, that is, $\LDIVar(\vx)$; + \item determining whether $\vx$ is not declared in $\tenv$ yields $\True$\ProseOrTypeError; + \item $\newenv$ is $\tenv$ modified so that $\vx$ is locally declared to have type $\tty$; + \item $\newldi$ is the declaration of variable $\vx$. +\end{itemize} +\subsubsection{Formally} +\begin{mathpar} +\inferrule{ + \checkvarnotinenv{\tenv, \vx} \typearrow \True \OrTypeError\\\\ + \addlocal(\tenv, \vx, \tty, \ldk) \typearrow \newtenv +}{ + \annotatelocaldeclitem{\tenv, \tty, \LDIVar(\vx), \ldk} \typearrow (\newtenv, \LDIVar(\vx)) +} +\end{mathpar} +\CodeSubsection{\LDVarBegin}{\LDVarEnd}{../Typing.ml} +\lrmcomment{This is related to \identr{YSPM}, \identd{FXST}.} + +\subsection{Semantics} +\subsubsection{SemanticsRule.LDVar \label{sec:SemanticsRule.LDVar}} + \subsubsection{Prose} + All of the following apply: + \begin{itemize} + \item $\ldi$ is a variable declaration, $\LDIVar(\vx)$; + \item $\minitopt$ is $\vm$; + \item $\vm$ is a pair consisting of the value $\vv$ and execution graph $\vgone$; + \item declaring $\vx$ in $\env$ is $(\newenv, \vgtwo)$; + \item $\newg$ is the ordered composition of $\vgone$ and $\vgtwo$ with the $\asldata$ edge. + \end{itemize} + +\subsubsection{Example} +In the specification: +\VerbatimInput{../tests/ASLSemanticsReference.t/SemanticsRule.LDVar0.asl} +\texttt{var x = 3;} binds \texttt{x} to the evaluation of \texttt{3} in $\env$. + +\subsubsection{Example} +In the specification: +\VerbatimInput{../tests/ASLSemanticsReference.t/SemanticsRule.LDVar1.asl} +\texttt{var x : integer = 3;} binds \texttt{x} to the evaluation of +\texttt{3} in $\env$, without type consideration at runtime. + +\subsubsection{Formally} +\begin{mathpar} +\inferrule{ + \vm \eqname (\vv, \vgone)\\ + \declarelocalidentifier(\env, \vx, \vv)\evalarrow(\newenv, \vgtwo)\\ + \newg \eqdef \ordered{\vgone}{\asldata}{\vgtwo} +}{ + \evallocaldecl{\env, \LDIVar(\vx), \langle \vm\rangle} \evalarrow \Normal(\newg, \newenv) +} +\end{mathpar} +\CodeSubsection{\EvalLDVarBegin}{\EvalLDVarEnd}{../Interpreter.ml} + +\section{Type-annotated Variable Declarations\label{sec:TypeAnnotatedVariableDeclarations}} +\subsection{Typing} +\subsubsection{TypingRule.LDTyped\label{sec:TypingRule.LDTyped}} +\subsubsection{Example} +\VerbatimInput{../tests/ASLTypingReference.t/TypingRule.LDTyped.asl} + +\subsubsection{Prose} +All of the following apply: +\begin{itemize} + \item $\ldi$ denotes a local declaration item $\ldip$ with local declaration keyword $\ldk$ + and a type $\vt$, that is $\LDITyped(\ldip, \vt)$; + \item annotating the type $\vt$ in $\tenv$ yields $\vtp$\ProseOrTypeError; + \item determining whether $\vtp$ can be initialized with $\tty$ in $\tenv$ yields $\True$\ProseOrTypeError; + \item annotating the local declaration item $\ldip$ with the local declaration keyword $\ldk$, given + the type $\vt$, in the environment $\tenv$, yields $(\newtenv,\newldip)$; + \item $\newldi$ is the local declaration denoting $\newldip$ and the type $\vtp$, that is, \\ + $\LDITyped(\newldip, \vtp)$. +\end{itemize} +\subsubsection{Formally} +\begin{mathpar} +\inferrule{ + \annotatetype{\tenv, \vt} \typearrow \vtp \OrTypeError\\\\ + \checkcanbeinitializedwith(\tenv, \vtp, \tty) \typearrow \True \OrTypeError\\\\ + \annotatelocaldeclitem{\tenv, \vtp, \ldip, \ldk} \typearrow (\newtenv, \newldip) \OrTypeError +}{ + \annotatelocaldeclitem{\tenv, \tty, \LDITyped(\ldip, \vt), \ldk} \typearrow \\ + (\newtenv, \LDITyped(\newldip, \vtp)) +} +\end{mathpar} +\CodeSubsection{\LDTypedBegin}{\LDTypedEnd}{../Typing.ml} + +\subsubsection{TypingRule.CheckCanBeInitializedWith \label{sec:TypingRule.CheckCanBeInitializedWith}} +\hypertarget{def-checkcanbeinitializedwith}{} +The helper function +\[ +\checkcanbeinitializedwith(\overname{\staticenvs}{\tenv} \aslsep \overname{\ty}{\vs} \aslsep \overname{\ty}{\vt}) +\typearrow \{\True\} \cup \overname{\TTypeError}{\TypeErrorConfig} +\] +checks whether an expression of type $\vs$ can be used to initialize a storage element of type $\vt$ in the static environment +$\tenv$. +If the answer if $\False$, the result is a type error. + +\subsubsection{Prose} +One of the following applies: +\begin{itemize} + \item All of the following apply (\textsc{okay}): + \begin{itemize} + \item testing whether $\vt$ \typesatisfies\ $\vs$ in $\tenv$ yields $\True$; + \item the result is $\True$. + \end{itemize} + + \item All of the following apply (\textsc{error}): + \begin{itemize} + \item testing whether $\vt$ \typesatisfies\ $\vs$ in $\tenv$ yields $\False$; + \item the result is a type error indicating that an expression of type $\vs$ cannot + be used to initialize a storage element of type $\vt$. + \end{itemize} +\end{itemize} + +\subsubsection{Formally} +\begin{mathpar} +\inferrule[okay]{ + \typesatisfies(\tenv, \vt, \vs) \typearrow \True +}{ + \checkcanbeinitializedwith(\tenv, \vs, \vt) \typearrow \True +} +\end{mathpar} + +\begin{mathpar} +\inferrule[error]{ + \typesatisfies(\tenv, \vt, \vs) \typearrow \False +}{ + \checkcanbeinitializedwith(\tenv, \vs, \vt) \typearrow \TypeErrorVal{CannotBeInitializedWith} +} +\end{mathpar} +\lrmcomment{This is related to \identr{ZCVD} and \identr{LXQZ}.} + +\subsection{Semantics} +\subsubsection{SemanticsRule.LDTyped \label{sec:SemanticsRule.LDTyped}} +\subsubsection{Example (Initialized)} +In the specification: +\VerbatimInput{../tests/ASLSemanticsReference.t/SemanticsRule.LDTyped.asl} +\texttt{var x : integer = 42;} binds \texttt{x} in $\env$ to $\nvint(42)$. + +\subsubsection{Example (Uninitialized)} +In the specification: +\VerbatimInput{../tests/ASLSemanticsReference.t/SemanticsRule.LDUninitialisedTyped.asl} +\verb|var x : integer{3..43};| binds \texttt{x} in $\env$ to the base value of \verb|integer{3..43}|, +which is $\nvint(3)$. + +\subsubsection{Prose} +One of the following applies: +\begin{itemize} + \item All of the following apply (\textsc{initialized}): + \begin{itemize} + \item $\ldi$ is a typed declaration, $\LDITyped(\ldione, \vt)$; + \item $\minitopt$ corresponds to the initializing value $\vm$; + \item the resulting configuration is obtained via the evaluation + of the local declaration $\ldione$ in $\env$ with $\minitopt$ as $\vm$, + that is, \\ $\evallocaldecl{\env, \ldi1, \langle \vm\rangle}$. + \end{itemize} + + \item All of the following apply (\textsc{uninitialized}): + \begin{itemize} + \item $\ldi$ gives a local declaration with a type, but no initial value, \\ + $\LDITyped(\ldione, \vt)$; + \item $\minitopt$ is $\None$; + \item the base value of $\vt$ is $\vm$\ProseOrError; + \item evaluating the local declaration $\ldione$ with $\vm$ + as the $\minitopt$ component yields the output configuration. + \end{itemize} +\end{itemize} +\subsubsection{Formally} +\begin{mathpar} +\inferrule[initialized]{ + \evallocaldecl{\env, \ldi1, \langle \vm\rangle} \evalarrow C +}{ + \evallocaldecl{\env, \LDITyped(\ldi1, \Ignore), \langle \vm\rangle} \evalarrow C +} +\end{mathpar} + +\begin{mathpar} +\inferrule[uninitialized]{ + \basevalue(\env, \vt) \evalarrow \vm \OrDynError\\\\ + \evallocaldecl{\env, \ldione, \langle \vm \rangle} \evalarrow C +}{ + \evallocaldecl{\env, \LDITyped(\ldione, \vt), \None} \evalarrow C +} +\end{mathpar} +\CodeSubsection{\EvalLDTypedBegin}{\EvalLDTypedEnd}{../Interpreter.ml} + +\section{Tuple Declarations\label{sec:TupleDeclarations}} +\subsection{Typing} +\subsubsection{TypingRule.LDTuple\label{sec:TypingRule.LDTuple}} +\subsubsection{Example} +\VerbatimInput{../tests/ASLTypingReference.t/TypingRule.LDTuple.asl} + +\subsubsection{Prose} +All of the following apply: +\begin{itemize} + \item $\ldi$ denotes a tuple of local declaration items $\ldi_{1..k}$, that is, $\LDITuple(\ldi_{1..k})$; + \item determining the \structure\ of $\tty$ in $\tenv$ yields $\vtp$\ProseOrTypeError; + \item determining whether $\vtp$ is a tuple type yields $\True$\ProseOrTypeError; + \item determining whether $\vtp$ the number of elements of $\vtp$ is $k$ yields $\True$\ProseOrTypeError; + \item annotating the local declaration items in $\ldis$ from right to left with their corresponding + (that is, with the same index) types $t_{1..k}$ in $\tenv$, + propagating static environments from one annotation to the next, + yields the local declaration items $\ldip_{1..k}$\ProseOrTypeError; + \item $\newtenv$ is the static environment yielded by annotating $\ldi_1$; + \item $\newldi$ is a tuple of local declaration items with $\ldip_{1..k}$, that is, \\ + $\LDITuple(\ldip_{1..k})$. +\end{itemize} +\subsubsection{Formally} +\begin{mathpar} +\inferrule{ + \tstruct(\tenv, \tty) \typearrow \vtp \OrTypeError\\\\ + \checktrans{\astlabel(\vtp) = \TTuple}{TupleTypeExpected} \checktransarrow \True \OrTypeError\\\\ + \vtp \eqname \TTuple([\vt_{1..n}])\\\\ + \checktrans{k = n}{InvalidArity} \checktransarrow \True \OrTypeError\\\\ + \newtenv_k = \tenv\\ + { + \begin{array}{r} + i=k..1: + \annotatelocaldeclitem{\newtenv_{i}, \vt_{i}, \ldi_{i}, \ldk} \typearrow \\ + (\newtenv_{i-1}, \ldip_i) \OrTypeError + \end{array} + }\\ + \newtenv = \newtenv_0 +}{ + \annotatelocaldeclitem{\tenv, \tty, \LDITuple(\ldi_{1..k}), \ldk} \typearrow \\ + (\newtenv, \LDITuple(\ldip_{1..k})) +} +\end{mathpar} +\CodeSubsection{\LDTupleBegin}{\LDTupleEnd}{../Typing.ml} + +\subsection{Semantics} +\subsubsection{SemanticsRule.LDTuple \label{sec:SemanticsRule.LDTuple}} +\subsubsection{Example} +In the specification: +\VerbatimInput{../tests/ASLSemanticsReference.t/SemanticsRule.LDTuple.asl} +\texttt{var (x,y,z) = (1,2,3);} binds \texttt{x} to the evaluation of +\texttt{1}, \texttt{y} to the evaluation of \texttt{2}, and \texttt{z} to the +evaluation of \texttt{3} in $\env$. + +\subsubsection{Prose} +All of the following apply: +\begin{itemize} + \item $\ldi$ declares a list of local variables, $\LDITuple(\ldis)$; + \item $\minitopt$ is $\vm$; + \item $\vm$ is a pair consisting of the native vector $\vv$ and execution graph $\vg$; + \item $\ldis$ is a list of local declaration items $\ldi_{1..k}$; + \item the value at each index of $\vv$ is $\vv_i$, for $i=1..k$; + \item $\liv$ is the list of pairs $(\vv_i, \vg)$, for $i=1..k$; + \item the output configuration is obtained by declare each local declaration item $\ldi_i$ + with the corresponding value ($\minitopt$ component) $(\vv_i, \vg)$. +\end{itemize} +\subsubsection{Formally} +\hypertarget{def-ldituplefolder}{} +We first define the helper semantic relation +\[ + \ldituplefolder(\overname{\envs}{\env} \aslsep \overname{\localdeclitem^*}{\ldis} \aslsep \overname{(\vals \times \XGraphs)^*}{\liv}) \;\aslrel\; + \Normal(\overname{\XGraphs}{\vg} \aslsep \overname{\envs}{\newenv}) +\] +via the following rules: +\begin{mathpar} +\inferrule{} +{ + \ldituplefolder(\env, \emptylist, \emptylist) \evalarrow \Normal(\emptygraph, \env) +} +\and +\inferrule{ + \ldis \eqname [\ldi] \concat \ldis'\\ + \liv \eqname [\vm] \concat \liv'\\ + \vm \eqname (\vv, \vgone)\\ + \evallocaldecl{\env, \ldi, \langle\vm\rangle} \evalarrow \Normal(\vgone, \envone)\\ + \ldituplefolder(\envone, \ldis', \liv') \evalarrow \Normal(\vgtwo, \newenv)\\ + \newg \eqdef \vgone \parallelcomp \vgtwo +}{ + \ldituplefolder(\env, \ldis, \liv) \evalarrow \Normal(\newg, \newenv) +} +\end{mathpar} + +We now use the helper rules to define the rule for local declaration item tuples: +\begin{mathpar} +\inferrule{ + \vm \eqname (\vv, \vg)\\ + \ldis \eqname \ldi_{1..k}\\ + i=1..k: \getindex(i, \vv) \evalarrow \vv_i\\ + \liv \eqname [i=1..k: (\vv_i, \vg)]\\ + \ldituplefolder(\env, \ldis, \liv) \evalarrow C +}{ + \evallocaldecl{\env, \LDITuple(\ldis), \langle \vm\rangle} \evalarrow C +} +\end{mathpar} +\CodeSubsection{\EvalLDTupleBegin}{\EvalLDTupleEnd}{../Interpreter.ml} \ No newline at end of file diff --git a/asllib/doc/Makefile b/asllib/doc/Makefile index 827c16fc6..087de57fb 100644 --- a/asllib/doc/Makefile +++ b/asllib/doc/Makefile @@ -22,7 +22,7 @@ control: control.tex $(CONTROLS) ASLReference.pdf: control\ ASLASTLines.tex ASLTypeSatisfactionLines.tex ASLStaticModelLines.tex ASLStaticInterpreterLines.tex\ - ASLStaticEnvLines.tex ASLASTUtilsLines.tex\ + ASLStaticEnvLines.tex ASLEnvLines.tex ASLASTUtilsLines.tex\ ASLTypingLines.tex ASLSemanticsLines.tex $(LATEX) ASLReference.tex $(BIBTEX) ASLReference @@ -51,6 +51,9 @@ ASLStaticInterpreterLines.tex: ../StaticInterpreter.ml ASLStaticEnvLines.tex: ../StaticEnv.ml $(BENTO) $< > $@ +ASLEnvLines.tex: ../env.ml + $(BENTO) $< > $@ + ASLASTUtilsLines.tex: ../ASTUtils.ml $(BENTO) $< > $@ @@ -74,7 +77,7 @@ endif clean: /bin/rm -f $(PDFS) - /bin/rm -f ASLSemanticsLines.tex ASLTypingLines.tex ASLTypeSatisfactionLines.tex ASLASTLines.tex ASLStaticModelLines.tex ASLStaticInterpreterLines.tex ASLStaticEnvLines.tex ASLASTUtilsLines.tex + /bin/rm -f *Lines.tex /bin/rm -f *.aux *.log *.fls *.log *.toc *.fdb_latexmk *~ /bin/rm -f $(CONTROLS) /bin/rm -f comment.cut diff --git a/asllib/doc/PatternMatching.tex b/asllib/doc/PatternMatching.tex new file mode 100644 index 000000000..a7aaa6fc6 --- /dev/null +++ b/asllib/doc/PatternMatching.tex @@ -0,0 +1,1017 @@ +\chapter{Pattern Matching\label{chap:PatternMatching}} +Patterns are grammatically derived from $\Npattern$ and represented as an AST by $\pattern$. + +\hypertarget{build-pattern}{} +The function +\[ + \buildpattern(\overname{\parsenode{\Npattern}}{\vparsednode}) \;\aslto\; \overname{\pattern}{\vastnode} +\] +transforms a pattern parse node $\vparsednode$ into a pattern AST node $\vastnode$. + +\hypertarget{def-annotatepattern}{} +The function +\[ + \annotatepattern( + \overname{\staticenvs}{\tenv} \aslsep + \overname{\ty}{\vt} \aslsep + \overname{\pattern}{\vp}) \aslto \overname{\pattern}{\newp} \cup \overname{\TTypeError}{\TypeErrorConfig} +\] +annotates a pattern $\vp$ in a static environment $\tenv$ given a type $\vt$, +resulting in $\newp$, which is the typed AST node for $\vp$. \ProseOtherwiseTypeError. + +The relation +\hypertarget{def-evalpattern}{} +\[ + \evalpattern{\overname{\envs}{\env} \aslsep \overname{\vals}{\vv} \aslsep \overname{\pattern}{\vp}} \;\aslrel\; + \Normal(\overname{\tbool}{\vb}, \overname{\XGraphs}{\newg}) +\] +determines whether a value $\vv$ matches the pattern $\vp$ in an environment $\env$ +resulting in either $\Normal(\vb, \newg)$ or an abnormal configuration. + +We now define the syntax, abstract syntax, typing rules, and semantics rules for the following kinds of patterns: +\begin{itemize} +\item Matching All Values (\secref{MatchingAllValues}) +\item Matching a Single Value (\secref{MatchingASingleValue}) +\item Matching a Range of Integers (\secref{MatchingARangeOfIntegers}) +\item Matching an Upper Bounded Range of Integers (\secref{MatchingAnUpperBoundedRangeOfIntegers}) +\item Matching a Lower Bounded Range of Integers (\secref{MatchingALowerBoundedRangeOfIntegers}) +\item Matching a Bitmask (\secref{MatchingABitmask}) +\item Matching a Tuple of Patterns (\secref{MatchingATupleOfPatterns}) +\item Matching Any Pattern in a Set of Patterns (\secref{MatchingAnyPatternInASetOfPatterns}) +\item Matching a Negated Pattern (\secref{MatchingANegatedPattern}) +\end{itemize} + +Finally, expressions appearing in patterns are grammatically derived from \\ +$\Nexprpattern$. +The grammar is almost identical to that of $\Nexpr$, except that pattern expressions +for matching a single values and for matching a range of values, exclude tuples +(for which the tuple expression is used). +The AST for these expressions is $\expr$ --- same as the AST for $\Nexpr$. +The builders for $\Nexprpattern$ are identical to those of $\Nexpr$. For completeness, +we list those in \secref{ASTRulesForPatternExpressions}. + +\section{Matching All Values\label{sec:MatchingAllValues}} +\subsection{Syntax} +\begin{flalign*} +\Npattern \derives\ & \Tminus & +\end{flalign*} + +\subsection{Abstract Syntax} +\begin{flalign*} +\pattern \derives\ & \PatternAll & +\end{flalign*} + +\subsubsection{ASTRule.PAll} +\begin{mathpar} +\inferrule{}{ + \buildpattern(\Npattern(\Tminus)) \astarrow + \overname{\PatternAll}{\vastnode} +} +\end{mathpar} + +\subsection{Typing} +\subsubsection{TypingRule.PAll\label{sec:TypingRule.PAll}} +\subsubsection{Prose} +All of the following apply: +\begin{itemize} + \item $\vp$ is the pattern matching everything, that is, $\PatternAll$; + \item $\newp$ is $\vp$. +\end{itemize} +\subsubsection{Formally} +\begin{mathpar} +\inferrule{} +{ + \annotatepattern(\tenv, \vt, \overname{\PatternAll}{\vp}) \typearrow \overname{\PatternAll}{\newp} +} +\end{mathpar} +\CodeSubsection{\PAllBegin}{\PAllEnd}{../Typing.ml} + +\subsection{Semantics} +\subsubsection{SemanticsRule.PAll \label{sec:SemanticsRule.PAll}} +\subsubsection{Example} +\VerbatimInput{../tests/ASLSemanticsReference.t/SemanticsRule.PAll.asl} + +\subsubsection{Prose} +All of the following apply: +\begin{itemize} + \item $\vp$ is the pattern which matches everything, $\PatternAll$, and therefore + matches $\vv$; + \item $\vb$ is the native Boolean value \True; + \item $\newg$ is the empty graph. +\end{itemize} +\subsubsection{Formally} +\begin{mathpar} +\inferrule{} +{ + \evalpattern{\env, \Ignore, \PatternAll} \evalarrow \Normal(\nvbool(\True), \emptygraph) +} +\end{mathpar} +\CodeSubsection{\EvalPAllBegin}{\EvalPAllEnd}{../Interpreter.ml} + +\section{Matching a Single Value\label{sec:MatchingASingleValue}} +\subsection{Syntax} +\begin{flalign*} +\Npattern \derives\ & \Nexprpattern & +\end{flalign*} + +\subsection{Abstract Syntax} +\begin{flalign*} +\pattern \derives\ & \PatternSingle(\expr) & +\end{flalign*} + +\subsubsection{ASTRule.PSingle} +\begin{mathpar} +\inferrule{}{ + \buildpattern(\Npattern(\punnode{\Nexprpattern})) \astarrow + \overname{\PatternSingle(\astof{\vexprpattern})}{\vastnode} +} +\end{mathpar} + +\subsection{Typing} +\subsubsection{TypingRule.PSingle\label{sec:TypingRule.PSingle}} +\subsubsection{Prose} +All of the following apply: +\begin{itemize} + \item $\vp$ is the pattern that matches the expression $\ve$, that is, $\PatternSingle(\ve)$; + \item annotating the expression $\ve$ in $\tenv$ yields $(\vte, \vep)$\ProseOrTypeError; + \item obtaining the \structure\ of $\vt$ yields $\vtstruct$\ProseOrTypeError; + \item obtaining the \structure\ of $\vte$ yields $\testruct$\ProseOrTypeError; + \item One of the following holds: + \begin{itemize} + \item All of the following apply (\textsc{t\_bool, t\_real, t\_int}): + \begin{itemize} + \item the AST label of $\vtstruct$ is one of $\TBool$, $\TReal$, or $\TInt$; + \item checking that the labels of $\vtstruct$ and $\testruct$ are equal yields $\True$\ProseOrTypeError; + \end{itemize} + + \item All of the following apply (\textsc{t\_bits}): + \begin{itemize} + \item the AST label of $\vtstruct$ is $\TBits$; + \item checking that the labels of $\vtstruct$ and $\testruct$ are equal yields $\True$\ProseOrTypeError; + \item determining whether the bitwidths of $\vtstruct$ and $\testruct$ are equal yields $\True$\ProseOrTypeError; + \end{itemize} + + \item All of the following apply (\textsc{t\_enum}): + \begin{itemize} + \item the AST label of $\vtstruct$ is $\TEnum$; + \item checking that the labels of $\vtstruct$ and $\testruct$ are equal yields $\True$\ProseOrTypeError; + \item determining whether the lists of enumeration literals of $\vtstruct$ and $\testruct$ are equal yields $\True$\ProseOrTypeError; + \end{itemize} + + \item All of the following apply (\textsc{error}): + \begin{itemize} + \item determining whether the labels of $\vtstruct$ and $\testruct$ are the same yields $\True$\ProseOrTypeError; + \item the label of $\vtstruct$ is not one of $\TBool$, $\TReal$, $\TInt$, $\TBits$, or $\TEnum$; + \item the result is a type error indicating that the types $\vt$ and $\vte$ are inappropriate for this pattern. + \end{itemize} + \end{itemize} + \item $\newp$ is the pattern that matches the expression $\vep$, that is, $\PatternSingle(\vep)$. +\end{itemize} +\subsubsection{Formally} +\begin{mathpar} +\inferrule[t\_bool, t\_real, t\_int]{ + \annotateexpr{\tenv, \ve} \typearrow (\vte, \vep) \OrTypeError\\\\ + \tstruct(\tenv, \vt) \typearrow \vtstruct \OrTypeError\\\\ + \tstruct(\tenv, \vte) \typearrow \testruct \OrTypeError\\\\ + \commonprefixline\\\\ + \astlabel(\vtstruct) \in \{\TBool, \TReal, \TInt\}\\ + \checktrans{\astlabel(\vtstruct) = \astlabel(\testruct)}{\InvalidOperandTypesForBinop} \checktransarrow \True \OrTypeError +}{ + \annotatepattern(\tenv, \vt, \overname{\PatternSingle(\ve)}{\vp}) \typearrow \overname{\PatternSingle(\vep)}{\newp} +} +\end{mathpar} + +\begin{mathpar} +\inferrule[t\_bits]{ + \annotateexpr{\tenv, \ve} \typearrow (\vte, \vep) \OrTypeError\\\\ + \tstruct(\tenv, \vt) \typearrow \vtstruct \OrTypeError\\\\ + \tstruct(\tenv, \vte) \typearrow \vtestruct \OrTypeError\\\\ + \commonprefixline\\\\ + \astlabel(\vtstruct) = \TBits\\ + \checktrans{\astlabel(\vtstruct) = \astlabel(\testruct)}{\InvalidOperandTypesForBinop} \checktransarrow \True \OrTypeError\\ + \bitwidthequal(\tenv, \vtstruct, \testruct) \typearrow \vb\\ + \checktrans{\vb}{BitvectorsDifferentWidths} \checktransarrow \True \OrTypeError +}{ + \annotatepattern(\tenv, \vt, \overname{\PatternSingle(\ve)}{\vp}) \typearrow \overname{\PatternSingle(\vep)}{\newp} +} +\end{mathpar} + +\begin{mathpar} +\inferrule[t\_enum]{ + \annotateexpr{\tenv, \ve} \typearrow (\vte, \vep) \OrTypeError\\\\ + \tstruct(\tenv, \vt) \typearrow \vtstruct \OrTypeError\\\\ + \tstruct(\tenv, \vte) \typearrow \vtestruct \OrTypeError\\\\ + \commonprefixline\\\\ + \astlabel(\vtstruct) = \TEnum\\ + \checktrans{\astlabel(\vtstruct) = \astlabel(\testruct)}{\InvalidOperandTypesForBinop} \checktransarrow \True \OrTypeError\\ + \vtstruct \eqname \TEnum(\vlione)\\ + \vtestruct \eqname \TEnum(\vlitwo)\\ + \checktrans{\vlione = \vlitwo}{EnumDifferentLabels} \checktransarrow \True \OrTypeError\\ +}{ + \annotatepattern(\tenv, \vt, \overname{\PatternSingle(\ve)}{\vp}) \typearrow \overname{\PatternSingle(\vep)}{\newp} +} +\end{mathpar} + +\begin{mathpar} +\inferrule[error]{ + \annotateexpr{\tenv, \ve} \typearrow (\vte, \vep) \OrTypeError\\\\ + \tstruct(\tenv, \vt) \typearrow \vtstruct \OrTypeError\\\\ + \tstruct(\tenv, \vte) \typearrow \testruct \OrTypeError\\\\ + \commonprefixline\\\\ + \checktrans{\astlabel(\vtstruct) = \astlabel(\testruct)}{\InvalidOperandTypesForBinop} \checktransarrow \True \OrTypeError\\ + \astlabel(\vtstruct) \not\in \{\TBool, \TReal, \TInt, \TBits, \TEnum\} +}{ + \annotatepattern(\tenv, \vt, \overname{\PatternSingle(\ve)}{\vp}) \typearrow \TypeErrorVal{TypeConflict} +} +\end{mathpar} +\CodeSubsection{\PSingleBegin}{\PSingleEnd}{../Typing.ml} + +\subsection{Semantics} +\subsubsection{SemanticsRule.PSingle \label{sec:SemanticsRule.PSingle}} +\subsubsection{Example} +\VerbatimInput{../tests/ASLSemanticsReference.t/SemanticsRule.PSingleTRUE.asl} + +\subsubsection{Example} +\VerbatimInput{../tests/ASLSemanticsReference.t/SemanticsRule.PSingleFALSE.asl} + +\subsubsection{Prose} +All of the following apply: +\begin{itemize} + \item $\vp$ is the condition corresponding to being equal to the + side-effect-free expression $\ve$, $\PatternSingle(\ve)$; + \item the side-effect-free evaluation of $\ve$ in + environment $\env$ is \\ $\Normal(\vvone, \newg)$\ProseOrError; + \item $\vb$ is the Boolean value corresponding to whether $\vv$ + is equal to $\vvone$. +\end{itemize} +\subsubsection{Formally} +\begin{mathpar} +\inferrule{ + \evalexprsef{\env, \veone} \evalarrow \Normal(\vvone, \newg) \OrDynError\\\\ + \binoprel(\EQOP, \vvone, \vvone) \evalarrow \vb +}{ + \evalpattern{\env, \vv, \PatternSingle(\ve)} \evalarrow \Normal(\vb, \newg) +} +\end{mathpar} +\CodeSubsection{\EvalPSingleBegin}{\EvalPSingleEnd}{../Interpreter.ml} + +\section{Matching a Range of Integers\label{sec:MatchingARangeOfIntegers}} +\subsection{Syntax} +\begin{flalign*} +\Npattern \derives\ & \Nexprpattern \parsesep \Tslicing \parsesep \Nexpr & +\end{flalign*} + +\subsection{Abstract Syntax} +\begin{flalign*} +\pattern \derives\ & \PatternRange(\overtext{\expr}{lower}, \overtext{\expr}{upper}) & +\end{flalign*} + +\subsubsection{ASTRule.PRange} +\begin{mathpar} +\inferrule{}{ + { + \begin{array}{r} + \buildpattern(\Npattern(\punnode{\Nexprpattern}, \Tslicing, \punnode{\Nexpr})) \astarrow\\ + \overname{\PatternRange(\astof{\vexprpattern}, \astof{\vexpr})}{\vastnode} + \end{array} + } +} +\end{mathpar} + +\subsection{Typing} +\subsubsection{TypingRule.PRange\label{sec:TypingRule.PRange}} +\subsubsection{Prose} +All of the following apply: +\begin{itemize} + \item $\vp$ is the pattern which matches anything within the range given by + expressions $\veone$ and $\vetwo$, that is, $\PatternRange(\veone, \vetwo)$; + \item annotating the expression $\veone$ in $\tenv$ yields $(\vteone, \veonep)$\ProseOrTypeError; + \item annotating the expression $\vetwo$ in $\tenv$ yields $(\vtetwo, \vetwop)$\ProseOrTypeError; + \item determining whether both $\veonep$ and $\vetwop$ are compile-time constant expressions yields $\True$\ProseOrTypeError; + \item obtaining the \structure\ for $\vt$, $\vteone$, and $\vtetwo$ yields + $\vtstruct$, $\vteonestruct$, and $\vtetwostruct$, respectively\ProseOrTypeError; + \item a check the AST labels of $\vtstruct$, $\vteonestruct$, and $\vtetwostruct$ are all the same and are either + $\TInt$ or $\TReal$ yields $\True$. Otherwise, the result is a type error, which short-circuits the entire rule. + The type error indicates that the types of + $\veone$, $\vetwo$ and the type $\vt$ must be either of integer type or of real type. + \item $\newp$ is a range pattern with bounds $\veonep$ and $\vetwop$, that is, $\PatternRange(\veonep, \vetwop)$. +\end{itemize} +\subsubsection{Formally} +\begin{mathpar} +\inferrule{ + \annotateexpr{\tenv, \veone} \typearrow (\vteone, \veonep) \OrTypeError\\\\ + \annotateexpr{\tenv, \vetwo} \typearrow (\vtetwo, \vetwop) \OrTypeError\\\\ + \tstruct(\tenv, \vt) \typearrow \vtstruct \OrTypeError\\\\ + \tstruct(\tenv, \vteone) \typearrow \vteonestruct \OrTypeError\\\\ + \tstruct(\tenv, \vtetwo) \typearrow \vtetwostruct \OrTypeError\\\\ + { + \begin{array}{rl} + \vb \eqdef& \astlabel(\vtstruct) = \astlabel(\vteonestruct) = \astlabel(\vtetwostruct)\ \land\\ + & \astlabel(\vtstruct) \in \{\TInt, \TReal\} + \end{array} + }\\ + \checktrans{\vb}{InvalidTypesForBinop} \checktransarrow \True \OrTypeError +}{ + \annotatepattern(\tenv, \vt, \overname{\PatternRange(\veone, \vetwo)}{\vp}) \typearrow \overname{\PatternRange(\veonep, \vetwop)}{\newp} +} +\end{mathpar} +\CodeSubsection{\PRangeBegin}{\PRangeEnd}{../Typing.ml} + +\subsection{Semantics} +\subsubsection{SemanticsRule.PRange \label{sec:SemanticsRule.PRange}} +\subsubsection{Example} +\VerbatimInput{../tests/ASLSemanticsReference.t/SemanticsRule.PRangeTRUE.asl} + +\subsubsection{Example} +\VerbatimInput{../tests/ASLSemanticsReference.t/SemanticsRule.PRangeFALSE.asl} + +\subsubsection{Prose} +All of the following apply: +\begin{itemize} + \item $\vp$ is the condition corresponding to being greater than or equal + to $\veone$, and lesser or equal to $\vetwo$, that is, $\PatternRange(\veone, \vetwo)$; + \item $\veone$ and $\vetwo$ are side-effect-free expressions; + \item the side-effect-free evaluation of $\veone$ in $\env$ is $\Normal(\vvone, \vgone)$\ProseOrError; + \item the side-effect-free evaluation of $\vetwo$ in $\env$ is $\Normal(\vvtwo, \vgtwo)$\ProseOrError; + \item $\vbone$ is the Boolean value corresponding to whether + $\vv$ is greater than or equal to $\vvone$; + \item $\vbtwo$ is the Boolean value corresponding to whether + $\vv$ is less than or equal to $\vvtwo$; + \item $\vb$ is the Boolean conjunction of $\vbone$ and + $\vbtwo$; + \item $\newg$ is the parallel composition of $\vgone$ and $\vgtwo$. +\end{itemize} +\subsubsection{Formally} +\begin{mathpar} +\inferrule{ + \evalexprsef{\env, \veone} \evalarrow \Normal(\vvone, \vgone) \OrDynError\\\\ + \binoprel(\GEQ, \vv, \vvone) \evalarrow \vbone\\ + \evalexprsef{\env, \veone} \evalarrow \Normal(\vvtwo, \vgtwo) \OrDynError\\\\ + \binoprel(\LEQ, \vv, \vvtwo) \evalarrow \vbtwo\\ + \binoprel(\BAND, \vbone, \vbtwo) \evalarrow \vb\\ + \newg \eqdef \vgone \parallelcomp \vgtwo +}{ + \evalpattern{\env, \vv, \PatternRange(\veone, \vetwo)} \evalarrow \Normal(\vb, \newg) +} +\end{mathpar} +\CodeSubsection{\EvalPRangeBegin}{\EvalPRangeEnd}{../Interpreter.ml} + +\section{Matching an Upper Bounded Range of Integers\label{sec:MatchingAnUpperBoundedRangeOfIntegers}} +\subsection{Syntax} +\begin{flalign*} +\Npattern \derives\ & \Tleq \parsesep \Nexpr & +\end{flalign*} + +\subsection{Abstract Syntax} +\begin{flalign*} +\pattern \derives\ & \PatternLeq(\expr) & +\end{flalign*} + +\subsubsection{ASTRule.PLeq} +\begin{mathpar} +\inferrule{}{ + \buildpattern(\Npattern(\Tleq, \punnode{\Nexpr})) \astarrow + \overname{\PatternLeq(\astof{\vexpr})}{\vastnode} +} +\end{mathpar} + +\subsection{Typing} +\subsubsection{TypingRule.PLeq\label{sec:TypingRule.PLeq}} +\subsubsection{Prose} +All of the following apply: +\begin{itemize} +\item $\vp$ is the pattern which matches anything less than or equal to an expression $\ve$, +that is, $\PatternLeq(\ve)$; +\item annotating the expression $\ve$ in $\tenv$ yields $(\vte, \vep)$\ProseOrTypeError; +\item determining whether $\vep$ is a \staticallyevaluable\ expression yields $\True$\ProseOrTypeError; +\item obtaining the \structure\ of $\vt$ in $\tenv$ yields $\vtstruct$\ProseOrTypeError; +\item obtaining the \structure\ of $\vte$ in $\tenv$ yields $\testruct$\ProseOrTypeError; +\item $\vb$ is true if and only if $\vtstruct$ and $\testruct$ are both integer types or both real types; +\item if $\vb$ is $\False$ a type error is returned (indicating that the types of $\vt$ and $\vte$ + are inappropriate for the $\LEQ$ operator), +which short-circuits the entire rule; +\item $\newp$ is the pattern which matches anything less than or equal to $\vep$. +\end{itemize} +\subsubsection{Formally} +\begin{mathpar} +\inferrule{ + \annotateexpr{\tenv, \ve} \typearrow (\vte, \vep) \OrTypeError\\\\ + \checkstaticallyevaluable(\tenv, \vep) \typearrow \True \OrTypeError\\\\ + \tstruct(\tenv, \vt) \typearrow \vtstruct \OrTypeError\\\\ + \tstruct(\tenv, \vte) \typearrow \testruct \OrTypeError\\\\ + { + \begin{array}{rl} + \vb \eqdef& \astlabel(\vtstruct) = \astlabel(\testruct)\ \land\\ + & \astlabel(\vtstruct) \in \{\TInt, \TReal\} + \end{array} + }\\ + \checktrans{\vb}{InvalidTypesForBinop} \checktransarrow \True \OrTypeError +}{ + \annotatepattern(\tenv, \vt, \overname{\PatternLeq(\ve)}{\vp}) \typearrow \overname{\PatternLeq(\vep)}{\newp} +} +\end{mathpar} +\CodeSubsection{\PLeqBegin}{\PLeqEnd}{../Typing.ml} + +\subsection{Semantics} +\subsubsection{SemanticsRule.PLeq \label{sec:SemanticsRule.PLeq}} +\subsubsection{Example} +\VerbatimInput{../tests/ASLSemanticsReference.t/SemanticsRule.PLeqTRUE.asl} + +\subsubsection{Example} +\VerbatimInput{../tests/ASLSemanticsReference.t/SemanticsRule.PLeqFALSE.asl} + +\subsubsection{Prose} +All of the following apply: +\begin{itemize} + \item $\vp$ is the condition corresponding to being less than or equal + to the side-effect-free expression $\ve$, $\PatternLeq(\ve)$; + \item the side-effect-free evaluation of $\ve$ is either + $\Normal(\vvone, \newg)$\ProseOrError; + \item $\vb$ is the Boolean value corresponding to whether $\vv$ + is less than or equal to $\vvone$. +\end{itemize} +\subsubsection{Formally} +\begin{mathpar} +\inferrule{ + \evalexprsef{\env, \ve} \evalarrow \Normal(\vvone, \newg) \OrDynError\\\\ + \binoprel(\LEQ, \vv, \vvone) \evalarrow \vb +}{ + \evalpattern{\env, \vv, \PatternLeq(\ve)} \evalarrow \Normal(\vb, \newg) +} +\end{mathpar} +\CodeSubsection{\EvalPLeqBegin}{\EvalPLeqEnd}{../Interpreter.ml} + +\section{Matching a Lower Bounded Range of Integers\label{sec:MatchingALowerBoundedRangeOfIntegers}} +\subsection{Syntax} +\begin{flalign*} +\Npattern \derives\ & \Tgeq \parsesep \Nexpr & +\end{flalign*} + +\subsection{Abstract Syntax} +\begin{flalign*} +\pattern \derives\ & \PatternGeq(\expr) & +\end{flalign*} + +\subsubsection{ASTRule.PGeq} +\begin{mathpar} +\inferrule{}{ + \buildpattern(\Npattern(\Tgeq, \punnode{\Nexpr})) \astarrow + \overname{\PatternGeq(\astof{\vexpr})}{\vastnode} +} +\end{mathpar} + +\subsection{Typing} +\subsubsection{TypingRule.PGeq\label{sec:TypingRule.PGeq}} +\subsubsection{Prose} +All of the following apply: +\begin{itemize} +\item $\vp$ is the pattern which matches anything greater than or equal to an expression $\ve$, +that is, $\PatternGeq(\ve)$; +\item annotating the expression $\ve$ in $\tenv$ yields $(\vte, \vep)$\ProseOrTypeError; +\item determining whether $\vep$ is a \staticallyevaluable\ expression yields $\True$\ProseOrTypeError; +\item obtaining the \structure\ of $\vt$ in $\tenv$ yields $\vtstruct$\ProseOrTypeError; +\item obtaining the \structure\ of $\vte$ in $\tenv$ yields $\testruct$\ProseOrTypeError; +\item $\vb$ is true if and only if $\vtstruct$ and $\testruct$ are both integer types or both real types; +\item if $\vb$ is $\False$ a type error is returned (indicating that the types of $\vt$ and $\vte$ + are inappropriate for the $\GEQ$ operator), +which short-circuits the entire rule; +\item $\newp$ is the pattern which matches anything greater than or equal to $\vep$. +\end{itemize} +\subsubsection{Formally} +\begin{mathpar} +\inferrule{ + \annotateexpr{\tenv, \ve} \typearrow (\vte, \vep) \OrTypeError\\\\ + \checkstaticallyevaluable(\tenv, \vep) \typearrow \True \OrTypeError\\\\ + \tstruct(\tenv, \vt) \typearrow \vtstruct \OrTypeError\\\\ + \tstruct(\tenv, \vte) \typearrow \testruct \OrTypeError\\\\ + { + \begin{array}{rl} + \vb \eqdef& \astlabel(\vtstruct) = \astlabel(\testruct)\ \land\\ + & \astlabel(\vtstruct) \in \{\TInt, \TReal\} + \end{array} + }\\ + \checktrans{\vb}{InvalidTypesForBinop} \checktransarrow \True \OrTypeError +}{ + \annotatepattern(\tenv, \vt, \overname{\PatternGeq(\ve)}{\vp}) \typearrow \overname{\PatternGeq(\vep)}{\newp} +} +\end{mathpar} +\CodeSubsection{\PGeqBegin}{\PGeqEnd}{../Typing.ml} + +\subsection{Semantics} +\subsubsection{SemanticsRule.PGeq \label{sec:SemanticsRule.PGeq}} +\subsubsection{Example} +\VerbatimInput{../tests/ASLSemanticsReference.t/SemanticsRule.PGeqTRUE.asl} + +\subsubsection{Example} +\VerbatimInput{../tests/ASLSemanticsReference.t/SemanticsRule.PGeqFALSE.asl} + +\subsubsection{Prose} +All of the following apply: +\begin{itemize} + \item $\vp$ is the condition corresponding to being greater than or equal + than the side-effect-free expression $\ve$, $\PatternGeq(\ve)$; + \item the side-effect-free evaluation of $\ve$ is either + $\Normal(\vvone, \newg)$\ProseOrError; + \item $\vb$ is the Boolean value corresponding to whether $\vv$ + is greater than or equal to $\vvone$. +\end{itemize} +\subsubsection{Formally} +\begin{mathpar} +\inferrule{ + \evalexprsef{\env, \ve} \evalarrow \Normal(\vvone, \newg) \OrDynError\\\\ + \binoprel(\GEQ, \vv, \vvone) \evalarrow \vb +}{ + \evalpattern{\env, \vv, \PatternGeq(\ve)} \evalarrow \Normal(\vb, \newg) +} +\end{mathpar} +\CodeSubsection{\EvalPGeqBegin}{\EvalPGeqEnd}{../Interpreter.ml} + +\section{Matching a Bitmask\label{sec:MatchingABitmask}} +\subsection{Syntax} +\begin{flalign*} +\Npattern \derives\ & \Tmasklit & +\end{flalign*} + +\subsection{Abstract Syntax} +\begin{flalign*} +\pattern \derives\ & \PatternMask(\overtext{\{0,1,x\}^*}{mask constant}) & +\end{flalign*} + +\subsubsection{ASTRule.PMask} +\begin{mathpar} +\inferrule{}{ + \buildpattern(\Npattern(\Tmasklit(\vm))) \astarrow + \overname{\PatternMask(\vm)}{\vastnode} +} +\end{mathpar} + +\subsection{Typing} +\subsubsection{TypingRule.PMask\label{sec:TypingRule.PMask}} +\subsubsection{Prose} +All of the following apply: + \begin{itemize} + \item $\vp$ is the pattern which matches a mask $\vm$, that is, $\PatternMask(\vm)$; + \item determining whether $\vt$ has the structure of a bitvector type yields $\True$\ProseOrTypeError; + \item $\vn$ is the length of mask $\vm$; + \item determining whether $\vt$ \typesatisfies\ the bitvector type of length $\vn$ \\ + (that is, $\TBits(\vn, \emptylist)$), yields $\True$\ProseOrTypeError; + \item $\newp$ is $\vp$. +\end{itemize} +\subsubsection{Formally} +\begin{mathpar} +\inferrule{ + \checkstructurelabel(\tenv, \vt, \TBits) \typearrow \True \OrTypeError\\\\ + \vn \eqdef \listlen{\vm}\\ + \checktypesat(\tenv, \vt, \TBits(\vn, \emptylist)) \typearrow \True \OrTypeError +}{ + \annotatepattern(\tenv, \vt, \overname{\PatternMask(\vm)}{\vp}) \typearrow \overname{\PatternMask(\vm)}{\newp} +} +\end{mathpar} +\CodeSubsection{\PMaskBegin}{\PMaskEnd}{../Typing.ml} +\lrmcomment{This is related to \identi{VMKF}.} + +\subsection{Semantics} +\subsubsection{SemanticsRule.PMask \label{sec:SemanticsRule.PMask}} +\subsubsection{Example} +\VerbatimInput{../tests/ASLSemanticsReference.t/SemanticsRule.PMaskTRUE.asl} + +\subsubsection{Example} +\VerbatimInput{../tests/ASLSemanticsReference.t/SemanticsRule.PMaskFALSE.asl} + +\subsubsection{Prose} +All of the following apply: +\begin{itemize} + \item $\vp$ is a mask pattern, $\PatternMask(\vm)$, + of length $n$ (with spaces removed); + \item $\vv$ is a native bitvector of bits $\vu_{1..n}$; + \item $\vb$ is the native Boolean formed from the conjunction of Boolean values for each $i$, + where the bit $\vu_i$ is checked for matching the mask character $\vm_i$; + \item $\newg$ is the empty graph. +\end{itemize} +\subsubsection{Formally} +\newcommand\maskmatch[0]{\text{mask\_match}} +The helper function $\maskmatch : \{0, 1, \vx\} \times \{0,1\} \rightarrow \Bool$, +checks whether a bit value (second operand) matches a mask value (first operand), +is defined by the following table: +\[ +\begin{array}{|c|c|c|c|} + \hline + \textbf{\maskmatch} & 0 & 1 & \vx\\ + \hline + 0 & \True & \False & \True\\ + \hline + 1 & \False & \True & \True\\ + \hline +\end{array} +\] + +\begin{mathpar} +\inferrule{ + \vm \eqname \vm_{1..n}\\ + \vv \eqname \nvbitvector(\vu_{1..n})\\ + \vb \eqdef \nvbool(\bigwedge_{i=1..n} \maskmatch(\vm_i, \vu_i)) +}{ + \evalpattern{\env, \vv, \PatternMask(\vm)} \evalarrow \Normal(\vb, \emptygraph) +} +\end{mathpar} +\CodeSubsection{\EvalPMaskBegin}{\EvalPMaskEnd}{../Interpreter.ml} + +\section{Matching a Tuple of Patterns\label{sec:MatchingATupleOfPatterns}} +\subsection{Syntax} +\begin{flalign*} +\Npattern \derives\ & \Plisttwo{\Npattern} & +\end{flalign*} + +\subsection{Abstract Syntax} +\begin{flalign*} +\pattern \derives\ & \PatternTuple(\pattern^{*}) & +\end{flalign*} + +\subsubsection{ASTRule.PTuple} +\begin{mathpar} +\inferrule{ + \buildplist[\buildpattern](\vpatterns) \astarrow \vpatternasts +}{ + \buildpattern(\Npattern(\namednode{\vpatterns}{\Plisttwo{\Npattern}})) \astarrow + \overname{\PatternTuple(\vpatternasts)}{\vastnode} +} +\end{mathpar} + +\subsection{Typing} +\subsubsection{TypingRule.PTuple\label{sec:TypingRule.PTuple}} +\subsubsection{Prose} +All of the following apply: + \begin{itemize} + \item $\vp$ is the pattern which matches a tuple $\vli$, that is, $\PatternTuple(\vli)$; + \item obtaining the \structure\ of $\vt$ yields $\vtstruct$\ProseOrTypeError; + \item determining whether $\vtstruct$ is a tuple type yields $\True$\ProseOrTypeError; + \item $\vtstruct$ is a tuple type with list of tuple $\vts$; + \item determining whether $\vts$ is a list of the same size as $\vli$ yields $\True$\ProseOrTypeError; + \item annotating each pattern in $\vli$ with the corresponding type in $\vts$ at each position $\vi$ + yields a pattern $\vlip[\vi]$\ProseOrTypeError; + \item $\newli$ is the list of annotated patterns $\vlip[\vi]$ at the same positions those of $\vli$; + \item $\newp$ is the pattern which matches the tuple $\newli$, that is, $\PatternTuple(\newli)$. + \end{itemize} +\subsubsection{Formally} +\begin{mathpar} +\inferrule{ + \tstruct(\tenv, \vt) \typearrow \vtstruct \OrTypeError\\\\ + \checktrans{\astlabel(\vtstruct) = \TTuple}{TypeConflict} \checktransarrow \True \OrTypeError\\\\ + \vtstruct \eqname \TTuple(\vts)\\ + \checktrans{\equallength(\vli, \vts)}{InvalidArity} \checktransarrow \True \OrTypeError\\\\ + \vi\in\listrange(\vli): \annotatepattern(\tenv, \vts[\vi], \vli[\vi]) \typearrow \vlip[i] \OrTypeError\\\\ + \newli \eqdef \vi\in\listrange(\vli): \vlip[\vi] +}{ + \annotatepattern(\tenv, \vt, \overname{\PatternTuple(\vli)}{\vp}) \typearrow \overname{\PatternTuple(\newli)}{\newp} +} +\end{mathpar} +\CodeSubsection{\PTupleBegin}{\PTupleEnd}{../Typing.ml} + +\subsection{Semantics} +\subsubsection{SemanticsRule.PTuple \label{sec:SemanticsRule.PTuple}} +\subsubsection{Example} +\VerbatimInput{../tests/ASLSemanticsReference.t/SemanticsRule.PTupleTRUE.asl} + +\subsubsection{Example} +\VerbatimInput{../tests/ASLSemanticsReference.t/SemanticsRule.PTupleFALSE.asl} + +\subsubsection{Prose} +All of the following apply: +\begin{itemize} + \item $\vp$ gives a list of patterns $\vps$ of length $k$, $\PatternTuple(\vps)$; + \item $\vv$ gives a tuple of values $\vvs$ of length $k$; + \item for all $1 \leq i \leq n$, $\vb_i$ is the evaluation result + of $\vp_i$ with respect to the value $\vv_i$ in + environment $\env$; + \item $\vbs$ is the list of all $\vb_i$ for $1 \leq i \leq k$; + \item $\vb$ is the conjunction of the Boolean values of $\vbs$. +\end{itemize} +\subsubsection{Formally} +\begin{mathpar} +\inferrule{ + \vps \eqname \vp_{1..k}\\ + i=1..k: \getindex(i, \vv) \evalarrow \vvs_i\\ + i=1..k: \evalpattern{\env, \vvs_i, \vp_i} \evalarrow \Normal(\nvbool(\vbs_i), \vg_i) \OrDynError\\\\ + \vres \eqdef \nvbool(\bigwedge_{i=1..k} \vbs_i)\\ + \vg \eqdef \vg_1 \parallelcomp \ldots \parallelcomp \vg_k +}{ + \evalpattern{\env, \vv, \PatternTuple(\vps)} \evalarrow \Normal(\vres, \emptygraph) +} +\end{mathpar} +\CodeSubsection{\EvalPTupleBegin}{\EvalPTupleEnd}{../Interpreter.ml} + +\section{Matching Any Pattern in a Set of Patterns\label{sec:MatchingAnyPatternInASetOfPatterns}} +\subsection{Syntax} +\begin{flalign*} +\Npattern \derives\ & \Npatternset & +\end{flalign*} + +\subsection{Abstract Syntax} +\begin{flalign*} +\pattern \derives\ & \PatternAny(\pattern^{*}) & +\end{flalign*} + +\subsubsection{ASTRule.PAny} +\tododefine{Missing a rule for PatternAny} + +\begin{mathpar} +\inferrule{}{ + \buildpattern(\Npattern(\punnode{\Npatternset})) \astarrow + \overname{\astof{\vpatternset}}{\vastnode} +} +\end{mathpar} + +\subsection{Typing} +\subsubsection{TypingRule.PAny\label{sec:TypingRule.PAny}} +\subsubsection{Prose} +All of the following apply: +\begin{itemize} +\item $\vp$ is the pattern which matches anything in a list $\vli$, that is, $\PatternAny(\vli)$; +\item annotating each pattern in $\vli$ yields the list of annotated pattern $\newli$\ProseOrTypeError; +\item $\newp$ is the pattern which matches anything in $\newli$, that is, \\ $\PatternAny(\newli)$. +\end{itemize} +\CodeSubsection{\PAnyBegin}{\PAnyEnd}{../Typing.ml} + +\subsubsection{Formally} +\begin{mathpar} +\inferrule{ + \vl\in\vli: \annotatepattern(\tenv, \vt, \vl) \typearrow \vlp \OrTypeError\\\\ + \newli \eqdef [\vl\in\vli: \vlp] +} +{ + \annotatepattern(\tenv, \vt, \overname{\PatternAny(\vli)}{\vp}) \typearrow \overname{\PatternAny(\newli)}{\newp} +} +\end{mathpar} + +\subsection{Semantics} +\subsubsection{SemanticsRule.PAny \label{sec:SemanticsRule.PAny}} +\subsubsection{Example} +\VerbatimInput{../tests/ASLSemanticsReference.t/SemanticsRule.PAnyTRUE.asl} + +\subsubsection{Example} +\VerbatimInput{../tests/ASLSemanticsReference.t/SemanticsRule.PAnyFALSE.asl} + +\subsubsection{Prose} +All of the following apply: +\begin{itemize} + \item $\vp$ is a list of patterns, $\PatternAny(\vps)$; + \item $\vps$ is $\vp_{1..k}$; + \item evaluating each pattern $\vp_i$ in $\env$ results in $\Normal(\nvbool(\vb_i), \vg_i)$\ProseOrAbnormal; + \item $\vb$ is the native Boolean which is the disjunction of $\vb_i$, for $i=1..k$; + \item $\newg$ is the parallel composition of all execution graphs $\vg_i$, for $i=1..k$. +\end{itemize} +\subsubsection{Formally} +\begin{mathpar} +\inferrule{ + \vps \eqname \vp_{1..k}\\ + i=1..k : \evalpattern{\env, \vv, \vp_i} \evalarrow \Normal(\nvbool(\vb_i), \vg_i) \OrDynError\\\\ + \vb \eqdef \nvbool(\bigvee_{i=1..k} \vb_i)\\ + \newg \eqdef \vg_1 \parallelcomp \ldots \parallelcomp \vg_k +}{ + \evalpattern{\env, \vv, \PatternAny(\vps)} \evalarrow \Normal(\vb, \newg) +} +\end{mathpar} +\CodeSubsection{\EvalPAnyBegin}{\EvalPAnyEnd}{../Interpreter.ml} + +\section{Matching a Negated Pattern\label{sec:MatchingANegatedPattern}} +\subsection{Syntax} +See \secref{PatternMatchingExpressions}. + +\subsection{Abstract Syntax} +\begin{flalign*} +\pattern \derives\ & \PatternNot(\pattern) & +\end{flalign*} + +See \nameref{sec:ASTRule.PatternSet} (\textsc{NOT} case). + +\subsection{Typing} +\subsubsection{TypingRule.PNot\label{sec:TypingRule.PNot}} +\subsubsection{Prose} +All of the following apply: +\begin{itemize} + \item $\vp$ is the pattern which matches the negation of a pattern $\vq$, that is, $\PatternNot(\vq)$; + \item annotating $\vq$ in $\tenv$ yields $\newq$\ProseOrTypeError; + \item $\newp$ is pattern which matches the negation of $\newq$, that is, $\PatternNot(\newq)$. +\end{itemize} +\subsubsection{Formally} +\begin{mathpar} +\inferrule{ + \annotatepattern(\tenv, \vq) \typearrow \newq \OrTypeError +}{ + \annotatepattern(\tenv, \vt, \overname{\PatternNot(\vq)}{\vp}) \typearrow \overname{\PatternNot(\newq)}{\newp} +} +\end{mathpar} +\CodeSubsection{\PNotBegin}{\PNotEnd}{../Typing.ml} + +\subsection{semantics} +\subsubsection{SemanticsRule.PNot \label{sec:SemanticsRule.PNot}} +\subsubsection{Example} +\VerbatimInput{../tests/ASLSemanticsReference.t/SemanticsRule.PNotTRUE.asl} + +\subsubsection{Example} +\VerbatimInput{../tests/ASLSemanticsReference.t/SemanticsRule.PNotFALSE.asl} + +\subsubsection{Prose} +All of the following apply: +\begin{itemize} + \item $\vp$ is a negation pattern, $\PatternNot(\vpone)$; + \item evaluating that pattern $\vpone$ in an environment $\env$ is \\ + $\Normal(\vbone, \newg)$\ProseOrError; + \item $\vb$ is the Boolean negation of $\vbone$. +\end{itemize} +\subsubsection{Formally} +\begin{mathpar} +\inferrule{ + \evalexprsef{\env, \vpone} \evalarrow \Normal(\vbone, \newg) \OrDynError\\\\ + \unoprel(\BNOT, \vbone) \evalarrow \vb +}{ + \evalpattern{\env, \vv, \PatternNot(\vpone)} \evalarrow \Normal(\vb, \newg) +} +\end{mathpar} +\CodeSubsection{\EvalPNotBegin}{\EvalPNotEnd}{../Interpreter.ml} + +\section{AST Rules for Pattern Expressions\label{sec:ASTRulesForPatternExpressions}} +\subsection{ASTRule.ExprPattern\label{sec:ASTRule.ExprPattern}} +\hypertarget{build-exprpattern}{} +The function +\[ + \buildexprpattern(\overname{\parsenode{\Nexprpattern}}{\vparsednode}) \;\aslto\; \overname{\expr}{\vastnode} +\] +transforms a pattern expression parse node $\vparsednode$ into a pattern AST node $\vastnode$. + +\begin{mathpar} +\inferrule[literal]{}{ + \buildexprpattern(\Nexprpattern(\punnode{\Nvalue})) \astarrow + \overname{\ELiteral(\astof{\vvalue})}{\vastnode} +} +\end{mathpar} + +\begin{mathpar} + \inferrule[var]{}{ + \buildexprpattern(\Nexprpattern(\Tidentifier(\id))) \astarrow + \overname{\EVar(\id)}{\vastnode} +} +\end{mathpar} + +\begin{mathpar} + \inferrule[binop]{}{ + { + \begin{array}{r} + \buildexprpattern(\Nexprpattern(\punnode{\Nexprpattern}, \punnode{\Nbinop}, \punnode{\Nexpr})) \astarrow\\ + \overname{\EBinop(\astof{\vexprpattern}, \astof{\vbinop}, \astof{\vexpr})}{\vastnode} + \end{array} + } +} +\end{mathpar} + +\begin{mathpar} + \inferrule[unop]{}{ + \buildexprpattern(\Nexprpattern(\punnode{\Nunop}, \punnode{\Nexpr})) \astarrow + \overname{\EUnop(\astof{\vunop}, \astof{\vexpr})}{\vastnode} +} +\end{mathpar} + +\begin{mathpar} + \inferrule[cond]{ + \buildexpr(\vcondexpr) \astarrow \astversion{\vcondexpr}\\ + \buildexpr(\vthenexpr) \astarrow \astversion{\vthenexpr} + }{ + { + \begin{array}{r} + \buildexprpattern\left(\Nexprpattern\left( + \begin{array}{l} + \Tif, \namednode{\vcondexpr}{\Nexpr}, \Tthen, \\ + \wrappedline\ \namednode{\vthenexpr}{\Nexpr}, \punnode{\Neelse} + \end{array} + \right)\right) \astarrow\\ + \overname{\ECond(\astversion{\vcondexpr}, \astversion{\vthenexpr}, \astof{\veelse})}{\vastnode} + \end{array} + } +} +\end{mathpar} + +\begin{mathpar} + \inferrule[call]{ + \buildplist[\buildexpr](\vargs) \astarrow \vexprasts + }{ + \buildexprpattern(\Nexprpattern(\Tidentifier(\id), \namednode{\vargs}{\Plist{\Nexpr}})) \astarrow + \overname{\ECall(\id, \vexprasts)}{\vastnode} +} +\end{mathpar} + +\begin{mathpar} + \inferrule[slice]{}{ + { + \begin{array}{r} + \buildexprpattern(\Nexprpattern(\punnode{\Nexprpattern}, \punnode{\Nslice})) \astarrow\\ + \overname{\ESlice(\astof{\vexprpattern}, \astof{\vslice})}{\vastnode} + \end{array} + } +} +\end{mathpar} + +\begin{mathpar} + \inferrule[get\_field]{}{ + \buildexprpattern(\Nexprpattern(\Nexprpattern, \Tdot, \Tidentifier(\id))) \astarrow + \overname{\EGetField(\astof{\vexpr}, \id)}{\vastnode} +} +\end{mathpar} + +\begin{mathpar} + \inferrule[get\_fields]{ + \buildclist[\buildidentity](\vids) \astarrow \vidasts + }{ + { + \begin{array}{r} + \buildexprpattern(\Nexprpattern(\punnode{\Nexprpattern}, \Tdot, \Tlbracket, \namednode{\vids}{\NClist{\Tidentifier}}, \Trbracket)) \astarrow\\ + \overname{\EGetFields(\astof{\vexprpattern}, \vidasts)}{\vastnode} + \end{array} + } +} +\end{mathpar} + +\begin{mathpar} + \inferrule[concat]{ + \buildclist[\buildexpr](\vexprs) \astarrow \vexprasts + }{ + \buildexprpattern(\Nexprpattern(\Tlbracket, \namednode{\vexprs}{\NClist{\Nexpr}}, \Trbracket)) \astarrow + \overname{\EConcat(\vexprasts)}{\vastnode} +} +\end{mathpar} + +\begin{mathpar} + \inferrule[atc]{}{ + { + \begin{array}{r} + \buildexprpattern(\Nexprpattern(\punnode{\Nexprpattern}, \Tas, \punnode{\Nty})) \astarrow\\ + \overname{\EATC(\astof{\vexprpattern}, \astof{\tty})}{\vastnode} + \end{array} + } +} +\end{mathpar} + +\begin{mathpar} + \inferrule[atc\_int\_constraints]{}{ + { + \begin{array}{r} + \buildexprpattern(\Nexprpattern(\punnode{\Nexprpattern}, \Tas, \punnode{\Nintconstraints})) \astarrow\\ + \overname{\EATC(\astof{\vexprpattern}, \TInt(\astof{\vintconstraints}))}{\vastnode} +\end{array} +} +} +\end{mathpar} + +\begin{mathpar} + \inferrule[pattern\_set]{}{ + { + \begin{array}{r} + \buildexprpattern(\Nexprpattern(\punnode{\Nexprpattern}, \Tin, \punnode{\Npatternset})) \astarrow\\ + \overname{\EPattern(\astof{\vexprpattern}, \astof{\vpatternset})}{\vastnode} +\end{array} +} +} +\end{mathpar} + +\begin{mathpar} + \inferrule[pattern\_mask]{}{ + { + \begin{array}{r} + \buildexprpattern(\Nexprpattern(\punnode{\Nexprpattern}, \Tin, \Tmasklit(\vm))) \astarrow\\ + \overname{\EPattern(\astof{\vexprpattern}, \PatternMask(\vm))}{\vastnode} +\end{array} +} +} +\end{mathpar} + +\begin{mathpar} + \inferrule[unknown]{}{ + \buildexprpattern(\Nexprpattern(\Tunknown, \Tcolon, \punnode{\Nty})) \astarrow + \overname{\EUnknown(\astof{\tty})}{\vastnode} +} +\end{mathpar} + +\begin{mathpar} + \inferrule[record]{ + \buildclist[\buildfieldassign](\vfieldassigns) \astarrow \vfieldassignasts + }{ + { + \begin{array}{r} + \buildexprpattern\left(\Nexprpattern\left( + \begin{array}{l} + \Tidentifier(\vt), \Tlbrace, \\ + \wrappedline\ \namednode{\vfieldassigns}{\Clist{\Nfieldassign}}, \\ + \wrappedline\ \Trbrace + \end{array} + \right)\right) \\ + \astarrow\ \overname{\ERecord(\TNamed(\vt), \vfieldassignasts)}{\vastnode} +\end{array} +} +} +\end{mathpar} + +\begin{mathpar} + \inferrule[sub\_expr]{}{ + \buildexprpattern(\Nexprpattern(\Tlpar, \punnode{\Nexprpattern}, \Trpar)) \astarrow + \overname{\astof{\vexprpattern}}{\vastnode} +} +\end{mathpar} \ No newline at end of file diff --git a/asllib/doc/PrimitiveOperations.tex b/asllib/doc/PrimitiveOperations.tex new file mode 100644 index 000000000..2c7c278a0 --- /dev/null +++ b/asllib/doc/PrimitiveOperations.tex @@ -0,0 +1,1496 @@ +\chapter{Primitive Operations\label{chap:PrimitiveOperations}} + +The term \emph{Primitive Operations} denotes the set of operations available in the expression syntax. +\lrmcomment{\identd{KXWT}} +This includes $\binop$, $\unop$ and \texttt{if..then..else} expressions. +\lrmcomment{\identi{HSQL}} +This chapter defines the Primitive Operations as functions over literals. + +ASL follows mathematical and programming language tradition of allowing operators such as \texttt{+} to be overloaded +to refer to one of several different operations. +% +\taref{BooleanOperators}, \taref{IntegerOperators}, \taref{BitvectorOperators}, \taref{RealOperators}, +\taref{StringOperators}, and \taref{EnumerationOperators} define, +for each primitive operation, the kinds of input literals and the kind of output literals, +as well as a unique name. + +\begin{table}[!h] +\caption{Boolean Operation Signatures\label{ta:BooleanOperators}} +\centering +\hypertarget{def-notbool}{} +\hypertarget{def-andbool}{} +\hypertarget{def-orbool}{} +\hypertarget{def-eqbool}{} +\hypertarget{def-nebool}{} +\hypertarget{def-impliesbool}{} +\hypertarget{def-equivbool}{} +\begin{tabular}{lllll} +\hline +\textbf{Operator} & \textbf{Operand 1} & \textbf{Operand 2} & \textbf{Result} & \textbf{Name}\\ +\hline +\Tbnot & \lbool & - & \lbool & \notbool\\ +\Tband & \lbool & \lbool & \lbool & \andbool\\ +\Tbor & \lbool & \lbool & \lbool & \orbool\\ +\Teqop & \lbool & \lbool & \lbool & \eqbool\\ +\Tneq & \lbool & \lbool & \lbool & \nebool\\ +\Timpl & \lbool & \lbool & \lbool & \impliesbool\\ +\Tbeq & \lbool & \lbool & \lbool & \equivbool\\ +\hline +\end{tabular} +\end{table} + +\begin{table}[!h] +\caption{Integer Operation Signatures\label{ta:IntegerOperators}} +\centering +\hypertarget{def-negateint}{} +\hypertarget{def-addint}{} +\hypertarget{def-subint}{} +\hypertarget{def-mulint}{} +\hypertarget{def-expint}{} +\hypertarget{def-shiftleftint}{} +\hypertarget{def-shiftrightint}{} +\hypertarget{def-divint}{} +\hypertarget{def-fdivint}{} +\hypertarget{def-fremint}{} +\hypertarget{def-eqint}{} +\hypertarget{def-neint}{} +\hypertarget{def-leint}{} +\hypertarget{def-ltint}{} +\hypertarget{def-gtint}{} +\hypertarget{def-geint}{} +\begin{tabular}{lllll} +\hline +\textbf{Operator} & \textbf{Operand 1} & \textbf{Operand 2} & \textbf{Result} & \textbf{Name}\\ +\hline +\Tminus & \lint & - & \lint & \negateint\\ +\Tplus & \lint & \lint & \lint & \addint\\ +\Tminus & \lint & \lint & \lint & \subint\\ +\Tmul & \lint & \lint & \lint & \mulint\\ +\Tpow & \lint & \lint & \lint & \expint\\ +\Tshl & \lint & \lint & \lint & \shiftleftint\\ +\Tshr & \lint & \lint & \lint & \shiftrightint\\ +\Tdiv & \lint & \lint & \lint & \divint\\ +\Tdivrm & \lint & \lint & \lint & \fdivint\\ +\Tmod & \lint & \lint & \lint & \fremint\\ +\Teqop & \lint & \lint & \lbool & \eqint\\ +\Tneq & \lint & \lint & \lbool & \neint\\ +\Tleq & \lint & \lint & \lbool & \leint\\ +\Tlt & \lint & \lint & \lbool & \ltint\\ +\Tgt & \lint & \lint & \lbool & \gtint\\ +\Tgeq & \lint & \lint & \lbool & \geint\\ +\hline +\end{tabular} +\end{table} + +\begin{table}[!h] +\caption{Real Operation Signatures\label{ta:RealOperators}} +\centering +\hypertarget{def-negatereal}{} +\hypertarget{def-addreal}{} +\hypertarget{def-subreal}{} +\hypertarget{def-mulreal}{} +\hypertarget{def-expreal}{} +\hypertarget{def-divreal}{} +\hypertarget{def-eqreal}{} +\hypertarget{def-nereal}{} +\hypertarget{def-lereal}{} +\hypertarget{def-ltreal}{} +\hypertarget{def-gtreal}{} +\hypertarget{def-gereal}{} +\begin{tabular}{lllll} +\hline +\textbf{Operator} & \textbf{Operand 1} & \textbf{Operand 2} & \textbf{Result} & \textbf{Name}\\ +\hline +\Tminus & \lreal & - & \lreal & \negatereal\\ +\Tplus & \lreal & \lreal & \lreal & \addreal\\ +\Tminus & \lreal & \lreal & \lreal & \subreal\\ +\Tmul & \lreal & \lreal & \lreal & \mulreal\\ +\Tpow & \lreal & \lint & \lreal & \expreal\\ +\Tdiv & \lreal & \lreal & \lreal & \divreal\\ +\Teqop & \lreal & \lreal & \lbool & \eqreal\\ +\Tneq & \lreal & \lreal & \lbool & \nereal\\ +\Tleq & \lreal & \lreal & \lbool & \lereal\\ +\Tlt & \lreal & \lreal & \lbool & \ltreal\\ +\Tgt & \lreal & \lreal & \lbool & \gtreal\\ +\Tgeq & \lreal & \lreal & \lbool & \gereal\\ +\hline +\end{tabular} +\end{table} + +\begin{table}[!h] +\caption{Bitvector Operation Signatures\label{ta:BitvectorOperators}} +\centering +\hypertarget{def-addbits}{} +\hypertarget{def-addbitsint}{} +\hypertarget{def-subbits}{} +\hypertarget{def-subbitsint}{} +\hypertarget{def-notbits}{} +\hypertarget{def-andbits}{} +\hypertarget{def-orbits}{} +\hypertarget{def-xorbits}{} +\hypertarget{def-eqbits}{} +\hypertarget{def-nebits}{} +\begin{tabular}{lllll} +\hline +\textbf{Operator} & \textbf{Operand 1} & \textbf{Operand 2} & \textbf{Result} & \textbf{Name}\\ +\hline +\Tplus & \lbitvector & \lbitvector & \lbitvector & \addbits\\ +\Tplus & \lbitvector & \lint & \lbitvector & \addbitsint\\ +\Tminus & \lbitvector & \lbitvector & \lbitvector & \subbits\\ +\Tminus & \lbitvector & \lint & \lbitvector & \subbitsint\\ +\Tnot & \lbitvector & - & \lbitvector & \notbits\\ +\Tand & \lbitvector & \lbitvector & \lbitvector & \andbits\\ +\Tor & \lbitvector & \lbitvector & \lbitvector & \orbits\\ +\Txor & \lbitvector & \lbitvector & \lbitvector & \xorbits\\ +\Teqop & \lbitvector & \lbitvector & \lbool & \eqbits\\ +\Tneq & \lbitvector & \lbitvector & \lbool & \nebits\\ +\hline +\end{tabular} +\end{table} + +\begin{table}[!h] +\caption{String Operation Signatures\label{ta:StringOperators}} +\centering +\hypertarget{def-eqstring}{} +\hypertarget{def-nestring}{} +\begin{tabular}{lllll} +\hline +\textbf{Operator} & \textbf{Operand 1} & \textbf{Operand 2} & \textbf{Result} & \textbf{Name}\\ +\hline +\Teqop & \lstring & \lstring & \lbool & \eqstring\\ +\Tneq & \lstring & \lstring & \lbool & \nestring\\ +\hline +\end{tabular} +\end{table} + +\begin{table}[!h] +\caption{Enumeration Operation Signatures\label{ta:EnumerationOperators}} +\centering +\hypertarget{def-eqenum}{} +\hypertarget{def-neenum}{} +\begin{tabular}{lllll} +\hline +\textbf{Operator} & \textbf{Operand 1} & \textbf{Operand 2} & \textbf{Result} & \textbf{Name}\\ +\hline +\Teqop & \lint & \lint & \lbool & \eqenum\\ +\Tneq & \lint & \lint & \lbool & \neenum\\ +% \Teqop & \lenum & \lenum & \lbool & \eqenum\\ +% \Tneq & \lenum & \lenum & \lbool & \neenum\\ +\hline +\end{tabular} +\end{table} + +\pagebreak +\newpage +\section{Syntax} +\begin{flalign*} +\Nunop \derivesinline\ & \Tbnot \;|\; \Tminus \;|\; \Tnot &\\ +\Nbinop \derivesinline\ & \Tand \;|\; \Tband \;|\; \Tbor \;|\; \Tbeq \;|\; \Tdiv \;|\; \Tdivrm \;|\; \Txor \;|\; \Teqop \;|\; \Tneq &\\ + |\ & \Tgt \;|\; \Tgeq \;|\; \Timpl \;|\; \Tlt \;|\; \Tleq \;|\; \Tplus \;|\; \Tminus \;|\; \Tmod \;|\; \Tmul &\\ + |\ & \Tor \;|\; \Trdiv \;|\; \Tshl \;|\; \Tshr \;|\; \Tpow \;|\; \Tconcat +\end{flalign*} + +\section{Abstract Syntax} +\begin{flalign*} +\unop \derives\ & \overname{\BNOT}{\texttt{"!"}} \;|\; \overname{\NEG}{\texttt{"-"}} \;|\; \overname{\NOT}{\texttt{"NOT"}} +& \hypertarget{ast-binop}{} \hypertarget{ast-bor}{} \hypertarget{ast-impl}{} \hypertarget{ast-beq}{} \hypertarget{ast-band}{} +\\ +\binop \derives\ & \overname{\BAND}{\texttt{"\&\&"}} \;|\; \overname{\BOR}{\texttt{"||"}} \;|\; \overname{\IMPL}{\texttt{"-->"}} + \;|\; \overname{\BEQ}{\texttt{"<->"}} + & \hypertarget{ast-eqop}{} \hypertarget{ast-neq}{} \hypertarget{ast-gt}{} \hypertarget{ast-geq}{} \hypertarget{ast-lt}{} \hypertarget{ast-leq}{} +\\ + |\ & \overname{\EQOP}{\texttt{"=="}} \;|\; \overname{\NEQ}{\texttt{"!="}} \;|\; \overname{\GT}{\texttt{"<"}} + \;|\; \overname{\GEQ}{\texttt{">="}} \;|\; \overname{\LT}{\texttt{"<"}} \;|\; \overname{\LEQ}{\texttt{"<="}} + & \hypertarget{ast-plus}{} \hypertarget{ast-minus}{} \hypertarget{ast-or}{} \hypertarget{ast-xor}{} \hypertarget{ast-and}{} +\\ + |\ & \overname{\PLUS}{\texttt{"+"}} \;|\; \overname{\MINUS}{\texttt{"-"}} \;|\; \overname{\OR}{\texttt{"OR"}} + \;|\; \overname{\XOR}{\texttt{"XOR"}} \;|\; \overname{\AND}{\texttt{"AND"}} + & \hypertarget{ast-mul}{} \hypertarget{ast-div}{} \hypertarget{ast-divrm}{} \hypertarget{ast-mod}{} \hypertarget{ast-shl}{} \hypertarget{ast-shr}{} +\\ + |\ & \overname{\MUL}{\texttt{"*"}} \;|\; \overname{\DIV}{\texttt{"DIV"}} \;|\; \overname{\DIVRM}{\texttt{"DIVRM"}} + \;|\; \overname{\MOD}{\texttt{"MOD"}} \;|\; \overname{\SHL}{\texttt{"<<"}} \;|\; \overname{\SHR}{\texttt{">>"}} + & \hypertarget{ast-rdiv}{} \hypertarget{ast-pow}{} +\\ + |\ & \overname{\RDIV}{\texttt{"/"}} \;|\; \overname{\POW}{\texttt{"\^{}"}} + & +\end{flalign*} + +\subsection{ASTRule.Unop \label{sec:ASTRule.Unop}} +\hypertarget{build-unop}{} +The function +\[ + \buildunop(\overname{\parsenode{\Nunop}}{\vparsednode}) \;\aslto\; \overname{\unop}{\vastnode} +\] +transforms a parse node $\vparsednode$ into an AST node $\vastnode$. + +\begin{mathpar} +\inferrule[bnot]{}{ + \buildunop(\Nunop(\Tbnot)) \astarrow \overname{\BNOT}{\vastnode} +} +\end{mathpar} + +\begin{mathpar} +\inferrule[neg]{}{ + \buildunop(\Nunop(\Tminus)) \astarrow \overname{\NEG}{\vastnode} +} +\end{mathpar} + +\begin{mathpar} +\inferrule[not]{}{ + \buildunop(\Nunop(\Tnot)) \astarrow \overname{\NOT}{\vastnode} +} +\end{mathpar} + +\subsection{ASTRule.Binop \label{sec:ASTRule.Binop}} +\hypertarget{build-binop}{} +The function +\[ + \buildbinop(\overname{\parsenode{\Nbinop}}{\vparsednode}) \;\aslto\; \overname{\binop}{\vastnode} +\] +transforms a parse node $\vparsednode$ into an AST node $\vastnode$. + +\begin{mathpar} +\inferrule[]{}{ + \buildbinop(\Nbinop(\Tand)) \astarrow \overname{\AND}{\vastnode} +} +\end{mathpar} + +\begin{mathpar} +\inferrule[]{}{ + \buildbinop(\Nbinop(\Tband)) \astarrow \overname{\BAND}{\vastnode} +} +\end{mathpar} + +\begin{mathpar} +\inferrule[]{}{ + \buildbinop(\Nbinop(\Tbor)) \astarrow \overname{\BOR}{\vastnode} +} +\end{mathpar} + +\begin{mathpar} +\inferrule[]{}{ + \buildbinop(\Nbinop(\Tbeq)) \astarrow \overname{\EQOP}{\vastnode} +} +\end{mathpar} + +\begin{mathpar} +\inferrule[]{}{ + \buildbinop(\Nbinop(\Tdiv)) \astarrow \overname{\DIV}{\vastnode} +} +\end{mathpar} + +\begin{mathpar} +\inferrule[]{}{ + \buildbinop(\Nbinop(\Tdivrm)) \astarrow \overname{\DIVRM}{\vastnode} +} +\end{mathpar} + +\begin{mathpar} +\inferrule[]{}{ + \buildbinop(\Nbinop(\Txor)) \astarrow \overname{\XOR}{\vastnode} +} +\end{mathpar} + +\begin{mathpar} +\inferrule[]{}{ + \buildbinop(\Nbinop(\Teqop)) \astarrow \overname{\EQOP}{\vastnode} +} +\end{mathpar} + +\begin{mathpar} +\inferrule[]{}{ + \buildbinop(\Nbinop(\Tneq)) \astarrow \overname{\NEQ}{\vastnode} +} +\end{mathpar} + +\begin{mathpar} +\inferrule[]{}{ + \buildbinop(\Nbinop(\Tgt)) \astarrow \overname{\GT}{\vastnode} +} +\end{mathpar} + +\begin{mathpar} +\inferrule[]{}{ + \buildbinop(\Nbinop(\Tgeq)) \astarrow \overname{\GEQ}{\vastnode} +} +\end{mathpar} + +\begin{mathpar} +\inferrule[]{}{ + \buildbinop(\Nbinop(\Timpl)) \astarrow \overname{\IMPL}{\vastnode} +} +\end{mathpar} + +\begin{mathpar} +\inferrule[]{}{ + \buildbinop(\Nbinop(\Tlt)) \astarrow \overname{\LT}{\vastnode} +} +\end{mathpar} + +\begin{mathpar} +\inferrule[]{}{ + \buildbinop(\Nbinop(\Tleq)) \astarrow \overname{\LEQ}{\vastnode} +} +\end{mathpar} + +\begin{mathpar} +\inferrule[]{}{ + \buildbinop(\Nbinop(\Tplus)) \astarrow \overname{\PLUS}{\vastnode} +} +\end{mathpar} + +\begin{mathpar} +\inferrule[]{}{ + \buildbinop(\Nbinop(\Tminus)) \astarrow \overname{\MINUS}{\vastnode} +} +\end{mathpar} + +\begin{mathpar} +\inferrule[]{}{ + \buildbinop(\Nbinop(\Tmod)) \astarrow \overname{\MOD}{\vastnode} +} +\end{mathpar} + +\begin{mathpar} +\inferrule[]{}{ + \buildbinop(\Nbinop(\Tmul)) \astarrow \overname{\MUL}{\vastnode} +} +\end{mathpar} + +\begin{mathpar} +\inferrule[]{}{ + \buildbinop(\Nbinop(\Tor)) \astarrow \overname{\OR}{\vastnode} +} +\end{mathpar} + +\begin{mathpar} +\inferrule[]{}{ + \buildbinop(\Nbinop(\Trdiv)) \astarrow \overname{\RDIV}{\vastnode} +} +\end{mathpar} + +\begin{mathpar} +\inferrule[]{}{ + \buildbinop(\Nbinop(\Tshl)) \astarrow \overname{\SHL}{\vastnode} +} +\end{mathpar} + +\begin{mathpar} +\inferrule[]{}{ + \buildbinop(\Nbinop(\Tshr)) \astarrow \overname{\SHR}{\vastnode} +} +\end{mathpar} + +\begin{mathpar} +\inferrule[]{}{ + \buildbinop(\Nbinop(\Tpow)) \astarrow \overname{\POW}{\vastnode} +} +\end{mathpar} + +\begin{mathpar} +\inferrule[]{}{ + \buildbinop(\Nbinop(\Tconcat)) \astarrow \overname{\tododefine{CONCAT}}{\vastnode} +} +\end{mathpar} + +\section{Typing} +\subsection{TypingRule.UnopLiterals \label{sec:TypingRule.UnopLiterals}} +\hypertarget{def-unopliterals}{} +The function +\[ + \unopliterals(\overname{\unop}{\op} \aslsep \overname{\literals}{\vl}) \aslto + \overname{\literals}{\vr} \cup \TTypeError +\] +statically evaluates a unary operator $\op$ (a terminal derived from the AST non-terminal for unary operators) +over a literal $\vl$ and returns the resulting literal $\vr$. +\ProseOtherwiseTypeError + +\hypertarget{def-unopsignatures}{} +The following set of unary operator types and argument types defines the correct argument type +for a given unary operator: +\[ +\unopsignatures \triangleq +\left\{ +\begin{array}{lcll} + (\NEG &,& \lint) &,\\ + (\NEG &,& \lreal) &,\\ + (\BNOT &,& \lbool) &,\\ + (\NOT &,& \lbitvector) &\\ +\end{array} +\right\} +\] + +\subsubsection{Prose} +One of the following applies: +\begin{itemize} + \item All of the following apply (\textsc{error}): + \begin{itemize} + \item $(\op, \astlabel(\vl))$ is not in $\unopsignatures$; + \item the result is a type error indicating that the combination of $\op$ and $\astlabel(\vl)$ + is not legal. + \end{itemize} + + \item All of the following apply (\textsc{negate\_int}): + \begin{itemize} + \item $\op$ is $\NEG$ and $\vl$ is an integer literal for $\vn$; + \item define $\vr$ as the integer literal for $- \vn$. + \end{itemize} + + \item All of the following apply (\textsc{negate\_real}): + \begin{itemize} + \item $\op$ is $\NEG$ and $\vl$ is a real literal for $\vq$; + \item define $\vr$ as the real literal for $- \vq$. + \end{itemize} + + \item All of the following apply (\textsc{not\_bool}): + \begin{itemize} + \item $\op$ is $\BNOT$ and $\vl$ is a Boolean literal for $\vb$; + \item define $\vr$ as the Boolean literal for $\neg\vb$. + \end{itemize} + + \item All of the following apply (\textsc{not\_bits\_empty}, \textsc{not\_bits\_empty}): + \begin{itemize} + \item $\op$ is $\NOT$ and $\vl$ is a bitvector literal for the sequence of bits $\bits$; + \item $\vc$ is the sequence of bits of the same length as $\bits$ where in each position + the bit in $\vr$ is defined as the negation of the bit of $\bits$ in the same position; + \item define $\vr$ as the bitvector literal for $\vc$. + \end{itemize} +\end{itemize} + +\subsubsection{Formally} +\begin{mathpar} +\inferrule[error]{ + (\op, \vl) \not\in \unopsignatures +}{ + \unopliterals(\op, \astlabel(\vl)) \typearrow \TypeErrorVal{TypeMismatch} +} +\and +\inferrule[negate\_int]{}{ + \unopliterals(\overname{\NEG}{\op}, \overname{\lint(n)}{\vl}) \typearrow \overname{\lint(- n)}{\vr} +} +\and +\inferrule[negate\_real]{}{ + \unopliterals(\overname{\NEG}{\op}, \overname{\lreal(q)}{\vl}) \typearrow \overname{\lreal(- q)}{\vr} +} +\and +\inferrule[not\_bool]{}{ + \unopliterals(\overname{\BNOT}{\op}, \overname{\lbool(b)}{\vl}) \typearrow \overname{\lbool(\neg b)}{\vr} +} +\and +\inferrule[not\_bits\_empty]{ + \bits \eqname \emptylist\\ + c \eqdef \emptylist +}{ + \unopliterals(\overname{\NOT}{\op}, \overname{\lbitvector(\bits)}{\vl}) \typearrow\overname{\lbitvector(c)}{\vr} +} +\and +\inferrule[not\_bits\_not\_empty]{ + \bits \eqname \vb_{1..k}\\ + c \eqdef [i=1..k: (1-\vb_\vi)] +}{ + \unopliterals(\overname{\NOT}{\op}, \overname{\lbitvector(\bits)}{\vl}) \typearrow\overname{\lbitvector(c)}{\vr} +} +\end{mathpar} + +\subsection{TypingRule.BinopLiterals \label{sec:TypingRule.BinopLiterals}} +\hypertarget{def-binopliterals}{} +The function +\[ + \binopliterals(\overname{\binop}{\op} \aslsep \overname{\literals}{\vvone} \aslsep \overname{\literals}{\vvtwo}) \aslto + \overname{\literals}{\vr} \cup \TTypeError +\] +statically evaluates a binary operator $\op$ (a terminal derived from the AST non-terminal for binary operators) +over a pair of literals $\vlone$ and $\vltwo$ +and returns the resulting literal $\vr$. +The result is a type error, if it is illegal to apply the operator +to the given values, or a different kind of type error is detected. + +\hypertarget{def-binopsignatures}{} +The following set of binary operator types and argument types defines the correct +argument types for a given binary operator: +\[ +\binopsignatures \triangleq +\left\{ +\begin{array}{lclcll} + (\PLUS &,& \lint &,& \lint)&,\\ + (\MINUS &,& \lint &,& \lint)&,\\ + (\MUL &,& \lint &,& \lint)&,\\ + (\DIV &,& \lint &,& \lint)&,\\ + (\DIVRM &,& \lint &,& \lint)&,\\ + (\MOD &,& \lint &,& \lint)&,\\ + (\POW &,& \lint &,& \lint)&,\\ + (\SHL &,& \lint &,& \lint)&,\\ + (\SHR &,& \lint &,& \lint)&,\\ + (\EQOP &,& \lint &,& \lint)&,\\ + (\NEQ &,& \lint &,& \lint)&,\\ + (\LEQ &,& \lint &,& \lint)&,\\ + (\LT &,& \lint &,& \lint)&,\\ + (\GEQ &,& \lint &,& \lint)&,\\ + (\GT &,& \lint &,& \lint)&,\\ + (\BAND &,& \lbool &,& \lbool)&,\\ + (\BOR &,& \lbool &,& \lbool)&,\\ + (\IMPL &,& \lbool &,& \lbool)&,\\ + (\EQOP &,& \lbool &,& \lbool)&,\\ + (\NEQ &,& \lbool &,& \lbool)&,\\ + (\PLUS &,& \lreal &,& \lreal)&,\\ + (\MINUS &,& \lreal &,& \lreal)&,\\ + (\MUL &,& \lreal &,& \lreal)&,\\ + (\RDIV &,& \lreal &,& \lreal)&,\\ + (\POW &,& \lreal &,& \lint)&,\\ + (\EQOP &,& \lreal &,& \lreal)&,\\ + (\NEQ &,& \lreal &,& \lreal)&,\\ + (\LEQ &,& \lreal &,& \lreal)&,\\ + (\LT &,& \lreal &,& \lreal)&,\\ + (\GEQ &,& \lreal &,& \lreal)&,\\ + (\GT &,& \lreal &,& \lreal)&,\\ + (\EQOP &,& \lbitvector &,& \lbitvector)&,\\ + (\NEQ &,& \lbitvector &,& \lbitvector)&,\\ + (\OR &,& \lbitvector &,& \lbitvector)&,\\ + (\AND &,& \lbitvector &,& \lbitvector)&,\\ + (\XOR &,& \lbitvector &,& \lbitvector)&,\\ + (\MINUS &,& \lbitvector &,& \lbitvector)&,\\ + (\PLUS &,& \lbitvector &,& \lbitvector)&,\\ + (\MINUS &,& \lbitvector &,& \lint)&,\\ + (\PLUS &,& \lbitvector &,& \lint)&\\ +\end{array} +\right\} +\] + +\subsubsection{Prose} +One of the following applies: +\begin{itemize} + \item All of the following apply (\textsc{error}): + \begin{itemize} + \item $(\op, \astlabel(\vlone), \astlabel(\vltwo))$ is not included in $\binopsignatures$; + \item the result is a type error indicating the $\op$ cannot be applied to the arguments + with the types given by $\astlabel(\vlone)$ and $\astlabel(\vltwo)$. + \end{itemize} + + \item All of the following apply (\textsc{add\_int}): + \begin{itemize} + \item $\op$ is $\PLUS$, $\vlone$ is the literal integer for $a$, and $\vltwo$ is the literal integer for $b$; + \item define $\vr$ as the literal integer for $a+b$. + \end{itemize} + + \item All of the following apply (\textsc{sub\_int}): + \begin{itemize} + \item $\op$ is $\MINUS$, $\vlone$ is the literal integer for $a$, and $\vltwo$ is the literal integer for $b$; + \item define $\vr$ as the literal integer for $a-b$. + \end{itemize} + + \item All of the following apply (\textsc{mul\_int}): + \begin{itemize} + \item $\op$ is $\MUL$, $\vlone$ is the literal integer for $a$, and $\vltwo$ is the literal integer for $b$; + \item define $\vr$ as the literal integer for $a\times b$. + \end{itemize} + + \item All of the following apply (\textsc{div\_int}): + \begin{itemize} + \item $\op$ is $\DIV$, $\vlone$ is the literal integer for $a$, and $\vltwo$ is the literal integer for $b$; + \item checking that $b$ is positive yields $\True$\ProseOrTypeError; + \item define $n$ as $a$ divided by $b$ (note that $n$ is potentially a fraction); + \item checking that $n$ is an integer yields $\True$\ProseOrTypeError; + \item define $\vr$ as the literal integer for $a\div b$. + \end{itemize} + + \item All of the following apply (\textsc{fdiv\_int}): + \begin{itemize} + \item $\op$ is $\DIVRM$, $\vlone$ is the literal integer for $a$, and $\vltwo$ is the literal integer for $b$; + \item checking that $b$ is positive yields $\True$\ProseOrTypeError; + \item define $n$ as $a$ divided by $b$, rounded down (if $a$ is negative, $n$ is rounded down towards infinity); + \item define $\vr$ as the literal integer for $n$. + \end{itemize} + + \item All of the following apply (\textsc{frem\_int}): + \begin{itemize} + \item $\op$ is $\MOD$, $\vlone$ is the literal integer for $a$, and $\vltwo$ is the literal integer for $b$; + \item applying $\binopliterals$ to $\DIVRM$ with $\vlone$ and $\vltwo$ yields $c$\ProseOrTypeError; + \item define $n$ as $a-c$; + \item define $\vr$ as the literal integer for $n$. + \end{itemize} + + \item All of the following apply (\textsc{exp\_int}): + \begin{itemize} + \item $\op$ is $\POW$, $\vlone$ is the literal integer for $a$, and $\vltwo$ is the literal integer for $b$; + \item checking that $b$ is non-negative yields $\True$\ProseOrTypeError; + \item define $n$ as $a^b$; + \item define $\vr$ as the literal integer for $n$. + \end{itemize} + + \item All of the following apply (\textsc{shl}): + \begin{itemize} + \item $\op$ is $\SHL$, $\vlone$ is the literal integer for $a$, and $\vltwo$ is the literal integer for $b$; + \item checking that $b$ is non-negative yields $\True$\ProseOrTypeError; + \item applying $\binopliterals$ to $\POW$ with $2$ and $\vltwo$ yields the literal integer for $e$; + \item applying $\binopliterals$ to $\MUL$ with $2$ and the literal integer for $e$ yields $\vr$. + \end{itemize} + + \item All of the following apply (\textsc{shr}): + \begin{itemize} + \item $\op$ is $\SHR$, $\vlone$ is the literal integer for $a$, and $\vltwo$ is the literal integer for $b$; + \item checking that $b$ is non-negative yields $\True$\ProseOrTypeError; + \item applying $\binopliterals$ to $\POW$ with $2$ and $\vltwo$ yields the literal integer for $e$; + \item applying $\binopliterals$ to $\DIVRM$ with $2$ and the literal integer for $e$ yields $\vr$. + \end{itemize} + + \item All of the following apply (\textsc{eq\_int}): + \begin{itemize} + \item $\op$ is $\EQOP$, $\vlone$ is the literal integer for $a$, and $\vltwo$ is the literal integer for $b$; + \item define $\vr$ as the Boolean literal that is $\True$ if and only if $a$ is equal to $b$. + \end{itemize} + + \item All of the following apply (\textsc{ne\_int}): + \begin{itemize} + \item $\op$ is $\NEQ$, $\vlone$ is the literal integer for $a$, and $\vltwo$ is the literal integer for $b$; + \item define $\vr$ as the Boolean literal that is $\True$ if and only if $a$ is different from $b$ holds. + \end{itemize} + + \item All of the following apply (\textsc{le\_int}): + \begin{itemize} + \item $\op$ is $\LEQ$, $\vlone$ is the literal integer for $a$, and $\vltwo$ is the literal integer for $b$; + \item define $\vr$ as the Boolean literal that is $\True$ if and only if $a$ is less than or equal to $b$s. + \end{itemize} + + \item All of the following apply (\textsc{lt\_int}): + \begin{itemize} + \item $\op$ is $\LT$, $\vlone$ is the literal integer for $a$, and $\vltwo$ is the literal integer for $b$; + \item define $\vr$ as the Boolean literal that is $\True$ if and only if $a$ is less than $b$s. + \end{itemize} + + \item All of the following apply (\textsc{ge\_int}): + \begin{itemize} + \item $\op$ is $\GEQ$, $\vlone$ is the literal integer for $a$, and $\vltwo$ is the literal integer for $b$; + \item define $\vr$ as the Boolean literal that is $\True$ if and only if $a$ is greater or equal than $b$s. + \end{itemize} + + \item All of the following apply (\textsc{gt\_int}): + \begin{itemize} + \item $\op$ is $\GT$, $\vlone$ is the literal integer for $a$, and $\vltwo$ is the literal integer for $b$; + \item define $\vr$ as the Boolean literal that is $\True$ if and only if $a$ is greater than $b$s. + \end{itemize} + + \item All of the following apply (\textsc{and\_bool}): + \begin{itemize} + \item $\op$ is $\BAND$, $\vlone$ is the literal Boolean for $a$, and $\vltwo$ is the literal Boolean for $b$; + \item define $\vr$ as the Boolean literal that is $\True$ if and only if both $a$ and $b$ are $\True$. + \end{itemize} + + \item All of the following apply (\textsc{or\_bool}): + \begin{itemize} + \item $\op$ is $\BOR$, $\vlone$ is the literal Boolean for $a$, and $\vltwo$ is the literal Boolean for $b$; + \item define $\vr$ as the Boolean literal that is $\True$ if and only if at least one of $a$ and $b$ is $\True$. + \end{itemize} + + \item All of the following apply (\textsc{implies\_bool}): + \begin{itemize} + \item $\op$ is $\IMPL$, $\vlone$ is the literal Boolean for $a$, and $\vltwo$ is the literal Boolean for $b$; + \item define $\vr$ as the Boolean literal that is $\True$ if and only if $a$ is $\False$ or $b$ is $\True$. + \end{itemize} + + \item All of the following apply (\textsc{eq\_bool}): + \begin{itemize} + \item $\op$ is $\EQOP$, $\vlone$ is the literal Boolean for $a$, and $\vltwo$ is the literal Boolean for $b$; + \item define $\vr$ as the Boolean literal that is $\True$ if and only if $a$ is equal to $b$. + \end{itemize} + + \item All of the following apply (\textsc{ne\_bool}): + \begin{itemize} + \item $\op$ is $\NEQ$, $\vlone$ is the literal Boolean for $a$, and $\vltwo$ is the literal Boolean for $b$; + \item define $\vr$ as the Boolean literal that is $\True$ if and only if $a$ is different from $b$. + \end{itemize} + + \item All of the following apply (\textsc{add\_real}): + \begin{itemize} + \item $\op$ is $\PLUS$, $\vlone$ is the literal real for $a$, and $\vltwo$ is the literal real for $b$; + \item define $\vr$ as the real literal for $a + b$. + \end{itemize} + + \item All of the following apply (\textsc{sub\_real}): + \begin{itemize} + \item $\op$ is $\MINUS$, $\vlone$ is the literal real for $a$, and $\vltwo$ is the literal real for $b$; + \item define $\vr$ as the real literal for $a - b$. + \end{itemize} + + \item All of the following apply (\textsc{mul\_real}): + \begin{itemize} + \item $\op$ is $\MUL$, $\vlone$ is the literal real for $a$, and $\vltwo$ is the literal real for $b$; + \item define $\vr$ as the real literal for $a \times b$. + \end{itemize} + + \item All of the following apply (\textsc{div\_real}): + \begin{itemize} + \item $\op$ is $\RDIV$, $\vlone$ is the literal real for $a$, and $\vltwo$ is the literal real for $b$; + \item checking whether $b$ is different from $0$ yields $\True$\ProseOrTypeError; + \item define $\vr$ as the real literal for $a \div b$. + \end{itemize} + + \item All of the following apply (\textsc{exp\_real}): + \begin{itemize} + \item $\op$ is $\POW$, $\vlone$ is the literal real for $a$, and $\vltwo$ is the literal integer for $b$; + \item define $\vr$ as the real literal for $a^b$. + \end{itemize} + + \item All of the following apply (\textsc{eq\_real}): + \begin{itemize} + \item $\op$ is $\EQOP$, $\vlone$ is the literal real for $a$, and $\vltwo$ is the literal real for $b$; + \item define $\vr$ as the Boolean literal that is $\True$ if and only if $a$ is equal to $b$. + \end{itemize} + + \item All of the following apply (\textsc{ne\_real}): + \begin{itemize} + \item $\op$ is $\NEQ$, $\vlone$ is the literal real for $a$, and $\vltwo$ is the literal real for $b$; + \item define $\vr$ as the Boolean literal that is $\True$ if and only if $a$ is different from $b$. + \end{itemize} + + \item All of the following apply (\textsc{le\_real}): + \begin{itemize} + \item $\op$ is $\LEQ$, $\vlone$ is the literal real for $a$, and $\vltwo$ is the literal real for $b$; + \item define $\vr$ as the Boolean literal that is $\True$ if and only if $a$ is less than or equal to $b$. + \end{itemize} + + \item All of the following apply (\textsc{lt\_real}): + \begin{itemize} + \item $\op$ is $\LT$, $\vlone$ is the literal real for $a$, and $\vltwo$ is the literal real for $b$; + \item define $\vr$ as the Boolean literal that is $\True$ if and only if $a$ is less than $b$. + \end{itemize} + + \item All of the following apply (\textsc{ge\_real}): + \begin{itemize} + \item $\op$ is $\GEQ$, $\vlone$ is the literal real for $a$, and $\vltwo$ is the literal real for $b$; + \item define $\vr$ as the Boolean literal that is $\True$ if and only if $a$ is greater than or equal to $b$. + \end{itemize} + + \item All of the following apply (\textsc{gt\_real}): + \begin{itemize} + \item $\op$ is $\GT$, $\vlone$ is the literal real for $a$, and $\vltwo$ is the literal real for $b$; + \item define $\vr$ as the Boolean literal that is $\True$ if and only if $a$ is greater than $b$. + \end{itemize} + + \item All of the following apply (\textsc{bitwise\_different\_bitwidths}): + \begin{itemize} + \item $\vvone$ is a bitvector literal for $a$; + \item $\vvtwo$ is a bitvector literal for $b$; + \item the lengths of $a$ and $b$ are different; + \item the result is a type error indicating that the bitvectors must be of the same width. + \end{itemize} + + \item All of the following apply (\textsc{bitwise\_empty}): + \begin{itemize} + \item $\vvone$ is the empty bitvector literal; + \item $\vvtwo$ is the empty bitvector literal; + \item $\op$ is one of $\OR$, $\AND$, $\XOR$, $\PLUS$, or $\MINUS$; + \item define $\vr$ as the empty bitvector literal. + \end{itemize} + + \item All of the following apply (\textsc{eq\_bits\_empty}): + \begin{itemize} + \item $\vvone$ is the empty bitvector literal; + \item $\vvtwo$ is the empty bitvector literal; + \item $\op$ is $\EQOP$; + \item define $\vr$ as the Boolean literal for $\True$. + \end{itemize} + + \item All of the following apply (\textsc{eq\_bits\_not\_empty}): + \begin{itemize} + \item $\vvone$ is a bitvector literal for $a_{1..k}$; + \item $\vvtwo$ is a bitvector literal for $b_{1..k}$; + \item $\op$ is $\EQOP$; + \item define $\vb$ as $\True$ if and only if $a_i$ is equal to $b_i$, for $i=1..k$; + \item define $\vr$ as the Boolean literal for $\vb$. + \end{itemize} + + \item All of the following apply (\textsc{ne\_bits}): + \begin{itemize} + \item $\vvone$ is a bitvector literal for $a$; + \item $\vvtwo$ is a bitvector literal for $b$; + \item $\op$ is $\NEQ$; + \item applying $\binopliterals$ to $\NEQ$ for $\vvone$ and $\vvtwo$ yields the Boolean literal for $\vb$\ProseOrTypeError; + \item define $\vr$ as the Boolean literal for $\neg\vb$. + \end{itemize} + + \item All of the following apply (\textsc{or\_bits}): + \begin{itemize} + \item $\vvone$ is a bitvector literal for $a_{1..k}$; + \item $\vvtwo$ is a bitvector literal for $b_{1..k}$; + \item $\op$ is $\OR$; + \item define $c_i$ as the maximum of $a_i$ and $b_i$ for $i=1..k$; + \item define $\vr$ as the bitvector literal for $c_{1..k}$. + \end{itemize} + + \item All of the following apply (\textsc{and\_bits}): + \begin{itemize} + \item $\vvone$ is a bitvector literal for $a_{1..k}$; + \item $\vvtwo$ is a bitvector literal for $b_{1..k}$; + \item $\op$ is $\AND$; + \item define $c_i$ as the minimum of $a_i$ and $b_i$ for $i=1..k$; + \item define $\vr$ as the bitvector literal for $c_{1..k}$. + \end{itemize} + + \item All of the following apply (\textsc{xor\_bits}): + \begin{itemize} + \item $\vvone$ is a bitvector literal for $a_{1..k}$; + \item $\vvtwo$ is a bitvector literal for $b_{1..k}$; + \item $\op$ is $\XOR$; + \item define $c_i$ as $1$ if $a_i$ is different from $b_i$ and $0$ otherwise, for $i=1..k$; + \item define $\vr$ as the bitvector literal for $c_{1..k}$. + \end{itemize} + + \item All of the following apply (\textsc{add\_bits}): + \begin{itemize} + \item $\vvone$ is a bitvector literal for $a_{1..k}$; + \item $\vvtwo$ is a bitvector literal for $b_{1..k}$; + \item $\op$ is $\PLUS$; + \item define $a$ as the natural number represented by $a_{1..k}$; + \item define $b$ as the natural number represented by $b_{1..k}$; + \item define $c$ as the two's complement little endian representation of $a+b$ in $k$ bits; + \item define $\vr$ as the bitvector literal for $c$. + \end{itemize} + + \item All of the following apply (\textsc{sub\_bits}): + \begin{itemize} + \item $\vvone$ is a bitvector literal for $a_{1..k}$; + \item $\vvtwo$ is a bitvector literal for $b_{1..k}$; + \item $\op$ is $\MINUS$; + \item define $a$ as the natural number represented by $a_{1..k}$; + \item define $b$ as the natural number represented by $b_{1..k}$; + \item define $c$ as the two's complement little endian representation of $a-b$ in $k$ bits; + \item define $\vr$ as the bitvector literal for $c$. + \end{itemize} + + \item All of the following apply (\textsc{add\_bits\_int}): + \begin{itemize} + \item $\vvone$ is a bitvector literal for $a$; + \item $\vvtwo$ is an integer literal for $b$; + \item $\op$ is $\PLUS$; + \item define $y$ as the natural number represented by $a$; + \item define $c$ as the two's complement little endian representation of $y+b$ in $\listlen{a}$ bits; + \item define $\vr$ as the bitvector literal for $c$. + \end{itemize} + + \item All of the following apply (\textsc{sub\_bits\_int}): + \begin{itemize} + \item $\vvone$ is a bitvector literal for $a$; + \item $\vvtwo$ is an integer literal for $b$; + \item $\op$ is $\MINUS$; + \item define $y$ as the natural number represented by $a$; + \item define $c$ as the two's complement little endian representation of $y-b$ in $\listlen{a}$ bits; + \item define $\vr$ as the bitvector literal for $c$. + \end{itemize} +\end{itemize} + +\subsubsection{Formally} + +\begin{mathpar} +\inferrule[error]{ + (\op, \astlabel(\vlone), \astlabel(\vltwo)) \not\in \binopsignatures +}{ + \binopliterals(\op, \overname{\vlone}{\vvone}, \overname{\vltwo}{\vvtwo}) \typearrow \TypeErrorVal{TypeMismatch} +} +\end{mathpar} + +\subsubsection{Arithmetic Operators Over Integer Values \label{sec:AthimeticOverInt}} +\begin{mathpar} +\inferrule[add\_int]{}{ + \binopliterals(\overname{\PLUS}{\op}, \overname{\lint(a)}{\vvone}, \overname{\lint(b)}{\vvtwo}) \typearrow \overname{\lint(a + b)}{\vr} +} +\end{mathpar} + +\begin{mathpar} +\inferrule[sub\_int]{}{ + \binopliterals(\overname{\MINUS}{\op}, \overname{\lint(a)}{\vvone}, \overname{\lint(b)}{\vvtwo}) \typearrow \overname{\lint(a - b)}{\vr} +} +\end{mathpar} + +\begin{mathpar} +\inferrule[mul\_int]{}{ + \binopliterals(\overname{\MUL}{\op}, \overname{\lint(a)}{\vvone}, \overname{\lint(b)}{\vvtwo}) \typearrow \overname{\lint(a \times b)}{\vr} +} +\end{mathpar} + +\begin{mathpar} +\inferrule[div\_int]{ + \checktrans{b > 0}{DIV\_DenominatorNegative} \checktransarrow \True \OrTypeError\\\\ + n \eqdef a \div b \\\\ + \checktrans{n \in \Z}{\DivIntIndivisible} \checktransarrow \True \OrTypeError +}{ + \binopliterals(\overname{\DIV}{\op}, \overname{\lint(a)}{\vvone}, \overname{\lint(b)}{\vvtwo}) \typearrow \overname{\lint(n)}{\vr} +} +\and +\inferrule[fdiv\_int]{ + \checktrans{b > 0}{FDIV\_DenominatorNegative} \checktransarrow \True \OrTypeError\\\\ + n \eqdef \choice{a \geq 0}{\lfloor a \div b \rfloor}{-(\lceil (-a) \div b \rceil)} +}{ + \binopliterals(\overname{\DIVRM}{\op}, \overname{\lint(a)}{\vvone}, \overname{\lint(b)}{\vvtwo}) \typearrow \overname{\lint(n)}{\vr} +} +\end{mathpar} + +\begin{mathpar} +\inferrule[frem\_int]{ + \binopliterals(\DIVRM, \lint(a), \lint(b)) \typearrow \lint(c) \OrTypeError +}{ + \binopliterals(\overname{\MOD}{\op}, \overname{\lint(a)}{\vvone}, \overname{\lint(b)}{\vvtwo}) \typearrow \overname{\lint(a - (c \times b))}{\vr} +} +\end{mathpar} + +\begin{mathpar} +\inferrule[exp\_int]{ + \checktrans{b \geq 0}{ExponentNegative} \checktransarrow \True \OrTypeError +}{ + \binopliterals(\overname{\POW}{\op}, \overname{\lint(a)}{\vvone}, \overname{\lint(b)}{\vvtwo}) \typearrow \overname{\lint(a^b)}{\vr} +} +\end{mathpar} + +\begin{mathpar} +\inferrule[shl]{ + \checktrans{b \geq 0}{ShifterNegative} \checktransarrow \True \OrTypeError\\\\ + \binopliterals(\POW, \lint(2), \lint(b)) \typearrow \lint(e)\\ + \binopliterals(\MUL, \lint(a), \lint(e)) \typearrow \vr +}{ + \binopliterals(\overname{\SHL}{\op}, \overname{\lint(a)}{\vvone}, \overname{\lint(b)}{\vvtwo}) \typearrow \vr +} +\end{mathpar} + +\begin{mathpar} +\inferrule[shr]{ + \checktrans{b \geq 0}{ShifterNegative} \checktransarrow \True \OrTypeError\\\\ + \binopliterals(\POW, \lint(2), \lint(b)) \typearrow \lint(e)\\ + \binopliterals(\DIVRM, \lint(a), \lint(e)) \typearrow \vr +}{ + \binopliterals(\overname{\SHR}{\op}, \overname{\lint(a)}{\vvone}, \overname{\lint(b)}{\vvtwo}) \typearrow \vr +} +\end{mathpar} + +\subsubsection{Relational Operators Over Integer Values \label{sec:RelationalOverInt}} +\begin{mathpar} +\inferrule[eq\_int]{}{ + \binopliterals(\overname{\EQOP}{\op}, \overname{\lint(a)}{\vvone}, \overname{\lint(b)}{\vvtwo}) \typearrow \overname{\lbool(a = b)}{\vr} +} +\end{mathpar} + +\begin{mathpar} +\inferrule[ne\_int]{}{ + \binopliterals(\overname{\NEQ}{\op}, \overname{\lint(a)}{\vvone}, \overname{\lint(b)}{\vvtwo}) \typearrow \overname{\lbool(a \neq b)}{\vr} +} +\end{mathpar} + +\begin{mathpar} +\inferrule[le\_int]{}{ + \binopliterals(\overname{\LEQ}{\op}, \overname{\lint(a)}{\vvone}, \overname{\lint(b)}{\vvtwo}) \typearrow \overname{\lbool(a \leq b)}{\vr} +} +\end{mathpar} + +\begin{mathpar} +\inferrule[lt\_int]{}{ + \binopliterals(\overname{\LT}{\op}, \overname{\lint(a)}{\vvone}, \overname{\lint(b)}{\vvtwo}) \typearrow \overname{\lbool(a < b)}{\vr} +} +\end{mathpar} + +\begin{mathpar} +\inferrule[ge\_int]{}{ + \binopliterals(\overname{\GEQ}{\op}, \overname{\lint(a)}{\vvone}, \overname{\lint(b)}{\vvtwo}) \typearrow \overname{\lbool(a \geq b)}{\vr} +} +\end{mathpar} + +\begin{mathpar} +\inferrule[gt\_int]{}{ + \binopliterals(\overname{\GT}{\op}, \overname{\lint(a)}{\vvone}, \overname{\lint(b)}{\vvtwo}) \typearrow \overname{\lbool(a > b)}{\vr} +} +\end{mathpar} + +\subsubsection{Boolean Operators Over Boolean Values \label{sec:BooleanOverBoolean}} +\begin{mathpar} +\inferrule[and\_bool]{}{ + \binopliterals(\overname{\BAND}{\op}, \overname{\lbool(a)}{\vvone}, \overname{\lbool(b)}{\vvtwo}) \typearrow \overname{\lbool(a \wedge b)}{\vr} +} +\end{mathpar} + +\begin{mathpar} +\inferrule[or\_bool]{}{ + \binopliterals(\overname{\BOR}{\op}, \overname{\lbool(a)}{\vvone}, \overname{\lbool(b)}{\vvtwo}) \typearrow \overname{\lbool(a \lor b)}{\vr} +} +\end{mathpar} + +\begin{mathpar} +\inferrule[implies\_bool]{}{ + \binopliterals(\overname{\IMPL}{\op}, \overname{\lbool(a)}{\vvone}, \overname{\lbool(b)}{\vvtwo}) \typearrow \overname{\lbool(\neg a \lor b)}{\vr} +} +\end{mathpar} + +\begin{mathpar} +\inferrule[eq\_bool]{}{ + \binopliterals(\overname{\EQOP}{\op}, \overname{\lbool(a)}{\vvone}, \overname{\lbool(b)}{\vvtwo}) \typearrow \overname{\lbool(a = b)}{\vr} +} +\end{mathpar} + +\begin{mathpar} +\inferrule[ne\_bool]{}{ + \binopliterals(\overname{\NEQ}{\op}, \overname{\lbool(a)}{\vvone}, \overname{\lbool(b)}{\vvtwo}) \typearrow \overname{\lbool(a \neq b)}{\vr} +} +\end{mathpar} + +\subsubsection{Arithmetic Operators Over Real Values \label{sec:AthimeticOverReal}} +\begin{mathpar} +\inferrule[add\_real]{}{ + \binopliterals(\overname{\PLUS}{\op}, \overname{\lreal(a)}{\vvone}, \overname{\lreal(b)}{\vvtwo}) \typearrow \overname{\lreal(a+b)}{\vr} +} +\end{mathpar} + +\begin{mathpar} +\inferrule[sub\_real]{}{ + \binopliterals(\overname{\MINUS}{\op}, \overname{\lreal(a)}{\vvone}, \overname{\lreal(b)}{\vvtwo}) \typearrow \overname{\lreal(a-b)}{\vr} +} +\end{mathpar} + +\begin{mathpar} +\inferrule[mul\_real]{}{ + \binopliterals(\overname{\MUL}{\op}, \overname{\lreal(a)}{\vvone}, \overname{\lreal(b)}{\vvtwo}) \typearrow \overname{\lreal(a\times b)}{\vr} +} +\end{mathpar} + +\begin{mathpar} +\inferrule[div\_real]{ + \checktrans{b \neq 0}{RDIV\_DenominatorZero} \checktransarrow \True \OrTypeError +}{ + \binopliterals(\overname{\RDIV}{\op}, \overname{\lreal(a)}{\vvone}, \overname{\lreal(b)}{\vvtwo}) \typearrow \overname{\lreal(a\div b)}{\vr} +} +\end{mathpar} + +\begin{mathpar} +\inferrule[exp\_real]{}{ + \binopliterals(\overname{\POW}{\op}, \overname{\lreal(a)}{\vvone}, \overname{\lint(b)}{\vvtwo}) \typearrow \overname{\lreal(a^b)}{\vr} +} +\end{mathpar} + +\subsubsection{Relational Operators Over Real Values \label{sec:RealtionalOverReal}} +\begin{mathpar} +\inferrule[eq\_real]{}{ + \binopliterals(\overname{\EQOP}{\op}, \overname{\lreal(a)}{\vvone}, \overname{\lreal(b)}{\vvtwo}) \typearrow \overname{\lbool(a = b)}{\vr} +} +\end{mathpar} + +\begin{mathpar} +\inferrule[ne\_real]{}{ + \binopliterals(\overname{\NEQ}{\op}, \overname{\lreal(a)}{\vvone}, \overname{\lreal(b)}{\vvtwo}) \typearrow \overname{\lbool(a \neq b)}{\vr} +} +\end{mathpar} + +\begin{mathpar} +\inferrule[le\_real]{}{ + \binopliterals(\overname{\LEQ}{\op}, \overname{\lreal(a)}{\vvone}, \overname{\lreal(b)}{\vvtwo}) \typearrow \overname{\lbool(a \leq b)}{\vr} +} +\end{mathpar} + +\begin{mathpar} +\inferrule[lt\_real]{}{ + \binopliterals(\overname{\LT}{\op}, \overname{\lreal(a)}{\vvone}, \overname{\lreal(b)}{\vvtwo}) \typearrow \overname{\lbool(a < b)}{\vr} +} +\end{mathpar} + +\begin{mathpar} +\inferrule[ge\_real]{}{ + \binopliterals(\overname{\GEQ}{\op}, \overname{\lreal(a)}{\vvone}, \overname{\lreal(b)}{\vvtwo}) \typearrow \overname{\lbool(a \geq b)}{\vr} +} +\end{mathpar} + +\begin{mathpar} +\inferrule[gt\_real]{}{ + \binopliterals(\overname{\GT}{\op}, \overname{\lreal(a)}{\vvone}, \overname{\lreal(b)}{\vvtwo}) \typearrow \overname{\lbool(a > b)}{\vr} +} +\end{mathpar} + +\subsubsection{Operators Over Bitvectors \label{sec:BitvectorOperations}} +\hypertarget{def-bintounsigned}{} +The function $\bintounsigned : \{0,1\}^* \rightarrow \N$ converts a non-empty sequence of bits +into a natural number: +\[ + \bintounsigned(a_{n..1}) \triangleq \sum_{i=1}^n a_i \cdot 2^{a_i} +\] +and an empty sequence of bits into $0$: +\[ + \bintounsigned(\emptylist) \triangleq 0 \enspace. +\] + +\hypertarget{def-inttobits}{} +The function $\inttobits : \overname{\Z}{\texttt{val}} \times \overname{\Z}{\texttt{width}} \rightarrow \{0,1\}^*$ +converts an integer \texttt{val} to its two's complement little endian representation +of \texttt{width} bits. + +\begin{mathpar} +\inferrule[bitwise\_different\_bitwidths]{ + \listlen{a} \neq \listlen{b} +}{ + \binopliterals(\op, \overname{\lbitvector(a)}{\vvone}, \overname{\lbitvector(b)}{\vvtwo}) \typearrow + \TypeErrorVal{\RequireSameBitwidths} +} +\and +\inferrule[bitwise\_empty]{ + \op \in \{\OR, \AND, \XOR, \PLUS, \MINUS\} +}{ + \binopliterals(\op, \overname{\lbitvector(\emptylist)}{\vvone}, \overname{\lbitvector(\emptylist)}{\vvtwo}) \typearrow + \overname{\lbitvector(\emptylist)}{\vr} +} +\end{mathpar} + +\begin{mathpar} +\inferrule[eq\_bits\_empty]{}{ + \binopliterals(\overname{\EQOP}{\op}, \overname{\lbitvector(\emptylist)}{\vvone}, \overname{\lbitvector(\emptylist)}{\vvtwo}) \typearrow + \overname{\lbool(\True)}{\vr} +} +\and +\inferrule[eq\_bits\_not\_empty]{ + \vb \eqdef \bigwedge_{i=1}^k a_i = b_i +}{ + \binopliterals(\overname{\EQOP}{\op}, \overname{\lbitvector(a_{1..k})}{\vvone}, \overname{\lbitvector(b_{1..k})}{\vvtwo}) \typearrow + \overname{\lbool(\vb)}{\vr} +} +\end{mathpar} + +\begin{mathpar} +\inferrule[ne\_bits]{ + \binopliterals(\EQOP, \lbitvector(a), \lbitvector(b)) \typearrow \lbool(\vb) \OrTypeError +}{ + \binopliterals(\overname{\NEQ}{\op}, \overname{\lbitvector(a)}{\vvone}, \overname{\lbitvector(b)}{\vvtwo}) \typearrow \lbool(\neg\vb) +} +\end{mathpar} + +\begin{mathpar} +\inferrule[or\_bits]{ + i=1..k: c_i = \max(a_i, b_i) +}{ + \binopliterals(\overname{\OR}{\op}, \overname{\lbitvector(a_{1..k})}{\vvone}, \overname{\lbitvector(b_{1..k})}{\vvtwo}) \typearrow \lbitvector(c_{1..k}) +} +\end{mathpar} + +\begin{mathpar} +\inferrule[and\_bits]{ + i=1..k: c_i = \min(a_i, b_i) +}{ + \binopliterals(\overname{\AND}{\op}, \overname{\lbitvector(a_{1..k})}{\vvone}, \overname{\lbitvector(b_{1..k})}{\vvtwo}) \typearrow \lbitvector(c_{1..k}) +} +\end{mathpar} + +\begin{mathpar} +\inferrule[xor\_bits]{ + { + \textit{xor\_bit} = \lambda a,b\in\{0,1\}.\ \left\{ + \begin{array}{ll} + 0 & \text{ if } a = b\\ + 1 & \text{ otherwise} + \end{array} + \right. + }\\ + i=1..k: c_i=\textit{xor\_bit}(a_i, b_i) +}{ + \binopliterals(\overname{\XOR}{\op}, \overname{\lbitvector(a_{1..k})}{\vvone}, \overname{\lbitvector(b_{1..k})}{\vvtwo}) \typearrow \lbitvector(c_{1..k}) +} +\end{mathpar} + +\begin{mathpar} +\inferrule[add\_bits]{ + a \eqdef \bintounsigned(a_{1..k})\\ + b \eqdef \bintounsigned(b_{1..k})\\ + c \eqdef \inttobits(a + b, k) +}{ + \binopliterals(\overname{\PLUS}{\op}, \overname{\lbitvector(a_{1..k})}{\vvone}, \overname{\lbitvector(b_{1..k})}{\vvtwo}) \typearrow \overname{\lbitvector(c)}{\vr} +} +\end{mathpar} + +\begin{mathpar} +\inferrule[sub\_bits]{ + a \eqdef \bintounsigned(a_{1..k})\\ + b \eqdef \bintounsigned(b_{1..k})\\ + c \eqdef \inttobits(a - b, k) +}{ + \binopliterals(\overname{\MINUS}{\op}, \overname{\lbitvector(a_{1..k})}{\vvone}, \overname{\lbitvector(b_{1..k})}{\vvtwo}) \typearrow \overname{\lbitvector(c)}{\vr} +} +\end{mathpar} + +\begin{mathpar} +\inferrule[add\_bits\_int]{ + y \eqdef \bintounsigned(a)\\ + c \eqdef \inttobits(y + b, \listlen{a}) +}{ + \binopliterals(\overname{\PLUS}{\op}, \overname{\lbitvector(a)}{\vvone}, \overname{\lint(b)}{\vvtwo}) \typearrow \overname{\lbitvector(c)}{\vr} +} +\end{mathpar} + +\begin{mathpar} +\inferrule[sub\_bits\_int]{ + y \eqdef \bintounsigned(a)\\ + c \eqdef \inttobits(y - b, \listlen{a}) +}{ + \binopliterals(\overname{\MINUS}{\op}, \overname{\lbitvector(a)}{\vvone}, \overname{\lint(b)}{\vvtwo}) \typearrow \overname{\lbitvector(c)}{\vr} +} +\end{mathpar} + +\section{Semantics} + +\subsection{SemanticsRule.UnopValues \label{sec:SemanticsRule.UnopValues}} +\hypertarget{def-unoprel}{} +The function +\[ + \unoprel(\overname{\unop}{\op} \aslsep \overname{\vals}{\vv}) \aslto \overname{\vals}{\vw} +\] +evaluates a unary operator $\op$ over a \nativevalue\ $\vv$ and returns the \nativevalue\ $\vw$. + +\subsubsection{Prose} +One of the following applies: +\begin{itemize} + \item All of the following apply (\textsc{negate\_int}): + \begin{itemize} + \item $\op$ is $\NEG$ and $\vv$ is a literal integer for $n$; + \item statically evaluating $\NEG$ on the literal integer for $n$ yields the + literal integer for $m$; + \item $\vw$ is the native integer value for $m$. + \end{itemize} + + \item All of the following apply (\textsc{negate\_real}): + \begin{itemize} + \item $\op$ is $\NEG$ and $\vv$ is a literal real for $p$; + \item statically evaluating $\NEG$ on the literal real for $n$ yields the + literal real for $q$; + \item $\vw$ is the native real value for $q$. + \end{itemize} + + \item All of the following apply (\textsc{not\_bool}): + \begin{itemize} + \item $\op$ is $\BNOT$ and $\vv$ is a literal Boolean for $b$; + \item statically evaluating $\BNOT$ on the literal Boolean for $b$ yields the + literal real for $c$; + \item $\vw$ is the native Boolean value for $c$. + \end{itemize} + + \item All of the following apply (\textsc{not\_bits}): + \begin{itemize} + \item $\op$ is $\NOT$ and $\vv$ is a literal bitvector for $\bits$; + \item statically evaluating $\NOT$ on the literal bitvector for $\bits$ yields the + literal bitvector for $c$; + \item $\vw$ is the native bitvector value for $c$. + \end{itemize} +\end{itemize} + +\subsubsection{Formally} +\begin{mathpar} +\inferrule[negate\_int]{ + \unopliterals(\NEG, \lint(n)) \typearrow \lint(m) +}{ + \unoprel(\overname{\NEG}{\op}, \overname{\nvint(n)}{\vv}) \evalarrow \overname{\nvint(m)}{\vw} +} +\and +\inferrule[negate\_real]{ + \unopliterals(\NEG, \lreal(p)) \typearrow \lreal(q) +}{ + \unoprel(\overname{\NEG}{\op}, \overname{\nvreal(p)}{\vv}) \evalarrow \overname{\nvreal(q)}{\vw} +} +\and +\inferrule[not\_bool]{ + \unopliterals(\BNOT, \lbool(b)) \typearrow \lreal(c) +}{ + \unoprel(\overname{\BNOT}{\op}, \overname{\nvbool(b)}{\vv}) \evalarrow \overname{\nvbool(c)}{\vw} +} +\and +\inferrule[not\_bits]{ + \unopliterals(\NOT, \lbitvector(\bits)) \typearrow \lbitvector(c) +}{ + \unoprel(\overname{\NOT}{\op}, \overname{\nvbitvector(\bits)}{\vv}) \evalarrow \overname{\nvbitvector(c)}{\vw} +} +\end{mathpar} + +\subsection{SemanticsRule.BinopValues \label{sec:SemanticsRule.BinopValues}} +\hypertarget{def-binoprel}{} +The function +\[ + \binoprel(\overname{\binop}{\op} \aslsep \overname{\vals}{\vvone} \aslsep \overname{\vals}{\vvtwo}) + \aslto \overname{\vals}{\vr} \cup \TError +\] +evaluates a binary operator $\op$ over a pair of \nativevalues\ --- $\vvone$ and $\vvtwo$ --- and returns the +\nativevalue\ $\vw$ or an error. + +\subsubsection{Prose} +One of the following applies: +\begin{itemize} + \item All of the following apply (\textsc{int\_arith}): + \begin{itemize} + \item $\vvone$ is a literal integer for $a$; + \item $\vvtwo$ is a literal integer for $b$; + \item statically evaluating $\op$ on $\vvone$ and $\vvtwo$ yields the literal integer for $c$; + \item $\vr$ is the native integer value for $c$. + \end{itemize} + + \item All of the following apply (\textsc{int\_rel}): + \begin{itemize} + \item $\vvone$ is a literal integer for $a$; + \item $\vvtwo$ is a literal integer for $b$; + \item statically evaluating $\op$ on $\vvone$ and $\vvtwo$ yields the literal Boolean for $c$; + \item $\vr$ is the native Boolean value for $c$. + \end{itemize} + + \item All of the following apply (\textsc{int\_error}): + \begin{itemize} + \item $\vvone$ is a literal integer for $a$; + \item $\vvtwo$ is a literal integer for $b$; + \item statically evaluating $\op$ on $\vvone$ and $\vvtwo$ yields a type error with message $m$; + \item the result is a dynamic error with message $m$. + \end{itemize} + + \item All of the following apply (\textsc{bool\_okay}): + \begin{itemize} + \item $\vvone$ is a literal Boolean for $a$; + \item $\vvtwo$ is a literal Boolean for $b$; + \item statically evaluating $\op$ on $\vvone$ and $\vvtwo$ yields the literal Boolean for $c$; + \item $\vr$ is the native Boolean value for $c$. + \end{itemize} + + \item All of the following apply (\textsc{bool\_error}): + \begin{itemize} + \item $\vvone$ is a literal Boolean for $a$; + \item $\vvtwo$ is a literal Boolean for $b$; + \item statically evaluating $\op$ on $\vvone$ and $\vvtwo$ yields a type error with message $m$; + \item the result is a dynamic error with message $m$. + \end{itemize} + + \item All of the following apply (\textsc{real\_arith\_okay}): + \begin{itemize} + \item $\vvone$ is a literal real for $a$; + \item $\vvtwo$ is a literal real for $b$; + \item statically evaluating $\op$ on $\vvone$ and $\vvtwo$ yields the literal real for $c$; + \item $\vr$ is the native real value for $c$. + \end{itemize} + + \item All of the following apply (\textsc{real\_rel\_okay}): + \begin{itemize} + \item $\vvone$ is a literal real for $a$; + \item $\vvtwo$ is a literal real for $b$; + \item statically evaluating $\op$ on $\vvone$ and $\vvtwo$ yields the literal Boolean for $c$; + \item $\vr$ is the native Boolean value for $c$. + \end{itemize} + + \item All of the following apply (\textsc{real\_rel\_error}): + \begin{itemize} + \item $\vvone$ is a literal real for $a$; + \item $\vvtwo$ is a literal real for $b$; + \item statically evaluating $\op$ on $\vvone$ and $\vvtwo$ yields a type error with message $m$; + \item the result is a dynamic error with message $m$. + \end{itemize} + + \item All of the following apply (\textsc{bitvector\_rel\_okay}): + \begin{itemize} + \item $\vvone$ is a literal bitvector for $a$; + \item $\vvtwo$ is a literal bitvector for $b$; + \item statically evaluating $\op$ on $\vvone$ and $\vvtwo$ yields the literal Boolean for $c$; + \item $\vr$ is the native Boolean value for $c$. + \end{itemize} + + \item All of the following apply (\textsc{bitvector\_rel\_error}): + \begin{itemize} + \item $\vvone$ is a literal bitvector for $a$; + \item $\vvtwo$ is a literal bitvector for $b$; + \item statically evaluating $\op$ on $\vvone$ and $\vvtwo$ yields a type error with message $m$; + \item the result is a dynamic error with message $m$. + \end{itemize} + + \item All of the following apply (\textsc{bitvector\_bits\_okay}): + \begin{itemize} + \item $\vvone$ is a literal bitvector for $a$; + \item $\vvtwo$ is a literal bitvector for $b$; + \item statically evaluating $\op$ on $\vvone$ and $\vvtwo$ yields the literal bitvector for $c$; + \item $\vr$ is the native bitvector value for $c$. + \end{itemize} + + \item All of the following apply (\textsc{bitvector\_bits\_error}): + \begin{itemize} + \item $\vvone$ is a literal bitvector for $a$; + \item $\vvtwo$ is a literal bitvector for $b$; + \item statically evaluating $\op$ on $\vvone$ and $\vvtwo$ yields a type error with message $m$; + \item the result is a dynamic error with message $m$. + \end{itemize} +\end{itemize} + +\subsubsection{Formally} +\begin{mathpar} +\inferrule[int\_arith]{ + \binopliterals(\op, \lint(a), \lint(b)) \typearrow \lint(c) +}{ + \binoprel(\op, \overname{\nvint(a)}{\vvone}, \overname{\nvint(b)}{\vvtwo}) \evalarrow \overname{\nvint(c)}{\vr} +} +\and +\inferrule[int\_rel]{ + \binopliterals(\op, \lint(a), \lint(b)) \typearrow \lbool(c) +}{ + \binoprel(\op, \overname{\nvint(a)}{\vvone}, \overname{\nvint(b)}{\vvtwo}) \evalarrow \overname{\nvbool(c)}{\vr} +} +\and +\inferrule[int\_error]{ + \binopliterals(\op, \lint(a), \lint(b)) \typearrow \TypeError(m) +}{ + \binoprel(\op, \overname{\nvint(a)}{\vvone}, \overname{\nvint(b)}{\vvtwo}) \evalarrow \Error(m) +} +\end{mathpar} + +\begin{mathpar} +\inferrule[bool\_okay]{ + \binopliterals(\op, \lbool(a), \lbool(b)) \typearrow \lbool(c) +}{ + \binoprel(\op, \overname{\nvbool(a)}{\vvone}, \overname{\nvbool(b)}{\vvtwo}) \evalarrow \overname{\nvbool(c)}{\vr} +} +\and +\inferrule[bool\_error]{ + \binopliterals(\op, \lbool(a), \lbool(b)) \typearrow \TypeError(m) +}{ + \binoprel(\op, \overname{\nvbool(a)}{\vvone}, \overname{\nvbool(b)}{\vvtwo}) \evalarrow \Error(m) +} +\end{mathpar} + +\begin{mathpar} +\inferrule[real\_arith\_okay]{ + \binopliterals(\op, \lreal(a), \lreal(b)) \typearrow \lreal(c) +}{ + \binoprel(\op, \overname{\nvreal(a)}{\vvone}, \overname{\nvreal(b)}{\vvtwo}) \evalarrow \overname{\nvreal(c)}{\vr} +} +\and +\inferrule[real\_arith\_error]{ + \binopliterals(\op, \lreal(a), \lreal(b)) \typearrow \TypeError(m) +}{ + \binoprel(\op, \overname{\nvreal(a)}{\vvone}, \overname{\nvreal(b)}{\vvtwo}) \evalarrow \Error(m) +} +\end{mathpar} + +\begin{mathpar} +\inferrule[real\_rel\_okay]{ + \binopliterals(\op, \lreal(a), \lreal(b)) \typearrow \lbool(c) +}{ + \binoprel(\op, \overname{\nvreal(a)}{\vvone}, \overname{\nvreal(b)}{\vvtwo}) \evalarrow \overname{\nvbool(c)}{\vr} +} +\and +\inferrule[real\_rel\_error]{ + \binopliterals(\op, \lreal(a), \lreal(b)) \typearrow \TypeError(m) +}{ + \binoprel(\op, \overname{\nvreal(a)}{\vvone}, \overname{\nvreal(b)}{\vvtwo}) \evalarrow \Error(m) +} +\end{mathpar} + +\begin{mathpar} +\inferrule[bitvector\_rel\_okay]{ + \binopliterals(\op, \nvbitvector(a), \nvbitvector(b)) \typearrow \lbool(c) +}{ + \binoprel(\op, \overname{\lbitvector(a)}{\vvone}, \overname{\lbitvector(b)}{\vvtwo}) \evalarrow \overname{\nvbool(c)}{\vr} +} +\and +\inferrule[bitvector\_rel\_error]{ + \binopliterals(\op, \lbitvector(a), \lbitvector(b)) \typearrow \TypeError(m) +}{ + \binoprel(\op, \overname{\lbitvector(a)}{\vvone}, \overname{\lbitvector(b)}{\vvtwo}) \evalarrow \Error(m) +} +\and +\inferrule[bitvector\_bits\_okay]{ + \binopliterals(\op, \lbitvector(a), \lbitvector(b)) \typearrow \lbitvector(c) +}{ + \binoprel(\op, \overname{\lbitvector(a)}{\vvone}, \overname{\lbitvector(b)}{\vvtwo}) \evalarrow \overname{\nvbitvector(c)}{\vr} +} +\and +\inferrule[bitvector\_bits\_error]{ + \binopliterals(\op, \lbitvector(a), \lbitvector(b)) \typearrow \TypeError(m) +}{ + \binoprel(\op, \overname{\lbitvector(a)}{\vvone}, \overname{\lbitvector(b)}{\vvtwo}) \evalarrow \Error(m) +} +\end{mathpar} \ No newline at end of file diff --git a/asllib/doc/RelationsOnTypes.tex b/asllib/doc/RelationsOnTypes.tex new file mode 100644 index 000000000..9aa0e2c82 --- /dev/null +++ b/asllib/doc/RelationsOnTypes.tex @@ -0,0 +1,2743 @@ +\section{Relations Over Types\label{sec:RelationsOnTypes}} +This section defines the following relations over types and operators: +\begin{itemize} + \item Subtype (\secref{TypingRule.Subtype}) + \item Subtype Satisfaction (\secref{TypingRule.SubtypeSatisfaction}) + \item Type Satisfaction (\secref{TypingRule.TypeSatisfaction}) + \item Type Clash (\secref{TypingRule.TypeClash}) + \item Lowest Common Ancestor (\secref{TypingRule.LowestCommonAncestor}) + \item Checking adequacy of a unary operator for a type (\secref{TypingRule.CheckUnop}) + \item Checking adequacy of a binary operator for a pair of types (\secref{TypingRule.CheckBinop}) +\end{itemize} + +Finally, we define the following helper functions: +\begin{itemize} + \item TypingRule.AnnotateConstraintBinop (see \secref{TypingRule.AnnotateConstraintBinop}) + \item TypingRule.BinopFilterRhs (see \secref{TypingRule.BinopFilterRhs}) + \item TypingRule.RefineConstraintBySign (see \secref{TypingRule.RefineConstraintBySign}) + \item TypingRule.ReduceToZOpt (see \secref{TypingRule.ReduceToZOpt}) + \item TypingRule.RefineConstraints (see \secref{TypingRule.RefineConstraints}) + \item TypingRule.FilterReduceConstraintDiv (see \secref{TypingRule.FilterReduceConstraintDiv}) + \item TypingRule.GetLiteralDivOpt (see \secref{TypingRule.GetLiteralDivOpt}) + \item TypingRule.ExplodeIntervals (see \secref{TypingRule.ExplodeIntervals}) + \item TypingRule.ExplodeConstraint (see \secref{TypingRule.ExplodeConstraint}) + \item TypingRule.IntervalTooLarge (see \secref{TypingRule.IntervalTooLarge}) + \item TypingRule.BinopIsExploding (see \secref{TypingRule.BinopIsExploding}) +\end{itemize} + +We also define the helper rule TypingRule.FindNamedLCA (\secref{TypingRule.FindNamedLCA}). + +\subsection{TypingRule.Subtype\label{sec:TypingRule.Subtype}} +The \emph{subtype} relation is a partial order over \underline{named types}. +The \emph{supertype} is the inverse relation. That is, \tty\ is a supertype of \tsy\ if and only if \tsy\ is a subtype of \tty. + +\hypertarget{def-subtypesrel}{} +The predicate +\[ + \subtypesrel(\overname{\staticenvs}{\tenv} \aslsep \overname{\ty}{\vtone} \aslsep \overname{\ty}{\vttwo}) + \aslto \overname{\Bool}{\vb} +\] + +\subsubsection{Prose} +One of the following applies: +\begin{itemize} + \item all of the following apply (\textsc{reflexive}): + \begin{itemize} + \item $\vtone$ and $\vttwo$ are both the same named type; + \item $\vb$ is $\True$. + \end{itemize} + + \item all of the following apply (\textsc{transitive}): + \begin{itemize} + \item $\vtone$ is a named type with name $\idone$, that is $\TNamed(\idone)$; + \item $\vttwo$ is a named type with name $\idtwo$, that is $\TNamed(\idtwo)$, such that $\idone$ is different from $\idtwo$; + \item the global static environment maintains that $\idone$ is a subtype of $\idthree$; + \item testing whether the type named $\idthree$ is a subtype of $\vttwo$ in the static environment $\tenv$ + gives $\vb$. + \end{itemize} + + \item all of the following apply (\textsc{no\_supertype}): + \begin{itemize} + \item $\vtone$ is a named type with name $\idone$, that is $\TNamed(\idone)$; + \item $\vttwo$ is a named type with name $\idtwo$, that is $\TNamed(\idtwo)$, such that $\idone$ is different from $\idtwo$; + \item the global static environment maintains that $\idone$ does subtype any named type; + \item $\vb$ is $\False$. + \end{itemize} + + \item all of the following apply (\textsc{not\_named}): + \begin{itemize} + \item at least one of $\vtone$ and $\vttwo$ is not a named type; + \item $\vb$ is $\False$. + \end{itemize} +\end{itemize} +\subsubsection{Example} +In the following example \texttt{subInt} is a subtype of itself and of \texttt{superInt}: +\begin{verbatim} +type superInt of integer; +type subInt of integer subtypes superInt; +\end{verbatim} + +\CodeSubsection{\SubtypeBegin}{\SubtypeEnd}{../types.ml} + +\subsubsection{Formally} +\begin{mathpar} + \inferrule[reflexive]{}{ + \subtypesrel(\tenv, \TNamed(\id), \TNamed(\id)) \typearrow \True + } + \and + \inferrule[transitive]{ + \idone \neq \idtwo\\ + G^\tenv.\subtypes(\idone) = \idthree\\ + \subtypesrel(\tenv, \TNamed(\idthree), \vttwo) \typearrow \vb + }{ + \subtypesrel(\tenv, \TNamed(\idone), \TNamed(\idtwo)) \typearrow \vb + } + \and + \inferrule[no\_supertype]{ + \idone \neq \idtwo\\ + G^\tenv.\subtypes(\idone) = \bot + }{ + \subtypesrel(\tenv, \TNamed(\idone), \TNamed(\idtwo)) \typearrow \False + } + \and + \inferrule[not\_named]{ + (\astlabel(\vtone) \neq \TNamed \lor \astlabel(\vttwo) \neq \TNamed) + }{ + \subtypesrel(\tenv, \vtone, \vttwo) \typearrow \False + } +\end{mathpar} + +\isempty{\subsubsection{Comments}} +\lrmcomment{This is related to \identr{NXRX}, \identi{KGKS}, \identi{MTML}, \identi{JVRM}, \identi{CHMP}.} + +\subsection{TypingRule.SubtypeSatisfaction\label{sec:TypingRule.SubtypeSatisfaction}} +\hypertarget{def-subtypesat} +The predicate +\[ + \subtypesat(\overname{\staticenvs}{\tenv} \aslsep \overname{\ty}{\vt} \aslsep \overname{\ty}{\vs}) + \aslto \overname{\Bool}{\vb} \cup \overname{\TTypeError}{\TypeErrorConfig} +\] +tests whether a type $\vt$ \emph{subtype-satisfies} a type $\vs$ in environment $\tenv$, +returning the result $\vb$ or a type error, if one is detected. +The function assumes that both $\vt$ and $\vs$ are well-typed according to \chapref{Types}. + +\subsection{Prose} +One of the following applies: +\begin{itemize} +\item All of the following apply (\textsc{error1}): + \begin{itemize} + \item obtaining the \underlyingtype\ of $\vt$ gives a type error; + \item the rule results in a type error. + \end{itemize} + +\item All of the following apply (\textsc{error2}): + \begin{itemize} + \item obtaining the \underlyingtype\ of $\vt$ gives a type $\vttwo$; + \item obtaining the \underlyingtype\ of $\vs$ gives a type error; + \item the rule results in a type error. + \end{itemize} + +\item All of the following apply (\textsc{different\_labels}): + \begin{itemize} + \item the underlying types of $\vt$ and $\vs$ have different AST labels + (for example, \texttt{integer} and \texttt{real}); + \item $\vb$ is $\False$. + \end{itemize} + +\item All of the following apply (\textsc{simple}): + \begin{itemize} + \item the \underlyingtype\ of $\vt$, $\vttwo$, is either \texttt{real}, \texttt{string}, or \texttt{bool}; + \item the \underlyingtype\ of $\vs$, $\vstwo$, is either \texttt{real}, \texttt{string}, or \texttt{bool}; + \item $\vb$ is $\True$ if and only if both $\vttwo$ and $\vstwo$ have the same ASL label. + \end{itemize} + +\item All of the following apply (\textsc{t\_int}): + \begin{itemize} + \item the \underlyingtype\ of $\vt$, $\vttwo$, is an \texttt{integer} (any kind); + \item the \underlyingtype\ of $\vs$, $\vstwo$, is an \texttt{integer} (any kind); + \item determining whether $\vs$ subsumes $\vt$ in $\tenv$ via symbolic reasoning results in $\vb$. + \end{itemize} + +\item All of the following apply (\textsc{t\_enum}): + \begin{itemize} + \item the \underlyingtype\ of $\vt$ is an enumeration type with list of labels $\vlit$, that is, $\TEnum(\vlit)$; + \item the \underlyingtype\ of $\vs$ is is an enumeration type with list of labels $\vlis$, that is, $\TEnum(\vlis)$; + \item $\vb$ is $\True$ if and only if $\vlit$ is equal to $\vlis$. + \end{itemize} + +\item All of the following apply (\textsc{t\_bits}): + \begin{itemize} + \item the \underlyingtype\ of $\vs$ is a bitvector type with width $\ws$ and bit fields $\bfss$, that is $\TBits(\ws, \bfss)$; + \item the \underlyingtype\ of $\vt$ is a bitvector type with width $\wt$ and bit fields $\bfst$, that is $\TBits(\wt, \bfst)$; + \item determining whether the bit fields $\bfss$ are included in the bit fields $\bfst$ in $\tenv$ yields $\True$\ProseOrTypeError; + \item determining whether the \symbolicdomain{} of bitwidth $\ws$ subsumes the \symbolicdomain{} of bitwidth $\wt$ in $\tenv$ yields $\vb$. + \end{itemize} + +\item All of the following apply (\textsc{t\_array\_expr}): + \begin{itemize} + \item $\vs$ has the \underlyingtype\ of an array with index $\vlengths$ and element type $\vtys$, that is $\TArray(\vlengths, \vtys)$; + \item $\vt$ has the \underlyingtype\ of an array with index $\vlengtht$ and element type $\vtyt$, that is $\TArray(\vlengtht, \vtyt)$; + \item determining whether $\vtys$ and $\vtyt$ are equivalent in $\tenv$ is either $\True$ + or $\False$, which short-circuits the entire rule with $\vb=\False$; + \item either the AST labels of $\vlengths$ and $\vlengtht$ are the same or the rule short-circuits with $\vb=\False$; + \item $\vlengths$ is an array length expression with $\vlengthexprs$, that is \\ $\ArrayLengthExpr(\vlengthexprs)$; + \item $\vlengtht$ is an array length expression with $\vlengthexprt$, that is \\ $\ArrayLengthExpr(\vlengthexprt)$; + \item determining whether expressions $\vlengthexprs$ and $\vlengthexprt$ are equivalent gives $\vb$. + \end{itemize} + + \item All of the following apply (\textsc{t\_array\_enum}): + \begin{itemize} + \item $\vs$ has the \underlyingtype\ of an array with index $\vlengths$ and element type $\vtys$, that is $\TArray(\vlengths, \vtys)$; + \item $\vt$ has the \underlyingtype\ of an array with index $\vlengtht$ and element type $\vtyt$, that is $\TArray(\vlengtht, \vtyt)$; + \item determining whether $\vtys$ and $\vtyt$ are equivalent in $\tenv$ is either $\True$ + or $\False$, which short-circuits the entire rule with $\vb=\False$; + \item either the AST labels of $\vlengths$ and $\vlengtht$ are the same or the rule short-circuits with $\vb=\False$; + \item $\vlengths$ is an array with indices taken from the enumeration $\vnames$, that is $\ArrayLengthEnum(\vnames, \Ignore)$; + \item $\vlengtht$ is an array with indices taken from the enumeration $\vnamet$, that is $\ArrayLengthEnum(\vnamet, \Ignore)$; + \item $\vb$ is $\True$ if and only if $\vnames$ and $\vnamet$ are the same. + \end{itemize} + +\item All of the following apply (\textsc{t\_tuple}): + \begin{itemize} + \item $\vs$ has the \underlyingtype\ of a tuple with type list $\vlis$, that is $\TTuple(\vlis)$; + \item $\vt$ has the \underlyingtype\ of a tuple with type list $\vlit$, that is $\TTuple(\vlit)$; + \item equating the lengths of $\vlis$ and $\vlit$ is either $\True$ or $\False$, which short-circuits + the entire rule with $\vb=\False$; + \item checking at each index $\vi$ of the list $\vlis$ whether the type $\vlit[\vi]$ \typesatisfies\ the type $\vlis[\vi]$ + yields $\vb_\vi$\ProseOrTypeError; + \item $\vb$ is $\True$ if and only if all $\vb_\vi$ are $\True$; + \end{itemize} + +\item All of the following apply (\textsc{structured}): + \begin{itemize} + \item $\vs$ has the \underlyingtype\ $L(\vfieldss)$, which is a \structuredtype; + \item $\vt$ has the \underlyingtype\ $L(\vfieldst)$, which is a \structuredtype; + \item since both underlying types have the same AST label they are either both record types or both exception types; + \item $\vb$ is $\True$ if and only if for each field in $\vfieldss$ with type $\vtys$ + there exists a field in $\vfieldst$ with type $\vtyt$ such that both $\vtys$ and $\vtyt$ + are determined to be \typeequivalent\ in $\tenv$. + \end{itemize} +\end{itemize} + +\subsection{Formally} +\begin{mathpar} + \inferrule[error1]{ + \makeanonymous(\tenv, \vt) \typearrow \TypeErrorConfig + } + { + \subtypesat(\tenv, \vt, \vs) \typearrow \TypeErrorConfig + } + \and + \inferrule[error2]{ + \makeanonymous(\tenv, \vt) \typearrow \vttwo\\ + \makeanonymous(\tenv, \vs) \typearrow \TypeErrorConfig + } + { + \subtypesat(\tenv, \vt, \vs) \typearrow \TypeErrorConfig + } + \and + \inferrule[different\_labels]{ + \makeanonymous(\tenv, \vt) \typearrow \vttwo\\ + \makeanonymous(\tenv, \vs) \typearrow \vstwo\\ + \astlabel(\vttwo) \neq \astlabel(\vstwo) + } + { + \subtypesat(\tenv, \vt, \vs) \typearrow \False + } +\end{mathpar} + +\begin{mathpar} + \inferrule[simple]{ + \makeanonymous(\tenv, \vt) \typearrow \vttwo\\ + \makeanonymous(\tenv, \vs) \typearrow \vstwo\\ + \astlabel(\vttwo) \in \{\TInt, \TReal, \TString, \TBool\}\\ + \vb \eqdef \astlabel(\vstwo) = \astlabel(\vttwo) + }{ + \subtypesat(\tenv, \vt, \vs) \typearrow \vb + } +\end{mathpar} + +\begin{mathpar} +\inferrule[t\_int]{ + \makeanonymous(\tenv, \vt) \typearrow \vttwo\\ + \makeanonymous(\tenv, \vs) \typearrow \vstwo\\ + \vsstruct = \TInt(\vc)\\ + \symsubsumes(\tenv, \vsstruct, \vtstruct) \typearrow \vb +}{ + \subtypesat(\tenv, \vt, \vs) \typearrow \vb +} +\end{mathpar} + +\begin{mathpar} +\inferrule[t\_enum]{ + \makeanonymous(\tenv, \vt) \typearrow \TEnum(\vlit)\\ + \makeanonymous(\tenv, \vs) \typearrow \TEnum(\vlis)\\ + \vb \eqdef \vlit = \vlis +}{ + \subtypesat(\tenv, \vt, \vs) \typearrow \vb +} +\end{mathpar} + +\begin{mathpar} +\inferrule[t\_bits]{ + \makeanonymous(\tenv, \vs) \typearrow \TBits(\ws, \bfss)\\ + \makeanonymous(\tenv, \vt) \typearrow \TBits(\wt, \bfst)\\ + \bitfieldsincluded(\tenv, \bfss, \bfst) \typearrow \True \OrTypeError \\ + \symdomofwidth(\tenv, \ws) \typearrow \ds \\ + \symdomofwidth(\tenv, \wt) \typearrow \dt \\ + \symdomissubset(\tenv, \ds, \dt) \typearrow \vb +}{ + \subtypesat(\tenv, \vt, \vs) \typearrow \vb +} +\end{mathpar} + +\begin{mathpar} +\inferrule[t\_array\_expr]{ + \makeanonymous(\tenv, \vs) \typearrow \TArray(\vlengths,\vtys) \\ + \makeanonymous(\tenv, \vt) \typearrow \TArray(\vlengtht,\vtyt) \\ + \typeequal(\tenv, \vtys, \vtyt) \typearrow \True \terminateas \False\\ + \booltrans{\astlabel(\vlengths) = \astlabel(\vlengtht)} \booltransarrow \True \terminateas \False\\ + \vlengths \eqname \ArrayLengthExpr(\vlengthexprs)\\ + \vlengtht \eqname \ArrayLengthExpr(\vlengthexprt)\\ + \exprequal(\tenv, \vlengthexprs, \vlengthexprt) \typearrow \vb +}{ + \subtypesat(\tenv, \vt, \vs) \typearrow \vb +} +\and +\inferrule[t\_array\_enum]{ + \makeanonymous(\tenv, \vs) \typearrow \TArray(\vlengths,\vtys) \\ + \makeanonymous(\tenv, \vt) \typearrow \TArray(\vlengtht,\vtyt) \\ + \typeequal(\tenv, \vtys, \vtyt) \typearrow \True\\ + \booltrans{\astlabel(\vlengths) = \astlabel(\vlengtht)} \typearrow \True\\ + \vlengths \eqname \ArrayLengthEnum(\vnames, \Ignore)\\ + \vlengtht \eqname \ArrayLengthEnum(\vnamet, \Ignore)\\ + \vb \eqdef \vnames = \vnamet +}{ + \subtypesat(\tenv, \vt, \vs) \typearrow \vb +} +\end{mathpar} + +\begin{mathpar} +\inferrule[t\_tuple] +{ \makeanonymous(\tenv, \vs) \typearrow\TTuple(\vlis)\\ + \makeanonymous(\tenv, \vt) \typearrow\TTuple(\vlit)\\ + \equallength(\vlis, \vlit) \typearrow\True \terminateas \False\\ + \vi\in\listrange(\vlis): \typesat(\tenv, \vlit[\vi], \vlis[\vi]) \typearrow \vb_i \terminateas \TTypeError\\ + \vb \eqdef \bigwedge_{\vi=1}^k \vb_\vi +}{ + \subtypesat(\tenv, \vt, \vs) \typearrow \vb +} +\end{mathpar} + +\hypertarget{def-fieldnames}{} +For a list of typed fields $\fields$, we define the set of its field identifiers as: +\[ + \fieldnames(\fields) \triangleq \{ \id \;|\; (\id, \vt) \in \fields\} +\] +\hypertarget{def-fieldtype}{} +We define the type associated with the field name $\id$ in a list of typed fields $\fields$, +if there is a unique one, as follows: +\[ + \fieldtype(\fields, \id) \triangleq + \begin{cases} + \vt & \text{ if }\{ \vtp \;|\; (\id,\vtp) \in \fields\} = \{\vt\}\\ + \bot & \text{ otherwise} + \end{cases} +\] + +\begin{mathpar} +\inferrule[structured]{ + L \in \{\TRecord, \TException\}\\ + \makeanonymous(\tenv, \vs)\typearrow L(\vfieldss) \\ + \makeanonymous(\tenv, \vt)\typearrow L(\vfieldst) \\ + \vnamess \eqdef \fieldnames(\vfieldss)\\ + \vnamest \eqdef \fieldnames(\vfieldst)\\ + \booltrans{\vnamess \subseteq \vnamest} \booltransarrow \True \terminateas \False\\ + (\id,\vtys)\in\vfieldss: \typeequal(\tenv, \vtys, \fieldtype(\vfieldst, \id)) \typearrow \vb_\id\\ + \vb \eqdef \bigwedge_{\id \in \vnamess} \vb_\id +}{ + \subtypesat(\tenv, \vs, \vt) \typearrow \vb +} +\end{mathpar} + +\isempty{\subsection{Comments}} +\lrmcomment{This is related to \identd{TRVR}, \identi{SJDC}, \identi{MHYB}, \identi{TWTZ}, \identi{GYSK}, \identi{KXSD}, \identi{KNXJ}.} + +\isempty{\subsection{Example}} + +\CodeSubsection{\SubtypeSatisfactionBegin}{\SubtypeSatisfactionEnd}{../types.ml} + +\subsection{TypingRule.TypeSatisfaction \label{sec:TypingRule.TypeSatisfaction}} +\hypertarget{def-typesatisfies}{} +The predicate +\[ + \typesat(\overname{\staticenvs}{\tenv} \aslsep \overname{\ty}{\vt} \aslsep \overname{\ty}{\vs}) + \aslto \overname{\Bool}{\vb} \cup \overname{\TTypeError}{\TypeErrorConfig} +\] +tests whether a type $\vt$ \emph{\typesatisfies} a type $\vs$ in environment $\tenv$, +returning the result $\vb$ or a type error, if one is detected. + +\hypertarget{def-checktypesat}{} +We also define +\[ + \checktypesat(\overname{\staticenvs}{\tenv} \aslsep \overname{\ty}{\vt} \aslsep \overname{\ty}{\vs}) + \aslto \{\True\} \cup \overname{\TTypeError}{\TypeErrorConfig} +\] +which is the same as $\typesat$, but yields a type error when \\ $\typesat(\tenv, \vt, \vs)$ is $\False$. + +These functions assume that both $\vt$ and $\vs$ are well-typed according to \secref{Types}. + +\subsubsection{Prose} +One of the following applies: + \begin{itemize} + \item All of the following apply (\textsc{subtypes}): + \begin{itemize} + \item $\vt$ subtypes $\vs$ in $\tenv$ ; + \item $\vb$ is $\True$. + \end{itemize} + + \item All of the following apply (\textsc{anonymous}): + \begin{itemize} + \item $\vt$ does not subtype $\vs$ in $\tenv$; + \item at least one of $\vt$ and $\vs$ is an anonymous type in $\tenv$; + \item determining whether $\vt$ \subtypesatisfies\ $\vs$ in $\tenv$ yields $\True$\ProseOrTypeError; + \item $\vb$ is $\True$. + \end{itemize} + + \item All of the following apply (\textsc{t\_bits}): + \begin{itemize} + \item $\vt$ does not subtype $\vs$ in $\tenv$; + \item determining whether $\vt$ is anonymous yields $\vbone$; + \item determining whether $\vs$ is anonymous yields $\vbtwo$; + \item determining whether $\vt$ \subtypesatisfies\ $\vs$ in $\tenv$ yields $\vbthree$; + \item $(\vbone \lor \vbtwo) \land \vbthree$ is $\False$; + \item $\vt$ is a bitvector type with width $\widtht$ and no bitfields; + \item obtaining the \structure\ of $\vs$ in $\tenv$ yields a bitvector type with width \\ + $\widths$\ProseOrTypeError; + \item determining whether $\widtht$ and $\widths$ are \bitwidthequivalent\ yields $\vb$. + \end{itemize} + + \item All of the following apply (\textsc{otherwise1}): + \begin{itemize} + \item $\vt$ does not subtype $\vs$ in $\tenv$; + \item determining whether $\vt$ is anonymous yields $\vbone$; + \item determining whether $\vs$ is anonymous yields $\vbtwo$; + \item determining whether $\vt$ \subtypesatisfies\ $\vs$ in $\tenv$ yields $\vbthree$; + \item $(\vbone \lor \vbtwo) \land \vbthree$ is $\False$; + \item obtaining the \structure\ of $\vs$ in $\tenv$ yields a $\vsstruct$\ProseOrTypeError; + \item at least one of $\vt$ and $\vsstruct$ is not a bitvector type; + \end{itemize} + + \item All of the following apply (\textsc{otherwise2}): + \begin{itemize} + \item $\vt$ does not subtype $\vs$ in $\tenv$; + \item determining whether $\vt$ is anonymous yields $\vbone$; + \item determining whether $\vs$ is anonymous yields $\vbtwo$; + \item determining whether $\vt$ \subtypesatisfies\ $\vs$ in $\tenv$ yields $\vbthree$; + \item $(\vbone \lor \vbtwo) \land \vbthree$ is $\False$; + \item obtaining the \structure\ of $\vs$ in $\tenv$ yields a $\vsstruct$\ProseOrTypeError; + \item both $\vt$ and $\vsstruct$ are bitvector types; + \item the bitvector type $\vt$ has a non-empty list of bitfields; + \item $\vb$ is $\False$; + \end{itemize} +\end{itemize} + +\subsubsection{Example} +In the specification: +\VerbatimInput{../tests/ASLTypingReference.t/TypingRule.TypeSatisfaction1.asl} +\texttt{var pair: pairT = (1, dataT1)} is legal since the right-hand-side has +anonymous, non-primitive type \texttt{(integer, T1)}. + +\subsubsection{Example} +In the specification: +\VerbatimInput{../tests/ASLTypingReference.t/TypingRule.TypeSatisfaction2.asl} +\texttt{pair = (1, dataAsInt);} is legal since the right-hand-side has anonymous, +primitive type \texttt{(integer, integer)}. + +\subsubsection{Example} +In the specification: +\VerbatimInput{../tests/ASLTypingReference.t/TypingRule.TypeSatisfaction3.asl} +\texttt{pair = (1, dataT2);} is illegal since the right-hand-side has anonymous, +non-primitive type \texttt{(integer, T2)} which does not subtype-satisfy named +type \texttt{pairT}. + +\CodeSubsection{\TypeSatisfactionBegin}{\TypeSatisfactionEnd}{../types.ml} + +\subsubsection{Formally} +\begin{mathpar} +\inferrule[subtypes]{ + \subtypesrel(\tenv, \vt, \vs) \typearrow \True +}{ + \typesat(\tenv, \vt, \vs) \typearrow \True +} +\end{mathpar} + +\begin{mathpar} +\inferrule[anonymous]{ + \subtypesrel(\tenv, \vt, \vs) \typearrow \False\\ + \isanonymous(\tenv, \vt) \typearrow \vbone\\ + \isanonymous(\tenv, \vs) \typearrow \vbtwo\\ + \vbone \lor \vbtwo\\ + \subtypesat(\tenv, \vt, \vs) \typearrow \True +}{ + \typesat(\tenv, \vt, \vs) \typearrow \True +} +\end{mathpar} + +\begin{mathpar} +\inferrule[t\_bits]{ + \subtypesrel(\tenv, \vt, \vs) \typearrow \False\\ + \isanonymous(\tenv, \vt) \typearrow \vbone\\ + \isanonymous(\tenv, \vs) \typearrow \vbtwo\\ + \subtypesat(\tenv, \vt, \vs) \typearrow \vbthree\\ + \neg((\vbone \lor \vbtwo) \land \vbthree)\\ + \vt \eqname \TBits(\widtht, \emptylist)\\ + \tstruct(\tenv, \vs) \typearrow \TBits(\widths, \Ignore) \OrTypeError\\\\ + \bitwidthequal(\tenv, \widtht, \widths) \typearrow \vb +}{ + \typesat(\tenv, \vt, \vs) \typearrow \vb +} +\end{mathpar} + +\begin{mathpar} +\inferrule[otherwise1]{ + \subtypesrel(\tenv, \vt, \vs) \typearrow \False\\ + \isanonymous(\tenv, \vt) \typearrow \vbone\\ + \isanonymous(\tenv, \vs) \typearrow \vbtwo\\ + \subtypesat(\tenv, \vt, \vs) \typearrow \vbthree\\ + \neg((\vbone \lor \vbtwo) \land \vbthree)\\ + \tstruct(\tenv, \vs) \typearrow \vsstruct\\ + \astlabel(\vt) \neq \TBits \lor \astlabel(\vsstruct) \neq \TBits +}{ + \typesat(\tenv, \vt, \vs) \typearrow \overname{\False}{\vb} +} +\end{mathpar} + +\begin{mathpar} +\inferrule[otherwise2]{ + \subtypesrel(\tenv, \vt, \vs) \typearrow \False\\ + \isanonymous(\tenv, \vt) \typearrow \vbone\\ + \isanonymous(\tenv, \vs) \typearrow \vbtwo\\ + \subtypesat(\tenv, \vt, \vs) \typearrow \vbthree\\ + \neg((\vbone \lor \vbtwo) \land \vbthree)\\ + \tstruct(\tenv, \vs) \typearrow \vsstruct\\ + \astlabel(\vt) = \TBits \land \astlabel(\vsstruct) = \TBits\\ + \vt \eqname \TBits(\widtht, \bitfields)\\ + \bitfields \neq \emptylist +}{ + \typesat(\tenv, \vt, \vs) \typearrow \overname{\False}{\vb} +} +\end{mathpar} + +The rules for the checked type-satisfy predicate are: +\begin{mathpar} +\inferrule[true]{ + \typesat(\tenv, \vt, \vs) \typearrow \True \OrTypeError\\ +}{ + \checktypesat(\tenv, \vt, \vs) \typearrow \True +} +\end{mathpar} + +\begin{mathpar} +\inferrule[error]{ + \typesat(\tenv, \vt, \vs) \typearrow \False +}{ + \checktypesat(\tenv, \vt, \vs) \typearrow \TypeErrorVal{TypeConflict} +} +\end{mathpar} + +\subsubsection{Comments} +Since the subtype relation is a partial order, it is reflexive. Therefore +every type $\vt$ is a subtype of itself, and as a consequence, every type $\vt$ +\typesatisfies\ itself. + +\lrmcomment{This is related to \identr{FMXK} and \identi{NLFD}.} + +\subsection{TypingRule.TypeClash\label{sec:TypingRule.TypeClash}} +\hypertarget{def-typeclashes}{} +The predicate +\[ + \typeclashes(\overname{\staticenvs}{\tenv} \aslsep \overname{\ty}{\vt} \aslsep \overname{\ty}{\vs}) + \aslto \overname{\Bool}{\vb} \cup \overname{\TTypeError}{\TypeErrorConfig} +\] +tests whether a type $\vt$ \emph{type-clashes} with a type $\vs$ in environment $\tenv$, +returning the result $\vb$ or a type error, if one is detected. + +\subsubsection{Prose} + One of the following applies: +\begin{itemize} + \item All of the following apply (\textsc{subtype}): + \begin{itemize} + \item either $\vs$ subtypes $\vt$ or $\vt$ subtypes $\vs$; + \item $\vb$ is $\True$. + \end{itemize} + + \item All of the following apply (\textsc{simple}): + \begin{itemize} + \item neither $\vs$ subtypes $\vt$ nor $\vt$ subtypes $\vs$; + \item obtaining the \structure\ of $\vt$ in $\tenv$ yields $\vtstruct$\ProseOrTypeError; + \item obtaining the \structure\ of $\vs$ in $\tenv$ yields $\vsstruct$\ProseOrTypeError; + \item both $\vtstruct$ and $\vsstruct$ are one of the following types: \\ \texttt{integer}, \texttt{real}, \texttt{string}; + \item $\vb$ is $\True$. + \end{itemize} + + \item All of the following apply (\textsc{t\_enum}): + \begin{itemize} + \item neither $\vs$ subtypes $\vt$ nor $\vt$ subtypes $\vs$; + \item obtaining the \structure\ of $\vt$ in $\tenv$ yields an enumeration type with labels $\vlit$; + \item obtaining the \structure\ of $\vs$ in $\tenv$ yields an enumeration type with labels $\vlis$; + \item $\vb$ is $\True$ if and only if $\vlis$ and $\vlit$ are equal. + \end{itemize} + + \item All of the following apply (\textsc{t\_array}): + \begin{itemize} + \item neither $\vs$ subtypes $\vt$ nor $\vt$ subtypes $\vs$; + \item obtaining the \structure\ of $\vt$ in $\tenv$ yields an array type with element type $\vtyt$; + \item obtaining the \structure\ of $\vs$ in $\tenv$ yields an array type with element type $\vtys$; + \item $\vb$ is $\True$ if and only if $\vtyt$ and $\vtys$ type-clash. + \end{itemize} + + \item All of the following apply (\textsc{t\_tuple}): + \begin{itemize} + \item neither $\vs$ subtypes $\vt$ nor $\vt$ subtypes $\vs$; + \item obtaining the \structure\ of $\vt$ in $\tenv$ yields a tuple type with element types $\vt_{1..k}$; + \item obtaining the \structure\ of $\vs$ in $\tenv$ yields a tuple type with element types $\vs_{1..n}$; + \item if $n \neq k$ the rule short-circuits with $\vb=\False$; + \item $\vb$ is $\True$ if and only if $\vt_i$ type-clashes with $\vs_i$, for all $i=1..k$. + \end{itemize} + + \item All of the following apply (\textsc{otherwise\_different\_labels}): + \begin{itemize} + \item neither $\vs$ subtypes $\vt$ nor $\vt$ subtypes $\vs$; + \item obtaining the \structure\ of $\vt$ in $\tenv$ yields $\vtstruct$; + \item obtaining the \structure\ of $\vs$ in $\tenv$ yields $\vsstruct$; + \item $\vsstruct$ and $\vtstruct$ have different AST labels; + \item $\vb$ is $\False$; + \end{itemize} + + \item All of the following apply (\textsc{otherwise\_structured}): + \begin{itemize} + \item neither $\vs$ subtypes $\vt$ nor $\vt$ subtypes $\vs$; + \item obtaining the \structure\ of $\vt$ in $\tenv$ yields $\vtstruct$; + \item obtaining the \structure\ of $\vs$ in $\tenv$ yields $\vsstruct$; + \item $\vsstruct$ and $\vtstruct$ have the same AST label; + \item $\vtstruct$ (and thus $\vsstruct$) is a \structuredtype; + \item $\vb$ is $\False$; + \end{itemize} +\end{itemize} + +\isempty{\subsubsection{Example}} + +\CodeSubsection{\TypeClashBegin}{\TypeClashEnd}{../types.ml} + +\subsubsection{Formally} +\begin{mathpar} +\inferrule[subtype]{ + (\subtypesrel(\tenv, \vs, \vt) \typearrow \True) \lor (\subtypesrel(\tenv, \vt, \vs) \typearrow \True) +}{ + \typeclashes(\tenv, \vt, \vs) \typearrow \overname{\True}{\vb} +} +\end{mathpar} + +\begin{mathpar} +\inferrule[simple]{ + \subtypesrel(\tenv, \vs, \vt) \typearrow \False\\ + \subtypesrel(\tenv, \vt, \vs) \typearrow \False\\\\ + \tstruct(\tenv, \vt) \typearrow \vtstruct \OrTypeError \\ + \tstruct(\tenv, \vs) \typearrow \vsstruct \OrTypeError \\ + \astlabel(\vtstruct)=\astlabel(\vsstruct)\\ + \astlabel(\vtstruct) \in \{\TInt, \TReal, \TString, \TBits\} +}{ + \typeclashes(\tenv, \vt, \vs) \typearrow \overname{\True}{\vb} +} +\end{mathpar} + +\begin{mathpar} +\inferrule[t\_enum]{ + \subtypesrel(\tenv, \vs, \vt) \typearrow \False\\ + \subtypesrel(\tenv, \vt, \vs) \typearrow \False\\\\ + \tstruct(\tenv, \vt) \typearrow \TEnum(\Ignore, \vlis) \\ + \tstruct(\tenv, \vs) \typearrow \TEnum(\Ignore, \vlit) +}{ + \typeclashes(\tenv, \vt, \vs) \typearrow \overname{\vlis = \vlit}{\vb} +} +\end{mathpar} + +\begin{mathpar} +\inferrule[t\_array]{ + \subtypesrel(\tenv, \vs, \vt) \typearrow \False\\ + \subtypesrel(\tenv, \vt, \vs) \typearrow \False\\\\ + \tstruct(\tenv, \vt) \typearrow \TArray(\Ignore, \vtyt) \\ + \tstruct(\tenv, \vs) \typearrow \TArray(\Ignore, \vtys) \\ + \typeclashes(\tenv, \vtyt, \vtys) \typearrow \vb +}{ + \typeclashes(\tenv, \vt, \vs) \typearrow \vb +} +\end{mathpar} + +\begin{mathpar} +\inferrule[t\_tuple]{ + \subtypesrel(\tenv, \vs, \vt) \typearrow \False\\ + \subtypesrel(\tenv, \vt, \vs) \typearrow \False\\\\ + \tstruct(\tenv, \vt) \typearrow \TTuple(\vt_{1..k}) \\ + \tstruct(\tenv, \vs) \typearrow \TTuple(\vs_{1..n}) \\ + \booltrans{n = k} \booltransarrow \True \terminateas \False\\ + i=1..k: \typeclashes(\tenv, \vt_i, \vs_i) \typearrow \vb_i\\ + \vb \eqdef \bigwedge_{\vi=1}^k \vb_i +}{ + \typeclashes(\tenv, \vt, \vs) \typearrow \vb +} +\end{mathpar} + +\begin{mathpar} +\inferrule[otherwise\_different\_labels]{ + \subtypesrel(\tenv, \vs, \vt) \typearrow \False\\ + \subtypesrel(\tenv, \vt, \vs) \typearrow \False\\\\ + \tstruct(\tenv, \vt) \typearrow \vtstruct \\ + \tstruct(\tenv, \vs) \typearrow \vsstruct \\ + \astlabel(\vtstruct) \neq \astlabel(\vsstruct) +}{ + \typeclashes(\tenv, \vt, \vs) \typearrow \overname{\False}{\vb} +} +\end{mathpar} + +\begin{mathpar} +\inferrule[otherwise\_structured]{ + \subtypesrel(\tenv, \vs, \vt) \typearrow \False\\ + \subtypesrel(\tenv, \vt, \vs) \typearrow \False\\\\ + \tstruct(\tenv, \vt) \typearrow \vtstruct \\ + \tstruct(\tenv, \vs) \typearrow \vsstruct \\ + \astlabel(\vtstruct) = \astlabel(\vsstruct)\\ + \vb \eqdef \astlabel(\vtstruct) \in \{\TRecord, \TException\}\\ +}{ + \typeclashes(\tenv, \vt, \vs) \typearrow \overname{\False}{\vb} +} +\end{mathpar} + +\subsubsection{Comments} +Note that if $\vt$ subtype-satisfies $\vs$ then $\vt$ and $\vs$ type-clash, but not the other +way around. + +Note that type-clashing is an equivalence relation. Therefore if $\vt$ +type-clashes with \texttt{A} and \texttt{B} then it is also the case that \texttt{A} and \texttt{B} type-clash. + +\lrmcomment{This is related to \identd{VPZZ}, \identi{PQCT} and \identi{WZKM}.} + +\subsection{TypingRule.LowestCommonAncestor \label{sec:TypingRule.LowestCommonAncestor}} +\hypertarget{def-lowestcommonancestor}{} +Annotating a conditional expression (see \secref{TypingRule.ECond}), +requires finding a single type that can be used to annotate the results of both subexpressions. +The function +\[ + \lca(\overname{\staticenvs}{\tenv} \aslsep \overname{\ty}{\vt} \aslsep \overname{\ty}{\vs}) + \aslto \overname{\ty}{\tty} \cup \overname{\TTypeError}{\TypeErrorConfig} +\] +returns the \emph{lowest common ancestor} of types $\vt$ and $\vs$ in $\tenv$ --- $\tty$. +The result is a type error if a lowest common ancestor does not exist or a type error is detected. + +\subsubsection{Prose} +One of the following applies: +\begin{itemize} + \item All of the following apply (\textsc{type\_equal}): + \begin{itemize} + \item $\vt$ is \typeequal\ to $\vs$ in $\tenv$; + \item $\tty$ is $\vs$ (can as well be $\vt$). + \end{itemize} + + \item All of the following apply: + \begin{itemize} + \item $\vt$ is not \typeequal\ to $\vs$ in $\tenv$ and one of the following applies: + + \item All of the following apply (\textsc{named\_subtype1}): + \begin{itemize} + \item $\vt$ is a named type with identifier $\namesubt$, that is, $\TNamed(\namesubt)$; + \item $\vs$ is a named type with identifier $\namesubs$, that is, $\TNamed(\namesubs)$; + \item there is no \namedlowestcommonancestor\ of $\namesubs$ and $\namesubt$ in $\tenv$; + \item obtaining the \underlyingtype\ of $\vs$ yields $\vanons$\ProseOrTypeError; + \item obtaining the \underlyingtype\ of $\vt$ yields $\vanont$\ProseOrTypeError; + \item obtaining the lowest common ancestor of $\vanons$ and $\vanont$ in $\tenv$ yields $\tty$\ProseOrTypeError. + \end{itemize} + + \item All of the following apply (\textsc{named\_subtype2}): + \begin{itemize} + \item $\vt$ is a named type with identifier $\namesubt$, that is, $\TNamed(\namesubt)$; + \item $\vs$ is a named type with identifier $\namesubs$, that is, $\TNamed(\namesubs)$; + \item the \namedlowestcommonancestor\ of $\namesubs$ and $\namesubt$ in $\tenv$ is \\ + $\name$\ProseOrTypeError; + \item $\tty$ is the named type with identifier $\name$, that is, $\TNamed(\name)$. + \end{itemize} + + \item All of the following apply (\textsc{one\_named1}): + \begin{itemize} + \item only one of $\vt$ or $\vs$ is a named type; + \item obtaining the \underlyingtype\ of $\vs$ yields $\vanons$\ProseOrTypeError; + \item obtaining the \underlyingtype\ of $\vt$ yields $\vanont$\ProseOrTypeError; + \item $\vanont$ is \typeequal\ to $\vanons$; + \item $\tty$ is $\vt$ if it is a named type (that is, $\astlabel(\vt)=\TNamed$), and $\vs$ otherwise. + \end{itemize} + + \item All of the following apply (\textsc{one\_named2}): + \begin{itemize} + \item only one of $\vt$ or $\vs$ is a named type; + \item obtaining the \underlyingtype\ of $\vs$ yields $\vanons$\ProseOrTypeError; + \item obtaining the \underlyingtype\ of $\vt$ yields $\vanont$\ProseOrTypeError; + \item $\vanont$ is not \typeequal\ to $\vanons$; + \item the lowest common ancestor of $\vanont$ and $\vanons$ in $\tenv$ is $\tty$\ProseOrTypeError. + \end{itemize} + + \item All of the following apply (\textsc{t\_int\_unconstrained}): + \begin{itemize} + \item both $\vt$ and $\vs$ are integer types; + \item at least one of $\vt$ or $\vs$ is an unconstrained integer type; + \item $\tty$ is the unconstrained integer type. + \end{itemize} + + \item All of the following apply (\textsc{t\_int\_parameterized}): + \begin{itemize} + \item neither $\vt$ nor $\vs$ are the unconstrained integer type; + \item one of $\vt$ and $\vs$ is a \parameterizedintegertype; + \item the \wellconstrainedversion\ of $\vt$ is $\vtone$; + \item the \wellconstrainedversion\ of $\vs$ is $\vsone$; + \item $\tty$ the lowest common ancestor of $\vtone$ and $\vsone$ in $\tenv$ is $\tty$\ProseOrTypeError. + \end{itemize} + + \item All of the following apply (\textsc{t\_int\_wellconstrained}): + \begin{itemize} + \item $\vt$ is a well-constrained integer type with constraints $\cst$; + \item $\vs$ is a well-constrained integer type with constraints $\css$; + \item $\tty$ is the well-constrained integer type with constraints $\cst \concat \css$. + \end{itemize} + + \item All of the following apply (\textsc{t\_bits}): + \begin{itemize} + \item $\vt$ is a bitvector type with with length expression $\vet$, that is, $\TBits(\vet, \Ignore)$; + \item $\vs$ is a bitvector type with with length expression $\ves$, that is, $\TBits(\ves, \Ignore)$; + \item applying $\typeequal$ to $\vt$ and $\vs$ in $\tenv$ yields $\False$; + \item applying $\exprequal$ to $\vet$ and $\ves$ in $\tenv$ yields $\vbequal$; + \item checking whether $\vbequal$ is $\True$ yields $\True$\ProseTerminateAs{\NoLCA}; + \item $\tty$ is a bitvector type with length expression $\vet$ and an empty bitfield list, that is, $\TBits(\vet, \emptylist)$. + \end{itemize} + + \item All of the following apply (\textsc{t\_array}): + \begin{itemize} + \item $\vt$ is an array type with width expression $\widtht$ and element type $\vtyt$; + \item $\vs$ is an array type with width expression $\widths$ and element type $\vtys$; + \item applying $\arraylengthequal$ to $\widtht$ and $\widths$ in $\tenv$ to equate the array lengths, + yields $\vbequallength$\ProseOrTypeError; + \item checking that $\vbequallength$ is $\True$ yields $\True$\ProseTerminateAs{\NoLCA}; + \item the lowest common ancestor of $\vtyt$ and $\vtys$ is $\vtone$\ProseOrTypeError; + \item $\tty$ is an array type with width expression $\widths$ and element type $\vtone$. + \end{itemize} + + \item All of the following apply (\textsc{t\_tuple}): + \begin{itemize} + \item $\vt$ is a tuple type with type list $\vlit$; + \item $\vs$ is a tuple type with type list $\vlis$; + \item checking whether $\vlit$ and $\vlis$ have the same number of elements yields $\True$ + or a type error, which short-circuits the entire rule (indicating that the number of elements in both tuples is expected + to be the same and thus there is no lowest common ancestor); + \item applying $\lca$ to $\vlit[\vi]$ and $\vlis[\vi]$ in $\tenv$, for every position of $\vlit$, + yields $\vt_\vi$\ProseOrTypeError; + \item define $\vli$ to be the list of types $\vt_\vi$, for every position of $\vlit$; + \item define $\tty$ as the tuple type with list of types $\vli$, that is, $\TTuple(\vli)$. + \end{itemize} + + \item All of the following apply (\textsc{error}): + \begin{itemize} + \item either the AST labels of $\vt$ and $\vs$ are different, or one of them is $\TEnum$, $\TRecord$, or $\TException$; + \item the result is a type error indicating the lack of a lowest common ancestor. + \end{itemize} + \end{itemize} +\end{itemize} + +\isempty{\subsubsection{Example}} + +\CodeSubsection{\LowestCommonAncestorBegin}{\LowestCommonAncestorEnd}{../types.ml} + +\subsubsection{Formally} +Since we do not impose a canonical representation on types (e.g., \verb|integer {1, 2}| is equivalence to \verb|integer {1..2}|), +the lowest common ancestor is not unique. +We define $\lca(\tenv, \vt, \vs)$ to be any type $\vtp$ that is \typeequivalent\ to the lowest common ancestor of $\vt$ and $\vs$. + +\begin{mathpar} +\inferrule[type\_equal]{ + \typeequal(\tenv, \vt, \vs) \typearrow \True +}{ + \lca(\tenv, \vt, \vs) \typearrow \overname{\vs}{\tty} +} +\end{mathpar} + +\begin{mathpar} +\inferrule[named\_subtype1]{ + \vt = \TNamed(\namesubs)\\ + \vs = \TNamed(\namesubt)\\ + \typeequal(\tenv, \vt, \vs) \typearrow \False\\ + \namedlca(\tenv, \namesubs, \namesubt) \typearrow \None \OrTypeError\\\\ + \makeanonymous(\tenv, \vs) \typearrow \vanons \OrTypeError\\\\ + \makeanonymous(\tenv, \vt) \typearrow \vanont \OrTypeError\\\\ + \lca(\tenv, \vanont, \vanons) \typearrow \tty \OrTypeError +}{ + \lca(\tenv, \vt, \vs) \typearrow \tty +} +\end{mathpar} + +\begin{mathpar} +\inferrule[named\_subtype2]{ + \vt = \TNamed(\namesubs)\\ + \vs = \TNamed(\namesubt)\\ + \typeequal(\tenv, \vt, \vs) \typearrow \False\\ + \namedlca(\tenv, \namesubs, \namesubt) \typearrow \langle\name\rangle \OrTypeError\\ +}{ + \lca(\tenv, \vt, \vs) \typearrow \overname{\TNamed(\name)}{\tty} +} +\end{mathpar} + +\begin{mathpar} +\inferrule[one\_named1]{ + \typeequal(\tenv, \vt, \vs) \typearrow \False\\ + (\astlabel(\vt) = \TNamed \lor \astlabel(\vs) = \TNamed)\\ + \astlabel(\vt) \neq \astlabel(\vs)\\ + \makeanonymous(\tenv, \vs) \typearrow \vanons \OrTypeError\\\\ + \makeanonymous(\tenv, \vt) \typearrow \vanont \OrTypeError\\\\ + \typeequal(\tenv, \vanont, \vanons) \typearrow \True\\ + \tty \eqdef \choice{\astlabel(\vt) = \TNamed}{\vt}{\vs} +}{ + \lca(\tenv, \vt, \vs) \typearrow \tty +} +\end{mathpar} + +\begin{mathpar} +\inferrule[one\_named2]{ + \typeequal(\tenv, \vt, \vs) \typearrow \False\\ + (\astlabel(\vt) = \TNamed \lor \astlabel(\vs) = \TNamed)\\ + \astlabel(\vt) \neq \astlabel(\vs)\\ + \makeanonymous(\tenv, \vs) \typearrow \vanons \OrTypeError\\\\ + \makeanonymous(\tenv, \vt) \typearrow \vanont \OrTypeError\\\\ + \typeequal(\tenv, \vanont, \vanons) \typearrow \False\\ + \lca(\tenv, \vanont, \vanons) \typearrow \tty \OrTypeError +}{ + \lca(\tenv, \vt, \vs) \typearrow \tty +} +\end{mathpar} + +\begin{mathpar} +\inferrule[t\_int\_unconstrained]{ + \typeequal(\tenv, \vt, \vs) \typearrow \False\\ + \astlabel(\vt) = \astlabel(\vs) = \TInt\\ + \isunconstrainedinteger(\vt) \lor \isunconstrainedinteger(\vs) +}{ + \lca(\tenv, \vt, \vs) \typearrow \overname{\unconstrainedinteger}{\tty} +} +\and +\inferrule[t\_int\_parameterized]{ + \typeequal(\tenv, \vt, \vs) \typearrow \False\\ + \astlabel(\vt) = \astlabel(\vs) = \TInt\\ + \neg\isunconstrainedinteger(\vt)\\ + \neg\isunconstrainedinteger(\vs)\\ + \isparameterizedinteger(\vt) \lor \isparameterizedinteger(\vs)\\ + \towellconstrained(\tenv, \vt) \typearrow \vtone\\ + \towellconstrained(\tenv, \vs) \typearrow \vsone\\ + \lca(\tenv, \vtone, \vsone) \typearrow \tty \OrTypeError +}{ + \lca(\tenv, \vt, \vs) \typearrow \tty +} +\and +\inferrule[t\_int\_wellconstrained] +{ + \typeequal(\tenv, \vt, \vs) \typearrow \False\\ + \vt \eqname \TInt(\wellconstrained(\cst))\\ + \vs \eqname \TInt(\wellconstrained(\css)) +}{ + \lca(\tenv, \vt, \vs) \typearrow \overname{\TInt(\wellconstrained(\cst \concat \css))}{\tty} +} +\end{mathpar} + +\begin{mathpar} +\inferrule[t\_bits]{ + \typeequal(\tenv, \vt, \vs) \typearrow \False\\ + \exprequal(\tenv, \vet, \ves) \typearrow \vbequal\\ + \checktrans{\vbequal}{\NoLCA} \checktransarrow \True \OrTypeError +}{ + \lca(\tenv, \overname{\TBits(\vet, \Ignore)}{\vt}, \overname{\TBits(\ves, \Ignore)}{\vs}) \typearrow \overname{\TBits(\vet, \emptylist)}{\tty} +} +\end{mathpar} + +\begin{mathpar} +\inferrule[t\_array]{ + \typeequal(\tenv, \vt, \vs) \typearrow \False\\ + \arraylengthequal(\tenv, \widtht, \widths) \typearrow \vbequallength \OrTypeError\\\\ + \checktrans{\vbequallength}{\NoLCA} \checktransarrow \True \OrTypeError\\\\ + \lca(\tenv, \vtyt, \vtys) \typearrow \vtone \OrTypeError +}{ + { + \begin{array}{r} + \lca(\tenv, \overname{\TArray(\widtht, \vtyt)}{\vt}, \overname{\TArray(\widths, \vtys)}{\vs}) \typearrow \\ + \overname{\TArray(\widtht, \vtone)}{\tty} + \end{array} + } +} +\end{mathpar} + +\begin{mathpar} +\inferrule[t\_tuple]{ + \typeequal(\tenv, \vt, \vs) \typearrow \False\\ + \equallength(\vlit, \vlis) \typearrow \vb\\ + \checktrans{\vb}{\NoLCA} \typearrow \True \OrTypeError\\\\ + { + \begin{array}{r} + \vi\in\listrange(\vlit): \lca(\tenv, \vlit[\vi], \vlis[\vi]) \typearrow \\ + \vt_\vi \OrTypeError + \end{array} + }\\ + \vli \eqdef [\vi\in\listrange(\vlit): \vt_\vi] +}{ + \lca(\tenv, \overname{\TTuple(\vlit)}{\vt}, \overname{\TTuple(\vlis)}{\vs}) \typearrow \overname{\TTuple(\vli)}{\tty} +} +\end{mathpar} + +\begin{mathpar} +\inferrule[error]{ + \typeequal(\tenv, \vt, \vs) \typearrow \False\\ + (\astlabel(\vt) \neq \astlabel(\vs)) \lor + \astlabel(\vt) \in \{\TEnum, \TRecord, \TException\} +}{ + \lca(\tenv, \vt, \vs) \typearrow \TypeErrorVal{\NoLCA} +} +\end{mathpar} + +\isempty{\subsubsection{Comments}} +\lrmcomment{This is related to \identr{YZHM}.} + +\subsection{TypingRule.CheckUnop \label{sec:TypingRule.CheckUnop}} +\hypertarget{def-checkunop}{} +The function +\[ + \CheckUnop(\overname{\staticenvs}{\tenv} \aslsep \overname{\unop}{\op} \aslsep \overname{\ty}{\vt}) + \aslto \overname{\ty}{\vs} \cup \overname{\TTypeError}{\TypeErrorConfig} +\] +determines the result type of applying a unary operator when the type of its operand is known. +Similarly, we determine the negation of integer constraints. +\ProseOtherwiseTypeError + +\subsubsection{Prose} +One of the following applies: +\begin{itemize} +\item All of the following apply (\textsc{bnot\_t\_bool}): + \begin{itemize} + \item $\op$ is $\BNOT$; + \item determining whether $\vt$ \typesatisfies\ $\TBool$ yields $\True$\ProseOrTypeError; + \item $\vs$ is $\TBool$; + \end{itemize} + +\item All of the following apply (\textsc{neg\_error}): +\begin{itemize} + \item $\op$ is $\NEG$; + \item determining whether $\vt$ \typesatisfies\ $\TReal$ yields $\False$\ProseOrTypeError; + \item determining whether $\vt$ \typesatisfies\ $\unconstrainedinteger$ yields $\False$\ProseOrTypeError; + \item the result is a type error indicating the $\NEG$ is appropriate only for \texttt{real} and \texttt{integer} types; +\end{itemize} + +\item All of the following apply (\textsc{neg\_t\_real}): +\begin{itemize} + \item $\op$ is $\NEG$; + \item determining whether $\vt$ \typesatisfies\ $\TReal$ yields $\True$; + \item $\vs$ is $\TReal$; +\end{itemize} + +\item All of the following apply (\textsc{neg\_t\_int\_unconstrained}): +\begin{itemize} + \item $\op$ is $\NEG$; + \item obtaining the \wellconstrainedstructure\ of $\vt$ yields $\unconstrainedinteger$\ProseOrTypeError; + \item $\vs$ is $\unconstrainedinteger$; +\end{itemize} + +\item All of the following apply (\textsc{neg\_t\_int\_well\_constrained}): +\begin{itemize} + \item $\op$ is $\NEG$; + \item obtaining the \wellconstrainedstructure\ of $\vt$ yields the well-constrained integer type with constraints $\vcs$\ProseOrTypeError; + \item negating the constraints in $\vcs$ (see $\negateconstraint$) yields $\vcsnew$; + \item $\vs$ is the well-constrained integer type with constraints $\vcsnew$, that is, \\ + $\TInt(\wellconstrained(\vcsnew))$; +\end{itemize} + +\item All of the following apply (\textsc{not\_t\_bits}): + \begin{itemize} + \item $\op$ is $\NOT$; + \item $\vt$ has the structure of a bitvector; + \item $\vs$ is $\vt$. + \end{itemize} +\end{itemize} + +\isempty{\subsubsection{Example}} + +\CodeSubsection{\CheckUnopBegin}{\CheckUnopEnd}{../Typing.ml} + +\subsubsection{Formally} +\begin{mathpar} +\inferrule[bnot\_t\_bool]{ + \checktypesat(\tenv, \vtone, \TBool) \typearrow \True \OrTypeError\\ +}{ + \CheckUnop(\tenv, \BNOT, \vtone) \typearrow \TBool +} +\end{mathpar} + +\hypertarget{def-negateconstraint}{} +We now define the helper function +\[ + \negateconstraint(\intconstraint) \aslto \intconstraint +\] +which takes an integer constraint and returns the constraint that corresponds to the negation of all +the values it represents: + +\begin{mathpar} +\inferrule{} +{ + \negateconstraint(\ConstraintExact(\ve)) \typearrow \ConstraintExact(\EUnop(\MINUS, \ve)) +} +\and +\inferrule{} +{ + \negateconstraint(\ConstraintRange(\vvtop, \vbot)) \typearrow \\ + \ConstraintRange(\EUnop(\MINUS, \vbot), \EUnop(\MINUS, \vvtop)) +} +\end{mathpar} + +\begin{mathpar} +\inferrule[neg\_error]{ + \typesat(\tenv, \vt, \unconstrainedinteger) \typearrow \False \OrTypeError\\\\ + \typesat(\tenv, \vt, \TReal) \typearrow \False \OrTypeError\\ +}{ + \CheckUnop(\tenv, \overname{\NEG}{\op}, \vt) \typearrow \TypeErrorVal{InappropriateTypeForNeg} +} +\end{mathpar} + +\begin{mathpar} +\inferrule[neg\_t\_real]{ + \typesat(\tenv, \vt, \TReal) \typearrow \True +}{ + \CheckUnop(\tenv, \overname{\NEG}{\op}, \vt) \typearrow \overname{\TReal}{\vs} +} +\end{mathpar} + +\begin{mathpar} +\inferrule[neg\_t\_int\_unconstrained]{ + \getwellconstrainedstructure(\tenv, \vt) \typearrow \unconstrainedinteger \OrTypeError +}{ + \CheckUnop(\tenv, \overname{\NEG}{\op}, \vt) \typearrow \overname{\unconstrainedinteger}{\vs} +} +\end{mathpar} + +\begin{mathpar} +\inferrule[neg\_t\_int\_well\_constrained]{ + \getwellconstrainedstructure(\tenv, \vt) \typearrow \TInt(\wellconstrained(\vcs))\\ + \vc \in \vcs: \negateconstraint(\vc) \typearrow \vneg_\vc\\ + \vcsnew \eqdef [\vc \in \vcs: \vneg_\vc] +}{ + \CheckUnop(\tenv, \overname{\NEG}{\op}, \vt) \typearrow \overname{\TInt(\wellconstrained(\vcsnew))}{\vs} +} +\end{mathpar} + +\begin{mathpar} +\inferrule[not\_t\_bits]{ + \checkstructurelabel(\tenv, \vt, \TBits) \typearrow \True \OrTypeError +}{ + \CheckUnop(\tenv, \overname{\NOT}{\op}, \vt) \typearrow \vt +} +\end{mathpar} + +\isempty{\subsubsection{Comments}} + +\subsection{TypingRule.CheckBinop \label{sec:TypingRule.CheckBinop}} +\hypertarget{def-checkbinop}{} +The function +\[ + \CheckBinop(\overname{\staticenvs}{\tenv} \aslsep \overname{\binop}{\op} \aslsep \overname{\ty}{\vtone} + \aslsep \overname{\ty}{\vttwo}) + \aslto \overname{\ty}{\vt} \cup \overname{\TTypeError}{\TypeErrorConfig} +\] +determines the result type $\vt$ of applying the binary operator $\op$ +to operands of type $\vtone$ and $\vttwo$ in the static environment $\tenv$. +\ProseOtherwiseTypeError + +\subsubsection{Prose} +One of the following applies: +\begin{itemize} + \item All of the following apply (\textsc{boolean}): + \begin{itemize} + \item $\op$ is $\AND$, $\OR$, $\EQOP$ or $\IMPL$; + \item determining whether $\vtone$ \typesatisfies\ $\TBool$ in $\tenv$ yields $\True$\ProseOrTypeError; + \item determining whether $\vttwo$ \typesatisfies\ $\TBool$ in $\tenv$ yields $\True$\ProseOrTypeError; + \item $\vt$ is $\TBool$. + \end{itemize} + + \item All of the following apply (\textsc{bits\_bool}): + \begin{itemize} + \item $\op$ is $\AND$, $\OR$, or $\XOR$; + \item checking whether $\vtone$ and $\vttwo$ have the \structure\ of bitvector types + of the same width in $\tenv$ yields $\True$\ProseOrTypeError; + \item the bitvector width of $\vtone$ in $\tenv$ is $\vw$; + \item $\vt$ is the bitvector type of width $\vw$ and empty list of bitfields, that is, \\ $\TBits(\vw, \emptylist)$. + \end{itemize} + + \item All of the following apply (\textsc{plus\_minus\_error}): + \begin{itemize} + \item $\op$ is $\PLUS$ or $\MINUS$; + \item obtaining the \structure\ of $\vtone$ in $\tenv$ is $\vtonestruct$\ProseOrTypeError; + \item $\vtonestruct$ is neither a bitvector type nor an integer type; + \item the result is a type error indicating that the type of $\vtone$ is inappropriate for $\op$. + \end{itemize} + + \item All of the following apply (\textsc{plus\_minus\_bits\_int}): + \begin{itemize} + \item $\op$ is $\PLUS$ or $\MINUS$; + \item obtaining the \structure\ of $\vtone$ in $\tenv$ is $\vtonestruct$\ProseOrTypeError; + \item $\vtonestruct$ is a bitvector type; + \item $\vttwo$ \typesatisfies\ the unconstrained integer type in $\tenv$; + \item obtaining the bitwidth of $\vtone$ in $\tenv$ yields $\vw$. + \item $\vt$ is the bitvector type of width $\vw$ and empty list of bitfields, that is, \\ $\TBits(\vw, \emptylist)$. + \end{itemize} + + \item All of the following apply (\textsc{plus\_minus\_bits\_bits}): + \begin{itemize} + \item $\op$ is $\PLUS$ or $\MINUS$; + \item obtaining the \structure\ of $\vtone$ in $\tenv$ is a bitvector of width $\veone$, that is,\\ $\TBits(\veone, \Ignore)$; + \item $\vttwo$ does not \typesatisfy\ the unconstrained integer type in $\tenv$ + \item obtaining the \structure\ of $\vttwo$ in $\tenv$ is $\vttwostruct$\ProseOrTypeError; + \item determining whether $\vttwostruct$ has a bitvector type yields $\True$\ProseOrTypeError; + \item $\vttwostruct$ is a bitvector of width $\vwtwo$, that is, $\TBits(\vwtwo, \Ignore)$; + \item determining whether $\vwone$ and $\vwtwo$ are equal bitwidths yields $\vb$; + \item $\vb$ is $\True$\ProseOrTypeError; + \item $\vt$ is the bitvector type of width $\vwone$ and empty list of bitfields, that is, \\ $\TBits(\vwone, \emptylist)$. + \end{itemize} + + \item All of the following apply (\textsc{eq\_neq\_error}): + \begin{itemize} + \item $\op$ is either $\EQOP$ or $\NEQ$; + \item the \underlyingtype\ of $\vtone$ in $\tenv$ is $\vtoneanon$\ProseOrTypeError; + \item the \underlyingtype\ of $\vttwo$ in $\tenv$ is $\vttwoanon$\ProseOrTypeError; + \item the AST labels of $\vtoneanon$ and $\vttwoanon$ are different or one of them is not in + $\{\TInt, \TReal, \TBool, \TBits, \TEnum\}$; + \item the result is a type error indicating that the types of $\vtone$ and $\vttwo$ are inappropriate for $\op$. + \end{itemize} + + \item All of the following apply (\textsc{eq\_neq\_bits}): + \begin{itemize} + \item $\op$ is either $\EQOP$ or $\NEQ$; + \item the \underlyingtype\ of $\vtone$ in $\tenv$ is $\vtoneanon$\ProseOrTypeError; + \item $\vtoneanon$ is a bitvector type; + \item the \underlyingtype\ of $\vttwo$ in $\tenv$ is $\vttwoanon$\ProseOrTypeError; + \item $\vttwoanon$ is a bitvector type; + \item checking whether the bitwidth of $\vtoneanon$ and $\vttwoanon$ is the same yields $\True$\ProseOrTypeError; + \item $\vt$ is $\TBool$. + \end{itemize} + + \item All of the following apply (\textsc{eq\_neq\_bool}): + \begin{itemize} + \item $\op$ is either $\EQOP$ or $\NEQ$; + \item the \underlyingtype\ of $\vtone$ in $\tenv$ is $\TBool$\ProseOrTypeError; + \item the \underlyingtype\ of $\vttwo$ in $\tenv$ is $\TBool$\ProseOrTypeError; + \item checking whether $\vtoneanon$ \typesatisfies\ $\TBool$ yields $\True$\ProseOrTypeError; + \item checking whether $\vttwoanon$ \typesatisfies\ $\TBool$ yields $\True$\ProseOrTypeError; + \item $\vt$ is $\TBool$. + \end{itemize} + + \item All of the following apply (\textsc{eq\_neq\_real}): + \begin{itemize} + \item $\op$ is either $\EQOP$ or $\NEQ$; + \item the \underlyingtype\ of $\vtone$ in $\tenv$ is $\TReal$\ProseOrTypeError; + \item the \underlyingtype\ of $\vttwo$ in $\tenv$ is $\TReal$\ProseOrTypeError; + \item checking whether $\vtoneanon$ \typesatisfies\ $\TBool$ yields $\True$\ProseOrTypeError; + \item checking whether $\vttwoanon$ \typesatisfies\ $\TBool$ yields $\True$\ProseOrTypeError; + \item $\vt$ is $\TBool$. + \end{itemize} + + \item All of the following apply (\textsc{eq\_neq\_string}): + \begin{itemize} + \item $\op$ is either $\EQOP$ or $\NEQ$; + \item the \underlyingtype\ of $\vtone$ in $\tenv$ is $\TString$\ProseOrTypeError; + \item the \underlyingtype\ of $\vttwo$ in $\tenv$ is $\TString$\ProseOrTypeError; + \item checking whether $\vtoneanon$ \typesatisfies\ $\TBool$ yields $\True$\ProseOrTypeError; + \item checking whether $\vttwoanon$ \typesatisfies\ $\TBool$ yields $\True$\ProseOrTypeError; + \item $\vt$ is $\TBool$. + \end{itemize} + + \item All of the following apply (\textsc{eq\_neq\_enum}): + \begin{itemize} + \item $\op$ is either $\EQOP$ or $\NEQ$; + \item the \underlyingtype\ of $\vtone$ in $\tenv$ is $\TEnum(\vlione)$\ProseOrTypeError; + \item the \underlyingtype\ of $\vttwo$ in $\tenv$ is $\TEnum(\vlitwo)$\ProseOrTypeError; + \item checking whether $\vlione$ is equal to $\vlitwo$ yields $\True$\ProseOrTypeError; + \item $\vt$ is $\TBool$. + \end{itemize} + + \item All of the following apply (\textsc{relational}): + \begin{itemize} + \item $\op$ is one of $\LT$, $\LEQ$, $\GT$, and $\GEQ$; + \item determining whether both $\vtone$ and $\vttwo$ \typesatisfy\ the unconstrained integer type in $\tenv$ + or both $\vtone$ and $\vttwo$ \typesatisfy\ the \texttt{real} type in $\tenv$ yields $\True$\ProseOrTypeError; + \item $\vt$ is $\TBool$. + \end{itemize} + + \item All of the following apply (\textsc{arith\_error}): + \begin{itemize} + \item obtaining the \structure\ of $\vtone$ in $\tenv$ yields $\vtonestruct$\ProseOrTypeError; + \item obtaining the \structure\ of $\vttwo$ in $\tenv$ yields $\vttwostruct$\ProseOrTypeError; + \item the operator and the AST labels of $\vtonestruct$ and $\vttwostruct$ do not match any of the rows in the following table: + + \begin{center} + \begin{tabular}{lll} + \op & $\astlabel(\vtonestruct)$ & $\astlabel(\vttwostruct)$\\ + \hline + \MUL & \TInt & \TInt\\ + \DIV & \TInt & \TInt\\ + \DIVRM & \TInt & \TInt\\ + \MOD & \TInt & \TInt\\ + \SHL & \TInt & \TInt\\ + \SHR & \TInt & \TInt\\ + \POW & \TInt & \TInt\\ + \PLUS & \TInt & \TInt\\ + \MINUS & \TInt & \TInt\\ + \PLUS & \TReal & \TReal\\ + \MINUS & \TReal & \TReal\\ + \MUL & \TReal & \TReal\\ + \RDIV & \TReal & \TReal\\ + \POW & \TReal & \TInt\\ + \end{tabular} + \end{center} + \item the result is a type error indicating that the types of $\vtone$ and $\vttwo$ are inappropriate for $\op$. + \end{itemize} + + \item All of the following apply (\textsc{arith\_t\_int\_unconstrained1}, \\ + \textsc{arith\_t\_int\_unconstrained2}): + \begin{itemize} + \item $\op$ is one of $\{\MUL, \DIV, \DIVRM, \MOD, \SHL, \SHR, \POW, \PLUS, \MINUS\}$; + \item the \wellconstrainedstructure\ of $\vtone$ or $\vttwo$ in $\tenv$ is that of the unconstrained integer type; + \item $\vt$ is the unconstrained integer type; + \end{itemize} + + \item All of the following apply (\textsc{arith\_t\_int\_wellconstrained}): + \begin{itemize} + \item $\op$ is one of $\{\MUL, \POW, \PLUS, \MINUS, \DIVRM, \DIV, \MOD, \SHL, \SHR\}$; + \item the \wellconstrainedstructure\ of $\vtone$ in $\tenv$ is that of a well-constrained integer type with + constraints $\vcsone$; + \item the \wellconstrainedstructure\ of $\vttwo$ in $\tenv$ is that of a well-constrained integer type with + constraints $\vcstwo$; + \item applying $\annotateconstraintbinop$ to $\op$, $\vcsone$, and $\vcstwo$ in $\tenv$ yields $\vcs$; + \item $\vt$ is the integer type with constraints $\vcs$; + \end{itemize} + + \item All of the following apply (\textsc{plus\_minus\_mul\_real}): + \begin{itemize} + \item $\op$ is one of $\{\PLUS, \MINUS, \MUL\}$; + \item obtaining the \structure\ of $\vtone$ in $\tenv$ yields $\TReal$; + \item obtaining the \structure\ of $\vttwo$ in $\tenv$ yields $\TReal$; + \item $\vt$ is $\TReal$. + \end{itemize} + + \item All of the following apply (\textsc{pow\_real\_int}): + \begin{itemize} + \item $\op$ is one of $\{\PLUS, \MINUS, \MUL\}$; + \item obtaining the \structure\ of $\vtone$ in $\tenv$ yields $\TReal$; + \item obtaining the \structure\ of $\vttwo$ in $\tenv$ yields an integer type; + \item $\vt$ is $\TReal$. + \end{itemize} + + \item All of the following apply (\textsc{rdiv}): + \begin{itemize} + \item $\op$ is one of $\{\RDIV\}$; + \item determining whether $\vtone$ \typesatisfies\ $\TReal$ yields $\True$\ProseOrTypeError; + \item determining whether $\vttwo$ \typesatisfies\ $\TReal$ yields $\True$\ProseOrTypeError; + \item $\vt$ is $\TReal$. + \end{itemize} +\end{itemize} + +\isempty{\subsubsection{Example}} + +\CodeSubsection{\CheckBinopBegin}{\CheckBinopEnd}{../Typing.ml} + +\subsubsection{Formally} +\begin{mathpar} +\inferrule[boolean]{ + \op \in \{\BAND, \BOR, \IMPL, \EQOP\}\\ + \checktypesat(\tenv, \vt1, \TBool) \typearrow \True \OrTypeError\\\\ + \checktypesat(\tenv, \vttwo, \TBool) \typearrow \True \OrTypeError +}{ + \CheckBinop(\tenv, \op, \vtone, \vttwo) \typearrow \overname{\TBool}{\vt} +} +\end{mathpar} + +\begin{mathpar} +\inferrule[bits\_bool]{ + \op \in \{\AND, \OR, \XOR\}\\ + \checkbitsequalwidth(\tenv, \vtone, \vttwo) \typearrow \True \OrTypeError\\\\ + \getbitvectorwidth(\tenv, \vtone) \typearrow \vw +}{ + \CheckBinop(\tenv, \op, \vtone, \vttwo) \typearrow \overname{\TBits(\vw, \emptylist)}{\vt} +} +\end{mathpar} + +\begin{mathpar} +\inferrule[plus\_minus\_error]{ + \op \in \{\PLUS, \MINUS\}\\ + \tstruct(\tenv, \vtone) \typearrow \vtonestruct \OrTypeError\\\\ + \astlabel(\vtonestruct) \not\in \{\TBits,\TInt\}\\ +}{ + \CheckBinop(\tenv, \op, \vtone, \vttwo) \typearrow \TypeErrorVal{\InvalidOperandTypesForBinop} +} +\and +\inferrule[plus\_minus\_bits\_int]{ + \op \in \{\PLUS, \MINUS\}\\ + \tstruct(\tenv, \vtone) \typearrow \vtonestruct \OrTypeError\\\\ + \astlabel(\vtonestruct) = \TBits\\ + \typesat(\tenv, \vttwo, \unconstrainedinteger) \typearrow \True\\ + \getbitvectorwidth(\tenv, \vtone) \typearrow \vw\\ +}{ + \CheckBinop(\tenv, \op, \vtone, \vttwo) \typearrow \overname{\TBits(\vw, \emptylist)}{\vt} +} +\and +\inferrule[plus\_minus\_bits\_bits]{ + \op \in \{\PLUS, \MINUS\}\\ + \tstruct(\tenv, \vtone) \typearrow \TBits(\vwone, \Ignore) \\ + \typesat(\tenv, \vttwo, \unconstrainedinteger) \typearrow \False\\ + \tstruct(\tenv, \vttwo) \typearrow \vttwostruct \OrTypeError\\\\ + \checktrans{\astlabel(\vttwostruct)=\TBits}{\ExpectedBitvectorType} \checktransarrow \True \OrTypeError\\\\ + \vttwostruct \eqname \TBits(\vwtwo, \Ignore)\\ + \bitwidthequal(\tenv, \vwone, \vwtwo) \typearrow \vb\\ + \checktrans{\vb}{DifferentBitwidths} \checktransarrow \True \OrTypeError +}{ + \CheckBinop(\tenv, \op, \vtone, \vttwo) \typearrow \overname{\TBits(\vwone, \emptylist)}{\vt} +} +\end{mathpar} + +\begin{mathpar} +\inferrule[eq\_neq\_error] +{ + \op \in \{\EQOP, \NEQ\}\\ + \makeanonymous(\tenv, \vtone) \typearrow \vtoneanon \OrTypeError\\\\ + \makeanonymous(\tenv, \vttwo) \typearrow \vttwoanon \OrTypeError\\\\ + { + \left(\begin{array}{ll} + \astlabel(\vtoneanon) \neq \astlabel(\vttwoanon) & \lor \\ + \astlabel(\vtoneanon) \not\in \{\TInt, \TReal, \TBool, \TBits, \TEnum\} & + \end{array}\right) + } +}{ + \CheckBinop(\tenv, \op, \vtone, \vttwo) \typearrow \TypeErrorVal{\InvalidOperandTypesForBinop} +} +\and +\inferrule[eq\_neq\_bits]{ + \op \in \{\EQOP, \NEQ\}\\ + \makeanonymous(\tenv, \vtone) \typearrow \vtoneanon \OrTypeError\\\\ + \makeanonymous(\tenv, \vttwo) \typearrow \vttwoanon \OrTypeError\\\\ + \astlabel(\vtoneanon) = \TBits\\ + \astlabel(\vttwoanon) = \TBits\\ + \checkbitsequalwidth(\tenv, \vtoneanon, \vttwoanon) \typearrow \True \OrTypeError +}{ + \CheckBinop(\tenv, \op, \vtone, \vttwo) \typearrow \overname{\TBool}{\vt} +} +\and +\inferrule[eq\_neq\_bool]{ + \op \in \{\EQOP, \NEQ\}\\ + \makeanonymous(\tenv, \vtone) \typearrow \vtoneanon \OrTypeError\\\\ + \makeanonymous(\tenv, \vttwo) \typearrow \vttwoanon \OrTypeError\\\\ + \checktypesat(\tenv, \vtoneanon, \TBool) \typearrow \True \OrTypeError\\\\ + \checktypesat(\tenv, \vttwoanon, \TBool) \typearrow \True \OrTypeError +}{ + \CheckBinop(\tenv, \op, \vtone, \vttwo) \typearrow \overname{\TBool}{\vt} +} +\and +\inferrule[eq\_neq\_real]{ + \op \in \{\EQOP, \NEQ\}\\ + \makeanonymous(\tenv, \vtone) \typearrow \vtoneanon \OrTypeError\\\\ + \makeanonymous(\tenv, \vttwo) \typearrow \vttwoanon \OrTypeError\\\\ + \checktypesat(\tenv, \vtoneanon, \TReal) \typearrow \True \OrTypeError\\\\ + \checktypesat(\tenv, \vttwoanon, \TReal) \typearrow \True \OrTypeError +}{ + \CheckBinop(\tenv, \op, \vtone, \vttwo) \typearrow \overname{\TBool}{\vt} +} +\and +\inferrule[eq\_neq\_string]{ + \op \in \{\EQOP, \NEQ\}\\ + \makeanonymous(\tenv, \vtone) \typearrow \vtoneanon \OrTypeError\\\\ + \makeanonymous(\tenv, \vttwo) \typearrow \vttwoanon \OrTypeError\\\\ + \checktypesat(\tenv, \vtoneanon, \TString) \typearrow \True \OrTypeError\\\\ + \checktypesat(\tenv, \vttwoanon, \TString) \typearrow \True \OrTypeError +}{ + \CheckBinop(\tenv, \op, \vtone, \vttwo) \typearrow \overname{\TBool}{\vt} +} +\and +\inferrule[eq\_neq\_enum]{ + \op \in \{\EQOP, \NEQ\}\\ + \makeanonymous(\tenv, \vtone) \typearrow \TEnum(\vlione)\\ + \makeanonymous(\tenv, \vttwo) \typearrow \TEnum(\vlitwo)\\ + \checktrans{\vlione = \vlitwo}{DifferentEnumLabels} \checktransarrow \True \OrTypeError +}{ + \CheckBinop(\tenv, \op, \vtone, \vttwo) \typearrow \overname{\TBool}{\vt} +} +\end{mathpar} + +\begin{mathpar} +\inferrule[relational]{ + \op \in \{\LT, \LEQ, \GT, \GEQ\}\\ + \typesat(\tenv, \vtone, \unconstrainedinteger) \typearrow \vbone \OrTypeError\\\\ + \typesat(\tenv, \vttwo, \unconstrainedinteger) \typearrow \vbtwo \OrTypeError\\\\ + \typesat(\tenv, \vtone, \TReal) \typearrow \vbthree \OrTypeError\\\\ + \typesat(\tenv, \vttwo, \TReal) \typearrow \vbfour \OrTypeError\\\\ + \checktrans{\vbone \land \vbtwo \lor \vbthree \land \vbfour}{\InvalidOperandTypesForBinop} \checktransarrow \True \OrTypeError +}{ + \CheckBinop(\tenv, \op, \vtone, \vttwo) \typearrow \overname{\TBool}{\vt} +} +\end{mathpar} + +\begin{mathpar} +\inferrule[arith\_error]{ + \tstruct(\tenv, \vtone) \typearrow \vtonestruct \OrTypeError\\\\ + \tstruct(\tenv, \vttwo) \typearrow \vttwostruct \OrTypeError\\\\ + (\op, \astlabel(\vtonestruct), \astlabel(\vttwostruct)) \not\in + { + \left\{ + \begin{array}{lclcl} + (\MUL &,& \TInt &,& \TInt)\\ + (\DIV &,& \TInt &,& \TInt)\\ + (\DIVRM &,& \TInt &,& \TInt)\\ + (\MOD &,& \TInt &,& \TInt)\\ + (\SHL &,& \TInt &,& \TInt)\\ + (\SHR &,& \TInt &,& \TInt)\\ + (\POW &,& \TInt &,& \TInt)\\ + (\PLUS &,& \TInt &,& \TInt)\\ + (\MINUS &,& \TInt &,& \TInt)\\ + (\PLUS &,& \TReal &,& \TReal)\\ + (\MINUS &,& \TReal &,& \TReal)\\ + (\MUL &,& \TReal &,& \TReal)\\ + (\RDIV &,& \TReal &,& \TReal)\\ + (\POW &,& \TReal &,& \TInt)\\ + \end{array} + \right\} + } +}{ + \CheckBinop(\tenv, \op, \vtone, \vttwo) \typearrow \TypeErrorVal{\InvalidOperandTypesForBinop} +} +\end{mathpar} + +The following two rules are not mutually exclusive, but both yield the same result when they are both active. +\begin{mathpar} +\inferrule[arith\_t\_int\_unconstrained1]{ + \op \in \{\MUL, \DIV, \DIVRM, \MOD, \SHL, \SHR, \POW, \PLUS, \MINUS\}\\ + \getwellconstrainedstructure(\tenv, \vtone) \typearrow \unconstrainedinteger\\ + \getwellconstrainedstructure(\tenv, \vttwo) \typearrow \TInt(\Ignore)\\ +}{ + \CheckBinop(\tenv, \op, \vtone, \vttwo) \typearrow \unconstrainedinteger +} +\and +\inferrule[arith\_t\_int\_unconstrained2]{ + \op \in \{\MUL, \DIV, \DIVRM, \MOD, \SHL, \SHR, \POW, \PLUS, \MINUS\}\\ + \getwellconstrainedstructure(\tenv, \vtone) \typearrow \TInt(\Ignore)\\ + \getwellconstrainedstructure(\tenv, \vttwo) \typearrow \unconstrainedinteger\\ +}{ + \CheckBinop(\tenv, \op, \vtone, \vttwo) \typearrow \unconstrainedinteger +} +\end{mathpar} + +\begin{mathpar} +\inferrule[arith\_t\_int\_wellconstrained]{ + \op \in \{\MUL, \POW, \PLUS, \MINUS, \DIVRM, \DIV, \MOD, \SHL, \SHR\}\\ + \getwellconstrainedstructure(\tenv, \vtone) \typearrow \TInt(\wellconstrained(\vcsone))\\ + \getwellconstrainedstructure(\tenv, \vttwo) \typearrow \TInt(\wellconstrained(\vcstwo))\\ + \annotateconstraintbinop(\tenv, \op, \vcsone, \vcstwo) \typearrow \vcs +}{ + \CheckBinop(\tenv, \op, \vtone, \vttwo) \typearrow \TInt(\vcs) +} +\end{mathpar} + +\begin{mathpar} +\inferrule[plus\_minus\_mul\_real]{ + \op \in \{\PLUS, \MINUS, \MUL\}\\ + \tstruct(\tenv, \vtone) \typearrow \TReal\\ + \tstruct(\tenv, \vttwo) \typearrow \TReal +}{ + \CheckBinop(\tenv, \op, \vtone, \vttwo) \typearrow \TReal +} +\end{mathpar} + +\begin{mathpar} +\inferrule[pow\_real\_int]{ + \tstruct(\tenv, \vtone) \typearrow \TReal\\ + \astlabel(\tstruct(\tenv, \vttwo)) \typearrow \TInt +}{ + \CheckBinop(\tenv, \POW, \vtone, \vttwo) \typearrow \TReal +} +\end{mathpar} + +\begin{mathpar} +\inferrule[rdiv]{ + \checktypesat(\tenv, \vtone, \TReal) \typearrow \True \OrTypeError\\\\ + \checktypesat(\tenv, \vttwo, \TReal) \typearrow \True \OrTypeError\\ +}{ + \CheckBinop(\tenv, \RDIV, \vtone, \vttwo) \typearrow \TReal +} +\end{mathpar} + +\isempty{\subsubsection{Comments}} +\lrmcomment{ + This is related to \identr{BKNT}, \identr{ZYWY}, \identr{BZKW}, + \identr{KFYS}, \identr{KXMR}, \identr{SQXN}, \identr{MRHT}, \identr{JGWF}, + \identr{TTGQ}, \identi{YHML}, \identi{YHRP}, \identi{VMZF}, \identi{YXSY}, + \identi{LGHJ}, \identi{RXLG}. +} + +\subsection{TypingRule.FindNamedLCA \label{sec:TypingRule.FindNamedLCA}} +\hypertarget{def-namedlowestcommonancestor}{} +The function +\[ + \namedlca(\overname{\staticenvs}{\tenv} \aslsep \overname{\ty}{\vt} \aslsep \overname{\ty}{\vs}) + \aslto \overname{\ty}{\tty} \cup \overname{\TTypeError}{\TypeErrorConfig} +\] +returns the lowest common named super type --- $\tty$ --- of the types $\vt$ and $\vs$ in $\tenv$. + +\newcommand\supers[0]{\texttt{supers}} +The helper function +\[ + \supers(\overname{\staticenvs}{\tenv} \aslsep \overname{\ty}{\vt}) + \aslto \pow{\ty} +\] +returns the set of \emph{named supertypes} given via the $\subtypes$ function of the global environment: +\[ + \supers(\tenv, \vt) \triangleq + \begin{cases} + \{\vt\} \cup \supers(\vs) & \text{ if }G^\tenv.\subtypes(\vt) = \vs\\ + \{\vt\} & \text{ otherwise } (\text{that is, }G^\tenv.\subtypes(\vt) = \bot)\\ + \end{cases} +\] + +\subsubsection{Prose} +One of the following holds: +\begin{itemize} + \item $\vtsupers$ is in the set of named supertypes of $\vt$; + \item All of the following hold (\textsc{found}): + \begin{itemize} + \item $\vs$ is in $\vtsupers$; + \item $\tty$ is $\vs$; + \end{itemize} + + \item All of the following hold (\textsc{super}): + \begin{itemize} + \item $\vs$ is not in $\vtsupers$; + \item $\vs$ has a named super type in $\tenv$ --- $\vsp$; + \item $\tty$ is the lowest common named supertype of $\vt$ and $\vsp$ in $\tenv$. + \end{itemize} + + \item All of the following hold (\textsc{none}): + \begin{itemize} + \item $\vs$ is not in $\vtsupers$; + \item $\vs$ has no named super type in $\tenv$; + \item $\tty$ is $\None$. + \end{itemize} +\end{itemize} + +\subsubsection{Formally} +\begin{mathpar} +\inferrule[found]{ + \supers(\tenv, \vt) \typearrow \vtsupers\\ + \vs \in \vtsupers +}{ + \namedlca(\tenv, \vt, \vs) \typearrow \vs +} +\and +\inferrule[super]{ + \supers(\tenv, \vt) \typearrow \vtsupers\\ + \vs \not\in \vtsupers\\ + G^\tenv.\subtypes(\vs) = \vsp\\ + \namedlca(\tenv, \vt, \vsp) \typearrow \tty +}{ + \namedlca(\tenv, \vt, \vs) \typearrow \tty +} +\and +\inferrule[none]{ + \supers(\tenv, \vt) \typearrow \vtsupers\\ + \vs \not\in \vtsupers\\ + G^\tenv.\subtypes(\vs) = \None +}{ + \namedlca(\tenv, \vt, \vs) \typearrow \None +} +\end{mathpar} + +\subsection{TypingRule.AnnotateConstraintBinop \label{sec:TypingRule.AnnotateConstraintBinop}} +\hypertarget{def-annotateconstraintbinop}{} +The function +\[ +\begin{array}{r} +\annotateconstraintbinop( + \overname{\staticenvs}{\tenv} \aslsep + \overname{\binop}{\op} \aslsep + \overname{\intconstraint^*}{\csone} \aslsep + \overname{\intconstraint^*}{\cstwo} +) \aslto \\ +\overname{\intconstraints}{\vics} +\cup \overname{\TTypeError}{\TypeErrorConfig} +\end{array} +\] +annotates the application of the binary operation $\op$ to the lists of integer constraints +$\csone$ and $\cstwo$, yielding an integer constraints element $\vics$. +\ProseOtherwiseTypeError\ + +The operator $\op$ is assumed to be only one of the operators in the following set: +$\{\SHL, \SHR, \POW, \MOD, \DIVRM, \MINUS, \MUL, \PLUS, \DIV\}$. + +Annotating the constraints involves applying symbolic reasoning and in particular filtering out values that +will definitely result in a dynamic error. + +\subsubsection{Prose} +All of the following apply: +\begin{itemize} + \item applying $\binopfilterrhs$ to $\op$ $\cstwo$ in $\tenv$, to filter out constraints that will definitely fail dynamically, yields $\cstwof$; + \item applying $\binopisexploding$ to $\op$ yields $\vbexploding$; + \item applying $\explodeintervals$ to $\csone$ in $\tenv$ yields $\csonee$; + \item applying $\explodeintervals$ to $\cstwo$ in $\tenv$ yields $\cstwo$; + \item define $(\csonearg, \cstwoarg)$ as $(\csonee, \cstwoe)$ if $\vbexploding$ is $\True$ and $(\csone, \cstwof)$, otherwise; + \item applying $\constraintbinop$ yo $\op$, $\csonearg$, and $\cstwoarg$ yields $\csvanilla$; + \item applying $\reduceconstraints$ to $\csvanilla$ in $\tenv$ yields $\cs$; + \item one of the following applies: + \begin{itemize} + \item All of the following apply (\textsc{div\_wellconstrained}): + \begin{itemize} + \item $\op$ is $\DIV$ and $\cs$ is a $\wellconstrained$ constraint; + \item view $\cs$ as $\wellconstrained(\cslist)$; + \item applying $\refineconstraints$ to $\filterreduceconstraintdiv$ and \\ + $\cslist$ yields $\cslistfiltered$; + \item applying $\reduceconstants$ to $\cslistfiltered$ yields $\vics$. + \end{itemize} + + \item All of the following apply (\textsc{else}): + \begin{itemize} + \item either $\op$ is not $\DIV$ or $\cs$ is not a $\wellconstrained$ constraint; + \item $\vics$ is $\cs$. + \end{itemize} + \end{itemize} +\end{itemize} + +\CodeSubsection{\AnnotateConstraintBinopBegin}{\AnnotateConstraintBinopEnd}{../Typing.ml} + +\subsubsection{Formally} +\begin{mathpar} +\inferrule[div\_wellconstrained]{ + \binopfilterrhs(\tenv, \op, \cstwo) \typearrow \cstwof\\ + \binopisexploding(\op) \typearrow \vbexploding\\ + \explodeintervals(\tenv, \csone) \typearrow \csonee\\ + \explodeintervals(\tenv, \cstwof) \typearrow \cstwoe\\ + (\csonearg, \cstwoarg) \eqdef \choice{\vbexploding}{(\csonee, \cstwoe)}{(\csone, \cstwof)}\\ + \constraintbinop(\op, \csonearg, \cstwoarg) \typearrow \csvanilla\\ + \reduceconstraints(\tenv, \csvanilla) \typearrow \cs\\\\ + \commonprefixline\\\\ + \op = \DIV \land \astlabel(\cs) = \wellconstrained\\ + \cs \eqname \wellconstrained(\cslist)\\ + { + \begin{array}{r} + \refineconstraints(\filterreduceconstraintdiv, \cslist) \typearrow \\ + \cslistfiltered + \end{array} + }\\ + \reduceconstraints(\cslistfiltered) \typearrow \vics +}{ + \annotateconstraintbinop(\tenv, \op, \csone, \cstwo) \typearrow \vics +} +\end{mathpar} + +\begin{mathpar} +\inferrule[else]{ + \binopfilterrhs(\tenv, \op, \cstwo) \typearrow \cstwof\\ + \binopisexploding(\op) \typearrow \vbexploding\\ + \explodeintervals(\tenv, \csone) \typearrow \csonee\\ + \explodeintervals(\tenv, \cstwof) \typearrow \cstwoe\\ + (\csonearg, \cstwoarg) \eqdef \choice{\vbexploding}{(\csonee, \cstwoe)}{(\csone, \cstwof)}\\ + \constraintbinop(\op, \csonearg, \cstwoarg) \typearrow \csvanilla\\ + \reduceconstraints(\tenv, \csvanilla) \typearrow \cs\\\\ + \commonprefixline\\\\ + \neg(\op = \DIV \land \astlabel(\cs) = \wellconstrained) +}{ + \annotateconstraintbinop(\tenv, \op, \csone, \cstwo) \typearrow \overname{\cs}{\vics} +} +\end{mathpar} + +\subsection{TypingRule.BinopFilterRhs \label{sec:TypingRule.BinopFilterRhs}} +\hypertarget{def-binopfilterrhs}{} +The function +\[ +\binopfilterrhs(\overname{\staticenvs}{\tenv} \aslsep \overname{\binop}{\op} \aslsep \overname{\intconstraint^*}{\cs}) +\aslto \overname{\intconstraint^*}{\newcs} +\] +\subsubsection{Prose} +One of the following applies: +\begin{itemize} + \item All of the following apply (\textsc{greater\_or\_equal}): + \begin{itemize} + \item $\op$ is one of $\SHL$, $\SHR$, and $\POW$; + \item define $\vf$ as the specialization of $\refineconstraintbysign$ for the predicate + $\lambda x.\ x \geq 0$, which is $\True$ if and only if the tested number is greater or equal to $0$; + \item refining the list of constraints $\cs$ with $\vf$ via $\refineconstraints$ yields $\newcs$; + \item checking whether $\newcs$ is empty yields $\True$\ProseTerminateAs{\BinaryOperationFailsAllConstraints}. + \end{itemize} + + \item All of the following apply (\textsc{greater\_than}): + \begin{itemize} + \item $\op$ is one of $\MOD$, $\DIV$, and $\DIVRM$; + \item define $\vf$ as the specialization of $\refineconstraintbysign$ for the predicate + $\lambda x.\ x > 0$, which is $\True$ if and only if the tested number is greater than $0$; + \item refining the list of constraints $\cs$ with $\vf$ via $\refineconstraints$ yields $\newcs$; + \item checking whether $\newcs$ is empty yields $\True$\ProseTerminateAs{\BinaryOperationFailsAllConstraints}. + \end{itemize} + + \item All of the following apply (\textsc{no\_filtering}): + \begin{itemize} + \item $\op$ is one of $\MINUS$, $\MUL$, and $\PLUS$; + \item $\newcs$ is $\cs$. + \end{itemize} +\end{itemize} + +\subsubsection{Formally} +\begin{mathpar} +\inferrule[greater\_or\_equal]{ + \op \in \{\SHL, \SHR, \POW\}\\\\ + \vf \eqdef \refineconstraintbysign(\tenv, \lambda x.\ x \geq 0)\\ + \refineconstraints(\cs, \vf) \typearrow \newcs\\ + \checktrans{\newcs \neq \emptylist}{\BinaryOperationFailsAllConstraints} \typearrow \True\OrTypeError +}{ + \binopfilterrhs(\tenv, \op, \cs) \typearrow \newcs +} +\end{mathpar} + +\begin{mathpar} +\inferrule[greater\_than]{ + \op \in \{\MOD, \DIV, \DIVRM\}\\\\ + \vf \eqdef \refineconstraintbysign(\tenv, \lambda x.\ x > 0)\\ + \refineconstraints(\cs, \vf) \typearrow \newcs\\ + \checktrans{\newcs \neq \emptylist}{\BinaryOperationFailsAllConstraints} \typearrow \True\OrTypeError +}{ + \binopfilterrhs(\tenv, \op, \cs) \typearrow \newcs +} +\end{mathpar} + +\begin{mathpar} +\inferrule[no\_filter]{ + \op \in \{\MINUS, \MUL, \PLUS\} +}{ + \binopfilterrhs(\op, \cs) \typearrow \overname{\cs}{\newcs} +} +\end{mathpar} + +\subsection{TypingRule.RefineConstraintBySign \label{sec:TypingRule.RefineConstraintBySign}} +\hypertarget{def-refineconstraintbysign}{} +The function +\[ +\refineconstraintbysign(\overname{\staticenvs}{\tenv} \aslsep \overname{\Z\rightarrow \Bool}{\vp} \aslsep \overname{\intconstraint}{\vc}) +\aslto \overname{\langle\intconstraint\rangle}{\vcopt} +\] +takes a predicate $\vp$ that returns $\True$ based on the sign of its input. +The function conservatively refines the constraint $\vc$ in $\tenv$ by applying symbolic reasoning to yield a new constraint +(inside an optional) +that represents the values that satisfy the $\vc$ and for which $\vp$ holds. +In this context, conservatively means that the new constraint may represent a superset of the values that a more precise +reasoning may yield. +If the set of those values is empty the result is $\None$. + +\subsubsection{Prose} +One of the following applies: +\begin{itemize} + \item All of the following apply (\textsc{exact\_reduces\_to\_z}): + \begin{itemize} + \item $\vc$ is an exact constraint for the expression $\ve$, that is, $\ConstraintExact(\ve)$; + \item applying $\reducetozopt$ to $\ve$ in $\tenv$, in order to symbolically simplify $\ve$ to an integer, + yields $\langle\vz\rangle$; + \item $\vcopt$ is $\langle\vc\rangle$ if $\vp$ holds for $\vz$ and $\None$ otherwise. + \end{itemize} + + \item All of the following apply (\textsc{exact\_does\_not\_reduce\_to\_z}): + \begin{itemize} + \item $\vc$ is an exact constraint for the expression $\ve$, that is, $\ConstraintExact(\ve)$; + \item applying $\reducetozopt$ to $\ve$ in $\tenv$, in order to symbolically simplify $\ve$ to an integer, + yields $\None$; + \item $\vcopt$ is $\langle\vc\rangle$. + \end{itemize} + + \item All of the following apply (\textsc{range\_both\_reduce\_to\_z}): + \begin{itemize} + \item $\vc$ is a range constraint for the expressions $\veone$ and $\vetwo$, that is, \\ + $\ConstraintRange(\veone, \vetwo)$; + \item applying $\reducetozopt$ to $\veone$ in $\tenv$, in order to symbolically simplify $\veone$ to an integer, + yields $\langle\vzone\rangle$; + \item applying $\reducetozopt$ to $\vetwo$ in $\tenv$, in order to symbolically simplify $\vetwo$ to an integer, + yields $\langle\vztwo\rangle$; + \item One of the following applies (defining $\vcopt$): + \begin{itemize} + \item if $\vp$ is $\True$ for both $\vzone$ and $\vztwo$, define $\vcopt$ as $\langle\vc\rangle$; + \item if $\vp$ is $\False$ for $\vzone$ and $\True$ for $\vztwo$, define $\vcopt$ as the optional range constraint + where the bottom expression is the literal expression for $0$ if $\vp$ holds for $0$ and the literal expression for $1$ otherwise, + and the top expression is $\vetwo$; + \item if $\vp$ is $\True$ for $\vzone$ and $\False$ for $\vztwo$, define $\vcopt$ as the optional range constraint + where the bottom expression is $\veone$ and the top expression is the literal expression for $0$ if $\vp$ holds for $0$ + and the literal expression for $-1$ otherwise; + \item if $\vp$ is $\False$ for both $\vzone$ and $\vztwo$, define $\vcopt$ as $\None$. + \end{itemize} + \end{itemize} + + \item All of the following apply (\textsc{only\_e1\_reduces\_to\_z}): + \begin{itemize} + \item $\vc$ is a range constraint for the expressions $\veone$ and $\vetwo$, that is, \\ + $\ConstraintRange(\veone, \vetwo)$; + \item applying $\reducetozopt$ to $\veone$ in $\tenv$, in order to symbolically simplify $\veone$ to an integer, + yields $\langle\vzone\rangle$; + \item applying $\reducetozopt$ to $\vetwo$ in $\tenv$, in order to symbolically simplify $\vetwo$ to an integer, + yields $\None$; + \item One of the following applies (defining $\vcopt$): + \begin{itemize} + \item if $\vp$ is $\True$ for $\vzone$, define $\vcopt$ as $\langle\vc\rangle$; + \item if $\vp$ is $\False$ for $\vzone$, define $\vcopt$ as the optional range constraint with the bottom expression + as the literal expression for $0$ if $\vp$ holds for $0$ and the literal expression for $1$ otherwise, + and the top expression $\vetwo$. + \end{itemize} + \end{itemize} + + \item All of the following apply (\textsc{only\_e2\_reduces\_to\_z}): + \begin{itemize} + \item $\vc$ is a range constraint for the expressions $\veone$ and $\vetwo$, that is, \\ + $\ConstraintRange(\veone, \vetwo)$; + \item applying $\reducetozopt$ to $\veone$ in $\tenv$, in order to symbolically simplify $\veone$ to an integer, + yields $\None$; + \item applying $\reducetozopt$ to $\vetwo$ in $\tenv$, in order to symbolically simplify $\vetwo$ to an integer, + yields $\langle\vztwo\rangle$; + \item One of the following applies (defining $\vcopt$): + \begin{itemize} + \item if $\vp$ is $\True$ for $\vztwo$, define $\vcopt$ as $\langle\vc\rangle$; + \item if $\vp$ is $\False$ for $\vztwo$, define $\vcopt$ as the optional range constraint with the bottom expression + $\veone$ and the top expression the literal expression for $0$ if $\vp$ holds for $0$ and the literal expression for $-1$ otherwise. + \end{itemize} + \end{itemize} +\end{itemize} + +\subsubsection{Formally} +\begin{mathpar} +\inferrule[exact\_reduces\_to\_z]{ + \reducetozopt(\tenv, \ve) \typearrow \langle\vz\rangle\\ + \vcopt \eqdef \choice{\vp(\vz)}{\langle\vc\rangle}{\None} +}{ + \refineconstraintbysign(\tenv, \vp, \overname{\ConstraintExact(\ve)}{\vc}) \typearrow \vcopt +} +\end{mathpar} + +\begin{mathpar} +\inferrule[exact\_does\_not\_reduce\_to\_z]{ + \reducetozopt(\tenv, \ve) \typearrow \None +}{ + \refineconstraintbysign(\tenv, \vp, \overname{\ConstraintExact(\ve)}{\vc}) \typearrow \overname{\langle\vc\rangle}{\vcopt} +} +\end{mathpar} + +\begin{mathpar} +\inferrule[range\_both\_reduce\_to\_z]{ + \reducetozopt(\tenv, \veone) \typearrow \langle\vzone\rangle\\ + \reducetozopt(\tenv, \vetwo) \typearrow \langle\vztwo\rangle\\ + { + \begin{array}{c} + \vcopt \eqdef \\ \wrappedline\ \begin{cases} + \langle\vc\rangle& \text{if }\vp(\vzone) \land \vp(\vztwo)\\ + \langle\ConstraintRange(\choice{\vp(0)}{\ELInt{0}}{\ELInt{1}}, \vetwo)\rangle& \text{if }\neg\vp(\vzone) \land \vp(\vztwo)\\ + \langle\ConstraintRange(\veone, \choice{\vp(0)}{\ELInt{0}}{\ELInt{-1}})\rangle& \text{if }\vp(\vzone) \land \neg\vp(\vztwo)\\ + \None& \text{if }\neg\vp(\vzone) \land \neg\vp(\vztwo)\\ + \end{cases} +\end{array} + } +}{ + \refineconstraintbysign(\tenv, \vp, \overname{\ConstraintRange(\veone, \vetwo)}{\vc}) \typearrow \vcopt +} +\end{mathpar} + +\begin{mathpar} +\inferrule[only\_e1\_reduces\_to\_z]{ + \reducetozopt(\tenv, \veone) \typearrow \langle\vzone\rangle\\ + \reducetozopt(\tenv, \vetwo) \typearrow \None\\ + { + \begin{array}{c} + \vcopt \eqdef \\ \wrappedline\ \begin{cases} + \langle\vc\rangle& \text{if }\vp(\vzone)\\ + \langle\ConstraintRange(\choice{\vp(0)}{\ELInt{0}}{\ELInt{1}}, \vetwo)\rangle& \text{else}\\ + \end{cases} +\end{array} + } +}{ + \refineconstraintbysign(\tenv, \vp, \overname{\ConstraintRange(\veone, \vetwo)}{\vc}) \typearrow \vcopt +} +\end{mathpar} + +\begin{mathpar} +\inferrule[only\_e2\_reduces\_to\_z]{ + \reducetozopt(\tenv, \veone) \typearrow \None\\ + \reducetozopt(\tenv, \vetwo) \typearrow \langle\vztwo\rangle\\ + { + \begin{array}{c} + \vcopt \eqdef \\ \wrappedline\ \begin{cases} + \langle\vc\rangle& \text{if }\vp(\vztwo)\\ + \langle\ConstraintRange(\veone, \choice{\vp(0)}{\ELInt{0}}{\ELInt{-1}})\rangle& \text{else}\\ + \end{cases} +\end{array} + } +}{ + \refineconstraintbysign(\tenv, \vp, \overname{\ConstraintRange(\veone, \vetwo)}{\vc}) \typearrow \vcopt +} +\end{mathpar} + +\begin{mathpar} +\inferrule[none\_reduce\_to\_z]{ + \reducetozopt(\tenv, \veone) \typearrow \None\\ + \reducetozopt(\tenv, \vetwo) \typearrow \None +}{ + \refineconstraintbysign(\tenv, \vp, \overname{\ConstraintRange(\veone, \vetwo)}{\vc}) \typearrow \overname{\vc}{\vcopt} +} +\end{mathpar} + +\subsection{TypingRule.ReduceToZOpt \label{sec:TypingRule.ReduceToZOpt}} +\hypertarget{def-reducetozopt}{} +The function +\[ +\reducetozopt(\overname{\staticenvs}{\tenv} \aslsep \overname{\expr}{\ve}) +\aslto \overname{\langle\Z\rangle}{\vzopt} +\] +returns an integer inside an optional if $\ve$ can be symbolically simplified into an integer in $\tenv$ +and $\None$ otherwise. +The expression $\ve$ is assumed to appear in a constraint for a type that has been successfully annotated, +which means that applying $\normalize$ to it should not yield a type error. + +\subsubsection{Prose} +One of the following applies: +\begin{itemize} + \item All of the following apply (\textsc{normalizes\_to\_z}): + \begin{itemize} + \item symbolically simplifying $\ve$ in $\tenv$ via $\normalize$ yields a literal expression for the integer $\vz$; + \item define $\vzopt$ as $\langle\vz\rangle$. + \end{itemize} + + \item All of the following apply (\textsc{does\_not\_normalize\_to\_z}): + \begin{itemize} + \item symbolically simplifying $\ve$ in $\tenv$ via $\normalize$ yields an expression that is not an integer literal; + \item define $\vzopt$ as $\None$. + \end{itemize} +\end{itemize} + +\subsubsection{Formally} +\begin{mathpar} +\inferrule[normalizes\_to\_z]{ + \normalize(\tenv, \ve) \typearrow \ELInt{\vz} +}{ + \reducetozopt(\tenv, \ve) \typearrow \overname{\langle\vz\rangle}{\vzopt} +} +\end{mathpar} + +\begin{mathpar} +\inferrule[does\_not\_normalize\_to\_z]{ + \normalize(\tenv, \ve) \typearrow \vep\\ + \forall \vz\in\Z.\ \vep \neq \ELInt{\vz} +}{ + \reducetozopt(\tenv, \ve) \typearrow \overname{\None}{\vzopt} +} +\end{mathpar} + +\subsection{TypingRule.RefineConstraints \label{sec:TypingRule.RefineConstraints}} +\hypertarget{def-refineconstraints}{} +The function +\[ +\begin{array}{r} +\refineconstraints(\overname{\staticenvs}{\tenv} \aslsep \overname{\intconstraint\rightarrow\langle\intconstraint\rangle}{\vf} \aslsep \overname{\intconstraint^*}{\cs}) +\aslto \\ +\overname{\intconstraint^*}{\newcs} +\end{array} +\] +refines a list of constraints $\cs$ by applying the refinement function $\vf$ to each constraint and retaining the constraints +that do not refine to $\None$. The resulting list of constraints is given in $\newcs$. + +\subsubsection{Prose} +One of the following applies: +\begin{itemize} + \item All of the following apply (\textsc{empty}): + \begin{itemize} + \item $\cs$ is the empty list; + \item $\newcs$ is the empty list. + \end{itemize} + + \item All of the following apply (\textsc{non\_empty\_none}): + \begin{itemize} + \item $\cs$ is the list with $\vc$ as its \head\ and $\csone$ as its \tail; + \item applying $\vf$ to $\vc$ yields $\None$; + \item applying $\refineconstraints$ to $\vf$ and $\csone$ yields $\csonep$; + \item $\newcs$ is $\csonep$. + \end{itemize} + + \item All of the following apply (\textsc{non\_empty\_somee}): + \begin{itemize} + \item $\cs$ is the list with $\vc$ as its \head\ and $\csone$ as its \tail; + \item applying $\vf$ to $\vc$ yields $\langle\vcp\rangle$; + \item applying $\refineconstraints$ to $\vf$ and $\csone$ yields $\csonep$; + \item $\newcs$ is the list with $\vcp$ as its \head\ and $\csonep$ as its \tail. + \end{itemize} +\end{itemize} + +\subsubsection{Formally} +\begin{mathpar} +\inferrule[empty]{}{ + \refineconstraints(\tenv, \vf, \overname{\emptylist}{\cs}) \typearrow \overname{\emptylist}{\newcs} +} +\end{mathpar} + +\begin{mathpar} +\inferrule[non\_empty\_none]{ + \vf(\vc) \typearrow \None\\ + \refineconstraints(\vf, \csone) \typearrow \csonep\\ +}{ + \refineconstraints(\vf, \overname{[\vc]\concat \csone}{\cs}) \typearrow \overname{\csonep}{\newcs} +} +\end{mathpar} + +\begin{mathpar} +\inferrule[non\_empty\_some]{ + \vf(\vc) \typearrow \langle\vcp\rangle\\ + \refineconstraints(\vf, \csone) \typearrow \csonep\\ +}{ + \refineconstraints(\vf, \overname{[\vc]\concat \csone}{\cs}) \typearrow \overname{[\vcp] \concat \csonep}{\newcs} +} +\end{mathpar} + +\subsection{TypingRule.FilterReduceConstraintDiv \label{sec:TypingRule.FilterReduceConstraintDiv}} +\hypertarget{def-filterreduceconstraintdiv}{} +The function +\[ +\filterreduceconstraintdiv(\overname{\intconstraint}{\vc}) \aslto \overname{\langle\intconstraint\rangle}{\vcopt} +\] +returns $\None$ if $\vc$ is an exact constraint for a binary expression for dividing two integer literals +where the denominator does not divide the numerator and an optional containing $\vc$. +The result is returned in $\vcopt$. +This is used to conservatively test whether $\vc$ would always fail dynamically. + +\subsubsection{Prose} +If $\vc$ is an exact constraint for a binary expression for the division operation and two integer literal +expressions for the integers $\vzone$ and $\vztwo$ such that $\vztwo$ does not divide $\vzone$ then +$\vcopt$ is $\None$. Otherwise $\vcopt$ is $\langle\vc\rangle$. + +\subsubsection{Formally} +\begin{mathpar} +\inferrule[exact\_div\_literals]{ + \vc = \ConstraintExact(\ve)\\ + \getliteraldivopt(\ve) \typearrow \None +}{ + \filterreduceconstraintdiv(\tenv, \vc) \typearrow \overname{\langle\vc\rangle}{\vcopt} +} +\end{mathpar} + +\begin{mathpar} +\inferrule[exact\_not\_div\_literals]{ + \vc = \ConstraintExact(\ve)\\ + \getliteraldivopt(\ve) \typearrow \langle(\vzone, \vztwo)\rangle + \vcopt \eqdef \choice{\frac{\vzone}{\vztwo} \in \Z}{\langle\vc\rangle}{\None} +}{ + \filterreduceconstraintdiv(\tenv, \vc) \typearrow \vcopt +} +\end{mathpar} + +\begin{mathpar} +\inferrule[range]{ + \astlabel(\vc) = \ConstraintRange +}{ + \filterreduceconstraintdiv(\tenv, \vc) \typearrow \overname{\langle\vc\rangle}{\vcopt} +} +\end{mathpar} + +\subsection{TypingRule.GetLiteralDivOpt \label{sec:TypingRule.GetLiteralDivOpt}} +\hypertarget{def-getliteraldivopt}{} +The function +\[ +\getliteraldivopt(\overname{\expr}{\ve}) \aslto \overname{\langle\Z\cartimes\Z\rangle}{\rangeopt} +\] +matches the expression $\ve$ to a binary operation expression over the division operation and two literal integer expressions. +If $\ve$ matches this pattern the result $\rangeopt$ is an optional containing the pair of integers appearing in the operand +expressions. Otherwise, the result is $\None$. + +\subsubsection{Prose} +The value $\rangeopt$ is $\langle(\vzone, \vztwo)\rangle$ if $\ve$ is a binary operation expression over the division operation +and two literal integer expressions for the integers $\vzone$ and $\vztwo$ and $\None$ otherwise. + +\subsubsection{Formally} +\begin{mathpar} +\inferrule{ + \rangeopt \eqdef \choice{\ve = \EBinop(\DIV, \ELInt{\vzone}, \ELInt{\vztwo})}{\langle(\vzone, \vztwo)\rangle}{\None} +}{ + \getliteraldivopt(\ve) \typearrow \rangeopt +} +\end{mathpar} + +\subsection{TypingRule.ExplodeIntervals \label{sec:TypingRule.ExplodeIntervals}} +\hypertarget{def-explodeintervals}{} +The function +\[ +\explodeintervals(\overname{\staticenvs}{\tenv} \aslsep \overname{\intconstraint^*}{\cs}) +\aslto \overname{\intconstraint^*}{\newcs} +\] +applies $\explodedinterval$ to each constraint of $\cs$ in $\tenv$ and concatenates the resulting +list, yielding the result in $\newcs$. + +\subsubsection{Prose} +One of the following applies: +\begin{itemize} + \item All of the following apply (\textsc{empty}): + \begin{itemize} + \item $\cs$ is the empty list; + \item $\newcs$ is the empty list. + \end{itemize} + + \item All of the following apply (\textsc{non\_empty}): + \begin{itemize} + \item $\cs$ is the list with $\vc$ as its \head\ and $\csone$ as its \tail; + \item applying $\explodeconstraint$ to $\vc$ in $\tenv$ yields $\vcp$ (a list of constraints); + \item applying $\explodeintervals$ to $\csone$ in $\tenv$ yields $\csonep$; + \item $\newcs$ is the concatenation of $\vcp$ and $\csonep$. + \end{itemize} +\end{itemize} + +\subsubsection{Formally} +\begin{mathpar} +\inferrule[empty]{}{ + \explodeintervals(\tenv, \overname{\emptylist}{\cs}) \typearrow \overname{\emptylist}{\newcs} +} +\end{mathpar} + +\begin{mathpar} +\inferrule[non\_empty]{ + \explodeconstraint(\tenv, \vc) \typearrow \vcp\\ + \explodeintervals(\tenv, \csone) \typearrow \csonep\\ +}{ + \explodeintervals(\tenv, \overname{[\vc] \concat \csone}{\cs}) \typearrow \overname{\vcp \concat \csonep}{\newcs} +} +\end{mathpar} + +\subsection{TypingRule.ExplodeConstraint \label{sec:TypingRule.ExplodeConstraint}} +\hypertarget{def-explodeconstraint}{} +The function +\[ +\explodeconstraint(\overname{\staticenvs}{\tenv} \aslsep \overname{\intconstraint}{\vc}) +\aslto \overname{\intconstraint^*}{\vcs} +\] +expands the constraint $\vc$ into the equivalent list of exact constraints if +$\vc$ matches a n ascending range constraint that is not too large in $\tenv$ +and the singleton list for $\vc$ otherwise. + +\subsubsection{Prose} +One of the following applies: +\begin{itemize} + \item All of the following apply (\textsc{exact}): + \begin{itemize} + \item $\vc$ is an exact constraint; + \item $\vcs$ is the singleton list for $\vc$. + \end{itemize} + + \item All of the following apply (\textsc{range\_reduced}): + \begin{itemize} + \item $\vc$ is a range constraint for the expressions $\va$ and $\vb$; + \item applying $\reducetozopt$ to $\va$ in $\tenv$ yields $\langle\vza\rangle$; + \item applying $\reducetozopt$ to $\vb$ in $\tenv$ yields $\langle\vzb\rangle$; + \item define $\explodedinterval$ as the list of exact constraints for each integer literal in the range starting + at $\vza$ and ending at $\vzb$, inclusively, which is empty if $\vzb < \vza$; + \item applying $\intervaltoolarge$ to $\vza$ and $\vzb$ yields $\vbtoolarge$; + \item define $\vcs$ as the singleton list for $\vc$ if $\vbtoolarge$ is $\True$ and \\ + $\explodedinterval$ otherwise. + \end{itemize} + + \item All of the following apply (\textsc{range\_not\_reduced}): + \begin{itemize} + \item $\vc$ is a range constraint for the expressions $\va$ and $\vb$; + \item applying $\reducetozopt$ to $\va$ in $\tenv$ yields $\vzaopt$; + \item applying $\reducetozopt$ to $\vb$ in $\tenv$ yields $\vzbopt$; + \item at least one of $\vzaopt$ and $\vzbopt$ is $\None$; + \item $\vcs$ is the singleton list for $\vc$. + \end{itemize} +\end{itemize} + +\subsubsection{Formally} +\begin{mathpar} +\inferrule[exact]{ + \astlabel(\vc) = \ConstraintExact +}{ + \explodeconstraint(\tenv, \vc) \typearrow \overname{[\vc]}{\vcs} +} +\end{mathpar} + +\begin{mathpar} +\inferrule[range\_reduced]{ + \vc = \ConstraintRange(\va, \vb)\\ + \reducetozopt(\tenv, \va) \typearrow \langle\vza\rangle\\ + \reducetozopt(\tenv, \vb) \typearrow \langle\vzb\rangle\\ + \explodedinterval \eqdef [\vz \in \vza..\vzb: \ConstraintExact(\ELInt{\vz})]\\ + \intervaltoolarge(\vza, \vzb) \typearrow \vbtoolarge\\ + \vcs \eqdef \choice{\vbtoolarge}{[\vc]}{\explodedinterval} +}{ + \explodeconstraint(\tenv, \vc) \typearrow \vcs +} +\end{mathpar} + +\begin{mathpar} +\inferrule[range\_not\_reduced]{ + \vc = \ConstraintRange(\va, \vb)\\ + \reducetozopt(\tenv, \va) \typearrow \vzaopt\\ + \reducetozopt(\tenv, \vb) \typearrow \vzbopt\\ + \vzaopt = \None \lor \vzbopt = \None +}{ + \explodeconstraint(\tenv, \vc) \typearrow \overname{[\vc]}{\vcs} +} +\end{mathpar} + +\subsection{TypingRule.IntervalTooLarge \label{sec:TypingRule.IntervalTooLarge}} +\hypertarget{def-intervaltoolarge}{} +The function +\[ +\intervaltoolarge(\overname{\Z}{\vzone} \aslsep \overname{\Z}{\vztwo}) \aslto \overname{\Bool}{\vb} +\] +tests whether the set of numbers between $\vzone$ and $\vztwo$, inclusive, contains more than $2^{14}$ +integers, yielding the result in $\vb$. + +\subsubsection{Prose} +The value $\vb$ is $\True$ if and only if the absolute value of $\vzone-\vztwo$ is greater than $2^{14}$. + +\subsubsection{Formally} +\begin{mathpar} +\inferrule{}{ + \intervaltoolarge(\vzone, \vztwo) \typearrow \overname{|\vzone-\vztwo| > 2^{14}}{\vb} +} +\end{mathpar} + +\subsection{TypingRule.BinopIsExploding \label{sec:TypingRule.BinopIsExploding}} +\hypertarget{def-binopisexploding}{} +The function +\[ +\binopisexploding(\overname{\binop}{\op}) \aslto \overname{\Bool}{\vb} +\] +determines whether the binary operation $\op$ should lead to applying $\explodeintervals$ +when the $\op$ is applied to a pair of constraint lists. +It is assumed that $\op$ is one of $\MUL$, $\SHL$, $\POW$, $\PLUS$, $\DIV$, $\MINUS$, $\MOD$, $\SHR$, +and $\DIVRM$. + +\subsubsection{Prose} +The value $\vb$ is $\True$ if and only if $\op$ is one of $\MUL$, $\SHL$, and $\POW$. + +\subsubsection{Formally} +\begin{mathpar} +\inferrule{}{ + \binopisexploding(\op) \typearrow \overname{\op \in \{\MUL, \SHL, \POW\}}{\vb} +} +\end{mathpar} + +\subsubsection{TypingRule.BitFieldsIncluded} +\hypertarget{def-bitfieldsincluded}{} +The predicate +\[ + \bitfieldsincluded(\overname{\staticenvs}{\tenv}, \overname{\bitfield^*}{\bfsone} \aslsep \overname{\bitfield^*}{\bfstwo}) + \aslto \overname{\Bool}{\vb} \cup \overname{\TTypeError}{\TypeErrorConfig} +\] +tests whether the set of bit fields $\bfsone$ is included in the set of bit fields $\bfstwo$ in environment $\tenv$, +returning a type error, if one is detected. + +\subsubsection{Prose} +All of the following apply: +\begin{itemize} + \item checking whether each field $\vbf$ in $\bfsone$ exists in $\bfstwo$ via $\membfs$ yields $\vb_\vbf$\ProseOrTypeError; + \item the result --- $\vb$ --- is the conjunction of $\vb_\vbf$ for all bitfields $\vbf$ in $\bfsone$. +\end{itemize} + +\begin{mathpar} +\inferrule{ + \vbf \in \bfsone: \membfs(\bfstwo, \vbf) \typearrow \vb_\vbf \OrTypeError\\\\ + \vbf \eqdef \bigwedge_{\bf \in \bfsone} \vb_\vbf +}{ + \bitfieldsincluded(\tenv, \bfsone, \bfstwo) \typearrow \vb +} +\end{mathpar} + +\subsubsection{TypingRule.MemBfs} +\hypertarget{def-membfs}{} +The function +\[ + \membfs(\overname{\staticenvs}{\tenv} \aslsep \overname{\bitfield^+}{\bfstwo} \aslsep \overname{\bitfield}{\vbfone}) + \aslto \overname{\Bool}{\vb} +\] +checks whether the bitfield $\vbf$ exists in $\bfstwo$ in the context of $\tenv$, returning the result in $\vb$. + +\subsubsection{Prose} +One of the following applies: +\begin{itemize} + \item All of the following apply (\textsc{none}): + \begin{itemize} + \item the name associated with the bitfield $\vbfone$ is $\name$; + \item finding the bitfield associated with $\name$ in $\bfstwo$ yields $\None$; + \item $\vb$ is $\False$. + \end{itemize} + + \item All of the following apply (\textsc{simple\_any}): + \begin{itemize} + \item the name associated with the bitfield $\vbfone$ is $\name$; + \item finding the bitfield associated with $\name$ in $\bfstwo$ yields $\vbftwo$; + \item $\vbftwo$ is a simple bitfield; + \item symbolically checking whether $\vbfone$ is equivalent to $\vbftwo$ in $\tenv$ yields $\vb$. + \end{itemize} + + \item All of the following apply (\textsc{nested\_simple}): + \begin{itemize} + \item the name associated with the bitfield $\vbfone$ is $\name$; + \item finding the bitfield associated with $\name$ in $\bfstwo$ yields $\vbftwo$; + \item $\vbftwo$ is a nested bitfield with name $\nametwo$, slices $\slicestwo$, and bitfields $\bfstwop$; + \item $\vbfone$ is a simple bitfield; + \item symbolically checking whether $\vbfone$ is equivalent to $\vbftwo$ in $\tenv$ yields $\vb$. + \end{itemize} + + \item All of the following apply (\textsc{nested\_nested}): + \begin{itemize} + \item the name associated with the bitfield $\vbfone$ is $\name$; + \item finding the bitfield associated with $\name$ in $\bfstwo$ yields $\vbftwo$; + \item $\vbftwo$ is a nested bitfield with name $\nametwo$, slices $\slicestwo$, and bitfields $\bfstwop$; + \item $\vbfone$ is a nested bitfield with name $\nameone$, slices $\sliceone$, and $\bfsone$; + \item $\vbone$ is true if and only if $\nameone$ is equal to $\nametwo$; + \item symbolically equating the slices $\slicesone$ and $\slicestwo$ in $\tenv$ yields $\vbtwo$; + \item checking $\bfsone$ is included in $\bfstwop$ in the context of $\tenv$ yields $\vbthree$; + \item $\vb$ is defined as the conjunction of $\vbone$, $\vbtwo$, and $\vbthree$. + \end{itemize} + + \item All of the following apply (\textsc{nested\_typed}): + \begin{itemize} + \item the name associated with the bitfield $\vbfone$ is $\name$; + \item finding the bitfield associated with $\name$ in $\bfstwo$ yields $\vbftwo$; + \item $\vbftwo$ is a nested bitfield with name $\nametwo$, slices $\slicestwo$, and bitfields $\bfstwop$; + \item $\vbfone$ is a typed bitfield; + \item $\vb$ is $\False$. + \end{itemize} + + \item All of the following apply (\textsc{typed\_simple}): + \begin{itemize} + \item the name associated with the bitfield $\vbfone$ is $\name$; + \item finding the bitfield associated with $\name$ in $\bfstwo$ yields $\vbftwo$; + \item $\vbftwo$ is a typed bitfield with name $\nametwo$, slices $\slicestwo$, and type $\ttytwo$; + \item $\vbfone$ is a simple bitfield; + \item symbolically checking whether $\vbfone$ is equivalent to $\vbftwo$ in $\tenv$ yields $\vb$. + \end{itemize} + + \item All of the following apply (\textsc{typed\_nested}): + \begin{itemize} + \item the name associated with the bitfield $\vbfone$ is $\name$; + \item finding the bitfield associated with $\name$ in $\bfstwo$ yields $\vbftwo$; + \item $\vbftwo$ is a typed bitfield with name $\nametwo$, slices $\slicestwo$, and type $\ttytwo$; + \item $\vbfone$ is a nested bitfield; + \item $\vb$ is $\False$. + \end{itemize} + + \item All of the following apply (\textsc{typed\_typed}): + \begin{itemize} + \item the name associated with the bitfield $\vbfone$ is $\name$; + \item finding the bitfield associated with $\name$ in $\bfstwo$ yields $\vbftwo$; + \item $\vbftwo$ is a typed bitfield with name $\nametwo$, slices $\slicestwo$, and type $\ttytwo$; + \item $\vbfone$ is a typed bitfield with name $\nameone$, slices $\slicesone$, and type $\ttyone$; + \item $\vbone$ is true if and only if $\nameone$ is equal to $\nametwo$; + \item symbolically equating the slices $\slicesone$ and $\slicestwo$ in $\tenv$ yields $\vbtwo$; + \item checking whether $\ttyone$ subtypes $\ttytwo$ in $\tenv$ yields $\vbthree$; + \item $\vb$ is defined as the conjunction of $\vbone$, $\vbtwo$, and $\vbthree$. + \end{itemize} +\end{itemize} + +\begin{mathpar} +\inferrule[none]{ + \bitfieldgetname(\vbfone) \typearrow \name\\ + \findbitfieldopt(\name, \bfstwo) \typearrow \None +}{ + \membfs(\tenv, \bfstwo, \vbfone) \typearrow \False +} +\and +\inferrule[simple\_any]{ + \bitfieldgetname(\vbf) \typearrow \name\\ + \findbitfieldopt(\name, \bfstwo) \typearrow \langle \vbftwo \rangle\\ + \astlabel(\vbftwo) = \BitFieldSimple\\ + \bitfieldsequal(\tenv, \vbfone, \vbftwo) \typearrow \vb +}{ + \membfs(\tenv, \bfstwo, \vbfone) \typearrow \vb +} +\end{mathpar} + +\begin{mathpar} +\inferrule[nested\_simple]{ + \bitfieldgetname(\vbf) \typearrow \name\\ + \findbitfieldopt(\name, \bfstwo) \typearrow \langle \vbftwo \rangle\\ + \vbftwo = \BitFieldNested(\nametwo, \slicestwo, \bfstwop)\\ + \vbfone = \BitFieldSimple(\Ignore)\\ + \bitfieldsequal(\tenv, \vbfone, \vbftwo) \typearrow \vb +}{ + \membfs(\tenv, \bfstwo, \vbfone) \typearrow \overname{\False}{\vb} +} +\and +\inferrule[nested\_nested]{ + \bitfieldgetname(\vbf) \typearrow \name\\ + \findbitfieldopt(\name, \bfstwo) \typearrow \langle \vbftwo \rangle\\ + \vbftwo = \BitFieldNested(\nametwo, \slicestwo, \bfstwop)\\ + \vbfone = \BitFieldNested(\nameone, \slicesone, \bfsone)\\ + \vbone \eqdef \nameone = \nametwo\\ + \slicesequal(\tenv, \slicesone, \slicestwo) \typearrow \vbtwo\\ + \bitfieldsincluded(\tenv, \bfsone, \bfstwop) \typearrow \vbthree\\ + \vb \eqdef \vbone \land \vbtwo \land \vbthree +}{ + \membfs(\tenv, \bfstwo, \vbfone) \typearrow \vb +} +\and +\inferrule[nested\_typed]{ + \bitfieldgetname(\vbf) \typearrow \name\\ + \findbitfieldopt(\name, \bfstwo) \typearrow \langle \vbftwo \rangle\\ + \vbftwo = \BitFieldNested(\nametwo, \slicestwo, \bfstwop)\\ + \astlabel(\vbfone) = \BitFieldType +}{ + \membfs(\tenv, \bfstwo, \vbfone) \typearrow \overname{\False}{\vb} +} +\end{mathpar} + +\begin{mathpar} +\inferrule[typed\_simple]{ + \bitfieldgetname(\vbf) \typearrow \name\\ + \findbitfieldopt(\name, \bfstwo) \typearrow \langle \vbftwo \rangle\\ + \vbftwo = \BitFieldType(\nametwo, \slicestwo, \ttytwo)\\ + \vbfone = \BitFieldSimple(\Ignore)\\ + \bitfieldsequal(\tenv, \vbfone, \vbftwo) \typearrow \vb +}{ + \membfs(\tenv, \bfstwo, \vbfone) \typearrow \vb +} +\and +\inferrule[typed\_nested]{ + \bitfieldgetname(\vbf) \typearrow \name\\ + \findbitfieldopt(\name, \bfstwo) \typearrow \langle \vbftwo \rangle\\ + \vbftwo = \BitFieldType(\nametwo, \slicestwo, \ttytwo)\\ + \astlabel(\vbfone) = \BitFieldNested +}{ + \membfs(\tenv, \bfstwo, \vbfone) \typearrow \overname{\False}{\vb} +} +\and +\inferrule[typed\_typed]{ + \bitfieldgetname(\vbf) \typearrow \name\\ + \findbitfieldopt(\name, \bfstwo) \typearrow \langle \vbftwo \rangle\\ + \vbftwo = \BitFieldType(\nametwo, \slicestwo, \ttytwo)\\ + \vbfone = \BitFieldType(\nameone, \slicesone, \ttyone)\\ + \vbone \eqdef \nameone = \nametwo\\ + \slicesequal(\tenv, \slicesone, \slicestwo) \typearrow \vbtwo\\ + \subtypesat(\tenv, \ttyone, \ttytwo) \typearrow \vbthree \OrTypeError\\\\ + \vb \eqdef \vbone \land \vbtwo \land \vbthree +}{ + \membfs(\tenv, \bfstwo, \vbfone) \typearrow \vb +} +\end{mathpar} + +\hypertarget{def-checkstructurelabel}{} +\subsubsection{TypingRule.CheckStructure \label{sec:TypingRule.CheckStructure}} +The function +\[ + \checkstructurelabel(\overname{\staticenvs}{\tenv} \aslsep \overname{\ty}{\vt} \aslsep \overname{\astlabels}{\vl}) \aslto + \{\True\} \cup \TTypeError +\] +returns $\True$ is $\vt$ is has the \structure\ a of type corresponding to the AST label $\vl$ and a type error otherwise. + +\subsubsection{Prose} +One of the following applies: +\begin{itemize} + \item All of the following apply (\textsc{okay}): + \begin{itemize} + \item determining the \structure\ of $\vt$ yields $\vtp$\ProseOrTypeError; + \item $\vtp$ has the label $\vl$; + \item the result is $\True$; + \end{itemize} + + \item All of the following apply (\textsc{error}): + \begin{itemize} + \item determining the \structure\ of $\vt$ yields $\vtp$\ProseOrTypeError; + \item $\vtp$ does not have the label $\vl$; + \item the result is a type error indicating that $\vt$ was expected to have the \structure\ of a type with the AST label $\vl$. + \end{itemize} +\end{itemize} + +\subsubsection{Formally} +\begin{mathpar} +\inferrule[okay]{ + \tstruct(\vt) \typearrow \vtp \OrTypeError\\\\ + \astlabel(\vtp) = \vl +} +{ + \checkstructurelabel(\tenv, \vt, \vl) \typearrow \True +} +\and +\inferrule[error]{ + \tstruct(\vt) \typearrow \vtp\\ + \astlabel(\vtp) \neq \vl +} +{ + \checkstructurelabel(\tenv, \vt, \vl) \typearrow \TypeErrorVal{UnexpectedTypeStructure} +} +\end{mathpar} + +\subsubsection{TypingRule.ToWellConstrained} +\hypertarget{def-towellconstrained}{} +The function +\[ + \towellconstrained(\overname{\ty}{\vt}) \aslto \overname{\ty}{\vtp} +\] +returns the \wellconstrainedversion\ of a type $\vt$ --- $\vtp$, which is defined as follows. + +One of the following applies: +\begin{itemize} + \item All of the following apply (\textsc{t\_int\_parameterized}): + \begin{itemize} + \item $\vt$ is a \parameterizedintegertype\ for the variable $\vv$; + \item $\vtp$ is the well-constrained integer constrained by the variable expression for $\vv$, + that is, $\TInt(\wellconstrained(\constraintexact(\EVar(\vv))))$. + \end{itemize} + + \item All of the following apply (\textsc{t\_int\_other, other}): + \begin{itemize} + \item $\vt$ is not a \parameterizedintegertype\ for the variable $\vv$; + \item $\vtp$ is $\vt$. + \end{itemize} +\end{itemize} + +\subsubsection{Formally} +\begin{mathpar} +\inferrule[t\_int\_parameterized]{} +{ + \towellconstrained(\TInt(\parameterized(\vv))) \typearrow\\ \TInt(\wellconstrained(\constraintexact(\EVar(\vv)))) +} +\and +\inferrule[t\_int\_other]{ + \astlabel(\vi) \neq \parameterized +}{ + \towellconstrained(\TInt(\vi)) \typearrow \vt +} +\and +\inferrule[other]{ + \astlabel(\vt) \neq \TInt +}{ + \towellconstrained(\vt) \typearrow \vt +} +\end{mathpar} + +\subsubsection{TypingRule.GetWellConstrainedStructure} +\hypertarget{def-getwellconstrainedstructure}{} +The function +\[ + \getwellconstrainedstructure(\overname{\staticenvs}{\tenv} \aslsep \overname{\ty}{\vt}) + \aslto \overname{\ty}{\vtp} \cup \overname{\TTypeError}{\TypeErrorConfig} +\] +returns the \wellconstrainedstructure\ of a type $\vt$ in the static environment $\tenv$ --- $\vtp$, which is defined as follows. +\ProseOtherwiseTypeError + +\subsubsection{Prose} +All of the following apply: +\begin{itemize} + \item the \structure\ of $\vt$ in $\tenv$ is $\vtone$\ProseOrTypeError; + \item the well-constrained version of $\vtone$ is $\vtp$. +\end{itemize} + +\subsubsection{Formally} +\begin{mathpar} +\inferrule{ + \tstruct(\tenv, \vt) \typearrow \vtone \OrTypeError\\\\ + \towellconstrained(\vtone) \typearrow \vtp +}{ + \getwellconstrainedstructure(\tenv, \vt) \typearrow \vtp +} +\end{mathpar} + +\subsubsection{TypingRule.GetBitvectorWidth} +\hypertarget{def-getbitvectorwidth}{} +The function +\[ + \getbitvectorwidth(\overname{\staticenvs}{\tenv} \aslsep \overname{\ty}{\vt}) \aslto + \overname{\expr}{\ve} \cup \TTypeError +\] +returns the expression $\ve$, which represents the width of the bitvector type $\vt$, +or a type error if $\vt$ is not a bitvector type or another type error is detected. + +\subsubsection{Prose} +One of the following applies: +\begin{itemize} + \item All of the following apply (\textsc{okay}): + \begin{itemize} + \item obtaining the \structure\ of $\vt$ in $\tenv$ yields a bitvector type with width expression $\ve$, + that is, $\TBits(\ve, \Ignore)$\ProseOrTypeError; + \item the result is $\ve$. + \end{itemize} + + \item All of the following apply (\textsc{error}): + \begin{itemize} + \item obtaining the \structure\ of $\vt$ in $\tenv$ yields a type that is not a bitvector type; + \item the result is a type error indicating that a bitvector type was expected. + \end{itemize} +\end{itemize} + +\subsubsection{Formally} +\begin{mathpar} +\inferrule[okay]{ + \tstruct(\tenv, \vt) \typearrow \TBits(\ve, \Ignore) \OrTypeError +}{ + \getbitvectorwidth(\tenv, \vt) \typearrow \ve +} +\and +\inferrule[error]{ + \tstruct(\tenv, \vt) \typearrow \vtp\\ + \astlabel(\vtp) \neq \TBits +}{ + \getbitvectorwidth(\tenv, \vt) \typearrow \TypeErrorVal{\ExpectedBitvectorType} +} +\end{mathpar} + +\subsubsection{TypingRule.CheckBitsEqualWidth} +\hypertarget{def-checkbitsequalwidth}{} +The function +\[ + \checkbitsequalwidth( + \overname{\staticenvs}{\tenv} \aslsep + \overname{\ty}{\vtone} \aslsep + \overname{\ty}{\vttwo}) \aslto + \{\True\} \cup \TTypeError +\] +tests whether the types $\vtone$ and $\vttwo$ are bitvector types of the same width. +If the answer is positive, the result is $\True$. \ProseOtherwiseTypeError + +\subsubsection{Prose} +All of the following apply: +\begin{itemize} + \item obtaining the width of $\vtone$ in $\tenv$ (via $\getbitvectorwidth$) yields the expression $\vn$\ProseOrTypeError; + \item obtaining the width of $\vttwo$ in $\tenv$ (via $\getbitvectorwidth$) yields the expression $\vm$\ProseOrTypeError; + \item One of the following applies: + \begin{itemize} + \item All of the following apply (\textsc{true}): + \begin{itemize} + \item symbolically checking whether the bitwidth expressions $\vn$ and $\vm$ are equal (via $\bitwidthequal$) yields $\True$; + \item the result is $\True$. + \end{itemize} + + \item All of the following apply (\textsc{error}): + \begin{itemize} + \item symbolically checking whether the bitwidth expressions $\vn$ and $\vm$ are equal (via $\bitwidthequal$) yields $\False$; + \item the result is a type error indicating that the bitwidths are different. + \end{itemize} + \end{itemize} +\end{itemize} + +\subsubsection{Formally} +\begin{mathpar} +\inferrule[true]{ + \getbitvectorwidth(\tenv, \vtone) \typearrow \vn \OrTypeError\\\\ + \getbitvectorwidth(\tenv, \vttwo) \typearrow \vm \OrTypeError\\\\ + \bitwidthequal(\tenv, \vn, \vm) \typearrow \True +}{ + \checkbitsequalwidth(\tenv, \vtone, \vttwo) \typearrow \True +} +\and +\inferrule[error]{ + \getbitvectorwidth(\tenv, \vtone) \typearrow \vn \OrTypeError\\\\ + \getbitvectorwidth(\tenv, \vttwo) \typearrow \vm \OrTypeError\\\\ + \bitwidthequal(\tenv, \vn, \vm) \typearrow \False +}{ + \checkbitsequalwidth(\tenv, \vtone, \vttwo) \typearrow \TypeErrorVal{DifferentBitwidths} +} +\end{mathpar} diff --git a/asllib/doc/Semantics.tex b/asllib/doc/Semantics.tex new file mode 100644 index 000000000..e87a10dbb --- /dev/null +++ b/asllib/doc/Semantics.tex @@ -0,0 +1,570 @@ +\chapter{Semantics Definitions\label{chap:Semantics}} + +The semantics of ASL define all valid behaviors of a given ASL specification. +More precisely, an ASL specification is first parsed into an \emph{abstract syntax tree}, +or AST, for short. Second, a type checker analyzes the \emph{untyped AST} to determine whether it +is well-typed and, if successful, returns a \emph{static environment} and a \emph{typed AST}. +Otherwise, it returns a type error. + +Tools such as interpreters, Verilog simulators, and verifiers can operate over the typed AST, based on the definition +of the semantics in this reference, to test and analyze a given specification. + +\paragraph{Understanding the Semantics Formalization:} +We assume basic familiarity with the ASL language constructs. +The ASL semantics is defined in terms of its AST, +and as a consequence familiarity with the AST is required to understand the semantics. +The few components of the type system needed to understand the ASL semantics are explained in context. +The mathematical background needed to understand the mathematical formalization +of the ASL semantics appears in \chapref{FormalSystem} and \secref{semanticsbuildingblocks}. + +\section{When Do ASL Specifications Have Meaning\label{sec:MeaningfulASLSpecifications}} +The ASL semantics defined here assign meaning only to \emph{well-typed specifications}. +That is, specifications for which the type-checker produces a static environment rather than +a type error. +Specifications that are not well-typed have no defined semantics. +In the rest of this reference, we assume well-typed specifications. + +ASL admits non-determinism, for example via the \texttt{UNKNOWN} expression. +This means that a given specification might have (potentially infinitely) many +\hyperlink{def-derivationtree}{derivation trees}. + +An ASL specification is \emph{terminating} when \underline{all} of its derivation trees are finite. + +Although ASL does not require specifications to terminate, the semantics defined in this +reference assign meaning only to terminating specifications. +A future version of this reference, will assign meaning to non-terminating specifications. + +\section{Basic Semantic Concepts} +The ASL semantics are given by relations between \emph{semantic configurations}, +or \hyperlink{def-configuration}{\emph{semantic configurations}}~\cite{SemanticsWithApplicationsBook}, for short. +We refer to relations between semantic configurations as \emph{semantic relations}. +Semantic configurations encapsulate information needed to transition into other semantic configurations, such as: +\begin{itemize} + \item a \emph{dynamic environment}, which binds variables to values; + \item the typed AST node that needs to be evaluated; + \item a \emph{concurrent execution graph}, as per a given memory model; and + \item values resulting from evaluating expressions. +\end{itemize} +The semantic relations are constructively defined via \emph{semantic rules}. +These semantic rules are defined by induction over the typed AST. + +\paragraph{Execution:} +A valid execution of an ASL specification transitions from an \emph{initial semantic configuration}, +which consists of the given specification and the standard library specification, to an output semantic configuration +consisting of an output value and a concurrent execution graph. + +\paragraph{Primitive Subprograms:} +The semantics of ASL are parameterized by a set of primitive subprograms --- +subprograms whose implementation is not defined by ASL statements and whose effect on the dynamic environment +is defined externally. Critically, access to memory is given by primitive subprograms. + +We define two types of semantics --- \emph{sequential semantics} and \emph{concurrent semantics}. + +\paragraph{Concurrent Semantics:} +The concurrent semantics operate over concurrent execution graphs. +Intuitively, these graphs define Read Effects and Write Effects to variables and constraints over those effects. +Together with the constraints that define a given memory model (such as the ARM memory model~\cite{AlglaveDGHM21}), +these graphs axiomatically define +the valid interactions of shared variables of a given specification. + +\paragraph{Sequential Semantics:} +The sequential semantics correspond to executing an ASL specification in the context of a single thread +of execution; notice that ASL does not contain any concurrency constructs. +% +Technically, the sequential semantics are defined by omitting the concurrent execution graph components +from all semantic configurations. + +\section{Semantics Building Blocks} +\label{sec:semanticsbuildingblocks} +This section defines the mathematical types over which our semantics are defined. +An \hyperlink{eval-example}{example} of semantic evaluation appears at the end. + +\section{Semantic Configurations\label{sec:SemanticConfigurations}} + +Semantic configurations express intermediate states related by \emph{semantic relations}. +% +More precisely, semantic relations relate two distinct sets of semantic configurations --- +\emph{input semantic configurations} and \emph{output semantic configurations}. +Input semantic configurations consist of an environment and an AST node. +Output semantic configurations consist of an output environment, values, +and concurrent execution graphs. +% +Semantic configurations wrap together elements such as environments and AST nodes +and associate them with a \emph{configuration domain}. Input semantic configuration domains +determine the semantic relation they pertain to, while output semantic configuration +domains distinguish between conceptually different kinds of outputs, for example +ones where an exception was raised, ones when a dynamic error occurred, etc. + +We now explain the components over which semantic configurations are defined: +\begin{itemize} + \item Native values. + \item Static Environments, which consist of the information inferred + by the type-checker for the specification. + \item Dynamic Environments (\defref{dynamicenvironments}) associate \nativevalues\ to variables. + \item Concurrent Execution Graphs (\secref{concurrentexecutiongraphs}) track Read and Write Effects over variables. +\end{itemize} + +\hypertarget{def-vals}{} +\hypertarget{def-nativevalue}{} +\hypertarget{def-nativevalues}{} +\section{Native Values\label{sec:nativevalues}} +Semantic evaluation binds values to storage elements when a specification is semantically evaluated. +To formalize this, we define the set of \emph{\nativevalues}, denoted $\vals$ +(\texttt{NV} stands for Native Value). + +\subsection{Prose} +The set of \nativevalues\ $\vals$ is the minimal set satisfying all of the following rules: +\begin{itemize} + \item \textsc{basis set}: if $\vv$ is a literal then $\nvliteral{\vv}$ is a \nativevalue; + \item \textsc{tuple values and array values}: if $\vl$ is a list of \nativevalues\ then $\nvvector{\vl}$ is a \nativevalue; + \item \textsc{record values}: if $\vr$ is a finite function from identifiers to \nativevalues\ then $\nvrecord{\vr}$ is a \nativevalue. +\end{itemize} + +\subsection{Formally} +\hypertarget{def-nvliteral}{} +\hypertarget{def-nvvector}{} +\hypertarget{def-nvrecord}{} +\begin{mathpar} + \inferrule[(Basis Set: Integers, Reals, Booleans, Strings, and Bitvectors)] + {\vv \in \literal} + { \nvliteral{\vv} \in \vals } + \and + \inferrule[(Tuple Values and Array Values)]{\vvl \in \vals^*} + { \nvvector{\vvl} \in \vals } + \and + \inferrule[(Record Values)] + {\vr : \Identifiers \rightarrowfin \vals} + { \nvrecord{\vr} \in \vals } +\end{mathpar} + +We define the following shorthands for \nativevalue\ literals: +\hypertarget{def-nvint}{} +\[ +\begin{array}{rcl} +\nvint(z) &\triangleq& \nvliteral{\lint(z)} \hypertarget{def-nvbool}{}\\ +\nvbool(b) &\triangleq& \nvliteral{\lbool(b)} \hypertarget{def-nvreal}{}\\ +\nvreal(r) &\triangleq& \nvliteral{\lreal(r)} \hypertarget{def-nvstring}{}\\ +\nvstring(s) &\triangleq& \nvliteral{\lstring(s)} \hypertarget{def-nvbitvector}{}\\ +\nvbitvector(v) &\triangleq& \nvliteral{\lbitvector(v)}\\ +\end{array} +\] + +We define the following types of \nativevalues: +\hypertarget{def-tint}{} +\[ +\begin{array}{rcl} + \tint &\triangleq& \{ \nvint(z) \;|\; z \in \Z\} \hypertarget{def-tbool}{}\\ + \tbool &\triangleq& \{ \nvbool(\True), \nvbool(\False) \} \hypertarget{def-treal}{}\\ + \treal &\triangleq& \{ \nvreal(r) \;|\; r \in \Q\} \hypertarget{def-tstring}{}\\ + \tstring &\triangleq& \{ \nvstring(s) \;|\; s \in \Strings\} \hypertarget{def-tbitvector}{}\\ + \tbitvector &\triangleq& \{ \nvbitvector(\textit{bits}) \;|\; \textit{bits} \in \{0,1\}^*\} \hypertarget{def-tvector}{}\\ + \tvector &\triangleq& \{ \nvvector{\textit{vals}} \;|\; \textit{vals} \in \vals^*\} \hypertarget{def-trecord}{}\\ + \trecord &\triangleq& \{ \nvrecord{\fieldmap} \;|\; \fieldmap \in \Identifiers\rightarrowfin\vals\}\\ +\end{array} +\] + +\hypertarget{def-dynamicenvs}{} +\begin{definition}[Dynamic Environments\label{def:dynamicenvironments}] +A \emph{sequential dynamic environment}, or \\ \emph{dynamic environment}, for short, is a structure which, +associates \nativevalues\ to variables. +Formally, a sequential environment $\denv \in \dynamicenvs$ is a pair consisting of a partial function +(see \defref{PartialFunction}) from global +variable names to their \nativevalue, and a partial function from local variable names to their +\nativevalues: +\[ +\begin{array}{rcl} +\dynamicenvs &\triangleq& \globaldynamicenvs \times \localdynamicenvs \\ +\globaldynamicenvs &\triangleq& (\Identifiers \partialto \vals) \\ +\localdynamicenvs &\triangleq& (\Identifiers \partialto \vals) \\ +\end{array} +\] +\end{definition} + +\paragraph{Static Environments} +A \emph{static environment} (see \secref{StaticEnvironments}) $\tenv \in \staticenvs$ (also referred to as a \emph{type environment}) +is produced by the type-checker from the untyped AST. + +We assume that the static environment supports the following functions: +\hypertarget{def-findfunc}{} +\hypertarget{def-typesatisfies}{} +\[ + \begin{array}{rcl} + \findfunc &:& \staticenvs \times \Identifiers \partialto \func\\ + \typesat &:& \staticenvs \times (\ty \times \ty) \rightarrow \{\True, \False\} + \end{array} +\] +The partial function $\findfunc$ returns the typed AST of the subprogram for a given identifier. +(Recall that ASL allows subprogram overloading so a name does not uniquely identify +a specific subprogram. +However, the type-checker renames each function uniquely so that it can be accessed based +on its name alone.) +% +The function $\typesat(\vt, \vs)$ returns true +if the type $\vt$ \emph{type-satisfies} the type $\vs$ +(see \secref{TypingRule.TypeSatisfaction}). +This is used in matching a raised exception to a corresponding catch clause. + +\hypertarget{def-envs}{} +\begin{definition}[Environments] +Environments pair static environments with dynamic environments: +$\envs = \staticenvs \times \dynamicenvs$. +\end{definition} +\hypertarget{def-env}{} +We write $\env \in \envs$ to range over environments. +% +From the perspective of the semantics, the static environment is immutable. +That is, all environments share the same static environment. + +\subsection{Concurrent Execution Graphs\label{sec:concurrentexecutiongraphs}} + +The concurrent semantics of an ASL specification utilize \emph{concurrent execution graphs} +(\emph{execution graphs}, for short), +which track the Read and Write Effects over variables, yielded by the sequential semantics, +and the \emph{ordering constraints} between those effects. +The graphs resulting from executing an ASL specification are converted into +\emph{candidate execution graphs}, which are introduced, defined, +and used in~\cite{AlglaveMT14,alglave2016syntax,AlglaveDGHM21}. + +\hypertarget{def-xgraphs}{} +Formally, an execution graph $\xgraph = (N^\xgraph, E^\xgraph, O^\xgraph) \in \XGraphs$ +is defined via a set of \emph{nodes} ($N^\xgraph$), a set of \emph{edges} ($E^\xgraph$), and a set of \emph{output nodes} ($O^\xgraph$): +\hypertarget{def-nodes}{} +\[ +\begin{array}{rcl} +\XGraphs &\triangleq& \pow{\Nodes} \times \pow{\Nodes \times \Nodes \times \Labels} \times \pow{\Nodes} \hypertarget{def-read}{}\hypertarget{def-write}{}\\ +\Nodes &\triangleq& \N \times \{ \Read, \Write \} \times \Identifiers \hypertarget{def-labels}{}\\ +\Labels &\triangleq& \{ \asldata, \aslctrl, \aslpo \} +\end{array} +\] + +Nodes represent unique Read and Write Effects. Formally, a node $(u,l,\id) \in \Nodes$ associates a unique instance counter $u$ +to an \emph{ordering label} $l$, which specifies whether it represents a Read Effect of a Write Effect to a variable named $\id$. +% +We say that en Effect \texttt{E1} is \emph{$l$-before} another Effect \texttt{E2}, for $l\in \Labels$ and a given execution graph +$g$, when $(\texttt{E1}, l, \texttt{E2}) \in E^g$. + +An edge represents an ordering constraint between two effects, which can be one of the following: +\hypertarget{def-asldata}{} +\begin{description} +\item[$\asldata$] Represents a \emph{data dependency}. +That is, when one effect hands over its data to another effect. +\hypertarget{def-aslctrl}{} +\item[$\aslctrl$] Represents a \emph{control dependency}. +That is, when a Read Effect to a variable determines the flow of control (e.g., which condition of a branch is taken), +which then leads to another Read/Write Effect. +\hypertarget{def-aslpo}{} +\item[$\aslpo$] Represents a \emph{program order}. +That is, when two Effects are generated by ASL constructs, which are separated by a semicolon in the text of the specification, +or appear in successive iterations of loop a unrolling. +% That is, when two effects are defined to be ordered according to the sequential semantics. +\end{description} + +An execution graph is \emph{well-formed} if all nodes have unique instance counters, edges connect graph nodes, +and the output nodes are contained in the set of nodes: +\[ + \begin{array}{rcl} + \forall n, n' \in N^\xgraph &.& n=(u,l,\id) \wedge n=(u',l',\id') \;\Rightarrow\; u \neq u' \\ + \forall e \in E^\xgraph &.& e=(n, n', l) \;\Rightarrow\; n, n' \in N^\xgraph \\ + & & O^\xgraph \subseteq N^\xgraph \enspace. + \end{array} +\] +\hypertarget{def-emptygraph}{} + +We denote the empty execution graph $\emptygraph \triangleq (\emptyset, \emptyset, \emptyset)$. +% +We define the following functions, which return an execution graph that represents a single Read/Write Effect to a variable \texttt{x}. +\hypertarget{def-writeeffect}{} +\hypertarget{def-readeffect}{} +\begin{definition}[Read/Write Effects] +\[ + \begin{array}{rclll} + \WriteEffect(\vx) &\triangleq& (\{n\}, \emptyset, \{n\}) & \text{where } n=(u, \Write, \vx), & u\in\N \text{ is fresh}\\ + \ReadEffect(\vx) &\triangleq& (\{n\}, \emptyset, \{n\}) & \text{where } n=(u, \Read, \vx), & u\in\N \text{ is fresh}\\ + \end{array} +\] +\end{definition} + +We also define two ways to compose execution graphs --- \emph{unordered composition} and +\emph{ordered composition with a given label}. + +\hypertarget{def-parallel}{} +\begin{definition}[Unordered Graph Composition] +Given two execution graphs $S_1 = (N_1, E_1, O_1)$ and $S_1 = (N_2, E_2, O_2)$ their unordered composition, +denoted $S_1 \parallelcomp S_2$ is defined as follows: +\[ + S_1 \parallelcomp S_2\triangleq (N_1 \cup N_2, E_1 \cup E_2, O_1 \cup O_2) \enspace. +\] +Intuitively, this composition conveys the fact that there are no ordering constraints between the effects +in the arguments graphs. +\end{definition} + +\hypertarget{def-ordered}{} +\begin{definition}[Ordered Graph Composition] +Given two execution graphs, \\ $S_1 = (N_1, E_1, O_1)$ and $S_1 = (N_2, E_2, O_2)$ and an ordering label $l$, +the ordered composition $\ordered{S_1}{l}{S_2}$ is defined as follows: +\[ + \ordered{S_1}{l}{S_2} \triangleq (N_1 \cup N_2,\ E_1 \cup E_2 \cup (O_1 \times \{l\} \times N_2),\ O_2) \enspace. +\] +Intuitively, this composition constrains the output effects of $S_1$ to appear before any effect of $S_2$ with respect +to the given ordering label. +\end{definition} + +\subsection{Kinds of Semantic Configurations\label{sec:KindsOfSemanticConfigurations}} + +Recall that the ASL semantics defines a relation between input semantic configurations and output semantic configurations +(\secref{SemanticConfigurations}). +Input semantic configuration domains are unique to the semantic relation that employs them. +For that reason, we name semantic relations by the name of the corresponding configuration domain of the input semantic configuration. +For example, the semantic relation that employs input semantic configurations with the domain $\texttt{eval\_expr}$ +is named $\texttt{eval\_expr}$. +% +We will often use the prefix \texttt{eval} for semantic relations with the intuition being that their input semantic configurations +should be semantically evaluated, yielding an output semantic configuration. + +ASL semantics mainly utilizes the following types of output semantic configurations: +\begin{description} + \item[Normal Values.] \hypertarget{def-normal}{} + Semantic configurations consisting of different combinations of values, + execution graphs, and environments, representing intermediate results + generated while evaluating statements: + \begin{itemize} + \item $\Normal(\vals \times \XGraphs)$, + \item $\Normal((\vals \times \XGraphs), \envs)$, + \item $\Normal(((\vals \times \vals)^* \times \XGraphs), \envs)$, + \item $\Normal(\XGraphs, \envs)$, + \item $\Normal((\vals^* \times \XGraphs), \envs)$, and + \item $\Normal((\vals\times\XGraphs)^*, \envs)$. + \end{itemize} + + \hypertarget{def-throwing}{} + \item[Exceptions.] Semantic configurations in + \[ + \Throwing(\langle \valuereadfrom(\vals,\Identifiers) \times \ty\rangle \times \XGraphs, \envs) + \] + represent thrown exceptions. + \hypertarget{def-valuereadfrom}{} + + There are two flavors of exceptions: + exceptions without an exception value (as in \texttt{throw;}), and ones with an exception value, + an identifier to which the Read Effect is attributed, and an associated type. + The type $\valuereadfrom(\vals,\Identifiers)$ is a semantic configuration nested inside an exception semantic configuration. + The ASL semantics propagates these \emph{exceptional semantic configurations} to the nearest catch clause that matches + them, and otherwise they are caught at the top-level and reported as errors (see dynamic errors below). + + \hypertarget{def-returning}{} + \item[Returned Values.] Semantic configurations in $\Returning((\vals^* \times \XGraphs), \envs)$ + represent (tuples of) values being returned by the currently executing subprogram. + The ASL semantics propagates these \emph{early return semantic configurations} to the respective call expression/statement. + + \hypertarget{def-continuing}{} + \item[In-flight Subprogram.] Semantic semantic configurations in $\Continuing(\XGraphs, \envs)$ + represent the fact that a subprogram has more statements to execute. + The ASL semantics treats these semantic configurations as a signal to keep evaluating the remainder + of the subprogram currently being evaluated. +%where is this used? + + \hypertarget{def-error}{} + \item[Dynamic Errors.] Semantic configurations in $\Error(\Strings)$ + represent dynamic errors (for example, division by zero). + The ASL semantics is set up such that when these \emph{error semantic configurations} appear, + the evaluation of the entire specification terminates by outputting them. +\end{description} +Helper relations often have output semantic configurations that are just tuples, without an associated configuration domain. + +We define the following shorthands for types of output semantic configurations: +\hypertarget{def-tnormal}{} +\hypertarget{def-tcontinuing}{} +\hypertarget{def-tthrowing}{} +\hypertarget{def-treturning}{} +\hypertarget{def-terror}{} +\[ + \begin{array}{rcl} + \TNormal & \triangleq & \Normal(\vals, \XGraphs) \cup \Normal((\vals \times \XGraphs), \envs)\ \cup \\ + & & \Normal(((\vals \times \vals)^* \times \XGraphs), \envs) \cup \Normal(\XGraphs, \envs)\ \cup \\ + & & \Normal((\vals^* \times \XGraphs), \envs) \cup \Normal((\vals\times\XGraphs)^*, \envs)\\ + \TThrowing & \triangleq & \Throwing(\langle\vals \times \ty\rangle \times \XGraphs, \envs)\\ + \TContinuing & \triangleq & \Continuing(\XGraphs, \envs)\\ + \TReturning & \triangleq & \Returning((\vals^* \times \XGraphs), \envs)\\ + \TError & \triangleq & \Error(\Strings)\\ + \end{array} +\] + +We will say that a semantic transition \emph{terminates}: +\begin{itemize} +\item \emph{normally} when the output semantic configuration domain is +$\Normal$, +\item \emph{exceptionally} when the output semantic configuration domain is +$\Throwing$, +\item \emph{erroneously} when the output semantic configuration domain is +$\Error$, and +\item \emph{abnormally} when it either terminates exceptionally or +erroneously. +\end{itemize} + +We introduce the following shorthands for semantic configurations where all variables +appearing are \hyperlink{def-freshvariables}{fresh}: +\begin{itemize} +\hypertarget{def-throwingconfig}{} +\item $\ThrowingConfig \triangleq \Throwing((\vv, \vg), \newenv)$. +\hypertarget{def-errorconfig}{} +\item $\ErrorConfig \triangleq \Error(\vs)$. +\hypertarget{def-returningconfig}{} +\item $\ReturningConfig \triangleq \Returning((\vvs,\newg), \newenv)$ +is an early return semantic configuration. +\hypertarget{def-continuingconfig}{} +\item $\ContinuingConfig \triangleq \Continuing(\newg, \newenv)$. +\end{itemize} + +\subsection{Extracting and Substituting Elements of Semantic configurations} + +\hypertarget{def-graphof}{} +\hypertarget{def-environof}{} +Given a semantic configuration $C$, we define the graph component of the semantic configuration, \\ +$\graphof{C}$, and the environment of the semantic configuration, $\environof{C}$, as follows: +\[ +\begin{array}{lcc} + C & \graphof{C} & \environof{C}\\ + \hline + \Normal(\vv,\vg) & \vg & \text{undefined}\\ + \Normal((\vv,\vg), \env) & \vg & \env\\ + \Normal(([i=1..k: (\texttt{va}_i,\texttt{vb})],\vg), \env) & \vg & \env\\ + \Normal(\vg, \env) & \vg & \env\\ + \Normal([\vv_{1..k}], \vg) & \vg & \env\\ + \Normal([i=1..k: (\vv_i,\vg_i)], \env) & \text{undefined} & \env\\ + \Throwing((\valuereadfrom(\vx,\vv),\vg), \env) & \vg & \env\\ + \Returning(([\vv_{1..k}],\vg), \env) & \vg & \env\\ + \Continuing(\vg, \env) & \vg & \env\\ +\end{array} +\] + +\hypertarget{def-withgraph}{} +Given a semantic configuration $C$, we define $\withgraph{C}{\vgp}$ to be a semantic configuration +like $C$ where the graph component is substituted with $\vgp$: +\[ +\begin{array}{ll} + C & \withgraph{C}{\vgp}\\ + \hline + \Normal(\vv,\vg) & \Normal(\vv,\vgp)\\ + \Normal((\vv,\vg), \env) & \Normal((\vv,\vgp), \env)\\ + \Normal((i=1..k: (\texttt{va}_i,\texttt{vb}),\vg), \env) & \Normal((i=1..k: (\texttt{va}_i,\texttt{vb}),\vgp), \env)\\ + \Normal(\vg, \env) & \Normal(\vgp, \env)\\ + \Normal(i=1..k: \vv_i, \vg) & \Normal(i=1..k: \vv_i, \vgp)\\ + \Normal([i=1..k: (\vv_i,\vg_i)], \env) & \text{undefined}\\ + \Throwing((\valuereadfrom(\vx,\vv),\vg), \env) & \Throwing((\valuereadfrom(\vx,\vv),\vgp), \env)\\ + \Returning((i=1..k: \vv_i,\vg), \env) & \Returning((i=1..k: \vv_i,\vgp), \env)\\ + \Continuing(\vg, \env) & \Continuing(\vgp, \env)\\ +\end{array} +\] +\hypertarget{def-withenviron}{} +Similarly, we define the $\withenviron{C}{\envp}$ to be a semantic configuration +like $C$ where the environment component, if one exists, is substituted with $\envp$: +\[ +\begin{array}{ll} + \textbf{Semantic configuration} & \withenviron{C}{\envp}\\ + \hline + \Normal(\vv,\vg) & \text{undefined}\\ + \Normal((\vv,\vg), \env) & \Normal((\vv,\vg), \envp)\\ + \Normal((i=1..k: (\texttt{va}_i,\texttt{vb}),\vg), \env) & \Normal((i=1..k: (\texttt{va}_i,\texttt{vb}),\vg), \envp)\\ + \Normal(\vg, \env) & \Normal(\vg, \envp)\\ + \Normal(i=1..k: \vv_i, \vg) & \Normal(i=1..k: \vv_i, \vg)\\ + \Normal([i=1..k: (\vv_i,\vg_i)], \env) & \Normal([i=1..k: (\vv_i,\vg_i)], \envp)\\ + \Throwing((\valuereadfrom(\vx,\vv),\vg), \env) & \Throwing((\valuereadfrom(\vx,\vv),\vg), \envp)\\ + \Returning((i=1..k: \vv_i,\vg), \env) & \Returning((i=1..k: \vv_i,\vg), \envp)\\ + \Continuing(\vg, \env) & \Continuing(\vg, \envp)\\ +\end{array} +\] + +\section{Semantic Evaluation} +\hypertarget{def-evalrel}{} +\hypertarget{def-primitiverel}{} +The semantics of ASL is given by the relations\footnote{The reason that relations, rather than functions, are used is due to the +potential non-determinism in the primitive subprograms +and the non-determinism inherent in the \texttt{UNKNOWN} expression.} +\evalrel\ and \primitiverel. +The relation \evalrel\ is defined as the disjoint union of the relations defined in this reference. +The relation \primitiverel\ provides the semantics of primitive subprograms and is not otherwise defined +constructively. + +\subsection{Natural Operational Semantics} +We define the ASL semantics in the style of \emph{natural operational semantics}~\cite{SemanticsWithApplicationsBook} +(also known as \emph{big step semantics}). +Natural operational semantics evaluates the AST inductively. +That is, it concludes transitions for semantic configurations starting from +non-leaf AST nodes by concluding transitions from semantic configurations starting from their children nodes. + +\subsubsection{No Undefined Behaviors} +When an input semantic configuration does not satisfy any semantic rule, +there is no output semantic configuration for it to transition to. We say that +the semantic configuration is \emph{stuck} and the ASL semantics is undefined for that +input semantic configuration. + +The ASL semantics is defined for well-typed ASL specifications +and gets stuck only in cases of non-terminating specifications +(due to non-terminating loops, or infinite recursion). +Otherwise, for every input semantic configuration there is at least one rule that can be used to take a semantic transition. + +\hypertarget{eval-example}{} +\subsubsection{Evaluation Example} +\newcommand\elint[1]{\ELiteral(\lint(#1))} +The following example shows how to utilize the rules for expression literals and binary operator expressions +to derive a transition from an input semantic configuration with the expression $(1+2)*(4+5)$, +given by the AST +\[ + \begin{array}{rl} + \EBinop(\MUL, &\overname{\EBinop(\PLUS, \overname{\elint{1}}{\veone}, \overname{\elint{2}}{\vetwo})}{\veonetwo}, \\ + &\overname{\EBinop(\PLUS, \overname{\elint{4}}{\vefour}, \overname{\elint{5}}{\vefive})}{\vefourfive}) + \end{array} +\] +to an output semantic configuration with the value resulting from the calculation of the expression. + +We annotate subexpressions to allow referring to them. + +\hypertarget{def-emptyenv}{} +We write $\emptyenv$ to stand for a trivial environment (that is, one where all functions are empty). + +Notice that, we have dropped the execution graph component and simplified pairs of the form $(\vv,\vg)$, +where $\vv$ is a \nativevalue\ and $\vg$ is an execution graph, to just $\vv$. +This is because we are interested in demonstrating the sequential semantics (also, the execution graphs +in this case are all empty). + +The example shows (using references to the relevant rules on the right), how the expression for $1+2$ is evaluated +using the rule for literal expressions, the rule for binary operator (for addition), and the rules for binary expressions. +Similarly, the expression for $4+5$ is evaluated. +Finally, the transitions for both of the subexpressions are used as premises for the binary expression +rule, along with the rule for binary operator (for multiplication), to evaluate the entire expression. + +\begin{mathpar} + \inferrule*[right=\ref{sec:SemanticsRule.Binop}]{ + \inferrule*[right=\ref{sec:SemanticsRule.Lit}]{}{ \evalexpr{\emptyenv, \veone} \evalarrow \Normal(\nvint(1), \emptyenv) } \\\\ + \inferrule*[right=\ref{sec:SemanticsRule.Lit}]{}{ \evalexpr{\emptyenv, \vetwo} \evalarrow \Normal(\nvint(2), \emptyenv) } \\\\ + \inferrule*[right=\ref{sec:SemanticsRule.BinopValues}]{}{\binoprel(\PLUS, \nvint(1), \nvint(2)) \evalarrow \nvint(3)} + } + { + \evalexpr{ \emptyenv, \veonetwo } \evalarrow + \Normal(\nvint(3), \emptyenv) + } +\end{mathpar} + +\begin{mathpar} + \inferrule*[right=\ref{sec:SemanticsRule.Binop}]{ + \inferrule*[right=\ref{sec:SemanticsRule.Lit}]{}{ \evalexpr{\emptyenv, \vefour} \evalarrow \Normal(\nvint(4), \emptyenv) } \\\\ + \inferrule*[right=\ref{sec:SemanticsRule.Lit}]{}{ \evalexpr{\emptyenv, \vefive} \evalarrow \Normal(\nvint(5), \emptyenv) } \\\\ + \inferrule*[right=\ref{sec:SemanticsRule.BinopValues}]{}{\binoprel(\PLUS, \nvint(4), \nvint(5)) \evalarrow \nvint(9)} + } + { + \evalexpr{ \emptyenv, \vefourfive } \evalarrow + \Normal(\nvint(9), \emptyenv) + } +\end{mathpar} + +\begin{mathpar} + \inferrule*[right=\ref{sec:SemanticsRule.Binop}]{ + \evalexpr{ \emptyenv, \veonetwo } \evalarrow \Normal(\nvint(3), \emptyenv)\\ + \evalexpr{ \emptyenv, \vefourfive } \evalarrow \Normal(\nvint(9), \emptyenv)\\ + \inferrule*[right=\ref{sec:SemanticsRule.BinopValues}]{}{\binoprel(\MUL, \nvint(3), \nvint(9)) \evalarrow \nvint(27)} + } + { + \evalexpr{ \emptyenv, \EBinop(\MUL, \veonetwo, \vefourfive) } \evalarrow + \Normal(\nvint(27), \emptyenv) + } +\end{mathpar} \ No newline at end of file diff --git a/asllib/doc/SemanticsUtilities.tex b/asllib/doc/SemanticsUtilities.tex new file mode 100644 index 000000000..5929cadba --- /dev/null +++ b/asllib/doc/SemanticsUtilities.tex @@ -0,0 +1,446 @@ +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +\chapter{Semantics Utility Rules\label{chap:SemanticsUtilityRules}} +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +In this chapter, we define helper relations for operating on \nativevalues, +\hyperlink{def-envs}{environments}, and operations involving values and types. + +We now define the following relations: +\begin{itemize} + \item SemanticsRule.RemoveLocal \secref{SemanticsRule.RemoveLocal}; + \item SemanticsRule.ReadIdentifier \secref{SemanticsRule.ReadIdentifier}; + \item SemanticsRule.WriteIdentifier \secref{SemanticsRule.WriteIdentifier}; + \item SemanticsRule.CreateBitvector \secref{SemanticsRule.CreateBitvector}; + \item SemanticsRule.ConcatBitvectors \secref{SemanticsRule.ConcatBitvectors}; + \item SemanticsRule.ReadFromBitvector \secref{SemanticsRule.ReadFromBitvector}; + \item SemanticsRule.WriteToBitvector \secref{SemanticsRule.WriteToBitvector}; + \item SemanticsRule.GetIndex \secref{SemanticsRule.GetIndex}; + \item SemanticsRule.SetIndex \secref{SemanticsRule.SetIndex}; + \item SemanticsRule.GetField \secref{SemanticsRule.GetField}; + \item SemanticsRule.SetField \secref{SemanticsRule.SetField}; + \item SemanticsRule.DeclareLocalIdentifier \secref{SemanticsRule.DeclareLocalIdentifier}; + \item SemanticsRule.DeclareLocalIdentifierM\secref{SemanticsRule.DeclareLocalIdentifierM}; + \item SemanticsRule.DeclareLocalIdentifierMM \secref{SemanticsRule.DeclareLocalIdentifierMM}; +\end{itemize} + +\subsubsection{SemanticsRule.RemoveLocal \label{sec:SemanticsRule.RemoveLocal}} +\subsubsection{Prose} +The relation +\hypertarget{def-removelocal}{} +\[ + \removelocal(\overname{\envs}{\env} \aslsep \overname{\Identifiers}{\name}) \;\aslrel\; \overname{\envs}{\newenv} +\] +removes the binding of the identifier $\name$ from the local storage of the environment $\env$. + +Removal of the identifier $\name$ from the local storage of the environment $\env$ +is the environment $\newenv$ and all of the following apply: +\begin{itemize} + \item $\env$ consists of the static environment $\tenv$ and dynamic environment $\denv$; + \item $\newenv$ consists of the static environment $\tenv$ and the dynamic environment + with the same global component as $\denv$ --- $G^\denv$, and local component $L^\denv$, + with the identifier $\name$ removed from its domain. +\end{itemize} + +\subsubsection{Formally} +(Recall that $[\name\mapsto\bot]$ means that $\name$ is not in the domain of the resulting function.) +\begin{mathpar} + \inferrule{ + \env \eqname (\tenv, (G^\denv, L^\denv))\\ + \newenv \eqdef (\tenv, (G^\denv, L^\denv[\name \mapsto \bot])) + } + { + \removelocal(\env, \name) \evalarrow \newenv + } +\end{mathpar} + +\subsubsection{SemanticsRule.ReadIdentifier \label{sec:SemanticsRule.ReadIdentifier}} +\subsubsection{Prose} +The relation +\hypertarget{def-readidentifier}{} +\[ + \readidentifier(\overname{\Identifiers}{\name}\aslsep\overname{\vals}{\vv}) \;\aslrel\; (\overname{\vals}{\vv} \times \XGraphs) +\] +reads a value $\vv$ into a storage element given by an identifier $\name$. +The result is the value and an execution graph containing a single Read Effect, +which denoting reading from $\name$. + +\subsubsection{Formally} +\begin{mathpar} + \inferrule{} + { + \readidentifier(\name, \vv) \evalarrow (\vv, \ReadEffect(\name)) + } +\end{mathpar} + +\subsubsection{SemanticsRule.WriteIdentifier \label{sec:SemanticsRule.WriteIdentifier}} +\subsubsection{Prose} +The relation +\hypertarget{def-writeidentifier}{} +\[ + \writeidentifier(\overname{\Identifiers}{\name}\aslsep\overname{\vals}{\vv}) \;\aslrel\; \XGraphs +\] +writes the value $\vv$ into a storage element given by an identifier $\name$. +The result is an execution graph containing a single Write Effect, +which denotes writing into $\name$. + +\subsubsection{Formally} +\begin{mathpar} + \inferrule{} + { + \writeidentifier(\name, \vv) \evalarrow \WriteEffect(\name) + } +\end{mathpar} + +\subsubsection{SemanticsRule.CreateBitvector \label{sec:SemanticsRule.CreateBitvector}} +\subsubsection{Prose} +The relation +\[ + \createbitvector(\overname{\vals^*}{\vvs}) \;\aslrel\; \tbitvector +\] +creates a native vector value bitvector from a sequence of values $\vvs$. + +\subsubsection{Formally} +\begin{mathpar} + \inferrule{} + { + \createbitvector(\vvs) \evalarrow \nvbitvector{\vvs} + } +\end{mathpar} + +\subsubsection{SemanticsRule.ConcatBitvectors \label{sec:SemanticsRule.ConcatBitvectors}} +\subsubsection{Prose} +The relation +\[ + \concatbitvectors(\overname{\tbitvector^*}{\vvs}) \;\aslrel\; \tbitvector +\] +transforms a (possibly empty) list of bitvector \nativevalues\ $\vvs$ into a single bitvector. + +\subsubsection{Formally} +\begin{mathpar} + \inferrule[ConcatBitvector.Empty]{} + { + \concatbitvectors(\emptylist) \evalarrow \nvbitvector(\emptylist) + } + \and + \inferrule[ConcatBitvector.NonEmpty]{ + \vvs \eqname [\vv] \concat \vvs'\\ + \vv\eqname\nvbitvector(\bv)\\ + \concatbitvectors(\vvs') \evalarrow \nvbitvector(\bv')\\ + \vres \eqdef \bv \concat \bv' + } + { + \concatbitvectors(\vvs) \evalarrow \nvbitvector(\vres) + } +\end{mathpar} + +\subsubsection{SemanticsRule.ReadFromBitvector \label{sec:SemanticsRule.ReadFromBitvector}} +\hypertarget{def-readfrombitvector}{} +The relation +\[ + \readfrombitvector(\overname{\tbitvector}{\bv} \aslsep \overname{(\tint\times\tint)^*}{\slices}) \;\aslrel\; + \overname{\tbitvector}{\vv} \cup \overname{\TError}{\ErrorConfig} +\] +reads from a bitvector $\bv$, or an integer seen as a bitvector, the indices specified by the list of slices $\slices$, +thereby concatenating their values. + +\subsubsection{Prose} +One of the following applies: +\begin{itemize} + \item all indices are in range for $\bv$ and the returned bitvector consists of the concatenated bits specified + by the slices. + \item there exists an out-of-range index and an error is returned. +\end{itemize} + +\subsubsection{Formally} +We start by introducing a few helper relations. + +\hypertarget{def-positioninrange}{} +The predicate $\positioninrange(\vs, \vl, n)$ checks whether the indices starting at index $\vs$ and +up to $\vs + \vl$, inclusive, would refer to actual indices of a bitvector of length $n$: +\[ + \positioninrange(\vs, \vl, \vn) \triangleq (\vs \geq 0) \land (\vl \geq 0) \land (\vs + \vl < \vn) \enspace. +\] + +The relation +\hypertarget{def-slicestopositions}{} +\[ + \slicestopositions(\overname{\N}{\vn} \aslsep \overname{(\overname{\tint}{\vs_i}\times\overname{\tint}{\vl_i})^+}{\slices}) \;\aslrel\; + (\overname{\N^*}{\positions} \cup\ \TError) +\] +returns the list of positions (indices) specified by the slices $\slices$, +unless an index would be out of range for a bitvector of length $\vn$, in which case it returns an error configuration. + +\begin{mathpar} + \inferrule[SlicesToPositionsOutOfRange]{ + \slices \eqname [i=1..k: (\nvint(\vs_i), \nvint(\vl_i))]\\ + j \in 1..k: \neg\positioninrange(\vs_j, \vl_j, \vn) + } + { + \slicestopositions(\vn, \slices) \evalarrow \ErrorVal{Slice\_PositionOutOfRange} + } + \and + \inferrule[SlicesToPositionsInRange]{ + \slices \eqname [i=1..k: (\nvint(\vs_i), \nvint(\vl_i))]\\ + i=1..k: \positioninrange(\vs_i, \vl_i, \vn)\\ + \positions \eqdef [\vs_1,\ldots,\vs_1+\vl_1] \concat \ldots \concat [\vs_k,\ldots,\vs_k+\vl_k]\\ + } + { + \slicestopositions(\vn, \slices) \evalarrow \positions + } +\end{mathpar} + +\hypertarget{def-asbitvector}{} +The function $\asbitvector : (\tbitvector\cup\tint) \rightarrow \{0,1\}^*$ transforms \nativevalue\ integers and \nativevalue\ bitvectors into +a sequence of binary values: +\begin{mathpar} + \inferrule[AsBitvectorBitvector]{} + { + \asbitvector(\nvbitvector(\bv)) \evalarrow \bv + } + \and + \inferrule[AsBitvectorInt]{ + \bv \eqdef \text{ two's complement representation of }n + } + { + \asbitvector(\nvint(n)) \evalarrow \bv + } +\end{mathpar} + +Finally, the rules below distinguish between empty bitvectors and non-empty bitvectors. +\begin{mathpar} + \inferrule[ReadFromBitvector.Empty]{} + { + \readfrombitvector(\bv, \emptylist) \evalarrow \nvbitvector(\emptylist) + } + \and + \inferrule[ReadFromBitvector.NonEmpty]{ + \asbitvector(\bv) \eqdef \vb_n \ldots \vb_1\\ + \slicestopositions(n, \slices) \evalarrow [j_{1..m}] \OrDynError\\\\ + \vv \eqdef \nvbitvector(\vb_{j_m + 1}\ldots\vb_{j_1 + 1}) + } + { + \readfrombitvector(\bv, \slices) \evalarrow \vv + } +\end{mathpar} +Notice that the bits of a bitvector go from the least significant bit being on the right to the most significant bit being on the left, +which is reflected by how the rules list the bits. +The effect of placing the bits in sequence is that of concatenating the results +from all of the given slices. +Also notice that bitvector bits are numbered from 1 and onwards, which is why we add 1 to the indices specified +by the slices when accessing a bit. + +\subsubsection{SemanticsRule.WriteToBitvector \label{sec:SemanticsRule.WriteToBitvector}} +\subsubsection{Prose} +The relation +\[ + \writetobitvector(\overname{(\tint\times\tint)^*}{\slices} \aslsep \overname{\tbitvector}{\src} \aslsep \overname{\tbitvector}{\dst}) + \;\bigtimes\; \overname{\tbitvector}{\vv} \cup \overname{\TError}{\ErrorConfig} +\] +overwrites the bits of $\dst$ at the positions given by $\slices$ with the bits of $\src$ +and one of the following applies: +\begin{itemize} + \item all positions specified by $\slices$ are within range for $\dst$ and the modified version + of $\dst$ with the bits of $\src$ at the specified positions is returned; + \item there exists a position in $\slices$ that is not in range for $\dst$ and an error is returned. +\end{itemize} + +\subsubsection{Formally} +\begin{mathpar} + \inferrule[WriteToBitvector.Empty]{} + { + \writetobitvector(\emptylist, \nvbitvector(\emptylist), \nvbitvector(\emptylist)) \evalarrow \nvbitvector(\emptylist) + } + \and + \inferrule[WriteToBitvector.NonEmpty]{ + \vs_n \ldots \vs_1 \eqdef \asbitvector(\src)\\ + \vd_n \ldots \vd_1 \eqdef \asbitvector(\dst)\\ + \slicestopositions(n, \slices) \evalarrow \positions \OrDynError\\\\ + {\mathit{bit} = \lambda i \in 1..n.\left\{ \begin{array}{ll} + \vs_i & i \in \positions\\ + \vd_i & \text{otherwise} + \end{array} \right.}\\ + \vv\eqdef\nvbitvector(\mathit{bit}(n-1)\ldots \mathit{bit}(0))\\ + } + { + \writetobitvector(\slices, \src, \dst) \evalarrow \vv + } +\end{mathpar} + +\subsubsection{SemanticsRule.GetIndex \label{sec:SemanticsRule.GetIndex}} +\subsubsection{Prose} +The relation +\hypertarget{def-getindex}{} +\[ + \getindex(\overname{\N}{\vi} \aslsep \overname{\tvector}{\vvec}) \;\aslrel\; \overname{\tvector}{\vv_{\vi}} +\] +reads the value $\vv_i$ from the vector of values $\vvec$ at the index $\vi$. + +\subsubsection{Formally} +\begin{mathpar} + \inferrule{ + \vvec \eqname \vv_{0..k}\\ + \vi \leq k\\ + } + { + \getindex(\vi, \vvec) \evalarrow \vv_{\vi} + } +\end{mathpar} +Notice that there is no rule to handle the case where the index is out of range --- +this is guaranteed by the type-checker not to happen. Specifically, +\begin{itemize} + \item \texttt{TypingRule.EGetArray} ensures that an index is within the bounds of the array + being accessed via a check that the type of the index satisfies the type of the array size. + \item Typing rules \texttt{TypingRule.LEDestructuring}, \texttt{TypingRule.PTuple}, + and \\ \texttt{TypingRule.LDTuple} use the same index sequences for the tuples + involved and the corresponding lists of expressions. +\end{itemize} +If the rules listed above do not hold the type checker fails. + +\subsubsection{SemanticsRule.SetIndex \label{sec:SemanticsRule.SetIndex}} +\subsubsection{Prose} +The relation +\hypertarget{def-setindex}{} +\[ + \setindex(\overname{\N}{\vi} \aslsep \overname{\vals}{\vv} \aslsep \overname{\tvector}{\vvec}) \;\aslrel\; \overname{\tvector}{\vres} +\] +overwrites the value at the given index $\vi$ in a vector of values $\vvec$ with the new value $\vv$. + +\subsubsection{Formally} +\begin{mathpar} + \inferrule{ + \vvec \eqname \vu_{0..k}\\ + \vi \leq k\\ + \vres \eqname \vw_{0..k}\\ + \vv \eqdef \vw_{\vi} \\ + j \in \{0..k\} \setminus \{\vi\}.\ \vw_{j} = \vu_j\\ + } + { + \setindex(\vi, \vv, \vvec) \evalarrow \vres + } +\end{mathpar} +Similar to $\getindex$, there is no need to handle the out-of-range index case. + +\subsubsection{SemanticsRule.GetField \label{sec:SemanticsRule.GetField}} +\subsubsection{Prose} +The relation +\hypertarget{def-getfield}{} +\[ + \getfield(\overname{\Identifiers}{\name} \aslsep \overname{\trecord}{\record}) \;\aslrel\; \vals +\] +retrieves the value corresponding to the field name $\name$ from the record value $\record$. + +\subsubsection{Formally} +\begin{mathpar} + \inferrule{ + \record \eqname \nvrecord{\fieldmap} + } + { + \getfield(\name, \record) \evalarrow \fieldmap(\name) + } +\end{mathpar} +The type-checker ensures, via TypingRule.EGetRecordField, that the field $\name$ exists in $\record$. + +\subsubsection{SemanticsRule.SetField \label{sec:SemanticsRule.SetField}} +\subsubsection{Prose} +The relation +\hypertarget{def-setfield}{} +\[ + \setfield(\overname{\Identifiers}{\name} \aslsep \overname{\vals}{\vv} \aslsep \overname{\trecord}{\record}) \;\aslrel\; \trecord +\] +overwrites the value corresponding to the field name $\name$ in the record value $\record$ with the value $\vv$. + +\subsubsection{Formally} +\begin{mathpar} + \inferrule{ + \record \eqname \nvrecord{\fieldmap}\\ + \fieldmap' \eqdef \fieldmap[\name\mapsto\vv] + } + { + \setfield(\name, \vv, \record) \evalarrow \nvrecord{\fieldmap'} + } +\end{mathpar} +The type-checker ensures that the field $\name$ exists in $\record$. + +\subsubsection{SemanticsRule.DeclareLocalIdentifier \label{sec:SemanticsRule.DeclareLocalIdentifier}} +\subsubsection{Prose} +The relation +\hypertarget{def-declarelocalidentifier}{} +\[ + \declarelocalidentifier(\overname{\envs}{\env} \aslsep \overname{\Identifiers}{\name} \aslsep \overname{\vals}{\vv}) \;\aslrel\; + (\overname{\envs}{\newenv}\times\overname{\XGraphs}{\vg}) +\] +associates $\vv$ to $\name$ as a local storage element in the environment $\env$ and +returns the updated environment $\newenv$ with the execution graph consisting of a Write Effect to $\name$. + +\subsubsection{Formally} +\begin{mathpar} + \inferrule{ + \vg \eqdef \WriteEffect(\name)\\ + \env \eqname (\tenv, (G^\denv, L^\denv))\\ + \newenv \eqdef (\tenv, (G^\denv, L^\denv[\name\mapsto \vv])) + } + { \declarelocalidentifier(\env, \name, \vv) \evalarrow (\newenv, \vg) } +\end{mathpar} + +\subsubsection{SemanticsRule.DeclareLocalIdentifierM \label{sec:SemanticsRule.DeclareLocalIdentifierM}} +\subsubsection{Prose} +\hypertarget{def-declarelocalidentifierm}{} +The relation +\[ + \declarelocalidentifierm(\overname{\envs}{\env} \aslsep + \overname{\Identifiers}{\vx} \aslsep + \overname{(\overname{\vals}{\vv}\times\overname{\XGraphs}{\vg})}{\vm}) \;\aslrel\; + (\overname{\envs}{\newenv} \times \overname{\XGraphs}{\newg}) +\] +declares the local identifier $\vx$ in the environment $\env$, in the context +of the value-graph pair $(\vv, \vg)$, and all of the following apply: +\begin{itemize} + \item \newenv\ is the environment $\env$ modified to declare the variable $\vx$ as a local storage element; + \item $\vgone$ is the execution graph resulting from the declaration of $\vx$; + \item $\vgtwo$ is the execution graph resulting from the ordered composition of $\vg$ and $\vgone$ + with the $\asldata$ edge. +\end{itemize} + +\subsubsection{Formally} +\begin{mathpar} + \inferrule{ + \vm \eqname (\vv, \vg)\\ + \declarelocalidentifier(\env, \vx, \vv) \evalarrow (\newenv, \vgone)\\ + \newg \eqdef \ordered{\vg}{\asldata}{\vgone} + } + { + \declarelocalidentifierm(\env, \vx, \vm) \evalarrow (\newenv, \newg) + } +\end{mathpar} + +\subsubsection{SemanticsRule.DeclareLocalIdentifierMM \label{sec:SemanticsRule.DeclareLocalIdentifierMM}} +\subsubsection{Prose} +\hypertarget{def-declarelocalidentifermm}{} +The relation +\[ + \declarelocalidentifiermm(\overname{\envs}{\env} \aslsep + \overname{\Identifiers}{\vx} \aslsep + \overname{(\overname{\vals}{\vv}\times\overname{\XGraphs}{\vg})}{\vm}) \;\aslrel\; + (\overname{\envs}{\newenv} \times \overname{\XGraphs}{\vgtwo}) +\] +declares the local identifier $\vx$ in the environment $\env$, +in the context of the value-graph pair $(\vv, \vg)$, +and all of the following apply: +\begin{itemize} + \item \newenv\ is the environment $\env$ modified to declare the variable $\vx$ as a local storage element; + \item $\vgone$ is the execution graph resulting from the declaration of $\vx$; + \item $\vgtwo$ is the execution graph resulting from the ordered composition of $\vg$ and $\vgone$ + with the $\aslpo$ edge. +\end{itemize} + +\subsubsection{Formally} +\begin{mathpar} + \inferrule{ + \declarelocalidentifierm(\env, \vm) \evalarrow (\newenv, \vgone)\\ + \vgtwo \eqdef \ordered{\vg}{\aslpo}{\vgone} + } + { + \declarelocalidentifiermm(\env, \vx, \vm) \evalarrow (\newenv, \vgtwo) + } +\end{mathpar} + diff --git a/asllib/doc/Slicing.tex b/asllib/doc/Slicing.tex new file mode 100644 index 000000000..9a45d9876 --- /dev/null +++ b/asllib/doc/Slicing.tex @@ -0,0 +1,541 @@ +\chapter{Bitvector Slicing\label{chap:BitvectorSlicing}} + +\section{A List of Slices} +A list of bitvector slices is grammatically derived from $\Nslices$ and the AST +is given by a list of $\slice$ AST nodes. +% +The function $\buildslices$ builds the AST for a list of slices. +% +The function $\annotateslices$ (see \nameref{sec:TypingRule.Slices}) annotates a list of slices. +% +The relation $\evalslices$ (see \nameref{sec:SemanticsRule.Slices}) evaluates a list of slices. + +\subsection{Syntax} +\begin{flalign*} +\Nslices \derivesinline\ & \Tlbracket \parsesep \Clist{\Nslice} \parsesep \Trbracket & +\end{flalign*} + +\subsection{Abstract Syntax} +\subsubsection{ASTRule.Slices\label{sec:ASTRule.Slices}} +\hypertarget{build-slices}{} +The function +\[ + \buildslices(\overname{\parsenode{\Nslices}}{\vparsednode}) \;\aslto\; \overname{\slice^*}{\vastnode} +\] +transforms a parse node for a list of slices $\vparsednode$ into an AST node for a list of slices $\vastnode$. + +\begin{mathpar} +\inferrule{ + \buildclist[\buildslice](\vslices) \astarrow \vsliceasts +}{ + \buildslices(\Nslices(\Tlbracket, \namednode{\vslices}{\Clist{\Nslice}}, \Trbracket)) \astarrow + \overname{\vsliceasts}{\vastnode} +} +\end{mathpar} + +\subsection{Typing} +\subsubsection{TypingRule.Slices\label{sec:TypingRule.Slices}} +\hypertarget{def-annotateslices}{} +The function +\[ +\annotateslices(\overname{\staticenvs}{\tenv}, \overname{\slice^*}{\vslices}) \aslto \overname{\slice^*}{\slicesp} +\] +annotates a list of slices $\vslices$ in the static environment $\tenv$, yielding a list of annotated slices (that is, +slices in the \typedast). \ProseOtherwiseTypeError +\subsection{Prose} +All of the following apply: +\begin{itemize} + \item annotating the slice $\vslices[\vi]$ in $\tenv$, for each $\vi\in\listrange(\vslices)$, yields the slice $\vs_\vi$\ProseOrTypeError; + \item define $\slicesp$ as the list of slices $\vs_\vi$, for each $\vi\in\listrange(\vslices)$. +\end{itemize} +\subsection{Formally} +\begin{mathpar} +\inferrule{ + \vi\in\listrange(\vslices): \annotateslice(\tenv, \vslices[\vi]) \typearrow \vs_\vi \OrTypeError\\\\ + \slicesp \eqdef [\vi\in\listrange(\vslices): \vs_\vi] +}{ + \annotateslices(\tenv, \vslices) \typearrow \slicesp +} +\end{mathpar} + +\subsection{Semantics} +\subsubsection{SemanticsRule.Slices \label{sec:SemanticsRule.Slices}} +The relation +\hypertarget{def-evalslices}{} +\[ + \begin{array}{rl} + \evalslices(\overname{\envs}{\env} \aslsep \overname{\slice^*}{\slices}) \;\aslrel & + \Normal((\overname{(\vals \times \vals)^*}{\ranges} \times \overname{\XGraphs}{\newg}), \overname{\envs}{\newenv})\ \cup \\ + & \overname{\Throwing}{\ThrowingConfig} \cup \overname{\TError}{\ErrorConfig} + \end{array} +\] +evaluates a list of slices $\slices$ in an environment $\env$, resulting in either \\ +$\Normal((\ranges, \newg), \newenv)$ or an abnormal configuration. +\subsubsection{Prose} +One of the following applies: +\begin{itemize} + \item All of the following apply (\textsc{empty}): + \begin{itemize} + \item the list of slices is empty; + \item $\ranges$ is the empty list; + \item $\newg$ is the empty graph; + \item $\newenv$ is $\env$; + \end{itemize} + + \item All of the following apply (\textsc{nonempty}): + \begin{itemize} + \item the list of slices has $\slice$ as the head and $\slicesone$ as the tail; + \item evaluating the slice $\vslice$ in $\env$ results in \\ + $\Normal((\range, \vgone), \envone)$\ProseOrAbnormal; + \item evaluating the tail list $\slicesone$ in $\envone$ results in \\ + $\Normal((\rangesone, \vgtwo), \newenv)$\ProseOrAbnormal; + \item $\ranges$ is the concatenation of $\range$ to $\rangesone$; + \item $\newg$ is the parallel composition of $\vgone$ and $\vgtwo$. + \end{itemize} +\end{itemize} + +$\evalslices(\env, \vslices)$ is the list of pairs \texttt{(start\_n, length\_n)} that +correspond to the start (included) and the length of each slice in +$\slices$. + +\subsubsection{Formally} +\begin{mathpar} +\inferrule[empty]{} +{ + \evalslices(\env, \emptylist) \evalarrow \Normal((\emptylist, \emptygraph), \env) +} +\end{mathpar} +\begin{mathpar} +\inferrule[nonempty]{ + \slices \eqname [\vslice] \concat \slicesone\\ + \evalslice(\env, \vslice) \evalarrow \Normal((\range, \vgone), \envone) \OrAbnormal\\ + \evalslices(\envone, \slicesone) \evalarrow \Normal((\rangesone, \vgtwo), \newenv) \OrAbnormal\\ + \ranges \eqdef [\range] \concat \rangesone\\ + \newg \eqdef \vgone \parallelcomp \vgtwo +}{ + \evalslices(\env, \slices) \evalarrow \Normal((\ranges, \newg), \newenv) +} +\end{mathpar} +\CodeSubsection{\EvalSlicesBegin}{\EvalSlicesEnd}{../Interpreter.ml} + +\section{Slicing Constructs} +An individual slice construct is grammatically derived from $\Nslice$ and +represented as an AST by $\slice$. +% +The function $\buildslice$ (see \nameref{sec:ASTRule.Slice}) builds the AST for an individual slice construct. +% +the function $\annotateslice$ (see \nameref{sec:TypingRule.Slice}) annotates a single slice. + +\subsection{Syntax} +\begin{flalign*} +\Nslice \derivesinline\ & \Nexpr &\\ + |\ & \Nexpr \parsesep \Tcolon \parsesep \Nexpr &\\ + |\ & \Nexpr \parsesep \Tpluscolon \parsesep \Nexpr &\\ + |\ & \Nexpr \parsesep \Tstarcolon \parsesep \Nexpr & +\end{flalign*} + +\subsection{Abstract Syntax} +\begin{flalign*} +\slice \derives\ & \SliceSingle(\overname{\expr}{\vi}) &\\ + |\ & \SliceRange(\overname{\expr}{\vj}, \overname{\expr}{\vi}) &\\ + |\ & \SliceLength(\overname{\expr}{\vi}, \overname{\expr}{\vn}) &\\ + |\ & \SliceStar(\overname{\expr}{\vi}, \overname{\expr}{\vn}) & +\end{flalign*} + +\subsubsection{ASTRule.Slice\label{sec:ASTRule.Slice}} +\hypertarget{build-slice}{} +The function +\[ + \buildslice(\overname{\parsenode{\Nslice}}{\vparsednode}) \;\aslto\; \overname{\slice}{\vastnode} +\] +transforms a parse node for a slice $\vparsednode$ into an AST node for a slice $\vastnode$. + +\begin{mathpar} +\inferrule[single]{}{ + \buildslices(\Nslice(\punnode{\Nexpr})) \astarrow + \overname{\SliceSingle(\astof{\vexpr})}{\vastnode} +} +\end{mathpar} + +\begin{mathpar} +\inferrule[range]{ + \buildexpr(\veone) \astarrow \astversion{\veone}\\ + \buildexpr(\vetwo) \astarrow \astversion{\vetwo} +}{ + \buildslices(\Nslice(\namednode{\veone}{\Nexpr}, \Tcolon, \namednode{\vetwo}{\Nexpr})) \astarrow + \overname{\SliceRange(\astversion{\veone}, \astversion{\vetwo})}{\vastnode} +} +\end{mathpar} + +\begin{mathpar} +\inferrule[length]{ + \buildexpr(\veone) \astarrow \astversion{\veone}\\ + \buildexpr(\vetwo) \astarrow \astversion{\vetwo} +}{ + \buildslices(\Nslice(\namednode{\veone}{\Nexpr}, \Tpluscolon, \namednode{\vetwo}{\Nexpr})) \astarrow + \overname{\SliceLength(\astversion{\veone}, \astversion{\vetwo})}{\vastnode} +} +\end{mathpar} + +\begin{mathpar} +\inferrule[scaled]{ + \buildexpr(\veone) \astarrow \astversion{\veone}\\ + \buildexpr(\vetwo) \astarrow \astversion{\vetwo} +}{ + \buildslices(\Nslice(\namednode{\veone}{\Nexpr}, \Tstarcolon, \namednode{\vetwo}{\Nexpr})) \astarrow + \overname{\SliceStar(\astversion{\veone}, \astversion{\vetwo})}{\vastnode} +} +\end{mathpar} + +\subsection{Typing} +\subsubsection{TypingRule.Slice\label{sec:TypingRule.Slice}} +\hypertarget{def-annotateslice}{} +the function +\[ + \annotateslice(\overname{\staticenvs}{\tenv} \aslsep \overname{\slice}{\vs}) + \aslto + \overname{\slice}{\vsp} \cup \overname{\TTypeError}{\TypeErrorConfig} +\] +annotates a single slice $\vs$ in the static environment $\tenv$, +resulting in an annotated slice $\vsp$. +\ProseOtherwiseTypeError +\subsubsection{Prose} +One of the following applies: +\begin{itemize} + \item All of the following apply (\textsc{single}): + \begin{itemize} + \item $\vs$ is a \singleslice\ at index \vi, that is $\SliceSingle(\vi)$; + \item annotating the slice at offset $\vi$ of length $1$ yields $\vsp$\ProseOrTypeError. + \end{itemize} + + \item All of the following apply (\textsc{range}): + \begin{itemize} + \item $\vs$ is a slice for the range \texttt{(j, i)}, that is $\SliceRange(\vj, \vi)$; + \item $\prelength$ is \texttt{i+:(j-i+1)}; + \item annotating the slice at offset $\vi$ of length $\prelength$ yields $\vsp$\ProseOrTypeError. + \end{itemize} + + \item All of the following apply (\textsc{length}): + \begin{itemize} + \item $\vs$ is a \lengthslice\ of length $\elength$ and offset $\eoffset$, that is, \\ + $\SliceLength(\eoffset, \elength)$; + \item annotating the expression $\eoffset$ in $\tenv$ yields $(\toffset, \eoffsetp)$\ProseOrTypeError; + \item annotating the \staticallyevaluable\ \constrainedinteger\ expression $\elength$ in $\tenv$ yields + $\elength$\ProseOrTypeError; + \item determining whether $\toffset$ has the \structureofinteger\ yields $\True$\ProseOrTypeError; + \item $\vsp$ is the slice at offset $\eoffsetp$ and length $\elength'$, that is,\\ + $\SliceLength(\eoffsetp, \elength')$. + \end{itemize} + + \item All of the following apply (\textsc{scaled}): + \begin{itemize} + \item $\vs$ is a \scaledslice\ \texttt{[factor *: pre\_length]}, that is, \\ + $\SliceStar(\factor, \prelength)$; + \item $\preoffset$ is $\factor * \prelength$; + \item annotating the slice at offset $\preoffset$ of length $\prelength$ yields $\vsp$\ProseOrTypeError. + \end{itemize} +\end{itemize} + +\subsubsection{Formally} +\begin{mathpar} +\inferrule[single]{ + \annotateslice(\SliceLength(\vi, \eliteral{1})) \typearrow \vsp \OrTypeError +}{ + \annotateslice(\tenv, \overname{\SliceSingle(\vi)}{\vs}) \typearrow \vsp +} +\end{mathpar} + +\begin{mathpar} +\inferrule{ + \binopliterals(\MINUS, \vi, \vi) \typearrow \prelengthp\\ + \binopliterals(\PLUS, \prelengthp, \eliteral{1}) \typearrow \prelength\\ + \annotateslice(\SliceLength(\vi, \prelength)) \typearrow \vsp \OrTypeError +}{ + \annotateslice(\tenv, \overname{\SliceRange(\vj, \vi)}{\vs}) \typearrow \vsp +} +\end{mathpar} + +\begin{mathpar} +\inferrule[length]{ + \annotateexpr{\tenv, \eoffset} \typearrow (\toffset, \eoffsetp) \OrTypeError\\\\ + \annotatestaticconstrainedinteger(\tenv, \elength) \typearrow \elengthp \OrTypeError\\\\ + \checkstructureinteger(\tenv, \toffset) \typearrow \True \OrTypeError +}{ + { + \begin{array}{r} + \annotateslice(\tenv, \overname{\SliceLength(\eoffset, \elength)}{\vs}) \typearrow \\ + \overname{\SliceLength(\eoffsetp, \elength')}{\vsp} + \end{array} + } +} +\end{mathpar} + +\begin{mathpar} +\inferrule[scaled]{ + \binopliterals(\MUL, \factor, \prelength) \typearrow \preoffset\\ + \annotateslice(\SliceLength(\preoffset, \prelength)) \typearrow \vsp \OrTypeError +}{ + \annotateslice(\tenv, \overname{\SliceStar(\factor, \prelength)}{\vs}) \typearrow \vsp +} +\end{mathpar} +\lrmcomment{\identr{GXKG}: The notation \texttt{b[j:i]} is syntactic sugar for \texttt{b[i+:(j-i+1)]}.} +\lrmcomment{\identr{GXKG}: The notation \texttt{b[i]} is syntactic sugar for \texttt{b[i +: 1]}.} +\lrmcomment{\identr{GXQG}: The notation \texttt{b[i *: n]} is syntactic sugar for \texttt{b[i*n +: n]}} + +\subsubsection{TypingRule.SlicesWidth\label{sec:TypingRule.SlicesWidth}} +\hypertarget{def-sliceswidth}{} +The helper function +\[ + \sliceswidth(\overname{\staticenvs}{\tenv} \aslsep \overname{\slice^*}{\vslices}) \aslto + \overname{\expr}{\vwidth} \cup \overname{\TTypeError}{\TypeErrorConfig} +\] +returns an expression $\vslices$ that represents the width of all slices given by $\vslices$ +in the static environment $\tenv$. + +\subsubsection{Prose} +One of the following applies: +\begin{itemize} + \item All of the following apply (\textsc{empty}): + \begin{itemize} + \item $\vslices$ is the empty list; + \item $\vwidth$ is the literal integer expression for $0$. + \end{itemize} + + \item All of the following apply (\textsc{non\_empty}): + \begin{itemize} + \item $\vslices$ is the list with \head\ $\vs$ and \tail\ $\slicesone$; + \item applying $\slicewidth$ to $\vs$ yields $\veone$; + \item applying $\sliceswidth$ to $\slicesone$ yields $\vetwo$; + \item symbolically simplifying the binary expression summing $\veone$ with $\vetwo$ yields $\vwidth$\ProseOrTypeError. + \end{itemize} +\end{itemize} +\subsubsection{Formally} +\begin{mathpar} +\inferrule[empty]{}{ + \sliceswidth(\tenv, \overname{\emptylist}{\vslices}) \typearrow \overname{\ELInt{0}}{\vwidth} +} +\end{mathpar} + +\begin{mathpar} +\inferrule[non\_empty]{ + \slicewidth(\vs) \typearrow \veone\\ + \sliceswidth(\slicesone) \typearrow \vetwo\\ + \normalize(\AbbrevEBinop{\PLUS}{\veone}{\vetwo}) \typearrow \vwidth \OrTypeError +}{ + \sliceswidth(\tenv, \overname{[\vs]\concat\slicesone}{\vslices}) \typearrow \vwidth +} +\end{mathpar} + +\subsubsection{TypingRule.SliceWidth\label{sec:TypingRule.SliceWidth}} +\hypertarget{def-slicewidth}{} +The helper function +\[ + \slicewidth(\overname{\slice}{\vslice}) \aslto + \overname{\expr}{\vwidth} +\] +returns an expression $\vslices$ that represents the width of the slices given by $\vslice$. + +\subsubsection{Prose} +One of the following applies: +\begin{itemize} + \item All of the following apply (\textsc{single}): + \begin{itemize} + \item $\vslice$ is a single slice, that is, $\SliceSingle(\Ignore)$; + \item $\vwidth$ is the literal integer expression for $1$; + \end{itemize} + + \item All of the following apply (\textsc{star}, \text{length}): + \begin{itemize} + \item $\vslice$ is either a slice of the form \texttt{\_:*$\ve$} or \texttt{\_:+$\ve$}; + \item $\vwidth$ is $\ve$; + \end{itemize} + + \item All of the following apply (\textsc{range}): + \begin{itemize} + \item $\vslice$ is a slice of the form \texttt{$\veone$..$\vetwo$}; + \item $\vwidth$ is the expression for $1 + (\veone - \vetwo)$. + \end{itemize} +\end{itemize} +\subsubsection{Formally} +\begin{mathpar} +\inferrule[single]{}{ + \slicewidth(\overname{\SliceSingle(\Ignore)}{\vslice}) \typearrow \overname{\ELInt{1}}{\vwidth} +} +\and +\inferrule[scaled]{}{ + \slicewidth(\overname{\SliceStar(\Ignore, \ve)}{\vslice}) \typearrow \overname{\ve}{\vwidth} +} +\and +\inferrule[length]{}{ + \slicewidth(\overname{\SliceLength(\Ignore, \ve)}{\vslices}) \typearrow \overname{\ve}{\vwidth} +} +\and +\inferrule[range]{}{ + \slicewidth(\overname{\SliceRange(\veone, \vetwo)}{\vslices}) \typearrow + \overname{\AbbrevEBinop{\PLUS}{\ELInt{1}}{(\AbbrevEBinop{\MINUS}{\veone}{\vetwo})}}{\vwidth} +} +\end{mathpar} + +\subsubsection{TypingRule.StaticConstrainedInteger\label{sec:TypingRule.StaticConstrainedInteger}} +\hypertarget{def-annotatestaticconstrainedinteger}{} +The function +\[ + \annotatestaticconstrainedinteger(\overname{\staticenvs}{\tenv} \aslsep \overname{\expr}{\ve}) \aslto + \overname{\expr}{\vepp} \cup \overname{\TTypeError}{\TypeErrorConfig} +\] +annotates a \staticallyevaluable\ integer expression $\ve$ of a constrained integer type in the static environment $\tenv$ +and returns the annotated expression $\vepp$. +\ProseOtherwiseTypeError + +\subsubsection{Prose} +All of the following apply: +\begin{itemize} + \item annotating the expression $\ve$ in $\tenv$ yields $ (\vt, \vep)$\ProseOrTypeError; + \item determining whether $\vt$ is a statically \constrainedinteger\ in $\tenv$ yields $\True$\ProseOrTypeError; + \item determining whether $\vep$ is \staticallyevaluable\ in $\tenv$ yields $\True$\ProseOrTypeError; + \item applying $\normalize$ to $\vep$ in $\tenv$ yields $\vepp$. +\end{itemize} +\subsubsection{Formally} +\begin{mathpar} +\inferrule{ + \annotateexpr{\tenv, \ve} \typearrow (\vt, \vep) \OrTypeError\\\\ + \checkconstrainedinteger(\tenv, \vt) \typearrow \True \OrTypeError\\\\ + \checkstaticallyevaluable(\tenv, \vep) \typearrow \True \OrTypeError\\\\ + \normalize(\tenv, \vep) \typearrow \vepp +}{ + \annotatestaticconstrainedinteger(\tenv, \ve) \typearrow \vepp +} +\end{mathpar} +\CodeSubsection{\StaticConstrainedIntegerBegin}{\StaticConstrainedIntegerEnd}{../Typing.ml} + +\subsection{Semantics} +\subsubsection{SemanticsRule.Slice} +The relation +\hypertarget{def-evalslice}{} +\[ + \begin{array}{rl} + \evalslice{\overname{\envs}{\env} \aslsep \overname{\slice}{\vs}} \;\aslrel & + \Normal(((\overname{\tint}{\vstart} \times \overname{\tint}{\vlength}) \times \overname{\XGraphs}{\newg}), \overname{\envs}{\newenv})\ \cup \\ + & \overname{\Throwing}{\ThrowingConfig} \cup \overname{\TError}{\ErrorConfig} + \end{array} +\] +evaluates an individual slice $\vs$ in an environment $\env$ is, +resulting either in \\ +$\Normal(((\vstart, \vlength), \vg), \newenv)$, a throwing configuration, or a dynamic error configuration. + +\subsubsection{Example (Single Slice)} +In the specification: + \VerbatimInput{../tests/ASLSemanticsReference.t/SemanticsRule.SliceSingle.asl} +the slice \texttt{[2]} evaluates to \texttt{(2, 1)}, i.\,e.\ the slice of +length 1 starting at index 2. + +\subsubsection{Example (Range Slice)} +In the specification: +\VerbatimInput{../tests/ASLSemanticsReference.t/SemanticsRule.SliceRange.asl} +\texttt{4:2} evaluates to \texttt{(2, 3)}. + +\subsubsection{Example (Length Slice)} +In the specification: + \VerbatimInput{../tests/ASLSemanticsReference.t/SemanticsRule.SliceLength.asl} +\texttt{2+:3} evaluates to \texttt{(2, 3)}. + +\subsubsection{Example (Scaled Slice)} +In the specification: +\VerbatimInput{../tests/ASLSemanticsReference.t/SemanticsRule.SliceStar.asl} +\texttt{x[3*:2]} evaluates to \texttt{'11'}. + +\subsubsection{Prose} +One of the following applies: +\begin{itemize} + \item All of the following apply (\textsc{single}): + \begin{itemize} + \item $\vs$ is a \singleslice\ with the expression $\ve$, $\SliceSingle(\ve)$; + \item evaluating $\ve$ in $\env$ results in $\Normal((\vstart, \newg)$\newenv)\ProseOrAbnormal; + \item $\vlength$ is the integer value 1. + \end{itemize} + + \item All of the following apply (\textsc{range}): + \begin{itemize} + \item $\vs$ is the \rangeslice\ between the + expressions $\estart$ and $\etop$, that is, \\ $\SliceRange(\etop, \estart)$; + \item evaluating $\etop$ in $\env$ is $\Normal(\mtop, \envone)$\ProseOrAbnormal; + \item $\mtop$ is a pair consisting of the native integer $\vvsubtop$ and execution graph $\vgone$; + \item evaluating $\estart$ in $\envone$ is $\Normal(\mstart, \newenv)$\ProseOrAbnormal; + \item $\mstart$ is a pair consisting of the native integer $\vstart$ and execution graph $\vgtwo$; + \item $\vlength$ is the integer value \texttt{(v\_top - v\_start) + 1}; + \item $\newg$ is the parallel composition of $\vgone$ and $\vgtwo$. + \end{itemize} + + \item All of the following apply (\textsc{length}): + \begin{itemize} + \item $\vs$ is the \lengthslice, which starts at expression~$\estart$ with length~$\elength$, + that is, $\SliceLength(\estart, \elength)$; + \item evaluating $\estart$ in $\env$ is \Normal(\mstart, \envone)\ProseOrAbnormal; + \item evaluating $\elength$ in $\envone$ is \Normal(\mlength, \newenv)\ProseOrAbnormal; + \item $\mstart$ is a pair consisting of the native integer $\vstart$ and execution graph $\vgone$; + \item $\mlength$ is a pair consisting of the native integer $\vlength$ and execution graph $\vgtwo$; + \item $\newg$ is the parallel composition of $\vgone$ and $\vgtwo$. + \end{itemize} + + \item All of the following apply (\textsc{scaled}): + \begin{itemize} + \item $\vs$ is the \scaledslice\ with factor given by the + expression $\efactor$ and length given by the + expression $\elength$, that is, $\SliceStar(\efactor, \elength)$; + \item evaluating $\efactor$ in $\env$ is $\Normal(\mfactor, \envone)$\ProseOrAbnormal; + \item $\mfactor$ is a pair consisting of the native integer $\vfactor$ and execution graph $\vgone$; + \item evaluating $\elength$ in $\env$ is $\Normal(\mlength, \newenv)$\ProseOrAbnormal; + \item $\mlength$ is a pair consisting of the native integer $\vlength$ and execution graph $\vgtwo$; + \item $\vstart$ is the native integer $\vfactor \times \vlength$; + \item $\newg$ is the parallel composition of $\vgone$ and $\vgtwo$. + \end{itemize} +\end{itemize} + +\subsubsection{Formally} +\begin{mathpar} +\inferrule[single]{ + \evalexpr{\env, \ve} \evalarrow \Normal((\vstart, \newg), \newenv) \OrAbnormal\\ + \vlength \eqdef \nvint(1) +}{ + \evalslice(\env, \SliceSingle(\ve)) \evalarrow \Normal(((\vstart, \vlength), \newg), \newenv) +} +\end{mathpar} + +\begin{mathpar} +\inferrule[range]{ + \evalexpr{\env, \etop} \evalarrow \Normal(\mtop, \envone) \OrAbnormal\\\\ + \mtop \eqname (\vvsubtop, \vgone)\\ + \evalexpr{\envone, \estart} \evalarrow \Normal(\mstart, \newenv) \OrAbnormal\\\\ + \mstart \eqname (\vstart, \vgtwo)\\ + \binoprel(\MINUS, \vvsubtop, \vstart) \evalarrow \vdiff\\ + \binoprel(\PLUS, \nvint(1), \vdiff) \evalarrow \vlength\\ + \newg \eqdef \vgone \parallelcomp \vgtwo +}{ + \evalslice(\env, \SliceRange(\etop, \estart)) \evalarrow \\ \Normal(((\vstart, \vlength), \newg), \newenv) +} +\end{mathpar} + +\begin{mathpar} +\inferrule[length]{ + \evalexpr{\env, \estart} \evalarrow \Normal(\mstart, \envone) \OrAbnormal\\ + \evalexpr{\envone, \elength} \evalarrow \Normal(\mlength, \newenv) \OrAbnormal\\ + \mstart \eqname (\vstart, \vgone)\\ + \mlength \eqname (\vlength, \vgtwo)\\ + \newg \eqdef \vgone \parallelcomp \vgtwo +}{ + \evalslice(\env, \SliceLength(\estart, \elength)) \evalarrow \\ \Normal(((\vstart, \vlength), \newg), \newenv) +} +\end{mathpar} + +\begin{mathpar} +\inferrule[scaled]{ + \evalexpr{\env, \efactor} \evalarrow \Normal(\mfactor, \envone) \OrAbnormal\\ + \mfactor \eqname (\vfactor, \vgone)\\ + \evalexpr{\envone, \elength} \evalarrow \Normal(\mlength, \newenv) \OrAbnormal\\ + \mlength \eqname (\vlength, \vgtwo)\\ + \binoprel(\MUL, \vfactor, \vlength) \evalarrow \vstart \\ + \newg \eqdef \vgone \parallelcomp \vgtwo +}{ + \evalslice(\env, \SliceStar(\efactor, \elength)) \evalarrow \\ \Normal(((\vstart, \vlength), \newg), \newenv) +} +\end{mathpar} diff --git a/asllib/doc/Specifications.tex b/asllib/doc/Specifications.tex new file mode 100644 index 000000000..eb87a1c86 --- /dev/null +++ b/asllib/doc/Specifications.tex @@ -0,0 +1,1813 @@ +\chapter{Specifications\label{chap:Specifications}} + +Specifications are grammatically derived from $\Nast$ and represented as ASTs by \\ +$\specification$. +% +Typing specifications is done by the relation $\typecheckast$, which is defined in +\nameref{sec:TypingRule.TypeCheckAST}. +% +The semantics of specifications in given by the relation $\evalspec$, which is defined in \nameref{sec:SemanticsRule.TopLevel}. + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +\section{Syntax} +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +\begin{flalign*} +\Nast \derives\ & \productionname{ast}{ast}\ \maybeemptylist{\Ndecl} & +\end{flalign*} + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +\section{Abstract Syntax} +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +\begin{flalign*} +\specification \derives\ & \decl^* & +\end{flalign*} + +\subsubsection{ASTRule.AST \label{sec:ASTRule.AST}} +\hypertarget{build-ast}{} +The relation +\[ + \buildast : \overname{\parsenode{\Nast}}{\vparsednode} \;\aslrel\; \overname{\specification}{\vastnode} +\] +transforms an $\Nast$ node $\vparsednode$ into an AST specification node $\vastnode$. + +We define this function for subprogram declarations, type declarations, and global storage declarations in the corresponding chapters. + +\begin{mathpar} +\inferrule[ast]{ + \buildlist[\builddecl](\vdecls) \astarrow \vadecls +}{ + \buildast(\overname{\Nast(\namednode{\vdecls}{\maybeemptylist{\Ndecl}})}{\vparsednode}) \astarrow \overname{\vadecls}{\vastnode} +} +\end{mathpar} + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +\section{Typing} +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +The untyped AST of an ASL specification consists of a list of declarations. +Type-checking the untyped AST succeeds if all declarations can be successfully annotated. +This is achieved via \nameref{sec:TypingRule.TypeCheckAST}. + +We define the following helper rules: +\begin{itemize} + \item TypingRule.AnnotateDeclComps (see \secref{TypingRule.AnnotateDeclComps}) + \item TypingRule.BuildDependencies (see \secref{TypingRule.BuildDependencies}) + \item TypingRule.DeclDependencies (see \secref{TypingRule.DeclDependencies}) + \item TypingRule.TypeCheckMutuallyRec (see \secref{TypingRule.TypeCheckMutuallyRec}) + \item TypingRule.FoldEnvAndFs (see \secref{TypingRule.FoldEnvAndFs}) + \item TypingRule.DefDecl (see \secref{TypingRule.DefDecl}) + \item TypingRule.DefEnumLabels (see \secref{TypingRule.DefEnumLabels}) + \item TypingRule.UseDecl (see \secref{TypingRule.UseDecl}) + \item TypingRule.UseTy (see \secref{TypingRule.UseTy}) + \item TypingRule.UseSubtypes (see \secref{TypingRule.UseSubtypes}) + \item TypingRule.UseExpr (see \secref{TypingRule.UseExpr}) + \item TypingRule.UseLexpr (see \secref{TypingRule.UseLexpr}) + \item TypingRule.UsePattern (see \secref{TypingRule.UsePattern}) + \item TypingRule.UseSlice (see \secref{TypingRule.UseSlice}) + \item TypingRule.UseBitfield (see \secref{TypingRule.UseBitfield}) + \item TypingRule.UseConstraint (see \secref{TypingRule.UseConstraint}) + \item TypingRule.UseStmt (see \secref{TypingRule.UseStmt}) + \item TypingRule.UseLDI (see \secref{TypingRule.UseLDI}) + \item TypingRule.UseCase (see \secref{TypingRule.UseCase}) + \item TypingRule.UseCatcher (see \secref{TypingRule.UseCatcher}) +\end{itemize} + +\subsubsection{TypingRule.TypeCheckAST \label{sec:TypingRule.TypeCheckAST}} +\hypertarget{def-typecheckast}{} +The relation +\[ +\typecheckast( + \overname{\staticenvs}{\tenv} \aslsep + \overname{\decl^*}{\decls} +) \aslrel +(\overname{\decl^*}{\newdecls} \times \overname{\staticenvs}{\newtenv}) +\cup \overname{\TTypeError}{\TypeErrorConfig} +\] +annotates a list of declarations $\decls$ in an input static environment $\tenv$, +yielding an output static environment $\newtenv$ and annotated list of declarations $\newdecls$. +\ProseOtherwiseTypeError + +\begin{definition}[Strongly Connected Components] +\hypertarget{def-scc}{} +Given a graph $G=(V, E)$, a \\ subset of its nodes $C \subseteq V$ is called +a \emph{strongly connected component} of $G$ if +every pair of nodes $u,v \in C$ reachable from one another. + +The \emph{strongly connected components} of a graph $(V, E)$ uniquely partitions its set of +nodes $V$ into a set of strongly connected components: +\[ +\SCC(V, E) \triangleq \{ C \subseteq V \;|\; \forall u,v\in C.\ (u,v), (v,u) \in E^* \} \enspace. +\] + +We write $E^*$ to denote the reflexive-transitive closure of $E$. +\end{definition} + +\begin{definition}[Topological Ordering] +For a graph $G=(V, E)$ and its \\ +strongly connected components $\comps \triangleq \SCC(V, E)$, +we say that $C_1\in\comps$ is ordered before $C_2\in\comps$, denoted $C_1 < C_2$, +if the following condition holds: +\[ +C_1 < C_2 \Leftrightarrow \exists c_1\in C_1.\ c_2\in C_2.\ (c_1,c_2) \in E^* \enspace. +\] +This ordering is not total. That is, there may exist strongly connected components +$A,B\in\comps$ such that $A \not< B$ and $B \not< A$. + +\hypertarget{def-topologicalordering}{} +We say that a list of subsets of $V$ --- $\compstwo$ --- respects the topological ordering of $\comps$ +if each element of $\compstwo$ is a member of $\comps$ and for every $C_1,C_2\in\comps$ such that +$C_1 < C_2$ we have that $C_1$ appears before $C_2$ in $\compstwo$. +We denote this as $\compstwo \in \topologicalordering(V, E, \comps)$. +\end{definition} + +\subsubsection{Prose} +All of the following apply: +\begin{itemize} + \item applying $\builddependencies$ to $\decls$ yields the dependency graph \\ $(\defs, \dependencies)$; + \item partitioning the nodes of the dependency graph $(\defs, \dependencies)$ into strongly connected components + yields $\comps$; + \item $\compstwo$ is an ordering of $\comps$ that respects the topological ordering induced by $\dependencies$; + \item $\compdecls$ applies $\declsofcomp$ to each component $\vc$ in $\compstwo$ to transform it into a list, + yielding a list of lists where each sublist corresponds to one strongly connected component; + \item applying $\annotatedeclcomps$ to $\compdecls$ in $\tenv$ yields \\ + $(\newdecls, \newtenv)$\ProseOrTypeError. +\end{itemize} +\CodeSubsection{\TypeCheckASTBegin}{\TypeCheckASTEnd}{../Typing.ml} + +\subsubsection{Formally} +\begin{mathpar} +\inferrule{ + \builddependencies(\decls) \typearrow (\defs, \dependencies)\\ + \SCC(\defs, \dependencies) = \compsone\\ + \compstwo \in \topologicalordering(\compsone, \dependencies)\\ + \compdecls \eqdef [ \vc\in\compstwo: \declsofcomp(\vc, \decls) ]\\ + \annotatedeclcomps(\tenv, \compdecls) \typearrow (\newdecls, \newtenv) \OrTypeError +}{ + \typecheckast(\tenv, \decls) \typearrow (\newdecls, \newtenv) +} +\end{mathpar} + +\subsubsection{Comments} +It is crucial to process the strongly connected components obtained from the dependency graph +according to the topological ordering of the components. Otherwise, the type-system could +falsely result in a type error indicating that some identifier is not defined. +However, a topological ordering is not unique, which is why $\typecheckast$ is a relation rather than +a function. +It is possible to obtain a deterministic ordering by ordering components so as to respect +the order of declarations in $\decls$, that is, +the order in which declarations appear in the specification. +Similarly, any ordering of the declarations within a single strongly connected component is correct, +but it is possible to order the declarations according to their order of appearance in $\decls$, +as demonstrated in TypingRule.DeclsOfComp. + +\lrmcomment{This relates to \identi{LWQQ}.} + +\subsubsection{TypingRule.DeclsOfComp \label{sec:TypingRule.DeclsOfComp}} +\hypertarget{def-declsofcomp}{} +The helper function +\[ +\declsofcomp( + \overname{\pow{\identifier}}{\comp} \aslsep + \overname{\decl^*}{\decls} +) \aslto \overname{\decl^*}{\compdecls} +\] +lists the sublist of declarations in $\decls$ corresponding to the identifiers in $\comp$ +yielding $\compdecls$ + +\subsubsection{Prose} +One of the following applies: +\begin{itemize} + \item All of the following apply (\textsc{empty}): + \begin{itemize} + \item $\decls$ is the empty list; + \item define $\compdecls$ as the empty list. + \end{itemize} + + \item All of the following apply (\textsc{non\_empty}): + \begin{itemize} + \item $\decls$ is the list with \head\ $\vd$ and \tail\ $declsone$; + \item define $\declstwo$ as the singleton list for $\vd$ if applying $\defdecl$ to $\vd$ yields an identifier + that is a member of $\comp$ and the empty list, otherwise; + \item applying $\declsofcomp$ to $\comp$ and $\declsone$ yields $\declsthree$; + \item define $\compdecls$ as the concatenation of $\declstwo$ and $\declsthree$. + \end{itemize} +\end{itemize} + +\subsubsection{Formally} +\begin{mathpar} +\inferrule[empty]{}{ + \declsofcomp(\comp, \overname{\emptylist}{\decls}) \typearrow \overname{\emptylist}{\compdecls} +} +\and +\inferrule[non\_empty]{ + \declstwo \eqdef \choice{\defdecl(\vd) \in \comp}{[\vd]}{\emptylist}\\ + \declsofcomp(\comp, \declsone) \typearrow \declsthree +}{ + \declsofcomp(\comp, \overname{[\vd]\concat\declsone}{\decls}) \typearrow \overname{\declstwo\concat\declsthree}{\compdecls} +} +\end{mathpar} + +\subsubsection{TypingRule.AnnotateDeclComps \label{sec:TypingRule.AnnotateDeclComps}} +\hypertarget{def-annotatedeclcomps}{} +The function +\[ +\annotatedeclcomps(\overname{\staticenvs}{\tenv} \aslsep \overname{(\decl^*)^*}{\comps}) +\aslto +(\overname{\staticenvs}{\newtenv} \times \overname{\decl^*}{\newdecls}) +\cup \overname{\TTypeError}{\TypeErrorConfig} +\] +annotates a list of declaration components $\comps$ +(a list of lists) in the static environment $\tenv$, +yielding the annotated list of declarations $\newdecls$ and modified environment $\newtenv$. +\ProseOtherwiseTypeError + +We note that a strongly-connected component containing just a single declaration may contain +any kind of global declaration --- +a type declaration, a global storage declaration, or a subprogram declaration --- +whereas a strongly-connected component containing multiple declarations must be checked +to contain only subprograms. This is because the only type of mutually-recursive declarations +allows in ASL are between subprograms. The rules below handle these cases separately (\textsc{single} +for single declarations and \textsc{mutually\_recursive} for more than one declaration). + +\subsubsection{Prose} +One of the following applies: +\begin{itemize} + \item All of the following apply (\textsc{empty}): + \begin{itemize} + \item $\comps$ is the empty list; + \item define $\newtenv$ as $\tenv$; + \item define $\newdecls$ as the empty list. + \end{itemize} + + \item All of the following apply (\textsc{single}): + \begin{itemize} + \item $\comps$ is a list with \head\ $\comp$ and \tail\ $\compsone$; + \item $\comp$ is a single declaration $\vd$; + \item applying $\typecheckdecl$ to $\vd$ in $\tenv$ yields $(\vdone, \tenvone)$\ProseOrTypeError; + \item applying $\annotatedeclcomps$ to $\compsone$ in $\tenvone$ yields \\ $(\newtenv, \declsone)$\ProseOrTypeError; + \item define $\newdecls$ as the list with \head\ $\vdone$ and \tail\ $\declsone$. + \end{itemize} + + \item All of the following apply (\textsc{mutually\_recursive}): + \begin{itemize} + \item $\comps$ is a list with \head\ $\comp$ and \tail\ $\compsone$; + \item $\comp$ is a list with more than one declaration (which together represent a mutually-recursive + list of declarations); + \item applying $\typecheckmutuallyrec$ to $\comp$ in $\tenv$ yields \\ $(\declsone, \tenvone)$\ProseOrTypeError; + \item applying $\annotatedeclcomps$ to $\compsone$ in $\tenvone$ yields \\ $(\newtenv, \declstwo)$\ProseOrTypeError; + \item define $\newdecls$ as the concatenation of $\declsone$ and $\declstwo$. + \end{itemize} +\end{itemize} + +\subsubsection{Formally} +\begin{mathpar} +\inferrule[empty]{}{ + \annotatedeclcomps(\tenv, \overname{\emptylist}{\comps}) \aslto (\overname{\tenv}{\newtenv}, \overname{\emptylist}{\newdecls}) +} +\and +\inferrule[single]{ + \comp = [\vd]\\ + \typecheckdecl(\tenv, \vd) \typearrow (\vdone, \tenvone) \OrTypeError\\\\ + \annotatedeclcomps(\tenvone, \compsone) \typearrow (\newtenv, \declsone) \OrTypeError +}{ + \annotatedeclcomps(\tenv, \overname{[\comp] \concat \compsone}{\comps}) \aslto + (\newtenv, \overname{[\vdone] \concat \declsone}{\newdecls}) +} +\and +\inferrule[mutually\_recursive]{ + |\comp| > 1\\ + \typecheckmutuallyrec(\tenv, \comp) \typearrow (\declsone, \tenvone) \OrTypeError\\\\ + \annotatedeclcomps(\tenvone, \compsone) \typearrow (\newtenv, \declstwo) \OrTypeError +}{ + \annotatedeclcomps(\tenv, \overname{[\comp] \concat \compsone}{\comps}) \aslto + (\newtenv, \overname{\declsone \concat \declstwo}{\newdecls}) +} +\end{mathpar} + +\subsubsection{TypingRule.BuildDependencies \label{sec:TypingRule.BuildDependencies}} +\hypertarget{def-builddependencies}{} +The function +\[ +\builddependencies(\overname{\decl^*}{\decls}) +\aslto +(\overname{\identifier^*}{\defs}, \overname{(\identifier\times\identifier)^*}{\dependencies}) +\] +takes a set of declarations $\decls$ and +returns a graph whose set of nodes are the identifiers that are used to name declarations +and whose set of edges $\dependencies$ consists of pairs $(a,b)$ +where the declaration of $a$ uses an identifier defined by $b$. +We refer to this graph as the \emph{dependency graph} (of $\decls$). + +\subsubsection{Prose} +All of the following apply: +\begin{itemize} + \item define $\defs$ as the union of two sets: + \begin{enumerate} + \item the set of identifiers obtained by applying $\defdecl$ to each declaration in $\decls$; + \item the union of applying $\defenumlabels$ to each declaration in $\decls$. + \end{enumerate} + \item define $\dependencies$ as the union of applying $\decldependencies$ to each declaration in $\decls$. +\end{itemize} + +\subsubsection{Formally} +\begin{mathpar} +\inferrule{ + \defs \eqdef \{ \defdecl(\vd) \;|\; \vd \in \decls\} \cup \bigcup_{\vd\in\decls} \defenumlabels(\vd)\\ + \dependencies \eqdef \bigcup_{\vd \in \decls} \decldependencies(\vd) +}{ + \builddependencies(\decls) \typearrow (\ids, \dependencies) +} +\end{mathpar} + +\subsubsection{TypingRule.DeclDependencies \label{sec:TypingRule.DeclDependencies}} +\hypertarget{def-decldependencies}{} +The function +\[ +\decldependencies(\overname{\decl}{\vd}) \aslto \overname{(\identifier\times\identifier)^*}{\dependencies} +\] +returns the set of dependent pairs of identifiers $\dependencies$ induced by the declaration $\vd$. + +\subsubsection{Prose} +Define $\dependencies$ as the union of the following two sets: +\begin{enumerate} + \item a pair $(\idone, \idtwo)$ where $\idone$ is the result of applying $\defdecl$ to $\vd$ + and $\idtwo$ included in the result of applying $\defenumlabels$ to $\vd$; and + \item a pair $(\idone, \idtwo)$ where $\idone$ is the result of applying $\defdecl$ to $\vd$ + and $\idtwo$ included in the result of applying $\usedecl$ to $\vd$; and +\end{enumerate} + +\subsubsection{Formally} +\begin{mathpar} +\inferrule{ + { + \begin{array}{rcll} + \dependencies & \eqdef & \{ (\idone, \idtwo) \;|\; \idone = \defdecl(\vd) \land \idtwo \in \defenumlabels(\vd) \} & \cup\\ + & & \{ (\idone, \idtwo) \;|\; \idone = \defdecl(\vd) \land \idtwo \in \usedecl(\vd) \} & + \end{array} + } +}{ + \decldependencies(\vd) \typearrow \dependencies +} +\end{mathpar} + +\subsubsection{TypingRule.TypeCheckMutuallyRec \label{sec:TypingRule.TypeCheckMutuallyRec}} +\hypertarget{def-typecheckmutuallyrec}{} +The function +\[ + \typecheckmutuallyrec( + \overname{\staticenvs}{\tenv} \aslsep + \overname{\decl^*}{\decls} + ) + \aslto + ( + \overname{\decl^*}{\newdecls} \times + \overname{\staticenvs}{\newtenv} + ) + \cup \overname{\TTypeError}{\TypeErrorConfig} +\] +annotates a list of mutually recursive declarations +$\decls$ in the static environment $\tenv$, +yielding the annotated list of subprogram declarations $\newdecls$ +and modified environment $\newtenv$. + +One of the requirements from an ASL specification is that each setter has a corresponding getter. +To facilitate checking this requirement, the type-system annotates the declarations of all subprograms +that are not setters before annotating the declarations of setters. This way, when annotating a setter, +the corresponding getter should have already been annotated and added to the environment, making it +easy to check this requirement. + +\subsubsection{Prose} +All of the following apply: +\begin{itemize} + \item checking that each declaration in $\vd$ is a subprogram declaration yields $\True$\ProseOrTypeError; + \item applying $\annotatefuncsig$ to each node $\vf$ in $\tenv$, where $\DFunc(\vf)$ is a declaration in $\decls$, + yields $(\tenv_\vf, \vd_\vf)$\ProseOrTypeError; + \item define $\envandfs$ as the list of pairs, each consisting of the local environment component of $\tenv_\vf$ + and the annotated subprogram $\vd_\vf$, for each subprogram declaration $\DFunc(\vf)$ in $\decls$; + \item splitting $\envandfs$ into two sublists by testing each pair to check whether the subprogram declaration + component is that of a setter (or an empty setter) yields $\setters$ and $\others$, respectively; + \item define $\envandfsone$ as the concatenation of $\others$ and $\setters$; + \item applying $\foldenvandfs$ to the global component of $\tenv$ and $\envandfsone$ yields $(\genv, \envandfstwo)$\ProseOrTypeError; + \item for each pair consisting of a local static environment and subprogram declaration $(\lenv, \DFunc(\vf))$, + applying $\annotatesubprogram$ to the static environment $(\genv, \lenv)$ and $\vf$ yields $\newd_\vf$\ProseOrTypeError; + \item define $\newdecls$ as the list of subprogram declarations $\DFunc(\newd_\vf)$, for each pair $(\Ignore, \DFunc(\vf))$ in + $\envandfstwo$; + \item define $\newtenv$ as the static environment $(\genv, L^\tenv)$. +\end{itemize} + +\CodeSubsection{\TypeCheckMutuallyRecBegin}{\TypeCheckMutuallyRecEnd}{../Typing.ml} + +\subsubsection{Formally} +\begin{mathpar} +\inferrule{ + \vd\in\decls: \checktrans{\astlabel(\vd) = \DFunc}{\BadRecursiveDecls} \typearrow \True\OrTypeError\\\\ + \DFunc(\vf)\in\decls: \annotatefuncsig(\tenv, \vf) \typearrow (\tenv_\vf, \vd_\vf)\OrTypeError\\\\ + \envandfs \eqdef [\DFunc(\vf)\in\decls: (L^{\tenv_\vf}, \vd_\vf)]\\ + { + \setters \eqdef \left[ \begin{array}{r|l} + (\lenv,\vd) & (\lenv, \DFunc(\vf)) \in \envandfs\ \land \\ + & \astlabel(\vf) \in \{\STSetter, \STEmptySetter\} + \end{array}\right] + }\\ + { + \others \eqdef \left[ \begin{array}{r|l} + (\lenv,\vd) & (\lenv, \DFunc(\vf)) \in \envandfs\ \land \\ + & \astlabel(\vf) \not\in \{\STSetter, \STEmptySetter\} + \end{array}\right] + }\\ + \envandfsone \eqdef \others \concat \setters\\ + \foldenvandfs(G^\tenv, \envandfsone) \typearrow (\genv, \envandfstwo) \OrTypeError\\\\ + { + \begin{array}{r} + (\lenv, \DFunc(\vf))\in\envandfstwo: \annotatesubprogram{(\genv, \lenv), \vf} \typearrow \\ \newd_\vf \OrTypeError + \end{array} + }\\\\ + \newdecls \eqdef [(\Ignore, \DFunc(\vf))\in\envandfstwo: \DFunc(\newd_\vf)] +}{ + \typecheckmutuallyrec(\tenv, \decls) \typearrow (\newdecls, \overname{(\genv, L^\tenv)}{\newtenv}) +} +\end{mathpar} + +\subsubsection{TypingRule.FoldEnvAndFs \label{sec:TypingRule.FoldEnvAndFs}} +\hypertarget{def-foldenvandfs}{} +The function +\[ + \foldenvandfs( + \overname{\globalstaticenvs}{\genv} \aslsep + \overname{(\localstaticenvs\times\func)^*}{\envandfs} + ) \aslto + \overname{\globalstaticenvs}{\newgenv} \times + \overname{(\localstaticenvs\times\func)^*}{\newenvandfs} + \cup \overname{\TTypeError}{\TypeErrorConfig} +\] +processes a list of pairs, each consisting of a local static environment and a subprogram declaration, $\envandfs$, +in the context of a global static environment $\genv$. +The result is a modified global static environment $\newgenv$ and list of pairs $\newenvandfs$. + +\subsubsection{Prose} +One of the following applies: +\begin{itemize} + \item All of the following apply (\textsc{empty}): + \begin{itemize} + \item $\envandfs$ is the empty list; + \item define $\newgenv$ as $\genv$; + \item define $\newenvandfs$ as the empty list. + \end{itemize} + + \item All of the following apply (\textsc{non\_empty}): + \begin{itemize} + \item $\envandfs$ is the list with \head\ $(\lenv, \vf)$ and \tail\ $\envandfsone$; + \item define $\tenv$ as the environment where the global environment component is $\genv$ and the local environment component is $\lenv$; + \item applying $\declareonefunc$ to $\vf$ in $\tenv$ yields $(\tenvone, \vfone)$\ProseOrTypeError; + \item applying $\foldenvandfs$ to the global environment of $\tenvone$ and \\ + $\envandfsone$ yields $(\newgenv, \envandfstwo)$\ProseOrTypeError; + \item define $\newenvandfs$ as the list with \head\ $(\lenv, \vfone)$ and \tail\ $\envandfstwo$. + \end{itemize} +\end{itemize} + +\subsubsection{Formally} +\begin{mathpar} +\inferrule[empty]{}{ + \foldenvandfs(\genv, \overname{\emptylist}{\envandfs}) \typearrow (\overname{\genv}{\newgenv}, \overname{\emptylist}{\newenvandfs}) +} +\and +\inferrule[non\_empty]{ + \tenv \eqdef (\genv, \lenv)\\ + \declareonefunc(\tenv, \vf) \typearrow (\tenvone, \vfone) \OrTypeError\\\\ + \foldenvandfs(G^\tenvone, \envandfsone) \typearrow (\newgenv, \envandfstwo) \OrTypeError\\\\ + \newenvandfs \eqdef [(\lenv, \vfone)] \concat \envandfstwo +}{ + \foldenvandfs(\genv, \overname{[(\lenv, \vf)]\concat\envandfsone}{\envandfs}) \typearrow (\overname{\genv}{\newgenv}, \newenvandfs) +} +\end{mathpar} + +\subsubsection{TypingRule.DefDecl \label{sec:TypingRule.DefDecl}} +\hypertarget{def-defdecl}{} +The function +\[ +\defdecl(\overname{\decl}{\vd}) \aslto \overname{\identifier}{\name} +\] +returns the identifier $\name$ being defined by the declaration $\vd$. + +\subsubsection{Prose} +One of the following applies: +\begin{itemize} + \item All of the following apply (\textsc{d\_func}): + \begin{itemize} + \item $\vd$ declares a subprogram for the identifier $\name$. + \end{itemize} + + \item All of the following apply (\textsc{d\_globalstorage}): + \begin{itemize} + \item $\vd$ declares a global storage element for the identifier $\name$. + \end{itemize} + + \item All of the following apply (\textsc{d\_typedecl}): + \begin{itemize} + \item $\vd$ declares a type for the identifier $\name$. + \end{itemize} +\end{itemize} + +\begin{mathpar} +\inferrule[d\_func]{}{ + \defdecl(\overname{\DFunc(\funcname: \name, \ldots)}{\vd}) \typearrow \name +} +\and +\inferrule[d\_globalstorage]{}{ + \defdecl(\overname{\DGlobalStorage(\GDname: \name, \ldots)}{\vd}) \typearrow \name +} +\and +\inferrule[d\_typedecl]{}{ + \defdecl(\overname{\DTypeDecl(\name, \Ignore, \Ignore)}{\vd}) \typearrow \name +} +\end{mathpar} + +\subsubsection{TypingRule.DefEnumLabels \label{sec:TypingRule.DefEnumLabels}} +\hypertarget{def-defenumlabels}{} +The function +\[ +\defenumlabels(\overname{\decl}{\vd}) \aslto \overname{\pow{\identifier}}{\vlabels} +\] +takes a declaration $\vd$ and returns the set of enumeration labels it defines --- $\vlabels$ -- +if it defines any. + +\subsubsection{Prose} +One of the following applies: +\begin{itemize} + \item All of the following apply (\textsc{decl\_enum}): + \begin{itemize} + \item $\vd$ is a declaration of an enumeration type with labels $\vlabels$; + \item the result is $\vlabels$ as a set (rather than a list). + \end{itemize} + + \item All of the following apply (\textsc{other}): + \begin{itemize} + \item $\vd$ is not a declaration of an enumeration type; + \item define $\vlabels$ as the empty set. + \end{itemize} +\end{itemize} + +\begin{mathpar} +\inferrule[decl\_enum]{ + \vd = \DTypeDecl(\name, \TEnum(\vlabels, \Ignore)) +}{ + \defenumlabels(\vd) \typearrow \overname{\{\vlabels\}}{\vlabels} +} +\and +\inferrule[other]{ + \vd \neq \DTypeDecl(\name, \TEnum(\vlabels, \Ignore)) +}{ + \defenumlabels(\vd) \typearrow \overname{\emptyset}{\vlabels} +} +\end{mathpar} + +\subsubsection{TypingRule.UseDecl \label{sec:TypingRule.UseDecl}} +\hypertarget{def-usedecl}{} +The function +\[ +\usedecl(\overname{\decl}{\vd}) \aslto \overname{\pow{\identifier}}{\ids} +\] +returns the set of identifiers $\ids$ which the declaration $\vd$ depends on. + +\subsubsection{Prose} +One of the following applies: +\begin{itemize} + \item All of the following apply (\textsc{D\_TypeDecl}): + \begin{itemize} + \item $\vd$ declares a type $\tty$ and fields $\fields$, that is, + $\DTypeDecl(\Ignore, \tty, \fields)$ (the first component is the name, which is being defined); + \item define $\ids$ as the union of applying $\usety$ to $\tty$ and applying $\usesubtypes$ to $\fields$. + \end{itemize} + + \item All of the following apply (\textsc{D\_GlobalStorage}): + \begin{itemize} + \item $\vd$ declares a global storage element with initial value $\initialvalue$ and type $\tty$; + \item define $\ids$ as the union of applying $\useexpr$ to $\initialvalue$ and applying $\usety$ to $\tty$. + \end{itemize} + + \item All of the following apply (\textsc{D\_Func}): + \begin{itemize} + \item $\vd$ declares a subprogram with arguments $\vargs$, \optional\ return type \\ + $\rettyopt$, parameters $\vparams$, and body statement $\body$; + \item define $\ids$ as the union of applying $\usety$ to each type of an argument in $\vargs$, + applying $\usety$ to $\rettyopt$, applying $\usety$ to each type of a parameter in $\vparams$, + and applying $\useexpr$ to $\body$. + \end{itemize} +\end{itemize} + +\subsubsection{Formally} +\begin{mathpar} +\inferrule[D\_TypeDecl]{}{ + \usedecl(\overname{\DTypeDecl(\Ignore, \tty, \fields)}{\vd}) \typearrow \overname{\usety(\tty) \cup \usesubtypes(\fields)}{\ids} +} +\and +\inferrule[D\_GlobalStorage]{ + \ids \eqdef \useexpr(\initialvalue) \cup \usety(\tty) +}{ + \usedecl(\overname{\DGlobalStorage(\{ + \GDinitialvalue: \initialvalue, + \GDty: \tty\ldots\})}{\vd}) + \typearrow \ids +} +\and +\inferrule[D\_Func]{ + { + \begin{array}{rcll} + \ids &\eqdef& \{ (\Ignore, \vt) \in \usety(\vt) : \id \} &\cup\\ + && \usety(\rettyopt) &\cup\\ + && \{ (\Ignore, \vt) \in \vparams : \usety(\vt) \} &\cup \\ + && \useexpr(\body) & + \end{array} + } +}{ + { + \usedecl\left(\overname{ + \DFunc\left( + \left\{ + \begin{array}{l} + \funcbody: \body,\\ + \funcargs: \vargs,\\ + \funcreturntype: \rettyopt,\\ + \funcparameters: \vparams,\\ + \ldots\\ + \end{array} + \right\} + \right)}{\vd} + \right) + \typearrow \ids + } +} +\end{mathpar} + +\subsubsection{TypingRule.UseTy \label{sec:TypingRule.UseTy}} +\hypertarget{def-usety}{} +The function +\[ +\usety(\overname{\ty \cup \langle\ty\rangle}{\vt}) \aslto \overname{\pow{\identifier}}{\ids} +\] +returns the set of identifiers $\ids$ which the type or \optional\ type $\vt$ depends on. + +\subsubsection{Prose} +One of the following applies: +\begin{itemize} + \item All of the following apply (\textsc{none}): + \begin{itemize} + \item $\vt$ is $\None$; + \item define $\ids$ as $\emptyset$. + \end{itemize} + + \item All of the following apply (\textsc{some}): + \begin{itemize} + \item $\vt$ is $\langle\tty\rangle$; + \item applying $\usety$ to $\tty$ yields $\ids$. + \end{itemize} + + \item All of the following apply (\textsc{simple}): + \begin{itemize} + \item $\vt$ is one of the following types: enumeration, Boolean, real, or string; + \item define $\ids$ as the empty set. + \end{itemize} + + \item All of the following apply (\textsc{t\_named}): + \begin{itemize} + \item $\vt$ is the named type for $\vs$; + \item define $\ids$ as the singleton set for $\vs$. + \end{itemize} + + \item All of the following apply (\textsc{int\_no\_constraints}): + \begin{itemize} + \item $\vt$ is either the unconstrained integer type or a \parameterizedintegertype; + \item define $\ids$ as the empty set. + \end{itemize} + + \item All of the following apply (\textsc{int\_well\_constrained}): + \begin{itemize} + \item $\vt$ is the well-constrained integer type with constraints $\vcs$; + \item define $\ids$ as the union of applying $\useconstraint$ to each constraint in $\vcs$. + \end{itemize} + + \item All of the following apply (\textsc{t\_tuple}): + \begin{itemize} + \item $\vt$ is the tuple type with list of types $\vli$; + \item define $\ids$ as the union of applying $\useconstraint$ to each constraint in $\vcs$. + \end{itemize} + + \item All of the following apply (\textsc{structured}): + \begin{itemize} + \item $\vt$ is a \structuredtype\ with fields $\fields$; + \item define $\ids$ as the union of applying $\usety$ to each field type in $\fields$. + \end{itemize} + + \item All of the following apply (\textsc{array\_expr}): + \begin{itemize} + \item $\vt$ is an array expression with length expression $\ve$ and element type $\vtp$; + \item define $\ids$ as the union of applying $\useexpr$ to $\ve$ and applying $\usety$ to $\vtp$. + \end{itemize} + + \item All of the following apply (\textsc{array\_enum}): + \begin{itemize} + \item $\vt$ is an array expression with enumeration type $\vs$ and element type $\vtp$; + \item define $\ids$ as the union of the singleton set for $\vs$ and applying $\usety$ to $\vtp$. + \end{itemize} + + \item All of the following apply (\textsc{t\_bits}): + \begin{itemize} + \item $\vt$ is a bitvector type with width expression $\ve$ and bitfields $\bitfields$; + \item define $\ids$ as the union of applying $\useexpr$ to $\ve$ and applying $\usebitfield$ to each field in $\bitfields$. + \end{itemize} +\end{itemize} + +\subsubsection{Formally} +\begin{mathpar} +\inferrule[none]{}{ + \usety(\overname{\None}{\vt}) \typearrow \overname{\emptyset}{\ids} +} +\and +\inferrule[some]{ + \usety(\tty) \typearrow \ids +}{ + \usety(\overname{\langle\tty\rangle}{\vt}) \typearrow \ids +} +\and +\inferrule[simple]{ + \astlabel(\vt) \in \{\TEnum, \TBool, \TReal, \TString\} +}{ + \usety(\vt) \typearrow \overname{\emptyset}{\ids} +} +\and +\inferrule[t\_named]{}{ + \usety(\overname{\TNamed(\vs)}{\vt}) \typearrow \overname{\{\vs\}}{\ids} +} +\end{mathpar} + +\begin{mathpar} +\inferrule[int\_no\_constraints]{ + \astlabel(\vc) \in \{\unconstrained, \parameterized\} +}{ + \usety(\overname{\TInt(\vc)}{\vt}) \typearrow \overname{\emptyset}{\ids} +} +\end{mathpar} + +\begin{mathpar} +\inferrule[int\_well\_constrained]{}{ + \usety(\overname{\TInt(\wellconstrained(\vcs))}{\vt}) \typearrow \overname{\bigcup_{\vc \in \vcs} \useconstraint(\vc)}{\ids} +} +\end{mathpar} + +\begin{mathpar} +\inferrule[t\_tuple]{}{ + \usety(\overname{\TTuple(\vli)}{\vt}) \typearrow \overname{\bigcup_{\vt \in \vli} \usety(\vt)}{\ids} +} +\end{mathpar} + +\begin{mathpar} +\inferrule[structured]{ + L \in \{\TRecord, \TException\}}{ + \usety(\overname{L(\fields)}{\vt}) \typearrow \overname{\bigcup_{(\Ignore, \vt) \in \fields} \usety(\vt)}{\ids} +} +\end{mathpar} + +\begin{mathpar} +\inferrule[array\_expr]{}{ + \usety(\overname{\TArray(\ArrayLengthExpr(\ve), \vtp)}{\vt}) \typearrow \overname{\useexpr(\ve) \cup \usety(\vtp)}{\ids} +} +\end{mathpar} + +\begin{mathpar} +\inferrule[array\_enum]{}{ + \usety(\overname{\TArray(\ArrayLengthEnum(\vs, \Ignore), \vtp)}{\vt}) \typearrow \overname{\{\vs\} \cup \usety(\vtp)}{\ids} +} +\end{mathpar} + +\begin{mathpar} +\inferrule[t\_bits]{}{ + \usety(\overname{\TBits(\ve, \bitfields)}{\vt}) \typearrow \overname{\useexpr(\ve) \cup \bigcup_{\vf \in\bitfields}\usebitfield(\vf)}{\ids} +} +\end{mathpar} + +\subsubsection{TypingRule.UseSubtypes \label{sec:TypingRule.UseSubtypes}} +\hypertarget{def-usesubtypes}{} +The function +\[ +\usesubtypes(\overname{\langle(\overname{\identifier}{\vx}\times\overname{\field^*}{\subfields})\rangle}{\fields}) \aslto \overname{\pow{\identifier}}{\ids} +\] +returns the set of identifiers $\ids$ which the \optional\ pair consisting of +identifier $\vx$ (the type being subtyped) and fields $\subfields$ depends on. + +\subsubsection{Prose} +One of the following applies: +\begin{itemize} + \item All of the following apply (\textsc{none}): + \begin{itemize} + \item $\fields$ is $\None$; + \item define $\ids$ as the empty set. + \end{itemize} + + \item All of the following apply (\textsc{some}): + \begin{itemize} + \item $\fields$ is $\langle(\vx, \subfields)\rangle$; + \item define $\ids$ as the union of the singleton set for $\vx$ and the union of applying $\usety$ + to each field type in $\subfields$. + \end{itemize} +\end{itemize} + +\subsubsection{Formally} +\begin{mathpar} +\inferrule[none]{}{ + \usesubtypes(\None) \typearrow \overname{\emptyset}{\ids} +} +\and +\inferrule[some]{ + \ids \eqdef \{\vx\} \cup \bigcup_{(\Ignore, \vt) \usety(\vt)} +}{ + \usesubtypes(\langle(\vx, \subfields)\rangle) \typearrow \ids +} +\end{mathpar} + +\subsubsection{TypingRule.UseExpr \label{sec:TypingRule.UseExpr}} +\hypertarget{def-useexpr}{} +The function +\[ +\useexpr(\overname{\expr}{\ve} \cup \langle\overname{\expr}{\ve}\rangle) \aslto \overname{\pow{\identifier}}{\ids} +\] +returns the set of identifiers $\ids$ which the expression or \optional\ expression $\ve$ depends on. + +\subsubsection{Prose} +One of the following applies: +\begin{itemize} + \item All of the following apply (\textsc{none}): + \begin{itemize} + \item $\ve$ is $\None$; + \item define $\ids$ as the empty set. + \end{itemize} + + \item All of the following apply (\textsc{some}): + \begin{itemize} + \item $\ve$ is $\langle\veone\rangle$; + \item applying $\useexpr$ to $\veone$ yields $\ids$. + \end{itemize} + + \item All of the following apply (\textsc{e\_literal}): + \begin{itemize} + \item $\ve$ is a literal expression; + \item define $\ids$ as the empty set. + \end{itemize} + + \item All of the following apply (\textsc{e\_atc}): + \begin{itemize} + \item $\ve$ is the typing assertion for expression $\ve$ and type $\tty$; + \item define $\ids$ as the union of applying $\useexpr$ to $\veone$ and applying $\usety$ to $\tty$. + \end{itemize} + + \item All of the following apply (\textsc{e\_var}): + \begin{itemize} + \item $\ve$ is the variable expression for identifier $\vx$; + \item define $\ids$ as the singleton set for $\vx$. + \end{itemize} + + \item All of the following apply (\textsc{e\_getarray}): + \begin{itemize} + \item $\ve$ is the \arrayaccess\ expression for base expression $\veone$ and index expression $\vetwo$; + \item define $\ids$ as the union of applying $\useexpr$ to $\veone$ and applying $\useexpr$ to $\vetwo$. + \end{itemize} + + \item All of the following apply (\textsc{e\_binop}): + \begin{itemize} + \item $\ve$ is the binary operation expression over expressions $\veone$ and $\vetwo$; + \item define $\ids$ as the union of applying $\useexpr$ to $\veone$ and applying $\useexpr$ to $\vetwo$. + \end{itemize} + + \item All of the following apply (\textsc{e\_unop}): + \begin{itemize} + \item $\ve$ is the unary operation expression over any unary operation and an expression $\veone$; + \item define $\ids$ as the union of applying $\useexpr$ to $\veone$. + \end{itemize} + + \item All of the following apply (\textsc{e\_call}): + \begin{itemize} + \item $\ve$ is the call expression of the subprogram named $\vx$ with argument expressions $\vargs$ and parameter expressions $\namedargs$; + \item define $\ids$ as the union of the singleton set for $\vx$, and the set obtained by applying $\useexpr$ to each expression in + $\vargs$ and each expression in $\namedargs$. + \end{itemize} + + \item All of the following apply (\textsc{e\_slice}): + \begin{itemize} + \item $\ve$ is the slicing expression over expression $\veone$ and slices $\slices$; + \item define $\ids$ as the union of applying $\useexpr$ to $\veone$ and applying $\useslice$ to each slice in $\slices$. + \end{itemize} + + \item All of the following apply (\textsc{e\_cond}): + \begin{itemize} + \item $\ve$ is the conditional expression over expressions $\veone$, $\vetwo$, and $\vethree$; + \item define $\ids$ as the union of applying $\useexpr$ to each of $\veone$, $\vetwo$, and $\vethree$. + \end{itemize} + + \item All of the following apply (\textsc{e\_getitem}): + \begin{itemize} + \item $\ve$ is the tuple access expression over expression $\veone$; + \item define $\ids$ as the application of $\useexpr$ to $\veone$. + \end{itemize} + + \item All of the following apply (\textsc{e\_getfield}): + \begin{itemize} + \item $\ve$ is the field access expression over expression $\veone$; + \item define $\ids$ as the application of $\useexpr$ to $\veone$. + \end{itemize} + + \item All of the following apply (\textsc{e\_getfields}): + \begin{itemize} + \item $\ve$ is the multiple field access expression over expression $\veone$; + \item define $\ids$ as the application of $\useexpr$ to $\veone$. + \end{itemize} + + \item All of the following apply (\textsc{e\_record}): + \begin{itemize} + \item $\ve$ is the record construction expression of type $\tty$ and field initializations $\vli$; + \item define $\ids$ as the union of applying of $\usety$ to $\tty$ and applying $\usety$ to each field type in $\vli$. + \end{itemize} + + \item All of the following apply (\textsc{e\_concat}): + \begin{itemize} + \item $\ve$ is the concatenation of expression $\ves$; + \item define $\ids$ as the union of applying of $\useexpr$ to each expression in $\ves$. + \end{itemize} + + \item All of the following apply (\textsc{e\_tuple}): + \begin{itemize} + \item $\ve$ is the tuple construction expression for the expressions $\ves$; + \item define $\ids$ as the union of applying of $\useexpr$ to each expression in $\ves$. + \end{itemize} + + \item All of the following apply (\textsc{e\_unknown}): + \begin{itemize} + \item $\ve$ is the unknown expression with type $\vt$; + \item define $\ids$ as the application of $\usety$ to $\vt$. + \end{itemize} + + \item All of the following apply (\textsc{e\_pattern}): + \begin{itemize} + \item $\ve$ is the pattern testing expression for subexpression $\veone$ and pattern $\vp$; + \item define $\ids$ as the union of applying $\useexpr$ to $\veone$ and applying $\usepattern$ to $\vp$. + \end{itemize} +\end{itemize} + +\subsubsection{Formally} +\begin{mathpar} +\inferrule[none]{}{ + \useexpr(\overname{\None}{\ve}) \typearrow \overname{\emptyset}{\ids} +} +\and +\inferrule[some]{ + \useexpr(\veone) \typearrow \ids +}{ + \useexpr(\overname{\langle\veone\rangle}{\ve}) \typearrow \overname{\emptyset}{\ids} +} +\and +\inferrule[e\_literal]{}{ + \useexpr(\overname{\ELiteral(\Ignore)}{\ve}) \typearrow \overname{\emptyset}{\ids} +} +\and +\inferrule[e\_atc]{}{ + \useexpr(\overname{\EATC(\veone, \tty)}{\ve}) \typearrow \overname{\useexpr(\veone) \cup \usety(\tty)}{\ids} +} +\and +\inferrule[e\_var]{}{ + \useexpr(\overname{\EVar(\vx)}{\ve}) \typearrow \overname{\{\vx\}}{\ids} +} +\end{mathpar} + +\begin{mathpar} +\inferrule[e\_getarray]{}{ + \useexpr(\overname{\EGetArray(\veone, \vetwo)}{\ve}) \typearrow \overname{\useexpr(\veone) \cup \useexpr(\vetwo)}{\ids} +} +\end{mathpar} + +\begin{mathpar} +\inferrule[e\_binop]{}{ + \useexpr(\overname{\EBinop(\Ignore, \veone, \vetwo)}{\ve}) \typearrow \overname{\useexpr(\veone) \cup \useexpr(\vetwo)}{\ids} +} +\end{mathpar} + +\begin{mathpar} +\inferrule[e\_unop]{}{ + \useexpr(\overname{\EUnop(\Ignore, \veone)}{\ve}) \typearrow \overname{\useexpr(\veone)}{\ids} +} +\end{mathpar} + +\begin{mathpar} +\inferrule[e\_call]{ + \ids \eqdef \{\vx\} \cup \bigcup_{\veone\in\vargs}\useexpr(\veone) \cup \bigcup_{(\Ignore, \vt)\in\namedargs}\usety(\vt) +}{ + \useexpr(\overname{\ECall(\vx, \vargs, \namedargs)}{\ve}) \typearrow \ids +} +\end{mathpar} + +\begin{mathpar} +\inferrule[e\_slice]{}{ + \useexpr(\overname{\ESlice(\veone, \slices)}{\ve}) \typearrow \overname{\useexpr(\veone) \cup \bigcup_{\vs\in\slices}\useslice(\vs)}{\ids} +} +\end{mathpar} + +\begin{mathpar} +\inferrule[e\_cond]{}{ + \useexpr(\overname{\ECond(\veone, \vetwo, \vethree)}{\ve}) \typearrow \overname{\useexpr(\veone) \cup \useexpr(\vetwo) \cup \useexpr(\vethree)}{\ids} +} +\end{mathpar} + +\begin{mathpar} +\inferrule[e\_getitem]{}{ + \useexpr(\overname{\EGetItem(\veone, \Ignore)}{\ve}) \typearrow \overname{\useexpr(\veone)}{\ids} +} +\and +\inferrule[e\_getfield]{}{ + \useexpr(\overname{\EGetField(\veone, \Ignore)}{\ve}) \typearrow \overname{\useexpr(\veone)}{\ids} +} +\end{mathpar} + +\begin{mathpar} +\inferrule[e\_getfields]{}{ + \useexpr(\overname{\EGetFields(\veone, \Ignore)}{\ve}) \typearrow \overname{\useexpr(\veone)}{\ids} +} +\end{mathpar} + +\begin{mathpar} +\inferrule[e\_record]{}{ + \useexpr(\overname{\ERecord(\tty, \vli)}{\ve}) \typearrow \overname{\usety(\tty) \cup \bigcup_{(\Ignore, \vt)\in\vli}\usety(\vt)}{\ids} +} +\end{mathpar} + +\begin{mathpar} +\inferrule[e\_concat]{}{ + \useexpr(\overname{\EConcat(\ves)}{\ve}) \typearrow \overname{\bigcup_{\veone\in\ves}\useexpr(\veone)}{\ids} +} +\end{mathpar} + +\begin{mathpar} +\inferrule[e\_tuple]{}{ + \useexpr(\overname{\EConcat(\ves)}{\ve}) \typearrow \overname{\bigcup_{\veone\in\ves}\useexpr(\veone)}{\ids} +} +\and +\inferrule[e\_unknown]{}{ + \useexpr(\overname{\EUnknown(\vt)}{\ve}) \typearrow \overname{\usety(\vt)}{\ids} +} +\end{mathpar} + +\begin{mathpar} +\inferrule[e\_pattern]{}{ + \useexpr(\overname{\EPattern(\veone, \vp)}{\ve}) \typearrow \overname{\useexpr(\veone) \cup \usepattern(\vp)}{\ids} +} +\end{mathpar} + +\subsubsection{TypingRule.UseLexpr \label{sec:TypingRule.UseLexpr}} +\hypertarget{def-uselexpr}{} +The function +\[ +\uselexpr(\overname{\lexpr}{\vle}) \aslto \overname{\pow{\identifier}}{\ids} +\] +returns the set of identifiers $\ids$ which the left-hand-side expression $\vle$ depends on. + +\subsubsection{Prose} +One of the following applies: +\begin{itemize} + \item All of the following apply (\textsc{le\_var}): + \begin{itemize} + \item $\vle$ is a left-hand-side variable expression for $\vx$; + \item define $\ids$ as the singleton set for $\vx$. + \end{itemize} + + \item All of the following apply (\textsc{le\_destructuring}): + \begin{itemize} + \item $\vle$ is a left-hand-side expression for assigning to a list of expressions $\vles$, + that is $\LEDestructuring(\vles)$; + \item define $\ids$ as the union of applying $\uselexpr$ to each expression in $\vles$. + \end{itemize} + + \item All of the following apply (\textsc{le\_concat}): + \begin{itemize} + \item $\vle$ is a left-hand-side concatenation of the list of expressions $\vles$; + \item define $\ids$ as the union of applying $\uselexpr$ to each expression in $\vles$. + \end{itemize} + + \item All of the following apply (\textsc{le\_discard}): + \begin{itemize} + \item $\vle$ is a left-hand-side discard expression; + \item define $\ids$ as the empty set. + \end{itemize} + + \item All of the following apply (\textsc{le\_setarray}): + \begin{itemize} + \item $\vle$ is a left-hand-side array update of the array given by the expression $\veone$ and index expression $\vetwo$; + \item define $\ids$ as the union of applying $\uselexpr$ to $\veone$ and applying $\useexpr$ to $\vetwo$. + \end{itemize} + + \item All of the following apply (\textsc{le\_setfield}): + \begin{itemize} + \item $\vle$ is a left-hand-side field update of the record given by the expression $\veone$; + \item define $\ids$ as the application of $\uselexpr$ to $\veone$. + \end{itemize} + + \item All of the following apply (\textsc{le\_setfields}): + \begin{itemize} + \item $\vle$ is a left-hand-side multiple field updates of the record given by the expression $\veone$; + \item define $\ids$ as the application of $\uselexpr$ to $\veone$. + \end{itemize} + + \item All of the following apply (\textsc{le\_slice}): + \begin{itemize} + \item $\vle$ is a left-hand-side slicing of the expression $\veone$ by slices $\slices$; + \item define $\ids$ as the union of applying $\uselexpr$ to $\veone$ and applying $\useslice$ to each slice in $\slices$. + \end{itemize} +\end{itemize} + +\subsubsection{Formally} +\begin{mathpar} +\inferrule[le\_var]{}{ + \uselexpr(\overname{\LEVar(\vx)}{\vle}) \typearrow \overname{\vx}{\ids} +} +\and +\inferrule[le\_destructuring]{}{ + \uselexpr(\overname{\LEDestructuring(\vles)}{\vle}) \typearrow \overname{\bigcup_{\ve\in\vles}\uselexpr(\ve)}{\ids} +} +\and +\inferrule[le\_concat]{}{ + \uselexpr(\overname{\LEConcat(\vles)}{\vle}) \typearrow \overname{\bigcup_{\ve\in\vles}\uselexpr(\ve)}{\ids} +} +\and +\inferrule[le\_discard]{}{ + \uselexpr(\overname{\LEDiscard}{\vle}) \typearrow \overname{\emptyset}{\ids} +} +\end{mathpar} + +\begin{mathpar} +\inferrule[le\_setarray]{}{ + \uselexpr(\overname{\LESetArray(\veone, \vetwo)}{\vle}) \typearrow \overname{\uselexpr(\veone) \cup \useexpr(\vetwo)}{\ids} +} +\end{mathpar} + +\begin{mathpar} +\inferrule[le\_setfield]{}{ + \uselexpr(\overname{\LESetField(\veone, \Ignore)}{\vle}) \typearrow \overname{\uselexpr(\veone)}{\ids} +} +\end{mathpar} + +\begin{mathpar} +\inferrule[le\_setfields]{}{ + \uselexpr(\overname{\LESetFields(\veone, \Ignore)}{\vle}) \typearrow \overname{\uselexpr(\veone)}{\ids} +} +\end{mathpar} + +\begin{mathpar} +\inferrule[le\_slice]{}{ + \uselexpr(\overname{\LESlice(\veone, \slices)}{\vle}) \typearrow \overname{\uselexpr(\veone) \cup \bigcup_{\vs\in\slices}\useslice(\vs)}{\ids} +} +\end{mathpar} + +\subsubsection{TypingRule.UsePattern \label{sec:TypingRule.UsePattern}} +\hypertarget{def-usepattern}{} +The function +\[ +\usepattern(\overname{\pattern}{\vp}) \aslto \overname{\pow{\identifier}}{\ids} +\] +returns the set of identifiers $\ids$ which the declaration $\vd$ depends on. + +\subsubsection{Prose} +One of the following applies: +\begin{itemize} + \item All of the following apply (\textsc{mask\_all}): + \begin{itemize} + \item $\vp$ is either a mask pattern ($\PatternMask$) or a match-all pattern ($\PatternAll$); + \item define $\ids$ as the empty set. + \end{itemize} + + \item All of the following apply (\textsc{tuple}): + \begin{itemize} + \item $\vp$ is a tuple pattern list of patterns $\vli$; + \item define $\ids$ as the union of the application of $\usepattern$ for each pattern in $\vli$. + \end{itemize} + + \item All of the following apply (\textsc{any}): + \begin{itemize} + \item $\vp$ is a pattern for matching any of the patterns in the list of patterns $\vli$; + \item define $\ids$ as the union of the application of $\usepattern$ for each pattern in $\vli$. + \end{itemize} + + \item All of the following apply (\textsc{single}): + \begin{itemize} + \item $\vp$ is a pattern for matching the expression $\ve$; + \item define $\ids$ as the application of $\useexpr$ to $\ve$. + \end{itemize} + + \item All of the following apply (\textsc{geq}): + \begin{itemize} + \item $\vp$ is a pattern for testing greater-or-equal with respect to the expression $\ve$; + \item define $\ids$ as the application of $\useexpr$ to $\ve$. + \end{itemize} + + \item All of the following apply (\textsc{leq}): + \begin{itemize} + \item $\vp$ is a pattern for testing less-than-or-equal with respect to the expression $\ve$; + \item define $\ids$ as the application of $\useexpr$ to $\ve$. + \end{itemize} + + \item All of the following apply (\textsc{not}): + \begin{itemize} + \item $\vp$ is a pattern negating the pattern $\vpone$; + \item define $\ids$ as the application of $\usepattern$ to $\vpone$. + \end{itemize} + + \item All of the following apply (\textsc{range}): + \begin{itemize} + \item $\vp$ is a pattern for testing the range of expressions from $\veone$ to $\vetwo$; + \item define $\ids$ as the union of the application of $\useexpr$ to both $\veone$ and $\vetwo$. + \end{itemize} +\end{itemize} + +\subsubsection{Formally} +\begin{mathpar} +\inferrule[mask\_all]{ + \astlabel(\vp) \in \{\PatternMask, \PatternAll\} +}{ + \usepattern(\vp) \typearrow \overname{\emptyset}{\ids} +} +\end{mathpar} + +\begin{mathpar} +\inferrule[tuple]{}{ + \usepattern(\overname{\PatternTuple(\vli)}{\vp}) \typearrow \overname{\bigcup_{\vpone\in\vli}\usepattern(\vpone)}{\ids} +} +\end{mathpar} + +\begin{mathpar} +\inferrule[any]{}{ + \usepattern(\overname{\PatternAny(\vli)}{\vp}) \typearrow \overname{\bigcup_{\vpone\in\vli}\usepattern(\vpone)}{\ids} +} +\end{mathpar} + +\begin{mathpar} +\inferrule[single]{}{ + \usepattern(\overname{\PatternSingle(\ve)}{\vp}) \typearrow \overname{\useexpr(\ve)}{\ids} +} +\end{mathpar} + +\begin{mathpar} +\inferrule[geq]{}{ + \usepattern(\overname{\PatternGeq(\ve)}{\vp}) \typearrow \overname{\useexpr(\ve)}{\ids} +} +\end{mathpar} + +\begin{mathpar} +\inferrule[leq]{}{ + \usepattern(\overname{\PatternLeq(\ve)}{\vp}) \typearrow \overname{\useexpr(\ve)}{\ids} +} +\end{mathpar} + +\begin{mathpar} +\inferrule[not]{}{ + \usepattern(\overname{\PatternNot(\vpone)}{\vp}) \typearrow \overname{\usepattern(\vpone)}{\ids} +} +\end{mathpar} + +\begin{mathpar} +\inferrule[range]{}{ + \usepattern(\overname{\PatternRange(\veone, \vetwo)}{\vp}) \typearrow \overname{\useexpr(\veone) \cup \useexpr(\vetwo)}{\ids} +} +\end{mathpar} + +\subsubsection{TypingRule.UseSlice \label{sec:TypingRule.UseSlice}} +\hypertarget{def-useslice}{} +The function +\[ +\useslice(\overname{\slice}{\vs}) \aslto \overname{\pow{\identifier}}{\ids} +\] +returns the set of identifiers $\ids$ which the slice $\vs$ depends on. + +\subsubsection{Prose} +One of the following applies: +\begin{itemize} + \item All of the following apply (\textsc{single}): + \begin{itemize} + \item $\vs$ is the slice at the position given by the expression $\ve$; + \item define $\ids$ as the application of $\useexpr$ to $\ve$. + \end{itemize} + + \item All of the following apply (\textsc{start\_length\_rang}): + \begin{itemize} + \item $\vs$ is a slice given by the pair of expressions $\veone$ and $\vetwo$; + \item define $\ids$ as the union of applying $\useexpr$ to both $\veone$ and $\vetwo$. + \end{itemize} +\end{itemize} + +\subsubsection{Formally} +\begin{mathpar} +\inferrule[single]{}{ + \useslice(\overname{\SliceSingle(\ve)}{\vs}) \typearrow \overname{\useexpr(\ve)}{\ids} +} +\and +\inferrule[star\_length\_range]{ + L \in \{\SliceStar, \SliceLength, \SliceRange\} +}{ + \useslice(\overname{L(\veone, \vetwo)}{\vs}) \typearrow \overname{\useexpr(\veone) \cup \useexpr(\vetwo)}{\ids} +} +\end{mathpar} + +\subsubsection{TypingRule.UseBitfield \label{sec:TypingRule.UseBitfield}} +\hypertarget{def-usebitfield}{} +The function +\[ +\usebitfield(\overname{\decl}{\vbf}) \aslto \overname{\pow{\identifier}}{\ids} +\] +returns the set of identifiers $\ids$ which the bitfield $\vbf$ depends on. + +\subsubsection{Prose} +One of the following applies: +\begin{itemize} + \item All of the following apply (\textsc{simple}): + \begin{itemize} + \item $\vbf$ is the single field with slices $\slices$; + \item define $\ids$ as the union of applying $\useslice$ to each slice in $\slices$. + \end{itemize} + + \item All of the following apply (\textsc{nested}): + \begin{itemize} + \item $\vbf$ is the nested bitfield with slices $\slices$ and bitfields $\bitfields$; + \item define $\ids$ as the union of applying $\useslice$ to each slice in $\slices$ and applying + $\usebitfield$ to each bitfield in $\bitfields$. + \end{itemize} + + \item All of the following apply (\textsc{type}): + \begin{itemize} + \item $\vbf$ is the typed bitfield with slices $\slices$ and type $\tty$; + \item define $\ids$ as the union of applying $\useslice$ to each slice in $\slices$ and applying + $\usety$ to $\tty$. + \end{itemize} +\end{itemize} + +\subsubsection{Formally} +\begin{mathpar} +\inferrule[simple]{}{ + \usebitfield(\overname{\BitFieldSimple(\Ignore, \slices)}{\vbf}) \typearrow \overname{\bigcup_{\vs\in\slices}\useslice(\vs)}{\ids} +} +\and +\inferrule[nested]{ + \ids \eqdef \bigcup_{\bfone\in\bitfields}\usebitfield(\vs) \cup \bigcup_{\vs\in\slices}\useslice(\vs) +}{ + \usebitfield(\overname{\BitFieldNested(\Ignore, \slices, \bitfields)}{\vbf}) \typearrow \ids +} +\and +\inferrule[type]{ + \ids \eqdef \bigcup_{\vs\in\slices}\useslice(\vs) \cup \usety(\tty) +}{ + \usebitfield(\overname{\BitFieldType(\Ignore, \slices, \tty)}{\vbf}) \typearrow \ids +} +\end{mathpar} + +\subsubsection{TypingRule.UseConstraint \label{sec:TypingRule.UseConstraint}} +\hypertarget{def-useconstraint}{} +The function +\[ +\useconstraint(\overname{\intconstraint}{\vc}) \aslto \overname{\pow{\identifier}}{\ids} +\] +returns the set of identifiers $\ids$ which the integer constraint $\vc$ depends on. + +\subsubsection{Prose} +One of the following applies: +\begin{itemize} + \item All of the following apply (\textsc{exact}): + \begin{itemize} + \item $\vc$ is the single-value expression constraint with expression $\ve$; + \item define $\ids$ as the application of $\useexpr$ to $\ve$. + \end{itemize} + + \item All of the following apply (\textsc{range}): + \begin{itemize} + \item $\vc$ is the range constraint with expressions $\veone$ and $\vetwo$; + \item define $\ids$ as the union of applying $\useexpr$ to both $\veone$ and $\vetwo$. + \end{itemize} +\end{itemize} + +\subsubsection{Formally} +\begin{mathpar} +\inferrule[exact]{}{ + \useconstraint(\overname{\ConstraintExact(\ve)}{\vc}) \typearrow \overname{\useexpr(\ve)}{\ids} +} +\and +\inferrule[range]{}{ + \useconstraint(\overname{\ConstraintRange(\veone, \vetwo)}{\vc}) \typearrow \overname{\useexpr(\veone) \cup \useexpr(\vetwo)}{\ids} +} +\end{mathpar} + +\subsubsection{TypingRule.UseStmt \label{sec:TypingRule.UseStmt}} +\hypertarget{def-usestmt}{} +The function +\[ +\usestmt(\overname{\stmt}{\vs}) \aslto \overname{\pow{\identifier}}{\ids} +\] +returns the set of identifiers $\ids$ which the statement $\vs$ depends on. + +\subsubsection{Prose} +One of the following applies: +\begin{itemize} + \item All of the following apply (\textsc{pass\_return\_none\_throw\_none}): + \begin{itemize} + \item $\vs$ is either a pass statement $\SPass$, a return-nothing statement $\SReturn(\None)$, + or a throw-nothing statement ($\SThrow(\None)$); + \item define $\ids$ as the empty set. + \end{itemize} + + \item All of the following apply (\textsc{s\_seq}): + \begin{itemize} + \item $\vs$ is a sequencing statement for $\vsone$ and $\vstwo$; + \item define $\ids$ as the union of applying $\usestmt$ to both $\vsone$ and $\vstwo$. + \end{itemize} + + \item All of the following apply (\textsc{assert\_return\_some}): + \begin{itemize} + \item $\vs$ is either an assertion with expression $\ve$ or a return statement with expression $\ve$; + \item define $\ids$ as the application of $\useexpr$ to $\ve$. + \end{itemize} + + \item All of the following apply (\textsc{s\_assign}): + \begin{itemize} + \item $\vs$ is an assignment statement with left-hand-side $\vle$ and right-hand-side $\ve$; + \item define $\ids$ as the union of applying $\uselexpr$ to $\vle$ and $\useexpr$ to $\ve$. + \end{itemize} + + \item All of the following apply (\textsc{s\_call}): + \begin{itemize} + \item $\vs$ is a call statement for the subprogram with name $\vx$, arguments $\vargs$, and list of + pairs consisting of a parameter identifier and associated expression $\namedargs$; + \item define $\ids$ as the union of the singleton set for $\vx$, applying $\useexpr$ to + every expression in $\vargs$ and applying $\useexpr$ to every expression associated with + a parameter in $\namedargs$. + \end{itemize} + + \item All of the following apply (\textsc{s\_cond}): + \begin{itemize} + \item $\vs$ is the conditional statement with expression $\ve$ and statements $\vsone$ and $\vstwo$; + \item define $\ids$ as the union of applying $\useexpr$ to $\ve$ and $\usestmt$ to both of $\vsone$ and $\vstwo$. + \end{itemize} + + \item All of the following apply (\textsc{s\_case}): + \begin{itemize} + \item $\vs$ is the case statement with expression $\ve$ and case list $\vcases$; + \item define $\ids$ as the union of applying $\useexpr$ to $\ve$ and $\usecase$ to every case in $\vcases$. + \end{itemize} + + \item All of the following apply (\textsc{s\_for}): + \begin{itemize} + \item $\vs$ is the for statement $\SFor\left\{\begin{array}{rcl} + \Forindexname &:& \Ignore\\ + \Forstarte &:& \vstarte\\ + \fordirection &:& \vdirection\\ + \Forende &:& \vende\\ + \Forbody &:& \vbody\\ + \Forlimit &:& \vlimit + \end{array}\right\}$; + \item define $\ids$ as the union of applying $\useexpr$ to $\vlimit$, $\vstarte$, and $\vende$ and applying $\usestmt$ to $\vsone$. + \end{itemize} + + \item All of the following apply (\textsc{while\_repeat}): + \begin{itemize} + \item $\vs$ is either a while statement or repeat statement, each with expression $\ve$, body statement $\vsone$, + and optional limit expression $\vlimit$; + \item define $\ids$ as the union of applying $\useexpr$ to $\vlimit$ and to $\ve$, and applying $\usestmt$ to $\vsone$. + \end{itemize} + + \item All of the following apply (\textsc{s\_decl}): + \begin{itemize} + \item $\vs$ is a declaration statement with local declaration item $\ldi$ and \optional\ initialization expression $\ve$; + \item define $\ids$ as the union of applying $\useexpr$ to $\ve$ and $\useldi$ to $\ldi$. + \end{itemize} + + \item All of the following apply (\textsc{s\_try}): + \begin{itemize} + \item $\vs$ is a try statement with statement $\vsone$, catcher list $\catchers$, and otherwise statement $\vstwo$; + \item define $\ids$ as the union of applying $\usestmt$ to both $\vsone$ and $\vstwo$ and $\usecatcher$ to + every catcher in $\catchers$. + \end{itemize} + + \item All of the following apply (\textsc{s\_print}): + \begin{itemize} + \item $\vs$ is a print statement with list of expressions $\vargs$; + \item define $\ids$ as the union of applying $\useexpr$ to each expression in $\vargs$. + \end{itemize} +\end{itemize} + +\subsubsection{Formally} +\begin{mathpar} +\inferrule[pass\_return\_none\_throw\_none]{ + \vs = \SPass \lor \vs = \SReturn(\None) \lor \vs = \SThrow(\None) +}{ + \usestmt(\vs) \typearrow \overname{\emptyset}{\ids} +} +\end{mathpar} + +\begin{mathpar} +\inferrule[s\_seq]{}{ + \usestmt(\overname{\SSeq(\vsone, \vstwo)}{\vs}) \typearrow \overname{\usestmt(\vsone)\cup\usestmt(\vstwo)}{\ids} +} +\and +\inferrule[assert\_return\_some]{ + \vs = \SAssert(\ve) \lor \SReturn(\langle\ve\rangle) +}{ + \usestmt(\vs) \typearrow \overname{\useexpr(\ve)}{\ids} +} +\end{mathpar} + +\begin{mathpar} + +\inferrule[s\_assign]{}{ + \usestmt(\overname{\SAssign(\vle, \ve)}{\vs}) \typearrow \overname{\uselexpr(\vle) \cup \useexpr(\ve)}{\ids} +} +\end{mathpar} + +\begin{mathpar} +\inferrule[s\_call]{ + \ids \eqdef \{\vx\} \cup \bigcup_{\ve\in\vargs}\useexpr(\ve) \cup \bigcup_{(\Ignore, \ve)\in\namedargs} \useexpr(\ve) +}{ + \usestmt(\overname{\SCall(\vx, \vargs, \namedargs)}{\vs}) \typearrow \ids +} +\end{mathpar} + +\begin{mathpar} +\inferrule[s\_cond]{}{ + \usestmt(\overname{\SCond(\ve, \vsone, \vstwo)}{\vs}) \typearrow \overname{\useexpr(\ve) \cup \usestmt(\vsone) \cup \usestmt(\vstwo)}{\ids} +} +\end{mathpar} + +\begin{mathpar} +\inferrule[s\_case]{}{ + \usestmt(\overname{\SCase(\ve, \vcases)}{\vs}) \typearrow \overname{\useexpr(\ve) \cup \bigcup_{\vc\in\vcases}\usecase(\vc)}{\ids} +} +\end{mathpar} + +\begin{mathpar} +\inferrule[s\_for]{ + \ids \eqdef \useexpr(\vlimit) \cup \useexpr(\vstarte) \cup \useexpr(\vende) \cup \usestmt(\vbody) +}{ + { + \usestmt\left(\overname{\SFor\left\{\begin{array}{rcl} + \Forindexname &:& \Ignore\\ + \Forstarte &:& \vstarte\\ + \fordirection &:& \vdirection\\ + \Forende &:& \vende\\ + \Forbody &:& \vbody\\ + \Forlimit &:& \vlimit + \end{array}\right\}}{\vs}\right) \typearrow \ids + } +} +\and +\inferrule[while\_repeat]{ + \vs = \SWhile(\ve, \vlimit, \vs) \lor \vs = \SRepeat(\vs, \ve, \vlimit) +}{ + \usestmt(\vs) \typearrow \overname{\useexpr(\vlimit) \cup \useexpr(\ve) \cup \usestmt(\vsone)}{\ids} +} +\end{mathpar} + +\begin{mathpar} +\inferrule[s\_decl]{}{ + \usestmt(\overname{\SDecl(\Ignore, \ldi, \ve)}\vs) \typearrow \overname{\useexpr(\ve) \cup \useldi(\ldi)}{\ids} +} +\end{mathpar} + +\begin{mathpar} +\inferrule[s\_throw\_some]{}{ + \usestmt(\overname{\SThrow(\langle\ve\rangle)}\vs) \typearrow \overname{\useexpr(\ve)}{\ids} +} +\end{mathpar} + +\begin{mathpar} +\inferrule[s\_try]{ + \ids \eqdef \usestmt(\vsone) \cup \bigcup_{\vc\in\catchers}\usecatcher(\vc) \cup \usestmt(\vstwo) +}{ + \usestmt(\overname{\STry(\vsone, \catchers, \vstwo)}{\vs}) \typearrow \ids +} +\end{mathpar} + +\begin{mathpar} +\inferrule[s\_print]{}{ + \usestmt(\overname{\SPrint(\vargs)}{\vs}) \typearrow \overname{\bigcup_{\ve\in\vargs}\useexpr(\ve)}{\ids} +} +\end{mathpar} + +\subsubsection{TypingRule.UseLDI \label{sec:TypingRule.UseLDI}} +\hypertarget{def-useldi}{} +The function +\[ +\useldi(\overname{\localdeclitem}{\ldi}) \aslto \overname{\pow{\identifier}}{\ids} +\] +returns the set of identifiers $\ids$ which the local declaration item $\ldi$ depends on. + +\subsubsection{Prose} +One of the following applies: +\begin{itemize} + \item All of the following apply (\textsc{discard}): + \begin{itemize} + \item $\ldi$ is a discarding declaration; + \item define $\ids$ as the empty set. + \end{itemize} + + \item All of the following apply (\textsc{typed}): + \begin{itemize} + \item $\ldi$ is a typed declaration for the local declaration item $\ldione$ and type $\vt$; + \item define $\ids$ as the union of applying $\useldi$ to $\ldione$ and $\usety$ to $\vt$. + \end{itemize} + + \item All of the following apply (\textsc{tuple}): + \begin{itemize} + \item $\ldi$ is a multi-variable declaration for the list of local declarations $\ldis$; + \item define $\ids$ as the union of applying $\useldi$ to each local declaration item in $\ldis$. + \end{itemize} +\end{itemize} + +\subsubsection{Formally} +\begin{mathpar} +\inferrule[discard]{}{ + \useldi(\overname{\LDIDiscard}{\ldi}) \typearrow \overname{\emptyset}{\ids} +} +\end{mathpar} + +\begin{mathpar} +\inferrule[typed]{}{ + \useldi(\overname{\LDITyped(\ldione, \vt)}{\ldi}) \typearrow \overname{\useldi(\ldione) \cup \usety(\vt)}{\ids} +} +\end{mathpar} + +\begin{mathpar} +\inferrule[tuple]{}{ + \useldi(\overname{\LDITuple(\ldis)}{\ldi}) \typearrow \overname{\bigcup_{\ldione\in\ldis}\useldi(\ldione)}{\ids} +} +\end{mathpar} + +\subsubsection{TypingRule.UseCase \label{sec:TypingRule.UseCase}} +\hypertarget{def-usecase}{} +The function +\[ +\usecase(\overname{\casealt}{\vc}) \aslto \overname{\pow{\identifier}}{\ids} +\] +returns the set of identifiers $\ids$ which the case alternative $\vc$ depends on. + +\subsubsection{Prose} +All of the following apply: +\begin{itemize} + \item $\vc$ is the case alternative for the pattern $\pattern$, \optional\ \texttt{where} expression + $\veopt$ and \texttt{otherwise} statement $\vs$; + \item define $\ids$ as the union of applying $\usepattern$ to $\pattern$, applying $\useexpr$ to $\veopt$, + and applying $\usestmt$ to $\vs$. +\end{itemize} + +\subsubsection{Formally} +\begin{mathpar} +\inferrule{ + \ids \eqdef \usepattern(\pattern) \cup \useexpr(\veopt) \cup \usestmt(\vs) +}{ + \usecase(\overname{\{ \CasePattern : \pattern, \CaseWhere : \veopt, \CaseStmt : \vs \}}{\vc}) \typearrow \ids +} +\end{mathpar} + +\subsubsection{TypingRule.UseCatcher \label{sec:TypingRule.UseCatcher}} +\hypertarget{def-usecatcher}{} +The function +\[ +\usecatcher(\overname{\catcher}{\vc}) \aslto \overname{\pow{\identifier}}{\ids} +\] +returns the set of identifiers $\ids$ which the try statement catcher $\vc$ depends on. + +\subsubsection{Prose} +All of the following apply: +\begin{itemize} + \item $\vc$ is a case alternative with type $\tty$ and statement $\vs$; + \item define $\ids$ as the union of applying $\usety$ to $\ty$ and applying $\usestmt$ to $\vs$. +\end{itemize} + +\subsubsection{Formally} +\begin{mathpar} +\inferrule{}{ + \usecatcher(\overname{(\Ignore, \tty, \vs)}{\vc}) \typearrow \overname{\usety(\tty) \cup \usestmt(\vs)}{\ids} +} +\end{mathpar} + +\section{Semantics} +The rule SemanticsRule.TopLevel (see \secref{SemanticsRule.TopLevel}) +evaluates entire specifications with the help of the following rules: +\begin{itemize} + \item SemanticsRule.EvalGlobals (see \secref{SemanticsRule.EvalGlobals}); + \item SemanticsRule.BuildGlobalEnv (see \secref{SemanticsRule.BuildGlobalEnv}). +\end{itemize} + +\subsubsection{SemanticsRule.TopLevel \label{sec:SemanticsRule.TopLevel}} +The relation +\hypertarget{def-evalspec}{} +\[ + \evalspec(\overname{\spec}{\parsedast}, \overname{\spec}{\parsedstd}) \;\aslrel\; + ((\overname{\vals}{\vv}\times \overname{\XGraphs}{\vg}) \cup \overname{\TError}{\ErrorConfig}) +\] +evaluates the \texttt{main} function in a given specification and standard library. + +The function $\typecheckast$ (see \secref{TypingRule.TypeCheckAST}) +takes an initial typing environment and a untyped AST and returns a corresponding typed AST and typing +environment. + +\subsubsection{Prose} + All of the following apply: + \begin{itemize} + \item the AST for the parsed specification, $\parsedspec$, and AST for the parsed standard library, + $\parsedstd$, are concatenated to give $\parsedast$; + \item applying the type-checker to $\parsedast$ with an empty static environment yields + $(\typedspec, \tenv)$; + \item populating the environment with the declarations of the global storage elements + is $(\env, \vgone)$\ProseOrError; + \item One of the following applies: + \begin{itemize} + \item All of the following apply (\textsc{normal}): + \begin{itemize} + \item evaluating the subprogram \texttt{main} with an empty list of actual arguments and empty list of parameters + in $\env$ is $\Normal([(\vv, \vgtwo)], \Ignore)$\ProseOrError; + \item $\newg$ is the ordered composition of $\vgone$ and $\vgtwo$ with the $\aslpo$ edge; + \item the result of the entire evaluation is $(\vv, \newg)$. + \end{itemize} + + \item All of the following apply (\textsc{throwing}): + \begin{itemize} + \item evaluating the subprogram \texttt{main} with an empty list of actual arguments and empty list of parameters + in $\env$ is $\Throwing(\texttt{v\_opt}, \Ignore)$, which is an uncaught exception; + \item the result of the entire evaluation is an error indicating that an exception was not caught. + \end{itemize} + \end{itemize} + \end{itemize} + + \subsubsection{Example} + + \CodeSubsection{\EvalTopLevelBegin}{\EvalTopLevelEnd}{../Interpreter.ml} + +\subsubsection{Formally} +\begin{mathpar} +\inferrule[normal]{ + \parsedast \eqdef \parsedspec \concat \parsedstd\\ + \typecheckast(\emptytenv, \parsedast) \typearrow (\typedspec,\tenv)\\ + \buildgenv(\typedspec, (\tenv, (\emptyfunc, \emptyfunc))) \evalarrow (\env, \vgone) \OrDynError\\\\ + \evalsubprogram{\env, \texttt{"main"}, \emptylist, \emptylist} \evalarrow \Normal([(\vv, \vgtwo)], \Ignore) \OrDynError\\\\ + \newg \eqdef \ordered{\vgone}{\aslpo}{\vgtwo} +} +{ + \evalspec(\parsedast, \parsedstd) \evalarrow (\vv, \newg) +} +\end{mathpar} + +\begin{mathpar} +\inferrule[throwing]{ + \parsedast \eqdef \parsedspec \concat \parsedstd\\ + \typecheckast(\emptytenv, \parsedast) \typearrow (\typedspec,\tenv)\\ + \buildgenv(\typedspec, (\tenv, (\emptyfunc, \emptyfunc))) \evalarrow (\env, \vgone)\\ + \evalsubprogram{\env, \texttt{"main"}, \emptylist, \emptylist} \evalarrow \Throwing(\texttt{v\_opt}, \Ignore) +} +{ + \evalspec(\parsedspec, \parsedstd) \evalarrow \ErrorVal{UncaughtException} +} +\end{mathpar} +Notice that when the type-checker fails due to a type error in the given specification, +the corresponding premise in the rule above does not hold, and the semantics +is undefined. Indeed, the ASL semantics is only defined for well-typed specifications. + + +\subsubsection{SemanticsRule.BuildGlobalEnv \label{sec:SemanticsRule.BuildGlobalEnv}} +The helper relation +\hypertarget{def-buildgenv}{} +\[ + \buildgenv(\overname{\envs}{\env}, \overname{\spec}{\typedspec}) \;\aslrel\; + (\overname{\envs}{\newenv}\times\overname{\XGraphs}{\newg}) \cup \overname{\TError}{\ErrorConfig} +\] +populates the environment and output execution graph with the global +storage declarations. +This works by traversing the global storage declarations in \emph{dependency order} +and updating the environment accordingly. By dependency order, we mean that if +a declaration $b$ refers to an identifier declared in $a$ then $a$ is evaluated +before $b$. + +\subsubsection{Prose} +All of the following apply: +\begin{itemize} + \item sorting the declarations of the global storage elements in topological order with respect to the dependency order + gives $\vdecls$; + \item evaluating the global storage declarations in $\vdecls$ in $\env$ with the empty execution graph + is $(\newenv, \newg)$\ProseOrError. + \item the result of the entire evaluation is $(\newenv, \newg)$. +\end{itemize} +\subsubsection{Example} + +\CodeSubsection{\EvalBuildGlobalEnvBegin}{\EvalBuildGlobalEnvEnd}{../Interpreter.ml} + +\subsubsection{Formally} +\hypertarget{def-topologicaldecls}{} +The helper relation $\topologicaldecls(\overname{\decl^*}{\parsedspec}, \overname{\decl^*}{\parsedstd})$ +accepts a specification and returns the subset of global storage declarations ordered by +dependency order. + +\begin{mathpar} +\inferrule{ + \topologicaldecls(\typedspec) \evalarrow \vdecls\\ + \evalglobals(\vdecls, (\env, \emptygraph)) \evalarrow (\newenv, \newg) \OrDynError +}{ + \buildgenv(\env, \typedspec) \evalarrow (\newenv, \newg) +} +\end{mathpar} \ No newline at end of file diff --git a/asllib/doc/Statements.tex b/asllib/doc/Statements.tex new file mode 100644 index 000000000..c26814ba0 --- /dev/null +++ b/asllib/doc/Statements.tex @@ -0,0 +1,2648 @@ +\chapter{Statements\label{chap:Statements}} +Statements update storage elements and determine the flow of control of a subprogram. + +Statements are grammatically derived from $\Nstmt$ and represented as ASTs by $\stmt$. + +\hypertarget{build-stmt}{} +The function +\[ +\buildstmt(\overname{\parsenode{\Nstmt}}{\vparsednode}) \;\aslto\; \overname{\stmt}{\vastnode} +\] +transforms a statement parse node $\vparsednode$ into a statement AST node $\vastnode$. + +\hypertarget{def-annotatestmt}{} +The function +\[ + \annotatestmt(\overname{\staticenvs}{\tenv} \aslsep \overname{\stmt}{\vs}) \aslto + (\overname{\stmt}{\news}\aslsep \overname{\staticenvs}{\newtenv}) + \cup \overname{\TTypeError}{\TypeErrorConfig} +\] +annotates a statement $\vs$ in an environment $\tenv$, resulting in $\news$ --- +the \typedast\ for $\vs$, which is also known as the \emph{annotated statement} --- +and a modified environment $\newtenv$. \ProseOtherwiseTypeError + +The relation +\hypertarget{def-evalstmt}{} +\[ + \evalstmt{\overname{\envs}{\env} \aslsep \overname{\stmt}{\vs}} \;\aslrel\; + \left( + \begin{array}{cl} + \overname{\TReturning}{\Returning((\vvs,\newg), \newenv)} & \cup\\ + \overname{\TContinuing}{\Continuing(\newg,\newenv)} & \cup\\ + \overname{\TThrowing}{\ThrowingConfig} & \cup \\ + \overname{\TError}{\ErrorConfig} & + \end{array} + \right) +\] +evaluates a statement $\vs$ in an environment $\env$, resulting in one of four types of configurations +(see more details in \secref{KindsOfSemanticConfigurations}): +\begin{itemize} + \item returning configurations with values $\vvs$, execution graph $\newg$, and a modified environment $\newenv$; + \item continuing configurations with an execution graph $\newg$ and modified environment $\newenv$; + \item throwing configurations; + \item error configurations. +\end{itemize} + +We now define the syntax, abstract syntax, typing, and semantics for the following kinds of statements: +\begin{itemize} +\item Pass statements (see \secref{PassStatements}) +\item Assignment statements (see \secref{AssignmentStatements}) +\item Declaration statements (see \secref{DeclarationStatements}) +\item Sequencing statements (see \secref{SeuqncingStatements}) +\item Call statements (see \secref{CallStatements}) +\item Conditional statements (see \secref{ConditionalStatements}) +\item Case statements (see \secref{CaseStatements}) +\item Assertion statements (see \secref{AssertionStatements}) +\item While statements (see \secref{WhileStatements}) +\item Repeat statements (see \secref{RepeatStatements}) +\item For statements (see \secref{ForStatements}) +\item Throw statements (see \secref{ThrowStatements}) +\item Try statements (see \secref{TryStatements}) +\item Return statements (see \secref{ReturnStatements}) +\item Print statements (see \secref{PrintStatements}) +\item Pragma statements (see \secref{PragmaStatements}) +\end{itemize} + +\section{Pass Statements\label{sec:PassStatements}} +\subsection{Syntax} +\begin{flalign*} +\Nstmt \derivesinline\ & \Tpass \parsesep \Tsemicolon & +\end{flalign*} + +\subsection{Abstract Syntax} +\begin{flalign*} +\stmt \derives\ & \SPass & +\end{flalign*} + +\subsubsection{ASTRule.SPass} +\begin{mathpar} +\inferrule{}{ + \buildstmt(\overname{\Nstmt(\Tpass, \Tsemicolon)}{\vparsednode}) + \astarrow + \overname{\SPass}{\vastnode} +} +\end{mathpar} + +\subsection{Typing} +\subsubsection{TypingRule.SPass \label{sec:TypingRule.SPass}} +\subsubsection{Prose} +All of the following apply: +\begin{itemize} + \item $\vs$ is a pass statement, that is, $\SPass$; + \item $\news$ is $\vs$; + \item $\newtenv$ is $\tenv$. +\end{itemize} +\subsubsection{Formally} +\begin{mathpar} +\inferrule{}{\annotatestmt(\tenv, \SPass) \typearrow (\SPass,\tenv)} +\end{mathpar} +\CodeSubsection{\SPassBegin}{\SPassEnd}{../Typing.ml} + +\subsection{Semantics} +\subsubsection{SemanticsRule.SPass \label{sec:SemanticsRule.SPass}} +\subsubsection{Example} +In the specification: +\VerbatimInput{../tests/ASLSemanticsReference.t/SemanticsRule.SPass.asl} +\texttt{pass;} does nothing. + +\subsubsection{Prose} +All of the following apply: +\begin{itemize} +\item $\vs$ is a \texttt{pass} statement, $\SPass$; +\item $\newg$ is the empty graph; +\item $\newenv$ is $\env$. +\end{itemize} + +\subsubsection{Formally} +\begin{mathpar} +\inferrule{}{ + \evalstmt{\env, \SPass} \evalarrow \Continuing(\overname{\emptygraph}{\newg}, \overname{\env}{\newenv}) +} +\end{mathpar} +\CodeSubsection{\EvalSPassBegin}{\EvalSPassEnd}{../Interpreter.ml} + +\section{Assignment Statements\label{sec:AssignmentStatements}} +\subsection{Syntax} +\begin{flalign*} +\Nstmt \derivesinline\ & \Nlexpr \parsesep \Teq \parsesep \Nexpr \parsesep \Tsemicolon & +\end{flalign*} + +\subsection{Abstract Syntax} +\begin{flalign*} +\stmt \derives\ & \SAssign(\lexpr, \expr) & +\end{flalign*} + +\subsubsection{ASTRule.SAssign} +\begin{mathpar} +\inferrule{}{ + \buildstmt(\overname{\Nstmt(\punnode{\Nlexpr}, \Teq, \punnode{\Nexpr}, \Tsemicolon)}{\vparsednode}) + \astarrow + \overname{\SAssign(\astof{\vlexpr}, \astof{\vexpr})}{\vastnode} +} +\end{mathpar} + +\subsection{Typing} +\subsubsection{TypingRule.SAssign \label{sec:TypingRule.SAssign}} +\subsubsection{Prose} +All of the following apply: +\begin{itemize} + \item $\vs$ is an assignment \texttt{le = re}, that is, $\SAssign(\vle, \vre)$; + \item One of the following applies: + \begin{itemize} + \item All of the following apply (\textsc{setter}): + \begin{itemize} + \item reducing $(\tenv, \vle, \vre)$ to a setter call via \\ $\inlinesetter$ yields the statement $\news$ + (indicating that the assignment corresponds to setter)\ProseOrTypeError; + \item $\newtenv$ is $\tenv$. + \end{itemize} + + \item All of the following apply (\textsc{non\_setter}): + \begin{itemize} + \item reducing $(\tenv, \vle, \vre)$ to a setter call via \\ $\inlinesetter$ yields $\None$ + (indicating the assignment does not correspond to a setter); + \item annotating the right-hand-side expression $\vre$ in $\tenv$ yields $(\vtre, \vreone)$\ProseOrTypeError; + \item annotating the \assignableexpression\ $\vle$ with the type $\vtre$ in $\tenv$ yields $\vleone$\ProseOrTypeError; + \item $\news$ is the assignment \texttt{le1 = re1}, that is, $\SAssign(\vleone, \vreone)$; + \item $\newtenv$ is $\tenv$. + \end{itemize} + + \end{itemize} +\end{itemize} +\subsubsection{Formally} +\begin{mathpar} +\inferrule[setter]{ + \inlinesetter(\tenv, \vle, \vre) \typearrow \langle \news \rangle \OrTypeError\\ +}{ + \annotatestmt(\tenv, \overname{\SAssign(\vle, \vre)}{\vs}) \typearrow (\news,\overname{\tenv}{\newtenv}) +} +\end{mathpar} +\begin{mathpar} +\inferrule[non\_setter]{ + \inlinesetter(\tenv, \vle, \vre) \typearrow \None \OrTypeError\\\\ + \annotateexpr{\tenv, \vre} \typearrow (\vtre, \vreone) \OrTypeError\\\\ + \annotatelexpr{\tenv, \vle, \vtre} \typearrow \vleone \OrTypeError +}{ + \annotatestmt(\tenv, \overname{\SAssign(\vle, \vre)}{\vs}) \typearrow (\overname{\SAssign(\vleone, \vreone)}{\news},\overname{\tenv}{\newtenv}) +} +\end{mathpar} +\CodeSubsection{\SAssignBegin}{\SAssignEnd}{../Typing.ml} + +\subsection{Semantics} +\subsubsection{SemanticsRule.SAssign \label{sec:SemanticsRule.SAssign}} +\subsubsection{Example} +In the specification: +\VerbatimInput{../tests/ASLSemanticsReference.t/SemanticsRule.SAssign.asl} +\texttt{x = 3;} binds \texttt{x} to $\nvint(3)$ in the environment where \texttt{x} is bound to +$\nvint(42)$, and $\newenv$ is such that \texttt{x} is bound to $\nvint(3)$. + +\subsubsection{Prose} +All of the following apply: +\begin{itemize} + \item $\vs$ is an assignment statement, $\SAssign(\vle, \vre)$; + \item $\vre$ is not a call expression; + \item evaluating the expression $\vre$ in $\env$ yields + $\Normal(\vm, \envone)$ (here, $\vm$ is a pair consisting of a value and an execution graph)\ProseOrAbnormal; + \item evaluating the \assignableexpression\ $\vle$ with $\vm$ in $\envone$, + as per \chapref{AssignableExpressions}, yields $\Normal(\newg, \newenv)$\ProseOrAbnormal. +\end{itemize} + +\subsubsection{Formally} +\begin{mathpar} +\inferrule{ + \astlabel(\vre) \neq \ECall\\ + \evalexpr{\env, \vre} \evalarrow \Normal(\vm, \envone) \OrAbnormal\\ + \evallexpr{\envone, \vle, \vm} \evalarrow \Normal(\newg, \newenv) \OrAbnormal +}{ + \evalstmt{\env, \SAssign(\vle, \vre)} \evalarrow \Continuing(\newg, \newenv) +} +\end{mathpar} +\CodeSubsection{\EvalSAssignBegin}{\EvalSAssignEnd}{../Interpreter.ml} + +\subsubsection{Comments} +This rule covers all assignment statements, except the ones where the +right-hand side expression is a function call, which is covered by +\nameref{sec:SemanticsRule.SAssignCall}. Although +the sequential semantics of both statements is the same, +SemanticsRule.SAssignCall generates a different execution graph. + +Notice that this rule first produces a value for the right-hand side expression +and then completes the update via an appropriate rule for evaluating the +\assignableexpression, which in turn handles variables, tuples, bitvectors, +etc. + +\subsubsection{SemanticsRule.SAssignCall \label{sec:SemanticsRule.SAssignCall}} +\subsubsection{Example} +\VerbatimInput{\semanticstests/SemanticsRule.SAssignCall.asl} +given that the function call \texttt{f(1)} returns a pair of values --- $\nvint(1)$ and $\nvint(2)$ +(each with its own associated execution graph), +the statement \texttt{(a,b) = f(1)} assigns the value $\nvint(1)$ to the mutable variable \texttt{a} +and the value $\nvint(2)$ to the mutable variable~\texttt{b}. + +\subsubsection{Prose} +All of the following apply: +\begin{itemize} + \item $\vs$ assigns a \assignableexpression\ list from a subprogram call, \\ + $\SAssign(\LEDestructuring(\les),\ECall(\name, \args, \namedargs))$; + \item $\les$ is a list of \assignableexpressions, each of which is either \\ a variable ($\LEVar(\Ignore)$) + or a discarded variable (\LEDiscard); + \item evaluating the subprogram call as per \chapref{SubprogramCalls} is + $\Normal(\vms, \envone)$\ProseOrAbnormal; + \item assigning each value in $\vms$ to the respective element of the tuple $\les$ is \\ + $\Normal(\vgtwo, \newg)$\ProseOrAbnormal. +\end{itemize} + +\subsubsection{Formally} +\hypertarget{def-lexprisvar}{} +We first define the syntactic predicate +\[ + \lexprisvar(\lexpr) \aslto \True +\] +which holds when a left-hand side expression +represents a variable: +\begin{mathpar} + \inferrule{}{ \lexprisvar(\LEVar(\Ignore)) \evalarrow \True} + \and + \inferrule{}{ \lexprisvar(\LEDiscard) \evalarrow \False} +\end{mathpar} + +We now define the evaluation of assigning from a subprogram call: +\begin{mathpar} +\inferrule{ + \vles \eqdef \vle_{1..k}\\ + i=1..k: \lexprisvar(\vle_i) \evalarrow \True\\ + \evalcall{\env, \name, \args, \namedargs} \evalarrow \Normal(\vms, \envone) \OrAbnormal\\\\ + \evalmultiassignment(\envone, \vles, \vms) \evalarrow \Normal(\newg, \newenv) \OrAbnormal +}{ + \evalstmt{\env, \SAssign(\LEDestructuring(\les),\ECall(\name, \args, \namedargs))} \\ + \evalarrow \Continuing(\newg, \newenv) +} +\end{mathpar} +\CodeSubsection{\EvalSAssignCallBegin}{\EvalSAssignCallEnd}{../Interpreter.ml} + +\section{Declaration Statements\label{sec:DeclarationStatements}} +\subsection{Syntax} +\begin{flalign*} +\Nstmt \derivesinline\ & \Nlocaldeclkeyword \parsesep \Ndeclitem \parsesep \Teq \parsesep \Nexpr \parsesep \Tsemicolon &\\ +|\ & \Tvar \parsesep \Ndeclitem \parsesep \option{\Teq \parsesep \Nexpr} \parsesep \Tsemicolon &\\ +|\ & \Tvar \parsesep \Clisttwo{\Tidentifier} \parsesep \Tcolon \parsesep \Nty \parsesep \Tsemicolon &\\ +\end{flalign*} + +\subsection{Abstract Syntax} +\begin{flalign*} +\stmt \derives\ & \SDecl(\localdeclkeyword, \localdeclitem, \expr?) & +\end{flalign*} + +\subsubsection{ASTRule.SDecl} +\begin{mathpar} +\inferrule[let\_constant]{}{ + { + \begin{array}{r} + \buildstmt(\overname{\Nstmt(\Nlocaldeclkeyword, \Ndeclitem, \Teq, \punnode{\Nexpr}, \Tsemicolon)}{\vparsednode}) + \astarrow\\ + \overname{\SDecl(\astof{\vlocaldeclkeyword}, \astof{\vdeclitem}, \langle\astof{\vexpr}\rangle)}{\vastnode} + \end{array} + } +} +\end{mathpar} + +\begin{mathpar} +\inferrule[var]{ + \buildoption[\buildexpr](\ve) \astarrow \astversion{\ve} +}{ + { + \begin{array}{r} + \buildstmt(\overname{\Nstmt(\Tvar, \Ndeclitem, \namednode{\ve}{\option{\Teq, \Nexpr}}, \Tsemicolon)}{\vparsednode}) + \astarrow \\ + \overname{\SDecl(\LDKVar, \astof{\vdeclitem}, \astversion{\ve})}{\vastnode} +\end{array} +} +} +\end{mathpar} + +\begin{mathpar} +\inferrule[multi\_var]{ + \buildclist[\buildidentity](\vids) \astarrow \astversion{\vids}\\ + \vstmts \eqdef [\vx\in\astversion{\vids}: \SDecl(\LDKVar, \vx, \astof{\tty})]\\ + \stmtfromlist(\vstmts) \astarrow \vastnode +}{ + \buildstmt(\overname{\Nstmt(\Tvar, \namednode{\vids}{\Clisttwo{\Tidentifier}}, \Tcolon, \punnode{\Nty}, \Tsemicolon)}{\vparsednode}) + \astarrow + \vastnode +} +\end{mathpar} + +\subsection{Typing} +\subsubsection{TypingRule.SDecl\label{sec:TypingRule.SDecl}} +\subsubsection{Prose} +One of the following applies: +\begin{itemize} + \item All of the following apply (\textsc{some}): + \begin{itemize} + \item $\vs$ is a declaration with local declaration keyword $\ldk$, local identifiers $\ldi$, and an expression $\ve$, + that is, $\SDecl(\ldk, \ldi, \langle\ve\rangle)$; + \item annotating the right-hand-side expression $\ve$ in $\tenv$ yields $(\vte,\vep)$\ProseOrTypeError; + \item annotating the local declaration item $\ldi$ with local declaration keyword $\ldk$ and type $\vte$ in $\tenv$ + yields $(\tenvone, \ldip)$; + \item One of the following applies: + \begin{itemize} + \item All of the following apply (\textsc{constant}): + \begin{itemize} + \item $\ldk$ indicates a local constant declaration, that is, $\LDKConstant$; + \item symbolically simplifying $\ve$ in $\tenvone$ yields the literal $\vv$\ProseOrTypeError; + \item declaring a local constant of type $\vte$, literal $\vv$ and identifier $\ldi$ in $\tenvone$ yields $(\newtenv, \ldip)$; + \item $\news$ is a declaration with $\ldk$, $\ldip$ and an expression $\vep$. + \end{itemize} + + \item All of the following apply (\textsc{non\_constant}): + \begin{itemize} + \item $\ldk$ indicates that this is not a local constant declaration, that is, $\ldk\neq\LDKConstant$; + \item declaring the local identifiers $\ldi$ of type $\vte$ with local declaration keyword $\ldk$ in $\tenv$ + yields $(\newtenv, \ldip)$; + \item $\news$ is a declaration with $\ldk$, $\ldip$ and an expression $\vep$; + \item $\newtenv$ is $\tenvone$. + \end{itemize} + \end{itemize} + \end{itemize} + + \item All of the following apply (\textsc{none}): + \begin{itemize} + \item $\vs$ is a local declaration statement with a variable keyword and local identifiers $\ldi$, and no initial expression, + that is, $\SDecl(\LDKVar, \ldi, \None)$ (local declarations of \texttt{let} variables and constants require + an initializing expression, otherwise they are rejected by an ASL parser); + \item annotating the uninitialised local declarations $\ldi$ in $\tenv$ yields \\ + $(\newtenv, \ldip)$; + \item $\news$ is a local declaration statement with variable keyword, local identifiers $\ldip$, and no initial expression, + that is, $\SDecl(\LDKVar, \ldip, \None)$. + \end{itemize} +\end{itemize} +\subsubsection{Formally} +\begin{mathpar} +\inferrule[constant]{ + \annotateexpr{\tenv, \ve} \typearrow (\vte, \vep) \OrTypeError\\\\ + \annotatelocaldeclitem{\tenv, \vte, \ldk, \ldi} \typearrow (\tenvone, \ldip)\\\\ + \commonprefixline\\\\ + \ldk = \LDKConstant\\ + \reduceconstants(\tenvone, \ve) \typearrow \vv \OrTypeError\\\\ + \declarelocalconstant(\tenvone, \vv, \ldi) \typearrow \newtenv\\ + \news \eqdef \SDecl(\LDKConstant, \ldip, \langle\vep\rangle) +}{ + \annotatestmt(\tenv, \overname{\SDecl(\ldk, \ldi, \langle\ve\rangle)}{\vs}) \typearrow (\news, \newtenv) +} +\end{mathpar} + +\begin{mathpar} +\inferrule[non\_constant]{ + \annotateexpr{\tenv, \ve} \typearrow (\vte, \vep) \OrTypeError\\\\ + \annotatelocaldeclitem{\tenv, \vte, \ldk, \ldi} \typearrow (\tenvone, \ldip)\\\\ + \commonprefixline\\\\ + \ldk \neq \LDKConstant\\ + \news \eqdef \SDecl(\ldk, \ldip, \langle\vep\rangle) +}{ + \annotatestmt(\tenv, \overname{\SDecl(\ldk, \ldi, \langle\ve\rangle)}{\vs}) \typearrow (\news, \overname{\tenvone}{\newtenv}) +} +\end{mathpar} +\lrmcomment{This is related to \identr{YSPM}.} + +\begin{mathpar} +\inferrule[none]{ + \annotatelocaldeclitemuninit(\tenv, \ldi) \typearrow (\newtenv, \ldip) \OrTypeError\\\\ + \news \eqdef \SDecl(\LDKVar, \ldip, \None) +}{ + \annotatestmt(\tenv, \overname{\SDecl(\LDKVar, \ldi, \None)}{\vs}) \typearrow (\news, \newtenv) +} +\end{mathpar} +\CodeSubsection{\SDeclegin}{\SDeclEnd}{../Typing.ml} + +\subsubsection{TypingRule.DeclareLocalConstant \label{sec:TypingRule.DeclareLocalConstant}} +\hypertarget{def-declarelocalconstant}{} +The helper function +\[ +\declarelocalconstant(\overname{\staticenvs}{\tenv} \aslsep \overname{\literal}{\vv} \aslsep \overname{\localdeclitem}{\ldi}) +\typearrow \overname{\staticenvs}{\newtenv} +\] +adds the literal $\vv$ with the local declaration item $\ldi$ as a constant to the local component of the static environment $\tenv$, +yielding the modified static environment $\newtenv$. + +\subsubsection{Prose} +One of the following applies: +\begin{itemize} + \item All of the following apply (\textsc{discard}): + \begin{itemize} + \item $\ldi$ corresponds to a discarding declaration, that is, $\LDIDiscard$; + \item $\newtenv$ is $\tenv$. + \end{itemize} + + \item All of the following apply (\textsc{var}): + \begin{itemize} + \item $\ldi$ corresponds to a variable declaration for $\vx$, that is, $\LDIVar(\vx)$; + \item define $\newtenv$ and the environment $\tenv$ with its global component updated by binding + $\vx$ to $\vv$ in its $\constantvalues$ map. + \end{itemize} + + \item All of the following apply (\textsc{tuple}): + \begin{itemize} + \item $\ldi$ corresponds to a tuple declaration, that is, $\LDIVar(\Ignore)$; + \item this case is not yet implemented. + \end{itemize} + + \item All of the following apply (\textsc{typed}): + \begin{itemize} + \item $\ldi$ corresponds to a typed declaration of the local declaration item $\ldip$ and some type, that is, $\LDITyped(\ldip, \Ignore)$; + \item applying $\declarelocalconstant$ to $\vv$ and $\ldip$ in $\tenv$ yields $\newtenv$. + \end{itemize} +\end{itemize} +\subsubsection{Formally} +\begin{mathpar} +\inferrule[discard]{}{ + \declarelocalconstant(\tenv, \vv, \overname{\LDIDiscard}{\ldi}) \typearrow \overname{\tenv}{\newtenv} +} +\end{mathpar} + +\begin{mathpar} +\inferrule[var]{ + \newtenv \eqdef (G^\tenv, L^\tenv.\constantvalues[\vx \mapsto \vv]) +}{ + \declarelocalconstant(\tenv, \vv, \overname{\LDIVar(\vx)}{\ldi}) \typearrow \newtenv +} +\end{mathpar} + +\begin{mathpar} +\inferrule[tuple]{}{ + \declarelocalconstant(\tenv, \vv, \overname{\LDITuple(\Ignore)}{\ldi}) \typearrow \tododefine{not implemented yet} +} +\end{mathpar} + +\begin{mathpar} +\inferrule[typed]{ + \declarelocalconstant(\tenv, \vv, \ldip) \typearrow \newtenv +}{ + \declarelocalconstant(\tenv, \vv, \overname{\LDITyped(\ldip, \Ignore)}{\ldi}) \typearrow \newtenv +} +\end{mathpar} +\CodeSubsection{\DeclareLocalConstantBegin}{\DeclareLocalConstantEnd}{../Typing.ml} + +\subsubsection{TypingRule.AnnotateLocalDeclItemUninit \label{sec:TypingRule.AnnotateLocalDeclItemUninit}} +\hypertarget{def-annotatelocaldeclitemuninit}{} +The helper function +\[ +\begin{array}{r} +\annotatelocaldeclitemuninit(\overname{\staticenvs}{\tenv} \aslsep \overname{\localdeclitem}{\ldi}) +\typearrow \\ +(\overname{\staticenvs}{\newtenv} \times \overname{\localdeclitem}{\newldi}) +\cup \overname{\TTypeError}{\TypeErrorConfig} +\end{array} +\] +annotates the local declaration for a variable declaration without an initializing expressions in the static environment $\tenv$, +yielding a pair consisting of the annotated local declaration item $\newldi$ and the modified static environment $\newtenv$. +\ProseOtherwiseTypeError + +\subsubsection{Prose} +One of the following applies: +\begin{itemize} + \item All of the following apply (\textsc{discard}): + \begin{itemize} + \item $\ldi$ corresponds to a discarding declaration, that is, $\LDIDiscard$; + \item $\newtenv$ is $\tenv$ and $\newldi$ is $\ldi$. + \end{itemize} + + \item All of the following apply (\textsc{typed}): + \begin{itemize} + \item $\ldi$ corresponds to a variable declaration via the local declaration item $\ldip$ and type annotation $\vt$, + that is, $\LDITyped(\ldip, \vt)$; + \item annotating $\vt$ in $\tenv$ yields $\vtp$\ProseOrTypeError; + \item annotating the local declaration item $\ldip$ with the type $\vtp$ and local declaration keyword $\LDIVar$ + yields $(\newtenv, \newldip)$\ProseOrTypeError; + \item define $\newldi$ as the typed local declaration item with local declaration item $\newldip$ and type $\vtp$. + \end{itemize} +\end{itemize} + +\subsubsection{Formally} +\begin{mathpar} +\inferrule[discard]{}{ + \annotatelocaldeclitemuninit(\tenv, \overname{\LDIDiscard}{\ldi}) \typearrow (\overname{\tenv}{\newtenv}, \overname{\ldi}{\newldi}) +} +\end{mathpar} + +\begin{mathpar} +\inferrule[typed]{ + \annotatetype{\tenv, \vt} \typearrow \vtp \OrTypeError\\\\ + \annotatelocaldeclitem{\tenv, \vtp, \LDKVar, \ldip} \typearrow (\newtenv, \newldip) \OrTypeError\\\\ + \newldi \eqdef \LDITyped(\newldip, \vtp) +}{ + \annotatelocaldeclitemuninit(\tenv, \overname{\LDITyped(\ldip, \vt)}{\ldi}) \typearrow (\newtenv, \newldi) +} +\end{mathpar} + +\begin{mathpar} +\inferrule[error]{ + \astlabel(\ldi) \in \{\LDIVar, \LDITuple\} +}{ + \annotatelocaldeclitemuninit(\tenv, \ldi) \typearrow \TypeErrorVal{ExpectedTypedDeclaration} +} +\end{mathpar} +\CodeSubsection{\AnnotateLocalDeclItemUninitBegin}{\AnnotateLocalDeclItemUninitEnd}{../Typing.ml} + +\subsection{Semantics} +\subsubsection{SemanticsRule.SDeclSome\label{sec:SemanticsRule.SDeclSome}} +\subsubsection{Example (Declaration With an Initializing Value)} +The specification: +\VerbatimInput{../tests/ASLSemanticsReference.t/SemanticsRule.SDeclSome.asl} +\texttt{let x = 3;} binds \texttt{x} to $\nvint(3)$ in the empty environment. + +\subsubsection{Example (Declaration Without an Initializing Value)} +In the specification: +\VerbatimInput{../tests/ASLSemanticsReference.t/SemanticsRule.SDeclNone.asl} +\texttt{var x : integer;} binds \texttt{x} in $\env$ to the base value of \texttt{integer}. + +\subsubsection{Prose} +One of the following applies: +\begin{itemize} + \item All of the following apply (\textsc{some}): + \begin{itemize} + \item $\vs$ is a declaration with an initial value, + $\SDecl(\text{ldk}, \ldi, \langle\ve\rangle)$; + \item evaluating $\ve$ in $\env$ is $\Normal(\vm, \envone)$\ProseOrAbnormal; + \item evaluating the local declaration $\ldi$ with $\langle\vm\rangle$ as the initializing + value in $\envone$ as per \chapref{LocalStorageDeclarations} is $\Normal(\newg, \newenv)$; + \item the result of the entire evaluation is $\Continuing(\newg, \newenv)$. + \end{itemize} + + \item All of the following apply (\textsc{none}): + \begin{itemize} + \item $\vs$ is a declaration without an initial value, $\SDecl(\Ignore, \ldi, \None)$; + \item evaluating the local declaration $(\ldi, \None)$ as per \chapref{LocalStorageDeclarations} + is \\ $\Normal(\newg, \newenv)$; + \item the result of the entire evaluation is $\Continuing(\newg, \newenv)$. + \end{itemize} +\end{itemize} +\subsubsection{Formally} +\begin{mathpar} +\inferrule[some]{ + \evalexpr{\env, \ve} \evalarrow \Normal(\vm, \envone) \OrAbnormal\\ + \evallocaldecl{\envone, \ldi, \langle\vm\rangle} \evalarrow \Normal(\newg, \newenv)\\ +}{ + \evalstmt{\env, \SDecl(\Ignore, \ldi, \langle\ve\rangle)} \evalarrow \Continuing(\newg, \newenv) +} +\end{mathpar} + +\begin{mathpar} +\inferrule[none]{ + \evallocaldecl{\env, \vs, \ldi, \None} \evalarrow \Normal(\newg, \newenv)\\ +}{ + \evalstmt{\env, \SDecl(\Ignore, \ldi, \None)} \evalarrow \Continuing(\newg, \newenv) +} +\end{mathpar} +\CodeSubsection{\EvalSDeclBegin}{\EvalSDeclEnd}{../Interpreter.ml} + +\section{Sequencing Statements\label{sec:SeuqncingStatements}} +\subsection{Syntax} +\begin{flalign*} +\Nstmtlist \derivesinline\ & \nonemptylist{\Nstmt} & +\end{flalign*} + +\subsection{Abstract Syntax} +\begin{flalign*} +\stmt \derives\ & \SSeq(\stmt, \stmt) & +\end{flalign*} + +\subsubsection{ASTRule.StmtList \label{sec:ASTRule.StmtList}} +\hypertarget{build-stmtlist}{} +The function +\[ + \buildstmtlist(\overname{\parsenode{\Nstmtlist}}{\vparsednode}) \;\aslto\; \overname{\stmt}{\vastnode} +\] +transforms a parse node $\vparsednode$ into an AST node $\vastnode$. + +\begin{mathpar} +\inferrule{ + \buildlist[\Nstmt](\vstmts) \astarrow \vstmtlist\\ + \stmtfromlist(\vstmtlist) \astarrow \vastnode +}{ + \buildstmtlist(\Nstmtlist(\namednode{\vstmts}{\nonemptylist{\Nstmt}})) \astarrow \vastnode +} +\end{mathpar} + +\subsubsection{ASTRule.StmtFromList \label{sec:ASTRule.StmtFromList}} +\hypertarget{def-stmtfromlist}{} +The helper function +\[ +\stmtfromlist(\overname{\stmt^*}{\vstmts}) \aslto \overname{\stmt}{\news} +\] +builds a statement $\news$ from a possibly-empty list of statements $\vstmts$. + +\begin{mathpar} +\inferrule[empty]{ +}{ + \stmtfromlist(\overname{\emptylist}{\vstmts}) \astarrow \overname{\SPass}{\news} +} +\and +\inferrule[non\_empty]{ + \stmtfromlist(\vstmtsone) \astarrow \vsone\\ + \sequencestmts(\vs, \vsone) \astarrow \news +}{ + \stmtfromlist(\overname{[\vs] \concat \vstmtsone}{\vstmts}) \astarrow \news +} +\end{mathpar} + +\subsubsection{ASTRule.SequenceStmts \label{sec:ASTRule.SequenceStmts}} +\hypertarget{def-sequencestmts}{} +The helper function +\[ +\sequencestmts(\overname{\stmt}{\vsone}, \overname{\stmt}{\vstwo}) \aslto \overname{\stmt}{\news} +\] +Combines the statement $\vsone$ with $\vstwo$ into the statement $\news$, while filtering away +instances of $\SPass$. + +\begin{mathpar} +\inferrule[s1\_spass]{}{ + \sequencestmts(\overname{\SPass}{\vsone}, \vstwo) \astarrow \overname{\vstwo}{\news} +} +\and +\inferrule[s2\_spass]{ + \vsone \neq \SPass +}{ + \sequencestmts(\vsone, \overname{\SPass}{\vstwo}) \astarrow \overname{\vsone}{\news} +} +\and +\inferrule[no\_spass]{ + \vsone \neq \SPass\\ + \vstwo \neq \SPass +}{ + \sequencestmts(\vsone, \vstwo) \astarrow \overname{\SSeq(\vsone, \vstwo)}{\news} +} +\end{mathpar} + +\subsection{Typing} +\subsubsection{TypingRule.SSeq \label{sec:TypingRule.SSeq}} +\subsubsection{Prose} +All of the following apply: +\begin{itemize} + \item $\vs$ is the AST node for the sequence of statements $\vsone$ and $\vstwo$, that is, $\SSeq(\vsone, \vstwo)$; + \item annotating $\vsone$ in $\tenv$ yields $(\newsone, \tenvone)$\ProseOrTypeError; + \item annotating $\vstwo$ in $\tenvone$ yields $(\newstwo, \newtenv)$\ProseOrTypeError; + \item $\news$ is the AST node for the sequence of statements $\newsone$ and $\newstwo$, that is, $\SSeq(\newsone, \newstwo)$. +\end{itemize} +\subsubsection{Formally} +\begin{mathpar} +\inferrule{ + \annotatestmt(\tenv, \vs1) \typearrow (\newsone, \tenvone) \OrTypeError\\\\ + \annotatestmt(\tenvone, \vs2) \typearrow (\newstwo, \newtenv) \OrTypeError +}{ + \annotatestmt(\tenv, \overname{\SSeq(\vsone, \vstwo)}{\vs}) \typearrow (\overname{\SSeq(\newsone, \newstwo)}{\news}, \newtenv) +} +\end{mathpar} +\CodeSubsection{\SSeqBegin}{\SSeqEnd}{../Typing.ml} + +\subsection{Semantics} +\subsubsection{SemanticsRule.SSeq\label{sec:SemanticsRule.SSeq}} +\subsubsection{Example} +In the specification: +\VerbatimInput{../tests/ASLSemanticsReference.t/SemanticsRule.SSeq.asl} +\texttt{let x = 3; let y = x + 1} evaluates \texttt{let x = 3} then \texttt{let y = x + 1}. + +\subsubsection{Prose} +All of the following apply: +\begin{itemize} + \item $\vs$ is a \emph{sequencing statement} \texttt{s1; s2}, that is, $\SSeq(\vsone, \vstwo)$; + \item evaluating $\vsone$ in $\env$ is either $\Continuing(\vgone, \envone)$ in which case + the evaluation continues, + or a returning configuration ($\Returning((\vvs, \newg), \newenv)$)\ProseOrAbnormal; + \item evaluating $\vstwo$ in $\envone$ yields a non-abnormal configuration \\ + (either $\Normal$ or $\Continuing$) $C$\ProseOrAbnormal; + \item $\newg$ is the ordered composition of $\vgone$ and the execution graph of $C$ with the + $\aslpo$ edge; + \item $D$ is the configuration $C$ with the execution graph component replaced with $\newg$. +\end{itemize} +\subsubsection{Formally} +\begin{mathpar} + \inferrule{ + \evalstmt{\env, \vsone} \evalarrow \Continuing(\vgone, \envone) \terminateas \ReturningConfig,\ThrowingConfig,\ErrorConfig\\ + \evalstmt{\envone, \vstwo} \evalarrow C \OrAbnormal\\ + \newg \eqdef \ordered{\vgone}{\aslpo}{\graphof{C}}\\ + D \eqdef \withgraph{C}{\newg} + } + { + \evalstmt{\env, \SSeq(\vsone, \vstwo)} \evalarrow D + } +\end{mathpar} +\CodeSubsection{\EvalSSeqBegin}{\EvalSSeqEnd}{../Interpreter.ml} + +\section{Call Statements\label{sec:CallStatements}} +\subsection{Syntax} +\begin{flalign*} +\Nstmt \derivesinline\ & \Tidentifier \parsesep \Plist{\Nexpr} \parsesep \Tsemicolon & +\end{flalign*} + +\subsection{Abstract Syntax} +\begin{flalign*} +\stmt \derives\ & \SCall(\overtext{\identifier}{subprogram name}, \overtext{\expr^{*}}{actual arguments}) & +\end{flalign*} + +\subsubsection{ASTRule.SCall} +\begin{mathpar} +\inferrule{ + \buildplist[\Nexpr](\vargs) \astarrow \astversion{\vargs} +}{ + \buildstmt(\overname{\Nstmt(\Tidentifier(\vx), \namednode{\vargs}{\Plist{\Nexpr}}, \Tsemicolon)}{\vparsednode}) + \astarrow + \overname{\SCall(\vx, \astversion{\vargs})}{\vastnode} +} +\end{mathpar} + +\subsection{Typing} +\subsubsection{TypingRule.SCall \label{sec:TypingRule.SCall}} +\subsubsection{Prose} +All of the following apply: +\begin{itemize} + \item $\vs$ is a call to a subprogram named $\name$ with arguments $\vargs$; + \item annotating the call to $\name$ with arguments $\vargs$, as a procedure (that is, with $\STProcedure$), + as per \chapref{SubprogramCalls} (which makes sure that the call does not have a return type), + yields $(\newname, \newargs, \eqs, \None)$\ProseOrTypeError; + \item $\news$ is the call to a subprogram named $\newname$ with arguments + $\newargs$ and parameter assignments $\neweqs$; + \item $\newtenv$ is $\tenv$. +\end{itemize} +\subsubsection{Formally} +\begin{mathpar} +\inferrule{ + { + \begin{array}{r} + \annotatecall(\tenv, \name, \vargs, \STProcedure) \typearrow \\ (\newname, \newargs, \eqs, \None) \OrTypeError + \end{array} + } +}{ + { + \begin{array}{r} + \annotatestmt(\tenv, \overname{\SCall(\name, \vargs)}{\vs}) \typearrow \\ + (\overname{\SCall(\newname, \newargs, \eqs)}{\news}, \tenv) + \end{array} + } +} +\end{mathpar} +\CodeSubsection{\SCallBegin}{\SCallEnd}{../Typing.ml} + +\subsubsection{Comments} +Notice that the input statement, which belongs to the untyped AST, has two children nodes --- +$\name$ and $\vargs$, whereas the output statement, which belongs to the typed AST has the additional +node $\neweqs$, which associates expressions with parameters. +\lrmcomment{This is related to \identd{VXKM}.} + +\subsection{Semantics} +\subsubsection{SemanticsRule.SCall \label{sec:SemanticsRule.SCall}} +\subsubsection{Example} +In the specification: +\VerbatimInput{../tests/ASLSemanticsReference.t/SemanticsRule.SCall.asl} +\texttt{Zeros(3)} evaluates to \texttt{'000'}. + +\subsubsection{Prose} +All of the following apply: +\begin{itemize} + \item $\vs$ is a call statement, $\SCall(\name, \args, \namedargs)$; + \item evaluating the subprogram call as per \chapref{SubprogramCalls} is + \\ $\Normal(\newg, \newenv)$\ProseOrAbnormal; + \item the result of the entire evaluation is $\Continuing(\newg, \newenv)$. +\end{itemize} + +\subsubsection{Formally} +\begin{mathpar} +\inferrule{ + \evalcall{\env, \name, \args, \namedargs} \evalarrow \Normal(\newg, \newenv) \OrAbnormal +}{ + \evalstmt{\env, \overname{\SCall(\name, \args, \namedargs)}{\vs}} \evalarrow \Continuing(\newg, \newenv) +} +\end{mathpar} +\CodeSubsection{\EvalSCallBegin}{\EvalSCallEnd}{../Interpreter.ml} +% \lrmcomment{This is related to \identd{KCYT}:} + +\section{Conditional Statements\label{sec:ConditionalStatements}} +\subsection{Syntax} +\begin{flalign*} +\Nstmt \derivesinline\ & \Tif \parsesep \Nexpr \parsesep \Tthen \parsesep \Nstmtlist \parsesep \Nselse \parsesep \Tend &\\ +\Nselse \derives\ & \Telseif \parsesep \Nexpr \parsesep \Tthen \parsesep \Nstmtlist \parsesep \Nselse &\\ + |\ & \Tpass &\\ + |\ & \Telse \parsesep \Nstmtlist & +\end{flalign*} + +\subsection{Abstract Syntax} +\begin{flalign*} +\stmt \derives\ & \SCond(\expr, \stmt, \stmt) +\end{flalign*} + +\subsubsection{ASTRule.SCond} +\begin{mathpar} +\inferrule{}{ + { + \begin{array}{r} + \buildstmt(\overname{\Nstmt(\Tif, \punnode{\Nexpr}, \Tthen, \punnode{\Nstmtlist}, \punnode{\Nselse}, \Tend)}{\vparsednode}) + \astarrow \\ + \overname{\SCond(\astof{\vexpr}, \astof{\vstmtlist}, \astof{\velse})}{\vastnode} + \end{array} + } +} +\end{mathpar} + +\subsubsection{ASTRule.SElse \label{sec:ASTRule.SElse}} +\hypertarget{build-selse}{} +The function +\[ + \buildselse(\overname{\parsenode{\Nselse}}{\vparsednode}) \;\aslto\; \overname{\stmt}{\vastnode} +\] +transforms a parse node $\vparsednode$ into an AST node $\vastnode$. + +\begin{mathpar} +\inferrule[elseif]{}{ + { + \begin{array}{r} + \buildselse(\Nselse(\Telseif, \Nexpr, \Twhen, \Nstmtlist, \Nselse)) \astarrow \\ + \overname{\SCond(\astof{\vexpr}, \astof{\vstmtlist}, \astof{\vselse})}{\vastnode} + \end{array} + } +} +\end{mathpar} + +\begin{mathpar} +\inferrule[pass]{}{ + \buildselse(\Nselse(\Tpass)) \astarrow \overname{\SPass}{\vastnode} +} +\end{mathpar} + +\begin{mathpar} +\inferrule[else]{}{ + \buildselse(\Nselse(\Telse, \punnode{\Nstmtlist})) \astarrow \overname{\astof{\vstmtlist}}{\vastnode} +} +\end{mathpar} + +\subsection{Typing} +\subsubsection{TypingRule.SCond \label{sec:TypingRule.SCond}} +\subsubsection{Prose} +All of the following apply: +\begin{itemize} + \item $\vs$ is a condition $\ve$ with the statements $\vsone$ and $\vstwo$, that is, $\SCond(\ve, \vsone, \vstwo)$; + \item annotating the right-hand-side expression $\ve$ in $\tenv$ yields $(\tcond, \econd)$\ProseOrTypeError; + \item checking that $\tcond$ \typesatisfies\ $\TBool$ yields $\True$\ProseOrTypeError; + \item annotating the statement $\vsone$ in $\tenv$ yields $\vsonep$\ProseOrTypeError; + \item annotating the statement $\vstwo$ in $\tenv$ yields $\vstwop$\ProseOrTypeError; + \item $\news$ is the condition $\econd$ with the statements $\vsonep$ and $\vstwop$, that is, \\ $\SCond(\econd, \vsonep, \vstwop)$; + \item $\newtenv$ is $\tenv$. +\end{itemize} +\subsubsection{Formally} +\begin{mathpar} +\inferrule{ + \annotateexpr{\tenv, \ve} \typearrow (\tcond, \econd) \OrTypeError\\\\ + \checktypesat(\tenv, \tcond, \TBool) \typearrow \True \OrTypeError\\\\ + \annotateblock{\tenv, \vsone} \typearrow \vsonep \OrTypeError\\\\ + \annotateblock{\tenv, \vstwo} \typearrow \vstwop \OrTypeError +}{ + \annotatestmt(\tenv, \overname{\SCond(\ve, \vsone, \vstwo)}{\vs}) \typearrow + (\overname{\SCond(\econd, \vsonep, \vstwop)}{\news}, \overname{\tenv}{\newtenv}) +} +\end{mathpar} +\CodeSubsection{\SCondBegin}{\SCondEnd}{../Typing.ml} +\lrmcomment{This is related to \identr{NBDJ}.} + +\subsection{Semantics} +subsubsection{SemanticsRule.SCond\label{sec:SemanticsRule.SCond}} +\subsubsection{Examples} +The specification: +\VerbatimInput{../tests/ASLSemanticsReference.t/SemanticsRule.SCond.asl} +does not result in any Assertion Error. + +The specification: +\VerbatimInput{../tests/ASLSemanticsReference.t/SemanticsRule.SCond2.asl} + +The specification: +\VerbatimInput{../tests/ASLSemanticsReference.t/SemanticsRule.SCond3.asl} + +The specification: +\VerbatimInput{../tests/ASLSemanticsReference.t/SemanticsRule.SCond4.asl} + +\subsubsection{Prose} +All of the following apply: +\begin{itemize} +\item $\vs$ is a condition statement, $\SCond(\ve, \vsone, \vstwo)$; +\item evaluating $\ve$ in $\env$ is $\Normal(\vv, \vgone)$\ProseOrAbnormal; +\item $\vv$ is a native Boolean for $\vb$; +\item the statement $\vsp$ is $\vsone$ is $\vb$ is $\True$ and $\vstwo$ otherwise +(so that $\vsone$ will be evaluated if the condition evaluates to $\True$ and otherwise +$\vstwo$ will be evaluated); +\item evaluating $\vsp$ in $\envone$ as per \chapref{Blocks} is a non-abnormal configuration + (either $\Normal$ or $\Continuing$) $C$\ProseOrAbnormal; +\item $\vg$ is the ordered composition of $\vgone$ and the execution graph of the configuration $C$; +\item $D$ is the configuration $C$ with the execution graph component updated to be $\vg$. +\end{itemize} + +\subsubsection{Formally} +\begin{mathpar} +\inferrule{ + \evalexpr{\env, \ve} \evalarrow \Normal((\vv, \vgone), \envone) \OrAbnormal\\ + \vv \eqname \nvbool(\vb)\\ + \vsp \eqdef \choice{\vb}{\vsone}{\vstwo}\\ + \evalblock{\envone, \vsp} \evalarrow C \OrAbnormal\\\\ + \vg \eqdef \ordered{\vgone}{\aslctrl}{\graphof{C}}\\ + D \eqdef \withgraph{C}{\vg} +}{ + \evalstmt{\env, \overname{\SCond(\ve, \vsone, \vstwo)}{\vs}} \evalarrow D +} +\end{mathpar} +\CodeSubsection{\EvalSCondBegin}{\EvalSCondEnd}{../Interpreter.ml} + +\section{Case Statements\label{sec:CaseStatements}} +\subsection{Syntax} +\begin{flalign*} +\Nstmt \derivesinline\ & \Tcase \parsesep \Nexpr \parsesep \Tof \parsesep \nonemptylist{\Nalt} \parsesep \Tend &\\ +\Nalt \derivesinline\ & \Twhen \parsesep \Npatternlist \parsesep \option{\Twhere \parsesep \Nexpr} \parsesep \Tarrow \parsesep \Nstmtlist &\\ + |\ & \Totherwise \parsesep \Nstmtlist &\\ +\Notherwiseopt \derives\ & \option{\Totherwise \parsesep \Tarrow \parsesep \Nstmtlist} & +\end{flalign*} + +\subsection{Abstract Syntax} +\begin{flalign*} +\stmt \derives\ & \SCase(\expr, \casealt^*) & +\end{flalign*} + +\subsubsection{ASTRule.SCase} +\begin{mathpar} +\inferrule{ + \buildlist[\Nalt](\valtlist) \astarrow \valtlistast +}{ + { + \begin{array}{r} + \buildstmt(\overname{\Nstmt(\Tcase, \punnode{\Nexpr}, \Tof, \namednode{\valtlist}{\nonemptylist{\Nalt}}, \Tend)}{\vparsednode}) + \astarrow \\ + \overname{\SCase(\astof{\vexpr}, \valtlistast)}{\vastnode} + \end{array} + } +} +\end{mathpar} + +\subsubsection{ASTRule.Alt\label{sec:ASTRule.Alt}} +\hypertarget{build-alt}{} +The function +\[ +\buildalt(\overname{\parsenode{\Nalt}}{\vparsednode}) \;\aslto\; \overname{\casealt}{\vastnode} +\] +transforms a parse node $\vparsednode$ into an AST node $\vastnode$. + +\begin{mathpar} +\inferrule[when]{ + \buildoption[\buildexpr](\vwhereopt) \astarrow \vwhereast +}{ + { + \begin{array}{r} + \buildalt\left(\overname{\Nalt\left( + \begin{array}{l} + \Twhen, \punnode{\Npatternlist}, \\ + \wrappedline\ \namednode{\vwhereopt}{\option{\Twhere, \Nexpr}}, \Tarrow, \\ + \wrappedline\ \namednode{\vstmts}{\Nstmtlist} + \end{array} + \right)}{\vparsednode}\right) + \astarrow \\ + \overname{\casealt(\CasePattern: \astof{\vpatternlist}, \CaseWhere: \vwhereast, \CaseStmt: \astof{\vstmtlist})}{\vastnode} + \end{array} + } +} +\end{mathpar} + +\begin{mathpar} +\inferrule[otherwise]{}{ + { + \begin{array}{r} + \buildalt(\overname{\Nalt(\Totherwise, \namednode{\vstmts}{\Nstmtlist})}{\vparsednode}) + \astarrow \\ + \overname{\casealt(\CasePattern: \PatternAll, \CaseWhere: \None, \CaseStmt: \astof{\vstmtlist})}{\vastnode} + \end{array} + } +} +\end{mathpar} + +\subsubsection{ASTRule.OtherwiseOpt\label{sec:ASTRule.OtherwiseOpt}} +\hypertarget{build-otherwiseopt}{} +The function +\[ +\buildotherwiseopt(\overname{\parsenode{\Notherwiseopt}}{\vparsednode}) \;\aslto\; \overname{\stmt?}{\vastnode} +\] +transforms a parse node $\vparsednode$ into an AST node $\vastnode$. + +\begin{mathpar} +\inferrule{ + \buildoption[\buildstmtlist] (\vv)\astarrow \vastnode +}{ + { + \begin{array}{r} + \buildotherwiseopt(\overname{\Notherwiseopt(\namednode{\vv}{\option{\Totherwise, \Tarrow, \Nstmtlist}})}{\vparsednode}) + \astarrow \\ + \vastnode + \end{array} + } +} +\end{mathpar} + +\subsection{Typing} +\subsubsection{TypingRule.SCase \label{sec:TypingRule.SCase}} +\subsubsection{Prose} +All of the following apply: +\begin{itemize} + \item $\vs$ is a case statement with expression $\ve$ and case clauses $\vcases$, that is, \\ + $\SCase(\veone, \vcasesone)$; + \item annotating the right-hand-side expression $\ve$ in $\tenv$ yields $(\vte, \veone)$\ProseOrTypeError; + \item annotating each case clause as per \secref{TypingRule.CaseAlt} in $\vcases$ yields the annotated list of clauses $\vcasesone$\ProseOrTypeError; + \item $\news$ is a case statement with expression $\veone$ and case clauses $\vcasesone$; + \item $\newtenv$ is $\tenvone$. +\end{itemize} +\subsubsection{Formally} +\begin{mathpar} +\inferrule{ + \annotateexpr{\tenv, \ve} \typearrow (\vte, \veone) \OrTypeError\\\\ + \vi\in\listrange(\vcases): \annotatecase{\tenv, \vcases[\vi]} \typearrow \vcase_\vi \OrTypeError\\\\ + \vcasesone \eqdef [\vi\in\listrange(\vcases): \vcase_\vi] +}{ + \annotatestmt(\tenv, \overname{\SCase(\ve, \vcases)}{\vs}) \typearrow + (\overname{\SCase(\veone, \vcasesone)}{\news}, \overname{\tenv}{\newtenv}) +} +\end{mathpar} +\CodeSubsection{\SCaseBegin}{\SCaseEnd}{../Typing.ml} +\lrmcomment{This is related to \identr{WGSY}.} + +\subsubsection{TypingRule.CaseAlt\label{sec:TypingRule.CaseAlt}} +\hypertarget{def-annotatecase}{} +The helper function +\[ + \annotatecase{ + \overname{\staticenvs}{\tenv} \aslsep + \overname{\casealt}{\vcase} \aslsep + \overname{\ty}{\vte} + } \aslto + \overname{\casealt}{\vcaseone} \cup \overname{\TTypeError}{\TypeErrorConfig} +\] +annotates the case clause $\vcase$ for an expression of type $\vte$ in $\tenv$, +resulting in the annotated case clause $\vcaseone$. +\ProseOtherwiseTypeError + +\subsubsection{Prose} +All of the following apply: +\begin{itemize} + \item $\vcase$ is a case clause with pattern $\vpzero$, \optional\ \texttt{where} expression $\vwzero$, + and \texttt{otherwise} statement $\vszero$, that is, + $\{ \CasePattern: \vpzero, \CaseWhere: \vwzero, \CaseStmt: \vszero \}$; + \item annotating the pattern $\vpzero$ with type $\vte$ in $\tenv$ yields $\vpone$\ProseOrTypeError; + \item annotating the statement $\vszero$ as a block statement in $\tenv$ yields $\vsone$\ProseOrTypeError; + \item One of the following applies: + \begin{itemize} + \item All of the following apply (\textsc{no\_where\_stmt}): + \begin{itemize} + \item $\vwzero$ is $\None$ (that is, no \texttt{where} expression); + \item $\vcaseone$ is $\{ \CasePattern: \vpone, \CaseWhere: \None, \CaseStmt: \vsone \}$. + \end{itemize} + + \item All of the following apply (\textsc{where\_stmt}): + \begin{itemize} + \item $\vwzero$ is the singleton expression for $\vewzero$, that is, $\langle\vewzero\rangle$; + \item annotating the expression $\vewzero$ in $\tenv$ yields $(\vtwe, \vewone)$\ProseOrTypeError; + \item checking whether the structure of $\vtwe$ in $\tenv$ is that of the \texttt{boolean} type yields $\True$\ProseOrTypeError; + \item $\vcaseone$ is $\{ \CasePattern: \vpone, \CaseWhere: \langle\vewone\rangle, \CaseStmt: \vsone \}$. + \end{itemize} + \end{itemize} +\end{itemize} + +\subsubsection{Formally} +\begin{mathpar} +\inferrule[no\_where\_stmt]{ + \vcase = \{ \CasePattern: \vpzero, \CaseWhere: \None, \CaseStmt : \vszero \}\\ + \annotatepattern(\tenv, \vte, \vpzero) \typearrow \vpone \OrTypeError\\\\ + \annotateblock{\tenv, \vszero} \typearrow \vsone \OrTypeError\\ +}{ + \annotatecase{\tenv, \vcase, \vte} \typearrow \overname{\{ \CasePattern: \vpone, \CaseWhere: \None, \CaseStmt : \vsone \}}{\vcaseone} +} +\and +\inferrule[where\_stmt]{ + \vcase = \{ \CasePattern: \vpzero, \CaseWhere: \langle\vewzero\rangle, \CaseStmt : \vszero \}\\ + \annotatepattern(\tenv, \vte, \vpzero) \typearrow \vpone \OrTypeError\\\\ + \annotateblock{\tenv, \vszero} \typearrow \vsone \OrTypeError\\\\ + \annotateexpr{\tenv, \vewzero} \typearrow (\vtwe, \vewone) \OrTypeError\\\\ + \checkstructurelabel(\tenv, \vtwe, \TBool) \typearrow \True \OrTypeError +}{ + \annotatecase{\tenv, \vcase, \vte} \typearrow \overname{\{ \CasePattern: \vpone, \CaseWhere: \langle\vewone\rangle, \CaseStmt : \vsone \}}{\vcaseone} +} +\end{mathpar} + +\subsection{Semantics} +\subsubsection{SemanticsRule.SCase \label{sec:SemanticsRule.SCase}} +\subsubsection{Example} +The specification: +\VerbatimInput{../tests/ASLSemanticsReference.t/SemanticsRule.SCase.asl} +uses the second \texttt{when} clause because \texttt{3} is less than \texttt{42}. + +\subsubsection{Prose} +Evaluation of the statement $\vs$ in an environment $\env$ is a configuration $C$, +and all of the following apply: +\begin{itemize} + \item $\vs$ is a case statement, $\SCase(\ve, \caselist)$; + \item desugaring $\vs$ gives a statement $\vsone$, which assigns $\ve$ to a fresh variable + and then matches its value against a list of patterns corresponding to $\caselist$ nested conditions. + In particular, this means that the cases are considered in order and only one of them is executed; + \item evaluating $\vsone$ in $\env$ results in the output configuration $C$. +\end{itemize} + +\subsubsection{Formally} +\hypertarget{def-casetoconds}{} +A case statement is syntactic sugar for a condition ladder where each +of the alternatives is a pattern. +That is, a statement of the form +\texttt{if e1 then s1; else if e2 then s2; else if e3 then s3; ... else pass;} + +We define the relation +\[ + \casetoconds(\expr, (\pattern \times \stmt)^*) \;\bigtimes\; \stmt +\] +which performs this AST-to-AST transformation, effectively desugaring +the case statement. + +\begin{mathpar} +\inferrule[var-empty]{} +{ + \casetoconds(\EVar(\vx), \emptylist) \evalarrow \SPass +} +\and +\inferrule[var-non-empty]{ + \casetoconds(\EVar(\vx), \caselist) \evalarrow \caselist' +}{ + \casetoconds(\EVar(\vx), [(\vp, \vs)] \concat \caselist) \evalarrow \\ + \SCond(\EPattern(\EVar(\vx), \vp), \vs, \caselist') +} +\and +\inferrule[non-var]{ + \astlabel(\ve) \neq \EVar\\ + \vy \in \Identifiers \text{ is fresh}\\ + \vardecl \eqname \SDecl(\LDKLet, \LDITyped(\LDIVar(\vy), \TInt(\unconstrained)))\\ + \casetoconds(\EVar(\vy), \caselist) \evalarrow \casecond +}{ + \casetoconds(\ve, \caselist) \evalarrow + \SSeq(\vardecl, \casecond) +} +\end{mathpar} + +We now define the semantics of a case statement in terms of the desugared statement: +\begin{mathpar} +\inferrule{ + \casetoconds(\ve, \caselist) \evalarrow \vsone\\ + \evalstmt{\env, \vsone} \evalarrow C +}{ + \evalstmt{\env, \SCase(\ve, \caselist)} \evalarrow C +} +\end{mathpar} +\CodeSubsection{\EvalSCaseBegin}{\EvalSCaseEnd}{../Interpreter.ml} + +\section{Assertion Statements\label{sec:AssertionStatements}} +\subsection{Syntax} +\begin{flalign*} +\Nstmt \derivesinline\ & \Tassert \parsesep \Nexpr \parsesep \Tsemicolon & +\end{flalign*} + +\subsection{Abstract Syntax} +\begin{flalign*} +\stmt \derives\ & \SAssert(\expr) & +\end{flalign*} + +\subsubsection{ASTRule.SAssert} +\begin{mathpar} +\inferrule{}{ + \buildstmt(\overname{\Nstmt(\Tassert, \Nexpr, \Tsemicolon)}{\vparsednode}) + \astarrow + \overname{\SAssert(\astof{\vexpr})}{\vastnode} +} +\end{mathpar} + +\subsection{Typing} +\subsubsection{TypingRule.SAssert \label{sec:TypingRule.SAssert}} +\subsubsection{Prose} +All of the following apply: +\begin{itemize} + \item $\vs$ is an assert statement with expression $\ve$, that is, $\SAssert(\ve)$; + \item annotating the right-hand-side expression $\ve$ in $\tenv$ yields $(\tep,\vep)$\ProseOrTypeError; + \item checking that $\vtep$ \typesatisfies\ $\TBool$ in $\tenv$ yields $\True$\ProseOrTypeError; + \item $\news$ is an assert statement with expression $\vep$, that is, $\SAssert(\vep)$; + \item $\newtenv$ is $\tenv$. +\end{itemize} +\subsubsection{Formally} +\begin{mathpar} +\inferrule{ + \annotateexpr{\tenv, \ve} \typearrow (\vtep, \vep) \OrTypeError\\\\ + \checktypesat(\tenv, \vtep, \TBool) \typearrow \True \OrTypeError +}{ + \annotatestmt(\tenv, \overname{\SAssert(\ve)}{\vs}) \typearrow (\overname{\SAssert(\vep)}{\news}, \overname{\tenv}{\newtenv}) +} +\end{mathpar} +\CodeSubsection{\SAssertBegin}{\SAssertEnd}{../Typing.ml} +\lrmcomment{This is related to \identr{JQYF}.} + +\subsection{Semantics} +\subsubsection{SemanticsRule.SAssert \label{sec:SemanticsRule.SAssert}} +\subsubsection{Example} +In the specification: +\VerbatimInput{../tests/ASLSemanticsReference.t/SemanticsRule.SAssertOk.asl} +\texttt{assert (42 != 3);} ensures that \texttt{3} is not equal to \texttt{42}. + +\subsubsection{Example} +In the specification: +\VerbatimInput{../tests/ASLSemanticsReference.t/SemanticsRule.SAssertNo.asl} +\texttt{assert (42 == 3);} results in an \texttt{AssertionFailed} error. +\subsubsection{Prose} +All of the following apply: +\begin{itemize} + \item $\vs$ is an assertion statement, $\SAssert(\ve)$; + \item one of the following holds: + \begin{itemize} + \item all of the following hold (\textsc{okay}): + \begin{itemize} + \item evaluating $\ve$ in $\env$ is $\Normal((\vv, \newg), \newenv)$\ProseOrAbnormal; + \item $\vv$ is a native Boolean value for $\True$; + \item the resulting configuration is $\Continuing(\newg, \newenv)$. + \end{itemize} + + \item all of the following hold (\textsc{error}): + \begin{itemize} + \item evaluating $\ve$ in $\env$ is $\Normal((\vv, \newg), \newenv)$; + \item $\vv$ is a native Boolean value for $\False$; + \item an AssertionFailed error is returned. + \end{itemize} + \end{itemize} +\end{itemize} +\subsubsection{Formally} +\begin{mathpar} +\inferrule[okay]{ + \evalexpr{\env, \ve} \evalarrow \Normal((\vv, \newg), \newenv) \OrAbnormal\\\\ + \vv \eqname \nvbool(\True) +}{ + \evalstmt{\env, \SAssert(\ve)} \evalarrow \Continuing(\newg, \newenv) +} +\end{mathpar} + +\begin{mathpar} + \inferrule[error]{ + \evalexpr{\env, \ve} \evalarrow \Normal((\vv, \Ignore), \Ignore)\\ + \vv \eqname \nvbool(\False) +}{ + \evalstmt{\env, \SAssert(\ve)} \evalarrow \ErrorVal{AssertionFailed} +} +\end{mathpar} +\CodeSubsection{\EvalSAssertBegin}{\EvalSAssertEnd}{../Interpreter.ml} +\lrmcomment{This is related to \identd{QJYV}:} +\lrmcomment{This is related to \identr{WZSL}:} +\lrmcomment{This is related to \identr{WQRN}:} + +\section{While Statements\label{sec:WhileStatements}} +\subsection{Syntax} +\begin{flalign*} +\Nstmt \derivesinline\ & \Twhile \parsesep \Nexpr \parsesep \Tdo \parsesep \Nstmtlist \parsesep \Tend &\\ +|\ & \Tlooplimit \parsesep \Tlpar \parsesep \Nexpr \parsesep \Trpar \parsesep \Twhile \parsesep \Nexpr \parsesep \Tdo \parsesep \Nstmtlist \parsesep \Tend &\\ +\end{flalign*} + +\subsection{Abstract Syntax} +\begin{flalign*} +\stmt \derives\ & \SWhile(\overtext{\expr}{condition}, \overtext{\expr?}{loop limit}, \overtext{\stmt}{loop body}) & +\end{flalign*} + +\subsubsection{ASTRule.SWhile} +\begin{mathpar} +\inferrule[no\_limit]{}{ + { + \begin{array}{r} + \buildstmt(\overname{\Nstmt(\Twhile, \punnode{\Nexpr}, \Tdo, \punnode{\Nstmtlist}, \Tend)}{\vparsednode}) + \astarrow\\ + \overname{\SWhile(\astof{\vexpr}, \None, \astof{\vstmtlist})}{\vastnode} +\end{array} +} +} +\end{mathpar} + +\begin{mathpar} +\inferrule[limit]{ + \buildexpr(\vlimitexpr) \astarrow \astversion{\vlimitexpr} +}{ + { + \begin{array}{r} + \buildstmt\left(\overname{\Nstmt\left( + \begin{array}{r} + \Tlooplimit, \Tlpar, \namednode{\vlimitexpr}{\Nexpr}, \Trpar, \Twhile, \\ + \wrappedline\ \punnode{\Nexpr}, \Tdo, \punnode{\Nstmtlist}, \Tend + \end{array} + \right)}{\vparsednode}\right) + \astarrow\\ + \overname{\SWhile(\astof{\vexpr}, \langle\astversion{\vlimitexpr}\rangle, \astof{\vstmtlist})}{\vastnode} +\end{array} +} +} +\end{mathpar} + +\subsection{Typing} +\subsubsection{TypingRule.SWhile \label{sec:TypingRule.SWhile}} +\subsubsection{Prose} +All of the following apply: +\begin{itemize} +\item $\vs$ is a \texttt{while} statement with expression $\veone$, optional limit expression $\vlimitone$, + and statement block $\vsone$, that is, $\SWhile(\veone, \vsone)$; +\item annotating the right-hand-side expression $\veone$ in $\tenv$ yields $(\vt, \vetwo)$\ProseOrTypeError; +\item annotating the optional limit expression $\vlimitone$ via $\annotatelooplimit$ in $\tenv$ yields $\vlimittwo$\ProseOrTypeError; +\item checking that $\vt$ \typesatisfies\ $\TBool$ in $\tenv$ yields $\True$\ProseOrTypeError; +\item $\news$ is a \texttt{while} statement with expression $\vetwo$, optional limit expression $\vlimittwo$, + and statement block $\vstwo$, that is, $\SWhile(\vetwo, \vstwo)$; +\item $\newtenv$ is $\tenv$. +\end{itemize} +\subsubsection{Formally} +\begin{mathpar} +\inferrule{ + \annotateexpr{\tenv, \veone} \typearrow (\vt, \vetwo) \OrTypeError\\\\ + \annotatelooplimit(\tenv, \vlimitone) \typearrow \vlimittwo \OrTypeError\\\\ + \checktypesat(\tenv, \vt, \TBool) \typearrow \True \OrTypeError\\\\ + \annotateblock{\tenv, \vsone} \typearrow \vstwo \OrTypeError +}{ + \annotatestmt(\tenv, \overname{\SWhile(\veone, \vlimitone, \vsone)}{\vs}) \typearrow + (\overname{\SWhile(\vetwo, \vlimittwo, \vstwo)}{\news}, \overname{\tenv}{\newtenv}) +} +\end{mathpar} +\CodeSubsection{\SWhileBegin}{\SWhileEnd}{../Typing.ml} +\lrmcomment{This is related to \identr{FTVN}.} + +\subsubsection{TypingRule.AnnotateLoopLimit\label{sec:TypingRule.AnnotateLoopLimit}} +\hypertarget{def-annotatelooplimit}{} +The function +\[ + \annotatelooplimit( + \overname{\staticenvs}{\tenv} \aslsep + \overname{\langle\expr\rangle}{\ve} \aslsep + ) \aslto + \overname{\expr}{\vep} \cup\ \overname{\TTypeError}{\TypeErrorConfig} +\] +annotates an optional expression $\ve$ serving as the limit of a loop in $\tenv$, +yielding the optional loop expression $\vep$. +\ProseOtherwiseTypeError + +\subsubsection{Prose} +One of the following applies: +\begin{itemize} + \item All of the following apply (\textsc{none}): + \begin{itemize} + \item $\ve$ is $\None$; + \item $\vep$ is $\None$. + \end{itemize} + + \item All of the following apply (\textsc{some}): + \begin{itemize} + \item $\ve$ is $\langle\vlimit\rangle$; + \item annotating $\vlimit$ in $\tenv$ yields $(\vt, \vlimitp)$\ProseOrTypeError; + \item checking that $\vt$ is a constrained integer in $\tenv$ via \\ + $\checkconstrainedinteger$ yields $\True$\ProseOrTypeError; + \item $\vep$ is $\langle\vlimitp\rangle$. + \end{itemize} +\end{itemize} + +\subsubsection{Formally} +\begin{mathpar} +\inferrule[none]{}{ + \annotatelooplimit(\tenv, \overname{\None}{\vlimit}) \typearrow \overname{\None}{\vlimitp} +} +\end{mathpar} +\begin{mathpar} +\inferrule[some]{ + \annotateexpr{\tenv, \vlimit} \typearrow (\vt, \vlimitp) \OrTypeError\\\\ + \checkconstrainedinteger(\tenv, \vt) \typearrow \True \OrTypeError +}{ + \annotatelooplimit(\tenv, \overname{\langle\vlimit\rangle}{\vlimit}) \typearrow \overname{\langle\vlimitp\rangle}{\vlimitp} +} +\end{mathpar} +\CodeSubsection{\AnnotateLoopLimitBegin}{\AnnotateLoopLimitEnd}{../Typing.ml} + +\subsection{Semantics} +\subsubsection{SemanticsRule.SWhile \label{sec:SemanticsRule.SWhile}} +\subsubsection{Example} +The specification: +\VerbatimInput{../tests/ASLSemanticsReference.t/SemanticsRule.SWhile.asl} +prints \texttt{0123}. + +\subsubsection{Prose} +Evaluation of the statement $\vs$ in an environment $\env$ is +the output configuration $C$ and all of the following apply: +\begin{itemize} + \item $\vs$ is a \texttt{while} statement, $\SWhile(\ve, \Ignore, \vbody)$; + \item evaluating the loop as per \nameref{sec:SemanticsRule.Loop} in an environment $\env$, + with the arguments $\True$ (which conveys that this is a \texttt{while} statement), $\ve$, and $\vbody$ + results in $C$. +\end{itemize} +\subsubsection{Formally} +\begin{mathpar} +\inferrule{ + \evalloop{\env, \True, \ve, \vbody} \evalarrow C +}{ + \evalstmt{\env, \overname{\SWhile(\ve, \Ignore, \vbody)}{\vs}} \evalarrow C +} +\end{mathpar} +\CodeSubsection{\EvalSWhileBegin}{\EvalSWhileEnd}{../Interpreter.ml} + +\subsubsection{SemanticsRule.Loop\label{sec:SemanticsRule.Loop}} +The relation +\hypertarget{def-evalloop}{} +\[ + \evalloop{\overname{\envs}{\env} \aslsep \overname{\Bool}{\iswhile} \aslsep \overname{\expr}{\econd} \aslsep \overname{\stmt}{\vbody}} + \;\aslrel\; + \left( + \begin{array}{cl} + \Continuing(\overname{\XGraphs}{\newg} \aslsep \overname{\envs}{\newenv}) & \cup \\ + \overname{\TReturning}{\ReturningConfig} & \cup \\ + \overname{\TThrowing}{\ThrowingConfig} & \cup \\ + \overname{\TError}{\ErrorConfig} & + \end{array} + \right) +\] +to evaluate both \texttt{while} statements and \texttt{repeat} statements. + +More specifically, $\evalloop{\env, \iswhile, \econd, \vbody}$ +evaluates $\vbody$ in $\env$ as long as $\econd$ holds when $\iswhile$ is $\True$ +or until $\econd$ holds when $\iswhile$ is $\False$. +The result is either the continuing configuration \\ $\Continuing(\newg,\newenv)$, +an early return configuration, or an abnormal configuration. + +\subsubsection{Example} +The specification: +\VerbatimInput{../tests/ASLSemanticsReference.t/SemanticsRule.Loop.asl} +does not result in any Assertion Error and the specification terminates with exit +code $0$. + +\CodeSubsection{\EvalLoopBegin}{\EvalLoopEnd}{../Interpreter.ml} +\subsection{Prose} +One of the following applies: +\begin{itemize} +\item all of the following apply (\textsc{exit}): + \begin{itemize} + \item evaluating $\econd$ in $\env$ is $\Normal(\condm, \newenv)$\ProseOrAbnormal; + \item $\condm$ consists of a native Boolean for $\vb$ and an execution graph $\newg$; + \item $\vb$ is not equal to $\iswhile$; + \item the result of the entire evaluation is $\Continuing(\newg, \newenv)$ + and the loop is exited. + \end{itemize} +\item all of the following apply (\textsc{continue}): + \begin{itemize} + \item evaluating $\econd$ in $\env$ is $\Normal(\condm, \envone)$; + \item $\mcond$ consists of a native Boolean for $\vb$ and an execution graph $\vgone$; + \item $\vb$ is equal to $\iswhile$; + \item evaluating $\vbody$ in $\envone$ as per \chapref{eval_block} is either \\ + $\Continuing(\vgtwo, \envtwo)$\ProseTerminateAs{\ReturningConfig, \ThrowingConfig, \ErrorConfig}; + \item evaluating $(\iswhile, \econd, \vbody)$ in $\envtwo$ as a loop is \\ + $\Continuing(\vgthree, \newenv)$\ProseTerminateAs{\ReturningConfig, \ThrowingConfig, \ErrorConfig}; + \item $\newg$ is the ordered composition of $\vgone$ and $\vgtwo$ with the $\aslctrl$ label + and then the ordered composition of the result and $\vgthree$ with the $\aslpo$ edge; + \item the result of the entire evaluation is $\Continuing(\newg, \newenv)$. + \end{itemize} +\end{itemize} + +\subsubsection{Formally} +The premise $\vb \neq \iswhile$ is $\True$ in the case of a \texttt{while} loop +and the loop condition $\ve$ not holding, which is exactly when we want the +loop to exit. The opposite holds for a \texttt{repeat} loop. +The negation of the condition is used to decide whether to continue the loop iteration. + +\begin{mathpar} +\inferrule[exit]{ + \evalexpr{\env, \econd} \evalarrow \Normal(\condm, \newenv) \OrAbnormal\\ + \condm \eqname (\nvbool(\vb), \newg)\\ + \vb \neq \iswhile +}{ + \evalloop{\env, \iswhile, \econd, \vbody} \evalarrow \Continuing(\newg, \newenv) +} +\end{mathpar} + +\begin{mathpar} +\inferrule[continue]{ + \evalexpr{\env, \econd} \evalarrow \Normal(\condm, \envone)\\ + \condm \eqname (\nvbool(\vb), \vgone)\\ + \vb = \iswhile\\ + \evalblock{\envone, \vbody} \evalarrow \Continuing(\vgtwo, \envtwo) \terminateas \ReturningConfig, \ThrowingConfig, \ErrorConfig\\ + \evalloop{\envtwo, \iswhile, \econd, \vbody} \evalarrow \Continuing(\vgthree, \newenv) \terminateas \ReturningConfig, \ThrowingConfig, \ErrorConfig\\ + \newg \eqdef \ordered{\ordered{\vgone}{\aslctrl}{\vgtwo}}{\aslpo}{\vgthree} +}{ + \evalloop{\env, \iswhile, \econd, \vbody} \evalarrow \Continuing(\newg, \newenv) +} +\end{mathpar} + +\section{Repeat Statements\label{sec:RepeatStatements}} +\subsection{Syntax} +\begin{flalign*} +\Nstmt \derivesinline\ & \Trepeat \parsesep \Nstmtlist \parsesep \Tuntil \parsesep \Nexpr \parsesep \Tsemicolon &\\ +|\ & \Tlooplimit \parsesep \Tlpar \parsesep \Nexpr \parsesep \Trpar \parsesep \Trepeat \parsesep \Nstmtlist \parsesep \Tuntil \parsesep \Nexpr \parsesep \Tsemicolon & +\end{flalign*} + +\subsection{Abstract Syntax} +\begin{flalign*} +\stmt \derives\ & \SRepeat(\overtext{\stmt}{loop body}, \overtext{\expr}{condition}, \overtext{\expr?}{loop limit}) & +\end{flalign*} + +\subsubsection{ASTRule.SRepeat} +\begin{mathpar} +\inferrule[no\_limit]{}{ + { + \begin{array}{r} + \buildstmt(\overname{\Nstmt(\Trepeat, \Nstmtlist, \Tuntil, \Nexpr, \Tsemicolon)}{\vparsednode}) + \astarrow\\ + \overname{\SRepeat(\astof{\vstmtlist}, \astof{\vexpr}, \None)}{\vastnode} + \end{array} + } +} +\end{mathpar} + +\begin{mathpar} +\inferrule[limit]{ + \buildexpr(\vlimitexpr) \astarrow \astversion{\vlimitexpr} +}{ + { + \begin{array}{r} + \buildstmt\left(\overname{\Nstmt\left( + \begin{array}{r} + \Tlooplimit, \Tlpar, \namednode{\vlimitexpr}{\Nexpr}, \Trpar, \Trepeat, \\ + \wrappedline\ \Nstmtlist, \Tuntil, \Nexpr, \Tsemicolon + \end{array} + \right)}{\vparsednode}\right) + \astarrow\\ + \overname{\SRepeat(\astof{\vstmtlist}, \astof{\vexpr}, \langle\astversion{\vlimitexpr}\rangle)}{\vastnode} + \end{array} + } +} +\end{mathpar} + +\subsection{Typing} +\subsubsection{TypingRule.SRepeat \label{sec:TypingRule.SRepeat}} +\subsubsection{Prose} +All of the following apply: +\begin{itemize} + \item $\vs$ is a \texttt{repeat} statement with statement block $\vsone$, + optional limit expression $\vlimitone$, and expression $\veone$, that is, $\SRepeat(\vsone, \veone, \vlimitone)$; + \item annotating $\vsone$ as a block statement in $\tenv$ yields $\vstwo$\ProseOrTypeError; + \item annotating the optional limit expression $\vlimitone$ via $\annotatelooplimit$ in $\tenv$ yields $\vlimittwo$\ProseOrTypeError; + \item annotating the right-hand-side expression $\veone$ in $\tenv$ yields $(\vt, \vetwo)$\ProseOrTypeError; + \item checking that $\vt$ \typesatisfies\ $\TBool$ in $\tenv$ yields $\True$\ProseOrTypeError; + \item $\news$ is a \texttt{repeat} statement with statement block $\vstwo$, optional limit expression $\vlimittwo$, + and condition expression $\vetwo$ and , that is, $\SRepeat(\vstwo, \vetwo, \vlimittwo)$; + \item $\newtenv$ is $\tenv$. +\end{itemize} +\subsubsection{Formally} +\begin{mathpar} +\inferrule{ + \annotateblock{\tenv, \vsone} \typearrow \vstwo \OrTypeError\\\\ + \annotatelooplimit(\tenv, \vlimitone) \typearrow \vlimittwo \OrTypeError\\\\ + \annotateexpr{\tenv, \veone} \typearrow (\vt, \vetwo) \OrTypeError\\\\ + \checktypesat(\tenv, \vt, \TBool) \typearrow \True \OrTypeError +}{ + \annotatestmt(\tenv, \overname{\SRepeat(\vsone, \veone, \vlimitone)}{\vs}) \typearrow + (\overname{\SRepeat(\vstwo, \vetwo, \vlimittwo)}{\news}, \overname{\tenv}{\newtenv}) +} +\end{mathpar} +\CodeSubsection{\SRepeatBegin}{\SRepeatEnd}{../Typing.ml} +\lrmcomment{This is related to \identr{FTVN}.} + +\subsection{Semantics} +\subsubsection{SemanticsRule.SRepeat \label{sec:SemanticsRule.SRepeat}} +\subsubsection{Example} +The specification: +\VerbatimInput{../tests/ASLSemanticsReference.t/SemanticsRule.SRepeat.asl} +prints +\begin{Verbatim} + 0 + 1 + 2 + 3 +\end{Verbatim} + +\subsubsection{Prose} +Evaluation of the statement $\vs$ in an environment $\env$ is +either \\ $\Returning((\vvs, \newg), \newenv)$ or an output configuration $D$ and all of the following apply: +\begin{itemize} + \item $\vs$ is a \texttt{repeat} statement, $\SRepeat(\ve, \vbody, \Ignore)$; + \item evaluating $\vbody$ in $\env$ as per \chapref{Bloccks} + yields $\Continuing(\vgone, \envone)$\ProseTerminateAs{\ReturningConfig,\ThrowingConfig,\ErrorConfig}; + \item evaluating the loop as per \secref{SemanticsRule.Loop} in an environment $\envone$, + with the arguments $\False$ (which conveys that this is a \texttt{repeat} statement), $\ve$, and $\vbody$ + results in $C$; + \item $\vgtwo$ is the ordered composition of $\vgone$ and $\vgtwo$ with the $\aslpo$ edge; + \item the output configuration $D$ is the output configuration $C$ with its execution graph + substituted with $\vgtwo$. +\end{itemize} +\subsubsection{Formally} +\begin{mathpar} +\inferrule{ + \evalblock{\env, \vbody} \evalarrow \Continuing(\vgone, \envone) \terminateas \ReturningConfig,\ThrowingConfig,\ErrorConfig\\\\ + \evalloop{\envone, \False, \ve, \vbody} \evalarrow C\\ + \vgtwo \eqdef \ordered{\vgone}{\aslpo}{\graphof{C}}\\ + D \eqdef \withgraph{C}{\vgtwo} +}{ + \evalstmt{\env, \overname{\SRepeat(\ve, \vbody, \Ignore)}{\vs}} \evalarrow D +} +\end{mathpar} +\CodeSubsection{\EvalSRepeatBegin}{\EvalSRepeatEnd}{../Interpreter.ml} + +\section{For Statements\label{sec:ForStatements}} +\subsection{Syntax} +\begin{flalign*} +\Nstmt \derivesinline\ & \Tfor \parsesep \Tidentifier \parsesep \Teq \parsesep \Nexpr \parsesep \Ndirection \parsesep + \Nexpr \parsesep \Tdo \parsesep \Nstmtlist \parsesep \Tend &\\ +\Ndirection \derivesinline\ & \Tto \;|\; \Tdownto & +\end{flalign*} + +\subsection{Abstract Syntax} +\begin{flalign*} +\fordirection \derives\ & \UP \;|\; \DOWN &\\ +\stmt \derives\ & \SFor\left\{ + \begin{array}{rcl} + \Forindexname &:& \identifier,\\ + \Forstarte &:& \expr,\\ + \Fordir &:& \fordirection,\\ + \Forende &:& \expr,\\ + \Forbody &:& \stmt,\\ + \Forlimit &:& \expr? + \end{array} + \right\} & +\end{flalign*} + +\subsubsection{ASTRule.SFor} +\begin{mathpar} +\inferrule{ + \buildexpr(\vstarte) \astarrow \astversion{\vstarte}\\ + \buildexpr(\vende) \astarrow \astversion{\vende}\\ +}{ + { + \begin{array}{r} + \buildstmt\left(\overname{\Nstmt\left( + \begin{array}{l} + \Tfor, \Tidentifier(\vindexname), \Teq, \namednode{\vstarte}{\Nexpr}, \Ndirection, \\ + \wrappedline\ \namednode{\vende}{\Nexpr}, \Tdo, \punnode{\Nstmtlist}, \Tend + \end{array} + \right)}{\vparsednode}\right) + \astarrow \\ + \overname{ + \SFor\left(\left\{ + \begin{array}{rcl} + \Forindexname &:& \vindexname\\ + \Forstarte &:& \astversion{\vstarte}\\ + \Forende &:& \astversion{\vende}\\ + \Forbody &:& \astof{\vstmtlist}\\ + \Forlimit &:& \None\\ + \end{array} + \right\}\right) + }{\vastnode} + \end{array} + } +} +\end{mathpar} + +\subsubsection{ASTRule.Direction \label{sec:ASTRule.Direction}} +\hypertarget{build-direction}{} +The function +\[ +\builddirection(\overname{\parsenode{\Ndirection}}{\vparsednode}) \;\aslto\; \overname{\fordirection}{\vastnode} +\] +transforms a parse node $\vparsednode$ into an AST node $\vastnode$. + +\begin{mathpar} +\inferrule[to]{}{ + \builddirection(\overname{\Ndirection(\Tto)}{\vparsednode}) \astarrow \overname{\UP}{\vastnode} +} +\end{mathpar} + +\begin{mathpar} +\inferrule[downto]{}{ + \builddirection(\overname{\Ndirection(\Tdownto)}{\vparsednode}) \astarrow \overname{\DOWN}{\vastnode} +} +\end{mathpar} + +\subsection{Typing} +\subsubsection{TypingRule.SFor \label{sec:TypingRule.SFor}} +\subsubsection{Prose} +All of the following apply: +\begin{itemize} + \item $\vs$ is a \texttt{for} statement with index $\vindexname$, + start expression $\vstarte$, + direction $\dir$, + end expression $\vende$, + body statement (block) $\vbody$, + and optional limit expression $\vlimit$, + that is, $\SFor\left\{\begin{array}{rcl} + \Forindexname &:& \vindexname\\ + \Forstarte &:& \vstarte\\ + \fordirection &:& \vdirection\\ + \Forende &:& \vende\\ + \Forbody &:& \vbody\\ + \Forlimit &:& \vlimit + \end{array}\right\}$; + \item annotating the right-hand-side expression $\vstarte$ in $\tenv$ yields \\ + $(\vstartt, \vstartep)$\ProseOrTypeError; + \item annotating the right-hand-side expression $\vende$ in $\tenv$ yields $(\vendt, \vendep)$\ProseOrTypeError; + \item annotating the optional loop limit expression $\vlimit$ via $\annotatelooplimit$ in $\tenv$ + yields $\vlimitp$\ProseOrTypeError; + \item obtaining the \underlyingtype\ of $\vstartt$ in $\tenv$ yields $\vstartstruct$\ProseOrTypeError; + \item obtaining the \underlyingtype\ of $\vendt$ in $\tenv$ yields $\vendstruct$\ProseOrTypeError; + \item applying $\getforconstraints$ to $\vstartstruct$, $\vendstruct$, + $\vstartep$, $\vendep$, and $\dir$ in $\tenv$, + to obtain the constraints on the loop index $\vindexname$, + yields $\cs$\ProseOrTypeError; + \item $\tty$ is the integer type with constraints $\cs$; + \item checking that $\vindexname$ is not already declared in $\tenv$ yields $\True$\ProseOrTypeError; + \item adding $\vindexname$ as a local immutable variable with type $\tty$ to $\tenv$ yields $\tenvp$; + \item annotating $\vbody$ as a block statement in $\tenvp$ yields $\vbodyp$\ProseOrTypeError; + \item $\news$ is the \texttt{for} statement with index $\vindexname$, + start expression $\vstartep$, direction $\dir$, + end expression $\vendep$, + body statement (block) $\vbodyp$, and + optional limit expression $\vlimit$; + \item $\newtenv$ is $\tenv$ (notice that this means $\vindexname$ is only declared for annotating $\vbodyp$ but then goes + out of scope). +\end{itemize} +\subsubsection{Formally} +\begin{mathpar} +\inferrule{ + \annotateexpr{\tenv, \vstarte} \typearrow (\vstartt, \vstartep) \OrTypeError\\\\ + \annotateexpr{\tenv, \vende} \typearrow (\vendt, \vendep) \OrTypeError\\\\ + \annotatelooplimit(\tenv, \vlimit) \typearrow \vlimitp \OrTypeError\\\\ + \makeanonymous(\tenv, \vstartt) \typearrow \vstartstruct \OrTypeError\\\\ + \makeanonymous(\tenv, \vendt) \typearrow \vendstruct \OrTypeError\\\\ + { + \begin{array}{r} + \getforconstraints(\tenv, \vstartstruct, \vendstruct, \vstartep, \vendep, \dir) \typearrow \\ + \cs \OrTypeError + \end{array} + }\\\\ + \tty \eqdef \TInt(\cs)\\ + \checkvarnotinenv{\tenv, \vindexname} \typearrow \True \OrTypeError\\\\ + \addlocal(\tenv, \tty, \vindexname, \LDKLet) \typearrow \tenvp\\ + \annotateblock{\tenvp, \vbody} \typearrow \vbodyp \OrTypeError +}{ + { + \begin{array}{r} + \annotatestmt\left(\tenv, \overname{\SFor\left\{\begin{array}{rcl} + \Forindexname &:& \vindexname\\ + \Forstarte &:& \vstarte\\ + \fordirection &:& \vdirection\\ + \Forende &:& \vende\\ + \Forbody &:& \vbody\\ + \Forlimit &:& \vlimit + \end{array}\right\}}{\vs}\right) \typearrow \\ + \left(\overname{\SFor\left\{\begin{array}{rcl} + \Forindexname &:& \vindexname\\ + \Forstarte &:& \vstartep\\ + \fordirection &:& \vdirection\\ + \Forende &:& \vendep\\ + \Forbody &:& \vbodyp\\ + \Forlimit &:& \vlimitp + \end{array}\right\}}{\news}, \overname{\tenv}{\newtenv}\right) +\end{array} + } +} +\end{mathpar} +\CodeSubsection{\SForBegin}{\SForEnd}{../Typing.ml} +\lrmcomment{This is related to \identr{SSBD}, \identr{ZSND}, \identr{VTJW}.} + +\subsubsection{TypingRule.SForConstraints\label{sec:TypingRule.SForConstraints}} +\hypertarget{def-getforconstraints}{} +The function +\[ + \getforconstraints( + \overname{\staticenvs}{\tenv} \aslsep + \overname{\ty}{\structone} \aslsep + \overname{\ty}{\structtwo} \aslsep + \overname{\expr}{\veonep} \aslsep + \overname{\expr}{\vetwop} \aslsep + \overname{\dir}{\dir} + ) \aslto + \overname{\intconstraints}{\vis} \cup\ \overname{\TTypeError}{\TypeErrorConfig} +\] +infers the integer constraints for a \texttt{for} loop index variable from the following: +\begin{itemize} + \item the \wellconstrainedversion\ of the type of the start expression --- $\structone$ + \item the \wellconstrainedversion\ of the type of the end expression --- $\structtwo$ + \item the annotated start expression --- $\veonep$ + \item the annotated end expression --- $\vetwop$ + \item the loop direction --- $\dir$ +\end{itemize} +The result is $\vis$. +\ProseOtherwiseTypeError + +\subsubsection{Prose} +One of the following applies: +\begin{itemize} + \item All of the following apply (\textsc{not\_integers}): + \begin{itemize} + \item at least one of $\structone$ and $\structtwo$ is not an integer type; + \item the result is a type error indicating that the start expression and end expression of \texttt{for} loops + must have the \structure\ of integer types. + \end{itemize} + + \item All of the following apply (\textsc{unconstrained}): + \begin{itemize} + \item both of $\structone$ and $\structtwo$ are integer types; + \item at least one of $\structone$ and $\structtwo$ is the unconstrained integer type; + \item define $\vis$ as $\unconstrained$. + \end{itemize} + + \item All of the following apply (\textsc{well\_constrained}): + \begin{itemize} + \item both of $\structone$ and $\structtwo$ are integer types; + \item neither $\structone$ nor $\structtwo$ is the unconstrained integer type; + \item symbolically simplifying $\veonep$ in $\tenv$ yields $\eonen$\ProseOrTypeError; + \item symbolically simplifying $\vetwop$ in $\tenv$ yields $\etwon$\ProseOrTypeError; + \item define $\icsup$ as the single range constraint with expressions $\eonen$ and $\etwon$; + \item define $\icsdown$ as the single range constraint with expressions $\etwon$ and $\eonen$; + \item define $\vis$ as $\icsup$ if $\dir$ is $\UP$ and $\icsdown$ otherwise. + \end{itemize} +\end{itemize} + +\subsubsection{Formally} +\begin{mathpar} +\inferrule[not\_integers]{ + \astlabel(\structone) \neq \TInt \lor \astlabel(\structtwo) \neq \TInt +}{ + \getforconstraints(\tenv, \structone, \structtwo, \veonep, \vetwop, \dir) \typearrow \TypeErrorVal{\RequireIntegerForLoopBounds} +} +\end{mathpar} + +\begin{mathpar} +\inferrule[unconstrained]{ + \astlabel(\structone) = \TInt \land \astlabel(\structtwo) = \TInt\\ + \structone = \unconstrainedinteger \lor \structtwo = \unconstrainedinteger\\ +}{ + \getforconstraints(\tenv, \structone, \structtwo, \veonep, \vetwop, \dir) \typearrow \overname{\unconstrained}{\vis} +} +\end{mathpar} + +\begin{mathpar} +\inferrule[well\_constrained]{ + \astlabel(\structone) = \TInt \land \astlabel(\structtwo) = \TInt\\ + \structone \neq \unconstrainedinteger \land \structtwo \neq \unconstrainedinteger\\ + \normalize(\tenv, \veonep) \typearrow \eonen \OrTypeError\\\\ + \normalize(\tenv, \vetwop) \typearrow \etwon \OrTypeError\\\\ + \icsup \eqdef \wellconstrained([\ConstraintRange(\eonen, \etwon)])\\ + \icsdown \eqdef \wellconstrained([\ConstraintRange(\etwon, \eonen)])\\ + \vis \eqdef \choice{\dir=\UP}{\icsup}{\icsdown} +}{ + \getforconstraints(\tenv, \structone, \structtwo, \veonep, \vetwop, \dir) \typearrow \vis +} +\end{mathpar} + +\subsection{Semantics} +\subsubsection{SemanticsRule.SFor\label{sec:SemanticsRule.SFor}} +Evaluating a \texttt{for} statement involves introducing an index variable to the +environment. The type system ensures, via TypingRule.SFor, that the index variable +is not already declared in the scope of the subprogram containing the \texttt{for} +statement. + +\subsubsection{Example} +The specification: +\VerbatimInput{../tests/ASLSemanticsReference.t/SemanticsRule.SFor.asl} +prints +\begin{Verbatim} + 0 + 1 + 2 + 3 +\end{Verbatim} + +\subsubsection{Prose} +All of the following apply: +\begin{itemize} + \item $\vs$ is a \texttt{for} statement, $\SFor\left\{\begin{array}{rcl} + \Forindexname &:& \vindexname\\ + \Forstarte &:& \vstarte\\ + \fordirection &:& \vdirection\\ + \Forende &:& \vende\\ + \Forbody &:& \vbody\\ + \Forlimit &:& \Ignore + \end{array}\right\}$; + \item evaluating the side-effect-free expression $\veone$ in $\env$ is either + $\Normal(\vvone, \vgone)$\ProseOrError; + \item evaluating the side-effect-free expression $\vetwo$ in $\env$ is either + $\Normal(\vvtwo, \vgtwo)$\ProseOrError; + \item declaring the local identifier $\vindexname$ in $\env$ with value $\vvone$ is $(\vgthree, \envone)$; + \item evaluating the \texttt{for} loop with arguments $(\vindexname, \veone, \dir, \vetwo, \vs)$ in $\envone$, + as per \nameref{sec:SemanticsRule.SFor} is $\Normal(\vgfour, \envtwo)$\ProseOrAbnormal; + \item removing the local $\vindexname$ from $\envtwo$ is $\envthree$; + \item $\newg$ is formed as follows: taking the parallel composition of $\vgone$ and $\vgtwo$, + then taking the ordered composition of the result with the $\asldata$ edge, + and finally taking the ordered composition of the result with the $\aslpo$ edges; + \item $\newenv$ is $\envthree$. + \item the result of the entire evaluation is $\Continuing(\newg, \newenv)$. +\end{itemize} +\subsubsection{Formally} +Recall that the expressions for the \texttt{for} loop range are side-effect-free, +which is why they are evaluated via the rule for evaluating side-effect-free expressions. +\begin{mathpar} +\inferrule{ + \evalexprsef{\env, \vstarte} \evalarrow \Normal(\vstartv, \vgone) \terminateas \ErrorConfig\\ + \evalexprsef{\env, \vende} \evalarrow \Normal(\vendv, \vgtwo) \terminateas \ErrorConfig\\ + \declarelocalidentifier(\env, \vindexname, \vendv) \evalarrow (\vgthree,\envone)\\ + \evalfor{\envone, \vindexname, \vstartv, \dir, \vendv, \vbody} \evalarrow \Normal(\vgfour, \envtwo) \OrAbnormal\\ + \removelocal(\envtwo, \vindexname) \evalarrow \envthree\\ + \newg \eqdef \ordered{(\vgone \parallelcomp \vgtwo)}{\asldata}{ \ordered{\vgthree}{\aslpo}{\vgfour} }\\ + \newenv \eqdef \envthree +}{ + { + \begin{array}{r} + \evalstmt{\env, + \overname{ + \SFor\left\{\begin{array}{rcl} + \Forindexname &:& \vindexname\\ + \Forstarte &:& \vstarte\\ + \fordirection &:& \vdirection\\ + \Forende &:& \vende\\ + \Forbody &:& \vbody\\ + \Forlimit &:& \Ignore\\ + \end{array}\right\}}{\vs}} \evalarrow \\ \Continuing(\newg, \newenv) + \end{array} + } +} +\end{mathpar} +\CodeSubsection{\EvalSForBegin}{\EvalSForEnd}{../Interpreter.ml} + +\subsubsection{SemanticsRule.EvalFor\label{sec:SemanticsRule.EvalFor}} +The relation +\hypertarget{def-evalfor}{} +\[ + \evalfor{\overname{\envs}{\env} \aslsep \overname{\Identifiers}{\vindexname} \aslsep \overname{\tint}{\vstart} + \aslsep \overname{\{\UP, \DOWN\}}{\dir} \aslsep \overname{\tint}{\vend} \aslsep \overname{\stmt}{\vbody}} + \;\aslrel\; + \left( + \begin{array}{cl} + \overname{\TReturning}{\ReturningConfig} & \cup\\ + \overname{\TContinuing}{\ContinuingConfig} & \cup\\ + \overname{\TThrowing}{\ThrowingConfig} & \cup \\ + \overname{\TError}{\ErrorConfig} & + \end{array} + \right) +\] +evaluates the \texttt{for} loop with the index variable $\vindexname$ starting from the value +$\vstart$ going in the direction given by $\dir$ until the value given by $\vend$, +executing $\vbody$ on each iteration. +% +The evaluation utilizes two helper relations: $\evalforstep$ and $\evalforloop$. + +The helper relation +\[ + \evalforstep( + \overname{\envs}{\env}, + \overname{\Identifiers}{\vindexname}, + \overname{\tint}{\vstart}, + \overname{\{\UP,\DOWN\}}{\dir}) + \;\aslrel\; + ((\overname{\tint}{\vstep} \times \overname{\envs}{\newenv}) \times \overname{\XGraphs}{\newg}) +\] +either increments or decrements the index variable, +returning the new value of the index variable, the modified environment, +and the resulting execution graph. + +The helper relation +\[ + \evalforloop(\overname{ + \envs}{\env}, + \overname{\Identifiers}{\vindexname}, + \overname{\tint}{\vstart}, + \overname{\{\UP,\DOWN\}}{\dir}, + \overname{\tint}{\vend}, + \overname{\stmt}{\vbody}) \;\aslrel\; + \left( + \begin{array}{cl} + \overname{\TContinuing}{\Continuing(\newg, \newenv)} & \cup\\ + \overname{\TReturning}{\ReturningConfig} & \cup\\ + \overname{\TThrowing}{\ThrowingConfig} & \cup \\ + \overname{\TError}{\ErrorConfig} & + \end{array} + \right) +\] +executes one iteration of the loop body and then uses $\texttt{eval\_for}$ to execute the remaining +iterations. + +\subsection{Prose} +\subsubsection{Stepping the Index Variable} +All of the following apply: +\begin{itemize} + \item $\opfordir$ is either $\PLUS$ when $\dir$ is $\UP$ or $\MINUS$ when $\dir$ is $\DOWN$; + \item reading $\vstart$ into the identifier $\vindexname$ gives $\vgone$; + \item applying the binary operator $\opfordir$ to $\vstart$ and the native integer for $1$ is $\vstep$; + \item the execution graph for writing $\vstep$ into the identifier $\vindexname$ gives $\vgtwo$; + \item updating the local component of the dynamic environment of $\env$ by binding \\ $\vindexname$ to $\vstep$ + gives $\newenv$; + \item $\newg$ is the ordered composition of $\vgone$ and $\vgtwo$ with the $\asldata$ edge. +\end{itemize} + +\subsubsection{Running the Loop Body} +All of the following apply: +\begin{itemize} + \item evaluating $\vbody$ as a block statement (see \chapref{eval_block}) in $\env$ + is \\ $\Continuing(\vgone, \envone)$\ProseTerminateAs{\ReturningConfig, \ThrowingConfig, \ErrorConfig}; + \item stepping the index $\vindexname$ with $\vstart$ and the direction $\dir$ in $\envone$, + that is, $\evalforstep(\envone, \vindexname, \vstart, \dir)$ gives $((\vstep, \envtwo), \vgtwo)$; + \item evaluating the \texttt{for} loop with $(\vindexname, \vstep, \dir, \vend, \vbody)$ + in $\envtwo$ results in a continuing configuration $\Continuing(\vgthree, \newenv)$\ProseTerminateAs{\ReturningConfig, \ThrowingConfig, \ErrorConfig}; + \item $\newg$ is the ordered composition of $\vgone$, $\vgtwo$, and $\vgthree$ with the $\aslpo$ + edge. +\end{itemize} + +\subsubsection{Overall Evaluation} +\subsubsection{Example} +The specification: +\VerbatimInput{../tests/ASLSemanticsReference.t/SemanticsRule.For.asl} +does not result in any assertion error, and the specification terminates with exit-code $0$. + +Evaluating $(\vindexname, \vstart, \dir, \vend, \vbody)$ in $\env$ is either +a continuing configuration $\Continuing(\newg, \newenv)$ or a returning configuration +(in case the body of the loop results in an early return) +or an abnormal configuration, +and All of the following apply: +\begin{itemize} + \item $\compfordir$ is either $\LT$ when $\dir$ is $\UP$ or $\GT$ when $\dir$ is $\DOWN$; + \item reading $\vstart$ into the identifier $\vindexname$ gives $\vgone$; + \item One of the following applies: + \begin{itemize} + \item All of the following apply (\textsc{return}): + \begin{itemize} + \item using $\compfordir$ to compare $\vend$ to $\vstart$ gives the native Boolean for $\True$; + \item $\newg$ is $\vgone$; + \item $\newenv$ is $\env$; + \item the result of the entire evaluation is $\Continuing(\newg, \newenv)$. + \end{itemize} + \item All of the following apply (\textsc{continue}): + \begin{itemize} + \item using $\compfordir$ to compare $\vend$ to $\vstart$ gives the native Boolean for $\False$; + \item evaluating the loop body via $\evalforloop$ with \\ $(\vindexname, \vstart, \dir, \vend, \vbody)$ + in $\env$ is \\ $\Continuing(\vgtwo, \newenv)$\ProseTerminateAs{\ReturningConfig, \ThrowingConfig, \ErrorConfig}; + \item $\newg$ is the ordered composition of $\vgone$ and $\vgtwo$ with the $\aslctrl$ label. + \end{itemize} + \end{itemize} +\end{itemize} + +\subsubsection{Formally} +Advancing the loop counter one step towards the end of its range is achieved via the following rule: +\begin{mathpar} +\inferrule{ + \opfordir \eqdef \choice{\dir = \UP}{\PLUS}{\MINUS}\\ + \readidentifier(\vindexname, \vstart) \evalarrow \vgone\\ + \binoprel(\opfordir, \vstart, \nvint(1)) \evalarrow \vstep\\ + \writeidentifier(\vindex, \vstep) \evalarrow \vgtwo\\ + \env \eqname (\tenv, \denv)\\ + \newenv \eqdef (\tenv, (G^\denv, L^\denv[\vindexname\mapsto\vstep]))\\ + \newg \eqdef \ordered{\vgone}{\asldata}{\vgtwo} +}{ + \evalforstep(\env, \vindexname, \vstart, \dir) \evalarrow ((\vstep, \newenv), \newg) +} +\end{mathpar} + +Running the loop body is achieved via the following rule: +\begin{mathpar} +\inferrule{ + \evalblock{\env, \vbody} \evalarrow \Continuing(\vgone, \envone) \terminateas \ReturningConfig, \ThrowingConfig, \ErrorConfig\\ + \evalforstep(\envone, \vindexname, \vstart, \dir) \evalarrow ((\vstep, \envtwo), \vgtwo)\\ + \evalfor{\envtwo, \vindexname, \vstep, \dir, \vend, \vbody} \evalarrow \Continuing(\vgthree, \newenv) \terminateas \ReturningConfig, \ThrowingConfig, \ErrorConfig\\ + \newg \eqdef \ordered{\ordered{\vgone}{\aslpo}{\vgtwo}}{\aslpo}{\vgthree} +}{ + \evalforloop(\env, \vindexname, \vstart, \dir, \vend, \vbody) \evalarrow \Continuing(\newg, \newenv) +} +\end{mathpar} + +Finally, the rules for evaluating a \texttt{for} loop utilize both $\evalforstep$ +and $\evalforloop$ (the latter in a mutually recursive manner): +\begin{mathpar} +\inferrule[return]{ + \compfordir \eqdef \choice{\dir = \UP}{\LT}{\GT}\\ + \readidentifier(\vindexname, \vstart) \evalarrow \vgone\\ + \binoprel(\compfordir, \vend, \vstart) \evalarrow \nvbool(\True)\\ + \newg \eqdef \vgone\\ + \newenv = \env +} +{ + \evalfor{\env, \vindexname, \vstart, \dir, \vend, \vbody} \evalarrow \Continuing(\newg, \newenv) +} +\end{mathpar} + +\begin{mathpar} +\inferrule[continue]{ + \compfordir \eqdef \choice{\dir = \UP}{\LT}{\GT}\\ + \readidentifier(\vindexname, \vstart) \evalarrow \vgone\\ + \binoprel(\compfordir, \vend, \vstart) \evalarrow \nvint(\False)\\ + \evalforloop(\env, \vindexname, \vstart, \dir, \vend, \vbody) \evalarrow \\ + \Continuing(\vgtwo, \newenv) \terminateas \ReturningConfig, \ThrowingConfig, \ErrorConfig\\\\ + \newg \eqdef \ordered{\vgone}{\aslctrl}{\vgtwo} +}{ + \evalfor{\env, \vindexname, \vstart, \dir, \vend, \vbody} \evalarrow \Continuing(\newg, \newenv) +} +\end{mathpar} +\CodeSubsection{\EvalForBegin}{\EvalForEnd}{../Interpreter.ml} + +\section{Throw Statements\label{sec:ThrowStatements}} +\subsection{Syntax} +\begin{flalign*} +\Nstmt \derivesinline\ & \Tthrow \parsesep \Nexpr \parsesep \Tsemicolon &\\ +|\ & \Tthrow \parsesep \Tsemicolon & +\end{flalign*} + +\subsection{Abstract Syntax} +\begin{flalign*} +\stmt \derives\ & \SThrow(\expr?) & +\end{flalign*} + +\subsubsection{ASTRule.SThrow} +\begin{mathpar} +\inferrule[throw\_some]{}{ + \buildstmt(\overname{\Nstmt(\Tthrow, \Nexpr, \Tsemicolon)}{\vparsednode}) + \astarrow + \overname{\SThrow(\langle\astof{\vexpr}\rangle)}{\vastnode} +} +\end{mathpar} + +\begin{mathpar} +\inferrule[throw\_none]{}{ + \buildstmt(\overname{\Nstmt(\Tthrow, \Tsemicolon)}{\vparsednode}) + \astarrow + \overname{\SThrow(\None)}{\vastnode} +} +\end{mathpar} + +\subsection{Typing} +\subsubsection{TypingRule.SThrow\label{sec:TypingRule.SThrow}} +\subsubsection{Prose} +One of the following applies: +\begin{itemize} + \item All of the following apply (\textsc{none}): + \begin{itemize} + \item $\vs$ is a throw statement with no expression, that is, $\SThrow(\None)$; + \item $\news$ is $\vs$; + \item $\newtenv$ is $\tenv$. + \end{itemize} + + \item All of the following apply (\textsc{some}): + \begin{itemize} + \item $\vs$ is a throw statement with expression $\ve$, that is, $\SThrow(\langle\ve\rangle)$; + \item annotating the right-hand-side expression $\ve$ in $\tenv$ yields $(\vte, \vep)$\ProseOrTypeError; + \item checking that $\vte$ has the structure of an exception type yields $\True$\ProseOrTypeError; + \item $\news$ is a throw statement with expression $\vep$ and type $\vte$, that is, \\ + $\SThrow(\langle (\vep, \vte) \rangle)$; + \item $\newtenv$ is $\tenv$. + \end{itemize} +\end{itemize} +\subsubsection{Formally} +\begin{mathpar} +\inferrule[none]{}{ + \annotatestmt(\tenv, \overname{\SThrow(\None)}{\vs}) \typearrow (\overname{\SThrow(\None)}{\news}, \overname{\tenv}{\newtenv}) +} +\end{mathpar} +\lrmcomment{Note that \identr{BRCJ} is done in~\cite[SemanticsRule.TopLevel]{ASLSemanticsReference}.} + +\begin{mathpar} +\inferrule[some]{ + \annotateexpr{\tenv, \ve} \typearrow (\vte, \vep) \OrTypeError\\\\ + \checkstructurelabel(\tenv, \vte, \TException) \typearrow \True \OrTypeError +}{ + \annotatestmt(\tenv, \overname{\SThrow(\langle\ve\rangle)}{\vs}) \typearrow + (\overname{\SThrow(\langle (\vep, \vte) \rangle)}{\news}, \overname{\tenv}{\newtenv}) +} +\end{mathpar} +\lrmcomment{This is related to \identr{NXRC}.} +\CodeSubsection{\SThrowBegin}{\SThrowEnd}{../Typing.ml} + +\subsection{Semantics} +subsubsection{SemanticsRule.SThrow\label{sec:SemanticsRule.SThrow}} +\subsubsection{Example (Throwing Without an Exception)} +The specification: +\VerbatimInput{../tests/ASLSemanticsReference.t/SemanticsRule.SThrowNone.asl} +throws a \texttt{MyException} exception. + +\subsubsection{Example (Throwing a Typed Exception)} +The specification: +\VerbatimInput{../tests/ASLSemanticsReference.t/SemanticsRule.SThrowSomeTyped.asl} +terminates successfully. That is, no dynamic error occurs. + +\subsubsection{Prose} +One of the following applies: +\begin{itemize} + \item All of the following apply (\textsc{none}): + \begin{itemize} + \item $\vs$ is a \texttt{throw} statement that does not provide an expression, $\SThrow(\None)$; + \item $\newenv$ is $\env$; + \item $\vex$ is $\None$; + \item $\newg$ is the empty graph; + \item an exception is thrown with $\newenv$. + \end{itemize} + + \item All of the following apply (\textsc{some}): + \begin{itemize} + \item $\vs$ is a \texttt{throw} statement that provides an expression and a type, \\ + $\SThrow(\langle(\ve, \vt)\rangle)$; + \item evaluating $\ve$ in $\env$ is $\Normal((\vv, \vgone), \newenv)$\ProseOrAbnormal; + \item $\name$ is a fresh identifier (which conceptually holds the exception value); + \item $\vgtwo$ is a Write Effect to $\name$; + \item $\newg$ is the ordered composition of $\vgone$ and $\vgtwo$ with the $\asldata$ edge; + \item $\vex$ consists of the exception value $\vv$, the name of the variable holding it --- + $\name$, and the type annotation for the exception --- $\vt$; + \item the result of the entire evaluation is $\Throwing((\vex, \newg), \env)$. + \end{itemize} +\end{itemize} +\subsubsection{Formally} +\begin{mathpar} +\inferrule[none]{} +{ + \evalstmt{\env, \SThrow(\None)} \evalarrow \Throwing((\None, \emptygraph), \env) +} +\end{mathpar} +\begin{mathpar} +\inferrule[some]{ + \evalexpr{\env, \ve} \evalarrow \Normal((\vv, \vgone), \newenv) \OrAbnormal\\ + \name\in\Identifiers \text{ is fresh}\\ + \vgtwo \eqdef \WriteEffect(\name)\\ + \newg \eqdef \ordered{\vgone}{\asldata}{\vgtwo}\\ + \vex \eqdef \langle(\valuereadfrom(\vv, \name),\vt)\rangle +}{ + \evalstmt{\env, \SThrow(\langle(\ve, \vt)\rangle)} \evalarrow + \Throwing((\vex, \newg), \newenv) +} +\end{mathpar} +\CodeSubsection{\EvalSThrowBegin}{\EvalSThrowEnd}{../Interpreter.ml} + +\section{Try Statements\label{sec:TryStatements}} +\subsection{Syntax} +\begin{flalign*} +\Nstmt \derivesinline\ & \Ttry \parsesep \Nstmtlist \parsesep \Tcatch \parsesep \nonemptylist{\Ncatcher} \parsesep \Notherwiseopt \parsesep \Tend & +\end{flalign*} + +\subsection{Abstract Syntax} +\begin{flalign*} +\stmt \derives\ & \STry(\stmt, \catcher^*, \overtext{\stmt?}{otherwise}) & +\end{flalign*} + +\subsubsection{ASTRule.STry} +\begin{mathpar} +\inferrule{ + \buildlist[\Ncatcher] \astarrow \astversion{\vcatcherlist} +}{ + { + \begin{array}{r} + \buildstmt\left(\overname{\Nstmt\left( + \begin{array}{r} + \Ttry, \Nstmtlist, \Tcatch, \\ + \wrappedline\ \namednode{\vcatcherlist}{\nonemptylist{\Ncatcher}}, \\ + \wrappedline\ \Notherwiseopt, \Tend + \end{array} + \right)}{\vparsednode}\right) + \astarrow \\ + \overname{\STry(\astof{\vstmtlist}, \astversion{\vcatcherlist}, \astof{\votherwiseopt})}{\vastnode} +\end{array} +} +} +\end{mathpar} + +\subsection{Typing} +\subsubsection{TypingRule.STry \label{sec:TypingRule.STry}} +\subsubsection{Prose} +All of the following apply: +\begin{itemize} + \item $\vs$ is a try statement with statement $\vsp$, list of catchers $\catchers$ and an \optional\ \texttt{otherwise} block; + \item annotating the statement $\vsp$ as a block statement yields $\vspp$\ProseOrTypeError; + \item annotating each catcher $\catchers[\vi]$, for each $\vi$ in $\listrange(\catchers)$ in $\tenv$ yields $\vc\_\vi$\ProseOrTypeError; + \item $\catchersp$ is the list of annotated catchers $\vc\_\vi$ for each $\vi\in\listrange(\catchers)$; + \item One of the following applies: + \begin{itemize} + \item All of the following apply (\textsc{no\_otherwise}): + \begin{itemize} + \item there is no \texttt{otherwise} statement; + \item $\news$ is a try statement with statement $\vspp$, list catchers $\catchersp$ and no \texttt{otherwise} statement, + that is \\ + $\STry(\vspp, \catchersp, \None)$; + \end{itemize} + + \item All of the following apply (\textsc{otherwise}): + \begin{itemize} + \item there is an \texttt{otherwise} statement $\otherwise$; + \item annotating the statement $\otherwise$ as a block statement in $\tenv$ yields $\otherwisep$\ProseOrTypeError; + \item $\news$ is a try statement with statement $\vspp$, list catchers $\catchersp$ and \texttt{otherwise} statement + $\otherwisep$, that is \\ + $\STry(\vspp, \catchersp, \langle\otherwisep\rangle)$; + \end{itemize} + \end{itemize} + \item $\newtenv$ is $\tenv$. +\end{itemize} +\subsubsection{Formally} +\begin{mathpar} +\inferrule[no\_otherwise]{ + \annotateblock{\tenv, \vsp} \typearrow \vspp \OrTypeError\\\\ + \vi\in\listrange(\catchers): \annotatecatcher{\tenv, \catchers[\vi]} \typearrow \vc_\vi \OrTypeError\\\\ + \catchersp \eqdef [\vi\in\listrange(\catchers) : \vc_\vi]\\\\ + \commonprefixline\\\\ + \news \eqdef \STry(\vspp, \catchersp, \None) +}{ + \annotatestmt(\tenv, \overname{\STry(\vsp, \catchers, \None)}{\vs}) \typearrow (\news, \overname{\tenv}{\newtenv}) +} +\and +\inferrule[otherwise]{ + \annotateblock{\tenv, \vsp} \typearrow \vspp \OrTypeError\\\\ + \vi\in\listrange(\catchers): \annotatecatcher{\tenv, \catchers[\vi]} \typearrow \vc_\vi \OrTypeError\\\\ + \catchersp \eqdef [\vi\in\listrange(\catchers) : \vc_\vi]\\\\ + \commonprefixline\\\\ + \annotateblock{\tenv, \otherwise} \typearrow \otherwisep \OrTypeError\\\\ + \news \eqdef \STry(\vspp, \catchersp, \otherwise') +}{ + \annotatestmt(\tenv, \overname{\STry(\vsp, \catchers, \langle\otherwise\rangle)}{\vs}) \typearrow (\news, \overname{\tenv}{\newtenv}) +} +\end{mathpar} +\CodeSubsection{\STryBegin}{\STryEnd}{../Typing.ml} +\lrmcomment{This is related to \identr{WVXS}.} + +\subsection{Semantics} +\subsubsection{SemanticsRule.STry \label{sec:SemanticsRule.STry}} +\subsubsection{Example} +The specification: +\VerbatimInput{../tests/ASLSemanticsReference.t/SemanticsRule.STry.asl} +does not result in any Assertion error, and the specification terminates with the exit code $0$. + +\subsubsection{Prose} +All of the following apply: +\begin{itemize} + \item $\vs$ is a \texttt{try} statement, $\STry(\vs, \catchers, \otherwiseopt)$; + \item evaluating $\vsone$ in $\env$ as per \chapref{Blocks} + is a non-abnormal (that is, either $\Normal$ or $\Continuing$) configuration $\sm$\ProseOrAbnormal; + \item evaluating $(\catchers, \otherwiseopt, \sm)$ as per \chapref{CatchingExceptions} + is $C$, which is the result of the entire evaluation. +\end{itemize} +\subsubsection{Formally} +\begin{mathpar} +\inferrule{ + \evalblock{\env, \vsone} \evalarrow \sm \OrAbnormal\\ + \evalcatchers{\env, \catchers, \otherwiseopt, \sm} \evalarrow C +}{ + \evalstmt{\env, \STry(\vsone, \catchers, \otherwiseopt)} \evalarrow C +} +\end{mathpar} +\CodeSubsection{\EvalSTryBegin}{\EvalSTryEnd}{../Interpreter.ml} + +\section{Return Statements\label{sec:ReturnStatements}} +\subsection{Syntax} +\begin{flalign*} +\Nstmt \derivesinline\ & \Treturn \parsesep \option{\Nexpr} \parsesep \Tsemicolon & +\end{flalign*} + +\subsection{Abstract Syntax} +\begin{flalign*} + \stmt \derives\ & \SReturn(\expr?) & +\end{flalign*} + +\subsubsection{ASTRule.SReturn} +\begin{mathpar} +\inferrule{ + \buildoption[\Nexpr](\vexpr) \astarrow \astversion{\vexpr} +}{ + \buildstmt(\overname{\Nstmt(\Treturn, \namednode{\vexpr}{\option{\Nexpr}}, \Tsemicolon)}{\vparsednode}) + \astarrow + \overname{\SReturn(\astversion{\vexpr})}{\vastnode} +} +\end{mathpar} + +\subsection{Typing} +\subsubsection{TypingRule.SReturn\label{sec:TypingRule.SReturn}} +\subsubsection{Prose} +One of the following applies: +\begin{itemize} + \item All of the following apply (\textsc{error}): + \begin{itemize} + \item $\vs$ is a \texttt{return} statement with an optional expression $\veopt$, that is, \\ + $\SReturn(\veopt)$; + \item the condition that $\veopt$ is $\None$ if and only if the enclosing subprogram does not have a return type + (that is, $\returntype$ in the local static environment is $\None$) does not hold; + \item the result is an error indicating the mismatch between the declared (existence of the) return type + and the (existence of the) return expression. + \end{itemize} + + \item All of the following apply (\textsc{none}): + \begin{itemize} + \item $\vs$ is a \texttt{return} statement with no expression, that is, $\SReturn(\None)$; + \item the enclosing subprogram does not have a \texttt{return} type (it is either a setter + or a procedure); + \item $\news$ is a \texttt{return} statement with no expression, that is, $\SReturn(\None)$; + \item $\newtenv$ is $\tenv$. + \end{itemize} + + \item All of the following apply (\textsc{some}): + \begin{itemize} + \item $\vs$ is a \texttt{return} statement with an expression $\ve$, that is, $\SReturn(\langle \vep \rangle)$; + \item the enclosing subprogram has a return type $\vt$; + \item annotating the right-hand-side expression $\ve$ in $\tenv$ yields $(\tep,\vep)$\ProseOrTypeError; + \item checking whether $\vtep$ \typesatisfies\ $\vt$ in $\tenv$ yields $\True$\ProseOrTypeError; + \item $\news$ is a \texttt{return} statement with value $\vep$, that is, $\SReturn(\langle \vep \rangle)$; + \item $\newtenv$ is $\tenv$. + \end{itemize} +\end{itemize} +\subsubsection{Formally} +\begin{mathpar} +\inferrule[error]{ + L^\tenv.\returntype \neq \veopt +}{ + \annotatestmt(\tenv, \overname{\SReturn(\veopt)}{\vs}) \typearrow \TypeErrorVal{InvalidReturnStmt} +} +\end{mathpar} + +\begin{mathpar} +\inferrule[none]{ + L^\tenv.\returntype = \None +}{ + \annotatestmt(\tenv, \overname{\SReturn(\None)}{\vs}) \typearrow (\overname{\SReturn(\None)}{\news}, \overname{\tenv}{\newtenv}) +} +\end{mathpar} + +\begin{mathpar} +\inferrule[some]{ + L^\tenv.\returntype = \langle \vt \rangle\\ + \annotateexpr{\tenv, \ve} \typearrow (\vtep, \vep) \OrTypeError\\\\ + \checktypesat(\tenv, \vtep, \vt) \typearrow \True \OrTypeError +}{ + \annotatestmt(\tenv, \overname{\SReturn(\langle \ve \rangle)}{\vs}) \typearrow + (\overname{\SReturn(\langle \vep \rangle)}{\news}, \overname{\tenv}{\newtenv}) +} +\end{mathpar} +\CodeSubsection{\SReturn}{\SReturnEnd}{../Typing.ml} +\lrmcomment{This is related to \identr{FTPK}.} + +\subsection{Semantics} +\subsubsection{SemanticsRule.SReturn\label{sec:SemanticsRule.SReturn}} +\subsubsection{Example (No Return Value)} +The specification: +\VerbatimInput{../tests/ASLSemanticsReference.t/SemanticsRule.SReturnNone.asl} +exits the current procedure. + +\subsubsection{Example (Returning a Single Value)} +In the specification: +\VerbatimInput{../tests/ASLSemanticsReference.t/SemanticsRule.SReturnOne.asl} +\texttt{return 3;} exits the current subprogram with value \texttt{3}. + +\subsubsection{Example (Returning Multiple Values)} +In the specification: +\VerbatimInput{../tests/ASLSemanticsReference.t/SemanticsRule.SReturnSome.asl} +\texttt{return (3, 42);} exits the current subprogram with value \texttt{(3, 42)}. + +\subsubsection{Prose} +One of the following applies: +\begin{itemize} + \item All of the following apply (\textsc{none}): + \begin{itemize} + \item $\vs$ is a \texttt{return} statement, $\SReturn(\None)$; + \item $\vvs$ is the empty list, $\emptylist$; + \item $\newg$ is the empty graph; + \item $\newenv$ is $\env$. + \end{itemize} + + \item All of the following apply (\textsc{one}): + \begin{itemize} + \item $\vs$ is a \texttt{return} statement; + \item $\vs$ is a \texttt{return} statement for a single expression, $\SReturn(\langle\ve\rangle)$; + \item evaluating $\ve$ in $\env$ is $\Normal((\vv, \vgone), \newenv)$\ProseOrAbnormal; + \item $\vvs$ is $[\vv]$; + \item $\vgtwo$ is the result of adding a Write Effect for a fresh identifier and the value $\vv$; + \item $\newg$ is the ordered composition of $\vgone$ and $\vgtwo$ with the $\asldata$ edge. + \end{itemize} + + \item All of the following apply (\textsc{tuple}): + \begin{itemize} + \item $\vs$ is a \texttt{return} statement for a list of expressions, $\SReturn(\langle\ETuple(\es)\rangle)$; + \item evaluating each expression in $\es$ separately as per \secref{SemanticsRule.EExprListM} + is \\ $\Normal(\ms, \newenv)$\ProseOrAbnormal; + \item writing the list of values in $\vms$ results in $(\vvs, \newg)$. + \end{itemize} +\end{itemize} + +\begin{mathpar} +\inferrule[none]{} +{ + \evalstmt{\env, \SReturn(\None)} \evalarrow \Returning((\emptylist, \emptygraph), \env) +} +\end{mathpar} + +\begin{mathpar} +\inferrule[one]{ + \evalexpr{\env, \ve} \evalarrow \Normal((\vv, \vgone), \newenv) \OrAbnormal\\\\ + \wid \in \Identifiers\text{ is fresh}\\ + \writeidentifier(\wid, \vv) \evalarrow \vgtwo\\ + \newg \eqdef \ordered{\vgone}{\asldata}{\vgtwo} +}{ + \evalstmt{\env, \SReturn(\langle\ve\rangle)} \evalarrow \Returning(([\vv], \newg), \newenv) +} +\end{mathpar} + +\begin{mathpar} +\inferrule[tuple]{ + \evalexprlistm(\env, \es) \evalarrow \Normal(\ms, \newenv) \OrAbnormal\\ + \writefolder(\ms) \evalarrow (\vvs, \newg) +}{ + \evalstmt{\env, \SReturn(\langle\ETuple(\es)\rangle)} \evalarrow \Returning((\vvs, \newg), \newenv) +} +\end{mathpar} +\CodeSubsubsection{\SReturnBegin}{\EvalSReturnEnd}{../Interpreter.ml} + +\subsubsection{SemanticsRule.EExprListM \label{sec:SemanticsRule.EExprListM}} +The helper relation +\[ + \evalexprlistm(\overname{\envs}{\env} \aslsep \overname{\expr^*}{\vEs}) \;\aslrel\; + \Normal(\overname{(\vals\times\XGraphs)^* }{\vms} \aslsep \overname{\envs}{\newenv}) \cup + \overname{\TThrowing}{\ThrowingConfig} \cup \overname{\TError}{\ErrorConfig} +\] +evaluates a list of expressions $\vEs$ in left-to-right in the initial environment $\env$ +and returns the list of values associated with graphs $\vms$ and the new environment $\newenv$. +If the evaluation of any expression terminates abnormally then the abnormal configuration is returned. + +\subsubsection{Prose} +One of the following applies: +\begin{itemize} + \item All of the following apply (\textsc{empty}): + \begin{itemize} + \item $\vEs$ is an empty list; + \item $\vms$ is then empty list. + \end{itemize} + + \item All of the following apply (\textsc{non\_empty}): + \begin{itemize} + \item $\vEs$ is a list with \head\ $\ve$ and \tail\ $\vesone$; + \item evaluating $\ve$ in $\env$ yields $\Normal(\vmone, \envone)$\ProseOrAbnormal; + \item evaluating $\vesone$ in $\envone$ via $\evalexprlistm$ yields \\ + $\Normal(\vmsone, \newenv)$\ProseOrAbnormal; + \item the result is the normal configuration with the list consisting of $\vmone$ as its \head\ and $\vmsone$ + as its \tail\ and $\newenv$. + \end{itemize} +\end{itemize} + +\subsubsection{Formally} +\begin{mathpar} +\inferrule[empty]{} +{ + \evalexprlistm(\env, \overname{\emptylist}{\vEs}) \evalarrow \Normal(\overname{\emptylist}{\vms}, \overname{\env}{\newenv}) +} +\end{mathpar} + +\subsubsection{Semantics} +\begin{mathpar} +\inferrule[non\_empty]{ + \vEs \eqname [\ve] \concat \vesone\\ + \evalexpr{\env, \ve} \evalarrow \Normal(\vmone, \envone) \OrAbnormal\\ + \evalexprlistm(\envone, \vesone) \evalarrow \Normal(\vmsone, \newenv) \OrAbnormal +}{ + \evalexprlistm(\env, \vEs) \evalarrow \Normal([\vmone]\concat\vmsone, \newenv) +} +\end{mathpar} + +\subsubsection{SemanticsRule.WriteFolder\label{sec:SemanticsRule.WriteFolder}} +\hypertarget{def-writefolder}{} +The helper relation +\[ + \writefolder(\overname{(\vals\times\XGraphs)^*}{\vms}) \aslrel (\overname{\vals^*}{\vvs}, \overname{\XGraphs}{\newg}) \enspace, +\] +concatenates the input values in $\vms$ and generates an execution graph +by composing the graphs in $\vms$ with Write Effects for the respective values. + +\begin{mathpar} +\inferrule[empty]{}{ + \writefolder(\emptylist) \evalarrow (\emptylist, \emptygraph) +} +\and +\inferrule[nonempty]{ + \vms \eqname [\vm] \concat \vmsone\\ + \vm \eqdef (\vv, \vg)\\ + \wid \in \Identifiers\text{ is fresh}\\ + \writeidentifier(\wid, \vv) \evalarrow \vgone\\ + \writefolder(\vmsone, \vgone) \evalarrow (\vvsone, \vgtwo)\\ + \vvs \eqdef [\vv] \concat \vvsone\\ + \newg \eqdef \ordered{\vgone}{\asldata}{\vgtwo} +}{ + \writefolder(\vms) \evalarrow (\vvs, \ordered{\vg}{\aslpo}{\newg}) +} +\end{mathpar} + +\section{Print Statements\label{sec:PrintStatements}} +\subsection{Syntax} +\begin{flalign*} +\Nstmt \derivesinline\ & \Tprint \parsesep \Plist{\Nexpr} \parsesep \Tsemicolon & +\end{flalign*} + +\subsection{Abstract Syntax} +\begin{flalign*} +\stmt \derives\ & \SPrint(\overtext{\expr^*}{args}, \overtext{\Bool}{debug}) & +\end{flalign*} + +\subsubsection{ASTRule.SPrint} +\begin{mathpar} +\inferrule{ + \buildplist[\Nexpr](\vargs) \astarrow \astversion{\vargs} +}{ + \buildstmt(\overname{\Nstmt(\Tprint, \namednode{\vargs}{\Plist{\Nexpr}}, \Tsemicolon)}{\vparsednode}) + \astarrow + \overname{\SPrint(\astversion{\vargs})}{\vastnode} +} +\end{mathpar} + +\subsection{Typing} +\subsection{Semantics} + +\section{Pragma Statements\label{sec:PragmaStatements}} +\subsection{Syntax} +\begin{flalign*} +\Nstmt \derivesinline\ & \Tpragma \parsesep \Tidentifier \parsesep \Clist{\Nexpr} \parsesep \Tsemicolon & +\end{flalign*} + +\subsection{Abstract Syntax} +\subsection{Typing} +\subsection{Semantics} diff --git a/asllib/doc/StaticEvaluation.tex b/asllib/doc/StaticEvaluation.tex new file mode 100644 index 000000000..57abce240 --- /dev/null +++ b/asllib/doc/StaticEvaluation.tex @@ -0,0 +1,472 @@ +\chapter{Static Evaluation\label{chap:staticevaluation}} + +In this chapter, we define how to statically evaluate a subset of expressions +via TypingRule.StaticEval (see \secref{TypingRule.StaticEval}) and +the primitive operations defined in \chapref{PrimitiveOperations}. +We also define the following helper rules: +\begin{itemize} + \item TypingRule.SlicesToPositions (see \secref{TypingRule.SlicesToPositions}) + \item TypingRule.SliceToPositions (see \secref{TypingRule.SliceToPositions}) + \item TypingRule.EvalToInt (see \secref{TypingRule.EvalToInt}) + \item TypingRule.ExtractSlice (see \secref{TypingRule.ExtractSlice}) +\end{itemize} + +\hypertarget{def-unsupportedexpression} +In this chapter, as well as \chapref{SymbolicSubsumptionTesting} and +\chapref{SymbolicEquivalenceTesting}, we use the special value $\CannotBeTransformed$ +to represent a failure in transforming an expression into a desired form (the specific +desired form varies according to the functions utilizing this value). + +\hypertarget{def-staticeval}{} +\subsection{TypingRule.StaticEval \label{sec:TypingRule.StaticEval}} +The function +\[ + \staticeval(\overname{\staticenvs}{\tenv} \aslsep \overname{\expr}{\ve}) \;\aslto\; + \overname{\literals}{\vv} \cup + \{\CannotBeTransformed\} + \overname{\TTypeError}{\TypeErrorConfig} +\] +evaluates an expression $\ve$, from a restricted subset of all expressions, +in the static environment $\tenv$, returning a literal $\vv$. +If $\ve$ is not in the restricted set of expressions or cannot be statically evaluated to a compile-time +constant, the result is $\CannotBeTransformed$. +\ProseOtherwiseTypeError + +\subsubsection{Prose} +One of the following applies: +\begin{itemize} + \item All of the following apply (\textsc{e\_literal}): + \begin{itemize} + \item $\ve$ is the literal expression for the literal $\vv$, that is, $\ELiteral(\vv)$. + \end{itemize} + + \item All of the following apply (\textsc{e\_var\_constant}): + \begin{itemize} + \item $\ve$ is a variable expression with the identifier $\vx$, that is, $\EVar(\vx)$; + \item determining whether $\vx$ is bound to a constant in $\tenv$ via $\lookupconstant$ yields the literal $\vv$. + \end{itemize} + + \item All of the following apply (\textsc{e\_var\_non\_constant}): + \begin{itemize} + \item $\ve$ is a variable expression with the identifier $\vx$, that is, $\EVar(\vx)$; + \item determining whether $\vx$ is bound to a constant in $\tenv$ via $\lookupconstant$ yields $\bot$ + (that is, $\vx$ is not bound to a constant); + \item checking whether $\vx$ is defined in $\tenv$ yields $\True$\ProseOrTypeError; + \item the result is $\CannotBeTransformed$. + \end{itemize} + + \item All of the following apply (\textsc{e\_binop}): + \begin{itemize} + \item $\ve$ is a binary operation expression with operator $\op$ and operand expressions $\veone$ and $\vetwo$, + that is, $\EBinop(\op, \veone, \vetwo)$; + \item applying $\staticeval$ to $\veone$ in $\tenv$ yields the literal $\vvone$\ProseTerminateAs{\CannotBeTransformed, \TypeErrorConfig}; + \item applying $\staticeval$ to $\vetwo$ in $\tenv$ yields the literal $\vvtwo$\ProseTerminateAs{\CannotBeTransformed, \TypeErrorConfig}; + \item applying $\op$ to $\vvone$ and $\vvtwo$ via $\binopliterals$ yields $\vv$\ProseOrTypeError. + \end{itemize} + + \item All of the following apply (\textsc{e\_unop}): + \begin{itemize} + \item $\ve$ is a unary operation expression with operator $\op$ and operand expression $\veone$, + that is, $\EUnop(\op, \veone)$; + \item applying $\staticeval$ to $\veone$ in $\tenv$ yields the literal $\vvone$\ProseTerminateAs{\CannotBeTransformed, \TypeErrorConfig}; + \item applying $\op$ to $\vvone$ via $\unopliterals$ yields $\vv$\ProseOrTypeError. + \end{itemize} + + \item All of the following apply (\textsc{e\_slice\_int}): + \begin{itemize} + \item $\ve$ is a slicing expression of the integer literal for $\vi$ and slice list $\vslices$, that is, + $\ESlice(\lint(\vi), \vslices)$; + \item obtaining the indices of the slice list $\vslices$ in $\tenv$ via $\typingslicestopositions$ + yields $\positions$\ProseOrTypeError; + \item $\posmax$ is the maximum index in $\positions$; + \item converting the first $\posmax+1$ digits of the binary representation of $\vi$ into a bitvector + via $\inttobits$ yields $\bvone$; + \item extracting the slice of $\bvone$ given by $\positions$ yields $\bvtwo$\ProseOrTypeError; + \item $\vv$ is the bitvector literal for $\bvtwo$. + \end{itemize} + + \item All of the following apply (\textsc{e\_slice\_bitvector}): + \begin{itemize} + \item $\ve$ is a slicing expression of the bitvector literal for $\bv$ and slice list $\vslices$, that is, + $\ESlice(\lbitvector(\bv), \vslices)$; + \item obtaining the indices of the slice list $\vslices$ in $\tenv$ via $\typingslicestopositions$ + yields $\positions$\ProseOrTypeError; + \item $\posmax$ is the maximum index in $\positions$; + \item checking that the length of $\bv$ is greater than $\posmax$ (which is $0$-based) yields $\True$\ProseOrTypeError; + \item extracting the slice of $\bv$ given by $\positions$ yields $\bvtwo$\ProseOrTypeError; + \item $\vv$ is the bitvector literal for $\bvtwo$. + \end{itemize} + + \item All of the following apply (\textsc{e\_slice\_type\_error}): + \begin{itemize} + \item $\ve$ is a slicing expression of subexpression $\veone$ and slice list $\vslices$, that is, $\ESlice(\veone, \vslices)$; + \item $\veone$ is neither an integer literal nor a bitvector literal; + \item the result is a type error indicating that either an integer literal or a bitvector literal were expected. + \end{itemize} + + \item All of the following apply (\textsc{e\_cond}): + \begin{itemize} + \item $\ve$ is a conditional expression with condition subexpression $\econd$ and subexpressions $\veone$ (true case) + and $\vetwo$ (false case), that is, $\ECond(\econd, \veone, \vetwo)$; + \item evaluating $\econd$ in $\tenv$ either yields a Boolean literal $\vb$ or a type error or $\CannotBeTransformed$, + either of which short-circuits the rule; + \item $\vep$ is $\veone$ if $\vb$ is $\True$ and $\vetwo$ otherwise; + \item the result is given by applying $\staticeval$ to $\vep$ in $\tenv$. + \end{itemize} + + \item All of the following apply (\textsc{unsupported}): + \begin{itemize} + \item $\ve$ is an expression that is not one of the following: a literal, a variable, a binary operation expression, + a unary operation expression, a slice expression, and a conditional expression; + \item the result is a type error indicating that $\ve$ is not an expression that is supported + for static evaluation. + \end{itemize} +\end{itemize} + +\subsubsection{Formally} +\begin{mathpar} +\inferrule[e\_literal]{} +{ + \staticeval(\tenv, \overname{\ELiteral(\vv)}{\ve}) \typearrow \vv +} +\end{mathpar} + +\begin{mathpar} +\inferrule[e\_var\_constant]{ + \lookupconstant(\tenv, \vx) \typearrow \vv +}{ + \staticeval(\tenv, \overname{\EVar(\vx)}{\ve}) \typearrow \vv +} +\and +\inferrule[e\_var\_non\_constant]{ + \lookupconstant(\tenv, \vx) \typearrow \bot\\ + \isundefined(\tenv, \vx) \typearrow \vb\\ + \checktrans{\neg\vb}{\UndefinedIdentifier} \typearrow \True \OrTypeError +}{ + \staticeval(\tenv, \overname{\EVar(\vx)}{\ve}) \typearrow \CannotBeTransformed +} +\end{mathpar} + +\begin{mathpar} +\inferrule[e\_binop]{ + \staticeval(\tenv, \veone) \typearrow \vvone \terminateas \TypeErrorConfig, \CannotBeTransformed\\\\ + \staticeval(\tenv, \vetwo) \typearrow \vvtwo \terminateas \TypeErrorConfig, \CannotBeTransformed\\\\ + \binopliterals(\op, \vvone, \vvtwo) \typearrow \vv \OrTypeError +}{ + \staticeval(\tenv, \overname{\EBinop(\op, \veone, \vetwo)}{\ve}) \typearrow \vv +} +\end{mathpar} + +\begin{mathpar} +\inferrule[e\_unop]{ + \staticeval(\tenv, \veone) \typearrow \vvone \terminateas \TypeErrorConfig, \CannotBeTransformed\\\\ + \unopliterals(\op, \vvone) \typearrow \vv \OrTypeError +}{ + \staticeval(\tenv, \overname{\EUnop(\op, \veone)}{\ve}) \typearrow \vv +} +\end{mathpar} + +\begin{mathpar} +\inferrule[e\_slice\_int]{ + \typingslicestopositions(\tenv, \slices) \typearrow \positions \OrTypeError\\\\ + \posmax \eqdef \max(\positions)\\ + \bvone \eqdef \inttobits(\vi, \posmax + 1)\\ + \extractslice(\bvone, \positions) \typearrow \bvtwo \OrTypeError +}{ + \staticeval(\tenv, \overname{\ESlice(\lint(\vi), \slices)}{\ve}) \typearrow \overname{\lbitvector(\bvtwo)}{\vv} +} +\end{mathpar} + +\begin{mathpar} +\inferrule[e\_slice\_bitvector]{ + \typingslicestopositions(\tenv, \slices) \typearrow \positions \OrTypeError\\\\ + \posmax \eqdef \max(\positions)\\ + \checktrans{\listlen{\bv} > \posmax}{SliceOutOfRange} \checktransarrow \True \OrTypeError\\\\ + \extractslice(\bv, \positions) \typearrow \bvtwo \OrTypeError +}{ + \staticeval(\tenv, \overname{\ESlice(\lbitvector(\bv), \slices)}{\ve}) \typearrow \overname{\lbitvector(\bvtwo)}{\vv} +} +\end{mathpar} + +\begin{mathpar} +\inferrule[e\_slice\_type\_error]{ + \astlabel(\veone) \not\in \{\lint, \lbitvector\} +}{ + \staticeval(\tenv, \overname{\ESlice(\veone, \slices)}{\ve}) \typearrow \TypeErrorVal{TypeMismatch} +} +\end{mathpar} + +\begin{mathpar} +\inferrule[e\_cond]{ + \staticeval(\tenv, \econd) \typearrow \vcond \terminateas \TypeErrorConfig, \CannotBeTransformed\\\\ + \vcond \eqname \lbool(\vb)\\ + \vep \eqdef \choice{\vb}{\veone}{\vetwo}\\ + \staticeval(\tenv, \vep) \typearrow \vv \terminateas \TypeErrorConfig, \CannotBeTransformed +}{ + \staticeval(\tenv, \overname{\ECond(\econd, \veone, \vetwo)}{\ve}) \typearrow \vv +} +\end{mathpar} + +\begin{mathpar} +\inferrule[unsupported]{ + \astlabel(\ve) \not\in \{ \ELiteral, \EVar, \EBinop, \EUnop, \ESlice, \ECond\} +}{ + \staticeval(\tenv, \ve) \typearrow \TypeErrorVal{UnsupportedExpression} +} +\end{mathpar} + +\subsubsection{TypingRule.LookupConstant} +\hypertarget{def-lookupconstant}{} +The function +\[ + \lookupconstant(\overname{\staticenvs}{\tenv} \aslsep \overname{\identifier}{\vs}) + \;\aslto\; \overname{\literal}{\vv}\ \cup\ \{\bot\} +\] +looks up the environment $\tenv$ for a constant $\vv$ associated with an identifier +$\vs$. The result is $\bot$ if $\vs$ is not associated with any constant. + +\subsubsection{Prose} +One of the following applies: +\begin{itemize} + \item All of the following apply (\textsc{local}): + \begin{itemize} + \item $\vs$ is associated with a constant $\vv$ in the local environment of $\tenv$; + \end{itemize} + + \item All of the following apply (\textsc{global}): + \begin{itemize} + \item $\vs$ is not associated with a constant in the local environment of $\tenv$; + \item $\vs$ is associated with a constant $\vv$ in the global environment of $\tenv$; + \end{itemize} + + \item All of the following apply (\textsc{none}): + \begin{itemize} + \item $\vs$ is not associated with a constant in the local environment of $\tenv$; + \item $\vs$ is not associated with a constant in the global environment of $\tenv$; + \item the result is $\bot$. + \end{itemize} +\end{itemize} + +\subsubsection{Formally} +\begin{mathpar} +\inferrule[local]{ + L^\tenv.\constantvalues(\vs) = \vv +}{ + \lookupconstant(\tenv, \vs) \typearrow \vv +} +\and +\inferrule[global]{ + L^\tenv.\constantvalues(\vs) = \bot\\ + G^\tenv.\constantvalues(\vs) = \vv +}{ + \lookupconstant(\tenv, \vs) \typearrow \vv +} +\and +\inferrule[none]{ + L^\tenv.\constantvalues(\vs) = \bot\\ + G^\tenv.\constantvalues(\vs) = \bot +}{ + \lookupconstant(\tenv, \vs) \typearrow \bot +} +\end{mathpar} + +\subsection{TypingRule.SlicesToPositions \label{sec:TypingRule.SlicesToPositions}} +\hypertarget{def-typingslicestopositions}{} +The function +\[ + \typingslicestopositions(\overname{\staticenvs}{\tenv} \aslsep \overname{\slice^*}{\slices}) \aslto + \overname{\Z^*}{\positions} \cup \{\CannotBeTransformed\} \cup \overname{\TTypeError}{\TypeErrorConfig} +\] +transforms the list of slices $\slices$ in $\tenv$ into a list of indices $\positions$. +The result is $\CannotBeTransformed$ if $\slices$ cannot be statically evaluated to +a list of positions. +\ProseOtherwiseTypeError + +\subsubsection{Prose} +One of the following applies: +\begin{itemize} + \item All of the following apply (\textsc{empty}): + \begin{itemize} + \item $\slices$ is the empty list; + \item $\positions$ is the empty list. + \end{itemize} + + \item All of the following apply (\textsc{non\_empty}): + \begin{itemize} + \item \view\ $\slices$ as the list with $\vs$ as its \head\ and $\slicesone$ as its \tail; + \item applying $\slicetopositions$ to $\vs$ in $\tenv$ yields the list of positions \\ + $\positionsone$\ProseTerminateAs{\CannotBeTransformed, \TypeErrorConfig}; + \item transforming $\slicesone$ to a list of positions in $\tenv$ via $\typingslicestopositions$ yields + $\positionstwo$\ProseTerminateAs{\CannotBeTransformed, \TypeErrorConfig}; + \item $\positions$ is the concatenation of $\positionsone$ and $\positionstwo$. + \end{itemize} +\end{itemize} + +\subsubsection{Formally} +\begin{mathpar} +\inferrule[empty]{} +{ + \typingslicestopositions(\tenv, \overname{\emptylist}{\slices}) \typearrow \overname{\emptylist}{\positions} +} +\and +\inferrule[non\_empty]{ + \slicetopositions(\tenv, \vs) \typearrow \positionsone \terminateas \CannotBeTransformed,\TypeErrorConfig\\\\ + \typingslicestopositions(\tenv, \slicesone) \typearrow \positionstwo \terminateas \CannotBeTransformed,\TypeErrorConfig +}{ + \typingslicestopositions(\tenv, \overname{[\vs] \concat \slicesone}{\slices}) \typearrow \overname{\positionsone \concat \positionstwo}{\positions} +} +\end{mathpar} + +\subsection{TypingRule.SliceToPositions \label{sec:TypingRule.SliceToPositions}} +\hypertarget{def-slicetopositions}{} +The function +\[ + \slicetopositions(\overname{\staticenvs}{\tenv} \aslsep \overname{\slice}{\vs}) \aslto + \overname{\Z^+}{\positions} \cup \{\CannotBeTransformed\} \cup \overname{\TTypeError}{\TypeErrorConfig} +\] +transforms a slice $\vs$ in $\tenv$ into a list of indices $\positions$. +The result is $\CannotBeTransformed$ if $\slices$ cannot be statically evaluated to +a list of positions. +\ProseOtherwiseTypeError + +\subsubsection{Prose} +One of the following applies: +\begin{itemize} + \item All of the following apply (\textsc{single}): + \begin{itemize} + \item $\vs$ is a slice for a single position given by the expression $\ve$, that is, \\ $\SliceSingle(\ve)$; + \item applying $\evaltoint$ to $\ve$ in $\tenv$ yields the integer $n$\ProseOrTypeError; + \item checking that $n$ is non-negative yields $\True$\ProseOrTypeError; + \item $\positions$ is the list containing the single element $n$. + \end{itemize} + + \item All of the following apply (\textsc{range}): + \begin{itemize} + \item $\vs$ is a slice for a range given by the expression $\etop$ + for the top position and $\ebot$ for the bottom position, that is, \\ $\SliceRange(\etop, \ebot)$; + \item applying $\evaltoint$ to $\ebot$ in $\tenv$ yields the integer $b$\ProseOrTypeError; + \item applying $\evaltoint$ to $\etop$ in $\tenv$ yields the integer $t$\ProseOrTypeError; + \item checking that $t$ is greater or equal to $b$ and that $b$ is greater or equal to $0$ yields $\True$\ProseOrTypeError; + \item $\positions$ is the list of integers from $t$ down to $b$, inclusive. + \end{itemize} + + \item All of the following apply (\textsc{length}): + \begin{itemize} + \item $\vs$ is a slice for a length slice given by the expression $\ebot$ + for the bottom position and $\elength$ for the length of the slice, that is, \\ $\SliceLength(\ebot, \elength)$; + \item applying $\evaltoint$ to $\ebot$ in $\tenv$ to an integer yields the integer $b$\ProseOrTypeError; + \item applying $\evaltoint$ to $\elength$ in $\tenv$ to an integer yields the integer $l$\ProseOrTypeError; + \item $t$ is $b + l - 1$; + \item checking that $t$ is greater or equal to $b$ and that $b$ is greater or equal to $0$ yields $\True$\ProseOrTypeError; + \item $\positions$ is the list of integers from $t$ down to $b$, inclusive. + \end{itemize} + + \item All of the following apply (\textsc{star}): + \begin{itemize} + \item $\vs$ is a slice for a scaled slice given by the expression $\efactor$ + for the factor and $\elength$ for the length of the slice (\texttt{$\elength$*:$\efactor$}), + that is, \\ $\SliceStar(\efactor, \elength)$; + \item applying $\evaltoint$ to $\efactor$ in $\tenv$ to an integer yields the integer $f$\ProseOrTypeError; + \item applying $\evaltoint$ to $\elength$ in $\tenv$ to an integer yields the integer $l$\ProseOrTypeError; + \item $t$ is $(f \times l) + l - 1$; + \item $b$ is $t - l + 1$; + \item checking that $t$ is greater or equal to $b$ and that $b$ is greater or equal to $0$ yields $\True$\ProseOrTypeError; + \item $\positions$ is the list of integers from $t$ down to $b$, inclusive. + \end{itemize} +\end{itemize} + +\subsubsection{Formally} + +\begin{mathpar} +\inferrule[single]{ + \evaltoint(\tenv, \ve) \typearrow n \terminateas \CannotBeTransformed,\TypeErrorConfig\\\\ + \checktrans{n \geq 0}{BadSlice} \checktransarrow \True \OrTypeError +}{ + \slicetopositions(\tenv, \overname{\SliceSingle(\ve)}{\vs}) \typearrow [ n ] +} +\and +\inferrule[range]{ + \evaltoint(\tenv, \ebot) \typearrow b \terminateas \CannotBeTransformed,\TypeErrorConfig\\\\ + \evaltoint(\tenv, \etop) \typearrow t \terminateas \CannotBeTransformed,\TypeErrorConfig\\\\ + \checktrans{t \geq b \geq 0}{BadSlice} \checktransarrow \True \OrTypeError +}{ + \slicetopositions(\tenv, \overname{\SliceRange(\etop, \ebot)}{\vs}) \typearrow [ t..b ] +} +\and +\inferrule[length]{ + \evaltoint(\tenv, \ebot) \typearrow b \terminateas \CannotBeTransformed,\TypeErrorConfig\\\\ + \evaltoint(\tenv, \elength) \typearrow l \terminateas \CannotBeTransformed,\TypeErrorConfig\\\\ + t \eqdef b + l - 1\\ + \checktrans{t \geq b \geq 0}{BadSlice} \checktransarrow \True \OrTypeError +}{ + \slicetopositions(\tenv, \overname{\SliceLength(\ebot, \elength)}{\vs}) \typearrow [ t..b ] +} +\and +\inferrule[star]{ + \evaltoint(\tenv, \efactor) \typearrow f \terminateas \CannotBeTransformed,\TypeErrorConfig\\\\ + \evaltoint(\tenv, \elength) \typearrow l \terminateas \CannotBeTransformed,\TypeErrorConfig\\\\ + t \eqdef (f \times l) + l - 1\\ + b \eqdef t - l\\ + \checktrans{t \geq b \geq 0}{BadSlice} \checktransarrow \True \OrTypeError +}{ + \slicetopositions(\tenv, \overname{\SliceStar(\efactor, \elength)}{\vs}) \typearrow [ t..b ] +} +\end{mathpar} + +\subsection{TypingRule.EvalToInt \label{sec:TypingRule.EvalToInt}} +\hypertarget{def-evaltoint}{} +The function +\[ +\evaltoint(\overname{\staticenvs}{\tenv} \aslsep \overname{\expr}{\ve}) +\aslto \overname{\Z}{n} \cup \{\CannotBeTransformed\} \cup \overname{\TTypeError}{\TypeErrorConfig} +\] +statically evaluates the expression $\ve$ to the integer $n$. +The result is $\CannotBeTransformed$ if $\ve$ cannot be statically evaluated +to an integer. +\ProseOtherwiseTypeError + +\subsubsection{Prose} +All of the following apply: +\begin{itemize} + \item applying $\staticeval$ to $\ve$ in $\tenv$ has one of three outcomes: + \begin{itemize} + \item a literal $\vl$, which satisfies the premise; + \item $\CannotBeTransformed$ (which means the expression could not be evaluated to a literal), + which short-circuits the entire rule; + or + \item $\TypeErrorConfig$ (indicating a type error was detected), which short-circuits the entire rule; + \end{itemize} + \item checking that $\vl$ is an integer literal yields $\True$\ProseOrTypeError; + \item define $\vl$ as the literal integer for $n$. +\end{itemize} + +\subsubsection{Formally} +\begin{mathpar} +\inferrule{ + \staticeval(\tenv, \ve) \typearrow \vl \terminateas \CannotBeTransformed, \TypeErrorConfig\\\\ + \checktrans{\astlabel(\vl) = \lint}{ExpectedIntegerType} \checktransarrow \True \OrTypeError\\\\ + \vl \eqname \lint(n) +}{ + \evaltoint(\tenv, \ve) \typearrow n +} +\end{mathpar} + +\subsection{TypingRule.ExtractSlice \label{sec:TypingRule.ExtractSlice}} +\hypertarget{def-extractslice}{} +The function +\[ + \extractslice(\overname{\{0,1\}^*}{\bits} \aslsep \overname{\Z^*}{\positions}) \aslto + \overname{\{0,1\}^*}{\vr} \cup\ \TTypeError +\] +extracts from the list of bits $\bits$ the sublist $\vr$ of bits appearing at the positions given by $\positions$. +\ProseOtherwiseTypeError + +\subsubsection{Prose} +Define $\vr$ the sublist of $\bits$ given by taking $\bits[\vi]$, for every value given in $\positions$ (in the order they appear). + +\subsubsection{Formally} +\begin{mathpar} +\inferrule{}{ + \extractslice(\tenv, \bits, \positions) \typearrow \overname{[ \vi\in\positions: \bits[\vi] ]}{\vr} +} +\end{mathpar} \ No newline at end of file diff --git a/asllib/doc/SubprogramCalls.tex b/asllib/doc/SubprogramCalls.tex new file mode 100644 index 000000000..a9e958935 --- /dev/null +++ b/asllib/doc/SubprogramCalls.tex @@ -0,0 +1,1946 @@ +\chapter{Subprogram Calls\label{chap:SubprogramCalls}} + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +\section{Syntax} +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +\begin{flalign*} +\Nexpr \derives\ & \Tidentifier \parsesep \Plist{\Nexpr} &\\ +\Nstmt \derivesinline\ & \Tidentifier \parsesep \Plist{\Nexpr} \parsesep \Tsemicolon & +\end{flalign*} + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +\section{Abstract Syntax} +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +\subsection{Untyped AST} +\begin{flalign*} +\expr \derives\ & \ECall(\overtext{\identifier}{subprogram name}, \overtext{\expr^{*}}{actual arguments}) &\\ +\stmt \derives\ & \SCall(\overtext{\identifier}{subprogram name}, \overtext{\expr^{*}}{actual arguments}) & +\end{flalign*} + +\subsection{Typed AST} +The AST node for call expressions includes an extra component that explicitly associates expressions +with parameters: +\begin{flalign*} +\expr \derives\ & \ECall(\overtext{\identifier}{subprogram name}, \overtext{\expr^{*}}{actual arguments}, \overtext{(\identifier, \expr)^{*}}{parameters with initializers}) & +\end{flalign*} + +Similar to expressions, the AST node for call statements includes an extra component that explicitly associates expressions +with parameters: +\begin{flalign*} +\stmt \derives\ & \SCall(\overtext{\identifier}{subprogram name}, \overtext{\expr^{*}}{actual arguments}, \overtext{(\identifier, \expr)^{*}}{parameters with initializers}) & +\end{flalign*} + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +\section{Typing} +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +\hypertarget{def-annotatecall} +The function +\[ + \begin{array}{rl} + \annotatecall( & + \overname{\staticenvs}{\tenv} \aslsep + \overname{\identifier}{\name} \aslsep + \overname{\expr^*}{\vargs} \aslsep + \overname{\subprogramtype}{\calltype} + ) \aslto \\ & + (\overname{\identifier}{\nameone} \aslsep + \overname{\expr^*}{\vargsone} \aslsep + \overname{(\identifier\times\expr)^*}{\eqs} \aslsep + \overname{\langle \ty \rangle}{\rettyopt}) +\end{array} +\] +annotates the call to subprogram $\name$ with arguments $\vargs$ +and call type $\calltype$, resulting in the following: +\begin{itemize} + \item $\nameone$ --- a string, which uniquely identifies $\name$ among the set of overloading subprograms declared with $\name$; + \item $\vargsone$ --- the annotated argument expressions; + \item $\eqs$ --- the expressions providing values to the parameters; + \item $\rettyopt$ --- the \optional\ annotated return type. +\end{itemize} +\ProseOtherwiseTypeError + +The function is defined by the rule TypingRule.AnnotateCall (see \secref{TypingRule.AnnotateCall}). + +We also define helper functions via respective rules: +\begin{itemize} + \item TypingRule.AnnotateCallArgTyped (see \secref{TypingRule.AnnotateCallArgTyped}) + \item TypingRule.CheckCalleeParams (see \secref{TypingRule.CheckCalleeParams}) + \item TypingRule.RenameTyEqs (see \secref{TypingRule.RenameTyEqs}) + \item TypingRule.SubstExprNormalize (see \secref{TypingRule.SubstExprNormalize}) + \item TypingRule.SubstExpr (see \secref{TypingRule.SubstExpr}) + \item TypingRule.SubstConstraint (see \secref{TypingRule.SubstConstraint}) + \item TypingRule.CheckArgsTypeSat (see \secref{TypingRule.CheckArgsTypeSat}) + \item TypingRule.AnnotateParameterDefining (see \secref{TypingRule.AnnotateParameterDefining}) + \item TypingRule.AnnotateRetTy (\secref{TypingRule.AnnotateRetTy}) + \item TypingRule.SubprogramForName (see \secref{TypingRule.SubprogramForName}) + \item TypingRule.DeduceEqs (see \secref{TypingRule.DeduceEqs}) + \item TypingRule.FilterCallCandidates (see \secref{TypingRule.FilterCallCandidates}) + \item TypingRule.HasArgClash (see \secref{TypingRule.HasArgClash}) + \item TypingRule.ExpressionList (see \secref{TypingRule.ExpressionList}) +\end{itemize} + +\subsubsection{TypingRule.AnnotateCall \label{sec:TypingRule.AnnotateCall}} +\subsubsection{Prose} +All of the following apply: +\begin{itemize} + \item applying $\annotateexprlist$ to annotate the expression list $\vargs$ in $\tenv$ yields \\ + $\callerargtyped$\ProseOrTypeError; + \item applying $\annotatecallargtyped$ to $\name$, $\callerargtyped$, $\calltype$ in $\tenv$ yields + $(\nameone, \vargsone, \eqs, \retty)$\ProseOrTypeError. +\end{itemize} + +\CodeSubsection{\AnnotateCallBegin}{\AnnotateCallEnd}{../Typing.ml} + +\subsubsection{Formally} +\begin{mathpar} +\inferrule{ + \annotateexprlist(\tenv, \vargs) \typearrow \callerargtyped \OrTypeError\\\\ + { + \begin{array}{r} + \annotatecallargtyped(\tenv, \name, \callerargtyped, \calltype) \typearrow \\ + (\nameone, \vargsone, \eqs, \retty) \OrTypeError + \end{array} + } +}{ + \annotatecall(\tenv, \name, \vargs, \calltype) \typearrow + (\nameone, \vargsone, \eqs, \retty) +} +\end{mathpar}\lrmcomment{ + This is related to \identi{VFDP}, \identd{TRFW}, \identr{KMDB}, + \identi{YMHX}, \identr{CCVD}, \identr{QYBH}, \identr{PFWQ}, \identr{ZLWD}, + \identi{FLKF}, \identd{PMBL}, \identr{MWBN}, \identr{TZSP}, \identr{SBWR}, + \identi{CMLP}, \identr{BQJG}, \identr{RTCF}. +} + +\subsubsection{TypingRule.AnnotateCallArgTyped \label{sec:TypingRule.AnnotateCallArgTyped}} +\hypertarget{def-annotatecallargtyped}{} +The function +\[ + \begin{array}{r} + \annotatecallargtyped( + \overname{\staticenvs}{\tenv} \aslsep + \overname{\identifier}{\name} \aslsep + \overname{(\ty \times\expr)^*}{\callerargstyped} \aslsep + \overname{\subprogramtype}{\calltype} + ) \aslto \\ + (\overname{\identifier}{\nameone} \aslsep + \overname{\expr^*}{\vargsone} \aslsep + \overname{(\identifier\times\expr)^*}{\eqs} \aslsep + \overname{\langle \ty \rangle}{\rettyopt}) + \cup \overname{\TTypeError}{\TypeErrorConfig} +\end{array} +\] +is similar to $\annotatecall$, except that the argument expressions are replaced by +the annotated expressions. That is, pairs consisting of a type and an expression. +\ProseOtherwiseTypeError + +\subsubsection{Prose} +All of the following apply: +\begin{itemize} + \item applying $\unziplist$ to $\callerargtyped$ yields the corresponding lists of types + and expressions $\callerargtypes$ and $\vargsone$; + \item applying $\subprogramforname$ to match $\name$ and $\callerargtypes$ in $\tenv$ + yields $(\eqsone, \nameone, \callee)$\ProseOrTypeError; + \item checking that $\subprogramtype$ of $\callee$ equals $\calltype$ yields $\True$\ProseOrTypeError; + \item checking that the lengths of $\callee.\funcargs$ and $\vargsone$ are the same yields $\True$\ProseOrTypeError; + \item applying $\annotateparameterdefining$ to $\callee.\funcargs$, + $\callerargstyped$, and \\ + $\calleeparams$ in $\tenv$ to annotate the implicit parameters + yields $\eqsthreep$\ProseOrTypeError; + \item define $\eqsthree$ is the concatenation of $\eqsthreep$ and $\eqsone$; + \item applying $\checkargstypesat$ to $\calleeargtypes$ + to check that the actual arguments have correct types with respect to $\callerargtypes$ + in $\tenv$ yields $\True$\ProseOrTypeError; + \item applying $\checkcalleeparams$ to $\calleeparams$ to check they have correct types + with respect to $\eqsthree$ in $\tenv$ yields $\True$\ProseOrTypeError; + \item applying $\annotateretty$ to $\calltype$ and $\callee.\funcreturntype$ + to check that the two call types match and to substitute actual parameter arguments in the formal return type + yields $\rettyopt$ \ProseOrTypeError; + \item define $\eqs$ as $\eqsthree$. +\end{itemize} + +\CodeSubsection{\AnnotateCallArgTypedBegin}{\AnnotateCallArgTypedEnd}{../Typing.ml} + +\subsubsection{Formally} +\begin{mathpar} +\inferrule{ + \unziplist(\callerargstyped) = (\callerargtypes, \vargsone)\\ + { + \begin{array}{r} + \subprogramforname(\tenv, \name, \callerargtypes) \typearrow \\ + (\eqsone, \nameone, \callee) \OrTypeError + \end{array} + }\\ + \checktrans{\callee.\subprogramtype = \calltype}{\MismatchedReturnValue} \checktransarrow \True\OrTypeError\\\\ + \equallength(\callee.\funcargs, \vargsone) \typearrow \aritymatch\\ + \checktrans{\aritymatch}{\CallBadArity} \checktransarrow \True \OrTypeError\\\\ + { + \annotateparameterdefining\left( + \begin{array}{l} + \tenv,\\ + \callee.\funcargs, \\ + \callerargstyped, \\ + \callee.\funcparameters + \end{array} + \right) + \typearrow \eqsthreep \OrTypeError + }\\ + \eqsthree \eqdef \eqsthreep \concat \eqsone\\ + \checkargstypesat(\tenv, \callee.\funcargs, \callerargtypes, \eqsthree) \typearrow \True \OrTypeError\\\\ + \checkcalleeparams(\tenv, \callee.\funcparameters, \eqsthree) \typearrow \True \OrTypeError\\\\ + \annotateretty(\tenv, \calltype, \callee.\funcreturntype) \typearrow \rettyopt \OrTypeError +}{ + { + \begin{array}{r} + \annotatecallargtyped(\tenv, \name, \callerargstyped, \calltype) \typearrow \\ + (\nameone, \vargsone, \overname{\eqsthree}{\eqs}, \rettyopt) + \end{array} + } +} +\end{mathpar} + +\subsubsection{TypingRule.CheckCalleeParams \label{sec:TypingRule.CheckCalleeParams}} +\hypertarget{def-checkcalleeparams}{} +The function +\[ +\checkcalleeparams( + \overname{\staticenvs}{\tenv} \aslsep + \overname{(\identifier\times\langle\ty\rangle)^*}{\calleeparams} + \overname{(\identifier\times\expr)^*}{\eqsthree} + ) \aslto \\ + \{\True\}\ \cup \overname{\TTypeError}{\TypeErrorConfig} +\] +checks that the parameters in $\calleeparams$ are correct with respect +to the parameter expressions $\eqsthree$. +\ProseOtherwiseTypeError + +\subsubsection{Prose} +One of the following applies: +\begin{itemize} + \item All of the following apply (\textsc{empty}): + \begin{itemize} + \item $\calleeparams$ is an empty list; + \item the result is $\True$. + \end{itemize} + + \item All of the following apply: + \begin{itemize} + \item $\calleeparams$ is a non-empty list with \head\ $\calleeparam$ and \tail\ \\ + $\calleeparamsone$; + \item One of the following applies: + \begin{itemize} + \item All of the following apply (\textsc{no\_type}): + \begin{itemize} + \item $\calleeparam$ does not have a type annotation, that is, $(\Ignore, \None)$. + \end{itemize} + + \item All of the following apply (\textsc{parameterized}): + \begin{itemize} + \item $\calleeparam$ is a parameter $\vs$ with a type annotation of a + \parameterizedintegertype\ for the same parameter, that is, \\ + $(\vs, \langle\TInt(\parameterized(\vs))\rangle)$. + \end{itemize} + + \item All of the following apply (\textsc{other}): + \begin{itemize} + \item $\calleeparam$ is a parameter $\vs$ whose type annotation is \\ + $\calleeparamt$, that is, $(\vs, \langle\calleeparamt\rangle)$; + \item $\calleeparamt$ is not the \parameterizedintegertype\ for the same parameter; + \item substituting the parameter expressions from $\eqsthree$ in $\calleeparamt$ + yields $\calleeparamtrenamed$\ProseOrTypeError; + \item applying $\assocopt$ to $\eqsthree$ and $\vs$ yields the expression $\callerparame$ + (that is, the parameter $\vs$ is associated with the expression \\ + $\callerparame$); + \item annotating the expression $\callerparame$ in $\tenv$ yields \\ + $(\callerparamt, \Ignore)$\ProseOrTypeError; + \item checking that $\callerparamt$ \typesatisfies\ $\calleeparamtrenamed$ in $\tenv$ yields + $\True$\ProseOrTypeError; + \end{itemize} + \end{itemize} + \item applying $\checkcalleeparams$ to $\calleeparamsone$ and $\eqsthree$ in $\tenv$ + yields \\ $\True$\ProseOrTypeError. + \end{itemize} +\end{itemize} + +\subsubsection{Formally} +\begin{mathpar} +\inferrule[empty]{ +}{ + \checkcalleeparams(\tenv, \overname{\emptylist}{\calleeparams}, \eqsthree) \typearrow \True +} +\and +\inferrule[no\_type]{ + \calleeparams = [(\Ignore, \None)] \concat \calleeparamsone\\ + \checkcalleeparams(\tenv, \calleeparamsone, \eqsthree) \typearrow \True \OrTypeError +}{ + \checkcalleeparams(\tenv, \calleeparams, \eqsthree) \typearrow \True +} +\and +\inferrule[parameterized]{ + \calleeparams = [(\vs, \langle\TInt(\parameterized(\vs))\rangle)] \concat \calleeparamsone\\ + \checkcalleeparams(\tenv, \calleeparamsone, \eqsthree) \typearrow \True \OrTypeError +}{ + \checkcalleeparams(\tenv, \calleeparams, \eqsthree) \typearrow \True +} +\and +\inferrule[other]{ + \calleeparams = [(\vs, \langle\calleeparamt\rangle)] \concat \calleeparamsone\\ + \calleeparamt \neq \TInt(\parameterized(\vs))\\ + \renametyeqs(\tenv, \eqsthree, \calleeparamt) \typearrow \calleeparamtrenamed \OrTypeError\\\\ + \assocopt(\eqsthree, \vs) \typearrow \langle \callerparame \rangle\\ + \annotateexpr{\tenv, \callerparame} \typearrow \callerparamt \OrTypeError\\\\ + \checktypesat(\tenv, \callerparamt, \calleeparamtrenamed) \typearrow \True \OrTypeError\\\\ + \checkcalleeparams(\tenv, \calleeparamsone, \eqsthree) \typearrow \True \OrTypeError +}{ + \checkcalleeparams(\tenv, \calleeparams, \eqsthree) \typearrow \True +} +\end{mathpar} + +\subsubsection{TypingRule.RenameTyEqs \label{sec:TypingRule.RenameTyEqs}} +\hypertarget{def-renametyeqs}{} +The function +\[ +\renametyeqs( + \overname{\staticenvs}{\tenv} \aslsep + \overname{(\identifier\times\expr)^*}{\eqs} \aslsep + \overname{\ty}{\tty} +) \aslto +\overname{\ty}{\newty} \cup \overname{\TTypeError}{\TypeErrorConfig} +\] +transforms the type $\tty$ in the static environment $\tenv$, +by substituting parameter names with their corresponding expressions in +$\eqs$, yielding the type $\newty$. +\ProseOtherwiseTypeError + +\subsubsection{Prose} +One of the following applies: +\begin{itemize} + \item All of the following apply (\textsc{t\_bits}): + \begin{itemize} + \item $\tty$ is a bitvector type with width expression $\ve$ and fields $\fields$, that is, $\TBits(\ve, \fields)$; + \item applying $\substexprnormalize$ to $\eqs$ and $\ve$ in $\tenv$ yields the expression $\newe$; + \item define $\newty$ as a bitvector type with with expression $\newe$ and fields $\fields$. + \end{itemize} + + \item All of the following apply (\textsc{t\_int\_wellconstrained}): + \begin{itemize} + \item $\tty$ is a well-constrained integer type with constraints $\constraints$; + \item applying $\substconstraint$ to each constraint $\constraints[\vi]$, for $\vi$ in \\ + $\listrange(\constraints)$, yields the constraint $\newc_\vi$; + \item define $\newconstraints$ as the list of constraints $\newc_\vi$, for $\vi$ in \\ + $\listrange(\constraints)$; + \item define $\newty$ as the well-constrained integer type with constraints \\ + $\newconstraints$. + \end{itemize} + + \item All of the following apply (\textsc{t\_int\_parameterized}): + \begin{itemize} + \item $\tty$ is a \parameterizedintegertype\ for the parameter $\name$; + \item applying $\substexprnormalize$ to $\eqs$ and the expression $\EVar(\name)$ yields $\ve$; + \item define $\newty$ as the well-constrained integer type with the single constraint for $\ve$, that is, + $\TInt(\wellconstrained(\ConstraintExact(\ve)))$. + \end{itemize} + + \item All of the following apply (\textsc{t\_tuple}): + \begin{itemize} + \item $\tty$ is the tuple type over the list of tuples $\tys$, that is, $\TTuple(\tys)$; + \item applying $\renametyeqs$ to $\eqs$ and the type $\tys[\vi]$, for each $\vi$ in \\ + $\listrange(\tys)$, yields the type $\newty_\vi$; + \item define $\newtys$ as the list of types $\newty_\vi$, for each $\vi$ in $\listrange(\tys)$; + \item define $\newty$ as the tuple type over $\newtys$, that is, $\TTuple(\newtys)$. + \end{itemize} + + \item All of the following apply (\textsc{other}): + \begin{itemize} + \item $\tty$ is not one of the types in the previous cases, + that is, $\tty$ is not a bitvector type, nor an integer type, nor a tuple type; + \item $\newty$ is $\tty$. + \end{itemize} +\end{itemize} + +\subsubsection{Formally} +\begin{mathpar} +\inferrule[t\_bits]{ + \substexprnormalize(\tenv, \eqs, \ve) \typearrow \newe +}{ + \renametyeqs(\tenv, \eqs, \overname{\TBits(\ve, \fields)}{\tty}) \typearrow \overname{\TBits(\newe, \fields)}{\newty} +} +\and +\inferrule[t\_int\_wellconstrained]{ + \vi\in\listrange(\constraints): \substconstraint(\tenv, \constraints[\vi]) \typearrow \newc_\vi\\ + \newconstraints \eqdef [\vi\in\listrange(\constraints): \newc_\vi]\\ + \newty \eqdef \TInt(\wellconstrained(\newconstraints)) +}{ + \renametyeqs(\tenv, \eqs, \overname{\TInt(\wellconstrained(\constraints))}{\tty}) \typearrow + \newty +} +\and +\inferrule[t\_int\_parameterized]{ + \substexprnormalize(\eqs, \EVar(\name)) \typearrow \ve\\ + \newty \eqdef \TInt(\wellconstrained(\ConstraintExact(\ve))) +}{ + \renametyeqs(\tenv, \eqs, \overname{\TInt(\parameterized(\name))}{\tty}) \typearrow \newty +} +\and +\inferrule[t\_tuple]{ + \vi\in\listrange(\tys): \renametyeqs(\eqs, \tys[\vi]) \typearrow \newty_\vi\\ + \newtys \eqdef [\vi\in\listrange(\tys): \newty_\vi] +}{ + \renametyeqs(\tenv, \eqs, \overname{\TTuple(\tys)}{\tty}) \typearrow + \overname{\TTuple(\newtys)}{\newty} +} +\and +\inferrule[other]{ + \astlabel(\tty) \not\in \{\TBits, \TInt, \TTuple\} +}{ + \renametyeqs(\tenv, \eqs, \tty) \typearrow \overname{\tty}{\newty} +} +\end{mathpar} + +\subsubsection{TypingRule.SubstExprNormalize \label{sec:TypingRule.SubstExprNormalize}} +\hypertarget{def-substexprnormalize}{} +The function +\[ +\substexprnormalize( + \overname{\staticenvs}{\tenv} \aslsep + \overname{(\identifier\times\expr)^*}{\eqs} \aslsep + \overname{\expr}{\ve} +) \aslto \overname{\newe}{\expr} +\] +transforms the expression $\ve$ in the static environment $\tenv$, +by substituting parameter names with their corresponding expressions in +$\eqs$, and then attempting to symbolically simplify the result, yielding the expression $\newe$. +\ProseOtherwiseTypeError + +\subsubsection{Prose} +All of the following apply: +\begin{itemize} + \item transforming $\ve$ in the static environment $\tenv$, by substituting the parameter expressions + $\eqs$, yields $\veone$; + \item symbolically simplifying $\veone$ in $\tenv$ yields $\newe$. +\end{itemize} + +\subsubsection{Formally} +\begin{mathpar} +\inferrule{ + \substexpr(\tenv, \ve) \typearrow \veone\\ + \normalize(\tenv, \veone) \typearrow \newe +}{ + \substexprnormalize(\tenv, \eqs, \ve) \typearrow \newe +} +\end{mathpar} + +\subsubsection{TypingRule.SubstExpr \label{sec:TypingRule.SubstExpr}} +\hypertarget{def-substexpr}{} +The function +\[ +\substexpr( + \overname{\staticenvs}{\tenv} \aslsep + \overname{(\identifier\times\expr)^*}{\substs} \aslsep + \overname{\expr}{\ve} +) \aslto \overname{\expr}{\newe} +\] +transforms the expression $\ve$ in the static environment $\tenv$, +by substituting parameter names with their corresponding expressions in +$\substs$, yielding the expression $\newe$. +\ProseOtherwiseTypeError + +\subsubsection{Prose} +One of the following applies: +\begin{itemize} + \item All of the following apply (\textsc{e\_var\_in\_substs}): + \begin{itemize} + \item $\ve$ is a variable expression for the identifier $\vs$, that is, $\EVar(\vs)$; + \item applying $\assocopt$ to $\vs$ and $\substs$ yields the expression $\newe$. + That is, $\vs$ is a parameter with an associated expression; + \end{itemize} + + \item All of the following apply (\textsc{e\_var\_not\_in\_substs}): + \begin{itemize} + \item $\ve$ is the variable expression for the identifier $\vs$, that is, $\EVar(\vs)$; + \item applying $\assocopt$ to $\vs$ and $\substs$ yields $\None$. + That is, $\vs$ is not a parameter with an associated expression; + \item define $\newe$ is $\ve$. + \end{itemize} + + \item All of the following apply (\textsc{e\_unop}): + \begin{itemize} + \item $\ve$ is the unary operator expression for the operator $\op$ and expression $\ve$, that is, $\EUnop(\op, \veone)$; + \item applying $\substexpr$ to $\substs$ and $\veone$ in $\tenv$ yields $\veonep$; + \item define $\newe$ as the unary operator expression for the operator $\op$ and expression $\veonep$, that is, $\EUnop(\op, \veonep)$. + \end{itemize} + + \item All of the following apply (\textsc{e\_binop}): + \begin{itemize} + \item $\ve$ is the binary operator expression for the operator $\op$ and expressions $\veone$ and $\vetwo$, that is, $\EBinop(\op, \veone, \vetwo)$; + \item applying $\substexpr$ to $\substs$ and $\veone$ in $\tenv$ yields $\veonep$; + \item applying $\substexpr$ to $\substs$ and $\vetwo$ in $\tenv$ yields $\vetwop$; + \item define $\newe$ as the unary operator expression for the operator $\op$ and expression $\veonep$, that is, $\EUnop(\op, \veonep)$. + \end{itemize} + + \item All of the following apply (\textsc{e\_cond}): + \begin{itemize} + \item $\ve$ is the conditional expression for expressions $\veone$, $\vetwo$, and $\vethree$, that is, \\ + $\ECond(\veone, \vetwo, \vethree)$; + \item applying $\substexpr$ to $\substs$ and $\veone$ in $\tenv$ yields $\veonep$; + \item applying $\substexpr$ to $\substs$ and $\vetwo$ in $\tenv$ yields $\vetwop$; + \item applying $\substexpr$ to $\substs$ and $\vethree$ in $\tenv$ yields $\vethreep$; + \item define $\newe$ as the conditional expression for expressions $\veonep$, $\vetwop$, and $\vethreep$, that is, $\ECond(\veonep, \vetwop, \vethreep)$. + \end{itemize} + + \item All of the following apply (\textsc{e\_concat}): + \begin{itemize} + \item $\ve$ is the concatenation of expressions $\ves$, that is, $\EConcat(\ves)$; + \item applying $\substexpr$ to $\substs$ and every expression $\ves[\vi]$, for $\vi$ in \\ + $\listrange(\ves)$ yields $\newes_\vi$; + \item define $\vesp$ as the list of expressions $\newes_\vi$, for $\vi$ in $\listrange(\ves)$; + \item define $\newe$ as the concatenation of expressions $\vesp$, that is, $\EConcat(\vesp)$. + \end{itemize} + + \item All of the following apply (\textsc{e\_call}): + \begin{itemize} + \item $\ve$ is the call expression for subprogram $\vx$ with arguments $\vargs$ and parameter expressions $\paramargs$, + that is, $\ECall(\vx, \vargs, \paramargs)$; + \item applying $\substexpr$ to $\substs$ and every argument expression $\vargs[\vi]$, for $\vi$ in + $\listrange(\vargs)$ yields $\ve_\vi$; + \item define $\vargsp$ as $\ve_\vi$ for each $\vi$ in $\listrange(\vargs)$; + \item define $\newe$ as the call expression for subprogram $\vx$ with arguments $\vargsp$ and parameter expressions $\paramargs$, + that is, $\ECall(\vx, \vargsp, \paramargs)$. + \end{itemize} + + \item All of the following apply (\textsc{e\_getarray}): + \begin{itemize} + \item $\ve$ is the \arrayaccess\ expression for base expression $\veone$ and index expression $\vetwo$, + that is, $\EGetArray(\veone, \vetwo)$; + \item applying $\substexpr$ to $\substs$ and $\veone$ in $\tenv$ yields $\veonep$; + \item applying $\substexpr$ to $\substs$ and $\vetwo$ in $\tenv$ yields $\vetwop$; + \item define $\newe$ as the \arrayaccess\ expression for base expression $\veonep$ and index expression $\vetwop$, + that is, $\EGetArray(\veonep, \vetwop)$. + \end{itemize} + + \item All of the following apply (\textsc{e\_getfield}): + \begin{itemize} + \item $\ve$ is the field access expression for base expression $\ve$ and field $\vx$, + that is, $\EGetField(\veone, \vx)$; + \item applying $\substexpr$ to $\substs$ and $\veone$ in $\tenv$ yields $\veonep$; + \item define $\newe$ as the field access expression for base expression $\ve$ and field $\vx$, + that is, $\EGetField(\veonep, \vx)$. + \end{itemize} + + \item All of the following apply (\textsc{e\_getfields}): + \begin{itemize} + \item $\ve$ is the access to fields $\fields$ with base expression $\veone$, that is, \\ + $\EGetFields(\veone, \fields)$; + \item applying $\substexpr$ to $\substs$ and $\veone$ in $\tenv$ yields $\veonep$; + \item define $\newe$ as the access to fields $\fields$ with base expression $\veonep$, that is, $\EGetFields(\veonep, \fields)$. + \end{itemize} + + \item All of the following apply (\textsc{e\_getitem}): + \begin{itemize} + \item $\ve$ is the access to tuple item $\vi$ of the tuple expression $\veone$, that is, \\ + $\EGetItem(\veone, \vi)$; + \item applying $\substexpr$ to $\substs$ and $\veone$ in $\tenv$ yields $\veonep$; + \item define $\newe$ as the access to tuple item $\vi$ of the tuple expression $\veonep$, that is, \\ + $\EGetItem(\veonep, \vi)$. + \end{itemize} + + \item All of the following apply (\textsc{e\_pattern}): + \begin{itemize} + \item $\ve$ is the pattern expression of expression $\veone$ and patterns $\vps$, that is, \\ + $\EPattern(\veone, \vps)$; + \item applying $\substexpr$ to $\substs$ and $\veone$ in $\tenv$ yields $\veonep$; + \item define $\newe$ as the pattern expression of expression $\veonep$ and patterns $\vps$, that is, $\EPattern(\veonep, \vps)$. + \end{itemize} + + \item All of the following apply (\textsc{e\_record}): + \begin{itemize} + \item $\ve$ is the record expression of record type $\vt$ and list of fields $\fields$; + \item for every pair $(\vx,\veone)$ in $\fields$, applying $\substexpr$ to $\substs$ $\veone$ in $\tenv$ yields $\veonep_\vx$; + \item define $\fieldsp$ as the list of pairs $(\vx,\veonep_\vx)$ for every pair $(\vx,\veone)$ in $\fields$; + \item define $\newe$ as the record expression of record type $\vt$ and list of fields $\fieldsp$. + \end{itemize} + + \item All of the following apply (\textsc{e\_slice}): + \begin{itemize} + \item $\ve$ is the slicing expression for sub-expression $\veone$ and list of slices $\vslices$, that is, $\ESlice(\veone, \vslices)$; + \item applying $\substexpr$ to $\veone$ in $\tenv$ yields $\veonep$; + \item define $\newe$ as slicing expression for sub-expression $\veonep$ and list of slices $\vslices$, that is, $\ESlice(\veonep, \vslices)$. + \end{itemize} + + \item All of the following apply (\textsc{e\_tuple}): + \begin{itemize} + \item $\ve$ is the tuple expression of expressions $\ves$, that is, $\ETuple(\ves)$; + \item applying $\substexpr$ to $\substs$ and every expression $\ves[\vi]$ in $\tenv$, for every $\vi$ in $\listrange(\ves)$ + yields $\newe_\vi$; + \item define $\vesp$ as the list of expressions $\newe_\vi$, for every $\vi$ in $\listrange(\ves)$; + \item define $\newe$ as the tuple expression of expressions $\vesp$, that is, $\ETuple(\vesp)$. + \end{itemize} + + \item All of the following apply (\textsc{e\_atc}): + \begin{itemize} + \item $\ve$ is the type assertion of expression $\veone$ and type $\vt$, that is, $\EATC(\veone, \vt)$; + \item applying $\substexpr$ to $\substs$ and $\veone$ in $\tenv$ yields $\veonep$; + \item define $\newe$ as the type assertion of expression $\veonep$ and type $\vt$, that is, $\EATC(\veonep, \vt)$. + \end{itemize} + + \item All of the following apply (\textsc{other}): + \begin{itemize} + \item $\ve$ is either a literal expression or an unknown value expression; + \item define $\newe$ as $\ve$. + \end{itemize} +\end{itemize} + +\subsubsection{Formally} +\begin{mathpar} +\inferrule[e\_var\_in\_substs]{ + \assocopt(\vs, \substs) \typearrow \langle\newe\rangle +}{ + \substexpr(\tenv, \substs, \overname{\EVar(\vs)}{\ve}) \typearrow \newe +} +\end{mathpar} + +\begin{mathpar} +\inferrule[e\_var\_not\_in\_substs]{ + \assocopt(\vs, \substs) \typearrow \None +}{ + \substexpr(\tenv, \substs, \overname{\EVar(\vs)}{\ve}) \typearrow \overname{\ve}{\newe} +} +\end{mathpar} + +\begin{mathpar} +\inferrule[e\_unop]{ + \substexpr(\tenv, \substs, \veone) \typearrow \veonep\ +}{ + \substexpr(\tenv, \substs, \overname{\EUnop(\op, \veone)}{\ve}) \typearrow \overname{\EUnop(\op, \veonep)}{\newe} +} +\end{mathpar} + +\begin{mathpar} +\inferrule[e\_binop]{ + \substexpr(\tenv, \substs, \veone) \typearrow \veonep\\ + \substexpr(\tenv, \substs, \vetwop) \typearrow \vetwop +}{ + \substexpr(\tenv, \substs, \overname{\EBinop(\op, \veone, \vetwo)}{\ve}) \typearrow \overname{\EBinop(\op, \veonep, \vetwop)}{\newe} +} +\end{mathpar} + +\begin{mathpar} +\inferrule[e\_cond]{ + \substexpr(\tenv, \substs, \veone) \typearrow \veonep\\ + \substexpr(\tenv, \substs, \vetwop) \typearrow \vetwop\\ + \substexpr(\tenv, \substs, \vethreep) \typearrow \vethreep\\ +}{ + \substexpr(\tenv, \substs, \overname{\ECond(\veone, \vetwo, \vethree)}{\ve}) \typearrow \overname{\ECond(\veonep, \vetwop, \vethreep)}{\newe} +} +\end{mathpar} + +\begin{mathpar} +\inferrule[e\_concat]{ + \vi\in\listrange(\ves): \substexpr(\tenv, \substs, \ves[\vi]) \typearrow \newes_\vi\\ + \vesp \eqdef [\vi\in\listrange(\ves): \newes_\vi] +}{ + \substexpr(\tenv, \substs, \overname{\EConcat(\ves)}{\ve}) \typearrow \overname{\EConcat(\vesp)}{\newe} +} +\end{mathpar} + +\begin{mathpar} +\inferrule[e\_call]{ + \vi\in\listrange(\vargs): \substexpr(\tenv, \substs, \vargs[\vi]) \typearrow \ve_\vi\\ + \vargsp \eqdef [\vi\in\listrange(\vargs): \ve_\vi] +}{ + { + \begin{array}{r} + \substexpr(\tenv, \substs, \overname{\ECall(\vx, \vargs, \paramargs)}{\ve}) \typearrow \\ \overname{\ECall(\vx, \vargsp, \paramargs)}{\newe} + \end{array} + } +} +\end{mathpar} + +\begin{mathpar} +\inferrule[e\_getarray]{ + \substexpr(\tenv, \substs, \veone) \typearrow \veonep\\ + \substexpr(\tenv, \substs, \vetwop) \typearrow \vetwop +}{ + \substexpr(\tenv, \substs, \overname{\EGetArray(\veone, \vetwo)}{\ve}) \typearrow \overname{\EGetArray(\veonep, \vetwop)}{\newe} +} +\end{mathpar} + +\begin{mathpar} +\inferrule[e\_getfield]{ + \substexpr(\tenv, \substs, \veone) \typearrow \veonep +}{ + \substexpr(\tenv, \substs, \overname{\EGetField(\veone, \vx)}{\ve}) \typearrow \overname{\EGetField(\veonep, \vx)}{\newe} +} +\end{mathpar} + +\begin{mathpar} +\inferrule[e\_getfields]{ + \substexpr(\tenv, \substs, \veone) \typearrow \veonep +}{ + \substexpr(\tenv, \substs, \overname{\EGetFields(\veone, \fields)}{\ve}) \typearrow \overname{\EGetFields(\veonep, \fields)}{\newe} +} +\end{mathpar} + +\begin{mathpar} +\inferrule[e\_getitem]{ + \substexpr(\tenv, \substs, \veone) \typearrow \veonep +}{ + \substexpr(\tenv, \substs, \overname{\EGetItem(\veone, \vi)}{\ve}) \typearrow \overname{\EGetItem(\veonep, \vi)}{\newe} +} +\end{mathpar} + +\begin{mathpar} +\inferrule[e\_pattern]{ + \substexpr(\tenv, \substs, \veone) \typearrow \veonep +}{ + \substexpr(\tenv, \substs, \overname{\EPattern(\veone, \vps)}{\ve}) \typearrow \overname{\EPattern(\veonep, \vps)}{\newe} +} +\end{mathpar} + +\begin{mathpar} +\inferrule[e\_record]{ + (\vx, \veone)\in\fields: \substexpr(\tenv, \substs, \veone) \typearrow \veone_\vx\\ + \fieldsp \eqdef [(\vx, \veone)\in\fields: (\vx, \veone_\vx)] +}{ + \substexpr(\tenv, \substs, \overname{\ERecord(\vt, \fields)}{\ve}) \typearrow \overname{\ERecord(\vt, \fieldsp)}{\newe} +} +\end{mathpar} + +\begin{mathpar} +\inferrule[e\_slice]{ + \substexpr(\tenv, \substs, \veone) \typearrow \veonep +}{ + \substexpr(\tenv, \substs, \overname{\ESlice(\veone, \slices)}{\ve}) \typearrow \overname{\ESlice(\veonep, \slices)}{\newe} +} +\end{mathpar} + +\begin{mathpar} +\inferrule[e\_tuple]{ + \vi\in\listrange(\ves): \substexpr(\tenv, \substs, \ves[\vi]) \typearrow \newe_\vi\\ + \vesp \eqdef [\vi\in\listrange(\ves): \newe_\vi] +}{ + \substexpr(\tenv, \substs, \overname{\ETuple(\ves)}{\ve}) \typearrow \overname{\ETuple(\vesp)}{\newe} +} +\end{mathpar} + +\begin{mathpar} +\inferrule[e\_atc]{ + \substexpr(\tenv, \substs, \veone) \typearrow \veonep +}{ + \substexpr(\tenv, \substs, \overname{\EATC(\veone, \vt)}{\ve}) \typearrow \overname{\EATC(\veonep, \vt)}{\newe} +} +\end{mathpar} + +\begin{mathpar} +\inferrule[other]{ + \astlabel(\ve) \in \{\ELiteral, \EUnknown\}\ +}{ + \substexpr(\tenv, \substs, \ve) \typearrow \overname{\ve}{\newe} +} +\end{mathpar} + +\CodeSubsection{\SubstExprBegin}{\SubstExprEnd}{../ASTUtils.ml} + +\subsubsection{TypingRule.SubstConstraint \label{sec:TypingRule.SubstConstraint}} +\hypertarget{def-substconstraint}{} +The function +\[ +\substconstraint( + \overname{\staticenvs}{\tenv} \aslsep + \overname{(\identifier\times\expr)^*}{\eqs} \aslsep + \overname{\intconstraint}{\vc} +) \aslto \overname{\newc}{\intconstraint} +\] +transforms the integer constraint $\vc$ in the static environment $\tenv$, +by substituting parameter names with their corresponding expressions in +$\eqs$, and then attempting to symbolically simplify the result, +yielding the integer constraint $\newc$. +\ProseOtherwiseTypeError + +\subsubsection{Prose} +One of the following applies: +\begin{itemize} + \item All of the following apply (\textsc{exact}): + \begin{itemize} + \item $\vc$ is an exact constraint for the expression $\ve$, that is, $\ConstraintExact(\ve)$; + \item applying $\substexprnormalize$ in $\tenv$ to $\eqs$ and $\ve$ yields $\newe$; + \item define $\newc$ as the exact constraint for the expression $\newe$, that is, \\ + $\ConstraintExact(\newe)$. + \end{itemize} + + \item All of the following apply (\textsc{range}): + \begin{itemize} + \item $\vc$ is a range constraint for the expressions $\veone$ and $\vetwo$, that is, \\ + $\ConstraintRange(\veone, \vetwo)$; + \item applying $\substexprnormalize$ in $\tenv$ to $\eqs$ and $\veone$ yields $\veonep$; + \item applying $\substexprnormalize$ in $\tenv$ to $\eqs$ and $\vetwo$ yields $\vetwop$; + \item define $\newc$ as the range constraint for the expressions $\veonep$ and $\vetwop$, that is, $\ConstraintRange(\veonep, \vetwop)$. + \end{itemize} +\end{itemize} + +\subsubsection{Formally} +\begin{mathpar} +\inferrule[exact]{ + \substexprnormalize(\tenv, \eqs, \ve) \typearrow \newe +}{ + \substconstraint(\tenv, \eqs, \overname{\ConstraintExact(\ve)}{\vc}) \typearrow \overname{\ConstraintExact(\newe)}{\newc} +} +\and +\inferrule[range]{ + \substexprnormalize(\tenv, \eqs, \veone) \typearrow \veonep\\ + \substexprnormalize(\tenv, \eqs, \vetwo) \typearrow \vetwop +}{ + \substconstraint(\tenv, \eqs, \overname{\ConstraintRange(\veone, \vetwo)}{\vc}) \typearrow \overname{\ConstraintRange(\veonep, \vetwop)}{\newc} +} +\end{mathpar} + +\subsubsection{TypingRule.CheckArgsTypeSat \label{sec:TypingRule.CheckArgsTypeSat}} +\hypertarget{def-checkargstypesat}{} +The function +\[ +\begin{array}{r} + \checkargstypesat( + \overname{\staticenvs}{\tenv} \aslsep + \overname{(\identifier\times\ty)^*}{\calleeargs} \aslsep + \overname{\ty^*}{\callerargtypes} \aslsep + \overname{(\identifier\times\expr)^*}{\eqsthree} + ) \aslto \\ + \{\True\}\ \cup \overname{\TTypeError}{\TypeErrorConfig} +\end{array} +\] +checks that the types $\callerargtypes$ \typesatisfy\ the types of the corresponding +formal arguments $\calleeargs$ with the parameters substituted with their corresponding +arguments as per $\eqsthree$ and results in a type error otherwise. + +\subsubsection{Prose} +One of the following applies: +\begin{itemize} + \item All of the following apply (\textsc{empty}): + \begin{itemize} + \item both $\calleeargs$ and $\callerargtypes$ are empty; + \item the result is $\True$. + \end{itemize} + + \item All of the following apply (\textsc{non\_empty}): + \begin{itemize} + \item view $\calleeargs$ as a list with \head\ $(\calleeargname, \calleearg)$ and \tail\ $\calleeargsone$; + \item view $\callerargtypes$ as a list with \head\ $\callerarg$ and \tail\ \\ + $\callerargtypesone$; + \item applying $\renametyeqs$ to $\eqsthree$ and $\calleearg$ in $\tenv$ + to substitute parameter arguments in $\calleearg$ yields $\calleeargone$\ProseOrTypeError; + \item checking that $\callerarg$ \typesatisfies\ $\calleeargone$ in $\tenv$ yields $\True$\ProseOrTypeError; + \item applying $\checkargstypesat$ to $\calleeargsone$, $\callerargtypesone$, \\ + and $\eqsthree$ in $\tenv$ + yields $\True$\ProseOrTypeError; + \item the result is $\True$. + \end{itemize} +\end{itemize} + +\subsubsection{Formally} +We note that it is guaranteed by TypingRule.AnnotateCallArgTyped +that $\vargs$ and $\callerargstyped$ have the same length. + +\begin{mathpar} +\inferrule[empty]{}{ + \checkargstypesat(\tenv, \overname{\emptylist}{\calleeargs}, \overname{\emptylist}{\callerargtypes}, \eqsthree) + \typearrow \True +} +\and +\inferrule[non\_empty]{ + \calleeargs \eqname [(\calleeargname, \calleearg)] \concat \calleeargsone\\ + \callerargtypes \eqname [\callerarg] \concat \callerargtypesone\\ + \renametyeqs(\tenv, \eqsthree, \calleearg) \typearrow \calleeargone\OrTypeError\\\\ + \checktypesat(\tenv, \callerarg, \calleeargone) \typearrow \True\OrTypeError\\\\ + \checkargstypesat(\tenv, \calleeargsone, \callerargtypesone, \eqsthree) \typearrow \True +}{ + \checkargstypesat(\tenv, \calleeargs, \callerargtypes, \eqsthree) \typearrow \True +} +\end{mathpar} + +\subsubsection{TypingRule.AnnotateParameterDefining \label{sec:TypingRule.AnnotateParameterDefining}} +\hypertarget{def-annotateparameterdefining}{} +The function +\[ + \annotateparameterdefining + \left( + \begin{array}{c} + \overname{\staticenvs}{\tenv} \aslsep\\ + \overname{(\identifier\times\expr)^*}{\eqsone} \aslsep\\ + \overname{(\identifier\times\ty)^*}{\vargs} \aslsep\\ + \overname{(\ty\times\expr)^*}{\callerargstyped} \aslsep\\ + \overname{(\identifier\times\langle\ty\rangle)^*}{\calleeparams} + \end{array} + \right) + \aslto + \begin{array}{c} + \overname{(\identifier\times\expr)^*}{\eqs} \cup \\ + \overname{\TTypeError}{\TypeErrorConfig} + \end{array} +\] +checks that all parameter-defining arguments +in $\calleeparams$ are \staticallyevaluable\ constrained integers. +The result --- $\eqs$ --- is the list of parameter identifiers and their corresponding expressions, +added to $\eqsone$. +\ProseOtherwiseTypeError + +\subsubsection{Prose} +One of the following applies: +\begin{itemize} + \item All of the following apply (\textsc{empty}): + \begin{itemize} + \item both $\vargs$ and $\callerargstyped$ are empty; + \item define $\eqs$ as $\eqsone$. + \end{itemize} + + \item All of the following apply: + \begin{itemize} + \item view $\vargs$ as a list with \head\ $(\calleex, \Ignore)$ and \tail\ $\vargsone$; + \item view $\callerargstyped$ as a list with \head\ $(\callerty, \callere)$ and \tail\ $\callerargstypedone$; + \item define $\calleeargisparam$ as $\True$ if and only if $\calleex$ is listed as a parameter in $\calleeparams$; + \item One of the following applies: + \begin{itemize} + \item All of the following apply (\textsc{arg\_is\_param}): + \begin{itemize} + \item $\calleeargisparam$ is $\True$; + \item checking that $\callere$ is \staticallyevaluable\ in $\tenv$ yields $\True$\ProseOrTypeError; + \item checking that $\callerty$ is a constrained integer in $\tenv$ yields \\ + $\True$\ProseOrTypeError; + \item applying $\annotateparameterdefining$ to $\vargsone$, \\ + $\callerargstypedone$, $\eqsone$ in $\tenv$ yields $\eqstwo$\ProseOrTypeError; + \item define $\eqs$ as a list with \head\ $(\calleex, \callere)$ and \tail\ $\eqstwo$. + \end{itemize} + + \item All of the following apply (\textsc{arg\_is\_not\_param}): + \begin{itemize} + \item $\calleeargisparam$ is $\False$; + \item applying $\annotateparameterdefining$ to $\vargsone$, \\ + $\callerargstypedone$, $\eqsone$ in $\tenv$ yields $\eqs$\ProseOrTypeError. + \end{itemize} + \end{itemize} + \end{itemize} +\end{itemize} + +\subsubsection{Formally} +We note that it is guaranteed by TypingRule.AnnotateCallArgTyped +that $\vargs$ and $\callerargstyped$ have the same length. + +\begin{mathpar} +\inferrule[empty]{}{ + { + \begin{array}{r} + \annotateparameterdefining(\tenv, \eqsone, \overname{\emptylist}{\vargs}, \overname{\emptylist}{\callerargstyped}, \calleeparams) + \typearrow \\ + \overname{\eqsone}{\eqs} + \end{array} + } +} +\end{mathpar} + +\begin{mathpar} +\inferrule[arg\_is\_param]{ + \vargs \eqname [(\calleex, \Ignore)] \concat \vargsone\\ + \callerargstyped \eqname [(\callerty, \callere)] \concat \callerargstypedone\\ + { + \left(\begin{array}{l} + \calleeargisparam \eqdef \\ + \exists \vi\in\listrange(\calleeparams).\ \calleeparams[\vi]=(\calleex, \Ignore) + \end{array}\right) + }\\\\ + \commonprefixline\\\\ + \calleeargisparam\ = \True\\ + \checkstaticallyevaluable(\tenv, \callere) \typearrow \True\OrTypeError\\\\ + \checkconstrainedinteger(\tenv, \callerty) \typearrow \True\OrTypeError\\\\ + { + \begin{array}{r} + \annotateparameterdefining(\tenv, \vargsone, \callerargstypedone, \eqsone) \typearrow \\ \eqstwo \OrTypeError + \end{array} + }\\ + \eqs \eqdef [(\calleex, \callere)] \concat \eqstwo +}{ + { + \annotateparameterdefining + \left( + \begin{array}{c} + \tenv, \\ + \eqsone, \\ + \vargs, \\ + \callerargstyped, \\ + \calleeparams + \end{array} + \right) + \typearrow \eqs \OrTypeError + } +} +\end{mathpar} + +\begin{mathpar} +\inferrule[arg\_is\_not\_param]{ + \vargs \eqname [(\calleex, \Ignore)] \concat \vargsone\\ + \callerargstyped \eqname [(\callerty, \callere)] \concat \callerargstypedone\\ + { + \left(\begin{array}{l} + \calleeargisparam \eqdef \\ + \exists \vi\in\listrange(\calleeparams).\ \calleeparams[\vi]=(\calleex, \Ignore) + \end{array}\right) + }\\\\ + \commonprefixline\\\\ + \calleeargisparam = \False\\ + \annotateparameterdefining(\tenv, \vargsone, \callerargstypedone, \eqsone) \typearrow \eqs\\ +}{ + { + \annotateparameterdefining + \left( + \begin{array}{c} + \tenv, \\ + \eqsone, \\ + \vargs, \\ + \callerargstyped, \\ + \calleeparams + \end{array} + \right) + \typearrow \eqs \OrTypeError + } +} +\end{mathpar} + +\subsubsection{TypingRule.AnnotateRetTy \label{sec:TypingRule.AnnotateRetTy}} +\hypertarget{def-annotateretty}{} +The function +\[ +\begin{array}{r} +\annotateretty( + \overname{\staticenvs}{\tenv} \aslsep + \overname{\subprogramtype}{\calltype} \aslsep + \overname{\langle\ty\rangle}{\calleerettyopt} + \overname{(\identifier\times\expr)^*}{\eqsthree} +) \aslto \\ +\overname{\langle\ty\rangle}{\rettyopt} +\cup \overname{\TTypeError}{\TypeErrorConfig} +\end{array} +\] +annotates the \optional\ return type $\calleerettyopt$ given with the subprogram type +$\calltype$ with respect to the parameter expressions $\eqsthree$, +yielding the \optional\ annotated type $\rettyopt$. +\ProseOtherwiseTypeError + +\subsubsection{Prose} +One of the following applies: +\begin{itemize} + \item All of the following apply (\textsc{function\_or\_getter}): + \begin{itemize} + \item $\calltype$ is one of $\STFunction$, $\STGetter$, or $\STEmptyGetter$; + \item $\calleerettyopt$ is $\langle\tty\rangle$; + \item applying $\renametyeqs$ to $\eqsthree$ and $\tty$ yields $\ttyone$\ProseOrTypeError; + \item $\rettyopt$ is $\langle\ttyone\rangle$. + \end{itemize} + + \item All of the following apply (\textsc{procedure\_or\_setter}): + \begin{itemize} + \item $\calltype$ is one of $\STProcedure$, $\STSetter$, or $\STEmptySetter$; + \item $\calleerettyopt$ is $\None$; + \item define $\rettyopt$ as $\None$. + \end{itemize} + + \item All of the following apply (\textsc{ret\_type\_mismatch}): + \begin{itemize} + \item the condition that $\calltype$ is one of $\STProcedure$, $\STSetter$, or \\ + $\STEmptySetter$ + if and only if $\calleerettyopt$ is $\None$ does not hold; + \item the result is a type error indicating the mismatch. + \end{itemize} +\end{itemize} + +\subsubsection{Formally} +\begin{mathpar} +\inferrule[function\_or\_getter]{ + \calltype \in \{\STFunction, \STGetter, \STEmptyGetter\}\\ + \renametyeqs(\eqsthree, \tty) \typearrow \ttyone \OrTypeError +}{ + \annotateretty(\tenv, \calltype, \overname{\langle\tty\rangle}{\calleerettyopt}, \eqsthree) \typearrow + \overname{\langle\ttyone\rangle}{\rettyopt} +} +\end{mathpar} + +\begin{mathpar} +\inferrule[procedure\_or\_setter]{ + \calltype \in \{\STProcedure, \STSetter, \STEmptySetter\}\\ +}{ + \annotateretty(\tenv, \calltype, \overname{\None}{\calleerettyopt}, \eqsthree) \typearrow + \overname{\None}{\rettyopt} +} +\end{mathpar} + +\begin{mathpar} +\inferrule[ret\_type\_mismatch]{ + { + \neg\left( + \begin{array}{c}\calltype \in \{\STProcedure, \STSetter, \STEmptySetter\} \leftrightarrow \\ + \calleerettyopt=\None + \end{array} + \right) + } +}{ + \annotateretty(\tenv, \calltype, \calleerettyopt, \eqsthree) \typearrow + \TypeErrorVal{\MismatchedReturnValue} +} +\end{mathpar} + +\subsubsection{TypingRule.SubprogramForName \label{sec:TypingRule.SubprogramForName}} +\hypertarget{def-subprogramforname}{} +The function +\[ + \begin{array}{rl} + \subprogramforname( + \overname{\staticenvs}{\tenv} \aslsep + \overname{\Strings}{\name} \aslsep + \overname{\ty^*}{\callerargtypes} + ) + \aslto & + (\overname{(\identifier \times \expr)^*}{\extranargs} \aslsep + \overname{\Strings}{\namep} \aslsep + \overname{\func}{\callee} + )\\ + & \cup\ \overname{\TTypeError}{\TypeErrorConfig} + \end{array} +\] +looks up the static environment $\tenv$ for a subprogram associated with $\name$ +and the list of argument types $\calleeargtypes$ and determines which one of the following +cases holds: +\begin{itemize} + \item there is no declared subprogram that matches $\name$ and $\calleeargtypes$; + \item there is exactly one subprogram that matches $\name$ and $\calleeargtypes$; + \item there is more than one subprogram that matches $\name$ and $\calleeargtypes$; +\end{itemize} +The first and last cases result in a type error. +If the second case holds, the function returns a tuple comprised of: +\begin{itemize} +\item $\extranargs$ --- the list of extra named arguments (parameters); +\item $\namep$ --- the string that uniquely identifies this subprogram; +\item $\callee$ --- the AST node defining the called subprogram. +\end{itemize} +\ProseOtherwiseTypeError + +\subsubsection{Prose} +One of the following applies: +\begin{itemize} + \item All of the following apply (\textsc{undefined}): + \begin{itemize} + \item $\tenv$ does not contain a binding for $\name$ in the $\subprogramrenamings$ map + ($G^\tenv.\subprogramrenamings$); + \item the result is a type error indicating that the identifier has not been declared (as a subprogram). + \end{itemize} + + \item All of the following apply (\textsc{no\_candidates}): + \begin{itemize} + \item $\tenv$ binds $\name$ via $\subprogramrenamings$ map to $\renamingset$; + \item filtering the subprograms in $\renamingset$ with the caller argument types $\callerargtypes$ + in $\tenv$ (see \secref{TypingRule.FilterCallCandidates}) yields an empty set\ProseOrTypeError; + \item the result is a type error indicating that the call given by $\name$ and \\ $\callerargtypes$ + does not match any defined subprogram. + \end{itemize} + + \item All of the following apply (\textsc{too\_many\_candidates}): + \begin{itemize} + \item $\tenv$ binds $\name$ via $\subprogramrenamings$ map to $\renamingset$; + \item filtering the subprograms in $\renamingset$ with the caller argument types $\callerargtypes$ + in $\tenv$ (see \secref{TypingRule.FilterCallCandidates}) yields $\matchingrenamings$\ProseOrTypeError; + \item $\matchingrenamings$ contains at least two elements; + \item the result is a type error indicating that the call given by $\name$ and \\ + $\callerargtypes$ matches more than one defined subprogram. + \end{itemize} + + \item All of the following apply (\textsc{one\_candidate}): + \begin{itemize} + \item $\tenv$ binds $\name$ via $\subprogramrenamings$ map to $\renamingset$; + \item filtering the subprograms in $\renamingset$ with the caller argument types $\callerargtypes$ + in $\tenv$ (see \secref{TypingRule.FilterCallCandidates}) yields $\matchingrenamings$\ProseOrTypeError; + \item $\matchingrenamings$ contains a single element --- $(\matchedname, \funcsig)$; + \item deducing the argument values for the parameters via $\deduceeqs$ with \\ + $\callerargtypes$, $\funcsig.\funcargs$ in $\tenv$ yields \\ + $(\extranargs, \namep, \callee)$\ProseOrTypeError. + \end{itemize} +\end{itemize} +\CodeSubsection{\SubprogramForNameBegin}{\SubprogramForNameEnd}{../Typing.ml} + +\subsubsection{Formally} +\begin{mathpar} +\inferrule[undefined]{ + G^\tenv.\subprogramrenamings(\name) = \bot +}{ + \subprogramforname(\tenv, \name, \callerargtypes) \typearrow \TypeErrorVal{\UndefinedIdentifier} +} +\end{mathpar} + +\begin{mathpar} +\inferrule[no\_candidates]{ + G^\tenv.\subprogramrenamings(\name) = \renamingset\\ + { + \begin{array}{r} + \filtercallcandidates(\tenv, \callerargtypes, \renamingset) \typearrow \emptyset \OrTypeError + \end{array} + } +}{ + \subprogramforname(\tenv, \name, \callerargtypes) \typearrow \TypeErrorVal{\NoCallCandidates} +} +\end{mathpar} + +\begin{mathpar} +\inferrule[too\_many\_candidates]{ + G^\tenv.\subprogramrenamings(\name) = \renamingset\\ + { + \begin{array}{r} + \filtercallcandidates(\tenv, \callerargtypes, \renamingset) \typearrow \\ \matchingrenamings \OrTypeError + \end{array} + }\\\\ + \cardinality{\matchingrenamings} \geq 2 +}{ + \subprogramforname(\tenv, \name, \callerargtypes) \typearrow \TypeErrorVal{\TooManyCandidates} +} +\end{mathpar} + +\begin{mathpar} +\inferrule[one\_candidate]{ + G^\tenv.\subprogramrenamings(\name) = \renamingset\\ + { + \begin{array}{r} + \filtercallcandidates(\tenv, \callerargtypes, \renamingset) \typearrow \\ \matchingrenamings \OrTypeError + \end{array} + }\\\\ + \matchingrenamings = [(\matchedname, \funcsig)]\\ + { + \begin{array}{r} + \deduceeqs(\tenv, \callerargtypes, \funcsig.\funcargs) + \typearrow \\ (\extranargs, \namep, \callee) \OrTypeError + \end{array} + } +}{ + { + \begin{array}{r} + \subprogramforname(\tenv, \name, \callerargtypes) \typearrow \\ (\extranargs, \namep, \callee) + \end{array} + } +} +\end{mathpar} + +\subsubsection{TypingRule.DeduceEqs \label{sec:TypingRule.DeduceEqs}} +\hypertarget{def-deduceeqs}{} +The function +\[ +\deduceeqs( + \overname{\staticenvs}{\tenv} \aslsep + \overname{\ty^*}{\callerargtypes} \aslsep + \overname{(\identifier\times\ty)^*}{\vargs} +) \aslto +\overname{(\identifier\times\expr)^*}{\eqs} +\cup \overname{\TTypeError}{\TypeErrorConfig} +\] +takes the types of the actual arguments of a call --- $\callerargtypes$, +the list of formal arguments --- $\vargs$ --- which consist of the names of a subprogram arguments +and their associated types, and +infers the expressions associated with parameters that correspond to bitvector widths, +yielding the result in $\eqs$. +\ProseOtherwiseTypeError + +It guaranteed that by TypingRule.HasArgClash, +which is used by \\ TypingRule.FilterCallCandidates before calling $\deduceeqs$, +that $\callerargtypes$ and $\vargs$ have the same length. + +\subsubsection{Prose} +One of the following applies: +\begin{itemize} + \item All of the following apply (\textsc{empty}): + \begin{itemize} + \item both $\callerargtypes$ and $\vargs$ are empty lists; + \item define $\eqs$ as the empty list. + \end{itemize} + + \item All of the following apply (\textsc{not\_bits\_parameter}): + \begin{itemize} + \item $\callerargtypes$ has \head\ $\caller$ and \tail\ $\callerargtypesone$; + \item $\vargs$ has \head\ $(\Ignore, \callee)$ and \tail\ $\vargsone$; + \item $\caller$ is not a bitvector type with a width expression that is a variable expression; + \item applying $\deduceeqs$ to $\callerargtypesone$ and $\vargsone$ in $\tenv$ yields $\eqs$. + \end{itemize} + + \item All of the following apply (\textsc{bits\_parameter}): + \begin{itemize} + \item $\callerargtypes$ has \head\ $\caller$ and \tail\ $\callerargtypesone$; + \item $\vargs$ has \head\ $(\Ignore, \callee)$ and \tail\ $\vargsone$; + \item $\caller$ is bitvector type whose width expression is the variable expression for $\vx$; + \item obtaining the \structure\ of $\caller$ in $\tenv$ yields the bitvector type with width expression $\ecaller$\ProseOrTypeError; + \item applying $\deduceeqs$ to $\callerargtypesone$ and $\vargsone$ in $\tenv$ yields $\eqsone$; + \item define $\eqs$ as the list with \head\ $(\vx, \ecaller)$. + \end{itemize} +\end{itemize} + +\subsubsection{Formally} +\begin{mathpar} +\inferrule[empty]{}{ + \deduceeqs(\tenv, \overname{\emptylist}{\callerargtypes}, \overname{\emptylist}{\vargs}) \typearrow \overname{\emptylist}{\eqs} +} +\end{mathpar} + +\begin{mathpar} +\inferrule[not\_bits\_parameter]{ + \caller \neq \TBits(\EVar(\Ignore))\\ + \deduceeqs(\tenv, \callerargtypesone, \vargsone) \typearrow \eqs +}{ + \deduceeqs( + \tenv, + \overname{[\caller] \concat \callerargtypesone}{\callerargtypes}, + \overname{[(\Ignore, \callee)] \concat \vargsone}{\vargs}) \typearrow \eqs +} +\end{mathpar} + +\begin{mathpar} +\inferrule[bits\_parameter]{ + \caller = \TBits(\EVar(\vx))\\ + \tstruct(\tenv, \caller) \typearrow \TBits(\ecaller, \Ignore) \OrTypeError\\\\ + \deduceeqs(\tenv, \callerargtypesone, \vargsone) \typearrow \eqsone\\ + \eqs \eqdef [(\vx, \ecaller)] \concat \eqsone +}{ + \deduceeqs( + \tenv, + \overname{[\caller] \concat \callerargtypesone}{\callerargtypes}, + \overname{[(\Ignore, \callee)] \concat \vargsone}{\vargs}) \typearrow \eqs +} +\end{mathpar} + +\subsubsection{TypingRule.FilterCallCandidates \label{sec:TypingRule.FilterCallCandidates}} +\hypertarget{def-filtercandidates}{} +The helper function +\[ + \filtercallcandidates( + \overname{\staticenvs}{\tenv} \aslsep + \overname{\ty^*}{\formaltypes} \aslsep + \overname{\pow{\Strings}}{\candidates} + ) + \aslto \overname{(\Strings\times\func)^*}{\matches} +\] +iterates over the list of unique subprogram names in $\candidates$ and checks whether +their lists of arguments clash with the types in $\formaltypes$ in $\tenv$. +The result is the set of pairs consisting of the names and function definitions of the +subprograms whose arguments clash in $\candidates$. +\ProseOtherwiseTypeError + +The names $\candidates$ are assumed to exist in $G^\tenv.\subprograms$. + +\subsubsection{Prose} +One of the following applies: +\begin{itemize} + \item All of the following apply (\textsc{no\_candidates}): + \begin{itemize} + \item $\candidates$ is empty; + \item $\matches$ is empty. + \end{itemize} + + \item All of the following apply (\textsc{candidates\_exist}): + \begin{itemize} + \item $\candidates$ is a list with \head\ $\name$ and \tail\ $\candidatesone$; + \item the function definition associated with $\name$ in $\tenv$ is $\funcdef$; + \item determining whether there is an argument clash between $\formaltypes$ and the arguments in $\funcdef$ + (that is, $\funcdef.\funcargs$) yields $\vb$\ProseOrTypeError; + \item filtering the call candidates in $\candidatesone$ with $\formaltypes$ in $\tenv$ yields $\matchesone$\ProseOrTypeError; + \item if $\vb$ is $\True$ then $\matches$ is the list with \head\ $(\name,\funcdef)$ and \tail\ $\matchesone$, + and otherwise it is $\matchesone$. + \end{itemize} +\end{itemize} + +\subsubsection{Formally} +\begin{mathpar} +\inferrule[no\_candidates] +{}{ + \filtercallcandidates(\tenv, \formaltypes, \overname{\emptylist}{\candidates}) \typearrow \overname{\emptylist}{\matches} +} +\and +\inferrule[candidates\_exist] +{ + \funcdef \eqdef G^\tenv.\subprograms(\name) \\ + \hasargclash(\tenv, \formaltypes, \funcdef.\funcargs) \typearrow \vb \OrTypeError\\\\ + \filtercallcandidates(\tenv, \formaltypes, \candidatesone) \typearrow \matchesone \OrTypeError\\\\ + \matches \eqdef \choice{\vb}{\;[(\name,\funcdef)] \concat \matchesone}{\;\matchesone} +}{ + \filtercallcandidates(\tenv, \formaltypes, \overname{[\name] \concat \candidatesone}{\candidates}) \typearrow \matches +} +\end{mathpar} + +\subsubsection{TypingRule.HasArgClash \label{sec:TypingRule.HasArgClash}} +\hypertarget{def-hasargclash}{} +The function +\[ + \hasargclash( + \overname{\staticenvs}{\tenv} \aslsep + \overname{\ty^*}{\formaltys} \aslsep + \overname{(\identifier\times\ty)^*}{\vargs} + ) + \aslto \overname{\Bool}{\vb} \cup \overname{\TTypeError}{\TypeErrorConfig} +\] +checks whether a list of types $\formaltys$ clashes with the list of types appearing +in the list of arguments $\vargs$ in $\tenv$, yielding the result in $\vb$. +\ProseOtherwiseTypeError + +\subsubsection{Prose} +All of the following apply: +\begin{itemize} + \item equating the list lengths of $\formaltys$ and $\vargs$ either yields $\True$ + or $\False$, which short-circuits the entire rule; + \item $\argtys$ is the list of types appearing in $\vargs$, in the same order; + \item for each $\vi$ in the list of indices of $\formaltys$, applying $\typeclashes$ to + $\formaltys[\vi]$ and $\argtys[\vi]$ in $\tenv$ yields $\True$\ProseTerminateAs{\False, \TypeErrorConfig}; + \item $\vb$ is $\True$ (unless the rule short-circuited with $\False$ or a type error). +\end{itemize} + +\CodeSubsection{\HasArgClashBegin}{\HasArgClashEnd}{../Typing.ml} + +\subsubsection{Formally} +\begin{mathpar} +\inferrule{ + \equallength(\formaltypes, \vargs) \typearrow \True \terminateas \False\\ + \argtys \eqdef [(\Ignore, \vt) \in \vargs: \vt]\\ + \vi\in\listrange(\formaltys): \typeclashes(\tenv, \formaltys[\vi], \argtys[\vi]) \typearrow \True \terminateas \False,\TypeErrorConfig +}{ + \hasargclash(\tenv, \formaltys, \vargs) \typearrow \overname{\True}{\vb} +} +\end{mathpar} + +\subsubsection{TypingRule.ExpressionList\label{sec:TypingRule.ExpressionList}} +\hypertarget{def-annotateexprs}{} +The helper function +\[ + \annotateexprlist(\overname{\staticenvs}{\tenv} \aslsep \overname{\expr^*}{\exprs}) + \aslto \overname{(\ty \times \expr)^*}{\typedexprs} + \cup \overname{\TTypeError}{\TypeErrorConfig} +\] +annotates a list of expressions $\exprs$ from left to right, yielding a list of pairs $\typedexprs$, +each consisting of a type and expression. +\ProseOtherwiseTypeError + +\subsubsection{Prose} +One of the following applies: +\begin{itemize} + \item All of the following apply (\textsc{empty}): + \begin{itemize} + \item $\exprs$ is empty; + \item $\typedexprs$ is empty. + \end{itemize} + + \item All of the following apply (\textsc{non\_empty}): + \begin{itemize} + \item $\exprs$ has $\ve$ as its \head\ expression and $\exprsone$ as its \tail; + \item annotating $\ve$ in $\tenv$ yields the pair $\typedexpr$ consisting of a type and an expression + \ProseOrTypeError; + \item annotating the expression list $\exprsone$ in $\tenv$ yields + $\typedexprs$\ProseOrTypeError; + \item $\typedexprs$ is the list with $\typedexpr$ as its \head\ and $\typedexprs$ as its \tail. + \end{itemize} +\end{itemize} + +\subsubsection{Formally} +\begin{mathpar} +\inferrule[empty]{} +{ + \annotateexprlist(\tenv, \overname{\emptylist}{\exprs}) \typearrow \overname{\emptylist}{\typedexprs} +} +\end{mathpar} + +\begin{mathpar} +\inferrule[non\_empty]{ + \annotateexpr{\tenv, \ve} \typearrow \typedexpr \OrTypeError\\\\ + \annotateexprlist(\tenv, \exprsone) \typearrow \typedexprsone \OrTypeError +}{ + \annotateexprlist(\tenv, \overname{[\ve] \concat \exprsone}{\exprs}) \typearrow \overname{[\typedexpr] \concat \typedexprsone}{\typedexprs} +} +\end{mathpar} + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +\section{Semantics} +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +The relation +\hypertarget{def-evalcall}{} +\[ + \begin{array}{c} + \evalcall{\overname{\envs}{\env} \aslsep + \overbracket{\Identifiers}^{\texttt{name}} \aslsep + \overbracket{\expr^*}^{\texttt{args}} \aslsep + \overbracket{(\overname{\Identifiers}{\id_i}\times\overname{\expr}{\ve_i})^*}^{\texttt{named\_args}}} \;\aslrel\; \\ + \Normal(\overbracket{(\vals\times\XGraphs)^*}^{\vmstwo}, \overname{\envs}{\newenv}) \cup + \overname{\TThrowing}{\ThrowingConfig} \cup \overname{\TError}{\ErrorConfig} + \end{array} +\] +evaluates a call to the subprogram named $\name$ in the environment $\env$, +with the argument expressions +$\args$, and the parameter expressions $\namedargs$. +The evaluation results in either a list of returned values, each one associated +with an execution graph, and a new environment; +or an abnormal configuration. + +The evaluation first evaluates the expressions corresponding to the arguments +and parameters and then passes their values in a resulting configuration +to the helper relation \texttt{eval\_subprogram}. + +The relation +\hypertarget{def-evalsubprogram}{} +\[ + \begin{array}{c} + \evalsubprogram{\overname{\envs}{\env} \aslsep + \overname{\Identifiers}{\name} \aslsep + \overname{(\vals \times \XGraphs)^*}{\actualargs} \aslsep + \overname{(\Identifiers\times\vals)^*}{\params}} \aslrel \\ + \Normal(\overname{(\vals^* \aslsep \XGraphs)}{\vvs}, \overname{\envs}{\newenv}) \cup + \overname{\TThrowing}{\ThrowingConfig} \cup + \overname{\TError}{\ErrorConfig} + \end{array} +\] +evaluates the subprogram named $\name$ in the environment $\env$, with +$\actualargs$ the list of actual arguments, and $\params$ the +list of arguments deduced by type equality. +The result is either a normal configuration or an abnormal configuration. +In the case of a normal configuration, it consists of a list of pairs +with a value and an identifier, and a new environment $\newenv$. +The values represent values returned by the subprogram call and the +identifiers are used in generating execution graph constraints for the +returned values. + +The main subprogram call relation is given by +SemanticsRule.Call (see \secref{SemanticsRule.Call}). +% +The different types of subprogram calls are evaluated via one of the following rules: +\begin{itemize} +\item SemanticsRule.FPrimitive (see \secref{SemanticsRule.FPrimitive}) +\item SemanticsRule.FCall (see \secref{SemanticsRule.FCall}) +\end{itemize} + +We also define the following helper rules: +\begin{itemize} + \item SemanticsRule.ReadValueFrom (see \secref{SemanticsRule.ReadValueFrom}) + \item SemanticsRule.WriteRetVals (see \secref{SemanticsRule.WriteRetVals}) + \item SemanticsRule.AssignArgs (see \secref{SemanticsRule.AssignArgs}) + \item SemanticsRule.AssignNamedArgs (see \secref{SemanticsRule.AssignNamedArgs}) + \item SemanticsRule.MatchFuncRes (see \secref{SemanticsRule.MatchFuncRes}) +\end{itemize} + +\subsubsection{SemanticsRule.Call \label{sec:SemanticsRule.Call}} +\subsubsection{Prose} +All of the following apply: +\begin{itemize} + \item $\namedargs$ is a list of identifier-expression pairs $(\id_i, \ve_i)$, for $i=1..k$; + \item $\names$ is the list of identifiers in $\namedargs$; + \item $\nargsone$ is the list of argument expressions in $\namedargs$; + \item evaluating each expression in $\args$ separately in $\env$ as per \secref{SemanticsRule.EExprListM} + is \\ $\Normal(\vargs, \envone)$\ProseOrAbnormal; + \item evaluating each expression in $\nargs$ separately in $\envone$ as per \secref{SemanticsRule.EExprListM} + is \\ $\Normal(\nargstwo, \envtwo)$\ProseOrAbnormal; + \item $\nargstwo$ is the list of value-execution graph pairs $\vm_i$, for $i=1..k$; + \item $\nargsthree$ is the list of pairs $(\id_i, \vm_i)$, for $i=1..k$ (this is the format needed + for \texttt{eval\_subprogram}); + \item $\envtwo$ consists of the static environment $\tenv$ and the dynamic environment $\denvtwo$; + \item the environment $\envtwo'$ is defined as the environment + consisting of the static environment $\tenv$ and the dynamic environment with the global component + of $\denvtwo$ and an empty local component (intuitively, this is because the called subprogram does not have access + to the local environment of the caller); + \item evaluating the subprogram named $\name$ with arguments $\vvargs$ and parameters $\nargsthree$ in + $\denvtwo'$ is $\Normal(\vms, (\vglobal, \Ignore))$ (that is, we ignore the local environment + of the callee)\ProseOrAbnormal; + \item the list $\vms$ consists of value-identifier pairs $(\vv_j, \rid_j)$, for $i=1..n$; + \item applying the helper relation $\readvaluefrom$ to each $(\vv_j, \rid_j)$ + results in $\vmstwo_j$, for $i=1..n$; + \item $\vmstwo$ is defined as the list of $\vmstwo_j$, for $i=1..n$; + \item $\newenv$ consists of the static environment $\tenv$ and the dynamic environment consisting + of $\vglobal$ as the global component and the local component of $\denvtwo$ (that is, we restore + the local environment to that of the caller and drop the local environment of the callee). + \item the entire evaluation results in $\Normal(\vmstwo, \newenv)$. +\end{itemize} + +\CodeSubsection{\EvalCallBegin}{\EvalCallEnd}{../Interpreter.ml} + +\subsubsection{Formally} +\begin{mathpar} +\inferrule{ + \namedargs \eqname [i=1..k: (\id_i, \ve_i)]\\ + \names \eqdef [i=1..k: \id_i]\\ + \nargsone \eqdef [i=1..k: \ve_i]\\ + \evalexprlistm(\env, \args) \evalarrow \Normal(\vvargs, \envone)\OrAbnormal\\ + \evalexprlistm(\envone, \nargs1) \evalarrow \Normal(\nargstwo, \envtwo)\OrAbnormal\\ + \nargstwo \eqname [i=1..k: \vm_i]\\ + \nargsthree \eqdef [i=1...k: (\id_i, \vm_i)]\\ + \envtwo \eqname (\tenv, \denvtwo)\\ + \envtwo' \eqdef (\tenv,(G^\denvtwo,\emptyfunc))\\\\ + \evalsubprogram{\envtwo', \name, \vvargs, \nargsthree} \evalarrow \Normal(\vms, (\vglobal, \Ignore)) \OrAbnormal\\\\ + \vms \eqname [j=1..n: (\vv_j, \rid_j)]\\ + j=1..n: \readvaluefrom(\vv_j, \rid_j) \evalarrow \vmstwo_j\\ + \vmstwo \eqdef [j=1..n: \vmstwo_j]\\ + \newenv \eqdef (\tenv, (\vglobal, L^{\denvtwo})) +}{ + \evalcall{\env, \name, \args, \namedargs} \evalarrow \Normal(\vmstwo, \newenv) +} +\end{mathpar} + +\subsubsection{SemanticsRule.FPrimitive \label{sec:SemanticsRule.FPrimitive}} +\subsubsection{Prose} +All of the following apply: +\begin{itemize} + \item $\env$ consists of the static environment $\tenv$ and the dynamic environment with $\genv$ as its + global component and an empty local component; + \item finding the function named $\name$ in the static environment $\tenv$ gives a $\func$ AST node + with the body field \SBPrimitive; + \item evaluating the primitive subprogram $\name$ with the actual arguments $\actualargs$ + is $\Normal(\vms, \vgone)$\ProseOrError; + \item writing the returned values $\vms$ as per \secref{SemanticsRule.WriteRetVals} gives $\vvsm$; + \item $\vvsm$ is a pair consisting of the list of values $\vvs$ and execution graph $\vgtwo$; + \item $\newg$ is the ordered composition of $\vgone$ and $\vgtwo$ with the $\asldata$ label; + \item $\newenv$ is the environment with $\tenv$ as its static environment component + and the dynamic environment consisting of $\genv$ as its global component and an empty local component; + \item the result of the entire evaluation is $\Normal((\vvs, \newg), \newenv)$. +\end{itemize} + +\subsubsection{Example} +In the specification: +\VerbatimInput{../tests/ASLSemanticsReference.t/SemanticsRule.FPrimitive.asl} +\texttt{print ("Hello, world!");} calls the primitive \texttt{print} on the evaluation of \texttt{"Hello, world!"}. + +\CodeSubsection{\EvalFPrimitiveBegin}{\EvalFPrimitiveEnd}{../Interpreter.ml} + +\subsubsection{Formally} +The following rule utilizes the transition relation +\hypertarget{def-evalprimitive}{} +\[ + \evalprimitive{\overname{\Identifiers}{\name} \aslsep \overname{(\vals\times\XGraphs)^*}{\actualargs}} \bigtimes + \Normal(\overname{(\vals\times\XGraphs)^*}{\vms} \aslsep \overname{\XGraphs}{\vgone}) \cup \overname{\TError}{\ErrorConfig} \enspace, +\] +which parameterizes the ASL semantics and allows evaluating primitive subprograms. +That is, it is not a part of $\evalarrow$ but rather a separate transition relation denoted $\evalprimitivearrow$. + +\begin{mathpar} +\inferrule{ + \env \eqname (\tenv, (\genv, \emptyfunc))\\ + \findfunc(\tenv, \name) = \{ \body = \SBPrimitive \ldots \}\\ + \evalprimitive{\name, \actualargs} \evalprimitivearrow \Normal(\vms, \vgone) \OrDynError\\\\ + \writeretvals(\vms) \evalarrow \vvsm\\ + \vvsm \eqname (\vvs, \vgtwo)\\ + \newg \eqdef \ordered{\vgone}{\asldata}{\vgtwo}\\ + \newenv \eqdef (\tenv, (\genv, \emptyfunc)) +}{ + \evalsubprogram{\env, \name, \actualargs, \params} \evalarrow \Normal((\vvs, \newg), \newenv) +} +\end{mathpar} + +\subsubsection{SemanticsRule.FCall \label{sec:SemanticsRule.FCall}} +\subsubsection{Prose} +All of the following apply: +\begin{itemize} + \item $\env$ consists of the static environment $\tenv$ and the dynamic environment with the global + component $\genv$ and an empty local component; + \item finding the function named $\name$ in $\tenv$ gives the AST $\func$ node with body + $\SBASL(\vbody)$ and arguments $\argdecls$; + \item $\envone$ is the environment consisting of the static environment $\tenv$ and the dynamic1 + environment consisting of the dynamic component from $\denv$ and an empty local component; + \item assigning the actual arguments with $((\envone, \emptygraph), \argdecls, \actualargs)$ + as per \secref{SemanticsRule.AssignArgs} gives $(\envtwo, vgtwo)$ make sure that each + formal argument in $\argdecls$ is + locally bound to the corresponding actual argument in $\actualargs$; + \item declaring and assigning the parameter values with $((\envtwo, \vgtwo), \params)$ + as per \secref{SemanticsRule.AssignNamedArgs} gives $(\envthree, \vgthree)$; + \item evaluating the body of the subprogram $\vbody$ as a statement in in $\envthree$ + is $\vres$\ProseOrAbnormal; + \item matching the result $\vres$ to obtain a normal configuration as per \secref{SemanticsRule.MatchFuncRes} + gives $C$; + \item $\newg$ is the ordered composition of $\vgtwo$ and $\vgthree$ with the $\aslpo$ edge; + \item the result is $C$ with its graph substituted for $\newg$. +\end{itemize} + +\subsubsection{Example} +The specification: +\VerbatimInput{../tests/ASLSemanticsReference.t/SemanticsRule.FCall.asl} +calls the function \texttt{foo} and the procedure \texttt{bar}. + +\CodeSubsection{\EvalFCallBegin}{\EvalFCallEnd}{../Interpreter.ml} + +\subsubsection{Formally} +\begin{mathpar} +\inferrule{ + \env \eqname (\tenv, \denv)\\ + \findfunc(\tenv, \name) \eqname \{ \body: \SBASL(\vbody), \args: \argdecls, \ldots \}\\ + \envone \eqdef (\tenv, (G^\denv, \emptyfunc))\\ + \assignargs((\envone, \emptygraph), \argdecls, \actualargs) \evalarrow (\envtwo, \vgtwo)\\ + \assignnamedargs((\envtwo, \vgtwo), \params) \evalarrow (\envthree, \vgthree)\\ + \evalstmt{\envthree, \vbody} \evalarrow \vres \OrAbnormal\\ + \matchfuncres(\vres) \evalarrow C\\ + \newg \eqdef \ordered{\vgtwo}{\aslpo}{\vgthree}\\ +}{ + \evalsubprogram{\env, \name, \actualargs, \params} \evalarrow \withgraph{C}{\newg} +} +\end{mathpar} + +\subsubsection{Comments} +\lrmcomment{This is related to \identr{DFWZ}:} +It is not an error for execution of a procedure or setter to end without a +return statement. + +\subsubsection{SemanticsRule.ReadValueFrom \label{sec:SemanticsRule.ReadValueFrom}} +\hypertarget{def-readvaluefrom}{} +The helper relation +\[ + \readvaluefrom(\vals \aslsep \Identifiers) \;\aslrel\; (\vals \times \XGraphs) +\] +generates an execution graph for reading the given value to a variable given +by the identifier, and pairs it with the given value. + +\subsubsection{Prose} +All of the following apply: +\begin{itemize} + \item reading the value $\vv$ into the variable named $\id$ gives $\newg$; + \item the result is $(\vv, \newg)$. +\end{itemize} + +\CodeSubsection{\EvalReadValueFromBegin}{\EvalReadValueFromEnd}{../Interpreter.ml} + +\subsubsection{Formally} +\begin{mathpar} +\inferrule{ + \readidentifier(\vv, \id) \evalarrow \newg +}{ + \readvaluefrom(\vv, \id) \evalarrow (\vv, \newg) +} +\end{mathpar} + +\subsubsection{SemanticsRule.WriteRetVals \label{sec:SemanticsRule.WriteRetVals}} +\hypertarget{def-writeretvals}{} +The relation +\[ + \writeretvals(\overname{(\overname{\overname{\vals}{\vv}\times\overname{\XGraphs}{\vgone}}{\vm})^*}{\vvsm}) \;\aslrel\; + (\overname{\vals^*}{\vvs}\times\overname{\XGraphs}{\newg}) \enspace. +\] +generates Write Effects for the values +returned by the evaluation of a primitive subprogram: + +\subsubsection{Prose} + one of the following applies: + \begin{itemize} + \item All of the following apply (\textsc{empty}): + \begin{itemize} + \item the list of value-execution graphs $\vvsm$ is empty; + \item the result is a pair consisting of an empty list and an empty graph. + \end{itemize} + + \item All of the following apply (\textsc{non\_empty}): + \begin{itemize} + \item the list of value-execution graphs $\vvsm$ has $\vm$ as its head and $\vvsmone$ as its tail; + \item $\vx$ is a fresh identifier; + \item $\vm$ consists of the value $\vv$ and execution graph $\vgone$; + \item the execution graph $\vgtwo$ is generating by writing the value $\vv$ for the variable named $\vx$; + \item writing the returned values in $\vvsmone$ gives $(\vvsone, \vgthree)$; + \item $\vs$ is defined as the list with $\vv$ as its head and $\vvsone$ as its tail; + \item $\newg$ is defined by first taking the ordered composition of $\vgone$ and $\vgtwo$ with the $\asldata$ edge + and then composing the resulting execution graph in parallel with $\vgthree$; + \item the result of the entire evaluation is $(\vvs, \newg)$. + \end{itemize} +\end{itemize} + +%% Annotating the OCaml code is problematic, since the code for this rule is inside the code +%% for FPrimitive. One option is to factor it out into a separate function. +% +% \CodeSubsection{\EvalWriteRetValsBegin}{\EvalWriteRetValsEnd}{../Interpreter.ml} + +\subsubsection{Formally} + \begin{mathpar} + \inferrule[empty]{} + { + \writeretvals(\emptylist) \evalarrow (\emptylist, \emptygraph) + } + \and + \inferrule[non\_empty]{ + \vvsm \eqname [\vm] \concat \vvsmone\\ + \vx \in \Identifiers \text{ is fresh}\\ + \vm \eqname (\vv, \vgone)\\ + \writeidentifier(\vx, \vv) \evalarrow \vgtwo\\ + \writeretvals(\vvsmone) \evalarrow (\vvsone, \vgthree)\\ + \vvs \eqdef [\vv] \concat \vvsone\\ + \newg \eqdef (\ordered{\vgone}{\asldata}{\vgtwo}) \parallelcomp \vgthree + } + { + \writeretvals(\vvsm) \evalarrow (\vvs, \newg) + } + \end{mathpar} + +\subsubsection{SemanticsRule.AssignArgs \label{sec:SemanticsRule.AssignArgs}} +The helper relation +\hypertarget{def-assignargs}{} +\[ + \assignargs((\overname{\envs}{\env}\times\overname{\XGraphs}{\vgone})\aslsep \overname{(\Identifiers\times\ty)^*}{\texttt{arg\_decls}} + \aslsep \overname{(\vals\times\XGraphs)^*} {\texttt{actual\_args}}) \;\aslrel\; + (\overname{\envs}{\newenv} \times \overname{\XGraphs}{\newg}) +\] +assigns the values of (the actual) arguments to the +formal variables of a given subprogram. + +\subsubsection{Prose} +One of the following applies: +\begin{itemize} + \item All of the following apply (\textsc{empty}): + \begin{itemize} + \item both $\argdecls$ and $\actualargs$ are empty lists; + \item the result is $(\env, \vgone)$. + \end{itemize} + + \item All of the following apply (\textsc{non\_empty}): + \begin{itemize} + \item $\argdecls$ has $(\vx, \Ignore)$ as its head and $\argdecls$ as its tail, + and $\actualargs$ has $\vm$ as its head and $\actualargs$ as its tail; + \item declaring the local identifier $\vx$ with $\vm$ in $\env$ as per \secref{SemanticsRule.DeclareLocalIdentifierMM} + gives \\ $(\envone, \vgtwo)$. + \item assigning the remaining lists $\argdecls$ and $\actualargs$ with the environment $\envone$ and the ordered + composition of $\vgone$ and $\vgtwo$ with the $\aslpo$ edge gives $(\newenv, \newg)$. + \item the entire result of the evaluation is $(\newenv, \newg)$. + \end{itemize} +\end{itemize} + +\subsubsection{Formally} + \begin{mathpar} + \inferrule[empty]{} + { + \assignargs((\env, \vgone), \emptylist, \emptylist) \evalarrow (\env, \vgone) + } + \and + \inferrule[non\_empty]{ + \declarelocalidentifiermm(\env, \vx, \vm) \evalarrow (\envone, \vgtwo)\\ + \assignargs((\envone, \ordered{\vgone}{\aslpo}{\vgtwo}), \argdecls, \actualargs) \evalarrow (\newenv, \vg) + } + { + \assignargs((\env, \vgone), [(\vx, \Ignore)] \concat \argdecls, [\vm] \concat \actualargs) \evalarrow (\newenv, \vg) + } + \end{mathpar} + +\subsubsection{SemanticsRule.AssignNamedArgs \label{sec:SemanticsRule.AssignNamedArgs}} +The helper relation +\hypertarget{def-assignnamedargs}{} +\[ + \begin{array}{c} + \assignnamedargs((\overname{\envs}{\env}\times\overname{\XGraphs}{\vgone}) \aslsep + \overname{(\overname{\Identifiers}{\vx}\times\overname{(\vals\times\XGraphs)}{\vm})^*}{\params}) \;\aslrel\; + (\overname{\envs}{\newenv}\times\overname{\XGraphs}{\newg}) + \end{array} +\] +assigns values to the variables that correspond +to the parameters of a given subprogram. + +\subsubsection{Prose} +One of the following applies: +\begin{itemize} + \item All of the following apply (\textsc{empty}): + \begin{itemize} + \item $\params$ is an empty list; + \item the result is $\env, \vgone$; + \end{itemize} + + \item All of the following apply (\textsc{declared}): + \begin{itemize} + \item $\params$ has $(\vx,\vm)$ as its head and $\paramsone$ as its tail; + \item $\env$ consists of the static environment $\tenv$ and dynamic environment $\denv$; + \item $\vx$ is bound to a value in $\denv$; + \item $\vacc$ is defined as $(\env,\vgone)$; + \item assigning the named args with $\vacc$ and $\paramsone$ gives $(\newenv, \vgtwo)$; + \item $\newg$ is the ordered composition of $\vgone$ and $\vgtwo$ with the $\aslpo$ edge. + \item the result is $(\newenv, \newg)$. + \end{itemize} + + \item All of the following apply (\textsc{not\_declared}): + \begin{itemize} + \item $\params$ has $(\vx,\vm)$ as its head and $\paramsone$ as its tail; + \item $\env$ consists of the static environment $\tenv$ and dynamic environment $\denv$; + \item $\vx$ is not bound to a value in $\denv$; + \item declaring the local identifier $\vx$ with $\vm$ in $\env$, as per \secref{SemanticsRule.DeclareLocalIdentifierM}, + gives $(\envone, \vgtwo)$; + \item $\vacc$ is defined as $(\envone,\vgtwo)$; + \item assigning the named args with $\vacc$ and $\paramsone$ gives $(\newenv, \vgthree)$; + \item $\newg$ is the ordered composition of $\vgone$, $\vgtwo$, and $\vgthree$ with the $\aslpo$ edge. + \item the result is $(\newenv, \newg)$. + \end{itemize} +\end{itemize} + +\subsubsection{Formally} +\newcommand\isbound[0]{\hyperlink{def-isbound}{\texttt{is\_bound}}} +\hypertarget{def-isbound}{} +We use the helper predicate +\[ +\isbound(\denv, \vx) \triangleq G^\denv(\vx) \neq \bot \vee L^\denv(\vx) \neq \bot +\] +to test whether the variable $\vx$ is bound in the dynamic environment $\denv$. + +\begin{mathpar} + \inferrule[empty]{} + { + \assignnamedargs((\env, \vgone), \emptylist) \evalarrow (\env, \vgone) + } + \and + \inferrule[declared]{ + \params \eqname [(\vx, \vm)] \concat \paramsone\\ + \env \eqname (\tenv, \denv)\\ + \isbound(\denv,\vx)\\ + \vacc \eqdef (\env, \vgone) \\ + \assignnamedargs(\vacc, \paramsone) \evalarrow (\newenv, \vgtwo)\\ + \newg \eqdef \ordered{\vgone}{\aslpo}{\vgtwo} + } + { + \assignnamedargs((\env, \vgone), \params) \evalarrow (\newenv, \newg) + } + \and + \inferrule[not\_declared]{ + \params \eqname [(\vx, \vm)] \concat \paramsone\\ + \env \eqname (\tenv, \denv)\\ + \neg\isbound(\denv,\vx)\\ + \declarelocalidentifierm(\env, \vx, \vm) \evalarrow (\envone, \vgtwo)\\ + \vacc \eqdef (\envone, \vgtwo) \\ + \assignnamedargs(\vacc, \paramsone) \evalarrow (\newenv, \vgthree)\\ + \newg \eqdef \ordered{\ordered{\vgone}{\aslpo}{\vgtwo}}{\aslpo}{\vgthree} + } + { + \assignnamedargs((\env, \vgone), \params) \evalarrow (\newenv, \newg) + } +\end{mathpar} + +\subsubsection{SemanticsRule.MatchFuncRes \label{sec:SemanticsRule.MatchFuncRes}} +The helper relation +\hypertarget{def-matchfuncres}{} +\[ + \matchfuncres(\TContinuing \cup \TReturning) \;\aslrel\; + \Normal(((\Identifiers\times\vals)^*\times\XGraphs)\aslsep\envs) +\] +converts normal and throwing configurations +into corresponding normal configurations that can be returned by a subprogram evaluation. + +\subsubsection{Prose} +One of the following applies: +\begin{itemize} + \item All of the following apply (\textsc{continuing}): + \begin{itemize} + \item the given configuration is $\Continuing(\vg, \env)$. This happens when, + for example, the subprogram called is either a setter or a procedure; + \item the result is $\Normal((\emptylist, \vg), \env)$. + \end{itemize} + + \item All of the following apply (\textsc{returning}): + \begin{itemize} + \item the given configuration is $\Returning(\xs, \retenv)$, which is the case of a function; + \item $\xs$ is the list $\vv_i$, for $i=1..k$; + \item define the list of fresh identifiers $\id_i$, for $i=1..k$; + \item define $\vvs$ to be $(\vv_i, \id_i)$, for $i=1..k$; + \item the result is $\Normal((\vvs, \emptygraph), \retenv)$. + \end{itemize} +\end{itemize} + +\subsubsection{Formally} +\begin{mathpar} + \inferrule[continuing]{} + { + \matchfuncres(\Continuing(\vg, \env)) \evalarrow \Normal((\emptylist, \vg), \env) + } + \and + \inferrule[returning]{ + \xs \eqname [i=1..k: \vv_i]\\ + i=1..k: \id_i \in \Identifiers\text{ is fresh}\\ + \vvs \eqdef [i=1..k: (\vv_i, \id_i)] + } + { + \matchfuncres(\Returning(\xs, \retenv)) \evalarrow \Normal((\vvs, \emptygraph), \retenv) + } +\end{mathpar} diff --git a/asllib/doc/SubprogramDeclarations.tex b/asllib/doc/SubprogramDeclarations.tex new file mode 100644 index 000000000..fd6db6f6d --- /dev/null +++ b/asllib/doc/SubprogramDeclarations.tex @@ -0,0 +1,1577 @@ +\chapter{Subprogram Declarations\label{chap:SubprogramDeclarations}} + +Subprogram declarations are grammatically derived from $\Ndecl$ via the subset of productions shown in +\secref{SubprogramDeclarationsSyntax} and represented as ASTs via the production of $\decl$ +shown in \secref{SubprogramDeclarationsAbstractSyntax}. +% +Subprogram declarations are typed via $\annotateanddeclarefunc$, which is defined in \nameref{sec:TypingRule.AnnotateAndDeclareFunc}. +% +Subprogram declarations have no associated semantics. + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +\section{Syntax\label{sec:SubprogramDeclarationsSyntax}} +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +\begin{flalign*} +\Ndecl \derivesinline\ & \productionname{funcdecl}{func\_decl}\ \Tfunc \parsesep \Tidentifier \parsesep \Nparamsopt \parsesep \Nfuncargs \parsesep \Nreturntype \parsesep \Nfuncbody &\\ +|\ & \productionname{proceduredecl}{procedure\_decl}\ \Tfunc \parsesep \Tidentifier \parsesep \Nparamsopt \parsesep \Nfuncargs \parsesep \Nfuncbody &\\ +|\ & \productionname{getter}{getter}\ \Tgetter \parsesep \Tidentifier \parsesep \Nparamsopt \parsesep \Naccessargs \parsesep \Nreturntype \parsesep \Nfuncbody&\\ +|\ & \productionname{noarggetter}{no\_arg\_getter}\ \Tgetter \parsesep \Tidentifier \parsesep \Nreturntype \parsesep \Nfuncbody &\\ +|\ & \productionname{setter}{setter}\ \Tsetter \parsesep \Tidentifier \parsesep \Nparamsopt \parsesep \Naccessargs \parsesep \Teq \parsesep \Ntypedidentifier & \\ + & \wrappedline\ \parsesep \Nfuncbody &\\ +|\ & \productionname{noargsetter}{no\_arg\_setter}\ \Tsetter \parsesep \Tidentifier \parsesep \Teq \parsesep \Ntypedidentifier \parsesep \Nfuncbody&\\ +\end{flalign*} + +\begin{flalign*} +\Nparamsopt \derivesinline\ & \emptysentence &\\ + |\ & \Tlbrace \parsesep \Clist{\Nopttypedidentifier} \parsesep \Trbrace &\\ +\Nopttypedidentifier \derivesinline\ & \Tidentifier \parsesep \option{\Nasty} &\\ +\Nfuncargs \derivesinline\ & \Tlpar \parsesep \Clist{\Ntypedidentifier} \parsesep \Trpar &\\ +\Nreturntype \derivesinline\ & \Tarrow \parsesep \Nty &\\ +\Nfuncbody \derivesinline\ & \Tbegin \parsesep \Nmaybeemptystmtlist \parsesep \Tend &\\ +\Naccessargs \derivesinline\ & \Tlbracket \parsesep \Clist{\Ntypedidentifier} \parsesep \Trbracket &\\ +\Nmaybeemptystmtlist \derivesinline\ & \emptysentence \;|\; \Nstmtlist & +\end{flalign*} + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +\section{Abstract Syntax\label{sec:SubprogramDeclarationsAbstractSyntax}} +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +\begin{flalign*} +\decl \derives\ & \DFunc(\func) & +\end{flalign*} + +\begin{flalign*} +\func \derives\ & +{ +\left\{ + \begin{array}{rcl} + \funcname &:& \Strings, \\ + \funcparameters &:& (\identifier, \ty?)^*,\\ + \funcargs &:& \typedidentifier^*,\\ + \funcbody &:& \subprogrambody,\\ + \funcreturntype &:& \ty?,\\ + \funcsubprogramtype &:& \subprogramtype +\end{array} +\right\} +} &\\ +\typedidentifier \derives\ & (\identifier, \ty) &\\ +\subprogrambody \derives\ & \SBASL(\stmt) \;|\; \SBPrimitive &\\ +\subprogramtype \derives\ & \STProcedure \;|\; \STFunction &\\ + |\ & \STGetter \;|\; \STEmptyGetter &\\ + |\ & \STSetter \;|\; \STEmptySetter & +\end{flalign*} + +\subsubsection{ASTRule.GlobalDecl} +The relation +\[ + \builddecl : \overname{\parsenode{\Ndecl}}{\vparsednode} \;\aslrel\; \overname{\decl}{\vastnode} +\] +transforms a parse node $\vparsednode$ into an AST node $\vastnode$. + +\hypertarget{build-funcdecl}{} +\begin{mathpar} +\inferrule[func\_decl]{}{ + \builddecl( + \overname{\Ndecl( + \Tfunc, \Tidentifier(\name), \punnode{\Nparamsopt}, \punnode{\Nfuncargs}, \punnode{\Nreturntype}, \punnode{\Nfuncbody} + )}{\vparsednode}) + \astarrow \\ + { + \overname{ + \DFunc\left(\left\{ + \begin{array}{rcl} + \funcname &:& \name,\\ + \funcparameters &:& \astof{\vparamsopt},\\ + \funcargs &:& \astof{\vfuncargs},\\ + \funcbody &:& \SBASL(\astof{\vfuncbody}),\\ + \funcreturntype &:& \langle \astof{\vreturntype} \rangle,\\ + \funcsubprogramtype &:& \STFunction + \end{array} + \right\}\right)}{\vastnode} + } +} +\end{mathpar} + +\hypertarget{build-procedureecl}{} +\begin{mathpar} +\inferrule[procedure\_decl]{}{ + \builddecl( + \overname{\Ndecl(\Tfunc, \Tidentifier(\name), \punnode{\Nparamsopt}, \punnode{\Nfuncargs}, \punnode{\Nfuncbody})}{\vparsednode} + ) + \astarrow \\ + { + \overname{ + \DFunc\left(\left\{ + \begin{array}{rcl} + \funcname &:& \name,\\ + \funcparameters &:& \astof{\vparamsopt},\\ + \funcargs &:& \astof{\vfuncargs},\\ + \funcbody &:& \SBASL(\astof{\vfuncbody}),\\ + \funcreturntype &:& \None,\\ + \funcsubprogramtype &:& \STProcedure + \end{array} + \right\}\right) + }{\vastnode} + } +} +\end{mathpar} + +\hypertarget{build-getter}{} +\begin{mathpar} +\inferrule[getter]{}{ + { + \begin{array}{r} + \builddecl\left(\overname{\Ndecl\left( + \begin{array}{l} + \Tgetter, \Tidentifier(\name), \punnode{\Nparamsopt}, \punnode{\Naccessargs}, \\ + \wrappedline\ \punnode{\Nreturntype}, \punnode{\Nfuncbody} + \end{array} + \right)}{\vparsednode}\right) + \astarrow \\ + \overname{ + \DFunc\left(\left\{ + \begin{array}{rcl} + \funcname &:& \name,\\ + \funcparameters &:& \astof{\vparamsopt},\\ + \funcargs &:& \astof{\vaccessargs},\\ + \funcbody &:& \SBASL(\astof{\vfuncbody}),\\ + \funcreturntype &:& \langle \astof{\vreturntype}\rangle,\\ + \funcsubprogramtype &:& \STGetter + \end{array} + \right\}\right) + }{\vastnode} + \end{array} + } +} +\end{mathpar} + +\hypertarget{build-noarggetter}{} +\begin{mathpar} +\inferrule[no\_arg\_getter]{}{ + \builddecl(\overname{\Ndecl(\Tgetter, \Tidentifier(\name), \punnode{\Nreturntype}, \punnode{\Nfuncbody})}{\vparsednode}) + \astarrow \\ + { + \overname{ + \DFunc\left(\left\{ + \begin{array}{rcl} + \funcname &:& \name,\\ + \funcparameters &:& \emptylist,\\ + \funcargs &:& \emptylist,\\ + \funcbody &:& \SBASL(\astof{\vfuncbody}),\\ + \funcreturntype &:& \langle \astof{\vreturntype}\rangle,\\ + \funcsubprogramtype &:& \STEmptyGetter + \end{array} + \right\}\right) + }{\vastnode} + } +} +\end{mathpar} + +\hypertarget{build-setter}{} +\begin{mathpar} +\inferrule[setter]{}{ + { + \builddecl\left(\overname{\Ndecl\left( + \begin{array}{r} + \Tsetter, \Tidentifier(\name), \punnode{\Nparamsopt}, \punnode{\Naccessargs}, \Teq, \\ + \wrappedline\ \namednode{\vv}{\Ntypedidentifier}, \punnode{\Nfuncbody} + \end{array} + \right)}{\vparsednode}\right) + } \astarrow + \\ + { + \overname{ + \DFunc\left(\left\{ + \begin{array}{rcl} + \funcname &:& \name,\\ + \funcparameters &:& \astof{\vparamsopt},\\ + \funcargs &:& [\vv] \concat \astof{\vaccessargs},\\ + \funcbody &:& \SBASL(\astof{\vfuncbody}),\\ + \funcreturntype &:& \None,\\ + \funcsubprogramtype &:& \STSetter + \end{array} + \right\}\right) + }{\vastnode} + } +} +\end{mathpar} + +\hypertarget{build-noargsetter}{} +\begin{mathpar} +\inferrule[no\_arg\_setter]{}{ + \builddecl(\overname{\Ndecl(\Tsetter, \Tidentifier(\name), \Teq, \namednode{\vv}{\Ntypedidentifier}, \punnode{\Nfuncbody})}{\vparsednode}) + \astarrow \\ + { + \overname{ + \DFunc\left(\left\{ + \begin{array}{rcl} + \funcname &:& \name,\\ + \funcparameters &:& \emptylist,\\ + \funcargs &:& [\vv],\\ + \funcbody &:& \SBASL(\astof{\vfuncbody}),\\ + \funcreturntype &:& \None,\\ + \funcsubprogramtype &:& \STEmptySetter + \end{array} + \right\}\right) + }{\vastnode} + } +} +\end{mathpar} + +\subsubsection{ASTRule.TypedIdentifier \label{sec:ASTRule.TypedIdentifier}} +\hypertarget{build-typedidentifier}{} +The function +\[ +\buildtypedidentifier(\overname{\parsenode{\Ntypedidentifier}}{\vparsednode}) \aslto \overname{(\identifier \times \ty)}{\vastnode} +\] +transforms a parse node $\vparsednode$ into an AST node $\vastnode$. + +\begin{mathpar} +\inferrule{}{ + \buildtypedidentifier(\overname{\Ntypedidentifier(\Tidentifier(\id), \punnode{\Nasty})}{\vparsednode}) \astarrow \overname{(\id,\astof{\vasty})}{\vastnode} +} +\end{mathpar} + +\subsubsection{ASTRule.OptTypedIdentifier \label{sec:ASTRule.OptTypedIdentifier}} +\hypertarget{build-opttypedidentifier}{} +The function +\[ +\buildopttypedidentifier(\overname{\parsenode{\Nopttypedidentifier}}{\vparsednode}) \aslto \overname{(\identifier \times \langle\ty\rangle)}{\vastnode} +\] +transforms a parse node $\vparsednode$ into an AST node $\vastnode$. + +\begin{mathpar} +\inferrule{ + \buildoption[\Nasty](\vastyopt) \astarrow \astversion{\vastyopt} +}{ + { + \begin{array}{r} + \buildopttypedidentifier(\overname{\Ntypedidentifier(\Tidentifier(\id), \namednode{\vastyopt}{\option{\Nasty}})}{\vparsednode}) \astarrow \\ + \overname{(\id, \astversion{\vastyopt})}{\vastnode} + \end{array} + } +} +\end{mathpar} + +\subsubsection{ASTRule.ReturnType \label{sec:ASTRule.ReturnType}} +\hypertarget{build-returntype}{} +The function +\[ +\buildreturntype(\overname{\parsenode{\Nreturntype}}{\vparsednode}) \aslto \overname{\ty}{\vastnode} +\] +transforms a parse node $\vparsednode$ into an AST node $\vastnode$. + +\begin{mathpar} +\inferrule{}{ + \buildreturntype(\overname{\Nreturntype(\Tarrow, \punnode{\Nty})}{\vparsednode}) \astarrow + \overname{\astof{\tty}}{\vastnode} +} +\end{mathpar} + +\subsubsection{ASTRule.ParamsOpt \label{sec:ASTRule.ParamsOpt}} +\hypertarget{build-paramsopt}{} +The function +\[ +\buildparamsopt(\overname{\parsenode{\Nparamsopt}}{\vparsednode}) \aslto + \overname{(\identifier\times\langle\ty\rangle)^*}{\vastnode} +\] +transforms a parse node $\vparsednode$ into an AST node $\vastnode$. + +\begin{mathpar} +\inferrule[empty]{}{ + \buildparamsopt(\overname{\Nparamsopt(\epsilonnode)}{\vparsednode}) \astarrow + \overname{\emptylist}{\vastnode} +} +\end{mathpar} + +\begin{mathpar} +\inferrule[non\_empty]{ + \buildclist[\Nopttypedidentifier](\ids) \astarrow \astversion{\ids} +}{ + \buildparamsopt(\overname{\Nparamsopt(\Tlbrace, \namednode{\ids}{\Clist{\Nopttypedidentifier}}, \Trbrace)}{\vparsednode}) \astarrow + \overname{\astversion{\ids}}{\vastnode} +} +\end{mathpar} + +\subsubsection{ASTRule.AccessArgs \label{sec:ASTRule.AccessArgs}} +\hypertarget{build-accessargs}{} +The function +\[ +\buildaccessargs(\overname{\parsenode{\Naccessargs}}{\vparsednode}) \aslto + \overname{(\identifier\times\ty)^*}{\vastnode} +\] +transforms a parse node $\vparsednode$ into an AST node $\vastnode$. + +\begin{mathpar} +\inferrule{ + \buildclist[\Ntypedidentifier](\ids) \astarrow \astversion{\ids} +}{ + \buildaccessargs(\overname{\Naccessargs(\Tlbracket, \namednode{\ids}{\Clist{\Ntypedidentifier}}, \Trbracket)}{\vparsednode}) \astarrow + \overname{\astversion{\ids}}{\vastnode} +} +\end{mathpar} + +\subsubsection{ASTRule.FuncArgs \label{sec:ASTRule.FuncArgs}} +\hypertarget{build-funcargs}{} +The function +\[ +\buildfuncargs(\overname{\parsenode{\Nfuncargs}}{\vparsednode}) \aslto + \overname{(\identifier\times\ty)^*}{\vastnode} +\] +transforms a parse node $\vparsednode$ into an AST node $\vastnode$. + +\begin{mathpar} +\inferrule{ + \buildclist[\Ntypedidentifier](\ids) \astarrow \astversion{\ids} +}{ + \buildfuncargs(\overname{\Nfuncargs(\Tlpar, \namednode{\ids}{\Clist{\Ntypedidentifier}}, \Trpar)}{\vparsednode}) \astarrow + \overname{\astversion{\ids}}{\vastnode} +} +\end{mathpar} + +\subsubsection{ASTRule.MaybeEmptyStmtList \label{sec:ASTRule.MaybeEmptyStmtList}} +\hypertarget{build-maybeemptystmtlist}{} +The function +\[ +\buildmaybeemptystmtlist(\overname{\parsenode{\Nmaybeemptystmtlist}}{\vparsednode}) \aslto + \overname{\stmt}{\vastnode} +\] +transforms a parse node $\vparsednode$ into an AST node $\vastnode$. + +\begin{mathpar} +\inferrule[empty]{}{ + \buildmaybeemptystmtlist(\overname{\Nmaybeemptystmtlist(\epsilonnode)}{\vparsednode}) \astarrow + \overname{\SPass}{\vastnode} +} +\end{mathpar} + +\begin{mathpar} +\inferrule[non\_empty]{}{ + \buildmaybeemptystmtlist(\overname{\Nmaybeemptystmtlist(\Nstmtlist)}{\vparsednode}) \astarrow + \overname{\astof{\vstmtlist}}{\vastnode} +} +\end{mathpar} + +\subsubsection{ASTRule.FuncBody \label{sec:ASTRule.FuncBody}} +\hypertarget{build-funcbody}{} +The function +\[ +\buildfuncargs(\overname{\parsenode{\Nfuncbody}}{\vparsednode}) \aslto + \overname{\stmt}{\vastnode} +\] +transforms a parse node $\vparsednode$ into an AST node $\vastnode$. + +\begin{mathpar} +\inferrule{}{ + { + \begin{array}{r} + \buildfuncbody(\overname{\Nfuncbody(\Tbegin, \namednode{\vstmts}{\Nmaybeemptystmtlist}, \Tend)}{\vparsednode}) \astarrow \\ + \overname{\astof{\vmaybeemptystmtlist}}{\vastnode} + \end{array} + } +} +\end{mathpar} + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +\section{Typing} +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +We also define the following helper rules: +\begin{itemize} + \item TypingRule.AnnotateAndDeclareFunc (see \secref{TypingRule.AnnotateAndDeclareFunc}) + \item TypingRule.AnnotateFuncSig (see \secref{TypingRule.AnnotateFuncSig}) + \item TypingRule.UseFuncSig (\secref{TypingRule.UseFuncSig}) + \item TypingRule.GetUndeclaredDefining (see \secref{TypingRule.GetUndeclaredDefining}) + \item TypingRule.ScanForParams (see \secref{TypingRule.ScanForParams}) + \item TypingRule.AnnotateParams (see \secref{TypingRule.AnnotateParams}) + \item TypingRule.AnnotateOneParam (see \secref{TypingRule.AnnotateOneParam}) + \item TypingRule.ArgsAsParams (see \secref{TypingRule.ArgsAsParams}) + \item TypingRule.ArgAsParam (see \secref{TypingRule.ArgAsParam}) + \item TypingRule.AnnotateParamType (see \secref{TypingRule.AnnotateParamType}) + \item TypingRule.AnnotateArgs (see \secref{TypingRule.AnnotateArgs}) + \item TypingRule.AnnotateOneArg (see \secref{TypingRule.AnnotateOneArg}) + \item TypingRule.AnnotateReturnType (see \secref{TypingRule.AnnotateReturnType}) + \item TypingRule.DeclareOneFunc (see \secref{TypingRule.DeclareOneFunc}) + \item TypingRule.SubprogramClash (see \secref{TypingRule.SubprogramClash}) + \item TypingRule.AddNewFunc (see \secref{TypingRule.AddNewFunc}) + \item TypingRule.CheckSetterHasGetter (see \secref{TypingRule.CheckSetterHasGetter}) + \item TypingRule.AddSubprogram (see \secref{TypingRule.AddSubprogram}) +\end{itemize} + +\subsubsection{TypingRule.AnnotateAndDeclareFunc \label{sec:TypingRule.AnnotateAndDeclareFunc}} +\hypertarget{def-annotateanddeclarefunc}{} +The function +\[ + \annotateanddeclarefunc(\overname{\staticenvs}{\tenv}, \overname{\func}{\funcsig}) + \aslto (\overname{\staticenvs}{\tenv} \times \overname{\func}{\newfuncsig}) + \cup \overname{\TTypeError}{\TypeErrorConfig} +\] +annotates a subprogram definition $\funcsig$ in the static environment $\tenv$, +yielding a new subprogram definition $\newfuncsig$ and modified static environment +$\newtenv$. +\ProseOtherwiseTypeError + +\subsection{Prose} +All of the following apply: +\begin{itemize} + \item annotating the signature of $\funcsig$ in $\tenv$ as per + \secref{TypingRule.AnnotateFuncSig} yields + the environment $\tenvone$ and subprogram definition $\funcsigone$\ProseOrTypeError; + \item declaring the subprogram defined by $\funcsigone$ in $\tenvone$ + as per \secref{TypingRule.DeclareOneFunc} yields the environment $\newtenv$ + and new $\func$ node $\newfuncsig$\ProseOrTypeError. +\end{itemize} +\CodeSubsection{\AnnotateAndDeclareFuncBegin}{\AnnotateAndDeclareFuncEnd}{../Typing.ml} + +\subsection{Formally} +\begin{mathpar} +\inferrule{ + \annotatefuncsig(\tenv, \funcsig) \typearrow (\tenvone, \funcsigone) \OrTypeError\\\\ + \declareonefunc(\tenvone, \funcsigone) \typearrow (\newtenv, \newfuncsig) \OrTypeError +}{ + \annotateanddeclarefunc(\tenv, \funcsig) \typearrow (\newtenv, \newfuncsig) +} +\end{mathpar} + +\subsubsection{TypingRule.AnnotateFuncSig \label{sec:TypingRule.AnnotateFuncSig}} +\hypertarget{def-annotatefuncsig}{} +The function +\[ + \annotatefuncsig(\overname{\staticenvs}{\tenv}, \overname{\func}{\funcsig}) + \aslto (\overname{\staticenvs}{\newtenv} \times \overname{\func}{\newfuncsig}) + \cup \overname{\TTypeError}{\TypeErrorConfig} +\] +annotates the signature of a function definition $\funcsig$ in the static environment $\tenv$, +yielding a new function definition $\newfuncsig$ and modified static environment +$\newtenv$. +\ProseOtherwiseTypeError + +\subsection{Prose} +All of the following apply: +\begin{itemize} + \item $\tenvone$ is the static environment comprised of the global environment of $\tenv$ and an empty local environment; + \item obtaining the variables appearing in the formal types in $\funcsig$ that may be parameter-defining + in $\tenvone$ via $\getundeclareddefining$ yields \\ $\potentialparams$; + \item annotating the parameters explicitly listed in $\funcsig$ ($\funcsig.\funcparameters)$ \\ + yields environment $\tenvtwo$, in which the parameters are declared, + and the function \\ + $\declaredparams$, which binds parameter identifiers to their types\ProseOrTypeError; + \item annotating arguments from $\funcsig$ that serve as parameters in $\tenvtwo$ yields the list of parameters + $\argparams$ and modified environment $\tenvthree$\ProseOrTypeError; + \item $\vparameters$ is the list $\declaredparams$ concatenated with $\argparams$ with each type + transformed to an \optional\ type; + \item annotating the arguments listed in $\funcsig$ in $\tenvthree$ with $\tenvtwo$ via \\ + $\annotateargs$ yields the list of annotated + arguments $\vargs$ and modified environment $\tenvfour$\ProseOrTypeError; + \item annotating the return type of $\funcsig$ in $\tenvfour$ with $\tenvthree$ via \\ $\annotatereturntype$ yields + the annotated return type $\vreturntype$ and modified environment $\tenvfive$\ProseOrTypeError; + \item $\newfuncsig$ is $\funcsig$ with the listed of parameters substituted with \\ $\vparameters$, + the list of arguments substituted with $\vargs$, and return type substituted with $\vreturntype$; + \item $\newtenv$ is $\tenvfive$. +\end{itemize}\CodeSubsection{\AnnotateFuncSigBegin}{\AnnotateFuncSigEnd}{../Typing.ml} + +\subsection{Formally} +\begin{mathpar} +\inferrule{ + \tenvone \eqdef (G^\tenv, L^{\emptytenv})\\ + \getundeclareddefining(\tenvone, \funcsig) \typearrow \potentialparams\\ + { + \begin{array}{r} + \annotateparams(\tenvone, \potentialparams, \funcsig.\funcparameters, (\tenvone, \emptyfunc)) \typearrow \\ + (\tenvtwo, \declaredparams) \OrTypeError + \end{array} + }\\ + { + \begin{array}{r} + \argsasparams(\tenvtwo, \funcsig) \typearrow (\tenvthree, \argparams) \OrTypeError + \end{array} + }\\ + { + \begin{array}{rl} + \vparameters \eqdef & [(\id,\vt) \in \declaredparams: (\id, \langle\vt\rangle)]\ \concat \\ + & [(\id,\vt) \in \argparams: (\id, \langle\vt\rangle)] + \end{array} + }\\ + \annotateargs(\tenvthree, \tenvtwo, \funcsig, \argparams) \typearrow (\tenvfour, \vargs) \OrTypeError\\\\ + { + \begin{array}{r} + \annotatereturntype(\tenvfour, \tenvthree, \funcsig.\funcreturntype) \typearrow \\ + (\tenvfive, \vreturntype) \OrTypeError + \end{array} + }\\\\ + { + \begin{array}{rrcl} + \newfuncsig \eqdef \{ + & \funcname &:& \funcsig.\funcname,\\ + & \funcparameters &:& \vparameters,\\ + & \funcargs &:& \vargs,\\ + & \funcbody &:& \funcsig.\funcbody,\\ + & \funcreturntype &:& \vreturntype,\\ + & \funcsubprogramtype &:& \funcsig.\subprogramtype \\ + \} & && + \end{array} + } +}{ + \annotatefuncsig(\tenv, \funcsig) \typearrow (\overname{\tenvfive}{\newtenv}, \newfuncsig, \argparams) +} +\end{mathpar} + +\subsubsection{TypingRule.UseFuncSig \label{sec:TypingRule.UseFuncSig}} +\hypertarget{def-usefuncsig}{} +The function +\[ +\usefuncsig(\overname{\func}{\vf}) \aslto \overname{\pow{\identifier}}{\ids} +\] +returns the set of identifiers $\ids$ which the subprogram signature given +by $\vf$ depends on. + +\subsection{Prose} +Define $\ids$ as the union of applying $\usety$ to every type of an argument of $\vf$ +and applying $\usety$ to the \optional\ return type of $\vf$. + +\subsection{Formally} +\begin{mathpar} +\inferrule{}{ + \usefuncsig(\vf) \typearrow \overname{\bigcup_{(\Ignore, \vt) \in \vf.\funcargs}\usety(\vt) \cup \usety(\vf.\funcreturntype)}{\ids} +} +\end{mathpar} + +\subsubsection{TypingRule.GetUndeclaredDefining \label{sec:TypingRule.GetUndeclaredDefining}} +\hypertarget{def-getundeclareddefining}{} +The function +\[ +\getundeclareddefining(\overname{\staticenvs}{\tenv} \aslsep \overname{\func}{\funcsig}) +\aslto \overname{\pow{\identifier}}{\potentialparams} +\] +scans the list of types appearing in $\funcsig.\funcargs$ and in the return type +and returns the set of +identifiers that may be parameter-defining in $\tenv$. + +\subsection{Example} +In the following specification, the set of identifiers that may correspond +to parameters of the function \texttt{signature\_example} is $\{\texttt{A}\}$, +since \texttt{A} appears in the type \texttt{bits(A)} +of the argument \texttt{bv}. + +\VerbatimInput{\typingtests/TypingRule.AnnotateFuncSig.asl} + +\CodeSubsection{\GetUndeclaredDefiningBegin}{\GetUndeclaredDefiningEnd}{../Typing.ml} + +\subsection{Prose} +All of the following apply: +\begin{itemize} + \item define $\formaltypes$ to consist of the types associated with the list of arguments in $\funcsig$ + and the return type in $\funcsig$, if one exists; + \item scanning each type $\vt$ in $\formaltypes$ via $\scanforparams$ yields the set $\vparams_\vt$; + \item $\potentialparams$ is the union of $\vparams_\vt$ for each type $\vt$ in $\formaltypes$. +\end{itemize} + +\subsection{Formally} +\begin{mathpar} +\inferrule{ + { + \begin{array}{rcl} + \formaltypes &\eqdef& + [(\Ignore, \vt) \in \funcsig.\funcargs: \vt]\ \concat \\ + && \choice{\funcsig.\funcreturntype = \langle\retty\rangle}{[\retty]}{\emptylist} + \end{array} + }\\ + \vt\in\formaltypes: \scanforparams(\tenv, \vt) \typearrow \vparams_\vt +}{ + \getundeclareddefining(\tenv, \funcsig) \typearrow \overname{\bigcup_{\vt \in \tys} \vparams_\vt}{\potentialparams} +} +\end{mathpar} + +\subsubsection{TypingRule.ScanForParams \label{sec:TypingRule.ScanForParams}} +\hypertarget{def-scanforparams}{} +The function +\[ +\scanforparams(\overname{\staticenvs}{\tenv} \aslsep \overname{\ty}{\tty}) +\aslto \overname{\pow{\identifier}}{\potentialparams} +\] +scans a single type $\tty$ in $\tenv$ and returns the set of +identifiers that may be parameters in $\tenv$. + +\subsection{Example} +Consider the following specification: +\VerbatimInput{\typingtests/TypingRule.AnnotateFuncSig.asl} + +Scanning each type in the signature +of the function \texttt{signature\_example} yields the following results: +\begin{center} +\begin{tabular}{lll} +\textbf{Expression} & \textbf{Result} & \textbf{Reason}\\ +\hline +\texttt{bits(A)} & $\{\texttt{A}\}$ & \texttt{A} is a variable expression \\ +& & and \texttt{A} is not defined in the environment.\\ +\texttt{bits(W)} & $\emptyset$ & \texttt{W} is defined in the environment.\\ +\texttt{bits(A+B)} & $\emptyset$ & \texttt{A+B} is not a variable expression.\\ +\end{tabular} +\end{center} + +\subsection{Prose} +One of the following applies: +\begin{itemize} + \item All of the following apply (\textsc{tbits\_evar}): + \begin{itemize} + \item $\tty$ is a bitvector type over a variable expression for $\vx$, that is, \\ $\TBits(\EVar(\vx), \Ignore)$; + \item $\potentialparams$ is the singleton set consisting of $\vx$ if $\vx$ is not defined as a storage type in $\tenv$ + and the empty set, otherwise. + \end{itemize} + + \item All of the following apply (\textsc{tbits\_other}): + \begin{itemize} + \item $\tty$ is a bitvector type where the bitwidth expression is not a variable expression; + \item $\potentialparams$ is the empty set. + \end{itemize} + + \item All of the following apply (\textsc{ttuple}): + \begin{itemize} + \item $\tty$ is a tuple type over a list of types $\tys$; + \item obtaining the set of potential parameters for each type $\vt$ of $\tys$ in $\tenv$ yields $\vparams_\vt$; + \item $\potentialparams$ is the union of sets $\vparams_\vt$, for each type $\vt$ of $\tys$. + \end{itemize} + + \item All of the following apply (\textsc{other}): + \begin{itemize} + \item $\tty$ is neither a bitvector type or a tuple type; + \item $\potentialparams$ is the empty set. + \end{itemize} +\end{itemize} + +\begin{mathpar} + \inferrule[tbits\_evar]{ + \isundefined(\tenv, \vx) \typearrow \vb\\ + \potentialparams \eqdef \choice{\vb}{\{\vx\}}{\emptyset} + }{ + \scanforparams(\tenv, \overname{\TBits(\EVar(\vx), \Ignore)}{\tty}) \typearrow \potentialparams + } + \and + \inferrule[tbits\_other]{ + \astlabel(\ve) \neq \EVar + }{ + \scanforparams(\tenv, \overname{\TBits(\ve, \Ignore)}{\tty}) \typearrow \overname{\emptyset}{\potentialparams} + } + \and + \inferrule[ttuple]{ + \vt \in \tys: \scanforparams(\tenv, \vt) \typearrow \vparams_\vt + }{ + \scanforparams(\tenv, \overname{\TTuple(\tys)}{\tty}) \typearrow \overname{\bigcup_{\vt \in \tys} \vparams_\vt}{\potentialparams} + } + \and + \inferrule[other]{ + \astlabel(\tty) \not\in \{\TBits, \TTuple\} + }{ + \scanforparams(\tenv, \tty) \typearrow \overname{\emptyset}{\potentialparams} + } + \end{mathpar} + +\subsubsection{TypingRule.AnnotateParams \label{sec:TypingRule.AnnotateParams}} +\hypertarget{def-annotateparams}{} +The function +\[ +\begin{array}{r} +\annotateparams( + \overname{\staticenvs}{\tenv} \aslsep + \overname{\pow{\identifier}}{\potentialparams} \aslsep + \overname{(\identifier \times \langle\ty\rangle)^*}{\vparameters} \aslsep\ + (\overname{\staticenvs}{\tenvonep} \times \overname{\identifier\rightarrow\ty}{\acc}) +) \aslto \\ +(\overname{\staticenvs}{\newtenv} \times \overname{\identifier\rightarrow\ty}{\declaredparams}) +\cup \overname{\TTypeError}{\TypeErrorConfig} +\end{array} +\] +scans the list of explicitly defined parameters $\vparameters$ with respect to the set of potential +parameters $\potentialparams$ in $\tenv$ and then updates a pair +consisting of an updated environment $\tenvonep$, which accumulates local storage declarations +for the parameters, and a function $\acc$, which maps identifiers corresponding to parameters +to their associated types. +The updated pair is given in $\newtenv$ and $\declaredparams$. +\ProseOtherwiseTypeError + +\subsection{Example} +In the following specification, the list of explicitly defined parameters +of the function \texttt{signature\_example} is $\{\texttt{A}\}$. +Therefore, $\declaredparams$ binds \texttt{A} to the type \verb|integer{A}| +and $\newtenv$ effectively reflects an added declaration \verb|let A: integer{A}|. + +\VerbatimInput{\typingtests/TypingRule.AnnotateFuncSig.asl} + +\subsection{Prose} +One of the following applies: +\begin{itemize} + \item All of the following apply (\textsc{empty}): + \begin{itemize} + \item $\vparameters$ is the empty list; + \item $\newtenv$ is $\tenvonep$; + \item $\declaredparams$ is $\acc$. + \end{itemize} + + \item All of the following apply (\textsc{non\_empty}): + \begin{itemize} + \item $\vparameters$ is a list with $(\vx, \tyopt)$ as its \head\ and $\vparametersone$ as its \tail; + \item applying $\annotateoneparam$ to the parameter $(\vx, \tyopt)$ in $\tenvone$ with \\ + $\potentialparams$ and the pair $(\tenvonep, \acc)$ + yields the pair \\ + $(\tenvonepp, \accp)$\ProseOrTypeError; + \item annotating the parameter list $\vparametersone$ in $\tenvone$ with $\potentialparams$, starting with the pair + $(\tenvonepp, \accp)$ yields the pair \\ $(\newtenv, \declaredparams)$. + \end{itemize} +\end{itemize} + +\subsection{Formally} +\begin{mathpar} +\inferrule[empty]{}{ + { + \begin{array}{r} + \annotateparams(\tenvone, \potentialparams, \overname{\emptylist}{\vparameters}, (\tenvonep, \acc)) \typearrow \\ + (\overname{\tenvonep}{\newtenv}, \overname{\acc}{\declaredparams}) + \end{array} + } +} +\and +\inferrule[non\_empty]{ + \vparameters \eqname [(\vx,\tyopt)]\concat\vparametersone\\ + { + \begin{array}{r} + \annotateoneparam(\tenvone, \potentialparams, (\vx,\tyopt), (\tenvonep, \acc)) \typearrow \\ (\tenvonepp, \accp) \OrTypeError + \end{array} + }\\\\ + { + \begin{array}{r} + \annotateparams(\tenvone, \potentialparams, \vparametersone, (\tenvonepp, \accp)) \typearrow \\ (\newtenv, \declaredparams) \OrTypeError +\end{array} +}\\\\ +}{ + { + \begin{array}{r} + \annotateparams(\tenvone, \potentialparams, \vparameters, (\tenvonep, \acc)) \typearrow \\ + (\newtenv, \declaredparams) + \end{array} +} +} +\end{mathpar} + +\subsubsection{TypingRule.AnnotateOneParam \label{sec:TypingRule.AnnotateOneParam}} +The function +\hypertarget{def-annotateoneparam}{} +\[ +\begin{array}{r} +\annotateoneparam( + \overname{\staticenvs}{\tenv} \aslsep + \overname{\pow{\identifier}}{\potentialparams} \aslsep + (\overname{\identifier}{\vx} \times \overname{\langle\ty\rangle}{\tyopt}) \aslsep + (\overname{\staticenvs}{\tenvonep} \times \overname{\identifier\rightarrow\ty}{\acc}) +) \\ \aslto +(\overname{\staticenvs}{\newtenv} \times \overname{\identifier\rightarrow\ty}{\declaredparams}) +\cup \overname{\TTypeError}{\TypeErrorConfig} +\end{array} +\] +annotates the explicitly defined parameter given by $\vx$ and the \optional\ type $\tyoptp$ +with respect to the set of potential +parameters $\potentialparams$ in $\tenv$ and then updates a pair +consisting of an updated environment $\tenvonep$, which accumulates local storage declarations +for the parameters, and a function $\acc$, which maps identifiers corresponding to parameters +to their associated types. +The updated pair is given in $\newtenv$ and $\declaredparams$. +\ProseOtherwiseTypeError + +\subsection{Prose} +All of the following apply: +\begin{itemize} + \item checking that $\vx$ is not defined as a variable in $\tenvonep$ yields $\True$\ProseOrTypeError; + \item checking whether $\vx$ is included in the set $\potentialparams$ yields $\True$ or a type error + indicating that each parameter must have a defining argument, thus short-circuiting the entire rule; + \item One of the following applies: + \begin{itemize} + \item All of the following apply (\textsc{type\_parameterized}): + \begin{itemize} + \item $\tyopt$ is either $\None$ or a \parameterizedintegertype; + \item $\vt$ is defined as the \parameterizedintegertype\ for the identifier $\vx$. + \end{itemize} + + \item All of the following apply (\textsc{type\_annotated}): + \begin{itemize} + \item $\tyopt$ is the type $\vtone$, which is not the unconstrained integer type; + \item annotating $\vtone$ in $\tenvone$ yields $\vt$\ProseOrTypeError. + \end{itemize} + \end{itemize} + \item checking that $\vt$ is a constrained integer in $\tenvone$ via $\checkconstrainedinteger$ + yields $\True$\ProseOrTypeError; + \item adding the local storage element given by the identifier $\vx$, type $\vt$, and local declaration keyword + $\LDKLet$ in $\tenvonep$ yields $\newtenv$; + \item $\declaredparams$ is $\acc$ updated by the binding of $\vx$ to $\vt$. +\end{itemize} + +\subsection{Formally} +\begin{mathpar} +\inferrule[type\_parameterized]{ + \checkvarnotinenv{\tenvonep, \vx} \typearrow \True \OrTypeError\\\\ + \checktrans{\vx \in \potentialparams}{\ParameterWithoutDecl} \checktransarrow \True \OrTypeError\\\\ + (\tyopt = \None \lor \tyopt = \langle \unconstrainedinteger\rangle) \\ + \vt \eqdef \TInt(\parameterized(\vx))\\ + \checkconstrainedinteger(\tenvone, \vt) \typearrow \True \OrTypeError\\\\ + \addlocal(\tenvonep, \vx, \vt, \LDKLet) \typearrow \newtenv\\ + \declaredparams \eqdef \acc[\vx \mapsto \vt] +}{ + { + \begin{array}{r} + \annotateoneparam(\tenvone, \potentialparams, (\vx, \tyopt), (\tenvonep, \acc)) \typearrow \\ (\newtenv, \declaredparams) + \end{array} + } +} +\and +\inferrule[type\_annotated]{ + \checkvarnotinenv{\tenvonep, \vx} \typearrow \True \OrTypeError\\\\ + \checktrans{\vx \in \potentialparams}{\ParameterWithoutDecl} \checktransarrow \True \OrTypeError\\\\ + \vtone \neq \unconstrainedinteger\\ + \annotatetype{\False, \tenvone, \vtone} \typearrow \vt \OrTypeError\\\\ + \checkconstrainedinteger(\tenvone, \vt) \typearrow \True \OrTypeError\\\\ + \addlocal(\tenvonep, \vx, \vt, \LDKLet) \typearrow \newtenv\\ + \declaredparams \eqdef \acc[\vx \mapsto \vt] +}{ + { + \begin{array}{r} + \annotateoneparam(\tenvone, \potentialparams, (\vx, \overname{\langle\vtone\rangle}{\tyopt}), (\tenvonep, \acc)) \typearrow \\ (\newtenv, \declaredparams) + \end{array} + } +} + \end{mathpar} + +\subsubsection{TypingRule.ArgsAsParams \label{sec:TypingRule.ArgsAsParams}} +\hypertarget{def-argsasparams}{} +The function +\[ +\begin{array}{r} +\argsasparams( + \overname{\staticenvs}{\tenvone} \aslsep + \overname{\staticenvs}{\tenvtwo} \aslsep + \overname{\func}{\funcsig} \aslsep + \overname{\identifier\rightarrow\ty}{\declaredparams} + ) +\aslto \\ +(\overname{\staticenvs}{\newtenv} \times \overname{\identifier\rightarrow\ty}{\argparams}) +\cup \overname{\TTypeError}{\TypeErrorConfig} +\end{array} +\] +scans the list of arguments in $\func$ ($\func.\funcargs$) to find the ones that serve as +implicit parameters in $\tenvone$ and are not already included in the domain of $\declaredparams$. +The found parameters are added as local declarations to $\tenvtwo$, resulting in $\newtenv$, +and are used to update $\argparams$. +\ProseOtherwiseTypeError + +\subsection{Prose} +One of the following applies: +\begin{itemize} + \item All of the following apply (\textsc{empty}): + \begin{itemize} + \item the subprogram defined by $\funcsig$ has an empty list of arguments; + \item $\newtenv$ is $\tenvtwo$; + \item $\argparams$ is the empty list. + \end{itemize} + + \item All of the following apply (\textsc{non\_empty}): + \begin{itemize} + \item the subprogram defined by $\funcsig$ has arguments $\varg_{1..k}$; + \item obtaining the identifiers that can serve as parameters in the types of the formal arguments of $\funcsig$ + and in its return type yields $\vusedone$; + \item the set $\vused$ contains all identifiers $\vs$ from $\vusedone$ that are undefined in $\tenvone$ and are not + bound in $\declaredparams$; + \item the following premises define the sequences $\argparams_{1..k}$ and $\tenvtwo_{0..k}$ as follows; + \item $\argparams_1$ is $\declaredparams$; + \item $\tenvtwo_0$ is $\tenvtwo$; + \item for $\vi=1..k$, annotating the argument $\varg_\vi$ in $\tenvtwo$ with $\vused$ and the static environment $\tenvtwo_{\vi-1}$ + via $\argasparam$ yields $\tenvtwo_\vi$ and $\argparams_\vi$\ProseOrTypeError; + \item $\newtenv$ is $\tenvtwo_k$; + \item $\argparams$ is $\argparams_k$. + \end{itemize} +\end{itemize} + +\subsection{Example} +In the following specification, the argument \texttt{B} +of the function \texttt{signature\_example} is an implicit parameter +as it appears in the type \texttt{bits(A+B)} +(both for the argument \texttt{bv3} and as the return type) +and it is not listed as an explicit parameter. +Therefore, $\newtenv$ will effectively contain the declaration \verb|let B: integer{B}|. + +\VerbatimInput{\typingtests/TypingRule.AnnotateFuncSig.asl} + +\subsection{Formally} +\begin{mathpar} +\inferrule[empty]{ + \funcsig.\funcargs = \emptylist +}{ + { + \begin{array}{r} + \argsasparams(\tenvone, \tenvtwo, \funcsig, \declaredparams) \typearrow \\ + (\overname{\tenvtwo}{\newtenv}, \overname{\emptylist}{\argparams}) + \end{array} + } +} +\end{mathpar} + +\begin{mathpar} +\inferrule[non\_empty]{ + \funcsig.\funcargs \eqname \varg_{1..k}\\ + \usefuncsig(\funcsig) \typearrow \vusedone\\ + \vs\in\vusedone : \isundefined(\tenvone, \vs) \typearrow \vb_\vs\\ + \vused \eqdef \setcomprehension{\vs\in\vusedone \land \vb_\vs \land \declaredparams(\vs) = \bot}{\vs}\\ + \argparams_1 \eqdef \declaredparams\\ + \tenvtwo_0 \eqdef \tenvtwo\\ + \vi=1..k: \argasparam(\tenvtwo, \vused, \varg_\vi,\tenvtwo_{\vi-1}) \typearrow (\tenvtwo_\vi, \argparams_\vi) \OrTypeError +}{ + \argsasparams(\tenvone, \tenvtwo, \funcsig, \declaredparams) \typearrow + (\overname{\tenvtwo_k}{\newtenv}, \overname{\argparams_k}{\argparams}) +} +\end{mathpar} + +\subsubsection{TypingRule.ArgAsParam \label{sec:TypingRule.ArgAsParam}} +\hypertarget{def-argasparam}{} +The function +\[ +\argasparam\left( + \begin{array}{c} + \overname{\staticenvs}{\tenvtwo} \aslsep\\ + \overname{\pow{\identifier}}{\vused} \aslsep\\ + (\overname{\identifier}{\vx} \times \overname{\ty}{\tty}) \aslsep\\ + (\overname{\staticenvs}{\tenvtwop} \times \overname{\identifier\rightarrow\ty}{\acc}) + \end{array} + \right) +\aslto +(\overname{\staticenvs}{\newtenv} \times \overname{\identifier\rightarrow\ty}{\accp}) +\cup \overname{\TTypeError}{\TypeErrorConfig} +\] +checks whether the argument given by $\vx$ and type $\tty$ is an implicit parameter +by checking whether it appears in $\vused$ and not in $\acc$. +If it is identified as an implicit parameter, it is used to update $\tenvtwop$ to yield $\newtenv$ +and to update $\acc$ to yield $\accp$. +\ProseOtherwiseTypeError + +\subsection{Prose} +One of the following applies: +\begin{itemize} + \item All of the following apply (\textsc{not\_used}): + \begin{itemize} + \item $\vx$ is not a member of $\vused$; + \item $\newtenv$ is $\tenvtwop$; + \item $\accp$ is $\acc$. + \end{itemize} + + \item All of the following apply (\textsc{used}): + \begin{itemize} + \item $\vx$ is a member of $\vused$; + \item checking that $\vx$ is not declared in $\tenvtwop$ yields $\True$\ProseOrTypeError; + \item annotating $\tty$ with identifier $\vx$ as a potential parameter type in $\tenvtwo$, + which is an environment to which all explicit parameters have been added but implicit parameters were not added to, + via $\annotateparamtype$ yields $\vt$\ProseOrTypeError; + \item checking whether $\vt$ is a constrained integer type in $\tenvtwo$ yields $\True$\ProseOrTypeError; + \item adding $\vx$ as a local storage element to $\tenvtwop$ with type $\vt$ and local declaration keyword $\LDKLet$ yields + $\newtenv$; + \item $\accp$ is $\acc$ updated by binding $\vx$ to $\vt$. + \end{itemize} +\end{itemize} + +\subsection{Formally} +\begin{mathpar} +\inferrule[not\_used]{ + \vx \not\in \vused +}{ + \argasparam(\tenvtwo, \vused, (\vx, \tty), (\tenvtwop, \acc)) + \typearrow (\overname{\tenvtwop}{\newtenv}, \overname{\acc}{\accp}) +} +\and +\inferrule[used]{ + \vx \in \vused\\ + \checkvarnotinenv{\tenvtwop, \vx} \typearrow \True \OrTypeError\\\\ + \annotateparamtype(\tenvtwo, \tty, \vx) \typearrow \vt \OrTypeError\\\\ + \checkconstrainedinteger(\tenvtwo, \vt) \typearrow \True \OrTypeError\\\\ + \addlocal(\tenvtwop, \vx, \vt, \LDKLet) \typearrow \newtenv\\ + \accp \eqdef \acc[\vx\mapsto\vt] +}{ + \argasparam(\tenvtwo, \vused, (\vx, \tty), (\tenvtwop, \acc)) + \typearrow (\newtenv, \accp) +} +\end{mathpar} + +\subsubsection{TypingRule.AnnotateParamType \label{sec:TypingRule.AnnotateParamType}} +\hypertarget{def-annotateparamtype}{} +The function +\[ + \annotateparamtype(\overname{\staticenvs}{\tenv} \aslsep \overname{\ty}{\tty} \aslsep \overname{\identifier}{\vx}) + \typearrow \overname{\ty}{\newty} +\] +annotates the type $\tty$ in $\tenv$, considering it as a subprogram parameter with identifier $\vx$, +yielding the type $\newtenv$. +It is assumed that $\tenv$ is an environment to which all explicitly defined parameters of the subprogram +in context were added to, but the implicitly defined parameters were not added to. +\ProseOtherwiseTypeError + +\subsection{Prose} +One of the following applies: +\begin{itemize} + \item All of the following apply (\textsc{tint\_unconstrained}): + \begin{itemize} + \item $\tty$ is the unconstrained integer type; + \item $\newty$ is the \parameterizedintegertype\ for the identifier $\vx$. + \end{itemize} + + \item All of the following apply (\textsc{other}): + \begin{itemize} + \item $\tty$ is not the unconstrained integer type; + \item annotating the type $\tty$ in $\tenv$ yields $\newty$\ProseOrTypeError. + \end{itemize} +\end{itemize} + +\begin{mathpar} +\inferrule[tint\_unconstrained]{} +{ + \annotateparamtype(\tenv, \overname{\unconstrainedinteger}{\tty}, \vx) \typearrow \overname{\TInt(\parameterized(\vx))}{\newty} +} +\end{mathpar} + +\begin{mathpar} +\inferrule[other]{ + \tty \neq \unconstrainedinteger\\ + \annotatetype{\tenv, \tty} \typearrow \newty \OrTypeError +}{ + \annotateparamtype(\tenv, \tty, \vx) \typearrow \newty +} +\end{mathpar} + +\subsubsection{TypingRule.AnnotateArgs \label{sec:TypingRule.AnnotateArgs}} +\hypertarget{def-annotateargs}{} +The function +\[ +\begin{array}{r} +\annotateargs( + \overname{\staticenvs}{\tenvtwo} \aslsep + \overname{\staticenvs}{\tenvthree} \aslsep + \overname{\func}{\funcsig} \aslsep + \overname{\identifier\rightarrow\ty}{\argparams} +) +\aslto \\ +(\overname{\staticenvs}{\newtenv} \times \overname{(\identifier\times\ty)^*}{\vnewargs}) +\cup \overname{\TTypeError}{\TypeErrorConfig} +\end{array} +\] +annotates the arguments listed in $\funcsig$ in the context of +of $\argparams$, which binds parameters to their types, +and two static environments: +$\tenvtwo$ --- the environment to which only explicit parameters were added, and +$\tenvthree$ --- the environment to which all parameters (explicit and implicit) were added. +The result is the environment $\newtenv$ where all arguments have been declared and +the annotated list of arguments $\vnewargs$. +\ProseOtherwiseTypeError + +\subsection{Prose} +One of the following applies: +\begin{itemize} + \item All of the following apply (\textsc{no\_args}): + \begin{itemize} + \item the function defined by $\funcsig$ has an empty list of arguments; + \item $\newtenv$ is $\tenvthree$; + \item $\vnewargs$ is the empty list. + \end{itemize} + + \item All of the following apply (\textsc{some\_args}): + \begin{itemize} + \item the function defined by $\funcsig$ has arguments $\varg_{1..k}$; + \item the following premises define the sequence of static environments $\tenvthree_{0..k}$ and + list of typed identifiers $\vnewarg_{1..k}$; + \item $\tenvthree_0$ is $\tenvthree$; + \item annotating the argument $\varg_\vi$ in the context of $\tenvtwo$, $\tenvthree$, $\argparams$, + and $\tenvthree_{\vi-1}$ via $\annotateonearg$ yields $(\tenvthree_\vi, \vnewarg_\vi)$\ProseOrTypeError; + \item $\newtenv$ is $\tenvthree_k$; + \item $\vnewargs$ is the list $\vnewarg_{1..k}$. + \end{itemize} +\end{itemize} + +\subsection{Example} +In the following specification, the annotated arguments are +\texttt{bv}, \texttt{bv2}, \texttt{bv3}, and \texttt{C}. +The argument \texttt{B} is not annotated as an argument since it is classified +and annotated as a parameter. + +\VerbatimInput{\typingtests/TypingRule.AnnotateFuncSig.asl} + +\subsection{Formally} +\begin{mathpar} +\inferrule[no\_args]{ + \funcsig.\funcargs = \emptylist +}{ + \annotateargs(\tenvtwo, \tenvthree, \funcsig, \argparams) \typearrow (\overname{\tenvthree}{\newtenv}, \overname{\emptylist}{\vnewargs}) +} +\and +\inferrule[some\_args]{ + \funcsig.\funcargs \eqname \varg_{1..k}\\ + \tenvthree_{0} \eqdef \tenvthree\\ + { + \begin{array}{r} + \vi=1..k: \annotateonearg(\tenvtwo, \tenvthree, \argparams, (\tenvthree_{\vi-1}, \varg_{\vi})) \typearrow \\ + (\tenvthree_{\vi}, \vnewarg_\vi) \OrTypeError + \end{array} + }\\ + \vnewargs \eqdef [i=1..k: \vnewarg_{\vi}] +}{ + \annotateargs(\tenvtwo, \tenvthree, \funcsig, \argparams) \typearrow + (\overname{\tenvthree_k}{\newtenv}, \vnewargs) +} +\end{mathpar} + +\subsubsection{TypingRule.AnnotateOneArg \label{sec:TypingRule.AnnotateOneArg}} +\hypertarget{def-annotateonearg}{} +The function +\[ +\begin{array}{r} +\annotateonearg( + \overname{\staticenvs}{\tenvtwo} \aslsep + \overname{\staticenvs}{\tenvthree} \aslsep + \overname{\identifier\rightarrow\ty}{\argparams} \aslsep + (\overname{\staticenvs}{\tenvthreep} \times (\overname{\vx}{\identifier} \times \overname{\ty}{\tty})) +) \aslto \\ +(\overname{\staticenvs}{\newtenv} \times\ (\overname{\vx}{\identifier} \times \overname{\ty}{\ttyp})) +\cup \overname{\TTypeError}{\TypeErrorConfig} +\end{array} +\] +annotates the argument $\vx$ of type $\tty$ in the context of $\argparams$, which binds parameters to their types, +and the following static environments: +$\tenvtwo$ --- the environment to which only explicit parameters were added, +$\tenvthree$ --- $\tenvtwo$ with the addition of implicit parameters, and +$\tenvthreep$ --- same as $\tenvthree$ but updated with previously annotated arguments. +The result is the updated environment $\newtenv$ with the added declaration for the current argument +and the annotated argument, which has the same identifier $\vx$ and the annotated type $\vtp$. +\ProseOtherwiseTypeError + +\subsection{Prose} +One of the following applies: +\begin{itemize} + \item All of the following apply (\textsc{param}): + \begin{itemize} + \item $\vx$ is not bound in $\argparams$; + \item annotating the type $\tty$ in $\tenvtwo$ yields $\ttyp$; + \item $\newtenv$ is $\tenvthreep$. + \end{itemize} + + \item All of the following apply (\textsc{not\_param}): + \begin{itemize} + \item $\vx$ is bound in $\argparams$; + \item checking that $\vx$ is not defined in $\tenvthreep$ yields $\True$\ProseOrTypeError; + \item annotating the type $\tty$ in $\tenvthree$ yields $\ttyp$; + \item adding a local storage element $\vx$ with type $\ttyp$ and local declaration keyword $\LDKLet$ yields + $\newtenv$. + \end{itemize} +\end{itemize} + +\subsection{Formally} +\begin{mathpar} +\inferrule[param]{ + \argparams(\vx) \neq \bot\\ + \annotatetype{\tenvtwo, \tty} \typearrow \ttyp \OrTypeError +}{ + \annotateonearg(\tenvtwo, \tenvthree, \argparams, (\tenvthreep, (\vx, \tty))) + \typearrow (\overname{\tenvthreep}{\newtenv}, (\vx, \ttyp)) +} +\end{mathpar} + +\begin{mathpar} +\inferrule[not\_param]{ + \argparams(\vx) = \bot\\ + \checkvarnotinenv{\tenvthreep, \vx} \typearrow \True \OrTypeError\\\\ + \annotatetype{\tenvthree, \tty} \typearrow \ttyp \OrTypeError\\\\ + \addlocal(\tenvthreep, \vx, \ttyp, \LDKLet) \typearrow \newtenv +}{ + { + \begin{array}{r} + \annotateonearg(\tenvtwo, \tenvthree, \argparams, (\tenvthreep, (\vx, \tty))) + \typearrow \\ (\newtenv, (\vx, \ttyp)) + \end{array} + } +} +\end{mathpar} + +\subsubsection{TypingRule.AnnotateReturnType \label{sec:TypingRule.AnnotateReturnType}} +\hypertarget{def-annotatereturntype}{} +The function +\[ +\annotatereturntype( + \overname{\staticenvs}{\tenvthree} \aslsep + \overname{\staticenvs}{\tenvfour} \aslsep + \overname{\langle\ty\rangle}{\returntype} +) \aslto +(\overname{\staticenvs}{\newtenv} \times \overname{\ty}{\newreturntype}) +\cup \overname{\TTypeError}{\TypeErrorConfig} +\] +annotates the \optional\ return type $\returntype$ in the context of the static environment +$\tenvthree$ where all parameters have been added to, and +$\tenvfour$ where all parameters and arguments have been added to. +The result is the static environment $\newtenv$, which is $\tenvfour$ with the +annotated return type and the \optional\ annotated return type $\newreturntype$. +\ProseOtherwiseTypeError + +\subsection{Prose} +One of the following applies: +\begin{itemize} + \item All of the following apply (\textsc{no\_return\_type}): + \begin{itemize} + \item $\returntype$ is $\None$; + \item $\newtenv$ is $\tenvfour$; + \item $\newreturntype$ is $\None$. + \end{itemize} + + \item All of the following apply (\textsc{has\_return\_type}): + \begin{itemize} + \item $\returntype$ is $\langle\tty\rangle$; + \item annotating $\tty$ in $\tenvthree$ yields $\ttyp$\ProseOrTypeError; + \item $\newreturntype$ is $\langle\ttyp\rangle$; + \item $\newtenv$ is $\tenvfour$ with its local environment updated by binding its \\ $\funcreturntype$ field + to $\newreturntype$. + \end{itemize} +\end{itemize} + +\subsection{Formally} +\begin{mathpar} +\inferrule[no\_return\_type]{} +{ + \annotatereturntype(\tenvthree, \tenvfour, \overname{\None}{\returntype}) \typearrow + (\overname{\tenvfour}{\newtenv}, \overname{\None}{\newreturntype}) +} +\and +\inferrule[has\_return\_type]{ + \annotatetype{\tenvthree, \tty} \typearrow \ttyp \OrTypeError\\\\ + \newreturntype \eqdef \langle\ttyp\rangle\\ + \newtenv \eqdef (G^\tenvfour, L^\tenvfour[\funcreturntype\mapsto\newreturntype]) +}{ + \annotatereturntype(\tenvthree, \tenvfour, \overname{\langle\tty\rangle}{\returntype}) \typearrow + (\newtenv, \newreturntype) +} +\end{mathpar} + +\subsubsection{TypingRule.DeclareOneFunc \label{sec:TypingRule.DeclareOneFunc}} +\hypertarget{def-declareonefunc}{} +The function +\[ + \declareonefunc(\overname{\staticenvs}{\tenv}, \overname{\func}{\funcsig}) + \aslto (\overname{\staticenvs}{\newtenv} \times \overname{\func}{\newfuncsig}) + \cup \overname{\TTypeError}{\TypeErrorConfig} +\] +checks that a subprogram defined by $\funcsig$ can be added to the static environment $\tenv$, +resulting in an annotated function definition $\newfuncdef$ and new static environment $\newtenv$. +\ProseOtherwiseTypeError + +\subsection{Prose} +All of the following apply: +\begin{itemize} + \item $\funcsig$ has name $\name$, arguments $\vargs$, and type $\subprogramtype$, that is, + \[ + \begin{array}{rrcl} + \funcsig \eqdef \{ + & \funcname &:& \name,\\ + & \funcparameters &:& \vp,\\ + & \funcargs &:& \vargs,\\ + & \funcbody &:& \SBASL(\bd),\\ + & \funcreturntype &:& \vt,\\ + & \funcsubprogramtype &:& \subprogramtype \\ + \} & ; && + \end{array} + \] + \item adding a new subprogram with $\name$, $\vargs$, and $\subprogramtype$ to $\tenv$ yields the new + environment $\tenvone$ and new name $\namep$\ProseOrTypeError; + \item checking that $\namep$ is not already declared in the global environment of $\tenvone$ + yields $\True$\ProseOrTypeError; + \item ensuring that each setter has a getter given $\funcsig$ in $\tenv$ yields $\True$\ProseOrTypeError; + \item $\funcsigone$ is $\funcsig$ with $\name$ substituted by $\nameone$; + \item adding a subprogram with name $\namep$ and definition $\funcsigone$ to $\tenvone$ yields $\newtenv$\ProseOrTypeError. +\end{itemize} +\CodeSubsection{\DeclareOneFuncBegin}{\DeclareOneFuncEnd}{../Typing.ml} + +\subsection{Formally} +\begin{mathpar} +\inferrule{ + { + \begin{array}{rrcl} + \funcsig \eqdef \{ + & \funcname &:& \name,\\ + & \funcparameters &:& \vp,\\ + & \funcargs &:& \vargs,\\ + & \funcbody &:& \SBASL(\bd),\\ + & \funcreturntype &:& \vt,\\ + & \funcsubprogramtype &:& \subprogramtype \\ + \} &&& + \end{array} + }\\ + \addnewfunc(\tenv, \name, \vargs, \subprogramtype) \typearrow + (\tenvone, \namep) \OrTypeError\\\\ + \checkvarnotingenv{\tenvone, \namep} \typearrow \True \OrTypeError\\\\ + \checksetterhasgetter(\tenvone, \funcsig) \typearrow \True \OrTypeError\\\\ + { + \begin{array}{rrcl} + \newfuncsig \eqdef \{ + & \funcname &:& \namep,\\ + & \funcparameters &:& \vp,\\ + & \funcargs &:& \vargs,\\ + & \funcbody &:& \SBASL(\bd),\\ + & \funcreturntype &:& \vt,\\ + & \funcsubprogramtype &:& \subprogramtype \\ + \} &&& + \end{array} + }\\ + \addsubprogram(\tenvone, \namep, \funcsigone) \typearrow \newtenv \OrTypeError +}{ + \declareonefunc(\tenv, \funcsig) \typearrow (\newtenv, \newfuncsig) +} +\end{mathpar}\lrmcomment{This relates to \identi{HJRD}, \identd{BTBR}, \identi{FSFQ}, \identi{PFGQ}, and \identr{PGFC}.} + +\subsubsection{TypingRule.SubprogramClash \label{sec:TypingRule.SubprogramClash}} +\hypertarget{def-subprogramclash}{} +The function +\[ + \subprogramclash( + \overname{\staticenvs}{\tenv} \aslsep + \overname{\Strings}{\name} \aslsep + \overname{\subprogramtype}{\subpgmtype} \aslsep + \overname{\ty^*}{\formaltypes} + ) + \aslto + \overname{\Bool}{\vb} \cup \overname{\TTypeError}{\TypeErrorConfig} +\] +checks whether the unique subprogram associated with $\name$ +clashes with another subprogram +that has subprogram type $\subpgmtype$ and list of formal types $\formaltypes$, +yielding a Boolean value in $\vb$. +\ProseOtherwiseTypeError + +The function is only defined when there exists a binding for $\name$ in the +$\subprograms$ map of $\tenv$. + +\subsection{Prose} +All of the following apply: +\begin{itemize} + \item the subprogram type associated with the unique subprogram named by $\name$ is $\namesubpgmtype$; + \item applying $\subprogramtypesclash$ to $\namesubpgmtype$ and $\subpgmtype$ yields \\ + $\True$\ProseTerminateAs{\False} + (that is, if both $\namesubpgmtype$ and $\subpgmtype$ are $\STGetter$ or both are $\STSetter$ then the + subprogram types are considered to be non-clashing and the entire rule short-circuits to $\False$); + \item $\nameargs$ is the list of pairs of types and identifiers associated with the function definition + of $\name$ in $\tenv$; + \item determining whether there is an argument clash between $\formaltypes$ and \\ + $\nameformals$ in $\tenv$ yields $\vb$\ProseOrTypeError. +\end{itemize} +\subsection{Formally} +\hypertarget{def-subprogramtypeclash}{} +We first introduce the helper predicate +\[ + \subprogramtypesclash( + \overname{\subprogramtype}{\subpgmtypeone} \aslsep + \overname{\subprogramtype}{\subpgmtypetwo} + ) \aslto \overname{\Bool}{\vb} +\] +which defines whether two subprogram types are considered to be clashing: +\begin{mathpar} +\inferrule{ + \vbone \eqdef + { + \begin{array}{l} + (\subpgmtypeone=\STGetter \land \subpgmtypetwo=\STSetter)\ \lor\\ + (\subpgmtypeone=\STSetter \land \subpgmtypetwo=\STGetter) + \end{array} + }\\\\ + \vb \eqdef \neg\vbone +}{ + \subprogramtypesclash(\subpgmtypeone, \subpgmtypetwo) \typearrow \vb +} +\end{mathpar} + +\begin{mathpar} +\inferrule{ + \namesubpgmtype \eqdef G^\tenv.\subprograms(\name).\subprogramtype\\ + \subprogramtypesclash(\namesubpgmtype, \subpgmtype) \typearrow \True \terminateas \False\\ + \nameargs \eqdef G^\tenv.\subprograms(\name).\funcargs\\ + \hasargclash(\formaltypes, \nameargs) \typearrow \vb +}{ + \subprogramclash(\tenv, \namep, \subpgmtype, \formaltypes) \typearrow \vb +} +\end{mathpar}\lrmcomment{This is related to \identd{BTBR}, \identi{FSFQ}, \identi{PFGQ}.} + +\subsubsection{TypingRule.AddNewFunc \label{sec:TypingRule.AddNewFunc}} +\hypertarget{def-addnewfunc}{} +The function +\[ + \begin{array}{rl} + \addnewfunc( + \overname{\staticenvs}{\tenv} \aslsep + \overname{\identifier}{\name} \aslsep + \overname{\typedidentifier^*}{\formals} \aslsep + \overname{\subprogramtype}{\subpgmtype}) + & \aslto\\ + (\overname{\staticenvs}{\newtenv} \times \overname{\Strings}{\newname}) + \cup \overname{\TTypeError}{\TypeErrorConfig} & + \end{array} +\] +ensures that the subprogram given by the identifier $\name$, list of formals $\formals$, +and subprogram type $\subpgmtype$ has a unique name among all the potential subprograms +that overload $\name$. +The result is the unique subprogram identifier $\newname$, which is used to distinguish it in the set +of overloaded subprograms (that is, other subprograms that share the same name) +and the environment $\newtenv$, which is updated with $\newname$. +\ProseOtherwiseTypeError + +\subsection{Prose} +One of the following applies: +\begin{itemize} + \item All of the following apply (\textsc{first\_name}): + \begin{itemize} + \item the $\subprogramrenamings$ map in the global environment of $\tenv$ does not have a binding for $\name$; + \item $\newtenv$ is $\tenv$ with the $\subprogramrenamings$ updated by binding $\name$ to the singleton set containing + $\name$. + \end{itemize} + + \item All of the following apply (\textsc{name\_exists}): + \begin{itemize} + \item the $\subprogramrenamings$ map in the global environment of $\tenv$ binds $\name$ to the set of strings $\othernames$; + \item $\newname$ is the unique name that will be associated with the subprogram given by the identifier $\name$, list of formals $\formals$, + and subprogram type $\subpgmtype$. It is constructed by concatenating a hyphen (\texttt{-}) to $\name$, followed + by a string corresponding to the number of strings in $\othernames$. + Notice that this is not an ASL identifier, as ASL identifiers do not contain hyphens, which ensures that this string + does not occur in any specification; + \item $\formaltypes$ is the list of types that appear in $\formals$ in the same order; + \item checking for each $\namep$ in $\othernames$ whether the subprogram associated with $\namep$ clashes + with the subprogram type $\subpgmtype$ and list of types $\formaltypes$ yields $\False$ + or a type error that indicates there are multiply defined subprograms, which short-circuits the entire rule; + \item $\newtenv$ is $\tenv$ with the $\subprogramrenamings$ updated by binding $\name$ to the union of $\othernames$ and + $\{\newname\}$. + \end{itemize} +\end{itemize} +\subsection{Formally} +\newcommand\stringconcat[0]{\hyperlink{def-stringconcat}{\texttt{+}}} +\newcommand\stringofint[0]{\hyperlink{def-stringofnat}{\texttt{string\_of\_nat}}} + +We use the following functions to construct a unique string for each subprogram: +\begin{itemize} +\hypertarget{def-stringconcat}{} +\item The function $\stringconcat : \Strings \times \Strings \rightarrow \Strings$ +concatenates two strings. + +\hypertarget{def-stringofnat}{} +\item The function $\stringofint : \N \rightarrow \Strings$ converts a natural number +to the corresponding string. +\end{itemize} + +\begin{mathpar} +\inferrule[first\_name]{ + G^\tenv.\subprogramrenamings(\name) = \bot\\ + \newtenv \eqdef (G^\tenv.\subprogramrenamings[\name\mapsto\{\name\}], L^\tenv) +}{ + \addnewfunc(\tenv, \name, \formals, \subpgmtype) \typearrow + (\newtenv, \overname{\name}{\newname}) +} +\end{mathpar} + +\begin{mathpar} +\inferrule[name\_exists]{ + G^\tenv.\subprogramrenamings(\name) = \othernames\\ + k \eqdef \cardinality{\othernames}\\ + \newname \eqdef \name\ \stringconcat\ \texttt{"-"}\ \stringconcat\ \stringofint(k)\\ + \formaltypes \eqdef [(\id,\vt) \in \formals : \vt]\\ + { + \left(\begin{array}{l} + \namep \in \othernames: \\ \subprogramclash(\tenv, \namep, \subpgmtype, \formaltypes) \typearrow + \vb_{\namep} \OrTypeError + \end{array}\right) + }\\\\ + \namep \in \othernames: \checktrans{\neg\vb_{\namep}}{\SubrogramDeclaredMultipleTimes} \typearrow \True \OrTypeError\\\\ + \newtenv \eqdef (G^\tenv.\subprogramrenamings[\name\mapsto \othernames \cup \{\newname\}], L^\tenv) +}{ + \addnewfunc(\tenv, \name, \formals, \subpgmtype) \typearrow + (\newtenv, \newname) +} +\end{mathpar}\lrmcomment{This is related to \identr{PGFC}.} + +\CodeSubsection{\AddNewFuncBegin}{\AddNewFuncEnd}{../Typing.ml} + +\subsubsection{TypingRule.CheckSetterHasGetter \label{sec:TypingRule.CheckSetterHasGetter}} +\hypertarget{def-checksetterhashgetter}{} +The function +\[ + \checksetterhasgetter(\overname{\staticenvs}{\tenv} \aslsep \overname{\func}{\funcsig}) + \aslto \overname{\True}{\vb} \cup \overname{\TTypeError}{\TypeErrorConfig} +\] +checks whether the setter procedure given by $\funcsig$ has a corresponding getter, +returning $\True$ if this condition holds and a type error otherwise. + +\subsection{Prose} +All of the following apply: +\begin{itemize} + \item checking that the subprogram type of $\funcsig$ is one of $\STSetter$ and \\ $\STEmptySetter$ + has one of two outcomes: + $\False$, which satisfies the premise; + or $\True$, which short-circuits the entire rule + (since the subprogram is not any kind of setter and no getter is required); + \item \view\ the list of arguments of $\funcsig$ (that is, $\funcsig.\funcargs$) as follows: + the \head\ is an argument that has the type $\rettype$; + the \tail\ is a list with arguments that have the types $\argtypes$; + \item applying $\subprogramforname$ to look up $\tenv$ for a subprogram with the name given by $\funcsig$ (that is, $\funcsig.\funcname$) + yields a subprogram definition AST node $\funcsigp$\ProseOrTypeError; + \item define $\watendgettertype$ as $\STGetter$ if $\funcsig.\subprogramtype$ is \\ $\STSetter$ and + $\STEmptyGetter$ otherwise (meaning, $\funcsig.\subprogramtype$ is $\STEmptySetter$); + \item checking that $\watendgettertype$ is the same as $\funcsigp.\funcsubprogramtype$ \\ yields $\True$\ProseOrTypeError; + \item define $\argtypesp$ as the list of types appearing in the signature of $\funcsigp$ (that is, in $\funcsigp.\funcargs$); + \item checking, for each index $\vi$ in the indices for $\argtypes$, that the type at $\argtypes[\vi]$ and the type at $\argtypesp[\vi]$ + are \typeequivalent\ yields $\True$\ProseOrTypeError; + \item checking that $\rettype$ and $\funcsigp.\funcreturntype$ are \typeequivalent\ yields \\ + $\True$\ProseOrTypeError; + \item define $\vb$ as $\True$ (that is, unless the rule short-circuited with a type error). +\end{itemize} +\CodeSubsection{\CheckSetterHasGetterBegin}{\CheckSetterHasGetterEnd}{../Typing.ml} + +\subsection{Formally} +We define the helper function +\newcommand\matchsettertype[0]{\hyperlink{def-matchsettertype}{\texttt{match\_setter\_type}}} +\hypertarget{def-matchsettertype}{} +\[ + \matchsettertype \triangleq [\STSetter \mapsto \STGetter, \STEmptySetter \mapsto \STEmptyGetter] \enspace. +\] + +\begin{mathpar} +\inferrule{ + \issetter \eqdef \funcsig.\subprogramtype \in \{ \STSetter, \STEmptySetter\}\\ + \booltrans{\issetter} \booltransarrow \False \terminateas \True\\\\ + \funcsig.\funcargs \eqname (\Ignore, \rettype) \concat \vargs\\ + \argtypes \eqdef [(\Ignore, \vt) \in \vargs: \vt]\\ + \subprogramforname(\tenv, \funcsig.\funcname, \argtypes) \typearrow (\Ignore, \Ignore, \funcsigp) \OrTypeError\\\\ + \matchsettertype(\funcsig.\funcsubprogramtype) \typearrow \watendgettertype\\ + \checktrans{\watendgettertype = \funcsigp.\funcsubprogramtype}{\SetterWithoutGetter} \typearrow \True \OrTypeError\\\\ + \argtypesp \eqdef [(\Ignore, \vt) \in \funcsigp.\funcargs : \vt]\\ + \vi\in\listrange(\argtypes): \typeequal(\argtypes[\vi], \argtypesp[\vi]) \typearrow \vb_\vi \OrTypeError\\\\ + \vi\in\listrange(\argtypes): \checktrans{\vb_\vi}{\SetterWithoutGetter} \typearrow \True \OrTypeError\\\\ + \typeequal(\rettype, \funcsigp.\funcreturntype) \typearrow \vb_\ret \OrTypeError\\\\ + \checktrans{\vb_\ret}{\SetterWithoutGetter} \typearrow \True \OrTypeError +}{ + \checksetterhasgetter(\tenv, \funcsig) \typearrow \overname{\True}{\vb} +} +\end{mathpar} + +\subsubsection{TypingRule.AddSubprogram \label{sec:TypingRule.AddSubprogram}} +\hypertarget{def-addsubprogram}{} +The function +\[ + \addsubprogram( + \overname{\staticenvs}{\tenv} \aslsep + \overname{\Strings}{\name} \aslsep + \overname{\func}{\funcdef}) + \aslto + \overname{\staticenvs}{\newtenv} +\] +updates the global environment of $\tenv$ by mapping the (unique) subprogram identifier $\name$ +to the function definition $\funcdef$ in $\tenv$, resulting in a new static environment $\newtenv$. + +\subsection{Prose} +$\newtenv$ is $\tenv$ with its $\subprograms$ component updated by binding $\name$ to $\funcdef$. + +\subsection{Formally} +\begin{mathpar} +\inferrule{ + \newtenv \eqdef (G^\tenv.\subprograms[\name\mapsto\funcdef], L^\tenv) +}{ + \addsubprogram(\tenv, \name, \funcdef) \typearrow \newtenv +} +\end{mathpar} diff --git a/asllib/doc/SymbolicEquivalenceTesting.tex b/asllib/doc/SymbolicEquivalenceTesting.tex new file mode 100644 index 000000000..befac5e3b --- /dev/null +++ b/asllib/doc/SymbolicEquivalenceTesting.tex @@ -0,0 +1,2431 @@ +\chapter{Symbolic Reduction and Equivalence Testing\label{chap:SymbolicEquivalenceTesting}} + +In this chapter, we define two forms of symbolic reasoning --- +\emph{symbolic reduction} and \emph{symbolic equivalence testing}. +Symbolic reduction simplifies expressions into \emph{equivalent} expressions +that are simpler to reason about. +In our context, equivalence means that we can substitute one expression for another without +affecting the semantics of the overall specification. +% +Symbolic equivalence is a \emph{conservative} test. +By conservative, we mean that if a test for equivalence returns $\True$ then the expressions +being compared are indeed equivalent, but if the test returns $\False$ then +there are two possibilities: +\begin{itemize} + \item the expressions are not equivalent; + \item the expressions are equivalent, but the reasoning power of our rules + is not enough to prove it, and so we conservatively answer negatively. +\end{itemize} +In proof-theoretic terms, we can say that our equivalence tests are \emph{sound} but \emph{incomplete}. + +Notice that for a conservative test, it is always correct to return $\False$. + +We first define symbolic expressions and operations over symbolic expressions in \secref{symbolicexpressions} +and then define the rules for symbolic reduction and equivalence testing in \secref{SymbolicReductionAndEquivalenceTestingRules}. + +\section{Symbolic Expressions\label{sec:symbolicexpressions}} +Our symbolic reduction and equivalence testing rules use \emph{symbolic expressions}, defined below: +\hypertarget{def-sum}{} +\[ + \begin{array}{rcl} + \polynomial &\triangleq& \unitarymonomial \partialto \Q \setminus \{0\}\\ + \unitarymonomial &\triangleq& \Identifiers \partialto \Npos\\ + \end{array} +\] + +We now explain each component of a symbolic expression and how it can be interpreted as a mathematical formula +via the interpretation function $\alpha$. +We also define operations over symbolic expressions. + +\hypertarget{def-unitarymonomial}{} +\begin{definition}[Unitary Monomial] +A \emph{Unitary Monomial} is a partial function from identifiers to positive integers\footnote{A unitary monomial has a unit factor, +for example $x^3$, whereas a non-unitary monomial has a non-unit factor, for example, $2 x^3$.}. + +A non-empty unitary monomial, $\vm\in\unitarymonomial$ where $\vm \neq \emptyfunc$, can be interpreted as follows: +\[ + \alpha(\vm) \triangleq \prod_{\vx \in \dom(\vm)} \vx^{\vm(\vx)} \enspace. +\] + +An empty unitary monomial is interpreted as the constant $1$: +\[ + \alpha(\emptyfunc) \triangleq 1 \enspace. +\] +\end{definition} +For example, +\[ + \alpha(\ \{\vx\mapsto 3, \vy\mapsto 1, \vz\mapsto2\}\ ) = x^3 \cdot y \cdot z^2 \enspace. +\] + +\hypertarget{def-mulmonomials}{} +The function +\[ + \mulmonomials(\overname{\unitarymonomial}{\vmone} \aslsep \overname{\unitarymonomial}{\vmtwo}) \rightarrow + \overname{\unitarymonomial}{\vm} +\] +multiplies two unitary monomials and returns a unitary monomial +\begin{mathpar} + \inferrule{ + { + \vf \eqdef \lambda \vx\in\identifier.\ + \left\{ + \begin{array}{ll} + \vfone(\vx) & \text{if } \vx \in \dom(\vfone) \setminus \dom(\vftwo)\\ + \vftwo(\vx) & \text{if } \vx \in \dom(\vftwo) \setminus \dom(\vfone)\\ + \vfone(\vx)+\vftwo(\vx) & \text{else } \vx \in \dom(\vfone) \cap \dom(\vftwo)\\ + \end{array} + \right. + } + } + { + \mulmonomials(\overname{\vfone}{\vmone}, \overname{\vftwo}{\vmtwo}) \typearrow \overname{\vf}{\vm} + } +\end{mathpar} +For example, +\[ + \begin{array}{ll} + \mulmonomials( & \{\vx\mapsto 3, \vy\mapsto 1, \vz\mapsto2\}, \{\vx\mapsto 1, \vw\mapsto 2\}\ ) =\\ + & \{\vx\mapsto 4, \vy\mapsto 1, \vz\mapsto2, \vw\mapsto2\} + \end{array} +\] + +\hypertarget{def-polynomial}{} +\begin{definition}[Polynomial] + \emph{Polynomials} are partial functions from monomials to rationals other than zero. + Intuitively, each unitary monomial is mapped to its factor in the polynomial. + A polynomial $\vp$ can be interpreted as follows: + % +\[ + \alpha(\vp) \triangleq \sum_{\vm \in \dom(\vp)} \vp(\vm)\cdot\alpha(\vm) +\] +\end{definition} +For example, +\[ + \left(\left\{ + \begin{array}{lcl} + \{\vx\mapsto 3, \vy\mapsto 1, \vz\mapsto2\} &\mapsto& -1,\\ + \{\vx\mapsto 2, \vy\mapsto 1\} &\mapsto& \frac{3}{4} + \end{array} \right\}\right) = + -1\cdot x^3 \cdot y \cdot z^2 + \frac{3}{4} \cdot \vx^2\cdot \vy \enspace. +\] + +\hypertarget{def-addpolynomials}{} +The function +\[ + \addpolynomials : \polynomial \times \polynomial \rightarrow \polynomial +\] +adds two polynomials: +\begin{mathpar} +\inferrule{ + { + \vf \eqdef \lambda \vm\in\unitarymonomial.\ + \left\{ + \begin{array}{ll} + \vfone(\vm) & \text{if } \vm \in \dom(\vfone) \setminus \dom(\vftwo)\\ + \vftwo(\vm) & \text{if } \vm \in \dom(\vftwo) \setminus \dom(\vfone)\\ + \bot & \text{if } \vm \in \dom(\vfone) \cap \dom(\vftwo) \text{ and } \vfone(\vm)+\vftwo(\vm) = 0\\ + \vfone(\vm)+\vftwo(\vm) & \text{else } \vm \in \dom(\vfone) \cap \dom(\vftwo) \text{ and } \vfone(\vm)+\vftwo(\vm) \neq 0\\ + \end{array} + \right. + } +}{ + \addpolynomials(\overname{\vfone}{\vpone}, \overname{\vftwo}{\vptwo}) \typearrow \overname{\vf}{\vp} +} +\end{mathpar} + +The overloaded function +\[ + \addpolynomials : \polynomial^* \rightarrow \polynomial +\] +adds a list of polynomials: +\begin{mathpar} +\inferrule[empty]{}{ \addpolynomials(\emptylist) \typearrow \emptyfunc } +\and +\inferrule[one]{}{ \addpolynomials([ \vp ]) \typearrow \vp } +\and +\inferrule[two\_or\_more]{ + \addpolynomials(\vp_{2..k}) \typearrow \vpp\\ + \addpolynomials(\vp_1, \vpp) \typearrow \vp +}{ + \addpolynomials(\vp_{1..k}) \typearrow \vp +} +\end{mathpar} + +The function +\[ + \mulpolynomials : \overname{\polynomial}{\vpone} \times \overname{\polynomial}{\vptwo} \rightarrow \overname{\polynomial}{\vp} +\] +multiplies two polynomials. +\begin{mathpar} +\inferrule{ + { + \vps \eqdef \left\{ + \begin{array}{l} + \{\mulmonomials(\vmone, \vmtwo) \mapsto \vfone(\vmone)\times\vftwo(\vmtwo)\} \;|\; \\ + \vmone\in\dom(\vfone)\ \land\ \vmtwo\in\dom(\vgtwo) + \end{array} + \right\} + }\\ + \orderedps \eqdef [i=1..k: \vp_i ] \text{ such that }\{\vp_i \;|\; i=1..k\} = \vps\\ + \addpolynomials(i=1..k: \orderedps) \typearrow \vp\\ +}{ + \mulpolynomials(\overname{\vfone}{\vpone}, \overname{\vftwo}{\vptwo}) \typearrow \vp +} +\end{mathpar} + +\section{Typing Rules\label{sec:SymbolicReductionAndEquivalenceTestingRules}} +We employ the following rules: +\begin{itemize} + \item TypingRule.Normalize (see \secref{TypingRule.Normalize}) + \item TypingRule.ReduceConstants (see \secref{TypingRule.ReduceConstants}) + \item TypingRule.ReduceConstraint (see \secref{TypingRule.ReduceConstraint}) + \item TypingRule.ReduceConstraints (see \secref{TypingRule.ReduceConstraints}) + \item TypingRule.ToIR (see \secref{TypingRule.ToIR}) + \item TypingRule.ExprEqualNorm (see \secref{TypingRule.ExprEqualNorm}) + \item TypingRule.ExprEqual (see \secref{TypingRule.ExprEqual}) + \item TypingRule.ExprEqualCase (see \secref{TypingRule.ExprEqualCase}) + \item TypingRule.TypeEqual (see \secref{TypingRule.TypeEqual}) + \item TypingRule.BitwidthEqual (see \secref{TypingRule.BitwidthEqual}) + \item TypingRule.BitFieldsEqual (see \secref{TypingRule.BitFieldsEqual}) + \item TypingRule.BitFieldEqual (see \secref{TypingRule.BitFieldEqual}) + \item TypingRule.ConstraintsEqual (see \secref{TypingRule.ConstraintsEqual}) + \item TypingRule.ConstraintEqual (see \secref{TypingRule.ConstraintEqual}) + \item TypingRule.SlicesEqual (see \secref{TypingRule.SlicesEqual}) + \item TypingRule.SliceEqual (see \secref{TypingRule.SliceEqual}) + \item TypingRule.ArrayLengthEqual (see \secref{TypingRule.ArrayLengthEqual}) + \item TypingRule.LiteralEqual (see \secref{TypingRule.LiteralEqual}) +\end{itemize} + +\subsection{TypingRule.Normalize \label{sec:TypingRule.Normalize}} +\hypertarget{def-normalize}{} +The function +\[ +\normalize(\overname{\staticenvs}{\tenv} \aslsep \overname{\expr}{\ve}) \aslto \overname{\expr}{\newe} \cup \overname{\TTypeError}{\TypeErrorConfig} +\] +\hypertarget{def-symbolicallysimplifies}{symbolically simplifies} an expression $\ve$ in the static environment $\tenv$, +yielding an expression $\newe$. +\ProseOtherwiseTypeError + +\subsubsection{Prose} +One of the following applies: +\begin{itemize} + \item All of the following apply (\textsc{normalizable}) + \begin{itemize} + \item applying $\toir$ to $\ve$ in $\tenv$ to obtain a symbolic expression yields a symbolic expression $\vpone$\ProseOrTypeError; + \item applying $\reduceir$ to $\vpone$ to symbolically simplify $\vpone$ yields $\vptwo$; + \item applying $\polynomialtoexpr$ to $\vptwo$ to transform it into an expression yields $\newe$. + \end{itemize} + + \item All of the following apply (\textsc{not\_normalizable}) + \begin{itemize} + \item applying $\toir$ to $\ve$ in $\tenv$ to obtain a symbolic expression yields $\CannotBeTransformed$, + indicating it cannot be transformed to a corresponding symbolic expression; + \item define $\newe$ as $\ve$. + \end{itemize} +\end{itemize} +\subsubsection{Formally} +\begin{mathpar} +\inferrule[normalizable]{ + \toir(\tenv, \ve) \typearrow \vpone \OrTypeError\\\\ + \vpone \neq \CannotBeTransformed\\ + \reduceir(\vpone) \typearrow \vptwo\\ + \polynomialtoexpr(\vptwo) \typearrow \newe +}{ + \normalize(\tenv, \ve) \typearrow \newe +} +\and +\inferrule[not\_normalizable]{ + \toir(\tenv, \ve) \typearrow \CannotBeTransformed +}{ + \normalize(\tenv, \ve) \typearrow \overname{\ve}{\newe} +} +\end{mathpar} + +\CodeSubsection{\NormalizeBegin}{\NormalizeEnd}{../StaticModel.ml} + +\subsection{TypingRule.ReduceConstants \label{sec:TypingRule.ReduceConstants}} +\hypertarget{def-reduceconstants}{} +The function +\[ +\reduceconstants(\overname{\staticenvs}{\tenv} \aslsep \overname{\expr}{\ve}) +\aslto +\overname{\literal}{\vl} \cup \overname{\TTypeError}{\TypeErrorConfig} +\] +\symbolicallysimplifies\ an expression $\ve$ into the literal $\vl$. +\ProseOtherwiseTypeError + +\subsubsection{Prose} +One of the following applies: +\begin{itemize} + \item All of the following apply (\textsc{eval\_literal}): + \begin{itemize} + \item applying $\staticeval$ to $\ve$ in $\tenv$ yields the literal $\vl$\ProseOrTypeError. + \end{itemize} + + \item All of the following apply (\textsc{eval\_failure}): + \begin{itemize} + \item applying $\staticeval$ to $\ve$ in $\tenv$ yields $\CannotBeTransformed$; + \item the result is a type error indicating that $\ve$ cannot be reduced to a constant in $\tenv$. + \end{itemize} +\end{itemize} + +\CodeSubsection{\ReduceConstantsBegin}{\ReduceConstantsEnd}{../Typing.ml} + +\subsubsection{Formally} +\begin{mathpar} +\inferrule[eval\_literal]{ + \staticeval(\tenv, \ve) \typearrow \vl \OrTypeError\\\\ + \vl \neq \CannotBeTransformed +}{ + \reduceconstants(\tenv, \ve) \typearrow \vl +} +\and +\inferrule[eval\_failure]{ + \staticeval(\tenv, \ve) \typearrow \CannotBeTransformed +}{ + \reduceconstants(\tenv, \ve) \typearrow \TypeErrorVal{CannotBeReducedToAConstant} +} +\end{mathpar} + +\subsection{TypingRule.ReduceConstraint \label{sec:TypingRule.ReduceConstraint}} +\hypertarget{def-reduceconstraint}{} +The function +\[ +\reduceconstraint( + \overname{\staticenvs}{\tenv} \aslsep + \overname{\intconstraint}{\vc} +) \aslto +\overname{\intconstraint}{\newc} +\] +\symbolicallysimplifies\ an integer constraint $\vc$, yielding the integer constraint $\newc$ + +\subsubsection{Prose} +One of the following applies: +\begin{itemize} + \item All of the following apply (\textsc{exact}): + \begin{itemize} + \item $\vc$ is an exact integer constraint for $\ve$, that is, $\ConstraintExact(\ve)$; + \item applying $\normalize$ to $\ve$ in $\tenv$ yields $\vep$; + \item define $\newc$ as the exact integer constraint for $\vep$, that is, $\ConstraintExact(\ve)$. + \end{itemize} + + \item All of the following apply (\textsc{range}): + \begin{itemize} + \item $\vc$ is an range integer constraint for $\veone$ and $\vetwo$, that is, $\ConstraintRange(\veone, \vetwo)$; + \item applying $\normalize$ to $\veone$ in $\tenv$ yields $\veonep$; + \item applying $\normalize$ to $\vetwo$ in $\tenv$ yields $\vetwop$; + \item define $\newc$ as the exact integer constraint for $\vep$, that is, \\ $\ConstraintRange(\veonep, \vetwop)$. + \end{itemize} +\end{itemize} + +\CodeSubsection{\ReduceConstraintBegin}{\ReduceConstraintEnd}{../Typing.ml} + +\subsubsection{Formally} +\begin{mathpar} +\inferrule[exact]{ + \normalize(\tenv, \ve) \typearrow \vep +}{ + \reduceconstraint(\tenv, \overname{\ConstraintExact(\ve)}{\vc}) \typearrow \overname{\ConstraintExact(\vep)}{\newc} +} +\end{mathpar} + +\begin{mathpar} +\inferrule[range]{ + \normalize(\tenv, \veone) \typearrow \veonep\\ + \normalize(\tenv, \vetwo) \typearrow \vetwop\\ +}{ + \reduceconstraint(\tenv, \overname{\ConstraintRange(\veone, \vetwo)}{\vc}) \typearrow \overname{\ConstraintRange(\veonep, \vetwop)}{\newc} +} +\end{mathpar} + +\subsection{TypingRule.ReduceConstraints \label{sec:TypingRule.ReduceConstraints}} +\hypertarget{def-reduceconstraints}{} +The function +\[ +\reduceconstraints( + \overname{\staticenvs}{\tenv} \aslsep + \overname{\intconstraints}{\vc} +) \aslto +\overname{\intconstraints}{\newc} +\] +\symbolicallysimplifies\ an integer constraints AST node $\vc$, yielding the integer constraints AST node $\newc$ + +\subsubsection{Prose} +One of the following applies: +\begin{itemize} + \item All of the following apply (\textsc{unconstrained\_parameterized}): + \begin{itemize} + \item the AST label of $\vc$ is either $\unconstrained$ or $\parameterized$; + \item define $\newc$ as $\vc$. + \end{itemize} + + \item All of the following apply (\textsc{well\_constrained}): + \begin{itemize} + \item $\vc$ is a list of constraints, that is, $\wellconstrained(\cs)$; + \item applying $\reduceconstraint$ to every constraint $\cs[\vi]$ in $\tenv$ for every $\vi$ in $\listrange(\cs)$ + yields $\vc_\vi$; + \item define $\newcs$ as the list containing $\vc_\vi$ for every $\vi$ in $\listrange(\cs)$; + \item $\newc$ is $\wellconstrained(\newcs)$. + \end{itemize} +\end{itemize} + +\CodeSubsection{\ReduceConstraintsBegin}{\ReduceConstraintsEnd}{../Typing.ml} + +\subsubsection{Formally} +\begin{mathpar} +\inferrule[unconstrained\_parameterized]{ + \astlabel(\vc) \in \{\unconstrained, \parameterized\} +}{ + \reduceconstraints(\tenv, \vc) \typearrow \overname{\vc}{\newc} +} +\end{mathpar} + +\begin{mathpar} +\inferrule[well\_constrained]{ + \vi\in\listrange(\cs): \reduceconstraint(\tenv, \cs[\vi]) \typearrow \vc_\vi\\ + \newcs \eqdef [\vi\in\listrange(\cs): \vc_\vi] +}{ + \reduceconstraints(\tenv, \overname{\wellconstrained(\cs)}{\vc}) \typearrow \overname{\wellconstrained(\newcs)}{\newc} +} +\end{mathpar} + +\subsection{TypingRule.ToIR \label{sec:TypingRule.ToIR}} +\hypertarget{def-toir}{} +The function +\[ + \toir(\overname{\staticenvs}{\tenv} \aslsep \overname{\expr}{\ve}) \aslto + \overname{\polynomial}{\vp}\ \cup\ \{\CannotBeTransformed\}\ \cup\ \overname{\TTypeError}{\TypeErrorConfig} +\] +transforms a subset of ASL expressions into symbolic expressions. If an ASL expression cannot be represented +by a symbolic expression (because, for example, it contains operations that are not available in symbolic expressions), +the special value $\CannotBeTransformed$ is returned. + +\subsubsection{Prose} +Intuitively, $\toir$ conducts a case analysis to determine whether the ASL expression corresponds to a polynomial. + +\newcommand\ProseOrTypeErrorOrBot[0]{\ProseTerminateAs{\CannotBeTransformed,\TypeErrorConfig}} + +One of the following applies: +\begin{itemize} + \item All of the following apply (\textsc{literal\_int}): + \begin{itemize} + \item $\ve$ is an integer literal expression for $\vi$, that is, $\ELiteral(\lint(\vi))$; + \item $\vp$ is the symbolic expression for $\vi$. + \end{itemize} + + \item All of the following apply (\textsc{literal\_other}): + \begin{itemize} + \item $\ve$ is a variable expression other than an integer literal; + \item $\vp$ is $\bot$. + \end{itemize} + + \item All of the following apply (\textsc{evar\_int\_constant}): + \begin{itemize} + \item $\ve$ is a variable expression with identifier $\vs$, that is, $\EVar(\vs)$; + \item looking up the constant associated with $\vs$ in $\tenv$ via $\lookupconstant$ yields the literal expression for $\vv$, that is, $\ELiteral(\vv)$; + \item checking whether $\vv$ is an integer literal yields $\True$\ProseOrTypeError; + \item $\vv$ is an integer literal for $\vi$; + \item $\vp$ is the symbolic expression for $\vi$, that is, $\{ \emptyfunc\mapsto \vi \}$. + \end{itemize} + + \item All of the following apply (\textsc{evar\_immutable\_expr}): + \begin{itemize} + \item $\ve$ is a variable expression with identifier $\vs$, that is, $\EVar(\vs)$; + \item looking up the constant associated with $\vs$ in $\tenv$ via $\lookupconstant$ yields $\bot$; + \item looking up $\vs$ in $\tenv$ for an associated immutable expression via $\lookupimmutableexpr$ yields the expression $\vep$; + \item applying $\toir$ to $\vep$ in $\tenv$ yields $\vp$. + \end{itemize} + + \item All of the following apply (\textsc{evar\_exact\_constraint}): + \begin{itemize} + \item $\ve$ is a variable expression with identifier $\vs$, that is, $\EVar(\vs)$; + \item looking up the constant associated with $\vs$ in $\tenv$ via $\lookupconstant$ yields $\bot$; + \item looking up $\vs$ in $\tenv$ for an associated immutable expression via \\ + $\lookupimmutableexpr$ yields $\bot$; + \item determining the type of $\vs$ yields $\vt$\ProseOrTypeError; + \item the \underlyingtype\ of $\vt$ is $\ttyone$\ProseOrTypeError; + \item checking whether $\ttyone$ is an integer type yields $\True$\ProseOrTypeError; + \item $\ttyone$ is a well-constrained integer with the exact constraint $\ve$, that is, \\ $\TInt(\wellconstrained([\ConstraintExact(\ve)]))$; + \item converting $\ve$ to a symbolic expression yields $\vp$ (which may possibly be $\bot$). + \end{itemize} + + \item All of the following apply (\textsc{int\_var}): + \begin{itemize} + \item $\ve$ is a variable expression with identifier $\vs$, that is, $\EVar(\vs)$; + \item looking up the constant associated with $\vs$ in $\tenv$ yields $\bot$; + \item determining the type of $\vs$ yields $\vt$\ProseOrTypeError; + \item the \underlyingtype\ of $\vt$ is $\ttyone$\ProseOrTypeError; + \item checking whether $\ttyone$ is an integer type yields $\True$\ProseOrTypeError; + \item $\ttyone$ is not a well-constrained integer with a single exact constraint; + \item $\vp$ is the symbolic expression for the variable $\vs$, that is, $\{ \{\vs\mapsto 1\}\mapsto 1 \}$. + \end{itemize} + + \item All of the following apply (\textsc{ebinop\_plus}): + \begin{itemize} + \item $\ve$ is a binary addition expression with operands $\veone$ and $\vetwo$, that is, \\ $\EBinop(\PLUS, \veone, \vetwo)$; + \item converting $\veone$ to a symbolic expression in $\tenv$ yields $\irone$\ProseOrTypeErrorOrBot; + \item converting $\vetwo$ to a symbolic expression in $\tenv$ yields $\irtwo$\ProseOrTypeErrorOrBot; + \item $\vp$ is the symbolic expression adding up $\irone$ and $\irtwo$. + \end{itemize} + + \item All of the following apply (\textsc{ebinop\_minus}): + \begin{itemize} + \item $\ve$ is a binary subtraction expression with operands $\veone$ and $\vetwo$, that is, \\ $\EBinop(\MINUS, \veone, \vetwo)$; + \item $\vep$ is the addition expression with operands $\veone$ and the negation of $\vetwo$, that is, \\ $\EBinop(\PLUS, \veone, \EUnop(\MINUS, \vetwo))$; + \item converting $\vep$ into a symbolic expression in $\tenv$ yields $\vp$\ProseOrTypeErrorOrBot. + \end{itemize} + + \item All of the following apply (\textsc{ebinop\_mul}): + \begin{itemize} + \item $\ve$ is a binary multiplication expression with operands $\veone$ and $\vetwo$, that is, \\ $\EBinop(\MUL, \veone, \vetwo)$; + \item converting $\veone$ to a symbolic expression in $\tenv$ yields $\irone$\ProseOrTypeErrorOrBot; + \item converting $\vetwo$ to a symbolic expression in $\tenv$ yields $\irtwo$\ProseOrTypeErrorOrBot; + \item $\vp$ is the symbolic expression multiplying $\irone$ and $\irtwo$. + \end{itemize} + + \item All of the following apply (\textsc{ebinop\_div\_non\_int\_denominator}): + \begin{itemize} + \item $\ve$ is a binary division expression with operands $\veone$ and $\vetwo$, that is, \\ $\EBinop(\DIV, \veone, \vetwo)$; + \item $\vetwo$ is not an integer literal expression; + \item $\vp$ is $\bot$. + \end{itemize} + + \item All of the following apply (\textsc{ebinop\_div\_int\_denominator}): + \begin{itemize} + \item $\ve$ is a binary division expression with operands $\veone$ and $\vetwo$, that is, \\ $\EBinop(\DIV, \veone, \vetwo)$; + \item $\vetwo$ is an integer literal expression for $\vitwo$; + \item converting $\veone$ to a symbolic expression in $\tenv$ yields $\irone$\ProseOrTypeErrorOrBot; + \item $\vftwo$ is $\frac{1}{\vitwo}$ (testing against $\vitwo = 0$ is done dynamically); + \item $\vp$ is the polynomial $\irone$ with each monomial multiplied by $\vftwo$. + \end{itemize} + + \item All of the following apply (\textsc{ebinop\_shl\_non\_lint\_exponent}): + \begin{itemize} + \item $\ve$ is a binary shift-left expression with operands $\veone$ and $\vetwo$, that is, \\ $\EBinop(\SHL, \veone, \vetwo)$; + \item $\vetwo$ is not an integer literal expression; + \item $\vp$ is $\bot$. + \end{itemize} + + \item All of the following apply (\textsc{ebinop\_shl\_non\_neg\_shift}): + \begin{itemize} + \item $\ve$ is a binary shift-left expression with operands $\veone$ and $\vetwo$, that is, \\ $\EBinop(\SHL, \veone, \vetwo)$; + \item $\vetwo$ is an integer literal expression for $\vitwo$; + \item $\vitwo$ is negative; + \item $\vp$ is $\bot$. + \end{itemize} + + \item All of the following apply (\textsc{ebinop\_shl\_okay}): + \begin{itemize} + \item $\ve$ is a binary shift-left expression with operands $\veone$ and $\vetwo$, that is, \\ $\EBinop(\SHL, \veone, \vetwo)$; + \item $\vetwo$ is an integer literal expression for $\vitwo$; + \item converting $\veone$ to a symbolic expression in $\tenv$ yields $\irone$\ProseOrTypeErrorOrBot; + \item $\vitwo$ is non-negative; + \item $\vftwo$ is $2^{\vitwo}$; + \item $\vp$ is the polynomial $\irone$ with each monomial multiplied by $\vftwo$. + \end{itemize} + + \item All of the following apply (\textsc{ebinop\_other\_non\_literals}): + \begin{itemize} + \item $\ve$ is a binary expression with an operator $\op$ that is other than $\PLUS$, $\MINUS$, $\MUL$, or $\SHL$, + applied to the operand expressions $\veone$ and $\vetwo$; + \item at least one of $\veone$ and $\vetwo$ is not a literal expression; + \item $\vp$ is $\bot$. + \end{itemize} + + \item All of the following apply (\textsc{ebinop\_other\_literals\_non\_int\_result}): + \begin{itemize} + \item $\ve$ is a binary expression with an operator $\op$ that is other than $\PLUS$, $\MINUS$, $\MUL$, $\DIV$, or $\SHL$, + applied to the operand expressions $\veone$ and $\vetwo$; + \item $\veone$ is the literal expression for literal $\vlone$; + \item $\vetwo$ is the literal expression for literal $\vltwo$; + \item statically applying $\op$ to $\vlone$ and $\vltwo$ yields the literal $\vl$, which is not an integer literal; + \item $\vp$ is $\bot$. + \end{itemize} + + \item All of the following apply (\textsc{ebinop\_other\_literals\_int\_result}): + \begin{itemize} + \item $\ve$ is a binary expression with an operator $\op$ that is other than $\PLUS$, $\MINUS$, $\MUL$, or $\SHL$, + applied to the operand expressions $\veone$ and $\vetwo$; + \item $\veone$ is the literal expression for literal $\vlone$; + \item $\vetwo$ is the literal expression for literal $\vltwo$; + \item statically applying $\op$ to $\vlone$ and $\vltwo$ yields the integer literal for $k$; + \item $\vp$ is the symbolic expression for the integer $k$, that is, $\{ \emptyfunc\mapsto k \}$. + \end{itemize} + + \item All of the following apply (\textsc{eunop\_neg}): + \begin{itemize} + \item $\ve$ is a unary expression with the negation operator $\NEG$ and operand $\veone$; + \item converting the binary expression with operator $\MUL$ and left-hand-side operand for the integer literal $-1$ and + right-hand-side operand $\veone$ in $\tenv$ yields $\vp$\ProseOrTypeErrorOrBot. + \end{itemize} + + \item All of the following apply (\textsc{eunop\_other}): + \begin{itemize} + \item $\ve$ is a unary expression with an operator other than $\NEG$; + \item $\vp$ is $\CannotBeTransformed$. + \end{itemize} + + \item All of the following apply (\textsc{other}): + \begin{itemize} + \item $\ve$ is an expression with a label other than $\ELiteral$, $\EVar$, $\EBinop$, and $\EUnop$; + \item $\vp$ is $\CannotBeTransformed$. + \end{itemize} +\end{itemize} + +\subsubsection{Formally} +\begin{mathpar} +\inferrule[literal\_int]{} +{ + \toir(\tenv, \overname{\ELiteral(\lint(\vi))}{\ve}) \typearrow \overname{\{ \emptyfunc\mapsto \vi \}}{\vp} +} +\end{mathpar} + +\begin{mathpar} +\inferrule[literal\_other]{ + \astlabel(\vv) \neq \lint +}{ + \toir(\tenv, \overname{\ELiteral(\vv)}{\ve}) \typearrow \CannotBeTransformed +} +\end{mathpar} + +\begin{mathpar} +\inferrule[evar\_int\_constant]{ + \lookupconstant(\tenv, \vs) \typearrow \ELiteral(\vv)\\ + \checktrans{\astlabel(\vv) = \lint}{ExpectedIntegerLiteral} \typearrow \True \OrTypeError\\\\ + \vv \eqname \lint(\vi) +}{ + \toir(\tenv, \overname{\EVar(\vs)}{\ve}) \typearrow \overname{\{ \emptyfunc\mapsto \vi \}}{\vp} +} +\end{mathpar} + +\begin{mathpar} +\inferrule[evar\_immutable\_expr]{ + \lookupconstant(\tenv, \vs) \typearrow \CannotBeTransformed\\ + \lookupimmutableexpr(\tenv, \vs) \typearrow \vep\\ + \toir(\vep) \typearrow \vp +}{ + \toir(\tenv, \overname{\EVar(\vs)}{\ve}) \typearrow \vp +} +\end{mathpar} + +\begin{mathpar} +\inferrule[evar\_exact\_constraint]{ + \lookupconstant(\tenv, \vs) \typearrow \CannotBeTransformed\\ + \lookupimmutableexpr(\tenv, \vs) \typearrow \bot\\ + \typeof(\vs) \typearrow \vt \OrTypeError\\\\ + \makeanonymous(\vt) \typearrow \ttyone \OrTypeError\\\\ + \checktrans{\astlabel(\ttyone) = \TInt}{ExpectedIntegerType} \typearrow \True \OrTypeError\\\\ + \ttyone = \TInt(\wellconstrained([\ConstraintExact(\ve)]))\\ + \toir(\ve) \typearrow \vp +}{ + \toir(\tenv, \overname{\EVar(\vs)}{\ve}) \typearrow \vp +} +\end{mathpar} + +\begin{mathpar} +\inferrule[int\_var]{ + \lookupconstant(\tenv, \vs) \typearrow \CannotBeTransformed\\ + \lookupimmutableexpr(\tenv, \vs) \typearrow \bot\\ + \typeof(\vs) \typearrow \vt\\ + \makeanonymous(\vt) \typearrow \ttyone\\ + \checktrans{\astlabel(\ttyone) = \TInt}{ExpectedIntegerType} \typearrow \True\\ + \ttyone \neq \TInt(\wellconstrained([\ConstraintExact(\Ignore)])) +}{ + \toir(\tenv, \overname{\EVar(\vs)}{\ve}) \typearrow \overname{\{ \{\vs\mapsto 1\}\mapsto 1 \}}{\vp} +} +\end{mathpar} + +\begin{mathpar} +\inferrule[ebinop\_plus]{ + \toir(\tenv, \veone) \typearrow \irone \OrTypeError, \CannotBeTransformed\\\\ + \toir(\tenv, \vetwo) \typearrow \irtwo \OrTypeError, \CannotBeTransformed\\\\ + \vp \eqdef \addpolynomials(\irone, \irtwo) +}{ + \toir(\tenv, \overname{\EBinop(\PLUS, \veone, \vetwo)}{\ve}) \typearrow \vp +} +\end{mathpar} + +\begin{mathpar} +\inferrule[ebinop\_minus]{ + \vep \eqdef \EBinop(\PLUS, \veone, \EUnop(\MINUS, \vetwo))\\ + \toir(\tenv, \vep) \typearrow \vp \OrTypeError, \CannotBeTransformed\\\\ +}{ + \toir(\tenv, \overname{\EBinop(\MINUS, \veone, \vetwo)}{\ve}) \typearrow \vp +} +\end{mathpar} + +\begin{mathpar} +\inferrule[ebinop\_mul]{ + \toir(\tenv, \veone) \typearrow \irone \OrTypeError, \CannotBeTransformed\\\\ + \toir(\tenv, \vetwo) \typearrow \irtwo \OrTypeError, \CannotBeTransformed\\\\ + \vp \eqdef \mulpolynomials(\irone, \irtwo) +}{ + \toir(\tenv, \overname{\EBinop(\MUL, \veone, \vetwo)}{\ve}) \typearrow \vp +} +\end{mathpar} + +\begin{mathpar} +\inferrule[ebinop\_div\_non\_int\_denominator]{ + \vetwo \neq \ELiteral(\lint(\Ignore)) +}{ + \toir(\tenv, \overname{\EBinop(\DIV, \veone, \vetwo)}{\ve}) \typearrow \CannotBeTransformed +} +\and +\inferrule[ebinop\_div\_int\_denominator]{ + \toir(\tenv, \veone) \typearrow \irone \OrTypeError, \CannotBeTransformed\\\\ + \vftwo \eqdef \frac{1}{\vitwo}\\ + \irone \eqname [i=1..k: \vm_\vi \mapsto \vc_\vi]\\ + \vp \eqdef [i=1..k: \vm_\vi \mapsto \vc_\vi \times \vftwo]\\ +}{ + \toir(\tenv, \overname{\EBinop(\DIV, \veone, \overname{\ELiteral(\lint(\vitwo))}{\vetwo})}{\ve}) \typearrow \vp +} +\end{mathpar} + +\begin{mathpar} +\inferrule[ebinop\_shl\_non\_lint\_exponent]{ + \vetwo \neq \ELiteral(\lint(\Ignore)) +}{ + \toir(\tenv, \overname{\EBinop(\SHL, \Ignore, \vetwo)}{\ve}) \typearrow \CannotBeTransformed +} +\end{mathpar} + +\begin{mathpar} +\inferrule[ebinop\_shl\_neg\_shift]{ + \vitwo < 0 +}{ + \toir(\tenv, \overname{\EBinop(\SHL, \veone, \ELiteral(\lint(\vitwo)))}{\ve}) \typearrow \CannotBeTransformed +} +\and + \inferrule[ebinop\_shl\_okay]{ + \toir(\tenv, \veone) \typearrow \irone \OrTypeError, \CannotBeTransformed\\\\ + \vitwo \geq 0\\ + \vftwo \eqdef 2^{\vitwo}\\ + \irone \eqname [i=1..k: \vm_\vi \mapsto \vc_\vi]\\ + \vp \eqdef [i=1..k: \vm_\vi \mapsto \vc_\vi \times \vftwo]\\ +}{ + \toir(\tenv, \overname{\EBinop(\SHL, \veone, \ELiteral(\lint(\vitwo)))}{\ve}) \typearrow \vp +} +\end{mathpar} + +\begin{mathpar} +\inferrule[ebinop\_other\_non\_literals]{ + \op \not\in \{\PLUS, \MINUS, \MUL, \DIV, \SHL\}\\ + (\veone \neq \ELiteral(\Ignore) \lor \vetwo \neq \ELiteral(\Ignore)) +}{ + \toir(\tenv, \overname{\EBinop(\op, \veone, \vetwo)}{\ve}) \typearrow \CannotBeTransformed +} +\and +\inferrule[ebinop\_other\_literals\_non\_int\_result]{ + \op \not\in \{\PLUS, \MINUS, \MUL, \SHL\}\\ + \binopliterals(\op, \vlone, \vltwo) \typearrow \vl\\ + \vl \neq \lint(\Ignore) +}{ + \toir(\tenv, \overname{\EBinop(\op, \ELiteral(\vlone), \ELiteral(\vltwo))}{\ve}) \typearrow \CannotBeTransformed +} +\and +\inferrule[ebinop\_other\_literals\_int\_result]{ + \op \not\in \{\PLUS, \MINUS, \MUL, \SHL\}\\ + \binopliterals(\op, \vlone, \vltwo) \typearrow \lint(k)\\ + \vp \eqdef \{ \emptyfunc\mapsto k \} +}{ + \toir(\tenv, \overname{\EBinop(\op, \ELiteral(\vlone), \ELiteral(\vltwo))}{\ve}) \typearrow \vp +} +\end{mathpar} + +\begin{mathpar} +\inferrule[eunop\_neg]{ + \toir(\tenv, \EBinop(\MUL, \ELiteral(\lint(-1)),\veone )) \typearrow \vp \OrTypeError, \CannotBeTransformed\\\\ +}{ + \toir(\tenv, \overname{\EUnop(\NEG, \veone)}{\ve}) \typearrow \vp +} +\and +\inferrule[eunop\_other]{ + \op \neq \NEG +}{ + \toir(\tenv, \overname{\EUnop(\op, \Ignore)}{\ve}) \typearrow \CannotBeTransformed +} +\end{mathpar} + +\begin{mathpar} +\inferrule[other]{ + \astlabel(\ve) \not\in \{\ELiteral, \EVar, \EBinop, \EUnop\} +}{ + \toir(\tenv, \ve) \typearrow \CannotBeTransformed +} +\end{mathpar} + +\subsection{TypingRule.ExprEqualNorm \label{sec:TypingRule.ExprEqualNorm}} +\hypertarget{def-exprequalnorm}{} +The function +\[ + \exprequalnorm(\overname{\staticenvs}{\tenv} \aslsep \overname{\expr}{\veone} \aslsep \overname{\expr}{\vetwo}) + \aslto \overname{\{\True, \False\}}{\vb} \cup \overname{\TTypeError}{\TypeErrorConfig} +\] +conservatively tests whether the expression $\veone$ is equivalent to the expression $\vetwo$ in environment $\tenv$ +by attempting to transform both expressions to their symbolic expression form +and, if successful, comparing the resulting normal forms for equality. +The result is given in $\vb$ or a type error, if one is detected. + +\subsubsection{Prose} +One of the following applies: +\begin{itemize} + \item All of the following apply (\textsc{all\_supported}): + \begin{itemize} + \item transforming $\veone$ into a symbolic expression in $\tenv$ yields $\irone$\ProseOrTypeError; + \item transforming $\vetwo$ into a symbolic expression in $\tenv$ yields $\irtwo$\ProseOrTypeError; + \item $\vb$ is the result of equating $\irone$ and $\irtwo$. + \end{itemize} + + \item All of the following apply (\textsc{unsupported1}): + \begin{itemize} + \item transforming $\veone$ into a symbolic expression in $\tenv$ yields $\CannotBeTransformed$; + \item $\vb$ is $\False$; + \end{itemize} + + \item All of the following apply (\textsc{unsupported2}): + \begin{itemize} + \item transforming $\veone$ into a symbolic expression in $\tenv$ yields $\irone$; + \item transforming $\vetwo$ into a symbolic expression in $\tenv$ yields $\CannotBeTransformed$; + \item $\vb$ is $\False$; + \end{itemize} +\end{itemize} + +\subsubsection{Formally} +\begin{mathpar} +\inferrule[all\_supported]{ + \toir(\veone) \typearrow \irone \OrTypeError\\\\ + \toir(\vetwo) \typearrow \irtwo \OrTypeError +}{ + \exprequalnorm(\tenv, \veone, \vetwo) \typearrow \overname{\irone = \irtwo}{\vb} +} +\and +\inferrule[unsupported1]{ + \toir(\veone) \typearrow \CannotBeTransformed +}{ + \exprequalnorm(\tenv, \veone, \vetwo) \typearrow \overname{\False}{\vb} +} +\and +\inferrule[unsupported2]{ + \toir(\veone) \typearrow \irone\\ + \toir(\vetwo) \typearrow \CannotBeTransformed +}{ + \exprequalnorm(\tenv, \veone, \vetwo) \typearrow \overname{\False}{\vb} +} +\end{mathpar} + +\subsection{TypingRule.ExprEqual \label{sec:TypingRule.ExprEqual}} +\hypertarget{def-exprequal}{} +The function +\[ + \exprequal(\overname{\staticenvs}{\tenv} \aslsep \overname{\expr}{\veone} \aslsep \overname{\expr}{\vetwo}) \aslto + \overname{\{\True, \False\}}{\vb} \cup \overname{\TTypeError}{\TypeErrorConfig} +\] +conservatively checks whether the expression $\veone$ is equivalent to the expression $\vetwo$ in environment $\tenv$. +The result is given in $\vb$ or a type error, if one is detected. + +\subsubsection{Prose} +One of the following applies: +\begin{itemize} + \item All of the following apply (\textsc{norm\_true}): + \begin{itemize} + \item comparing $\veone$ to $\vetwo$ in $\tenv$ via $\exprequalnorm$ yields $\True$\ProseOrTypeError; + \item $\vb$ is $\True$. + \end{itemize} + + \item All of the following apply (\textsc{norm\_false}): + \begin{itemize} + \item comparing $\veone$ to $\vetwo$ in $\tenv$ via $\exprequalnorm$ yields $\False$; + \item comparing $\veone$ to $\vetwo$ by case analysis via $\exprequalcase$ yields $\vb$\ProseOrTypeError. + \end{itemize} +\end{itemize} + +\subsubsection{Formally} +\begin{mathpar} +\inferrule[norm\_true]{ + \exprequalnorm(\tenv, \veone, \vetwo) \typearrow \True \OrTypeError +}{ + \exprequal(\tenv, \veone, \vetwo) \typearrow \True +} +\and +\inferrule[norm\_false]{ + \exprequalnorm(\tenv, \veone, \vetwo) \typearrow \False\\ + \exprequalcase(\tenv, \veone, \vetwo) \typearrow \vb \OrTypeError +}{ + \exprequal(\tenv, \veone, \vetwo) \typearrow \vb +} +\end{mathpar} + +\subsection{TypingRule.ExprEqualCase \label{sec:TypingRule.ExprEqualCase}} +\hypertarget{def-exprequalcase}{} +The function +\[ + \exprequalcase(\overname{\staticenvs}{\tenv} \aslsep \overname{\expr}{\veone} \aslsep \overname{\expr}{\vetwo}) + \aslto \overname{\{\True, \False\}}{\vb} \cup \overname{\TTypeError}{\TypeErrorConfig} +\] +specializes the equivalence test for expressions $\veone$ and $\vetwo$ in $\tenv$ +for the different types of expressions. +The result is given in $\vb$ or a type error, if one is detected. + +\subsubsection{Prose} +One of the following applies: +\begin{itemize} + \item All of the following apply (\textsc{different\_labels}): + \begin{itemize} + \item the AST labels of $\veone$ and $\vetwo$ are different; + \item $\vb$ is $\False$. + \end{itemize} + + \item All of the following apply (\textsc{e\_binop}): + \begin{itemize} + \item $\veone$ is a binary expression with operator $\opone$ and operands $\veoneone$ and $\veonetwo$, + that is, $\EBinop(\opone, \veoneone, \veonetwo)$; + \item $\vetwo$ is a binary expression with operator $\optwo$ and operands $\vetwoone$ and $\vetwotwo$, + that is, $\EBinop(\optwo, \vetwoone, \vetwotwo)$; + \item testing the equivalence of $\veoneone$ and $\vetwoone$ in $\tenv$ yields $\vbone$\ProseOrTypeError; + \item testing the equivalence of $\veonetwo$ and $\vetwotwo$ in $\tenv$ yields $\vbtwo$\ProseOrTypeError; + \item $\vb$ is $\True$ if and only if $\opone$ is equal to $\optwo$ and both $\vbone$ and $\vbtwo$ are $\True$. + \end{itemize} + + \item All of the following apply (\textsc{e\_call}): + \begin{itemize} + \item $\veone$ is a call expression with subprogram name $\nameone$ and list of arguments $\vargsone$, + that is, $\ECall(\nameone, \vargsone, \Ignore)$; + \item $\vetwo$ is a call expression with subprogram name $\nametwo$ and list of arguments $\vargstwo$, + that is, $\ECall(\nametwo, \vargstwo, \Ignore)$; + \item checking whether $\nameone$ is equal to $\nametwo$ either yields $\True$ or $\False$, which short-circuits the entire rule; + \item checking whether the lists of arguments $\vargsone$ and $\vargstwo$ have the same length yields + $\True$ or $\False$, which short-circuits the entire rule; + \item for each index $i$ in the list of indices for $\vargsone$, testing whether $\vargsone[i]$ is equivalent to $\vargstwo[i]$ + in $\tenv$ yields $\vb_i$\ProseOrTypeError; + \item $\vb$ is $\True$ if and only if $\vb_i$ is $\True$ for each index $i$ in the list of indices for $\vargsone$. + \end{itemize} + + \item All of the following apply (\textsc{e\_concat}): + \begin{itemize} + \item $\veone$ is a concatenation expression with $\vlone$, that is, $\EConcat(\vlone)$; + \item $\vetwo$ is a concatenation expression with $\vltwo$, that is, $\EConcat(\vltwo)$; + \item checking whether the lists of expressions $\vlone$ and $\vltwo$ have the same length yields + $\True$ or $\False$, which short-circuits the entire rule; + \item for each index $i$ in the list of indices for $\vlone$, testing whether $\vlone[i]$ is equivalent to $\vltwo[i]$ + in $\tenv$ yields $\vb_i$\ProseOrTypeError; + \item $\vb$ is $\True$ if and only if $\vb_i$ is $\True$ for each index $i$ in the list of indices for $\vlone$. + \end{itemize} + + \item All of the following apply (\textsc{e\_cond}): + \begin{itemize} + \item $\veone$ is a conditional expression with expressions $\veoneone$, $\veonetwo$, and $\veonethree$, + that is, $\ECond(\veoneone, \veonetwo, \veonethree)$; + \item $\vetwo$ is a conditional expression with expressions $\vetwoone$, $\vetwotwo$, and $\vetwothree$, + that is, $\ECond(\vetwoone, \vetwotwo, \vetwothree)$; + \item testing whether $\veoneone$ is equivalent to $\vetwoone$ yields $\vbone$\ProseOrTypeError; + \item testing whether $\veonetwo$ is equivalent to $\vetwotwo$ yields $\vbtwo$\ProseOrTypeError; + \item testing whether $\veonethree$ is equivalent to $\vetwothree$ yields $\vbthree$\ProseOrTypeError; + \item $\vb$ is $\True$ if and only if all of $\vbone$, $\vbtwo$, and $\vbthree$ are $\True$. + \end{itemize} + + \item All of the following apply (\textsc{e\_slice}): + \begin{itemize} + \item $\veone$ is a slicing expression with expression $\veoneone$ and list of slices $\slicesone$, + that is, $\ESlice(\veoneone, \slicesone)$; + \item $\veone$ is a slicing expression with expression $\vetwoone$ and list of slices $\slicestwo$, + that is, $\ESlice(\vetwoone, \slicestwo)$; + \item testing whether $\veoneone$ is equivalent to $\vetwoone$ yields $\vbone$\ProseOrTypeError; + \item testing whether the lists of slices $\slicesone$ and $\slicestwo$ are equivalent in $\tenv$ yields $\vbtwo$\ProseOrTypeError; + \item $\vb$ is $\True$ if and only both $\vbone$ and $\vbtwo$ are $\True$. + \end{itemize} + + \item All of the following apply (\textsc{e\_getarray}): + \begin{itemize} + \item $\veone$ is an \arrayaccess\ expression with array expression $\veoneone$ and position expression $\veonetwo$, + that is, $\EGetArray(\veoneone, \veonetwo)$; + \item $\vetwo$ is an \arrayaccess\ expression with array expression $\vetwoone$ and position expression $\vetwotwo$, + that is, $\EGetArray(\vetwoone, \vetwotwo)$; + \item testing whether $\veoneone$ is equivalent to $\vetwoone$ yields $\vbone$\ProseOrTypeError; + \item testing whether $\veonetwo$ is equivalent to $\vetwotwo$ yields $\vbtwo$\ProseOrTypeError; + \item $\vb$ is $\True$ if and only both $\vbone$ and $\vbtwo$ are $\True$. + \end{itemize} + + \item All of the following apply (\textsc{e\_getfield}): + \begin{itemize} + \item $\veone$ is a field access expression with subexpression $\veoneone$ and field name $\vfieldone$, + that is, $\EGetField(\veoneone, \vfieldone)$; + \item $\vetwo$ is a field access expression with subexpression $\vetwoone$ and field name $\vfieldtwo$, + that is, $\EGetField(\vetwoone, \vfieldtwo)$; + \item $\vbone$ is $\True$ if and only if $\vfieldone$ is equal to $\vfieldtwo$; + \item testing whether $\veoneone$ is equivalent to $\vetwoone$ yields $\vbtwo$\ProseOrTypeError; + \item $\vb$ is $\True$ if and only both $\vbone$ and $\vbtwo$ are $\True$. + \end{itemize} + + \item All of the following apply (\textsc{e\_getfields}): + \begin{itemize} + \item $\veone$ is a fields access expression with subexpression $\veoneone$ and list of field names $\vfieldsone$, + that is, $\EGetFields(\veoneone, \vfieldsone)$; + \item $\vetwo$ is a fields access expression with subexpression $\vetwoone$ and list of field names $\vfieldstwo$, + that is, $\EGetFields(\vetwoone, \vfieldstwo)$; + \item $\vbone$ is $\True$ if and only if $\vfieldsone$ is equal to $\vfieldstwo$; + \item testing whether $\veoneone$ is equivalent to $\vetwoone$ yields $\vbtwo$\ProseOrTypeError; + \item $\vb$ is $\True$ if and only both $\vbone$ and $\vbtwo$ are $\True$. + \end{itemize} + + \item All of the following apply (\textsc{e\_getitem}): + \begin{itemize} + \item $\veone$ is a tuple access expression with subexpression $\veoneone$ and position $\vione$, + that is, $\EGetItem(\veoneone, \vione)$; + \item $\vetwo$ is a tuple access expression with subexpression $\vetwoone$ and position $\vitwo$, + that is, $\EGetItem(\vetwoone, \vitwo)$; + \item $\vbone$ is $\True$ if and only if $\vione$ is equal to $\vitwo$; + \item testing whether $\veoneone$ is equivalent to $\vetwoone$ yields $\vbtwo$\ProseOrTypeError; + \item $\vb$ is $\True$ if and only both $\vbone$ and $\vbtwo$ are $\True$. + \end{itemize} + + \item All of the following apply (\textsc{e\_literal}): + \begin{itemize} + \item $\veone$ is the literal expression with literal $\vvone$; + \item $\vetwo$ is the literal expression with literal $\vvtwo$; + \item $\vb$ is $\True$ if and only if $\vvone$ is equivalent to $\vvtwo$ in $\tenv$. + \end{itemize} + + \item All of the following apply (\textsc{e\_pattern}): + \begin{itemize} + \item both $\veone$ and $\vetwo$ are pattern expressions; + \item $\vb$ is $\False$. + \end{itemize} + + \item All of the following apply (\textsc{e\_record}): + \begin{itemize} + \item both $\veone$ and $\vetwo$ are record expressions; + \item $\vb$ is $\False$. + \end{itemize} + + \item All of the following apply (\textsc{e\_tuple}): + \begin{itemize} + \item $\veone$ is a tuple expression with subexpression list $\vlone$, + that is, $\ETuple(\vlone)$; + \item $\vetwo$ is a tuple expression with subexpression list $\vltwo$, + that is, $\ETuple(\vltwo)$; + \item checking whether the lengths of $\vlone$ and $\vltwo$ are equal yields either $\True$ or $\False$, which short-circuits + the entire rule; + \item for each index $i$ in the list of indices for $\vlone$, testing whether $\vlone[i]$ is equivalent to $\vltwo[i]$ + in $\tenv$ yields $\vb_i$\ProseOrTypeError; + \item $\vb$ is $\True$ if and only if $\vb_i$ is $\True$ for each index $i$ in the list of indices for $\vlone$. + \end{itemize} + + \item All of the following apply (\textsc{e\_unop}): + \begin{itemize} + \item $\veone$ is a unary operator expression with operator $\opone$ and operand expressions $\veoneone$, + that is, $\EUnop(\opone, \veoneone)$; + \item $\vetwo$ is a unary operator expression with operator $\optwo$ and operand expressions $\vetwoone$, + that is, $\EUnop(\optwo, \vetwoone)$; + \item testing whether $\veoneone$ is equivalent to $\vetwoone$ in $\tenv$ yields $\vbone$; + \item $\vb$ is $\True$ if and only if $\opone$ is equal to $\optwo$ and $\vbone$ is $\True$. + \end{itemize} + + \item All of the following apply (\textsc{e\_unknown}): + \begin{itemize} + \item both $\veone$ and $\vetwo$ are $\UNKNOWN$ expressions; + \item $\vb$ is $\False$. + \end{itemize} + + \item All of the following apply (\textsc{e\_atc}): + \begin{itemize} + \item $\veone$ is a type assertion with subexpression with operator $\veoneone$ and type $\vtone$, + that is, $\EATC(\veoneone, \vtone)$; + \item $\vetwo$ is a type assertion with subexpression with operator $\vetwoone$ and type $\vttwo$, + that is, $\EATC(\vetwoone, \vttwo)$; + \item testing whether $\veoneone$ is equivalent to $\vetwoone$ in $\tenv$ yields $\vbone$; + \item testing whether $\vtone$ is equivalent to $\vttwo$ in $\tenv$ yields $\vbtwo$; + \item $\vb$ is $\True$ if and only if both $\vbone$ and $\vbtwo$ are $\True$. + \end{itemize} + + \item All of the following apply (\textsc{e\_var}): + \begin{itemize} + \item $\veone$ is a variable expression with identifier $\nameone$, that is, $\EVar(\nameone)$; + \item $\vetwo$ is a variable expression with identifier $\nametwo$, that is, $\EVar(\nametwo)$; + \item $\vb$ is $\True$ if and only if both $\nameone$ is equal to $\nametwo$. + \end{itemize} +\end{itemize} + +\subsubsection{Formally} +\begin{mathpar} +\inferrule[different\_labels]{ + \astlabel(\veone) \neq \astlabel(\vetwo) +}{ + \exprequalcase(\tenv, \veone, \vetwo) \typearrow \False +} +\end{mathpar} + +\begin{mathpar} +\inferrule[e\_binop]{ + \veone \eqname \EBinop(\opone, \veoneone, \veonetwo)\\ + \vetwo \eqname \EBinop(\optwo, \vetwoone, \vetwotwo)\\ + \exprequal(\veoneone, \vetwoone) \typearrow \vbone \OrTypeError\\\\ + \exprequal(\veonetwo, \vetwotwo) \typearrow \vbtwo \OrTypeError\\\\ + \vb \eqdef (\opone = \optwo) \land \vbone \land \vbtwo +}{ + \exprequalcase(\tenv, \veone, \vetwo) \typearrow \vb +} +\end{mathpar} + +(Recall that a conjunction over an empty set equals $\True$.) +\begin{mathpar} +\inferrule[e\_call]{ + \veone \eqname \ECall(\nameone, \vargsone, \Ignore)\\ + \vetwo \eqname \ECall(\nametwo, \vargstwo, \Ignore)\\\\ + \booltrans{\nameone = \nametwo} \booltransarrow \True \terminateas \False\\\\ + \equallength(\vargsone, \vargstwo) \typearrow \True \terminateas \False\\\\ + i \in \listrange(\vargsone): \exprequal(\tenv, \vargsone[i], \vargstwo[i]) \typearrow \vb_i \OrTypeError\\\\ + \vb \eqdef \bigwedge_{i \in \listrange(\vargsone)} \vb_i +}{ + \exprequalcase(\tenv, \veone, \vetwo) \typearrow \vb +} +\end{mathpar} + +\begin{mathpar} + \inferrule[e\_concat]{ + \veone \eqname \EConcat(\vlone)\\ + \vetwo \eqname \EConcat(\vltwo)\\\\ + \equallength(\vlone, \vltwo) \typearrow \True \terminateas \False\\\\ + i \in \listrange(\vlone): \exprequal(\tenv, \vlone[i], \vltwo[i]) \typearrow \vb_i \OrTypeError\\\\ + \vb \eqdef \bigwedge_{i \in \listrange(\vlone)} \vb_i +}{ + \exprequalcase(\tenv, \veone, \vetwo) \typearrow \vb +} +\end{mathpar} + +\begin{mathpar} +\inferrule[e\_cond]{ + \veone \eqname \ECond(\veoneone, \veonetwo, \veonethree)\\ + \vetwo \eqname \ECond(\vetwoone, \vetwotwo, \vetwothree)\\\\ + \exprequal(\tenv, \veoneone, \vetwoone) \typearrow \vbone \OrTypeError\\\\ + \exprequal(\tenv, \veonetwo, \vetwotwo) \typearrow \vbtwo \OrTypeError\\\\ + \exprequal(\tenv, \veonethree, \vetwothree) \typearrow \vbthree \OrTypeError\\\\ + \vb \eqdef \vbone \land \vbtwo \land \vbthree +}{ + \exprequalcase(\tenv, \veone, \vetwo) \typearrow \True +} +\end{mathpar} + +\begin{mathpar} + \inferrule[e\_slice]{ + \veone \eqname \ESlice(\veoneone, \slicesone)\\ + \vetwo \eqname \ESlice(\vetwoone, \slicestwo)\\\\ + \exprequal(\tenv, \veoneone, \vetwoone) \typearrow \vbone \OrTypeError\\\\ + \slicesequal(\tenv, \slicesone, \slicestwo) \typearrow \vbtwo \OrTypeError\\\\ + \vb \eqdef \vbone \land \vbtwo +}{ + \exprequalcase(\tenv, \veone, \vetwo) \typearrow \vb +} +\end{mathpar} + +\begin{mathpar} + \inferrule[e\_getarray]{ + \veone \eqname \EGetArray(\veoneone, \veonetwo)\\ + \vetwo \eqname \EGetArray(\vetwoone, \vetwotwo)\\\\ + \exprequal(\tenv, \veoneone, \vetwoone) \typearrow \vbone \OrTypeError\\\\ + \exprequal(\tenv, \veonetwo, \vetwotwo) \typearrow \vbtwo \OrTypeError\\\\ + \vb \eqdef \vbone \land \vbtwo +}{ + \exprequalcase(\tenv, \veone, \vetwo) \typearrow \vb +} +\end{mathpar} + +\begin{mathpar} + \inferrule[e\_getfield]{ + \veone \eqname \EGetField(\veoneone, \vfieldone)\\ + \vetwo \eqname \EGetField(\vetwoone, \vfieldtwo)\\\\ + \vbone \eqdef \vfieldone = \vfieldtwo\\ + \exprequal(\tenv, \veoneone, \vetwoone) \typearrow \vbtwo \OrTypeError\\\\ + \vb \eqdef \vbone \land \vbtwo +}{ + \exprequalcase(\tenv, \veone, \vetwo) \typearrow \vb +} +\end{mathpar} + +\begin{mathpar} + \inferrule[e\_getfields]{ + \veone \eqname \EGetFields(\veoneone, \vfieldsone)\\ + \vetwo \eqname \EGetFields(\vetwoone, \vfieldstwo)\\\\ + \vbone \eqdef \vfieldsone = \vfieldstwo\\ + \exprequal(\tenv, \veoneone, \vetwoone) \typearrow \vbtwo \OrTypeError\\\\ + \vb \eqdef \vbone \land \vbtwo +}{ + \exprequalcase(\tenv, \veone, \vetwo) \typearrow \vb +} +\end{mathpar} + +\begin{mathpar} + \inferrule[e\_getitem]{ + \veone \eqname \EGetItem(\veoneone, \vione)\\ + \vetwo \eqname \EGetItem(\vetwoone, \vitwo)\\\\ + \vbone \eqdef \vione = \vitwo\\ + \exprequal(\tenv, \veoneone, \vetwoone) \typearrow \vbtwo \OrTypeError\\\\ + \vb \eqdef \vbone \land \vbtwo +}{ + \exprequalcase(\tenv, \veone, \vetwo) \typearrow \vb +} +\end{mathpar} + +\begin{mathpar} + \inferrule[e\_literal]{ + \veone \eqname \ELiteral(\vvone)\\ + \vetwo \eqname \ELiteral(\vvtwo)\\\\ + \literalequal(\vvone, \vvtwo) \typearrow \vb +}{ + \exprequalcase(\tenv, \veone, \vetwo) \typearrow \vb +} +\end{mathpar} + +\begin{mathpar} +\inferrule[e\_pattern]{ + \astlabel(\veone) = \EPattern \land \astlabel(\vetwo) = \EPattern +}{ + \exprequalcase(\tenv, \veone, \vetwo) \typearrow \False +} +\end{mathpar} + +\begin{mathpar} +\inferrule[e\_record]{ + \astlabel(\veone) = \ERecord \land \astlabel(\vetwo) = \ERecord +}{ + \exprequalcase(\tenv, \veone, \vetwo) \typearrow \False +} +\end{mathpar} + +\begin{mathpar} +\inferrule[e\_tuple]{ + \veone \eqname \ETuple(\vlone)\\ + \vetwo \eqname \ETuple(\vltwo)\\ + \equallength(\vlone, \vltwo) \typearrow \True \terminateas \False\\\\ + i \in \listrange(\vlone): \exprequal(\tenv, \vlone[i], \vltwo[i]) \typearrow \vb_i \OrTypeError\\\\ + \vb \eqdef \bigwedge_{i \in \listrange(\vlone)} \vb_i +}{ + \exprequalcase(\tenv, \veone, \vetwo) \typearrow \vb +} +\end{mathpar} + +\begin{mathpar} +\inferrule[e\_unop]{ + \veone \eqname \EUnop(\opone, \veoneone)\\ + \vetwo \eqname \EUnop(\optwo, \vetwoone)\\\\ + \exprequal(\veoneone, \vetwoone) \typearrow \vbone \OrTypeError\\\\ + \vb \eqdef (\opone = \optwo) \land \vbone +}{ + \exprequalcase(\tenv, \veone, \vetwo) \typearrow \vb +} +\end{mathpar} + +\begin{mathpar} +\inferrule[e\_unknown]{ + (\astlabel(\veone) = \EUnknown \land \astlabel(\vetwo) = \EUnknown) +}{ + \exprequalcase(\tenv, \veone, \vetwo) \typearrow \False +} +\end{mathpar} + +\begin{mathpar} +\inferrule[e\_atc]{ + \veone \eqname \EATC(\veoneone, \vtone)\\ + \vetwo \eqname \EATC(\vetwoone, \vttwo)\\ + \exprequal(\tenv, \veoneone, \vetwoone) \typearrow \vbone \OrTypeError\\\\ + \typeequal(\tenv, \vtone, \vttwo) \typearrow \vbtwo \OrTypeError\\\\ + \vb \eqdef \vbone \land \vbtwo +}{ + \exprequalcase(\tenv, \veone, \vetwo) \typearrow \vb +} +\end{mathpar} + +\begin{mathpar} +\inferrule[e\_var]{ + \veone \eqname \EVar(\nameone)\\ + \vetwo \eqname \EVar(\nametwo)\\\\ + \vb \eqdef \nameone = \nametwo +}{ + \exprequalcase(\tenv, \veone, \vetwo) \typearrow \vb +} +\end{mathpar} + +% | E_Pattern _, _ | E_Record _, _ -> assert false + +\subsection{TypingRule.TypeEqual \label{sec:TypingRule.TypeEqual}} +\hypertarget{def-typeequal}{} +The function +\[ + \typeequal(\overname{\ty}{\vtone} \aslsep \overname{\ty}{\vttwo}) \aslto + \overname{\{\True, \False\}}{\vb} \cup \overname{\TTypeError}{\TypeErrorConfig} +\] +conservatively tests whether the type $\vtone$ is equivalent to the type $\vttwo$ in environment $\tenv$ +and yields the result in $\vb$. \ProseOtherwiseTypeError + +\subsubsection{Prose} +One of the following applies: +\begin{itemize} + \item All of the following apply (\textsc{different\_labels}): + \begin{itemize} + \item the AST labels of $\vtone$ and $\vttwo$ are different; + \item $\vb$ is $\False$. + \end{itemize} + + \item All of the following apply (\textsc{tbool\_treal\_tstring}): + \begin{itemize} + \item both $\vtone$ and $\vttwo$ are both either $\TBool$, $\TReal$, or $\TString$; + \item $\vb$ is $\True$. + \end{itemize} + + \item All of the following apply (\textsc{tint\_unconstrained}): + \begin{itemize} + \item both $\vtone$ and $\vttwo$ are the unconstrained integer type $\unconstrainedinteger$; + \item $\vb$ is $\True$. + \end{itemize} + + \item All of the following apply (\textsc{tint\_parameterized}): + \begin{itemize} + \item $\vtone$ is the \parameterizedintegertype\ with identifier $\vione$, that is, \\ $\TInt(\parameterized(\vione))$; + \item $\vttwo$ is the \parameterizedintegertype\ with identifier $\vitwo$, that is, \\ $\TInt(\parameterized(\vitwo))$; + \item $\vb$ is $\True$ if and only if $\vione$ is equal to $\vitwo$. + \end{itemize} + + \item All of the following apply (\textsc{tint\_wellconstrained}): + \begin{itemize} + \item $\vtone$ is the well-constrained integer type with list of constraints $\vcone$, that is, \\ $\TInt(\wellconstrained(\vcone))$; + \item $\vttwo$ is the well-constrained integer type with list of constraints $\vctwo$, that is, \\ $\TInt(\wellconstrained(\vctwo))$; + \item testing whether $\vcone$ and $\vctwo$ are equivalent in $\tenv$ yields $\vb$\ProseOrTypeError. + \end{itemize} + + \item All of the following apply (\textsc{tbits}): + \begin{itemize} + \item $\vtone$ is the bitvector type with width expression $\vwone$ and list of bitfields $\bfone$, that is, $\TBits(\vwone, \bfone)$; + \item $\vttwo$ is the bitvector type with width expression $\vwtwo$ and list of bitfields $\bftwo$, that is, $\TBits(\vwtwo, \bftwo)$; + \item testing whether $\vwone$ and $\vwtwo$ are equivalent bitwidths in $\tenv$ yields $\vbone$\ProseOrTypeError; + \item testing whether $\bfone$ and $\bftwo$ are equivalent lists of bitfields in $\tenv$ yields $\vbtwo$\ProseOrTypeError; + \item $\vb$ is $\True$ if and only if both $\vbone$ and $\vbtwo$ are $\True$. + \end{itemize} + + \item All of the following apply (\textsc{tarray}): + \begin{itemize} + \item $\vtone$ is an array type with index $\vlone$ and element type $\vtone$, that is, $\TArray(\vlone, \vtone)$; + \item $\vttwo$ is an array type with index $\vltwo$ and element type $\vttwo$, that is, $\TArray(\vltwo, \vttwo)$; + \item testing whether $\vlone$ is equivalent to $\vltwo$ in $\tenv$ yields $\vbone$\ProseOrTypeError; + \item testing whether $\vtone$ is equivalent to $\vttwo$ in $\tenv$ yields $\vbtwo$\ProseOrTypeError; + \item $\vb$ is $\True$ if and only if both $\vbone$ and $\vbtwo$ are $\True$. + \end{itemize} + + \item All of the following apply (\textsc{tnamed}): + \begin{itemize} + \item $\vtone$ is a named type with identifier $\vsone$, that is $\TNamed(\vsone)$; + \item $\vttwo$ is a named type with identifier $\vstwo$, that is $\TNamed(\vstwo)$; + \item $\vb$ is $\True$ if and only if $\vsone$ is equal to $\vstwo$. + \end{itemize} + + \item All of the following apply (\textsc{tenum}): + \begin{itemize} + \item $\vtone$ is an enumeration type with identifier $\vlone$, that is $\TEnum(\vlone)$; + \item $\vttwo$ is an enumeration type with identifier $\vltwo$, that is $\TEnum(\vltwo)$; + \item $\vb$ is $\True$ if and only if $\vlone$ is equal to $\vltwo$. + \end{itemize} + + \item All of the following apply (\textsc{tstructured}): + \begin{itemize} + \item $L$ is either $\TRecord$ or $\TException$; + \item $\vtone$ is a \structuredtype\ with list of fields $\vfieldsone$, that is $L(\vfieldsone)$; + \item $\vttwo$ is a \structuredtype\ with list of fields $\vfieldstwo$, that is $L(\vfieldstwo)$; + \item checking whether the set of field names in $\vfieldsone$ is equal to the set of field names in $\vfieldstwo$ + yields $\True$ or $\False$, which short-circuits the entire rule; + \item for each field $\vf$ in the set of fields of $\vfieldsone$, testing whether the type associated with + $\vf$ in $\vfieldsone$ is equivalent to the type associated with + $\vf$ in $\vfieldstwo$ in $\tenv$ yields $\vb_\vf$\ProseOrTypeError; + \item $\vb$ is $\True$ if and only if $\vb_\vf$ is $\True$ for each field $\vf$ in the set of fields of $\vfieldsone$. + \end{itemize} + + \item All of the following apply (\textsc{ttuple}): + \begin{itemize} + \item $\vtone$ is a tuple type with list of types $\vtsone$, that is $\TTuple(\vtsone)$; + \item $\vttwo$ is a tuple type with list of types $\vtstwo$, that is $\TTuple(\vtstwo)$; + \item checking whether the list of types $\vtsone$ has the same length as the list of types $\vtstwo$ yields $\True$ + or $\False$, which short-circuits the entire rule; + \item for each index $i$ in the list $\vtsone$, testing whether $\vtsone[i]$ is equivalent to $\vtstwo[i]$ in $\tenv$ + yields $\vb_i$\ProseOrTypeError; + \item $\vb$ is $\True$ if and only if $\vb_i$ is $\True$ for each index $i$ in the list $\vtsone$. + \end{itemize} +\end{itemize} + +\subsubsection{Formally} +\begin{mathpar} +\inferrule[different\_labels]{ + \astlabel(\vtone) \neq \astlabel(\vttwo) +}{ + \typeequal(\tenv, \vtone, \vttwo) \typearrow \False +} +\end{mathpar} + +\begin{mathpar} +\inferrule[TBool\_TReal\_TString]{ + \astlabel(\vtone) = \astlabel(\vttwo)\\ + \astlabel(\vtone) \in \{\TBool, \TReal, \TString\} +}{ + \typeequal(\tenv, \vtone, \vttwo) \typearrow \True +} +\and +\end{mathpar} + +\begin{mathpar} +\inferrule[tint\_unconstrained]{} +{ + \typeequal(\tenv, \unconstrainedinteger, \unconstrainedinteger) \typearrow \True +} +\and +\inferrule[tint\_parameterized]{ + \vb \eqdef \vione = \vitwo +}{ + \typeequal(\tenv, \TInt(\parameterized(\vione)), \TInt(\parameterized(\vitwo))) \typearrow \vb +} +\and +\inferrule[tint\_wellconstrained]{ + \constraintsequal(\tenv, \vcone, \vctwo) \typearrow \vb \OrTypeError +}{ + \typeequal(\tenv, \TInt(\wellconstrained(\vcone)), \TInt(\wellconstrained(\vctwo))) \typearrow \vb +} +\end{mathpar} + +\begin{mathpar} +\inferrule[tbits]{ + \bitwidthequal(\tenv, \vwone, \vwtwo) \typearrow \vbone \OrTypeError\\\\ + \bitfieldsequal(\tenv, \bfone, \bftwo) \typearrow \vbtwo \OrTypeError\\\\ + \vb \eqdef \vbone \land \vbtwo +}{ + \typeequal(\tenv, \TBits(\vwone, \bfone), \TBits(\vwtwo, \bftwo)) \typearrow \vb +} +\end{mathpar} + +\begin{mathpar} +\inferrule[tarray]{ + \exprequal(\tenv, \vlone, \vltwo) \typearrow \vbone \OrTypeError\\\\ + \typeequal(\tenv, \vtone, \vttwo) \typearrow \vbtwo \OrTypeError\\\\ + \vb \eqdef \vbone \land \vbtwo +}{ + \typeequal(\tenv, \TArray(\vlone, \vtone), \TArray(\vltwo, \vttwo)) \typearrow \vb +} +\end{mathpar} + +\begin{mathpar} +\inferrule[tnamed]{ + \vb \eqdef \vsone = \vstwo +}{ + \typeequal(\tenv, \TNamed(\vsone), \TNamed(\vstwo)) \typearrow \vb +} +\end{mathpar} + +\begin{mathpar} +\inferrule[tenum]{ + \vb \eqdef \vlone = \vltwo +}{ + \typeequal(\tenv, \TEnum(\vlone), \TEnum(\vltwo)) \typearrow \vb +} +\end{mathpar} + +\begin{mathpar} +\inferrule[tstructured]{ + L \in \{\TRecord, \TException\}\\ + \booltrans{\fieldnames(\vfieldsone) = \fieldnames(\vfieldstwo)} \booltransarrow \True \terminateas \False\\\\ + { + \begin{array}{l} + \vf \in \fieldnames(\vfieldsone): \\ \typeequal(\tenv, \fieldtype(\vfieldsone, \vf), \fieldtype(\vfieldstwo, \vf)) \typearrow \vb_\vf \OrTypeError + \end{array} + }\\\\ + \vb \eqdef \bigwedge_{\vf \in \fieldnames(\vfieldsone)} \vb_\vf +}{ + \typeequal(\tenv, L(\vfieldsone), L(\vfieldstwo)) \typearrow \vb +} +\end{mathpar} + +\begin{mathpar} +\inferrule[ttuple]{ + \equallength(\vtsone, \vtstwo) \typearrow \True \terminateas \False\\ + i \in \listrange(\vtsone): \typeequal(\tenv, \vtsone[i], \vtstwo[i]) \typearrow \vb_i \OrTypeError\\\\ + \vb \eqdef \bigwedge_{i \in \listrange(\vtsone)} \vb_i +}{ + \typeequal(\tenv, \TTuple(\vtsone), \TTuple(\vtstwo)) \typearrow \vb +} +\end{mathpar} + +\subsection{TypingRule.BitwidthEqual \label{sec:TypingRule.BitwidthEqual}} +\hypertarget{def-bitwidthequal}{} +The function +\[ + \bitwidthequal(\overname{\staticenvs}{\tenv} \aslsep \overname{\expr}{\vwone} \aslsep \overname{\expr}{\vwtwo}) + \aslto \overname{\{\True, \False\}}{\vb} \cup \overname{\TTypeError}{\TypeErrorConfig} +\] +conservatively tests whether the bitwidth expression $\vwone$ is equivalent to the bitwidth expression $\vwtwo$ +in environment $\tenv$ and yields the result in $\vb$. \ProseOtherwiseTypeError + +\subsubsection{Prose} +Testing whether the expressions $\vwone$ and $\vwtwo$ are equivalent in $\tenv$ yields $\vb$\ProseOrTypeError. + +\subsubsection{Formally} +\begin{mathpar} +\inferrule{ + \exprequal(\tenv, \vwone, \vwtwo) \typearrow \vb \OrTypeError +}{ + \bitwidthequal(\tenv, \vwone, \vwtwo) \typearrow \vb +} +\end{mathpar} + +\subsection{TypingRule.BitFieldsEqual \label{sec:TypingRule.BitFieldsEqual}} +\hypertarget{def-bitfieldsequal}{} +The function +\[ + \bitfieldsequal(\overname{\staticenvs}{\tenv} \aslsep \overname{\bitfield^*}{\bfone} \aslsep \overname{\bitfield^*}{\bftwo}) + \aslto \overname{\{\True, \False\}}{\vb} \cup \overname{\TTypeError}{\TypeErrorConfig} +\] +conservatively tests whether the list of bitfields $\bfone$ is equivalent to the list of bitfields $\bftwo$ +in environment $\tenv$ and yields the result in $\vb$. \ProseOtherwiseTypeError + +\subsubsection{Prose} +One of the following applies: +\begin{itemize} + \item All of the following apply (\textsc{different\_lengths}): + \begin{itemize} + \item the number of bitfields in $\bfone$ is different from the number of bitfields in $\bftwo$; + \item $\vb$ is $\False$. + \end{itemize} + + \item All of the following apply (\textsc{same\_lengths}): + \begin{itemize} + \item the number of bitfields in $\bfone$ is the same as the number of bitfields in $\bftwo$; + \item testing whether the bitfield $\bfone[i]$ is equivalent to $\bftwo[i]$ in $\tenv$ for every index + of $\bfone$ yields $\vb_i$\ProseOrTypeError; + \item $\vb$ is $\True$ if and only if $\vb_i$ is $\True$ for every index of $\bfone$. + \end{itemize} +\end{itemize} + +\subsubsection{Formally} +\begin{mathpar} +\inferrule[different\_lengths]{ + \equallength(\bfone, \bftwo) \typearrow \False +}{ + \bitfieldsequal(\tenv, \bfone, \bftwo) \typearrow \False +} +\and +\inferrule[same\_lengths]{ + \equallength(\bfone, \bftwo) \typearrow \True\\ + i\in\listrange(\bfone): \bitfieldequal(\tenv, \bfone[i], \bftwo[i]) \typearrow \vb_i\\\\ + \vb \eqdef \bigwedge_{i\in\listrange(\bfone)} \vb_i +}{ + \bitfieldsequal(\tenv, \bfone, \bftwo) \typearrow \vb +} +\end{mathpar} + +\subsection{TypingRule.BitFieldEqual \label{sec:TypingRule.BitFieldEqual}} +The function +\[ + \bitfieldequal(\overname{\staticenvs}{\tenv} \aslsep \overname{\bitfield}{\bfone} \aslsep \overname{\bitfield}{\bftwo}) + \aslto \overname{\{\True, \False\}}{\vb} \cup \overname{\TTypeError}{\TypeErrorConfig} +\] +conservatively tests whether the bitfield $\bfone$ is equivalent to the bitfield $\bftwo$ in environment $\tenv$ +and yields the result in $\vb$. \ProseOtherwiseTypeError + +One of the following applies: +\begin{itemize} + \item All of the following apply (\textsc{different\_labels}): + \begin{itemize} + \item the AST labels of $\bfone$ and $\bftwo$ are different; + \item $\vb$ is $\False$. + \end{itemize} + + \item All of the following apply (\textsc{bitfield\_simple}): + \begin{itemize} + \item $\bfone$ is a simple bitfield with name $\nameone$ and list of slices $\slicesone$, that is, \\ $\BitFieldSimple(\nameone, \slicesone)$; + \item $\bftwo$ is a simple bitfield with name $\nametwo$ and list of slices $\slicestwo$, that is, \\ $\BitFieldSimple(\nametwo, \slicestwo)$; + \item checking whether $\nameone$ is equal to $\nametwo$ yields $\vbone$; + \item testing whether $\slicesone$ and $\slicestwo$ are equivalent in $\tenv$ yields $\vbtwo$\ProseOrTypeError; + \item $\vb$ is $\True$ if and only if both $\vbone$ and $\vbtwo$ are $\True$. + \end{itemize} + + \item All of the following apply (\textsc{bitfield\_nested}): + \begin{itemize} + \item $\bfone$ is a nested bitfield with name $\nameone$, list of slices $\slicesone$, and nested bitfields $\bfoneone$, that is, + $\BitFieldNested(\nameone, \slicesone, \bfoneone)$; + \item $\bftwo$ is a nested bitfield with name $\nametwo$, list of slices $\slicestwo$, and nested bitfields $\bftwoone$, that is, + $\BitFieldNested(\nametwo, \slicestwo, \bftwoone)$; + \item checking whether $\nameone$ is equal to $\nametwo$ yields $\vbone$; + \item testing whether $\slicesone$ and $\slicestwo$ are equivalent in $\tenv$ yields $\vbtwo$\ProseOrTypeError; + \item testing whether the bitfields $\bfoneone$ and $\bftwoone$ are equivalent in $\tenv$ yields $\vbtwo$\ProseOrTypeError; + \item $\vb$ is $\True$ if and only if both $\vbone$ and $\vbtwo$ are $\True$. + \end{itemize} + + \item All of the following apply (\textsc{bitfield\_typed}): + \begin{itemize} + \item $\bfone$ is a typed bitfield with name $\nameone$, list of slices $\slicesone$, and type $\vtone$, that is, + $\BitFieldType(\nameone, \slicesone, \vtone)$; + \item $\bftwo$ is a typed bitfield with name $\nametwo$, list of slices $\slicestwo$, and type $\vttwo$, that is, + $\BitFieldType(\nametwo, \slicestwo, \vttwo)$; + \item checking whether $\nameone$ is equal to $\nametwo$ yields $\True$\ProseTerminateAs{\False}; + \item testing whether $\slicesone$ and $\slicestwo$ are equivalent in $\tenv$ yields $\vbone$\ProseOrTypeError; + \item testing whether the types $\vtone$ and $\vttwo$ are equivalent in $\tenv$ yields $\vbtwo$\ProseOrTypeError; + \item $\vb$ is $\True$ if and only if both $\vbone$ and $\vbtwo$ are $\True$. + \end{itemize} +\end{itemize} + +\subsubsection{Formally} +\begin{mathpar} +\inferrule[different\_labels]{ + \astlabel(\bfone) \neq \astlabel(\bftwo) +}{ + \bitfieldequal(\tenv, \bfone, \bftwo) \typearrow \False +} +\and +\inferrule[bitfield\_simple]{ + \bfone \eqname \BitFieldSimple(\nameone, \slicesone)\\ + \bftwo \eqname \BitFieldSimple(\nametwo, \slicestwo)\\ + \booltrans{\nameone = \nametwo} \booltransarrow \vbone\\ + \slicesequal(\tenv, \slicesone, \slicestwo) \typearrow \vbtwo \OrTypeError\\\\ + \vb \eqdef \vbone \land \vbtwo +}{ + \bitfieldequal(\tenv, \bfone, \bftwo) \typearrow \vb +} +\and +\inferrule[bitfield\_nested]{ + \bfone \eqname \BitFieldNested(\nameone, \slicesone, \bfoneone)\\ + \bftwo \eqname \BitFieldNested(\nametwo, \slicestwo, \bftwoone)\\ + \booltrans{\nameone = \nametwo} \booltransarrow \True \terminateas \False\\\\ + \slicesequal(\tenv, \slicesone, \slicestwo) \typearrow \vbone \terminateas \TypeErrorConfig,\\\\ + \bitfieldsequal(\tenv, \bfoneone, \bftwoone) \typearrow \vbtwo +}{ + \bitfieldequal(\tenv, \bfone, \bftwo) \typearrow \vb +} +\and +\inferrule[bitfield\_typed]{ + \bfone \eqname \BitFieldType(\nameone, \slicesone, \vtone)\\ + \bftwo \eqname \BitFieldType(\nametwo, \slicestwo, \vttwo)\\ + \booltrans{\nameone = \nametwo} \booltransarrow \True \terminateas \False \\\\ + \slicesequal(\tenv, \slicesone, \slicestwo) \typearrow \vbone \OrTypeError\\\\ + \typeequal(\tenv, \vtone, \vttwo) \typearrow \vbtwo \OrTypeError\\\\ + \vb \eqdef \vbone \land \vbtwo +}{ + \bitfieldequal(\tenv, \bfone, \bftwo) \typearrow \vb +} +\end{mathpar} + +\subsection{TypingRule.ConstraintsEqual \label{sec:TypingRule.ConstraintsEqual}} +\hypertarget{def-constraintsequal}{} +The function +\[ + \constraintsequal(\overname{\staticenvs}{\tenv} \aslsep \overname{\intconstraint^*}{\csone} \aslsep \overname{\intconstraint^*}{\cstwo}) + \aslto \overname{\{\True, \False\}}{\vb} \cup \overname{\TTypeError}{\TypeErrorConfig} +\] +conservatively tests whether the constraint list $\csone$ is equivalent to the constraint list $\cstwo$ in environment $\tenv$ +and yields the result in $\vb$. \ProseOtherwiseTypeError + +\subsubsection{Prose} +All of the following apply: +\begin{itemize} + \item checking whether the number of constraints in $\csone$ is the same as the number of constraints in $\cstwo$ + yields $\True$\ProseTerminateAs{\False}; + \item testing whether the constraint $\csone[i]$ is equivalent to the constraint $\cstwo[i]$ in $\tenv$ + yields $\vb_i$ for each index in the index in the indices for $\csone$ ($i\in\listrange(\csone)$)\ProseOrTypeError; + \item $\vb$ is $\True$ if and only if all $\vb_i$ are $\True$ for each index in the indices for $\csone$. +\end{itemize} + +\subsubsection{Formally} +\begin{mathpar} +\inferrule{ + \equallength(\csone, \cstwo) \typearrow \True \terminateas \False\\ + i\in\listrange(\csone): \constraintequal(\tenv, \csone[i], \cstwo[i]) \typearrow \vb_i \OrTypeError\\\\ + \vb \eqdef \bigwedge_{i\in\listrange(\csone)} \vb_i +}{ + \constraintsequal(\tenv, \csone, \cstwo) \typearrow \vb +} +\end{mathpar} + +\subsection{TypingRule.ConstraintEqual \label{sec:TypingRule.ConstraintEqual}} +\hypertarget{def-constraintequal}{} +The function +\[ + \constraintequal(\overname{\staticenvs}{\tenv} \aslsep \overname{\intconstraint}{\vcone} \aslsep \overname{\intconstraint}{\vstwo}) + \aslto \overname{\{\True, \False\}}{\vb} \cup \overname{\TTypeError}{\TypeErrorConfig} +\] +conservatively tests whether the constraint $\vcone$ is equivalent to the constraint $\vctwo$ in environment $\tenv$ +and yields the result in $\vb$. \ProseOtherwiseTypeError + +\subsubsection{Prose} +One of the following applies: +\begin{itemize} + \item All of the following apply (\textsc{different\_labels}): + \begin{itemize} + \item the AST labels of $\vcone$ and $\vctwo$ are different; + \item define $\vb$ as $\False$. + \end{itemize} + + \item All of the following apply (\textsc{constraint\_exact}): + \begin{itemize} + \item $\vcone$ is an exact constraint with subexpression $\veone$, that is, $\ConstraintExact(\veone)$; + \item $\vctwo$ is an exact constraint with subexpression $\vetwo$, that is, $\ConstraintExact(\vetwo)$; + \item applying $\exprequal$ to $\veone$ and $\vetwo$ yields $\vb$\ProseOrTypeError. + \end{itemize} + + \item All of the following apply (\textsc{constraint\_range}): + \begin{itemize} + \item $\vcone$ is a range constraint with subexpressions $\veoneone$ and $\veonetwo$, that is, \\ $\ConstraintRange(\veoneone, \veonetwo)$; + \item $\vctwo$ is a range constraint with subexpressions $\vetwoone$ and $\vetwotwo$, that is, \\ $\ConstraintRange(\vetwoone, \vetwotwo)$; + \item applying $\exprequal$ to $\veoneone$ and $\vetwoone$ yields $\vbone$\ProseOrTypeError; + \item applying $\exprequal$ to $\veonetwo$ and $\vetwotwo$ yields $\vbtwo$\ProseOrTypeError; + \item define $\vb$ as $\True$ if and only if both $\vbone$ and $\vbtwo$ are $\True$. + \end{itemize} +\end{itemize} + +\subsubsection{Formally} +\begin{mathpar} +\inferrule[different\_labels]{ + \astlabel(\vcone) \neq \astlabel(\vctwo) +}{ + \constraintequal(\tenv, \vcone, \vctwo) \typearrow \False +} +\and +\inferrule[constraint\_exact]{ + \vcone \eqname \ConstraintExact(\veone)\\ + \vctwo \eqname \ConstraintExact(\vetwo)\\ + \exprequal(\tenv, \veone, \vetwo) \typearrow \vb \OrTypeError +}{ + \constraintequal(\tenv, \vcone, \vctwo) \typearrow \vb +} +\and +\inferrule[constraint\_range]{ + \bfone \eqname \ConstraintRange(\veoneone, \veonetwo)\\ + \bftwo \eqname \ConstraintRange(\vetwoone, \vetwotwo)\\ + \exprequal(\tenv, \veoneone, \vetwoone) \typearrow \vbone \OrTypeError\\\\ + \exprequal(\tenv, \veonetwo, \vetwotwo) \typearrow \vbtwo \OrTypeError\\\\ + \vb \eqdef \vbone \land \vbtwo +}{ + \constraintequal(\tenv, \bfone, \bftwo) \typearrow \vb +} +\end{mathpar} + +\subsection{TypingRule.SlicesEqual \label{sec:TypingRule.SlicesEqual}} +\hypertarget{def-slicesequal}{} +The function +\[ + \slicesequal(\overname{\staticenvs}{\tenv} \aslsep \overname{\slice^*}{\slicesone} \aslsep \overname{\slice^*}{\slicestwo}) + \aslto \overname{\{\True, \False\}}{\vb} \cup \overname{\TTypeError}{\TypeErrorConfig} +\] +conservatively tests whether the list of slices $\slicesone$ is equivalent to the list of slices $\slicestwo$ +in environment $\tenv$ and yields the result in $\vb$. \ProseOtherwiseTypeError + +\subsubsection{Formally} +One of the following applies: +\begin{itemize} + \item All of the following apply (\textsc{different\_lengths}): + \begin{itemize} + \item checking whether the number of slices in $\slicesone$ is equal to the number of slice in $\slicestwo$ yields $\False$; + \item $\vb$ is $\False$. + \end{itemize} + + \item All of the following apply (\textsc{same\_lengths}): + \begin{itemize} + \item checking whether the number of slices in $\slicesone$ is equal to the number of slice in $\slicestwo$ yields $\True$; + \item determining whether the expression $\slicesone[i]$ is equivalent to $\slicestwo[i]$ in $\tenv$ + for each index in the indices for $\slicesone$ ($i \in \listrange(\slicesone$) yields $\vb_i$\ProseOrTypeError; + \item $\vb$ is $\True$ if and only if all $\vb_i$ are $\True$ for each index in the indices for $\slicesone$. + \end{itemize} +\end{itemize} + +\subsubsection{Formally} +\begin{mathpar} +\inferrule[different\_lengths]{ + \equallength(\slicesone, \slicestwo) \typearrow \False +}{ + \slicesequal(\tenv, \slicesone, \slicestwo) \typearrow \False +} +\and +\inferrule[same\_lengths]{ + \equallength(\slicesone, \slicestwo) \typearrow \True\\ + i\in\listrange(\slicesone): \sliceequal(\tenv, \slicesone[i], \slicestwo[i]) \typearrow \vb_i \OrTypeError\\\\ + \vb \eqdef \bigwedge_{i\in\listrange(\slicesone)} \vb_i +}{ + \slicesequal(\tenv, \slicesone, \slicestwo) \typearrow \vb +} +\end{mathpar} + +\subsection{TypingRule.SliceEqual \label{sec:TypingRule.SliceEqual}} +\hypertarget{def-sliceequal}{} +The function +\[ + \sliceequal(\overname{\staticenvs}{\tenv} \aslsep \overname{\slice}{\sliceone} \aslsep \overname{\slice}{\slicetwo}) + \aslto \overname{\{\True, \False\}}{\vb} \cup \overname{\TTypeError}{\TypeErrorConfig} +\] +conservatively tests whether the slice $\sliceone$ is equivalent to the slice $\slicetwo$ +in environment $\tenv$ and yields the result in $\vb$. \ProseOtherwiseTypeError + +\subsubsection{Prose} +One of the following applies: +\begin{itemize} + \item All of the following apply (\textsc{different\_labels}): + \begin{itemize} + \item $\sliceone$ and $\slicetwo$ have different AST labels; + \item $\vb$ is $\False$. + \end{itemize} + + \item All of the following apply (\textsc{slice\_single}): + \begin{itemize} + \item $\sliceone$ is a slice for a single position, given by the expression $\veone$, that is, $\SliceSingle(\veone)$; + \item $\slicetwo$ is a slice for a single position, given by the expression $\vetwo$, that is, $\SliceSingle(\vetwo)$; + \item testing $\veone$ and $\vetwo$ for equivalence yields $\vb$\ProseOrTypeError. + \end{itemize} + + \item All of the following apply (\textsc{slice\_range}): + \begin{itemize} + \item $\sliceone$ is a slice for a range of positions, given by the expressions $\veoneone$ and $\veonetwo$, that is, $\SliceRange(\veoneone, \veonetwo)$; + \item $\slicetwo$ is a slice for a range of positions, given by the expressions $\vetwoone$ and $\vetwotwo$, that is, $\SliceRange(\vetwoone, \vetwotwo)$; + \item testing $\veoneone$ and $\vetwoone$ for equivalence yields $\vbone$\ProseOrTypeError; + \item testing $\veonetwo$ and $\vetwotwo$ for equivalence yields $\vbtwo$\ProseOrTypeError; + \item $\vb$ is $\True$ if and only if both $\vbone$ and $\vbtwo$ are $\True$. + \end{itemize} + + \item All of the following apply (\textsc{slice\_length}): + \begin{itemize} + \item $\sliceone$ is a slice for a range of positions, given by the start expression $\veoneone$ and length expression $\veonetwo$, that is, $\SliceLength(\veoneone, \veonetwo)$; + \item $\slicetwo$ is a slice for a range of positions, given by the start expression $\vetwoone$ and length expression $\vetwotwo$, that is, $\SliceLength(\vetwoone, \vetwotwo)$; + \item testing $\veoneone$ and $\vetwoone$ for equivalence yields $\vbone$\ProseOrTypeError; + \item testing $\veonetwo$ and $\vetwotwo$ for equivalence yields $\vbtwo$\ProseOrTypeError; + \item $\vb$ is $\True$ if and only if both $\vbone$ and $\vbtwo$ are $\True$. + \end{itemize} +\end{itemize} + +\subsubsection{Formally} +\begin{mathpar} +\inferrule[different\_label]{ + \astlabel(\sliceone) \neq \astlabel(\slicetwo) +}{ + \slicesequal(\tenv, \sliceone, \slicetwo) \typearrow \False +} +\and +\inferrule[slice\_single]{ + \exprequal(\tenv, \veone, \vetwo) \typearrow \vb \OrTypeError +}{ + \slicesequal(\tenv, \SliceSingle(\veone), \SliceSingle(\vetwo)) \typearrow \vb +} +\and +\inferrule[slice\_range]{ + \exprequal(\tenv, \veoneone, \vetwoone) \typearrow \vbone \OrTypeError\\\\ + \exprequal(\tenv, \vetwoone, \vetwotwo) \typearrow \vbtwo \OrTypeError\\\\ + \vb \eqdef \vbone \land \vbtwo +}{ + \slicesequal(\tenv, \SliceRange(\veoneone, \veonetwo), \SliceRange(\vetwoone, \vetwotwo)) \typearrow \vb +} +\and +\inferrule[slice\_length]{ + \exprequal(\tenv, \veoneone, \vetwoone) \typearrow \vbone \OrTypeError\\\\ + \exprequal(\tenv, \vetwoone, \vetwotwo) \typearrow \vbtwo \OrTypeError\\\\ + \vb \eqdef \vbone \land \vbtwo +}{ + \slicesequal(\tenv, \SliceLength(\veoneone, \veonetwo), \SliceLength(\vetwoone, \vetwotwo)) \typearrow \vb +} +\end{mathpar} + +\subsection{TypingRule.ArrayLengthEqual \label{sec:TypingRule.ArrayLengthEqual}} +\hypertarget{def-arraylengthequal}{} +The function +\[ + \arraylengthequal(\overname{\arrayindex}{\vlone} \aslsep \overname{\arrayindex}{\vltwo}) + \aslto \overname{\{\True, \False\}}{\vb} \cup \overname{\TTypeError}{\TypeErrorConfig} +\] +tests whether the array lengths $\vlone$ and $\vltwo$ are equivalent and yields the result +in $\vb$. \ProseOtherwiseTypeError + +\subsubsection{Prose} +One of the following applies: +\begin{itemize} + \item All of the following apply (\textsc{different\_labels}): + \begin{itemize} + \item $\vlone$ and $\vltwo$ have different AST labels; + \item $\vb$ is $\False$. + \end{itemize} + + \item All of the following apply (\textsc{expr\_expr}): + \begin{itemize} + \item $\vlone$ is an integer type length expression with subexpression $\veoneone$, that is, \\ $\ArrayLengthExpr(\veoneone)$; + \item $\vltwo$ is an integer type length expression with subexpression $\vetwoone$, that is, \\ $\ArrayLengthExpr(\vetwoone)$; + \item testing whether $\veoneone$ and $\vetwoone$ are equivalent in $\tenv$ yields $\vb$\ProseOrTypeError. + \end{itemize} + + \item All of the following apply (\textsc{enum\_enum}): + \begin{itemize} + \item $\vlone$ is an enumeration type length expression over the enumeration $\vsone$, that is, $\ArrayLengthEnum(\vsone, \Ignore)$; + \item $\vltwo$ is an enumeration type length expression over the enumeration $\vstwo$, that is, $\ArrayLengthEnum(\vstwo, \Ignore)$; + \item $\vb$ is $\True$ if and only if $\vsone$ is equal to $\vstwo$. + \end{itemize} +\end{itemize} + +\subsubsection{Formally} +\begin{mathpar} +\inferrule[different\_labels]{ + \astlabel(\vlone) \neq \astlabel(\vltwo) +}{ + \arraylengthequal(\vlone, \vltwo) \typearrow \False +} +\and + \inferrule[expr\_expr]{ + \exprequal(\veoneone, \vetwoone) \typearrow \vb \OrTypeError +}{ + \arraylengthequal(\ArrayLengthExpr(\veoneone), \ArrayLengthExpr(\vetwoone)) \typearrow \vb +} +\and +\inferrule[enum\_enum]{ + \vb \eqdef \vsone = \vstwo +}{ + \arraylengthequal(\ArrayLengthEnum(\vsone, \Ignore), \ArrayLengthEnum(\vstwo, \Ignore)) \typearrow \vb +} +\end{mathpar} + +\subsection{TypingRule.LiteralEqual \label{sec:TypingRule.LiteralEqual}} +\hypertarget{def-literalequal}{} +The function +\[ + \literalequal(\overname{\literal}{\vvone} \aslsep \overname{\literal}{\vvtwo}) \rightarrow \overname{\{\True, \False\}}{\vb} +\] +tests whether literal $\vvone$ is $\vvtwo$ by equating them. + +\subsubsection{Prose} +$\vb$ is $\True$ if and only if $\vvone$ is equal to $\vvtwo$. + +\subsubsection{Formally} +\begin{mathpar} +\inferrule{ + \vb \eqdef \vvone = \vvtwo +}{ + \literalequal(\vvone, \vvtwo) \typearrow \vb +} +\end{mathpar} + +\subsection{TypingRule.ReduceIR \label{sec:TypingRule.ReduceIR}} +\hypertarget{def-reduceir}{} +The function +\[ +\reduceir(\overname{\polynomial}{\vp}) \aslto \overname{\polynomial}{\newp} +\] +simplifies the polynomial $\vp$, yielding the simplified polynomial $\newp$. + +\subsubsection{Prose} +\subsubsection{Formally} +\subsection{TypingRule.PolynomialToExpr \label{sec:TypingRule.PolynomialToExpr}} +\hypertarget{def-polynomialtoexpr}{} +The function +\[ +\polynomialtoexpr(\overname{\polynomial}{\vp}) \typearrow \overname{\expr}{\ve} +\] +transforms a polynomial $\vp$ into the corresponding expression $\ve$. + +\subsubsection{Prose} +One of the following applies: +\begin{itemize} + \item All of the following apply (\textsc{empty}): + \begin{itemize} + \item $\vp$ is the polynomial with an empty list of monomials, that is, $\emptyfunc$; + \item define $\ve$ as the literal expression for $0$. + \end{itemize} + + \item All of the following apply (\textsc{non\_empty}): + \begin{itemize} + \item $\vp$ is the polynomial $f$; + \item sorting (see $\sort$ for details) the graph of $f$ (see $\funcgraph$ for details) + yields $\monoms$ --- a list consisting of pairs of unitary monomials and rationals. + In principle, any total order of the graph of $f$ is acceptable for sorting. + The function $\comparemonomialbindings$ provides one such way of ordering + the graph of $f$; + \item transforming $\monoms$ to an expression and sign via $\monomialstoexpr$ yields the expression $\veone$ + and sign $\vsone$; + \item define $\ve$ as $\veone$ if $\vsone$ is $1$, the integer literal expression for $0$ if $\vsone$ is $0$, + and the unary expression negating $\veone$, that is, + $\EUnop(\NEG, \veone)$, if $\vsone$ is $-1$. + \end{itemize} +\end{itemize} + +\subsubsection{Formally} +\begin{mathpar} +\inferrule[empty]{} +{ + \polynomialtoexpr(\overname{\emptyfunc}{\vp}) \typearrow \overname{\ELiteral(\lint(0))}{\ve} +} +\and +\inferrule[non\_empty]{ + \sort(\funcgraph(f), \comparemonomialbindings) = \monoms\\ + \monomialstoexpr(\monoms) \typearrow (\veone, \vsone)\\ + { + \ve \eqdef \begin{cases} + \ELiteral(\lint(0)) & \text{if }\vsone = 0\\ + \veone & \text{if }\vsone = 1\\ + \EUnop(\NEG, \veone) & \text{if }\vsone = -1 + \end{cases} + } +}{ + \polynomialtoexpr(\overname{f}{\vp}) \typearrow \ve +} +\end{mathpar} + +\subsection{TypingRule.CompareMonomialBindings \label{sec:TypingRule.CompareMonomialBindings}} +\hypertarget{def-comparemonomialbindings}{} +The function +\[ +\comparemonomialbindings( + (\overname{\monomial}{\vmone}\times\overname{\Q}{\vqone}) \aslsep + (\overname{\monomial}{\vmtwo}\times\overname{\Q}{\vqtwo}) +) \aslto \overname{\{-1,0,1\}}{\vs} +\] +compares two monomial bindings given by $(\vmone, \vqone)$ and $(\vmtwo, \vqtwo)$ +and yields in $\vs$ $-1$ to mean that the first monomial binding should be ordered before the second, +$0$ to mean that any ordering of the monomial bindings is acceptable, +and $1$ to mean that the second monomial binding should be ordered before the first. + +\subsubsection{Prose} +One of the following applies: +\begin{itemize} + \item All of the following apply (\textsc{equal\_monomials}): + \begin{itemize} + \item $\vmone$ is $f$ and $\vmtwo$ is $g$; + \item $f$ is equal to $g$; + \item $\vs$ is the sign of $\vqtwo - \vqone$. + \end{itemize} + + \item All of the following apply (\textsc{different\_monomials}): + \begin{itemize} + \item $\vmone$ is $f$ and $\vmtwo$ is $g$; + \item $f$ is different from to $g$; + \item $\ids$ is the list obtained by taking the set of identifiers in the domain of $f$ and in the domain of $g$, + and sorting them according to the lexical order for identifiers (ASCII string order); + \item $\vv$ is the first identifier in $\ids$ for which $f$ and $g$ behave differently (either one of them is defined + for $\vv$ and the other is not, or they both bind $\vv$ to a different value); + \item $s$ is determined as follows: $1$ if $\vv$ is not in the domain of $f$ and is in the domain of $g$; + $-1$ if $\vv$ is not in the domain of $f$ and is in the domain of $g$; + otherwise it is the sign of $g(\vv)-f(\vv)$. + \end{itemize} +\end{itemize} + +\subsubsection{Formally} +\hypertarget{def-compareidentifier}{} +The function $\compareidentifier$ compares two identifiers, which are lists of ASCII characters, +via the lexicographic ordering. + +\begin{mathpar} +\inferrule[equal\_monomials]{ + f = g\\ + \vs \eqdef \sign(\vqtwo - \vqone) +}{ + \comparemonomialbindings((\overname{f}{\vmone}, \vqone), (\overname{g}{\vmtwo}, \vqtwo)) \typearrow \vs +} +\and +\inferrule[different\_monomials]{ + f \neq g\\ + \ids \eqdef \sort(\dom(f) \cup \dom(g), \compareidentifier)\\ + \ids \eqname \idsone \concat \idstwo\\ + \vi\in\listrange(\idsone): f(\idsone[\vi]) = g(\idsone[\vi])\\ + \vv \eqdef \idstwo[1]\\ + \vs \eqdef { + \begin{cases} + 1 & f(\vv) = \bot \land g(\vv) \neq \bot\\ + -1 & f(\vv) \neq \bot \land g(\vv) = \bot\\ + \sign(g(\vv) - f(\vv)) & f(\vv) \neq \bot \land g(\vv) \neq \bot\\ + \end{cases} +} +}{ + \comparemonomialbindings((\overname{f}{\vmone}, \vqone), (\overname{g}{\vmtwo}, \vqtwo)) \typearrow \vs +} +\end{mathpar} + +\subsection{TypingRule.MonomialsToExpr \label{sec:TypingRule.MonomialsToExpr}} +\hypertarget{def-monomialstoexpr}{} +The function +\[ +\monomialstoexpr(\overname{(\overname{\unitarymonomial}{\vm}\times\overname{\Q}{q})^*}{\monoms}) \aslto +(\overname{\expr}{\ve},\overname{\{-1,0,1\}}{\vs}) +\] +transforms a list consisting of pairs of unitary monomials and rational factors $\monoms$ (so, general monomials), +into an expression $\ve$, which represents the absolute value of the sum of all the monomials, +and a sign value $\vs$, which indicates the sign of the resulting sum. + +\subsubsection{Prose} +One of the following applies: +\begin{itemize} + \item All of the following apply (\textsc{empty}): + \begin{itemize} + \item $\monoms$ is an empty list; + \item $\ve$ is the literal expression for the integer $0$ and $\vs$ is $0$. + \end{itemize} + + \item All of the following apply (\textsc{non\_empty}): + \begin{itemize} + \item $\monoms$ is a list with $(\vm,q)$ as its \head\ and $\monomsone$ as its \tail; + \item transforming the unitary monomial $\vm$ to an expression via \\ $\unitarymonomialstoexpr$ yields $\veonep$; + \item transforming $\veonep$ and $q$ via $\monomialtoexpr$ yields the expression $\veone$ and sign $\vsone$; + \item transforming $\monoms$ to an expression and sign via $\monomialstoexpr$ yields $(\vetwo, \vstwo)$; + \item symbolically adding $\veone, \vsone, \vetwo, \vstwo$ via $\symaddexpr$ yields $(\ve, \vs)$. + \end{itemize} +\end{itemize} + +\subsubsection{Formally} +\begin{mathpar} +\inferrule[empty]{} +{ + \monomialstoexpr(\overname{\emptylist}{\monoms}) \typearrow (\overname{\ELiteral(\lint(0))}{\ve}, \overname{0}{\vs}) +} +\and +\inferrule[non\_empty]{ + \unitarymonomialstoexpr(\vm) \typearrow \veonep\\ + \monomialtoexpr(\veonep, q) \typearrow (\veone,\vsone)\\ + \monomialstoexpr(\monoms) \typearrow (\vetwo, \vstwo)\\ + \symaddexpr(\veone, \vsone, \vetwo, \vstwo) \typearrow (\ve, \vs) +}{ + \monomialstoexpr(\overname{[(\vm,q)] \concat \monomsone}{\monoms}) \typearrow (\ve, \vs) +} +\end{mathpar} + +\subsection{TypingRule.MonomialToExpr \label{sec:TypingRule.MonomialToExpr}} +\hypertarget{def-monomialtoexpr}{} +The function +\[ +\monomialtoexpr(\overname{\expr}{\ve} \aslsep \overname{\Q}{q}) +\aslto (\overname{\expr}{\newe} \times \overname{\{-1,0,1\}}{\vs}) +\] +transforms an expression $\ve$ and rational $q$ into the expression $\newe$, +which represents the absolute value of $\ve$ multiplied by $q$, and the sign of $q$ as $\vs$. + +\subsubsection{Prose} +One of the following applies: +\begin{itemize} + \item All of the following apply (\textsc{q\_zero}): + \begin{itemize} + \item $q$ is $0$; + \item $\newe$ is the literal expression for $0$; + \item $\vs$ is $0$. + \end{itemize} + + \item All of the following apply (\textsc{q\_natural}): + \begin{itemize} + \item $q$ a strictly positive; + \item symbolically multiplying the literal expression for $q$ and $\ve$ via $\symmulexpr$ yields $\newe$; + \item $\vs$ is $1$. + \end{itemize} + + \item All of the following apply (\textsc{q\_positive\_fraction}): + \begin{itemize} + \item $q$ a strictly positive fraction, that is, not an integer; + \item the reduced representation of the fraction $q$ is $\frac{d}{n}$; + \item symbolically multiplying the literal expression for $q$ and $\ve$ via $\symmulexpr$ yields $\vetwo$; + \item $\ve$ is the binary expression with operator $\DIV$ and operands $\vetwo$ and the literal expression for $n$; + \item $\vs$ is $1$. + \end{itemize} + + \item All of the following apply (\textsc{q\_negative}): + \begin{itemize} + \item $q$ a strictly negative; + \item transforming $\ve$ with $-q$ to an expression and a sign via $\monomialtoexpr$ yields $(\newe, 1)$; + \item $\vs$ is $-1$. + \end{itemize} +\end{itemize} + +\subsubsection{Formally} +\begin{mathpar} +\inferrule[q\_zero]{ + q = 0\\ +}{ + \monomialtoexpr(\ve, q) \typearrow (\overname{\ELiteral(\lint(0))}{\newe}, \overname{0}{\vs}) +} +\and +\inferrule[q\_natural]{ + q > 0\\ + q \in \N\\ + \symmulexpr(\ELiteral(\lint(q)), \ve) \typearrow \newe +}{ + \monomialtoexpr(\ve, q) \typearrow (\newe, \overname{1}{\vs}) +} +\and +\inferrule[q\_positive\_fraction]{ + q > 0\\ + q \not\in \N\\\\ + q \eqname \frac{d}{n} \;\;\;\;\text{ is the reduced fraction for }q\\\\ + \symmulexpr(\ELiteral(\lint(d)), \ve) \typearrow \vetwo\\ + \newe \eqdef \EBinop(\DIV, \vetwo, \ELiteral(\lint(n))) +}{ + \monomialtoexpr(\ve, q) \typearrow (\newe, \overname{1}{\vs}) +} +\and +\inferrule[q\_negative]{ + q < 0\\ + \monomialtoexpr(\ve, -q) \typearrow (\newe, 1) +}{ + \monomialtoexpr(\ve, q) \typearrow (\newe, \overname{-1}{\vs}) +} +\end{mathpar} + +\subsection{TypingRule.SymAddExpr \label{sec:TypingRule.SymAddExpr}} +\hypertarget{def-symaddexpr}{} +The function +\[ +\symaddexpr( + \overname{\expr}{\veone} \aslsep + \overname{\{-1,0,1\}}{\vsone} \aslsep + \overname{\expr}{\vetwo} \aslsep + \overname{\{-1,0,1\}}{\vstwo} + ) + \typearrow (\overname{\expr}{\ve}, \overname{\{-1,0,1\}}{\vs}) +\] +symbolically sums the expressions $\veone$ and $\vetwo$ +with respective signs $\vsone$ and $\vstwo$ +yielding the expression $\ve$ and sign $\vs$. + +The effect of the function can be summarized by the following table: +\begin{center} +\begin{tabular}{|c|c|c|c|} +\hline +& \multicolumn{3}{c|}{$\vsone$}\\ +\hline +$\vstwo$ & -1 & 0 & 1\\ +\hline +-1 & $(\veone+\vetwo, \vsone)$ & (\vetwo,\vstwo) & $(\veone-\vetwo, \vsone)$ \\ +\hline + 0 & $(\veone, \vsone)$ & (\veone,\vsone) & $(\veone, \vsone)$ \\ + \hline + 1 & $(\veone-\vetwo, \vsone)$ & (\vetwo,\vstwo) & $(\veone+\vetwo, \vsone)$ \\ +\hline +\end{tabular} +\end{center} + +\subsubsection{Prose} +One of the following applies: +\begin{itemize} + \item All of the following apply (\textsc{zero}): + \begin{itemize} + \item either $\vsone$ is $0$ or $\vstwo$ is $0$; + \item the result is $(\vetwo, \vstwo)$ if $\vsone$ is $0$ and $(\veone, \vsone)$, otherwise. + \end{itemize} + + \item All of the following apply (\textsc{same\_sign}): + \begin{itemize} + \item both $\vsone$ and $\vstwo$ are not $0$; + \item $\vsone$ is equal to $\vstwo$; + \item $\ve$ is the binary expression with operator $\PLUS$ and operands $\veone$ and $\vetwo$, + that is, $\EBinop(\PLUS, \veone, \vetwo)$; + \item $\vs$ is $\vsone$; + \end{itemize} + + \item All of the following apply (\textsc{same\_sign}): + \begin{itemize} + \item both $\vsone$ and $\vstwo$ are not $0$; + \item $\vsone$ is different from $\vstwo$; + \item $\ve$ is the binary expression with operator $\MINUS$ and operands $\veone$ and $\vetwo$, + that is, $\EBinop(\MINUS, \veone, \vetwo)$; + \item $\vs$ is $\vsone$; + \end{itemize} +\end{itemize} + +\subsubsection{Formally} +\begin{mathpar} +\inferrule[zero]{ + (\vsone = 0 \lor \vstwo = 0)\\ + (\ve, \vs) \eqdef \choice{\vsone = 0}{(\vetwo, \vstwo)}{(\veone, \vsone)} +}{ + \symaddexpr(\veone, \vsone, \vetwo, \vstwo) \typearrow (\ve, \vs) +} +\and +\inferrule[same\_sign]{ + \vsone \neq 0 \land \vstwo \neq 0\\ + \vsone = \vstwo +}{ + \symaddexpr(\veone, \vetwo) \typearrow (\overname{\EBinop(\PLUS, \veone, \vetwo)}{\ve}, \overname{\vsone}{\vs}) +} +\and +\inferrule[different\_signs]{ + \vsone \neq 0 \land \vstwo \neq 0\\ + \vsone \neq \vstwo +}{ + \symaddexpr(\veone, \vetwo) \typearrow (\overname{\EBinop(\MINUS, \veone, \vetwo)}{\ve}, \overname{\vsone}{\vs}) +} +\end{mathpar} + +\subsection{TypingRule.UnitaryMonomialsToExpr \label{sec:TypingRule.UnitaryMonomialsToExpr}} +\hypertarget{def-unitarymonomialstoexpr}{} +The function +\[ +\unitarymonomialstoexpr(\overname{(\identifier\times\N)^*}{\monoms}) \aslto \overname{\expr}{\ve} +\] +transforms a list of single-variable unitary monomials $\monoms$ into an expression $\ve$. +Intuitively, $\monoms$ represented a multiplication of the single-variable unitary monomials. + +\subsubsection{Prose} +One of the following applies: +\begin{itemize} + \item All of the following apply (\textsc{empty}): + \begin{itemize} + \item $\monoms$ is the empty list; + \item $\ve$ is the literal expression for $1$. + \end{itemize} + + \item All of the following apply (\textsc{exp\_zero}): + \begin{itemize} + \item $\monoms$ is a list where the first element is $(\vv, 0)$ and its tail is $\monoms$; + \item transforming $\monomsone$ to an expression yields $\ve$. + \end{itemize} + + \item All of the following apply (\textsc{exp\_one}): + \begin{itemize} + \item $\monoms$ is a list where the first element is $(\vv, 1)$ and its tail is $\monoms$; + \item $\veone$ is the variable expression for $\vv$; + \item transforming $\monomsone$ to an expression yields $\vetwo$; + \item symbolically multiplying $\veone$ and $\vetwo$ via $\symmulexpr$ yields $\ve$. + \end{itemize} + + \item All of the following apply (\textsc{exp\_two}): + \begin{itemize} + \item $\monoms$ is a list where the first element is $(\vv, 2)$ and its tail is $\monoms$; + \item $\veone$ is the binary expression with operator $\MUL$ and operands $\EVar(\vv)$ and $\EVar(\vv)$ + (that is, $\vv$ squared); + \item transforming $\monomsone$ to an expression yields $\vetwo$; + \item symbolically multiplying $\veone$ and $\vetwo$ via $\symmulexpr$ yields $\ve$. + \end{itemize} + + \item All of the following apply (\textsc{exp\_gt\_two}): + \begin{itemize} + \item $\monoms$ is a list where the first element is $(\vv, n)$ and its tail is $\monoms$; + \item $n$ is greater than $1$; + \item $\veone$ is the binary expression with operator $\POW$ and base operand being the variable expression for $\vv$ + and the exponent operand being the variable expression for $n$; + \item transforming $\monomsone$ to an expression yields $\vetwo$; + \item symbolically multiplying $\veone$ and $\vetwo$ via $\symmulexpr$ yields $\ve$. + \end{itemize} +\end{itemize} + +\subsubsection{Formally} +\begin{mathpar} +\inferrule[empty]{} +{ + \unitarymonomialstoexpr(\overname{\emptylist}{\monoms}) \typearrow \overname{\ELiteral(\lint(1))}{\ve} +} +\end{mathpar} + +\begin{mathpar} +\inferrule[exp\_zero]{ + \unitarymonomialstoexpr(\monomsone) \typearrow \ve +}{ + \unitarymonomialstoexpr(\overname{[(\vv, 0)] \concat \monomsone}{\monoms}) \typearrow \ve +} +\end{mathpar} + +\begin{mathpar} +\inferrule[exp\_one]{ + \veone \eqdef \EVar(\vv)\\ + \unitarymonomialstoexpr(\monomsone) \typearrow \vetwo\\ + \symmulexpr(\veone, \vetwo) \typearrow \ve +}{ + \unitarymonomialstoexpr(\overname{[(\vv, 1)] \concat \monomsone}{\monoms}) \typearrow \ve +} +\end{mathpar} + +\begin{mathpar} +\inferrule[exp\_two]{ + \veone \eqdef \AbbrevEBinop{\MUL}{\EVar(\vv)}{\EVar(\vv)}\\ + \unitarymonomialstoexpr(\monomsone) \typearrow \vetwo\\ + \symmulexpr(\veone, \vetwo) \typearrow \ve +}{ + \unitarymonomialstoexpr(\overname{[(\vv, 2)] \concat \monomsone}{\monoms}) \typearrow \ve +} +\end{mathpar} + +\begin{mathpar} +\inferrule[exp\_gt\_two]{ + n \geq 2\\ + \veone \eqdef \AbbrevEBinop{\POW}{\EVar(\vv)}{\ELiteral(n)}\\ + \unitarymonomialstoexpr(\monomsone) \typearrow \vetwo\\ + \symmulexpr(\veone, \vetwo) \typearrow \ve +}{ + \unitarymonomialstoexpr(\overname{[(\vv, n)] \concat \monomsone}{\monoms}) \typearrow \ve +} +\end{mathpar} + +\subsection{TypingRule.SymMulExpr \label{sec:TypingRule.SymMulExpr}} +\hypertarget{def-symmulexpr}{} +The function +$ +\symmulexpr(\overname{\expr}{\veone} \aslsep \overname{\expr}{\vetwo}) \typearrow \overname{\expr}{\ve} +$ +produces an expression representing the multiplication of expressions $\veone$ and $\vetwo$, +simplifying away the case where one of the operands is the literal one. + +\subsubsection{Prose} +One of the following applies: +\begin{itemize} + \item All of the following apply (\textsc{one\_operand}): + \begin{itemize} + \item either $\veone$ or $\vetwo$ is the literal expression for $1$; + \item $\ve$ is $\vetwo$ if $\veone$ is the literal expression for $1$ and $\veone$, otherwise. + \end{itemize} +\end{itemize} + +\subsubsection{Formally} +\begin{mathpar} +\inferrule[one\_operand]{ + (\veone = \ELiteral(\lint(1)) \lor \vetwo = \ELiteral(\lint(1)))\\ + \ve \eqdef \choice{\veone = \ELiteral(\lint(1))}{\vetwo}{\veone} +}{ + \symmulexpr(\EBinop(\MUL, \veone, \vetwo)) \typearrow \ve +} +\and +\inferrule[no\_one\_operand]{ + (\veone \neq \ELiteral(\lint(1)) \land \vetwo \neq \ELiteral(\lint(1)))\\ + \ve \eqdef \EBinop(\MUL, \veone, \vetwo) +}{ + \symmulexpr(\EBinop(\MUL, \veone, \vetwo)) \typearrow \ve +} +\end{mathpar} + +\subsubsection{TypingRule.TypeOf} +\hypertarget{def-typeof}{} +The function +\[ + \typeof(\overname{\staticenvs}{\tenv} \aslsep \overname{\identifier}{\vs}) + \;\aslto\; \overname{\ty}{\tty}\ \cup\ \overname{\TTypeError}{\TypeErrorConfig} +\] +looks up the environment $\tenv$ for a type $\tty$ associated with an identifier +$\vs$. The result is type error if $\vs$ is not associated with any type. + +\subsubsection{Prose} +One of the following applies: +\begin{itemize} + \item All of the following apply (\textsc{local}): + \begin{itemize} + \item $\vs$ is associated with a type $\tty$ in the local environment of $\tenv$; + \end{itemize} + + \item All of the following apply (\textsc{global}): + \begin{itemize} + \item $\vs$ is not associated with a type in the local environment of $\tenv$; + \item $\vs$ is associated with a type $\tty$ in the global environment of $\tenv$; + \end{itemize} + + \item All of the following apply (\textsc{error}): + \begin{itemize} + \item $\vs$ is not associated with a type in the local environment of $\tenv$; + \item $\vs$ is not associated with a type in the global environment of $\tenv$; + \item the result is a type error indicating that $\vs$ was expected to be associated + with a type. + \end{itemize} +\end{itemize} + +\subsubsection{Formally} +\begin{mathpar} +\inferrule[local]{ + L^\tenv.\localstoragetypes(\vs) = \tty +}{ + \typeof(\tenv, \vs) \typearrow \tty +} +\and +\inferrule[global]{ + L^\tenv.\localstoragetypes(\vs) = \bot\\ + G^\tenv.\globalstoragetypes(\vs) = \tty +}{ + \typeof(\tenv, \vs) \typearrow \tty +} +\and +\inferrule[none]{ + L^\tenv.\localstoragetypes(\vs) = \bot\\ + G^\tenv.\globalstoragetypes(\vs) = \bot +}{ + \typeof(\tenv, \vs) \typearrow \TypeErrorVal{\UndefinedIdentifier} +} +\end{mathpar} diff --git a/asllib/doc/SymbolicSubsumptionTesting.tex b/asllib/doc/SymbolicSubsumptionTesting.tex new file mode 100644 index 000000000..dbbe1a00f --- /dev/null +++ b/asllib/doc/SymbolicSubsumptionTesting.tex @@ -0,0 +1,1254 @@ +\chapter{Symbolic Subsumption Testing\label{chap:SymbolicSubsumptionTesting}} +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +This chapter is concerned with implementing a \hyperlink{def-soundsubsumptiontest}{sound subsumption test} +for integer types, as defined in \secref{subsumptiontesting} and employed by +TypingRule.SubtypeSatisfaction (see \secref{TypingRule.SubtypeSatisfaction}). + +\hypertarget{def-symbolicdomain}{} +The symbolic reasoning operates by first transforming types into expressions in a \emph{symbolic domain} AST +(defined next, reusing $\intconstraint$ from the untyped AST) over which it then operates: +\hypertarget{def-symdom}{} +\hypertarget{def-finite}{} +\[ + \begin{array}{rcl} + \symdom &::=& \Finite(\powfin{\Z} \setminus \emptyset) \hypertarget{def-top}{}\\ + &| & \Top \hypertarget{def-fromsymtax}{}\\ + &| & \FromSyntax(\syntax) \hypertarget{def-syntax}{}\\ + \syntax &::=& \intconstraint^* + \end{array} +\] + +\begin{itemize} + \item We refer to an element of the form $\Finite(S)$ as a \emph{symbolic finite set integer domain}, + which represents the set of integers $S$; + \item We refer to an element of the form $\FromSyntax(\vcs)$ as a \emph{symbolic constrained integer domain}, + which represents the set of integers given by the list of constraints $\vcs$; and + \item We refer to an element of the form $\Top$ as a \emph{symbolic unconstrained integer domain}, + which represents the set of all integers. +\end{itemize} + +The main rule is of this chapter is TypingRule.SymSubsumes (see \secref{TypingRule.SymSubsumes}), which defines the function +$\symsubsumes$. + +Other helper rules are as follows: +\begin{itemize} + \item TypingRule.SymDomOfType (see \secref{TypingRule.SymDomOfType}) + \item TypingRule.SymDomOfExpr (see \secref{TypingRule.SymDomOfExpr}) + \item TypingRule.SymDomOfWidth (see \secref{TypingRule.SymDomOfWidth}) + \item TypingRule.IntSetOp (see \secref{TypingRule.IntSetOp}) + \item TypingRule.IntSetToIntConstraints (see \secref{TypingRule.IntSetToIntConstraints}) + \item TypingRule.SymDomOfLiteral (see \secref{TypingRule.SymDomOfLiteral}) + \item TypingRule.SymIntSetOfConstraints (see \secref{TypingRule.SymIntSetOfConstraints}) + \item TypingRule.ConstraintToIntSet (see \secref{TypingRule.ConstraintToIntSet}) + \item TypingRule.NormalizeToInt (see \secref{TypingRule.NormalizeToInt}) + \item TypingRule.SymDomIsSubset (see \secref{TypingRule.SymDomIsSubset}) + \item TypingRule.SymIntSetSubset (see \secref{TypingRule.SymIntSetSubset}) + \item TypingRule.ConstraintBinop (see \secref{TypingRule.ConstraintBinop}) + \item TypingRule.IsRightIncreasing (see \secref{TypingRule.IsRightIncreasing}) + \item TypingRule.IsRightDecreasing (see \secref{TypingRule.IsRightDecreasing}) + \item TypingRule.IsLeftIncreasing (see \secref{TypingRule.IsLeftIncreasing}) +\end{itemize} + +\subsection{TypingRule.SymSubsumes \label{sec:TypingRule.SymSubsumes}} +\hypertarget{def-symsubsumes}{} +The predicate +\[ + \symsubsumes(\overname{\staticenvs}{\tenv} \aslsep \overname{\ty}{\vt} \aslsep \overname{\ty}{\vs}) + \aslto \overname{\Bool}{\vb} +\] +soundly approximates $\subsumes(\tenv, \vt, \vs)$ for integer types. +\ProseOtherwiseTypeError + +We assume that both $\vt$ and $\vs$ have been successfully annotated to integer types as per \chapref{Types} +(otherwise a typing error prevents us from applying this function). + +\subsubsection{Prose} +All of the following apply: +\begin{itemize} + \item applying $\symdomoftype$ to $\vt$ in $\tenv$ yields $\dt$; + \item applying $\symdomoftype$ to $\vs$ in $\tenv$ yields $\ds$; + \item applying $\symdomissubset$ to $\dt$ and $\ds$ in $\tenv$ yields $\vb$. +\end{itemize} + +\subsubsection{Formally} +\begin{mathpar} +\inferrule{ + \symdomoftype(\tenv, \vt) \typearrow \dt\\ + \symdomoftype(\tenv, \vs) \typearrow \ds\\ + \symdomissubset(\tenv, \dt, \ds) \typearrow \vb +}{ + \symsubsumes(\tenv, \vt, \vs) \typearrow \vb +} +\end{mathpar} + +\subsection{TypingRule.SymDomOfType \label{sec:TypingRule.SymDomOfType}} +\hypertarget{def-symdomoftype}{} +The function +\[ + \symdomoftype(\overname{\staticenvs}{\tenv} \aslsep \overname{\ty}{\vt}) \aslto \overname{\symdom}{\vd} +\] +transforms a type $\vt$ in a static environment $\tenv$ into a symbolic domain $\vd$. +It assumes its input type has an \underlyingtype{} which is an integer. +\subsubsection{Prose} +One of the following applies: +\begin{itemize} + \item All of the following apply (\textsc{int\_unconstrained}): + \begin{itemize} + \item $\vt$ is the unconstrained integer type; + \item define $\vd$ as $\Top$, which intuitively represents the entire set of integers. + \end{itemize} + + \item All of the following apply (\textsc{int\_parameterized}): + \begin{itemize} + \item $\vt$ is the \parameterizedintegertype\ for the identifier $\id$; + \item define $\vd$ as the symbolic constrained integer domain with a single constraint for the variable expression for $\id$, + that is, \\ $\FromSyntax([\ConstraintExact(\EVar(\id))])$. + \end{itemize} + + \item All of the following apply (\textsc{int\_well\_constrained\_finite}): + \begin{itemize} + \item $\vt$ is the well-constrained integer type for the list of constraints $\vcs$; + \item applying $\intsetofintconstraints$ to $\vcs$ in $\tenv$ yields $\vis$; + \item $\vis$ is a set of integers, that is, $\astlabel(\vis)$ is $\Finite$; + \item define $\vd$ as the symbolic finite set integer domain for $\vis$. + \end{itemize} + + \item All of the following apply (\textsc{int\_well\_constrained\_symbolic}): + \begin{itemize} + \item $\vt$ is the well-constrained integer type for the list of constraints $\vcs$; + \item applying $\intsetofintconstraints$ to $\vcs$ in $\tenv$ yields $\vis$; + \item $\vis$ is not a set of integers, that is, $\astlabel(\vis)$ is not $\Finite$; + \item define $\vd$ as the symbolic constrained integer domain for the list of constraints $\vcs$, that is, $\FromSyntax(\vcs)$. + \end{itemize} + + \item All of the following apply (\textsc{t\_named}): + \begin{itemize} + \item $\vt$ is the named type for identifier $\id$; + \item applying $\makeanonymous$ to $\vt$ in $\tenv$ yields $\vtone$; + \item applying $\symdomoftype$ to $\vtone$ in $\tenv$ yields $\vd$. + \end{itemize} +\end{itemize} + +\subsubsection{Formally} +\begin{mathpar} +\inferrule[int\_unconstrained]{}{ \symdomoftype(\tenv, \overname{\unconstrainedinteger}{\vt}) \typearrow \overname{\Top}{\vd} } +\end{mathpar} + +\begin{mathpar} +\inferrule[int\_parameterized]{}{ + \symdomoftype(\tenv, \overname{\TInt(\parameterized(\id))}{\vt}) \typearrow \\ + \overname{\FromSyntax([\ConstraintExact(\EVar(\id))])}{\vd} +} +\end{mathpar} + +\begin{mathpar} +\inferrule[int\_well\_constrained\_finite]{ + \intsetofintconstraints(\tenv, \vcs) \typearrow \vis\\ + \astlabel(\vis) = \Finite +}{ + \symdomoftype(\tenv, \overname{\TInt(\wellconstrained(\vcs))}{\vt}) \typearrow \overname{\vis}{\vd} +} +\end{mathpar} + +\begin{mathpar} +\inferrule[int\_well\_constrained\_symbolic]{ + \intsetofintconstraints(\tenv, \vcs) \typearrow \vis\\ + \astlabel(\vis) \neq \Finite +}{ + \symdomoftype(\tenv, \overname{\TInt(\wellconstrained(\vcs))}{\vt}) \typearrow \overname{\FromSyntax(\vcs)}{\vd} +} +\end{mathpar} + +\begin{mathpar} +\inferrule[t\_named]{ + \vt = \TNamed(\id)\\ + \makeanonymous(\vt) \typearrow \vtone\\ + \symdomoftype(\tenv, \vtone) \typearrow \vd +}{ + \symdomoftype(\tenv, \vt) \typearrow \vd +} +\end{mathpar} + +\subsection{TypingRule.SymDomOfExpr \label{sec:TypingRule.SymDomOfExpr}} +\hypertarget{def-symdomofexpr}{} +The function +\[ +\symdomofexpr( + \overname{\staticenvs}{\tenv} \aslsep + \overname{\expr}{\ve} +) \aslto +\overname{\symdom}{\vd} +\] +assigns a symbolic domain $\vd$ to an \underline{integer typed} expression $\ve$ in the static environment $\tenv$. + +\subsubsection{Prose} +One of the following applies: +\begin{itemize} + \item All of the following apply (\textsc{e\_literal}): + \begin{itemize} + \item $\ve$ is a literal expression for the literal $\vv$; + \item applying $\symdomofliteral$ to $\vv$ yields $\vd$. + \end{itemize} + + \item All of the following apply (\textsc{e\_var\_constant}): + \begin{itemize} + \item $\ve$ is a variable expression for the identifier $\vx$; + \item applying $\lookupconstant$ to $\vx$ in $\tenv$ yields the literal $\vv$; + \item applying $\symdomofliteral$ to $\vv$ yields $\vd$. + \end{itemize} + + \item All of the following apply (\textsc{e\_var\_type}): + \begin{itemize} + \item $\ve$ is a variable expression for the identifier $\vx$; + \item applying $\lookupconstant$ to $\vx$ in $\tenv$ yields $\bot$; + \item applying $\typeof$ to $\vx$ in $\tenv$ yields $\vtone$; + \item applying $\symdomoftype$ to $\vtone$ yields $\vd$. + \end{itemize} + + \item All of the following apply (\textsc{e\_unop\_minus}): + \begin{itemize} + \item $\ve$ is a unary operation expression for the operation $\MINUS$ and subexpression $\veone$; + \item applying $\symdomofexpr$ to the binary operation expression with the operation $\MINUS$ + and the literal expression for $0$ and $\veone$ in $\tenv$ yields $\vd$. + \end{itemize} + + \item All of the following apply (\textsc{e\_unop\_unknown}): + \begin{itemize} + \item $\ve$ is a unary operation expression for an operation that is not $\MINUS$; + \item define $\vd$ as $\FromSyntax([\ConstraintExact(\ve)])$ + \end{itemize} + + \item All of the following apply (\textsc{e\_binop\_supported}): + \begin{itemize} + \item $\ve$ is a binary operation expression for an operation that is one of $\PLUS$, $\MINUS$, or $\MUL$ + and subexpressions $\veone$ and $\vetwo$; + \item applying $\symdomofexpr$ to $\veone$ in $\tenv$ yields a symbolic domain $\visone$; + \item applying $\symdomofexpr$ to $\vetwo$ in $\tenv$ yields a symbolic domain $\vistwo$; + \item applying $\intsetop$ to $\op$ and $\visone$ and $\vistwo$ yields $\vis$; + \item define $\vd$ as $\vis$. + \end{itemize} + + \item All of the following apply (\textsc{e\_binop\_unsupported}): + \begin{itemize} + \item $\ve$ is a binary operation expression for an operation that is not one of $\PLUS$, $\MINUS$, or $\MUL$; + \item define $\vd$ as $\FromSyntax([\ConstraintExact(\ve)])$ + \end{itemize} + + \item All of the following apply (\textsc{unsupported}): + \begin{itemize} + \item $\ve$ is not one of the following expression types a literal expression, a variable expression, a unary operation + expression, or a binary operation expression; + \item define $\vd$ as $\FromSyntax([\ConstraintExact(\ve)])$ + \end{itemize} +\end{itemize} + +\subsubsection{Formally} +\begin{mathpar} +\inferrule[e\_literal]{ + \symdomofliteral(\vv) \typearrow \vd +}{ + \symdomofexpr(\tenv, \overname{\ELiteral(\vv)}{\ve}) \typearrow \vd +} +\end{mathpar} + +\begin{mathpar} +\inferrule[e\_var\_constant]{ + \lookupconstant(\tenv, \vx) \typearrow \vv\\ + \symdomofliteral(\vv) \typearrow \vd +}{ + \symdomofexpr(\tenv, \overname{\EVar(\vx)}{\ve}) \typearrow \vd +} +\end{mathpar} + +\begin{mathpar} +\inferrule[e\_var\_type]{ + \lookupconstant(\tenv, \vx) \typearrow \bot\\ + \typeof(\tenv, \vx) \typearrow \vtone\\ + \symdomoftype(\vtone) \typearrow \vd +}{ + \symdomofexpr(\tenv, \overname{\EVar(\vx)}{\ve}) \typearrow \vd +} +\end{mathpar} + +\begin{mathpar} +\inferrule[e\_unop\_minus]{ + \symdomofexpr(\EBinop(\MINUS, \ELiteral(\lint(0)), \veone)) \typearrow \vd +}{ + \symdomofexpr(\tenv, \overname{\EUnop(\MINUS, \veone)}{\ve}) \typearrow \vd +} +\end{mathpar} + +\begin{mathpar} +\inferrule[e\_unop\_unknown]{ + \op \neq \MINUS +}{ + \symdomofexpr(\tenv, \overname{\EUnop(\op, \veone)}{\ve}) \typearrow \overname{\FromSyntax([\ConstraintExact(\ve)])}{\vd} +} +\end{mathpar} + +\begin{mathpar} +\inferrule[e\_binop\_supported]{ + \op \in \{\PLUS, \MINUS, \MUL\}\\ + \symdomofexpr(\tenv, \veone) \typearrow \visone\\ + \symdomofexpr(\tenv, \vetwo) \typearrow \vistwo\\ + \intsetop(\op, \visone, \vistwo) \typearrow \vis +}{ + \symdomofexpr(\tenv, \overname{\EBinop(\op, \veone, \vetwo)}{\ve}) \typearrow \overname{\vis}{\vd} +} +\end{mathpar} + +\begin{mathpar} +\inferrule[e\_binop\_unsupported]{ + \op \not\in \{\PLUS, \MINUS, \MUL\}\\ +}{ + \symdomofexpr(\tenv, \overname{\EBinop(\op, \Ignore, \Ignore)}{\ve}) \typearrow \overname{\FromSyntax([\ConstraintExact(\ve)])}{\vd} +} +\end{mathpar} + +\begin{mathpar} +\inferrule[unsupported]{ + \astlabel(\ve) \not\in \{\ELiteral, \EVar, \EUnop, \EBinop\} +}{ + \symdomofexpr(\tenv, \ve) \typearrow \overname{\FromSyntax([\ConstraintExact(\ve)])}{\vd} +} +\end{mathpar} + +\subsection{TypingRule.SymDomOfWidth \label{sec:TypingRule.SymDomOfWidth}} +\hypertarget{def-symdomofwidth}{} +The function +\[ +\symdomofwidth( + \overname{\staticenvs}{\tenv} \aslsep + \overname{\expr}{\ve} +) \aslto +\overname{\symdom}{\vd} +\] +assigns a symbolic domain $\vd$ to an \underline{integer typed} expression $\ve$ in the static environment $\tenv$. +In contrast to $\symdomofexpr$, $\symdomofwidth$ should be applied to expressions that represent a bit vector width. + +\subsubsection{Prose} +One of the following applies: +\begin{itemize} + \item All of the following apply (\textsc{finite\_one\_width}): + \begin{itemize} + \item applying $\symdomofexpr$ to $\ve$ in $\tenv$ yields $\vdone$; + \item $\vdone$ is a set of integers, that is, $\Finite(s)$; + \item the cardinality of $s$ is one; + \item $\vd$ is $\vdone$. + \end{itemize} + + \item All of the following apply (\textsc{finite\_multiple\_widths}): + \begin{itemize} + \item applying $\symdomofexpr$ to $\ve$ in $\tenv$ yields $\vdone$; + \item $\vdone$ is a set of integers, that is, $\Finite(s)$; + \item the cardinality of $s$ is \emph{not} one; + \item define $\vd$ as $\FromSyntax([\ConstraintExact(\ve)])$. + \end{itemize} + + \item All of the following apply (\textsc{non\_finite}): + \begin{itemize} + \item applying $\symdomofexpr$ to $\ve$ in $\tenv$ yields $\vdone$; + \item $\vdone$ is not a set of integers, that is, $\astlabel(\vdone)$ is not $\Finite$; + \item define $\vd$ as $\FromSyntax([\ConstraintExact(\ve)])$. + \end{itemize} +\end{itemize} + +\subsubsection{Formally} +\begin{mathpar} +\inferrule[finite\_one\_width]{ + \symdomofexpr(\tenv, \ve) \typearrow \vdone \\ + \vdone = \Finite(s) \\ + \cardinality{s} = 1 +}{ + \symdomofwidth(\tenv, \ve) \typearrow \overname{\vdone}{\vd} +} +\end{mathpar} + +\begin{mathpar} +\inferrule[finite\_multiple\_widths]{ + \symdomofexpr(\tenv, \ve) \typearrow \vdone \\ + \vdone = \Finite(s) \\ + \cardinality{s} \neq 1 +}{ + \symdomofwidth(\tenv, \ve) \typearrow \overname{\FromSyntax([\ConstraintExact(\ve)])}{\vd} +} +\end{mathpar} + +\begin{mathpar} +\inferrule[non\_finite]{ + \symdomofexpr(\tenv, \ve) \typearrow \vdone \\ + \astlabel(\vdone) \neq \Finite +}{ + \symdomofwidth(\tenv, \ve) \typearrow \overname{\FromSyntax([\ConstraintExact(\ve)])}{\vd} +} +\end{mathpar} + +\subsection{TypingRule.IntSetOp \label{sec:TypingRule.IntSetOp}} +\hypertarget{def-intsetop}{} +The function +\[ +\intsetop(\overname{\binop}{\op} \aslsep \overname{\symdom}{\visone} \aslsep \overname{\symdom}{\vistwo}) +\aslto \overname{\symdom}{\vis} +\] +applies the binary operation $\op$ to the symbolic domains $\visone$ and $\vistwo$, +yielding the symbolic domain $\vis$. + +\subsubsection{Prose} +One of the following applies: +\begin{itemize} + \item All of the following apply (\textsc{top}): + \begin{itemize} + \item at least one of $\visone$ and $\vistwo$ is $\Top$; + \item define $\vis$ as $\Top$. + \end{itemize} + + \item All of the following apply (\textsc{finite\_finite}): + \begin{itemize} + \item $\visone$ is the symbolic finite set integer domain for $\vsone$; + \item $\vistwo$ is the symbolic finite set integer domain for $\vstwo$; + \item define $\vis$ as the symbolic finite set domain for the set obtained + by applying $\op$ to each element of $\vsone$ and each element of $\vstwo$. + \end{itemize} + + \item All of the following apply (\textsc{finite\_syntax}): + \begin{itemize} + \item $\visone$ is the symbolic finite set integer domain for $\vsone$; + \item $\vistwo$ is the symbolic constrained integer domain for $\vstwo$; + \item applying $\intsettointconstraints$ to $\vsone$ yields the list of constraints $\csone$; + \item applying $\intsetop$ to $\op$, the symbolic constrained integer domain for $\csone$, + and $\vistwo$ yields $\vis$. + \end{itemize} + + \item All of the following apply (\textsc{syntax\_finite}): + \begin{itemize} + \item $\visone$ is the symbolic constrained integer domain for $\csone$; + \item $\vistwo$ is the symbolic finite set integer domain for $\vstwo$; + \item applying $\intsettointconstraints$ to $\vstwo$ yields the list of constraints $\cstwo$; + \item applying $\intsetop$ to $\op$, $\visone$, and the symbolic constrained integer domain + for $\cstwo$, yields $\vis$. + \end{itemize} + + \item All of the following apply (\textsc{syntax\_syntax\_well\_constrained}): + \begin{itemize} + \item $\visone$ is the symbolic constrained integer domain for $\csone$; + \item $\vistwo$ is the symbolic constrained integer domain for $\cstwo$; + \item applying $\constraintbinop$ to $\op$, $\csone$, and $\cstwo$ yields + a list of constraints $\vcs$; + \item define $\vis$ as the symbolic constrained integer domain for $\vcs$. + \end{itemize} + + \item All of the following apply (\textsc{syntax\_syntax\_top}): + \begin{itemize} + \item $\visone$ is the symbolic constrained integer domain for $\csone$; + \item $\vistwo$ is the symbolic constrained integer domain for $\cstwo$; + \item applying $\constraintbinop$ to $\op$, $\csone$, and $\cstwo$ yields $\top$; + \item define $\vis$ as $\Top$. + \end{itemize} +\end{itemize} + +\subsubsection{Formally} +\begin{mathpar} +\inferrule[top]{ + \visone = \Top \lor \vistwo = \Top +}{ + \intsetop(\op, \visone, \vistwo) \typearrow \overname{\Top}{\vis} +} +\and +\inferrule[finite\_finite]{ + \vis \eqdef \Finite(\{ \op(a, b) \;|\; a \in \vsone, b \in \vstwo \}) +}{ + \intsetop(\op, \overname{\Finite(\vsone)}{\visone}, \overname{\Finite(\vstwo)}{\vistwo}) \typearrow \vis +} +\end{mathpar} + +\begin{mathpar} +\inferrule[finite\_syntax]{ + \intsettointconstraints(\vsone) \typearrow \vcsone\\ + \intsetop(\op, \FromSyntax(\vcsone), \FromSyntax(\vcstwo)) \typearrow \vis +}{ + \intsetop(\op, \overname{\Finite(\vsone)}{\visone}, \overname{\FromSyntax(\vcstwo)}{\vistwo}) \typearrow \vis +} +\end{mathpar} + +\begin{mathpar} +\inferrule[syntax\_finite]{ + \intsettointconstraints(\vstwo) \typearrow \vcstwo\\ + \intsetop(\op, \FromSyntax(\vcsone), \FromSyntax(\vcstwo)) \typearrow \vis +}{ + \intsetop(\op, \overname{\FromSyntax(\vcsone)}{\visone}, \overname{\Finite(\vstwo)}{\vistwo}) \typearrow \vis +} +\end{mathpar} + +\begin{mathpar} +\inferrule[syntax\_syntax\_well\_constrained]{ + \constraintbinop(\op, \vcsone, \vcstwo) \typearrow \wellconstrained(\vcs) +}{ + \intsetop(\op, \overname{\FromSyntax(\vcsone)}{\visone}, \overname{\FromSyntax(\vcstwo)}{\vistwo}) \typearrow \overname{\FromSyntax(\vcs)}{\vis} +} +\end{mathpar} + +\begin{mathpar} +\inferrule[syntax\_syntax\_top]{ + \constraintbinop(\op, \vcsone, \vcstwo) \typearrow \top +}{ + \intsetop(\op, \overname{\FromSyntax(\vcsone)}{\visone}, \overname{\FromSyntax(\vcstwo)}{\vistwo}) \typearrow \overname{\Top}{\vis} +} +\end{mathpar} + +\subsection{TypingRule.IntSetToIntConstraints \label{sec:TypingRule.IntSetToIntConstraints}} +\hypertarget{def-intsettointconstraints}{} +The function +\[ +\intsettointconstraints(\overname{\powfin{\Z}}{\vs}) +\aslto \overname{\intconstraint^*}{\cs} +\] +transforms a finite set of integers into the equivalent list of integer constraints. + +\subsubsection{Prose} +One of the following applies: +\begin{itemize} + \item All of the following apply (\textsc{empty}): + \begin{itemize} + \item $\vs$ is the empty set; + \item define $\cs$ as the empty list. + \end{itemize} + + \item All of the following apply (\textsc{singleton}): + \begin{itemize} + \item $\vs$ is the singleton set for $a$; + \item define $\cs$ as the list containing the single range constraint for the interval starting from $a$ + and ending at $a$, that is, $\ConstraintRange(\ELInt{a}, \ELInt{a})$. + \end{itemize} + + \item All of the following apply (\textsc{new\_interval}): + \begin{itemize} + \item define $a$ as the minimal element of $\vs$; + \item define $\vsone$ as the set $\vs$ with $a$ removed from it; + \item applying $\intsettointconstraints$ to $\vsone$ yields the list of constraints $\csone$; + \item $\csone$ is a list where its \head\ is a range constraint for the interval starting from $b$ and ending at $c$ + and \tail\ $\cstwo$; + \item $b$ is greater than $a+1$; + \item define $\cs$ as the list with first element a range constraint for the interval from $a$ to $a$, + second element a range constraint for the interval from $b$ to $c$, and remaining elements given by $\cstwo$. + \end{itemize} + + \item All of the following apply (\textsc{merge\_interval}): + \begin{itemize} + \item define $a$ as the minimal element of $\vs$; + \item define $\vsone$ as the set $\vs$ with $a$ removed from it; + \item applying $\intsettointconstraints$ to $\vsone$ yields the list of constraints $\csone$; + \item $\csone$ is a list where its \head\ is a range constraint for the interval starting from $b$ and ending at $c$ + and \tail\ $\cstwo$; + \item $b$ is equal to $a+1$; + \item define $\cs$ as the list with \head\ a range constraint for the interval from $a$ to $c$ + and \tail\ $\cstwo$. + \end{itemize} +\end{itemize} + +\subsubsection{Formally} +\begin{mathpar} +\inferrule[empty]{}{ + \intsettointconstraints(\overname{\emptyset}{\vs}) \typearrow \overname{\emptylist}{\cs} +} +\end{mathpar} + +\begin{mathpar} +\inferrule[singleton]{}{ + \intsettointconstraints(\overname{\{a\}}{\vs}) \typearrow \overname{[\ConstraintRange(\ELInt{a}, \ELInt{a})]}{\cs} +} +\end{mathpar} + +\begin{mathpar} +\inferrule[new\_interval]{ + a = \min(\vs)\\ + \vsone \eqdef \vs \setminus \{a\}\\ + \intsettointconstraints(\vsone) \typearrow \csone\\ + \csone = [\ConstraintRange(\ELInt{b}, \ELInt{c})] \concat \cstwo\\ + b > a + 1\\\\ + { + \begin{array}{rcl} + \cs &\eqdef & [\ConstraintRange(\ELInt{a}, \ELInt{a})]\ \concat\\ + & & [\ConstraintRange(\ELInt{b}, \ELInt{c})]\ \concat \\ + & & \cstwo + \end{array} + } +}{ + \intsettointconstraints(\vs) \typearrow \cs +} +\end{mathpar} + +\begin{mathpar} +\inferrule[merge\_interval]{ + a = \min(\vs)\\ + \vsone \eqdef \vs \setminus \{a\}\\ + \intsettointconstraints(\vsone) \typearrow \csone\\ + \csone = [\ConstraintRange(\ELInt{b}, \ELInt{c})] \concat \cstwo\\ + b = a + 1\\ + \cs \eqdef [\ConstraintRange(\ELInt{a}, \ELInt{c})] \concat \cstwo +}{ + \intsettointconstraints(\vs) \typearrow \cs +} +\end{mathpar} + +\subsection{TypingRule.SymDomOfLiteral \label{sec:TypingRule.SymDomOfLiteral}} +\hypertarget{def-symdomofliteral}{} +The function +\[ +\symdomofliteral(\overname{\literal}{\vv}) \typearrow \overname{\symdom}{\vd} +\] +returns the symbolic domain $\vd$ that corresponds to the literal $\vv$. + +\subsubsection{Prose} +All of the following apply: +\begin{itemize} + \item $\vv$ is an integer literal for $n$; + \item define $\vd$ as the symbolic finite set integer domain for the singleton set for $n$, that is, $\Finite(\{n\})$. +\end{itemize} + +\subsubsection{Formally} +\begin{mathpar} +\inferrule{}{ + \symdomofliteral(\overname{\lint(n)}{\vv}) \typearrow \overname{\Finite(\{n\})}{\vd} +} +\end{mathpar} + +\subsection{TypingRule.SymIntSetOfConstraints \label{sec:TypingRule.SymIntSetOfConstraints}} +\hypertarget{def-intsetofintconstraintse}{} +The function +\[ + \intsetofintconstraints( + \overname{\staticenvs}{\tenv} \aslsep + \overname{\constraints}{\vcs} + ) \aslto + \overname{\symdom}{\vis} +\] +returns the symbolic domain $\vis$ for the list of constraints $\vcs$ +in the static environment $\tenv$. + +\subsubsection{Prose} +One of the following applies: +\begin{itemize} + \item All of the following apply (\textsc{finite}): + \begin{itemize} + \item applying $\constrainttointset$ to every constraint $\vcs[\vi]$ in $\tenv$, for $\vi$ in \\ $\listrange(\vcs)$, + yields a finite set of integers $C_\vi$, that is, $\Finite(C_\vi)$; + \item define $\vis$ as the union of $C_\vi$ for all $\vi$ in $\listrange(\vcs)$. + \end{itemize} + + \item All of the following apply (\textsc{symbolic}): + \begin{itemize} + \item there exists a constraint $\vc$ in $\vcs$ such that applying $\constrainttointset$ to $\vc$ + in $\tenv$ does not yield a finite set of integers; + \item define $\vis$ as the symbolic constrained integer domain for $\vcs$, that is, \\ + $\FromSyntax(\vcs)$. + \end{itemize} +\end{itemize} + +\subsubsection{Formally} +\begin{mathpar} +\inferrule[finite]{ + \vi\in\listrange(\vcs): \constrainttointset(\tenv, \vcs[\vi]) \typearrow \Finite(C_\vi)\\ + C \eqdef \bigcup_{\vi\in\listrange(\vcs)} C_\vi +}{ + \intsetofintconstraints(\tenv, \vcs) \typearrow \overname{\Finite(C)}{\vis} +} +\end{mathpar} + +\begin{mathpar} +\inferrule[symbolic]{ + { + \begin{array}{r} + \exists \vi\in\listrange(\vcs): \constrainttointset(\tenv, \vcs[\vi]) \typearrow \\ + \visone \land \astlabel(\visone) \neq \Finite + \end{array} + } +}{ + \intsetofintconstraints(\tenv, \vcs) \typearrow \overname{\FromSyntax(\vcs)}{\vis} +} +\end{mathpar} + +\subsection{TypingRule.ConstraintToIntSet \label{sec:TypingRule.ConstraintToIntSet}} +\hypertarget{def-constrainttointset}{} +The function +\[ + \constrainttointset( + \overname{\staticenvs}{\tenv} \aslsep + \overname{\intconstraint}{\vc} + ) \aslto + \overname{\symdom}{\vis} +\] +transforms an integer constraint $\vc$ into a symbolic domain $\vis$. +It produces $\Top$ when the expressions involved in the integer constraints cannot be simplified +to integers. + +\subsubsection{Prose} +One of the following applies: +\begin{itemize} + \item All of the following apply (\textsc{exact}): + \begin{itemize} + \item $\vc$ is a single expression constraint for $\ve$, that is, $\ConstraintExact(\ve)$; + \item applying $\normalizetoint$ to $\ve$ in $\tenv$ yields the integer $n$\ProseTerminateAs{\Top}; + \item define $\vis$ as the singleton set for $n$, that is, $\Finite(\{n\})$. + \end{itemize} + + \item All of the following apply (\textsc{range}): + \begin{itemize} + \item $\vc$ is a range constraint for $\veone$ and $\vetwo$, that is, $\ConstraintRange(\veone, \vetwo)$; + \item applying $\normalizetoint$ to $\veone$ in $\tenv$ yields the integer $b$\ProseTerminateAs{\Top}; + \item applying $\normalizetoint$ to $\vetwo$ in $\tenv$ yields the integer $t$\ProseTerminateAs{\Top}; + \item define $\vis$ as the set integers that are both greater or equal to $b$ and less than or equal to $t$. + \end{itemize} +\end{itemize} + +\subsubsection{Formally} +\begin{mathpar} +\inferrule[exact]{ + \normalizetoint(\tenv, \ve) \typearrow n \terminateas \Top +}{ + \constrainttointset(\tenv, \overname{\ConstraintExact(\ve)}{\vc}) \typearrow \overname{\Finite(\{n\})}{\vis} +} +\and +\inferrule[range]{ + \normalizetoint(\tenv, \veone) \typearrow b \terminateas \Top\\\\ + \normalizetoint(\tenv, \vetwo) \typearrow t \terminateas \Top\\\\ + \vis \eqdef \Finite(\{ n \;|\; b \leq n \leq t\}) +}{ + \constrainttointset(\tenv, \overname{\ConstraintRange(\veone, \vetwo)}{\vc}) \typearrow \vis +} +\end{mathpar} + +\subsection{TypingRule.NormalizeToInt \label{sec:TypingRule.NormalizeToInt}} +\hypertarget{def-normalizetoint}{} +The function +\[ +\normalizetoint( + \overname{\staticenvs}{\tenv} \aslsep + \overname{\expr}{\ve} +) \aslto \overname{\Z}{n} \cup \{\Top\} +\] +\symbolicallysimplifies\ the \underline{integer-typed} expression $\ve$ and returns the resulting integer or $\Top$ if +the result of the simplification is not an integer. + +We assume that $\ve$ has been annotated as it is part of the constraint for an integer type, +and therefore applying $\normalize$ to it does not yield a type error. + +\subsubsection{Prose} +One of the following applies: +\begin{itemize} + \item All of the following apply (\textsc{integer}): + \begin{itemize} + \item applying $\normalize$ to $\ve$ in $\tenv$ yields the expression $\veone$; + \item applying $\staticeval$ to $\veone$ in $\tenv$ yields the integer literal for $n$. + \end{itemize} + + \item All of the following apply (\textsc{top}): + \begin{itemize} + \item applying $\normalize$ to $\ve$ in $\tenv$ yields the expression $\veone$; + \item applying $\staticeval$ to $\veone$ in $\tenv$ yields $\top$. + \item the result is $\Top$. + \end{itemize} +\end{itemize} + +\subsubsection{Formally} +\begin{mathpar} +\inferrule[integer]{ + \normalize(\tenv, \ve) \typearrow \veone\\ + \staticeval(\tenv, \veone) \typearrow \lint(n) +}{ + \normalizetoint(\tenv, \ve) \typearrow n +} +\and +\inferrule[top]{ + \normalize(\tenv, \ve) \typearrow \veone\\ + \staticeval(\tenv, \veone) \typearrow \top +}{ + \normalizetoint(\tenv, \ve) \typearrow \Top +} +\end{mathpar} + +\subsection{TypingRule.SymDomIsSubset \label{sec:TypingRule.SymDomIsSubset}} +\hypertarget{def-symdomissubset}{} +The function +\[ + \symdomissubset( + \overname{\staticenvs}{\tenv} \aslsep + \overname{\symdom}{\vdone} \aslsep + \overname{\symdom}{\vdtwo} + ) \aslto + \overname{\Bool}{\vb} +\] +conservatively tests whether the symbolic domain $\vdone$ is subsumed by the symbolic domain $\vdtwo$, +yielding the result $\vb$. + +\subsubsection{Prose} +All of the following apply: +\begin{itemize} + \item applying $\symintsetsubset$ to $\vdone$ and $\vdtwo$ in $\tenv$ yields $\vb$. +\end{itemize} + +\subsubsection{Formally} +\begin{mathpar} +\inferrule[int]{ + \symintsetsubset(\tenv, \vdone, \vdtwo) \typearrow \vb +}{ + \symdomissubset(\tenv, \vdone, \vdtwo) \typearrow \vb +} +\end{mathpar} + +\subsection{TypingRule.SymIntSetSubset \label{sec:TypingRule.SymIntSetSubset}} +\hypertarget{def-symintsetsubset}{} +The function +\[ +\symintsetsubset(\overname{\staticenvs}{\tenv} \aslsep \overname{\symdom}{\visone} \aslsep \overname{\symdom}{\vistwo}) \aslto \overname{\Bool}{\vb} +\] + +\subsubsection{Prose} +One of the following applies: +\begin{itemize} + \item All of the following apply (\textsc{right\_top}): + \begin{itemize} + \item $\vistwo$ is $\Top$; + \item define $\vb$ as $\True$. + \end{itemize} + + \item All of the following apply (\textsc{left\_top\_right\_not\_top}): + \begin{itemize} + \item $\visone$ is $\Top$; + \item $\vistwo$ is not $\Top$; + \item define $\vb$ as $\False$. + \end{itemize} + + \item All of the following apply (\textsc{finite}): + \begin{itemize} + \item $\visone$ is a finite set of integers for $\vsone$, that is, $\Finite(\vsone)$; + \item $\vistwo$ is a finite set of integers for $\vstwo$, that is, $\Finite(\vstwo)$; + \item define $\vb$ as $\True$ if and only if $\vsone$ is a subset of $\vstwo$ or both sets are equal. + \end{itemize} + + \item All of the following apply (\textsc{syntax}): + \begin{itemize} + \item $\visone$ is a set of integers given by the list of constraints $\csone$, that is, \\ $\FromSyntax(\vsone)$; + \item $\vistwo$ is a set of integers given by the list of constraints $\cstwo$, that is, \\ $\FromSyntax(\vstwo)$; + \item applying $\constraintsequal$ to $\csone$ and $\cstwo$ in $\tenv$ yields $\vb$. + \end{itemize} + + \item All of the following apply (\textsc{other}): + \begin{itemize} + \item both $\visone$ and $\vistwo$ are not $\Top$; + \item the AST labels of $\visone$ and $\vistwo$ are different; + \item define $\vb$ as $\False$. + \end{itemize} +\end{itemize} + +\subsubsection{Formally} +\begin{mathpar} +\inferrule[right\_top]{}{ + \symintsetsubset(\tenv, \visone, \overname{\Top}{\vistwo}) \typearrow \overname{\True}{\vb} +} +\end{mathpar} + +\begin{mathpar} +\inferrule[left\_top\_right\_not\_top]{ + \vistwo \neq \Top +}{ + \symintsetsubset(\tenv, \overname{\Top}{\visone}, \vistwo) \typearrow \overname{\False}{\vb} +} +\end{mathpar} + +\begin{mathpar} +\inferrule[finite]{}{ + \symintsetsubset(\tenv, \overname{\Finite(\vsone)}{\visone}, \overname{\Finite(\vstwo)}{\vistwo}) \typearrow \overname{\vsone \subseteq \vstwo}{\vb} +} +\end{mathpar} + +\begin{mathpar} +\inferrule[syntax]{ + \constraintsequal(\tenv, \csone, \cstwo) \typearrow \vb +}{ + \symintsetsubset(\tenv, \overname{\FromSyntax(\csone)}{\visone}, \overname{\FromSyntax(\cstwo)}{\vistwo}) \typearrow \vb +} +\end{mathpar} + +\begin{mathpar} +\inferrule[other]{ + \visone \neq \Top \and \vistwo \neq \Top\\ + \astlabel(\visone) \neq \astlabel(\vistwo) +}{ + \symintsetsubset(\tenv, \visone, \vistwo) \typearrow \overname{\False}{\vb} +} +\end{mathpar} + +\subsection{TypingRule.ConstraintBinop \label{sec:TypingRule.ConstraintBinop}} +\hypertarget{def-constraintbinop}{} +The function +\[ +\constraintbinop( + \overname{\binop}{\op} \aslsep + \overname{\intconstraint^*}{\csone} \aslsep + \overname{\intconstraint^*}{\cstwo} +) +\aslto \overname{\intconstraints}{\vics} +\] +symbolically applies the binary operation $\op$ to the lists of integer constraints $\csone$ and $\cstwo$, +yielding the integer constraints $\vics$. + +\subsubsection{Prose} +One of the following applies: +\begin{itemize} + \item All of the following apply (\textsc{well\_constrained}): + \begin{itemize} + \item for every $\vi$ in $\listrange(\csone)$ and every $\vj$ in $\listrange(\cstwo)$, + applying \\ + $\constraintbinoppair$ to $\op$, $\csone[\vi]$, and $\cstwo[\vj]$, + yields the constraint $\vc_{(\vi,\vj)}$; + \item define $\cs$ as the list consisting of constraints $\vc_{(\vi,\vj)}$, + for every $\vi$ in $\listrange(\csone)$ and every $\vj$ in $\listrange(\cstwo)$; + \item $\vics$ is the well-constrained list of constrains $\cs$. + \end{itemize} + + \item All of the following apply (\textsc{unconstrained}): + \begin{itemize} + \item there exist $\vi$ in $\listrange(\csone)$ and $\vj$ in $\listrange(\cstwo)$, + such that applying + $\constraintbinoppair$ to $\op$, $\csone[\vi]$, and $\cstwo[\vj]$, + yields $\top$; + \item $\vics$ is $\unconstrained$. + \end{itemize} +\end{itemize} + +\subsubsection{Formally} +\begin{mathpar} +\inferrule[well\_constrained]{ + { + \begin{array}{l} + \vi\in\listrange(\csone), \vj\in\listrange(\cstwo): \\ + \constraintbinoppair(\op, \csone[\vi], \cstwo[\vj]) \typearrow \vc_{(\vi,\vj)} + \end{array} + }\\ + \cs \eqdef [\vi\in\listrange(\csone), \vj\in\listrange(\cstwo): \vc_{(\vi,\vj)}] +}{ + \constraintbinop(\op, \csone, \cstwo) \typearrow \overname{\wellconstrained(\cs)}{\vics} +} +\end{mathpar} + +\begin{mathpar} +\inferrule[unconstrained]{ + { + \begin{array}{l} + \exists \vi\in\listrange(\csone).\ \exists \vj\in\listrange(\cstwo).\ \\ + \constraintbinoppair(\op, \csone[\vi], \cstwo[\vj]) \typearrow \top + \end{array} + } +}{ + \constraintbinop(\op, \csone, \cstwo) \typearrow \overname{\unconstrained}{\vics} +} +\end{mathpar} + +\subsection{TypingRule.ConstraintBinopPair \label{sec:TypingRule.ConstraintBinopPair}} +\hypertarget{def-constraintbinoppair}{} +The function +\[ +\constraintbinoppair( + \overname{\binop}{\op} \aslsep + \overname{\intconstraint}{\vcone} \aslsep + \overname{\intconstraint}{\vctwo} +) +\aslto \overname{\overname{\intconstraint}{\vc} \cup \{\top\}}{\vres} +\] +symbolically applies the binary operation $\op$ to the pair of integer constraints $\vcone$ and $\vctwo$, +yielding $\vres$ which is an integer constraint $\vc$ or +$\top$, which indicates a failure in representing the result as an integer constraint. + +\subsubsection{Prose} +One of the following applies: +\begin{itemize} + \item All of the following apply (\textsc{exact\_exact}): + \begin{itemize} + \item $\vcone$ is an exact constraint for the expression $\veone$, that is, \ConstraintExact(\veone); + \item $\vctwo$ is an exact constraint for the expression $\vetwo$, that is, \ConstraintExact(\vetwo); + \item define $\vc$ as the exact constraint for the binary operation expression with $\op$, $\veone$, and $\vetwo$, + that is, $\ConstraintExact(\EBinop(\op, \veone, \vetwo))$; + \end{itemize} + + \item All of the following apply (\textsc{exact\_range}): + \begin{itemize} + \item $\vcone$ is an exact constraint for the expression $\veone$, that is, $\ConstraintExact(\veone)$; + \item $\vctwo$ is an range constraint for the expressions $\vetwoone$ and $\vetwotwo$, that is, \\ $\ConstraintRange(\vetwoone, \vetwotwo)$; + \item One of the following applies: + \begin{itemize} + \item All of the following apply: + \begin{itemize} + \item applying $\isrightincreasing$ to $\op$ yields $\True$; + \item define $\vc$ as the range constraint for the following two expressions: + the binary operation expression for $\op$ $\veone$ and $\vetwoone$, and + the binary operation expression for $\op$ $\veone$ and $\vetwotwo$; + \end{itemize} + + \item All of the following apply: + \begin{itemize} + \item applying $\isrightdecreasing$ to $\op$ yields $\True$; + \item define $\vc$ as the range constraint for the following two expressions: + the binary operation expression for $\op$ $\veone$ and $\vetwotwo$, and + the binary operation expression for $\op$ $\veone$ and $\vetwoone$; + \end{itemize} + + \item Otherwise, the result is $\Top$; + \end{itemize} + \end{itemize} + + \item All of the following apply (\textsc{range\_exact}): + \begin{itemize} + \item $\vcone$ is an range constraint for the expressions $\veoneone$ and $\veonetwo$, that is, \\ $\ConstraintRange(\veoneone, \veonetwo)$; + \item $\vctwo$ is an exact constraint for the expression $\vetwo$, that is, $\ConstraintExact(\vetwo)$; + \item One of the following applies: + \begin{itemize} + \item All of the following apply: + \begin{itemize} + \item applying $\isleftincreasing$ to $\op$ yields $\True$; + \item define $\vc$ as the range constraint for the following two expressions: + the binary operation expression for $\op$ $\veoneone$ and $\vetwo$, and + the binary operation expression for $\op$ $\veonetwo$ and $\vetwo$; + \end{itemize} + \item Otherwise, the result is $\Top$. + \end{itemize} + \end{itemize} + + \item All of the following apply (\textsc{range\_range}): + \begin{itemize} + \item $\vcone$ is an range constraint for the expressions $\veoneone$ and $\veonetwo$, that is, \\ $\ConstraintRange(\veoneone, \veonetwo)$; + \item $\vctwo$ is an range constraint for the expressions $\vetwoone$ and $\vetwotwo$, that is, \\ $\ConstraintRange(\vetwoone, \vetwotwo)$; + \item One of the following applies: + \begin{itemize} + \item All of the following apply: + \begin{itemize} + \item applying $\isleftincreasing$ to $\op$ yields $\True$; + \item applying $\isrightincreasing$ to $\op$ yields $\True$; + \item define $\vc$ as the range constraint for the following two expressions: + the binary operation expression for $\op$ $\veoneone$ and $\vetwoone$, and + the binary operation expression for $\op$ $\veonetwo$ and $\vetwotwo$; + \end{itemize} + \item All of the following apply: + \begin{itemize} + \item applying $\isleftincreasing$ to $\op$ yields $\True$; + \item applying $\isrightdecreasing$ to $\op$ yields $\True$; + \item define $\vc$ as the range constraint for the following two expressions: + the binary operation expression for $\op$ $\veoneone$ and $\vetwotwo$, and + the binary operation expression for $\op$ $\veonetwo$ and $\vetwoone$; + \end{itemize} + \item Otherwise, the result is $\Top$. + \end{itemize} + \end{itemize} +\end{itemize} + +\subsubsection{Formally} +\begin{mathpar} +\inferrule[exact\_exact]{}{ + \constraintbinoppair(\op, \overname{\AbbrevConstraintExact{\veone}}{\vcone}, \overname{\AbbrevConstraintExact{\vetwo}}{\vctwo}) \typearrow + \overname{\AbbrevConstraintExact{\AbbrevEBinop{\op}{\veone}{\vetwo}}}{\vc} +} +\end{mathpar} + +\begin{mathpar} +\inferrule[exact\_range]{ + \vres \eqdef + { + \begin{cases} + % 2 + \AbbrevConstraintRange{\AbbrevEBinop{\op}{\veone}{\vetwoone}}{\AbbrevEBinop{\op}{\veone}{\vetwotwo}} & \textbf{if } + (\isrightincreasing(\op) \typearrow \True) \\ + % 3 + \AbbrevConstraintRange{\AbbrevEBinop{\op}{\veone}{\vetwotwo}}{\AbbrevEBinop{\op}{\veone}{\vetwoone}} & \textbf{if } + (\isrightdecreasing(\op) \typearrow \True) \\ + % + \Top & \textbf{else} + \end{cases} + } +}{ + \constraintbinoppair(\op, \overname{\AbbrevConstraintExact{\veone}}{\vcone}, \overname{\AbbrevConstraintRange{\vetwoone}{\vetwotwo}}{\vctwo}) \typearrow \vres +} +\end{mathpar} + +\begin{mathpar} +\inferrule[range\_exact]{ + \vres \eqdef + { + \begin{cases} + % 4 + \AbbrevConstraintRange{\AbbrevEBinop{\op}{\veoneone}{\vetwo}}{\AbbrevEBinop{\op}{\veonetwo}{\vetwo}} & \textbf{if } + (\isleftincreasing(\op) \typearrow \True)\\ + % + \Top & \textbf{else} + \end{cases} + } +}{ + \constraintbinoppair(\op, \overname{\AbbrevConstraintRange{\veoneone}{\veonetwo}}{\vcone}, \overname{\AbbrevConstraintExact{\vetwo}}{\vctwo}) \typearrow \vres +} +\end{mathpar} + +\begin{mathpar} +\inferrule[range\_range]{ + \vres \eqdef + { + \begin{cases} + % 5 + \AbbrevConstraintRange{\AbbrevEBinop{\op}{\veoneone}{\vetwoone}}{\AbbrevEBinop{\op}{\veonetwo}{\vetwotwo}} & \textbf{if } + \left(\begin{array}{ll} + \isleftincreasing(\op) \typearrow \True\ \land\\ + \isrightincreasing(\op) \typearrow \True\\ + \end{array}\right)\\ + % 6 + \AbbrevConstraintRange{\AbbrevEBinop{\op}{\veoneone}{\vetwotwo}}{\AbbrevEBinop{\op}{\veonetwo}{\vetwoone}} & \textbf{if } + \left(\begin{array}{ll} + \isleftincreasing(\op) \typearrow \True\ \land\\ + \isrightdecreasing(\op) \typearrow \True + \end{array}\right)\\ + % + \Top & \textbf{else} + \end{cases} + } +}{ + \constraintbinoppair(\op, \overname{\AbbrevConstraintRange{\veoneone}{\veonetwo}}{\vcone}, \overname{\AbbrevConstraintRange{\vetwoone}{\vetwotwo}}{\vctwo}) \typearrow \vres +} +\end{mathpar} + +\subsection{TypingRule.IsRightIncreasing \label{sec:TypingRule.IsRightIncreasing}} +\hypertarget{def-isrightincreasing}{} +The function +\[ +\isrightincreasing(\overname{\binop}{\op}) \aslto \overname{\Bool}{\vb} \cup \{\top\} +\] +tests whether the value of binary operation $\op$ increases along with its right-hand-side operand, +yielding the result in $\vb$. +Otherwise, the result is $\top$, which indicates that the answer is not always $\True$ or $\False$. + +\subsubsection{Prose} +One of the following applies: +\begin{itemize} + \item All of the following (\textsc{true}): + \begin{itemize} + \item $\op$ is one of $\MUL, \SHL, \SHR, \POW, \PLUS$; + \item define $\vb$ as $\True$. + \end{itemize} + + \item All of the following (\textsc{false}): + \begin{itemize} + \item $\op$ is one of $\DIV, \DIVRM, \MOD, \MINUS$; + \item define $\vb$ as $\False$. + \end{itemize} + + \item All of the following (\textsc{top}): + \begin{itemize} + \item $\op$ is $\RDIV$; + \item define $\vb$ as $\top$. + \end{itemize} +\end{itemize} + +\subsubsection{Formally} +\begin{mathpar} +\inferrule[true]{ + \op \in \{\MUL, \SHL, \SHR, \POW, \PLUS\} +}{ + \isrightincreasing(\op) \typearrow \overname{\True}{\vb} +} +\and +\inferrule[false]{ + \op \in \{\DIV, \DIVRM, \MOD, \MINUS\} +}{ + \isrightincreasing(\op) \typearrow \overname{\False}{\vb} +} +\and +\inferrule[top]{}{ + \isrightincreasing(\overname{\RDIV}{\op}) \typearrow \top +} +\end{mathpar} + +\subsection{TypingRule.IsRightDecreasing \label{sec:TypingRule.IsRightDecreasing}} +\hypertarget{def-isrightdecreasing}{} +The function +\[ +\isrightdecreasing(\overname{\binop}{\op}) \aslto \overname{\Bool}{\vb} \cup \{\top\} +\] +tests whether the value of binary operation $\op$ decreases along with its right-hand-side operand, +yielding the result in $\vb$. +Otherwise, the result is $\top$, which indicates that the answer is not always $\True$ or $\False$. + +\subsubsection{Prose} +One of the following applies: +\begin{itemize} + \item All of the following (\textsc{true}): + \begin{itemize} + \item $\op$ is $\MINUS$; + \item define $\vb$ as $\True$. + \end{itemize} + + \item All of the following (\textsc{false}): + \begin{itemize} + \item $\op$ is one of $\DIV, \DIVRM, \MUL, \SHL, \SHR, \POW, \PLUS, \MOD$; + \item define $\vb$ as $\False$. + \end{itemize} + + \item All of the following (\textsc{top}): + \begin{itemize} + \item $\op$ is one of $\AND ,\BAND ,\BEQ ,\BOR ,\XOR ,\EQOP ,\GT ,\GEQ ,\IMPL ,\LT ,\LEQ ,\NEQ ,\OR, \RDIV$; + \item define $\vb$ as $\top$. + \end{itemize} +\end{itemize} + +\subsubsection{Formally} +\begin{mathpar} +\inferrule[true]{}{ + \isrightdecreasing(\overname{\MINUS}{\op}) \typearrow \overname{\True}{\vb} +} +\and +\inferrule[false]{ + \op \in \{\DIV, \DIVRM, \MUL, \SHL, \SHR, \POW, \PLUS, \MOD\} +}{ + \isrightdecreasing(\op) \typearrow \overname{\False}{\vb} +} +\and +\inferrule[top]{ + \op \in \{\AND ,\BAND ,\BEQ ,\BOR ,\XOR ,\EQOP ,\GT ,\GEQ ,\IMPL ,\LT ,\LEQ ,\NEQ ,\OR, \RDIV\} +}{ + \isrightdecreasing(\op) \typearrow \top +} +\end{mathpar} + +\subsection{TypingRule.IsLeftIncreasing \label{sec:TypingRule.IsLeftIncreasing}} +\hypertarget{def-isleftincreasing}{} +The function +\[ +\isleftincreasing(\overname{\binop}{\op}) \aslto \overname{\Bool}{\vb} \cup \{\top\} +\] +tests whether the value of binary operation $\op$ increases along with its left-hand-side operand, +yielding $\True$ or $\top$, which indicates that the answer is not always $\True$ or $\False$. + +\subsubsection{Prose} +One of the following applies: +\begin{itemize} + \item All of the following (\textsc{true}): + \begin{itemize} + \item $\op$ is one of $\MUL, \DIV, \DIVRM, \MOD, \SHL, \SHR, \POW, \PLUS, \MINUS$; + \item define $\vb$ as $\True$. + \end{itemize} + + \item All of the following (\textsc{top}): + \begin{itemize} + \item $\op$ is one of $\AND ,\BAND ,\BEQ ,\BOR ,\XOR ,\EQOP ,\GT ,\GEQ ,\IMPL ,\LT ,\LEQ ,\NEQ ,\OR, \RDIV$; + \item define $\vb$ as $\top$. + \end{itemize} +\end{itemize} + +\subsubsection{Formally} +\begin{mathpar} +\inferrule[true]{ + \op \in \{\MUL, \DIV, \DIVRM, \MOD, \SHL, \SHR, \POW, \PLUS, \MINUS\} +}{ + \isleftincreasing(\op) \typearrow \overname{\True}{\vb} +} +\and +\inferrule[top]{ + \op \in \{\AND ,\BAND ,\BEQ ,\BOR ,\XOR ,\EQOP ,\GT ,\GEQ ,\IMPL ,\LT ,\LEQ ,\NEQ ,\OR, \RDIV\} +}{ + \isleftincreasing(\op) \typearrow \top +} +\end{mathpar} diff --git a/asllib/doc/Syntax.tex b/asllib/doc/Syntax.tex new file mode 100644 index 000000000..765885c00 --- /dev/null +++ b/asllib/doc/Syntax.tex @@ -0,0 +1,704 @@ +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +\chapter{Syntax\label{chap:Syntax}} +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +This chapter defines the grammar of ASL. The grammar is presented via two extensions +to context-free grammars --- \emph{inlined derivations} and \emph{parametric productions}, +inspired by the Menhir Parser Generator~\cite{MenhirManual} for the OCaml language. +Those extensions can be viewed as macros over context-free grammars, which can be +expanded to yield a standard context-free grammar. + +Our definition of the grammar and description of the parsing mechanism heavily relies +on the theory of parsing via LR(1) grammars and LR(1) parser generators. +% +See ``Compilers: Principles, Techniques, and Tools''~\cite{ASU86} for a detailed +definition of LR(1) grammars and parser construction. + +The expanded context-free grammar is an LR(1) grammar, modulo shift-reduce +conflicts that are resolved via appropriate precedence definitions. +That is, given a list of token, returned from $\aslscan$, it is possible to apply +an LR(1) parser to obtain a parse tree if the list of tokens is in the formal language +of the grammar and return a parse error otherwise. + +The outline of this chapter is as follows: +\begin{itemize} + \item Definition of inlined derivations (see \secref{InlinedDerivations}) + \item Definition of parametric productions (see \secref{ParametricProductions}) + \item ASL Parametric Productions (see \secref{ASLParametricProductions}) + \item Definition of the ASL grammar (see \secref{ASLGrammar}) + \item Definition of parse trees (see \secref{ParseTrees}) + \item Definition of priority and associativity of operators (see \secref{PriorityAndAssociativity}) +\end{itemize} + +\section{Inlined Derivations \label{sec:InlinedDerivations}} +Context-free grammars consist of a list of \emph{derivations} $N \derives S^*$ +where $N$ is a non-terminal symbol and $S$ is a list of non-terminal symbols and terminal symbols, +which correspond to tokens. +We refer to a list of such symbols as a \emph{sentence}. +A special form of a sentence is the \emph{empty sentence}, written $\emptysentence$. + +As commonly done, we aggregate all derivations associated with the same non-terminal symbol +by writing $N \derives R_1 \;|\; \ldots \;|\; R_k$. +We refer to the right-hand-side sentences $R_{1..k}$ as the \emph{alternatives} of $N$. + +Our grammar contains another form of derivation --- \emph{inlined derivation} --- +written as $N \derivesinline R_1 \;|\; \ldots \;|\; R_k$. +Expanding an inlined derivation consists of replacing each instance of $N$ +in a right-hand-side sentence of a derivation with each of $R_{1..k}$, thereby +creating $k$ variations of it (and removing $N \derivesinline R_1 \;|\; \ldots \;|\; R_k$ +from the set of derivations). + +For example, consider the derivation +\begin{flalign*} +\Nexpr \derives\ & \Nexpr \parsesep \Nbinop \parsesep \Nexpr & +\end{flalign*} +coupled with the derivation +\begin{flalign*} +\Nbinop \derives\ & \Tand \;|\; \Tband \;|\; \Tbor \;|\; \Tbeq \;|\; \Tdiv \;|\; \Tdivrm \;|\; \Txor \;|\; \Teqop \;|\; \Tneq &\\ + |\ & \Tgt \;|\; \Tgeq \;|\; \Timpl \;|\; \Tlt \;|\; \Tleq \;|\; \Tplus \;|\; \Tminus \;|\; \Tmod \;|\; \Tmul &\\ + |\ & \Tor \;|\; \Trdiv \;|\; \Tshl \;|\; \Tshr \;|\; \Tpow \;|\; \Tconcat +\end{flalign*} + +A grammar containing these two derivations results in shift-reduce conflicts. +Resolving these conflicts is done by associating priority levels to each of the binary operators +and creating a version of the first derivation for each binary operator: +\begin{flalign*} +\Nexpr \derives\ & \Nexpr \parsesep \Tand \parsesep \Nexpr & \\ + |\ & \Nexpr \parsesep \Tband \parsesep \Nexpr & \\ + |\ & \Nexpr \parsesep \Tbor \parsesep \Nexpr & \\ + \ldots \\ + |\ & \Nexpr \parsesep \Tconcat \parsesep \Nexpr & +\end{flalign*} + +By defining the derivations of $\Nbinop$ as inlined, we achieve the same effect more compactly: +\begin{flalign*} +\Nbinop \derivesinline\ & \Tand \;|\; \Tband \;|\; \Tbor \;|\; \Tbeq \;|\; \Tdiv \;|\; \Tdivrm \;|\; \Txor \;|\; \Teqop \;|\; \Tneq &\\ + |\ & \Tgt \;|\; \Tgeq \;|\; \Timpl \;|\; \Tlt \;|\; \Tleq \;|\; \Tplus \;|\; \Tminus \;|\; \Tmod \;|\; \Tmul &\\ + |\ & \Tor \;|\; \Trdiv \;|\; \Tshl \;|\; \Tshr \;|\; \Tpow \;|\; \Tconcat +\end{flalign*} + +Barring mutually-recursive derivations involving inlined derivations, it is possible to expand +all inlined derivations to obtain a context-free grammar without any inlined derivations. + +\section{Parametric Productions \label{sec:ParametricProductions}} +A parametric production has the form +$N(p_{1..m}) \derives R_1 \;|\; \ldots \;|\; R_k$ +where $p_{1..m}$ are place holders for grammar symbols and may appear in any of the alternatives $R_{1..k}$. +We refer to $N(p_{1..m})$ as a \emph{parametric non-terminal}. + +\newcommand\uniquesymb[1]{\textsf{unique}(#1)} +Given sentences $S_{1..m}$, we can expand $N(p_{1..m}) \derives R_1 \;|\; \ldots \;|\; R_k$ +by creating a unique symbols for $N(p_{1..m})$, denoted as $\uniquesymb{N(S_{1..m})}$, defining the +derivations +\[ + \uniquesymb{N(S_{1..m})} \derives R_1[S_1/p_1,\ldots,S_m/p_m] \;|\; \ldots \;|\; R_k[S_1/p_1,\ldots,S_m/p_m] +\] +where for each $i= 1..k$, $R_i[S_1/p_1,\ldots,S_m/p_m]$ means replacing each instance of $p_j$ with $S_j$, for each $j=1..m$. +Then, each instance of $S_{1..m}$ in the grammar is replaced by $\uniquesymb{N(S_{1..m})}$. +If all instances of a parametric non-terminal are expanded this way, we can remove the derivations of the parametric +non-terminal altogether. + +We note that a parametric production can be either a normal derivation or an inlined derivation. + +For example, the derivation for a list of ASL global declarations is as follows: +\begin{flalign*} +\Nast \derives\ & \maybeemptylist{\Ndecl} & +\end{flalign*} +It is defined via the parametric production for possibly-empty lists: +\begin{flalign*} +\maybeemptylist{x} \derives\ & \emptysentence \;|\; x \parsesep \maybeemptylist{x} &\\ +\end{flalign*} + +\newcommand\Ndecllist[0]{\nonterminal{decl\_list}} +Expanding $\maybeemptylist{\Ndecl}$ produces the following derivations for a new unique symbol. +That is, a symbol that does not appear anywhere else in the grammar. +In this example we will choose $\uniquesymb{\maybeemptylist{\Ndecl}}$ the be the symbol $\Ndecllist$. +The result of the expansion is then: +\begin{flalign*} +\Ndecllist \derives\ & \emptysentence \;|\; \Ndecl \parsesep \Ndecllist &\\ +\end{flalign*} +The new symbol is substituted anywhere $\maybeemptylist{\Ndecl}$ appears in the original grammar, +which results in the following derivation replacing the original derivation for $\Nast$: +\begin{flalign*} +\Nast \derives\ & \Ndecllist & +\end{flalign*} + +% For example, +% \[ +% \option{x} \derives \emptysentence \;|\; x +% \] +% is useful for compactly defining derivations where part of a sentence may or may not appear. + +% Suppose we have +% \[ +% B \derives a \parsesep \option{A \parsesep b} +% \] +% then expanding the instance $\option{A, b}$ produces +% \[ +% \uniquesymb{\option{A \parsesep b}} \derives \emptysentence \;|\; A \parsesep b +% \] +% since $x[A \parsesep b/x]$ yields $A \parsesep b$ and $\emptysentence[A \parsesep b/x]$ yields $\emptysentence$, +% and the derivations for $B$ are replaced by +% \[ +% B \derives a \parsesep \uniquesymb{\option{A \parsesep b}} +% \] + +Expanding all instances of parametric productions results in a grammar without any parametric productions. + +\section{ASL Parametric Productions \label{sec:ASLParametricProductions}} +We define the following parametric productions for various types of lists and optional productions. + +\paragraph{Optional Symbol} +\hypertarget{def-option}{} +\begin{flalign*} +\option{x} \derives\ & \emptysentence \;|\; x &\\ +\end{flalign*} + +\paragraph{Possibly-empty List} +\hypertarget{def-maybeemptylist}{} +\begin{flalign*} +\maybeemptylist{x} \derives\ & \emptysentence \;|\; x \parsesep \maybeemptylist{x} &\\ +\end{flalign*} + +\paragraph{Non-empty List} +\hypertarget{def-nonemptylist}{} +\begin{flalign*} +\nonemptylist{x} \derives\ & x \;|\; x \parsesep \nonemptylist{x}&\\ +\end{flalign*} + +\paragraph{Non-empty Comma-separated List} +\hypertarget{def-nclist}{} +\begin{flalign*} +\NClist{x} \derives\ & x \;|\; x \parsesep \Tcomma \parsesep \NClist{x} &\\ +\end{flalign*} + +\paragraph{Possibly-empty Comma-separated List} +\hypertarget{def-clist}{} +\begin{flalign*} +\Clist{x} \derivesinline\ & \emptysentence \;|\; \NClist{x} &\\ +\end{flalign*} + +\paragraph{Comma-separated List With At Least Two Elements} +\hypertarget{def-clisttwo}{} +\begin{flalign*} +\Clisttwo{x} \derivesinline\ & x \parsesep \Tcomma \parsesep \NClist{x} &\\ +\end{flalign*} + +\paragraph{Possibly-empty Parenthesized, Comma-separated List} +\hypertarget{def-plist}{} +\begin{flalign*} +\Plist{x} \derivesinline\ & \Tlpar \parsesep \Clist{x} \parsesep \Trpar &\\ +\end{flalign*} + +\paragraph{Parenthesized Comma-separated List With At Least Two Elements} +\hypertarget{def-plisttwo}{} +\begin{flalign*} +\Plisttwo{x} \derivesinline\ & \Tlpar \parsesep x \parsesep \Tcomma \parsesep \NClist{x} \parsesep \Trpar &\\ +\end{flalign*} + +\paragraph{Non-empty Comma-separated Trailing List} +\hypertarget{def-tclist}{} +\begin{flalign*} +\NTClist{x} \derives\ & x \parsesep \option{\Tcomma} &\\ + |\ & x \parsesep \Tcomma \parsesep \NTClist{x} +\end{flalign*} + +\paragraph{Comma-separated Trailing List} +\hypertarget{def-tclist}{} +\begin{flalign*} +\TClist{x} \derivesinline\ & \option{\NTClist{x}} &\\ +\end{flalign*} + +\section{ASL Grammar\label{sec:ASLGrammar}} +We now present the list of derivations for the ASL Grammar where the start non-terminal is $\Nast$. +% +The derivations allow certain parse trees where lists may have invalid sizes. +Those parse trees must be rejected in a later phase. + +Notice that two of the derivations (for $\Nexprpattern$ and for $\Nexpr$) end with \\ +$\precedence{\Tunops}$. +This is a precedence annotation, which is not part of the right-hand-side sentence, and is explained in \secref{PriorityAndAssociativity} +and can be ignored upon first reading. + +For brevity, tokens are presented via their label only, dropping their associated value. +For example, instead of $\Tidentifier(\id)$, we simply write $\Tidentifier$. + +\hypertarget{def-nast}{} +\begin{flalign*} +\Nast \derives\ & \productionname{ast}{ast}\ \maybeemptylist{\Ndecl} & +\end{flalign*} + +\hypertarget{def-ndecl}{} +\hypertarget{def-funcdecl}{} +\begin{flalign*} +\Ndecl \derivesinline\ & \productionname{funcdecl}{func\_decl}\ \Tfunc \parsesep \Tidentifier \parsesep \Nparamsopt \parsesep \Nfuncargs \parsesep \Nreturntype \parsesep \Nfuncbody & +\hypertarget{def-proceduredecl}{}\\ +|\ & \productionname{proceduredecl}{procedure\_decl}\ \Tfunc \parsesep \Tidentifier \parsesep \Nparamsopt \parsesep \Nfuncargs \parsesep \Nfuncbody & +\hypertarget{def-getter}{}\\ +|\ & \productionname{getter}{getter}\ \Tgetter \parsesep \Tidentifier \parsesep \Nparamsopt \parsesep \Naccessargs \parsesep \Nreturntype \parsesep \Nfuncbody& +\hypertarget{def-noarggetter}{}\\ +|\ & \productionname{noarggetter}{no\_arg\_getter}\ \Tgetter \parsesep \Tidentifier \parsesep \Nreturntype \parsesep \Nfuncbody & +\hypertarget{def-setter}{}\\ +|\ & \productionname{setter}{setter}\ \Tsetter \parsesep \Tidentifier \parsesep \Nparamsopt \parsesep \Naccessargs \parsesep \Teq \parsesep \Ntypedidentifier & \\ + & \wrappedline\ \parsesep \Nfuncbody & +\hypertarget{def-noargsetter}{}\\ +|\ & \productionname{noargsetter}{no\_arg\_setter}\ \Tsetter \parsesep \Tidentifier \parsesep \Teq \parsesep \Ntypedidentifier \parsesep \Nfuncbody& +\hypertarget{def-typedecl}{}\\ +|\ & \productionname{typedecl}{type\_decl}\ \Ttype \parsesep \Tidentifier \parsesep \Tof \parsesep \Ntydecl \parsesep \Nsubtypeopt \parsesep \Tsemicolon& +\hypertarget{def-subtypedecl}{}\\ +|\ & \productionname{subtypedecl}{subtype\_decl}\ \Ttype \parsesep \Tidentifier \parsesep \Nsubtype \parsesep \Tsemicolon& +\hypertarget{def-globalstorage}{}\\ +|\ & \productionname{globalstorage}{global\_storage}\ \Nstoragekeyword \parsesep \Nignoredoridentifier \parsesep \option{\Tcolon \parsesep \Nty} \parsesep \Teq \parsesep &\\ + & \wrappedline\ \Nexpr \parsesep \Tsemicolon & +\hypertarget{def-globaluninitvar}{}\\ +|\ & \productionname{globaluninitvar}{global\_uninit\_var}\ \Tvar \parsesep \Nignoredoridentifier \parsesep \Tcolon \parsesep \Nty \parsesep \Tsemicolon& +\hypertarget{def-globalpragma}{}\\ +|\ & \productionname{globalpragma}{global\_pragma}\ \Tpragma \parsesep \Tidentifier \parsesep \Clist{\Nexpr} \parsesep \Tsemicolon& +\end{flalign*} + +\hypertarget{def-nsubtype}{} +\begin{flalign*} +\Nsubtype \derivesinline\ & \Tsubtypes \parsesep \Tidentifier \parsesep \Twith \parsesep \Nfields &\\ + |\ & \Tsubtypes \parsesep \Tidentifier &\\ +\end{flalign*} + +\hypertarget{def-nsubtypeopt}{} +\begin{flalign*} +\Nsubtypeopt \derivesinline\ & \option{\Nsubtype} & +\end{flalign*} + +\hypertarget{def-ntypedidentifier}{} +\begin{flalign*} +\Ntypedidentifier \derivesinline\ & \Tidentifier \parsesep \Nasty & +\end{flalign*} + +\hypertarget{def-nopttypeidentifier}{} +\begin{flalign*} +\Nopttypedidentifier \derivesinline\ & \Tidentifier \parsesep \option{\Nasty} & +\end{flalign*} + +\hypertarget{def-nasty}{} +\begin{flalign*} +\Nasty \derivesinline\ & \Tcolon \parsesep \Nty & +\end{flalign*} + +\hypertarget{def-nreturntype}{} +\begin{flalign*} +\Nreturntype \derivesinline\ & \Tarrow \parsesep \Nty & +\end{flalign*} + +\hypertarget{def-nparamsopt}{} +\begin{flalign*} +\Nparamsopt \derivesinline\ & \emptysentence &\\ + |\ & \Tlbrace \parsesep \Clist{\Nopttypedidentifier} \parsesep \Trbrace & +\end{flalign*} + +\hypertarget{def-naccessargs}{} +\begin{flalign*} +\Naccessargs \derivesinline\ & \Tlbracket \parsesep \Clist{\Ntypedidentifier} \parsesep \Trbracket & +\end{flalign*} + +\hypertarget{def-nfuncargs}{} +\begin{flalign*} +\Nfuncargs \derivesinline\ & \Tlpar \parsesep \Clist{\Ntypedidentifier} \parsesep \Trpar & +\end{flalign*} + +\hypertarget{def-nmaybeemptystmtlist}{} +\begin{flalign*} +\Nmaybeemptystmtlist \derivesinline\ & \emptysentence \;|\; \Nstmtlist & +\end{flalign*} + +\hypertarget{def-nfuncbody}{} +\begin{flalign*} +\Nfuncbody \derivesinline\ & \Tbegin \parsesep \Nmaybeemptystmtlist \parsesep \Tend & +\end{flalign*} + +\hypertarget{def-nignoredoridentifier}{} +\begin{flalign*} +\Nignoredoridentifier \derivesinline\ & \Tminus \;|\; \Tidentifier & +\end{flalign*} + +\vspace*{-\baselineskip} +\paragraph{Parsing note:} $\Tvar$ is not derived by $\Nlocaldeclkeyword$ to avoid an LR(1) conflict. +\hypertarget{def-nlocaldeclkeyword}{} +\begin{flalign*} +\Nlocaldeclkeyword \derivesinline\ & \Tlet \;|\; \Tconstant& +\end{flalign*} + +\hypertarget{def-nstoragekeyword}{} +\begin{flalign*} +\Nstoragekeyword \derivesinline\ & \Tlet \;|\; \Tconstant \;|\; \Tvar \;|\; \Tconfig& +\end{flalign*} + +\hypertarget{def-ndirection}{} +\begin{flalign*} +\Ndirection \derivesinline\ & \Tto \;|\; \Tdownto & +\end{flalign*} + +\hypertarget{def-nalt}{} +\begin{flalign*} +\Nalt \derivesinline\ & \Twhen \parsesep \Npatternlist \parsesep \option{\Twhere \parsesep \Nexpr} \parsesep \Tarrow \parsesep \Nstmtlist &\\ +|\ & \Totherwise \parsesep \Nstmtlist & +\end{flalign*} + +\hypertarget{def-notherwiseopt}{} +\begin{flalign*} +\Notherwiseopt \derives\ & \option{\Totherwise \parsesep \Tarrow \parsesep \Nstmtlist} & +\end{flalign*} + +\hypertarget{def-ncatcher}{} +\begin{flalign*} +\Ncatcher \derivesinline\ & \Twhen \parsesep \Tidentifier \parsesep \Tcolon \parsesep \Nty \parsesep \Tarrow \parsesep \Nstmtlist &\\ + |\ & \Twhen \parsesep \Nty \parsesep \Tarrow \parsesep \Nstmtlist &\\ +\end{flalign*} + +\hypertarget{def-nstmt}{} +\begin{flalign*} +\Nstmt \derivesinline\ & \Tif \parsesep \Nexpr \parsesep \Tthen \parsesep \Nstmtlist \parsesep \Nselse \parsesep \Tend &\\ +|\ & \Tcase \parsesep \Nexpr \parsesep \Tof \parsesep \nonemptylist{\Nalt} \parsesep \Tend &\\ +|\ & \Twhile \parsesep \Nexpr \parsesep \Tdo \parsesep \Nstmtlist \parsesep \Tend &\\ +|\ & \Tlooplimit \parsesep \Tlpar \parsesep \Nexpr \parsesep \Trpar \parsesep \Twhile \parsesep \Nexpr \parsesep \Tdo \parsesep \Nstmtlist \parsesep \Tend &\\ +|\ & \Tfor \parsesep \Tidentifier \parsesep \Teq \parsesep \Nexpr \parsesep \Ndirection \parsesep + \Nexpr \parsesep \Tdo \parsesep \Nstmtlist \parsesep \Tend &\\ +|\ & \Ttry \parsesep \Nstmtlist \parsesep \Tcatch \parsesep \nonemptylist{\Ncatcher} \parsesep \Notherwiseopt \parsesep \Tend &\\ +|\ & \Tpass \parsesep \Tsemicolon &\\ +|\ & \Treturn \parsesep \option{\Nexpr} \parsesep \Tsemicolon &\\ +|\ & \Tidentifier \parsesep \Plist{\Nexpr} \parsesep \Tsemicolon &\\ +|\ & \Tassert \parsesep \Nexpr \parsesep \Tsemicolon &\\ +|\ & \Nlocaldeclkeyword \parsesep \Ndeclitem \parsesep \Teq \parsesep \Nexpr \parsesep \Tsemicolon &\\ +|\ & \Nlexpr \parsesep \Teq \parsesep \Nexpr \parsesep \Tsemicolon &\\ +|\ & \Tvar \parsesep \Ndeclitem \parsesep \option{\Teq \parsesep \Nexpr} \parsesep \Tsemicolon &\\ +|\ & \Tvar \parsesep \Clisttwo{\Tidentifier} \parsesep \Tcolon \parsesep \Nty \parsesep \Tsemicolon &\\ +|\ & \Tprint \parsesep \Plist{\Nexpr} \parsesep \Tsemicolon &\\ +|\ & \Trepeat \parsesep \Nstmtlist \parsesep \Tuntil \parsesep \Nexpr \parsesep \Tsemicolon &\\ +|\ & \Tlooplimit \parsesep \Tlpar \parsesep \Nexpr \parsesep \Trpar \parsesep \Trepeat \parsesep \Nstmtlist \parsesep \Tuntil \parsesep \Nexpr \parsesep \Tsemicolon &\\ +|\ & \Tthrow \parsesep \Nexpr \parsesep \Tsemicolon &\\ +|\ & \Tthrow \parsesep \Tsemicolon &\\ +|\ & \Tpragma \parsesep \Tidentifier \parsesep \Clist{\Nexpr} \parsesep \Tsemicolon & +\end{flalign*} + +\hypertarget{def-nstmtlist}{} +\begin{flalign*} +\Nstmtlist \derivesinline\ & \nonemptylist{\Nstmt} & +\end{flalign*} + +\hypertarget{def-nselse}{} +\begin{flalign*} +\Nselse \derives\ & \Telseif \parsesep \Nexpr \parsesep \Tthen \parsesep \Nstmtlist \parsesep \Nselse &\\ +|\ & \Tpass &\\ +|\ & \Telse \parsesep \Nstmtlist & +\end{flalign*} + +\hypertarget{def-nlexpr}{} +\begin{flalign*} +\Nlexpr \derivesinline\ & \Nlexpratom &\\ +|\ & \Tminus &\\ +|\ & \Tlpar \parsesep \NClist{\Nlexpr} \parsesep \Trpar & +\end{flalign*} + +\hypertarget{def-nlexpratom}{} +\begin{flalign*} +\Nlexpratom \derives\ & \Tidentifier &\\ +|\ & \Nlexpratom \parsesep \Nslices &\\ +|\ & \Nlexpratom \parsesep \Tdot \parsesep \Tidentifier &\\ +|\ & \Nlexpratom \parsesep \Tdot \parsesep \Tlbracket \parsesep \Clist{{\Tidentifier}} \parsesep \Trbracket &\\ +|\ & \Tlbracket \parsesep \NClist{{\Nlexpratom}} \parsesep \Trbracket & +\end{flalign*} + +A $\Ndeclitem$ is another kind of left-hand-side expression, +which appears only in declarations. It cannot have setter calls or set record fields, +it must declare a new variable. +\hypertarget{def-ndeclitem}{} +\begin{flalign*} +\Ndeclitem \derives\ & \Nuntypeddeclitem \parsesep \Nasty&\\ +|\ & \Nuntypeddeclitem & +\end{flalign*} + +\hypertarget{def-nuntypeddeclitem}{} +\begin{flalign*} +\Nuntypeddeclitem \derivesinline\ & \Tidentifier &\\ +|\ & \Tminus &\\ +|\ & \Plisttwo{\Ndeclitem} & +\end{flalign*} + +\hypertarget{def-nintconstraintsopt}{} +\begin{flalign*} +\Nintconstraintsopt \derivesinline\ & \Nintconstraints \;|\; \emptysentence & +\end{flalign*} + +\hypertarget{def-nintconstraints}{} +\begin{flalign*} +\Nintconstraints \derivesinline\ & \Tlbrace \parsesep \NClist{\Nintconstraint} \parsesep \Trbrace & +\end{flalign*} + +\hypertarget{def-nintconstraint}{} +\begin{flalign*} +\Nintconstraint \derivesinline\ & \Nexpr &\\ +|\ & \Nexpr \parsesep \Tslicing \parsesep \Nexpr & +\end{flalign*} + +Pattern expressions ($\Nexprpattern$), given by the following derivations, is similar to regular expressions ($\Nexpr$), +except they do not derive tuples, which are the last derivation for $\Nexpr$. + +\hypertarget{def-nexprpattern}{} +\begin{flalign*} +\Nexprpattern \derives\ & \Nvalue &\\ + |\ & \Tidentifier &\\ + |\ & \Nexprpattern \parsesep \Nbinop \parsesep \Nexpr &\\ + |\ & \Nunop \parsesep \Nexpr & \precedence{\Tunops}\\ + |\ & \Tif \parsesep \Nexpr \parsesep \Tthen \parsesep \Nexpr \parsesep \Neelse &\\ + |\ & \Tidentifier \parsesep \Plist{\Nexpr} &\\ + |\ & \Nexprpattern \parsesep \Nslices &\\ + |\ & \Nexprpattern \parsesep \Tdot \parsesep \Tidentifier&\\ + |\ & \Nexprpattern \parsesep \Tdot \parsesep \Tlbracket \parsesep \NClist{\Tidentifier} \parsesep \Trbracket &\\ + |\ & \Tlbracket \parsesep \NClist{\Nexpr} \parsesep \Trbracket &\\ + |\ & \Nexprpattern \parsesep \Tas \parsesep \Nty &\\ + |\ & \Nexprpattern \parsesep \Tas \parsesep \Nintconstraints &\\ + |\ & \Nexprpattern \parsesep \Tin \parsesep \Npatternset &\\ + |\ & \Nexprpattern \parsesep \Tin \parsesep \Tmasklit &\\ + |\ & \Tunknown \parsesep \Tcolon \parsesep \Nty &\\ + |\ & \Tidentifier \parsesep \Tlbrace \parsesep \Clist{\Nfieldassign} \parsesep \Trbrace &\\ + |\ & \Tlpar \parsesep \Nexprpattern \parsesep \Trpar & +\end{flalign*} + +\hypertarget{def-npatternset}{} +\begin{flalign*} +\Npatternset \derivesinline\ & \Tbnot \parsesep \Tlbrace \parsesep \Npatternlist \parsesep \Trbrace &\\ + |\ & \Tlbrace \parsesep \Npatternlist \parsesep \Trbrace & +\end{flalign*} + +\hypertarget{def-npatternlist}{} +\begin{flalign*} +\Npatternlist \derivesinline\ & \NClist{\Npattern} & +\end{flalign*} + +\hypertarget{def-npattern}{} +\begin{flalign*} +\Npattern \derives\ & \Nexprpattern &\\ + |\ & \Nexprpattern \parsesep \Tslicing \parsesep \Nexpr &\\ + |\ & \Tminus &\\ + |\ & \Tleq \parsesep \Nexpr &\\ + |\ & \Tgeq \parsesep \Nexpr &\\ + |\ & \Tmasklit &\\ + |\ & \Plisttwo{\Npattern} &\\ + |\ & \Npatternset & +\end{flalign*} + +\hypertarget{def-nfields}{} +\begin{flalign*} +\Nfields \derivesinline\ & \Tlbrace \parsesep \TClist{\Ntypedidentifier} \parsesep \Trbrace & +\end{flalign*} + +\hypertarget{def-nfieldsopt}{} +\begin{flalign*} +\Nfieldsopt \derivesinline\ & \Nfields \;|\; \emptysentence & +\end{flalign*} + +\hypertarget{def-nnslices}{} +\begin{flalign*} +\Nnamedslices \derivesinline\ & \Tlbracket \parsesep \NClist{\Nslice} \parsesep \Trbracket & +\end{flalign*} + +\hypertarget{def-nslices}{} +\begin{flalign*} +\Nslices \derivesinline\ & \Tlbracket \parsesep \Clist{\Nslice} \parsesep \Trbracket & +\end{flalign*} + +\hypertarget{def-nslice}{} +\begin{flalign*} +\Nslice \derivesinline\ & \Nexpr &\\ + |\ & \Nexpr \parsesep \Tcolon \parsesep \Nexpr &\\ + |\ & \Nexpr \parsesep \Tpluscolon \parsesep \Nexpr &\\ + |\ & \Nexpr \parsesep \Tstarcolon \parsesep \Nexpr & +\end{flalign*} + +\hypertarget{def-nbitfields}{} +\begin{flalign*} +\Nbitfields \derivesinline\ & \Tlbrace \parsesep \TClist{\Nbitfield} \parsesep \Trbrace & +\end{flalign*} + +\hypertarget{def-nbitfield}{} +\begin{flalign*} +\Nbitfield \derivesinline\ & \Nnamedslices \parsesep \Tidentifier &\\ + |\ & \Nnamedslices \parsesep \Tidentifier \parsesep \Nbitfields &\\ + |\ & \Nnamedslices \parsesep \Tidentifier \parsesep \Tcolon \parsesep \Nty & +\end{flalign*} + +\hypertarget{def-nty}{} +\begin{flalign*} +\Nty \derives\ & \Tinteger \parsesep \Nintconstraintsopt &\\ + |\ & \Treal &\\ + |\ & \Tstring &\\ + |\ & \Tboolean &\\ + |\ & \Tbit &\\ + |\ & \Tbits \parsesep \Tlpar \parsesep \Nexpr \parsesep \Trpar \parsesep \maybeemptylist{\Nbitfields} &\\ + |\ & \Plist{\Nty} &\\ + |\ & \Tidentifier &\\ + |\ & \Tarray \parsesep \Tlbracket \parsesep \Nexpr \parsesep \Trbracket \parsesep \Tof \parsesep \Nty & +\end{flalign*} + +\hypertarget{def-ntydecl}{} +\begin{flalign*} +\Ntydecl \derives\ & \Nty &\\ + |\ & \Tenumeration \parsesep \Tlbrace \parsesep \NTClist{\Tidentifier} \parsesep \Trbrace &\\ + |\ & \Trecord \parsesep \Nfieldsopt &\\ + |\ & \Texception \parsesep \Nfieldsopt & +\end{flalign*} + +\hypertarget{def-nfieldassign}{} +\begin{flalign*} +\Nfieldassign \derivesinline\ & \Tidentifier \parsesep \Teq \parsesep \Nexpr & +\end{flalign*} + +\hypertarget{def-neelse}{} +\begin{flalign*} +\Neelse \derives\ & \Telse \parsesep \Nexpr &\\ + |\ & \Telseif \parsesep \Nexpr \parsesep \Tthen \parsesep \Nexpr \parsesep \Neelse & +\end{flalign*} + +\hypertarget{def-nexpr}{} +\begin{flalign*} +\Nexpr \derives\ & \Nvalue &\\ + |\ & \Tidentifier &\\ + |\ & \Nexpr \parsesep \Nbinop \parsesep \Nexpr &\\ + |\ & \Nunop \parsesep \Nexpr & \precedence{\Tunops}\\ + |\ & \Tif \parsesep \Nexpr \parsesep \Tthen \parsesep \Nexpr \parsesep \Neelse &\\ + |\ & \Tidentifier \parsesep \Plist{\Nexpr} &\\ + |\ & \Nexpr \parsesep \Nslices &\\ + |\ & \Nexpr \parsesep \Tdot \parsesep \Tidentifier&\\ + |\ & \Nexpr \parsesep \Tdot \parsesep \Tlbracket \parsesep \NClist{\Tidentifier} \parsesep \Trbracket &\\ + |\ & \Tlbracket \parsesep \NClist{\Nexpr} \parsesep \Trbracket &\\ + |\ & \Nexpr \parsesep \Tas \parsesep \Nty &\\ + |\ & \Nexpr \parsesep \Tas \parsesep \Nintconstraints &\\ + |\ & \Nexpr \parsesep \Tin \parsesep \Npatternset &\\ + |\ & \Nexpr \parsesep \Tin \parsesep \Tmasklit &\\ + |\ & \Tunknown \parsesep \Tcolon \parsesep \Nty &\\ + |\ & \Tidentifier \parsesep \Tlbrace \parsesep \Clist{\Nfieldassign} \parsesep \Trbrace &\\ + |\ & \Tlpar \parsesep \Nexpr \parsesep \Trpar &\\ + |\ & \Plisttwo{\Nexpr} & +\end{flalign*} + +\hypertarget{def-nvalue}{} +\begin{flalign*} +\Nvalue \derivesinline\ & \Tintlit &\\ + |\ & \Tboollit &\\ + |\ & \Treallit &\\ + |\ & \Tbitvectorlit &\\ + |\ & \Tstringlit & +\end{flalign*} + +\hypertarget{def-nunop}{} +\begin{flalign*} +\Nunop \derivesinline\ & \Tbnot \;|\; \Tminus \;|\; \Tnot & +\end{flalign*} + +\hypertarget{def-nbinop}{} +\begin{flalign*} +\Nbinop \derivesinline\ & \Tand \;|\; \Tband \;|\; \Tbor \;|\; \Tbeq \;|\; \Tdiv \;|\; \Tdivrm \;|\; \Txor \;|\; \Teqop \;|\; \Tneq &\\ + |\ & \Tgt \;|\; \Tgeq \;|\; \Timpl \;|\; \Tlt \;|\; \Tleq \;|\; \Tplus \;|\; \Tminus \;|\; \Tmod \;|\; \Tmul &\\ + |\ & \Tor \;|\; \Trdiv \;|\; \Tshl \;|\; \Tshr \;|\; \Tpow \;|\; \Tconcat +\end{flalign*} + +\section{Parse Trees \label{sec:ParseTrees}} +We now define \emph{parse trees} for the ASL expanded grammar. Those are later used for build Abstract Syntax Trees. + +\begin{definition}[Parse Trees] +A \emph{parse tree} has one of the following forms: +\begin{itemize} + \item A \emph{token node}, given by the token itself, for example, $\Tlexeme(\Tarrow)$ and $\Tidentifier(\id)$; + \item \hypertarget{def-epsilonnode}{} $\epsilonnode$, which represents the empty sentence --- $\emptysentence$. + \item A \emph{non-terminal node} of the form $N(n_{1..k})$ where $N$ is a non-terminal symbol, + which is said to label the node, + and $n_{1..k}$ are its children parse nodes, + for example, + $\Ndecl(\Tfunc, \Tidentifier(\id), \Nparamsopt, \Nfuncargs, \Nfuncbody)$ + is labeled by $\Ndecl$ and has five children nodes. +\end{itemize} +\end{definition} +(In the literature, parse trees are also referred to as \emph{derivation trees}.) + +\begin{definition}[Well-formed Parse Trees] +A parse tree is \emph{well-formed} if its root is labelled by the start non-terminal ($\Nast$ for ASL) +and each non-terminal node $N(n_{1..k})$ corresponds to a grammar derivation +$N \derives l_{1..k}$ where $l_i$ is the label of node $n_i$ if it is a non-terminal node and $n_i$ +itself when it is a token. +A non-terminal node $N(\epsilonnode)$ is well-formed if the grammar includes a derivation +$N \derives \emptysentence$. +\end{definition} + +\hypertarget{def-yield}{} +\begin{definition}[Parse Tree Yield] +The \emph{\yield} of a parse tree is the list of tokens +given by an in-order walk of the tree: +\[ +\yield(n) \triangleq \begin{cases} + [t] & n \text{ is a token }t\\ + \emptylist & n = \epsilonnode\\ + \yield(n_1) \concat \ldots \concat \yield(n_k) & n = N(n_{1..k})\\ +\end{cases} +\] +\end{definition} + +\hypertarget{def-parsenode}{} +We denote the set of well-formed parse trees for a non-terminal symbol $S$ by $\parsenode{S}$. + +\hypertarget{def-aslparse}{} +A parser is a function +\[ +\aslparse : (\Token^* \setminus \{\Terror\}) \aslto \parsenode{\Nast} \cup \{\ParseError\} +\] +\hypertarget{def-parseerror}{} +where $\ParseError$ stands for a \emph{parse error}. +If $\aslparse(\ts) = n$ then $\yield(n)=\ts$ +and if $\aslparse(\ts) = \ParseError$ then there is no well-formed tree +$n$ such that $\yield(n)=\ts$. +(Notice that we do not define a parser if $\ts$ is lexically illegal.) + +The \emph{language of a grammar} $G$ is defined as follows: +\[ +\Lang(G) = \{\yield(n) \;|\; n \text{ is a well-formed parse tree for }G\} \enspace. +\] + +\section{Priority and Associativity \label{sec:PriorityAndAssociativity}} +A context-free grammar $G$ is \emph{ambiguous} if there can be more than one parse tree for a given list of tokens +$\ts \in \Lang(G)$. +Indeed the expanded ASL grammar is ambiguous, for example, due to its definition of binary operation expressions. +To allow assigning a unique parse tree to each sequence of tokens in the language of the ASL grammar, +we utilize the standard technique of associating priority levels to productions and using them to resolve +any shift-reduce conflicts in the LR(1) parser associated with our grammar (our grammar does not have any +reduce-reduce conflicts). + +The priority of a grammar derivation is defined as the priority of its rightmost token. +Derivations that do not contain tokens do not require a priority as they do not induce shift-reduce conflicts. + +The table below assigns priorities to tokens in increasing order, starting from the lowest priority (for $\Telse$) +to the highest priority (for $\Tdot$). +When a shift-reduce conflict arises during the LR(1) grammar construction +it resolve in favor of the action (shift or reduce) associated with the derivation that has the higher priority. +If two derivations have the same priority due to them both having the same rightmost token, +the conflict is resolved based on the associativity associated with the token below: +reduce for $\leftassoc$, shift for $\rightassoc$, and a parsing error for $\nonassoc$. + +The two rules involving a unary minus operation are not assigned the priority level of $\Tminus$, +but rather then the priority level $\Tunops$, as denoted by the notation \\ +$\precedence{\Tunops}$ +appearing to their right. This is a standard way of dealing with a unary minus operation +in many programming languages, which involves defining an artificial token $\Tunops$, +which is never returned by the scanner. + +\begin{center} +\begin{tabular}{ll} +\textbf{Terminals} & \textbf{Associativity}\\ +\hline +\Telse & \nonassoc\\ +\Tbor, \Tband, \Timpl, \Tbeq, \Tas & \leftassoc\\ +\Teqop, \Tneq & \leftassoc\\ +\Tgt, \Tgeq, \Tlt, \Tleq & \nonassoc\\ +\Tplus, \Tminus, \Tor, \Txor, \Tand & \leftassoc\\ +\Tmul, \Tdiv, \Tdivrm, \Trdiv, \Tmod, \Tshl, \Tshr & \leftassoc\\ +\Tpow, \Tconcat & \leftassoc\\ +$\Tunops$ & \nonassoc\\ +\Tin & \nonassoc\\ +\Tdot, \Tlbracket & \leftassoc +\end{tabular} +\end{center} \ No newline at end of file diff --git a/asllib/doc/TypeAttributes.tex b/asllib/doc/TypeAttributes.tex new file mode 100644 index 000000000..d4d8b59c9 --- /dev/null +++ b/asllib/doc/TypeAttributes.tex @@ -0,0 +1,755 @@ +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +\section{Basic Type Attributes\label{sec:BasicTypeAttributes}} +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +This section defines some basic predicates for classifying types as well as +functions that inspect the structure of types: +\begin{itemize} + \item Builtin singular types (\secref{TypingRule.BuiltinSingularType}) + \item Builtin aggregate types (\secref{TypingRule.BuiltinAggregateType}) + \item Builtin types (\secref{TypingRule.BuiltinSingularOrAggregate}) + \item Named types (\secref{TypingRule.NamedType}) + \item Anonymous types (\secref{TypingRule.AnonymousType}) + \item Singular types (\secref{TypingRule.SingularType}) + \item Aggregate types (\secref{TypingRule.AggregateType}) + \item Non-primitive types (\secref{TypingRule.NonPrimitiveType}) + \item Primitive types (\secref{TypingRule.PrimitiveType}) + \item The structure of a type (\secref{TypingRule.structure}) + \item The underlying type of a type (\secref{anonymize}) + \item Checked constrained integers (\secref{TypingRule.CheckConstrainedInteger}) + \item Constrained types (\secref{ConstrainedTypes}) +\end{itemize} + +\subsection{TypingRule.BuiltinSingularType \label{sec:TypingRule.BuiltinSingularType}} +\hypertarget{def-isbuiltinsingular}{} +The predicate +\[ + \isbuiltinsingular(\overname{\ty}{\tty}) \;\aslto\; \Bool +\] +tests whether the type $\tty$ is a \emph{builtin singular type}. + +\subsubsection{Prose} +The \emph{builtin singular types} are: +\begin{itemize} +\item \texttt{integer}; +\item \texttt{real}; +\item \texttt{string}; +\item \texttt{boolean}; +\item \texttt{bits} (which also represents \texttt{bit}, as a special case); +\item \texttt{enumeration}. +\end{itemize} + +\subsubsection{Example} +In this example: +\VerbatimInput[firstline=3,lastline=8]{\typingtests/TypingRule.BuiltinSingularTypes.asl} + +Variables of builtin singular types \texttt{integer}, \texttt{real}, +\texttt{boolean}, \texttt{bits(4)}, \\ and~\texttt{bits(2)} are defined. + +\subsubsection{Example} +\VerbatimInput{\typingtests/TypingRule.EnumerationType.asl} +The builtin singular type \texttt{Color} consists in two constants +\texttt{RED}, and~\texttt{BLACK}. + +\CodeSubsection{\BuiltinSingularBegin}{\BuiltinSingularEnd}{../types.ml} + +\subsubsection{Formally} +\begin{mathpar} +\inferrule{ + \vb \eqdef \astlabel(\tty) \in \{\TReal, \TString, \TBool, \TBits, \TEnum, \TInt\} +}{ + \isbuiltinsingular(\tty) \typearrow \vb +} +\end{mathpar} + +\isempty{\subsubsection{Comments}} +\lrmcomment{This is related to \identd{PQCK} and \identd{NZWT}.} + +\subsection{TypingRule.BuiltinAggregateType \label{sec:TypingRule.BuiltinAggregateType}} +\hypertarget{def-isbuiltinaggregate}{} +The predicate +\[ + \isbuiltinaggregate(\overname{\ty}{\tty}) \;\aslto\; \Bool +\] +tests whether the type $\tty$ is a \emph{builtin aggregate type}. + +\subsubsection{Prose} +The builtin aggregate types are: +\begin{itemize} +\item tuple; +\item \texttt{array}; +\item \texttt{record}; +\item \texttt{exception}. +\end{itemize} + +\subsubsection{Example} +\VerbatimInput{\typingtests/TypingRule.BuiltinAggregateTypes.asl} +Type \texttt{Pair} is the type of integer and boolean pairs. + +Arrays are declared with indices that are either integer-typed +or enumeration-typed. In the example above, \texttt{T} is +declared as an array with an integer-typed index (as indicated +by the used of the integer-typed constant \texttt{3}) whereas +\texttt{PointArray} is declared with the index of +\texttt{Coord}, which is an enumeration type. + +Arrays declared with integer-typed indices can be accessed only by integers ranging from $0$ to +the size of the array minus $1$. In the example above, $\texttt{T}$ can be accessed with +one of $0$, $1$, and $2$. + +Arrays declared with an enumeration-typed index can only be accessed with labels from the corresponding +enumeration. In the example above, \texttt{PointArray} can only be accessed with one of the labels +\texttt{CX}, \texttt{CY}, and \texttt{CZ}. + +The (builtin aggregate) type \verb|{ x : real, y : real, z : real }| is a record type with three fields +\texttt{x}, \texttt{y} and \texttt{z}. + +\subsubsection{Example} +\VerbatimInput{\typingtests/TypingRule.BuiltinExceptionType.asl} +Two (builtin aggregate) exception types are defined: +\begin{itemize} +\item \verb|exception{}| (for \texttt{Not\_found}), which carries no value; and +\item \verb|exception { message:string }| (for \texttt{SyntaxException}), which carries a message. +\end{itemize} +Notice the similarity with record types and that the empty field list \verb|{}| can be +omitted in type declarations, as is the case for \texttt{Not\_found}. + +\CodeSubsection{\BuiltinAggregateBegin}{\BuiltinAggregateEnd}{../types.ml} + +\subsubsection{Formally} +\begin{mathpar} +\inferrule{ \vb \eqdef \astlabel(\tty) \in \{\TTuple, \TArray, \TRecord, \TException\} } +{ \isbuiltinaggregate(\tty) \typearrow \vb } +\end{mathpar} + +\isempty{\subsubsection{Comments}} +\lrmcomment{This is related to \identd{PQCK} and \identd{KNBD}.} + +\subsection{TypingRule.BuiltinSingularOrAggregate \label{sec:TypingRule.BuiltinSingularOrAggregate}} +\hypertarget{def-isbuiltin}{} +The predicate +\[ + \isbuiltin(\overname{\ty}{\tty}) \;\aslto\; \Bool +\] +tests whether the type $\tty$ is a \emph{builtin type}. + +\subsubsection{Prose} +$\tty$ is a builtin type and one of the following applies: +\begin{itemize} +\item $\tty$ is singular; +\item $\tty$ is builtin aggregate. +\end{itemize} + +\subsubsection{Example} +In the specification +\begin{verbatim} + type ticks of integer; +\end{verbatim} +the type \texttt{integer} is a builtin type but the type of \texttt{ticks} is not. + +\CodeSubsection{\BuiltinSingularOrAggregateBegin}{\BuiltinSingularOrAggregateEnd}{../types.ml} + +\subsubsection{Formally} +\begin{mathpar} + \inferrule{ + \isbuiltinsingular(\tty) \typearrow \vbone\\ + \isbuiltinaggregate(\tty) \typearrow \vbtwo + }{ + \isbuiltin(\tty) \typearrow \vbone \lor \vbtwo + } +\end{mathpar} + +\isempty{\subsubsection{Comments}} + +\subsection{TypingRule.NamedType \label{sec:TypingRule.NamedType} } +\hypertarget{def-isnamed}{} +The predicate +\[ + \isnamed(\overname{\ty}{\tty}) \;\aslto\; \Bool +\] +tests whether the type $\tty$ is a \emph{named type}. + +Enumeration types, record types, and exception types must be declared +and associated with a named type. + +\subsubsection{Prose} +A named type is a type that is declared by using the \texttt{type of} syntax. + +\subsubsection{Example} +In the specification +\begin{verbatim} + type ticks of integer; +\end{verbatim} +\texttt{ticks} is a named type. + +\CodeSubsection{\NamedBegin}{\NamedEnd}{../types.ml} + +\subsubsection{Formally} +\begin{mathpar} +\inferrule{ + \vb \eqdef \astlabel(\tty) = \TNamed +}{ + \isnamed(\tty) \typearrow \vb +} +\end{mathpar} + +\isempty{\subsubsection{Comments}} +\lrmcomment{This is related to \identd{vmzx}.} + +\subsection{TypingRule.AnonymousType \label{sec:TypingRule.AnonymousType}} +\hypertarget{def-isanonymous}{} +The predicate +\[ + \isanonymous(\overname{\ty}{\tty}) \;\aslto\; \Bool +\] +tests whether the type $\tty$ is an \anonymoustype. + +\subsubsection{Prose} +\Anonymoustypes\ are types that are not declared using the type syntax: +integer types, the real type, the string type, the Boolean type, +bitvector types, tuple types, and array types. + +\subsubsection{Example} +The tuple type \texttt{(integer, integer)} is an \anonymoustype. + +\CodeSubsection{\AnonymousBegin}{\AnonymousEnd}{../types.ml} + +\subsubsection{Formally} +\begin{mathpar} +\inferrule{ \vb \eqdef \astlabel(\tty) \neq \TNamed +} +{ + \isanonymous(\tty) \typearrow \vb +} +\end{mathpar} + +\isempty{\subsubsection{Comments}} +\lrmcomment{This is related to \identd{VMZX}.} + +\subsection{TypingRule.SingularType \label{sec:TypingRule.SingularType}} +\hypertarget{def-issingular}{} +The predicate +\[ + \issingular(\overname{\staticenvs}{\tenv} \aslsep \overname{\ty}{\tty}) \;\aslto\; + \overname{\Bool}{\vb} \cup \overname{\TTypeError}{\TypeErrorConfig} +\] +tests whether the type $\tty$ is a \emph{singular type} in the static environment $\tenv$. + +\subsubsection{Prose} +A type $\tty$ is singular if and only if all of the following apply: +\begin{itemize} + \item obtaining the \underlyingtype\ of $\tty$ in the environment $\tenv$ yields $\vtone$\ProseOrTypeError; + \item $\vtone$ is a builtin singular type. +\end{itemize} + +\subsubsection{Example} +In the following example, the types \texttt{A}, \texttt{B}, and \texttt{C} are all singular types: +\begin{verbatim} +type A of integer; +type B of A; +type C of B; +\end{verbatim} + +\CodeSubsection{\SingularBegin}{\SingularEnd}{../types.ml} + +\subsubsection{Formally} +\begin{mathpar} +\inferrule{ + \makeanonymous(\tenv, \tty) \typearrow \vtone \OrTypeError\\\\ + \isbuiltinsingular(\vtone) \typearrow \vb +}{ +\issingular(\tenv, \tty) \typearrow \vb +} +\end{mathpar} + +\isempty{\subsubsection{Comments}} +\lrmcomment{This is related to \identr{GVZK}.} + +\subsection{TypingRule.AggregateType \label{sec:TypingRule.AggregateType}} +\hypertarget{def-isbuiltinaggregate}{} +The predicate +\[ + \isaggregate(\overname{\staticenvs}{\tenv} \aslsep \overname{\ty}{\tty}) \;\aslto\; + \overname{\Bool}{\vb} \cup \overname{\TTypeError}{\TypeErrorConfig} +\] +tests whether the type $\tty$ is an \emph{aggregate type} in the static environment $\tenv$. + +\subsubsection{Prose} +A type $\tty$ is aggregate in an environment $\tenv$ if and only if all of the following apply: +\begin{itemize} + \item obtaining the \underlyingtype\ of $\tty$ in the environment $\tenv$ yields $\vtone$\ProseOrTypeError; + \item $\vtone$ is a builtin aggregate. +\end{itemize} + +\subsubsection{Example} +In the following example, the types \texttt{A}, \texttt{B}, and \texttt{C} are all aggregate types: +\begin{verbatim} +type A of (integer, integer); +type B of A; +type C of B; +\end{verbatim} + +\CodeSubsection{\AggregateBegin}{\AggregateEnd}{../types.ml} + +\subsubsection{Formally} +\begin{mathpar} +\inferrule{ + \makeanonymous(\tenv, \tty) \typearrow \vtone \OrTypeError\\\\ + \isbuiltinaggregate(\vtone) \typearrow \vb +}{ + \isaggregate(\tenv, \tty) \typearrow \vb +} +\end{mathpar} + +\isempty{\subsubsection{Comments}} +\lrmcomment{This is related to \identr{GVZK}.} + +\subsection{TypingRule.StructuredType \label{sec:TypingRule.StructuredType}} +\hypertarget{def-isstructured}{} +\hypertarget{def-structuredtype}{} +A \emph{\structuredtype} is any type that consists of a list of field identifiers +that denote individual storage elements. In ASL there are two such types --- record types and exception types. + +The predicate +\[ + \isstructured(\overname{\ty}{\tty}) \;\aslto\; \overname{\Bool}{\vb} +\] +tests whether the type $\tty$ is a \structuredtype\ and yields the result in $\vb$. + +\subsubsection{Prose} +The result $\vb$ is $\True$ if and only if $\tty$ is either a record type or an exception type, +which is determined via the AST label of $\tty$. + +\subsubsection{Example} +In the following example, the types \texttt{SyntaxException} and \texttt{PointRecord} +are each an example of a \structuredtype: +\begin{verbatim} +type SyntaxException of exception {message: string }; +type PointRecord of Record {x : real, y: real, z: real}; +\end{verbatim} + +\subsubsection{Formally} +\begin{mathpar} +\inferrule{}{ + \isstructured(\tty) \typearrow \overname{\astlabel(\tty) \in \{\TRecord, \TException\}}{\vb} +} +\end{mathpar} + +\isempty{\subsubsection{Comments}} +\lrmcomment{This is related to \identd{WGQS}, \identd{QXYC}.} + +\subsection{TypingRule.NonPrimitiveType \label{sec:TypingRule.NonPrimitiveType}} +\hypertarget{def-isnonprimitive}{} +The predicate +\[ + \isnonprimitive(\overname{\ty}{\tty}) \;\aslto\; \overname{\Bool}{\vb} +\] +tests whether the type $\tty$ is a \emph{non-primitive type}. + +\subsubsection{Prose} +One of the following applies: +\begin{itemize} + \item All of the following apply (\textsc{singular}): + \begin{itemize} + \item $\tty$ is a builtin singular type; + \item $\vb$ is $\False$. + \end{itemize} + \item All of the following apply (\textsc{named}): + \begin{itemize} + \item $\tty$ is a named type; + \item $\vb$ is $\True$. + \end{itemize} + \item All of the following apply (\textsc{tuple}): + \begin{itemize} + \item $\tty$ is a tuple type $\vli$; + \item $\vb$ is $\True$ if and only if there exists a non-primitive type in $\vli$. + \end{itemize} + \item All of the following apply (\textsc{array}): + \begin{itemize} + \item $\tty$ is an array of type $\tty'$ + \item $\vb$ is $\True$ if and only if $\tty'$ is non-primitive. + \end{itemize} + \item All of the following apply (\textsc{structured}): + \begin{itemize} + \item $\tty$ is a \structuredtype\ with fields $\fields$; + \item $\vb$ is $\True$ if and only if there exists a non-primitive type in $\fields$. + \end{itemize} +\end{itemize} + +\subsubsection{Example} +The following types are non-primitive: + +\begin{tabular}{ll} +\textbf{Type definition} & \textbf{Reason for being non-primitive}\\ +\hline +\texttt{type A of integer} & Named types are non-primitive\\ +\texttt{(integer, A)} & The second component, \texttt{A}, has non-primitive type\\ +\texttt{array[6] of A} & Element type \texttt{A} has a non-primitive type\\ +\verb|record { a : A }| & The field \texttt{a} has a non-primitive type +\end{tabular} + +\CodeSubsection{\NonPrimitiveBegin}{\NonPrimitiveEnd}{../types.ml} + +\subsubsection{Formally} +The cases \textsc{tuple} and \textsc{structured} below, use the notation $\vb_\vt$ to name +Boolean variables by using the types denoted by $\vt$ as a subscript. +\begin{mathpar} +\inferrule[singular]{ + \astlabel(\tty) \in \{\TReal, \TString, \TBool, \TBits, \TEnum, \TInt\} +}{ + \isnonprimitive(\tty) \typearrow \False +} +\end{mathpar} + +\begin{mathpar} +\inferrule[named]{\astlabel(\tty) = \TNamed}{\isnonprimitive(\tty) \typearrow \True} +\end{mathpar} + +\begin{mathpar} +\inferrule[tuple]{ + \vt \in \tys: \isnonprimitive(\vt) \typearrow \vb_{\vt}\\ + \vb \eqdef \bigvee_{\vt \in \tys} \vb_{\vt} +}{ + \isnonprimitive(\overname{\TTuple(\tys)}{\tty}) \typearrow \vb +} +\end{mathpar} + +\begin{mathpar} +\inferrule[array]{ + \isnonprimitive(\tty') \typearrow \vb +}{ + \isnonprimitive(\overname{\TArray(\Ignore, \tty')}{\tty}) \typearrow \vb +} +\end{mathpar} + +\begin{mathpar} +\inferrule[structured]{ + L \in \{\TRecord, \TException\}\\ + (\Ignore,\vt) \in \fields : \isnonprimitive(\vt) \typearrow \vb_\vt\\ + \vb \eqdef \bigvee_{\vt \in \vli} \vb_{\vt} +}{ + \isnonprimitive(\overname{L(\fields)}{\tty}) \typearrow \vb +} +\end{mathpar} + +\isempty{\subsubsection{Comments}} +\lrmcomment{This is related to \identd{GWXK}.} + +\subsection{TypingRule.PrimitiveType \label{sec:TypingRule.PrimitiveType}} +\hypertarget{def-isprimitive}{} +The predicate +\[ + \isprimitive(\overname{\ty}{\tty}) \;\aslto\; \Bool +\] +tests whether the type $\tty$ is a \emph{primitive type}. + +\subsubsection{Prose} +A type $\tty$ is primitive if it is not non-primitive. + +\subsubsection{Example} +The following types are primitive: + +\begin{tabular}{ll} +\textbf{Type definition} & \textbf{Reason for being primitive}\\ +\hline +\texttt{integer} & Integers are primitive\\ +\texttt{(integer, integer)} & All tuple elements are primitive\\ +\texttt{array[5] of integer} & The array element type is primitive\\ +\verb|record {ticks : integer}| & The single field \texttt{ticks} has a primitive type +\end{tabular} + +\CodeSubsection{\PrimitiveBegin}{\PrimitiveEnd}{../types.ml} + +\subsubsection{Formally} +\begin{mathpar} +\inferrule{ + \isnonprimitive(\tty) \typearrow \vb +}{ + \isprimitive(\tty) \typearrow \neg\vb +} +\end{mathpar} + +\isempty{\subsubsection{Comments}} +\lrmcomment{This is related to \identd{GWXK}.} + +\subsection{TypingRule.Structure\label{sec:TypingRule.structure}} +\hypertarget{def-structure}{} +The function +\[ + \tstruct(\overname{\staticenvs}{\tenv} \aslsep \overname{\ty}{\tty}) \aslto \overname{\ty}{\vt} \cup \overname{\TTypeError}{\TypeErrorConfig} +\] +assigns a type to its \hypertarget{def-tstruct}{\emph{\structure}}, which is the type formed by +recursively replacing named types by their type definition in the static environment $\tenv$. +If a named type is not associated with a declared type in $\tenv$, a type error is returned. + +TypingRule.Specification ensures the absence of circular type definitions, +which ensures that TypingRule.Structure terminates\footnote{In mathematical terms, +this ensures that TypingRule.Structure is a proper \emph{structural induction.}}. + +\subsubsection{Prose} +One of the following applies: +\begin{itemize} +\item All of the following apply (\textsc{named}): + \begin{itemize} + \item $\tty$ is a named type $\vx$; + \item obtaining the declared type associated with $\vx$ in the static environment $\tenv$ yields $\vtone$\ProseOrTypeError; + \item obtaining the structure of $\vtone$ static environment $\tenv$ yields $\vt$\ProseOrTypeError; + \end{itemize} +\item All of the following apply (\textsc{builtin\_singular}): + \begin{itemize} + \item $\tty$ is a builtin singular type; + \item $\vt$ is $\tty$. + \end{itemize} +\item All of the following apply (\textsc{tuple}): + \begin{itemize} + \item $\tty$ is a tuple type with list of types $\tys$; + \item the types in $\tys$ are indexed as $\vt_i$, for $i=1..k$; + \item obtaining the structure of each type $\vt_i$, for $i=1..k$, in $\tys$ in the static environment $\tenv$, + yields $\vtp_i$\ProseOrTypeError; + \item $\vt$ is a tuple type with the list of types $\vtp_i$, for $i=1..k$. + \end{itemize} +\item All of the following apply (\textsc{array}): + \begin{itemize} + \item $\tty$ is an array type of length $\ve$ with element type $\vt$; + \item obtaining the structure of $\vt$ yields $\vtone$\ProseOrTypeError; + \item $\vt$ is is an array type with of length $\ve$ with element type $\vtone$. + \end{itemize} +\item All of the following apply (\textsc{structured}): + \begin{itemize} + \item $\tty$ is a \structuredtype\ with fields $\fields$; + \item obtaining the structure for each type $\vt$ associated with field $\id$ yields a type $\vt_\id$\ProseOrTypeError; + \item $\vt$ is a record or an exception, in correspondence to $\tty$, with the list of pairs $(\id, \vt\_\id)$; + \end{itemize} +\end{itemize} + +\subsubsection{Example} +In this example: +\texttt{type T1 of integer;} is the named type \texttt{T1} +whose structure is \texttt{integer}. + +In this example: +\texttt{type T2 of (integer, T1);} +is the named type \texttt{T2} whose structure is (integer, integer). In this +example, \texttt{(integer, T1)} is non-primitive since it uses \texttt{T1}, which is builtin aggregate. + +In this example: +\texttt{var x: T1;} +the type of $\vx$ is the named (hence non-primitive) type \texttt{T1}, whose structure +is \texttt{integer}. + +In this example: +\texttt{var y: integer;} +the type of \texttt{y} is the anonymous primitive type \texttt{integer}. + +In this example: +\texttt{var z: (integer, T1);} +the type of \texttt{z} is the anonymous non-primitive type +\texttt{(integer, T1)} whose structure is \texttt{(integer, integer)}. + +\CodeSubsection{\StructureBegin}{\StructureEnd}{../types.ml} + +\subsubsection{Formally} +\begin{mathpar} +\inferrule[named]{ + \declaredtype(\tenv, \vx) \typearrow \vtone \OrTypeError\\\\ + \tstruct(\tenv, \vtone)\typearrow\vt \OrTypeError +}{ + \tstruct(\tenv, \TNamed(\vx)) \typearrow \vt +} +\and +\inferrule[builtin\_singular]{ + \isbuiltinsingular(\tty) \typearrow \True +}{ + \tstruct(\tenv, \tty) \typearrow \tty +} +\and +\inferrule[tuple]{ + \tys \eqname \vt_{1..k}\\ + i=1..k: \tstruct(\tenv, \vt_i) \typearrow \vtp_i \OrTypeError +}{ + \tstruct(\tenv, \TTuple(\tys)) \typearrow \TTuple(i=1..k: \vtp_i) +} +\and +\inferrule[array]{ + \tstruct(\tenv, \vt) \typearrow \vtone \OrTypeError +}{ + \tstruct(\tenv, \TArray(\ve, \vt)) \typearrow \TArray(\ve, \vtone) +} +\and +\inferrule[structured]{ + L \in \{\TRecord, \TException\}\\\\ + (\id,\vt) \in \fields : \tstruct(\tenv, \vt) \typearrow \vt_\id \OrTypeError +}{ + \tstruct(\tenv, L(\fields)) \typearrow + L([ (\id,\vt) \in \fields : (\id,\vt_\id) ]) +} +\end{mathpar} + +\isempty{\subsubsection{Comments}} +\lrmcomment{This is related to \identd{FXQV}.} + +\subsection{TypingRule.Anonymize \label{sec:anonymize}} +\hypertarget{def-makeanonymous}{} +\hypertarget{def-underlyingtype}{} +The function +\[ + \makeanonymous(\overname{\staticenvs}{\tenv} \aslsep \overname{\ty}{\tty}) \aslto \overname{\ty}{\vt} \cup \overname{\TTypeError}{\TypeErrorConfig} +\] +returns the \emph{\underlyingtype} --- $\vt$ --- of the type $\tty$ in the static environment $\tenv$ or a type error. +Intuitively, $\tty$ is the first non-named type that is used to define $\tty$. Unlike $\tstruct$, +$\makeanonymous$ replaces named types by their definition until the first non-named type is found but +does not recurse further. + +\subsubsection{Prose} +One of the following applies: +\begin{itemize} + \item All of the following apply (\textsc{named}): + \begin{itemize} + \item $\tty$ is a named type $\vx$; + \item obtaining the type declared for $\vx$ yields $\vtone$\ProseOrTypeError; + \item the \underlyingtype\ of $\vtone$ is $\vt$. + \end{itemize} + + \item All of the following apply (\textsc{non-named}): + \begin{itemize} + \item $\tty$ is not a named type $\vx$; + \item $\vt$ is $\tty$. + \end{itemize} +\end{itemize} + +\subsubsection{Example} +Consider the following example: +\begin{verbatim} +type T1 of integer; +type T2 of T1; +type T3 of (integer, T2); +\end{verbatim} + +The underlying types of \texttt{integer}, \texttt{T1}, and \texttt{T2} is \texttt{integer}. + +The underlying type of \texttt{(integer, T2)} and \texttt{T3} is +\texttt{(integer, T2)}. Notice how the underlying type does not replace +\texttt{T2} with its own underlying type, in contrast to the structure of +\texttt{T2}, which is \texttt{(integer, integer)}. + +\CodeSubsection{\AnonymizeBegin}{\AnonymizeEnd}{../types.ml} + +\subsubsection{Formally} +\begin{mathpar} +\inferrule[named]{ + \tty \eqname \TNamed(\vx) \\ + \declaredtype(\tenv, \vx) \typearrow \vtone \OrTypeError \\\\ + \makeanonymous(\tenv, \vtone) \typearrow \vt +}{ + \makeanonymous(\tenv, \tty) \typearrow \vt +} +\and +\inferrule[non-named]{ + \astlabel(\tty) \neq \TNamed +}{ + \makeanonymous(\tenv, \tty) \typearrow \tty +} +\end{mathpar} + +\isempty{\subsubsection{Comments}} + +\subsection{TypingRule.CheckConstrainedInteger \label{sec:TypingRule.CheckConstrainedInteger}} +\hypertarget{def-checkconstrainedinteger}{} +The function +\[ + \checkconstrainedinteger(\overname{\staticenvs}{\tenv} \aslsep \overname{\ty}{\tty}) \aslto \{\True\} \cup \overname{\TTypeError}{\TypeErrorConfig} +\] +checks whether the type $\vt$ is a \constrainedinteger. If so, the result is $\True$, otherwise a type error is returned. + +\subsubsection{Prose} +One of the following applies: +\begin{itemize} + \item All of the following apply (\textsc{well-constrained}): + \begin{itemize} + \item $\vt$ is a well-constrained integer; + \item the result is $\True$. + \end{itemize} + + \item All of the following apply (\textsc{parameterized}): + \begin{itemize} + \item $\vt$ is a \parameterizedintegertype; + \item the result is $\True$. + \end{itemize} + + \item All of the following apply (\textsc{unconstrained}): + \begin{itemize} + \item $\vt$ is an unconstrained integer; + \item the result is a type error indicating that a constrained integer type is expected. + \end{itemize} + + \item All of the following apply (\textsc{conflicting\_type}): + \begin{itemize} + \item $\vt$ is not an integer type; + \item the result is a type error indicating the type conflict. + \end{itemize} +\end{itemize} + +\isempty{\subsubsection{Example}} + +\CodeSubsection{\CheckConstrainedIntegerBegin}{\CheckConstrainedIntegerEnd}{../Typing.ml} + +\subsubsection{Formally} +\begin{mathpar} +\inferrule[well-constrained]{} +{ + \checkconstrainedinteger(\tenv, \TInt(\wellconstrained(\Ignore))) \typearrow \True +} +\and +\inferrule[parameterized]{} +{ + \checkconstrainedinteger(\tenv, \TInt(\parameterized(\Ignore))) \typearrow \True +} +\and +\inferrule[unconstrained]{} +{ + \checkconstrainedinteger(\tenv, \TInt(\unconstrained(\Ignore))) \typearrow \\ + \TypeErrorVal{ConstrainedIntegerExpected} +} +\and +\inferrule[conflicting\_type]{ + \astlabel(\vt) \neq \TInt +}{ + \checkconstrainedinteger(\tenv, \vt) \typearrow \TypeErrorVal{TypeConflict} +} +\end{mathpar} + +\section{Constrained Types\label{sec:ConstrainedTypes}} +\begin{itemize} + \item A \emph{constrained type} is a type whose definition is parameterized by an expression. + In ASL only integer types and bitvector types can be constrained. + \item A type which is not constrained is \emph{unconstrained}. + \item A constrained type with a non-empty constraint is \emph{well-constrained}. + \hypertarget{def-parameterizedintegertype} + \item A \emph{\parameterizedintegertype} is an implicit type of a subprogram parameter. + \end{itemize} +The widths of bitvector storage elements are constrained integers. + +\hypertarget{def-isunconstrainedinteger}{} +\hypertarget{def-isparameterizedinteger}{} +\hypertarget{def-iswellconstrainedinteger}{} +We use the following helper predicates to classify integer types: +\[ + \begin{array}{rcl} + \isunconstrainedinteger(\overname{\ty}{\vt}) &\aslto& \Bool\\ + \isparameterizedinteger(\overname{\ty}{\vt}) &\aslto& \Bool\\ + \iswellconstrainedinteger(\overname{\ty}{\vt}) &\aslto& \Bool + \end{array} +\] +Those are defined as follows: +\[ + \begin{array}{rcl} + \isunconstrainedinteger(\vt) &\triangleq& \vt = \TInt(c) \land \astlabel(c)=\unconstrained\\ + \isparameterizedinteger(\vt) &\triangleq& \vt = \TInt(c) \land \astlabel(c)=\parameterized\\ + \iswellconstrainedinteger(\vt) &\triangleq& \vt = \TInt(c) \land \astlabel(c)=\wellconstrained\\ +\end{array} +\]\lrmcomment{This is related to \identd{ZTPP}, \identr{WJYH}, \identr{HJPN}, \identr{CZTX}, \identr{TPHR}.} + +\paragraph{Shorthand Notations:} + +\hypertarget{def-unconstrainedinteger}{} +We use the shorthand notation $\unconstrainedinteger$ to denote the unconstrained integer type: $\TInt(\unconstrained)$. diff --git a/asllib/doc/TypeChecking.tex b/asllib/doc/TypeChecking.tex new file mode 100644 index 000000000..4eab729c7 --- /dev/null +++ b/asllib/doc/TypeChecking.tex @@ -0,0 +1,191 @@ +\chapter{Type Inference and Type-checking Definitions\label{chap:TypeChecking}} + +The purpose of the ASL type system is to describe, in a formal and authoritative way, +which ASL specifications are considered \emph{well-typed}. +Whether a specification is well-typed is defined in terms of a \emph{type system}~\cite{TypeSystemsLucaCardelli}. +That is, a set of \emph{typing rules}. +Typing a specification consists of annotating the root of its AST with the rules defined +in the remainder of this document. + +An ASL parser accepts an ASL specification and checks whether it is valid with respect to the syntax of ASL, +which is defined in \secref{ASLGrammar}. +If the specification is syntactically valid, the parser returns an \emph{abstract syntax tree} (AST, for short), +which represents the specification as a labelled structured tree. Otherwise, it returns a syntax error. +When an ASL specification is successfully parsed, we refer to the resulting AST as the \emph{untyped AST}. + +A \emph{type checker} is an implementation of the ASL type system, which accepts an untyped AST and applies the +rules of the type system to the untyped AST. If it is successful, the specification +is considered \emph{well-typed} and the result is a pair consisting of +a \emph{static environment} and a \emph{typed AST}, +which are used in defining the ASL semantics (\chapref{Semantics}). +Otherwise, the type checker returns a type error. + +\hypertarget{def-annotaterel}{} +The type system of ASL is given by the relation $\annotaterel$, which is defined as the disjoint union +of the functions and relations defined in this reference. +The functions and relations in this reference are defined, in turn, via type system rules. + +Types are represented by respective Abstract Syntax Trees derived from the non-terminal $\ty$. +Throughout this document we use $\tty$ to denote a type variable, which should not be confused with the abstract syntax variable $\ty$. + +\section{Static Environments \label{sec:StaticEnvironments}} + +A \emph{static environment} (also called a \emph{type environment}) is what the typing rules operate over: +a structure, which amongst other things, associates types to variables. +Intuitively, the typing of a specification makes an initial environment evolve, with new types as given by the +variable declarations of the specification. + +\begin{definition} +\hypertarget{def-staticenvs}{} +Static environments, denoted as $\staticenvs$, are defined as follows (referring to symbols defined by the abstract syntax): +\[ +\begin{array}{rcl} +\staticenvs &\triangleq& \globalstaticenvs \times \localstaticenvs \hypertarget{def-globalstaticenvs}{}\\ +\\ +\globalstaticenvs &\triangleq& \left[ +\begin{array}{lcl} + \declaredtypes &\mapsto& \identifier \partialto \ty,\\ + \constantvalues &\mapsto& \identifier \partialto \literal,\\ + \globalstoragetypes &\mapsto& \identifier \partialto \ty \times \globaldeclkeyword,\\ + \exprequiv &\mapsto& \identifier \partialto \expr,\\ + \subtypes &\mapsto& \identifier \partialto \identifier,\\ + \subprograms &\mapsto& \identifier \partialto \func,\\ + \subprogramrenamings &\mapsto& \identifier \rightarrow \pow{\Strings} +\end{array} +\right]\\ +\hypertarget{def-localstaticenvs}{}\\ +\localstaticenvs &\triangleq& \left[ +\begin{array}{lcl} + \constantvalues &\mapsto& \identifier \partialto \literal,\\ + \localstoragetypes &\mapsto& \identifier \partialto \ty \times \globaldeclkeyword,\\ + \exprequiv &\mapsto& \identifier \partialto \expr,\\ + \returntype &\mapsto& \langle \ty \rangle +\end{array} +\right]\\ +\end{array} +\] +\end{definition} + +We use $\tenv$ and similar variable names (for example, $\tenvone$ and $\newtenv$) to range over static environments. + +A static environment $\tenv=(G^\tenv, L^\tenv)$ consists of two +distinct components: the global environment $G^\tenv \in \globalstaticenvs$ --- pertaining to AST nodes +appearing outside of a given subprogram, and the local environment +$L^\tenv \in \localstaticenvs$ --- pertaining to AST nodes appearing inside a given subprogram. +This separation allows us to type-check subprograms by using an empty local environment. + +The intuitive meaning of each component is as follows: +\begin{itemize} + \hypertarget{def-declaredtypes}{} + \item $\declaredtypes$ assigns types to their declared names; + \hypertarget{def-constantvalues}{} + \item $\constantvalues$ assigns literals to their declaring (constant) names; + \hypertarget{def-globalstoragetypes}{} + \item $\globalstoragetypes$ associates names of global storage elements to their inferred type + and how they were declared --- as constants, configuration variables, \texttt{let} variables, + or mutable variables; + \hypertarget{def-localstoragetypes}{} + \item $\localstoragetypes$ associates names of local storage elements to their inferred type + and how they were declared --- as variables, constants, or as \texttt{let} variables; + \hypertarget{def-exprequiv}{} + \item $\exprequiv$ associates names of immutable storage elements to a simplified version + of their initializing expression; + \hypertarget{def-subtypes}{} + \item $\subtypes$ associates type names to the names that their type subtypes; + \hypertarget{def-subprograms}{} + \item $\subprograms$ associates names of subprograms to the $\func$ AST node they were + declared with; + \hypertarget{def-subprogramrenamings}{} + \item $\subprogramrenamings$ associates names of subprograms to the set of overloading + subprograms --- $\func$ AST nodes that share the same name; + \hypertarget{def-returntype}{} + \item $\returntype$ contains the name of the type that a subprogram declares, if it is + a function or a getter. +\end{itemize} + +\hypertarget{def-emptytenv}{} +\begin{definition}[Empty Static Environment] +The \emph{empty static environment}, \\ denoted as $\emptytenv$, is defined as follows: +\[ +\emptytenv \triangleq \left( + \overname{ + \left[ +\begin{array}{lcl} + \declaredtypes &\mapsto& \emptyfunc,\\ + \constantvalues &\mapsto& \emptyfunc,\\ + \globalstoragetypes &\mapsto& \emptyfunc,\\ + \exprequiv &\mapsto& \emptyfunc,\\ + \subtypes &\mapsto& \emptyfunc,\\ + \subprograms &\mapsto& \emptyfunc,\\ + \subprogramrenamings &\mapsto& \emptyfunc +\end{array} +\right]}{\globalstaticenvs}, +\overname{ + \left[ +\begin{array}{lcl} + \constantvalues &\mapsto& \emptyfunc,\\ + \localstoragetypes &\mapsto& \emptyfunc,\\ + \exprequiv &\mapsto& \emptyfunc,\\ + \returntype &\mapsto& \None +\end{array} +\right]}{\localstaticenvs} +\right) +\] +\end{definition} + +The global environment and local environment consist of various components. +We use the notation $G^\tenv.m$ and $L^\tenv.m$ to access the $m$ component of a given environment. + +To update a function component $f$ (e.g., $\declaredtypes$) of a global or local environment $E$ +with a new mapping $x \mapsto v$, we use the notation $\tenv.f[x \mapsto v]$ to stand for $E[f \mapsto E.f[x \mapsto v]]$. + +\lrmcomment{This is related to \identd{JRXM} and \identi{ZTMQ}.} + +\section{Typing Rule Configurations} +The output configurations of type system assertions have two flavors: +\begin{description} + \item[Normal Outputs.] \hypertarget{def-normal-type-outputs}{} + Configurations are typically tuples with different combinations + of \emph{static environments}, types, and Boolean values. + + \hypertarget{def-typeerror}{} + \item[Type Errors.] Configurations in $\TypeError(\Strings)$ + represent type errors, for example, using an integer type as a condition expression, as in \verb|if 5 then 1 else 2|. + The ASL type system is designed such that when these \emph{type error configurations} appear, + the typing of the entire specification terminates by outputting them. +\end{description} + +We define the mathematical type of type error configurations +(which is needed to define the types of functions in the ASL type system) +as follows: +\hypertarget{def-ttypeerror}{} +\[ + \TTypeError \triangleq \{\TypeErrorVal{\vs} \;|\; \vs \in \Strings \} \enspace. +\] + +\hypertarget{def-typeerrorconfig}{} +and the shorthand $\TypeErrorConfig \triangleq \TypeError(\vs)$ for type error configurations. + +% \hypertarget{def-proseortypeerror}{} +% Specifically,\ProseOrTypeError\ means: ``or a type error configuration $\TypeErrorConfig$, which short-circuits the rule, +% making it transition into the type error configuration $\TypeErrorConfig$.''. +% +When several \hyperlink{def-caserules}{case rules} for the same function use the same short-circuiting transition assertion, +we do not repeat the\ProseOrTypeError, but rather include it only in the first rule. + +% \subsection*{Rule Example} +% The following rule is used to type a sequence of two statements: +% \[ +% \inferrule{ +% \annotatestmt{\tenv, \vs1} = (\newsone, \tenvone)\\ +% \annotatestmt{\tenvone, \vs2} = (\newstwo, \tenvtwo)\\ +% } +% { +% \annotatestmt{\tenv, \SSeq(\vsone, \vstwo)} = (\SSeq(\newsone, \newstwo), \tenvtwo) +% } +% \] +% The rule uses the annotation function $\annotatestmt{\cdot}$, which +% accepts an environment $\tenv$ and two statements and returns a new statement and a new environment. +% The function returns a new statement in order to implement certain code transformations, such as +% inlining setter functions. + diff --git a/asllib/doc/TypeDeclarations.tex b/asllib/doc/TypeDeclarations.tex new file mode 100644 index 000000000..cfff07639 --- /dev/null +++ b/asllib/doc/TypeDeclarations.tex @@ -0,0 +1,603 @@ +\chapter{Type Declarations\label{chap:TypeDeclarations}} +Type declarations are grammatically derived from $\Ndecl$ via the subset of productions shown in +\secref{TypeDeclarationsSyntax} and represented as ASTs via the production of $\decl$ +shown in \secref{TypeDeclarationsAbstractSyntax}. +% +Typing type declarations is done via $\declaretype$, which is defined in \nameref{sec:TypingRule.DeclareType}. +% +Type declarations have no associated semantics. + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +\section{Syntax\label{sec:TypeDeclarationsSyntax}} +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +\begin{flalign*} +\Ndecl \derivesinline\ & \productionname{typedecl}{type\_decl}\ \Ttype \parsesep \Tidentifier \parsesep \Tof \parsesep \Ntydecl \parsesep \Nsubtypeopt \parsesep \Tsemicolon&\\ +|\ & \productionname{subtypedecl}{subtype\_decl}\ \Ttype \parsesep \Tidentifier \parsesep \Nsubtype \parsesep \Tsemicolon&\\ +\Nsubtypeopt \derivesinline\ & \option{\Nsubtype} &\\ +\Nsubtype \derivesinline\ & \Tsubtypes \parsesep \Tidentifier \parsesep \Twith \parsesep \Nfields &\\ + |\ & \Tsubtypes \parsesep \Tidentifier &\\ +\Nfields \derivesinline\ & \Tlbrace \parsesep \TClist{\Ntypedidentifier} \parsesep \Trbrace &\\ +\Nfieldsopt \derivesinline\ & \Nfields \;|\; \emptysentence &\\ +\Ntypedidentifier \derivesinline\ & \Tidentifier \parsesep \Nasty &\\ +\Nasty \derivesinline\ & \Tcolon \parsesep \Nty & +\end{flalign*} + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +\section{Abstract Syntax\label{sec:TypeDeclarationsAbstractSyntax}} +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +\begin{flalign*} +\decl \derives\ & \DTypeDecl(\identifier, \ty, (\identifier, \overtext{\Field^*}{with fields})?) &\\ +\Field \derives\ & (\identifier, \ty) & +\end{flalign*} + +\subsubsection{ASTRule.GlobalDecl} +The relation +\[ + \builddecl : \overname{\parsenode{\Ndecl}}{\vparsednode} \;\aslrel\; \overname{\decl}{\vastnode} +\] +transforms a parse node $\vparsednode$ into an AST node $\vastnode$. + +\hypertarget{build-typedecl}{} +\begin{mathpar} +\inferrule[type\_decl]{} +{ + { + \begin{array}{c} + \builddecl(\overname{\Ndecl(\Ttype, \Tidentifier(\vx), \Tof, \punnode{\Ntydecl}, \Nsubtypeopt, \Tsemicolon)}{\vparsednode}) + \astarrow \\ + \overname{\DTypeDecl(\vx, \astof{\vt}, \astof{\vsubtypeopt})}{\vastnode} + \end{array} + } +} +\end{mathpar} + +\hypertarget{build-subtypedecl}{} +\begin{mathpar} +\inferrule[subtype\_decl]{ + \buildsubtype(\vsubtype) \astarrow \vs\\ + \vs \eqname (\name, \vfields) +}{ + { + \begin{array}{c} + \builddecl(\overname{\Ndecl(\Ttype, \Tidentifier(\vx), \Tof, \punnode{\Nsubtype}, \Tsemicolon)}{\vparsednode}) + \astarrow \\ + \overname{\DTypeDecl(\vx, \TNamed(\name), \langle(\name, \vfields)\rangle)}{\vastnode} + \end{array} + } +} +\end{mathpar} + +\subsubsection{ASTRule.Subtype \label{sec:ASTRule.Subtype}} +\hypertarget{build-subtype}{} +The function +\[ + \buildsubtype(\overname{\parsenode{\Nsubtype}}{\vparsednode}) \aslto \overname{(\identifier \times (\identifier\times \ty)^*)}{\vastnode} +\] +transforms a parse node $\vparsednode$ into an AST node $\vastnode$. + +\hypertarget{build-subtype}{} +\begin{mathpar} +\inferrule[with\_fields]{}{ + { + \begin{array}{r} + \buildsubtype(\overname{\Nsubtype( + \Tsubtypes, \Tidentifier(\id), \Twith, \punnode{\Nfields} + )}{\vparsednode}) + \astarrow \\ + \overname{(\id, \astof{\vfields})}{\vastnode} + \end{array} + } +} +\end{mathpar} + +\begin{mathpar} + \inferrule[no\_fields]{}{ + \buildsubtype(\overname{\Nsubtype( + \Tsubtypes, \Tidentifier(\id))}{\vparsednode}) + \astarrow + \overname{(\id, \emptylist)}{\vastnode} +} +\end{mathpar} + +\subsubsection{ASTRule.Subtypeopt \label{sec:ASTRule.Subtypeopt}} +\hypertarget{build-subtypeopt}{} +The function +\[ + \buildsubtypeopt(\overname{\parsenode{\Nsubtypeopt}}{\vparsednode}) \aslto + \overname{\langle(\identifier \times \langle (\identifier\times \ty)^* \rangle)\rangle}{\vastnode} +\] +transforms a parse node $\vparsednode$ into an AST node $\vastnode$. + +\begin{mathpar} +\inferrule[subtype\_opt]{ + \buildoption[\Nsubtype](\vsubtypeopt) \astarrow \vastnode +}{ + \buildsubtypeopt(\overname{\Nsubtypeopt(\namednode{\vsubtypeopt}{\option{\Nsubtype}})}{\vparsednode}) \astarrow \vastnode +} +\end{mathpar} + +\subsubsection{ASTRule.Fields \label{sec:ASTRule.Fields}} +\hypertarget{build-fields}{} +The function +\[ + \buildfields(\overname{\parsenode{\Nfields}}{\vparsednode}) \;\aslto\; \overname{\Field^*}{\vastnode} +\] +transforms a parse node $\vparsednode$ into an AST node $\vastnode$. + +\begin{mathpar} +\inferrule{ + \buildtclist[\buildtypedidentifier](\vfields) \astarrow \vfieldasts +}{ + \buildfields(\Nfields(\Tlbrace, \namednode{\vfields}{\TClist{\Ntypedidentifier}}, \Trbrace)) \astarrow + \overname{\vfieldasts}{\vastnode} +} +\end{mathpar} + +\subsubsection{ASTRule.FieldsOpt \label{sec:ASTRule.FieldsOpt}} +\hypertarget{build-fieldsopt}{} +The function +\[ + \buildfieldsopt(\overname{\parsenode{\Nfieldsopt}}{\vparsednode}) \;\aslto\; \overname{\Field^*}{\vastnode} +\] +transforms a parse node $\vparsednode$ into an AST node $\vastnode$. + +\begin{mathpar} +\inferrule[fields]{}{ + \buildfieldsopt(\Nfieldsopt(\punnode{\Nfields})) \astarrow + \overname{\astof{\vfields}}{\vastnode} +} +\end{mathpar} + +\begin{mathpar} +\inferrule[empty]{}{ + \buildfieldsopt(\Nfieldsopt(\emptysentence)) \astarrow + \overname{\emptylist}{\vastnode} +} +\end{mathpar} + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +\section{Typing} +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +We also define the following helper rules: +\begin{itemize} + \item TypingRule.AnnotateTypeOpt (see \secref{TypingRule.AnnotateTypeOpt}) + \item TypingRule.AnnotateExprOpt (see \secref{TypingRule.AnnotateExprOpt}) + \item TypingRule.AnnotateInitType (see \secref{TypingRule.AnnotateInitType}) + \item TypingRule.AddGlobalStorage (see \secref{TypingRule.AddGlobalStorage}) + \item TypingRule.DeclareType (see \secref{TypingRule.DeclareType}) + \item TypingRule.AnnotateExtraFields (see \secref{TypingRule.AnnotateExtraFields}) + \item TypingRule.AnnotateEnumLabels (see \secref{TypingRule.AnnotateEnumLabels}) + \item TypingRule.DeclareConst (see \secref{TypingRule.DeclareConst}) +\end{itemize} + +\subsubsection{TypingRuleDeclareType \label{sec:TypingRule.DeclareType}} +\hypertarget{def-declaretype}{} +The function +\[ +\declaretype(\overname{\staticenvs}{\tenv} \aslsep + \overname{\identifier}{\name} \aslsep + \overname{\ty}{\tty} \aslsep + \overname{\langle(\identifier\times\field^*)\rangle}{\vs} +) \aslto \overname{\staticenvs}{\newtenv} +\cup \overname{\TTypeError}{\TypeErrorConfig} +\] +declares a type named $\name$ with type $\tty$ and \optional\ additional fields +over another type $\vs$ +in the static environment $\tenv$, resulting in the modified environment $\newtenv$. +\ProseOtherwiseTypeError + +\subsection{Prose} +All of the following apply: +\begin{itemize} + \item checking that $\name$ is not already declared in the global environment of $\tenv$ yields $\True$\ProseOrTypeError; + \item annotating the \optional\ extra fields $\vs$ for $\tty$ in $\tenv$ yields via \\ $\annotateextrafields$ + yields the modified environment $\tenvone$ and type $\vtone$\ProseOrTypeError; + \item annotating $\vtone$ in $\tenvone$ yields $\vttwo$\ProseOrTypeError; + \item $\tenvtwo$ is $\tenvone$ with its $\declaredtypes$ component updated by binding $\name$ to $\vttwo$; + \item One of the following applies: + \begin{itemize} + \item All of the following apply (\textsc{enum}): + \begin{itemize} + \item $\vttwo$ is an enumeration type with labels $\ids$, that is, $\TEnum(\ids)$; + \item applying $\declareenumlabels$ to $\vttwo$ in $\tenvtwo$ $\newtenv$\ProseOrTypeError. + \end{itemize} + + \item All of the following apply (\textsc{not\_enum}): + \begin{itemize} + \item $\vttwo$ is not an enumeration type; + \item $\newtenv$ is $\tenvtwo$. + \end{itemize} + \end{itemize} +\end{itemize} +\CodeSubsection{\DeclareTypeBegin}{\DeclareTypeEnd}{../Typing.ml} + +\subsection{Formally} +\begin{mathpar} +\inferrule[enum]{ + \checkvarnotingenv{\tenv, \name} \typearrow \True \OrTypeError\\\\ + \annotateextrafields(\tenv, \tty, \vs) \typearrow (\tenvone, \vtone)\\ + \annotatetype{\True, \tenvone, \vtone} \typearrow \vttwo \OrTypeError\\\\ + \tenvtwo \eqdef (G^\tenvone.\declaredtypes[\name\mapsto\vttwo], L^\tenvone)\\ + \vttwo = \TEnum(\ids)\\ + \declareenumlabels(\tenvtwo, \vttwo) \typearrow \newtenv \OrTypeError +}{ + \declaretype(\tenv, \name, \tty, \vs) \typearrow \newtenv +} +\and +\inferrule[not\_enum]{ + \checkvarnotingenv{\tenv, \name} \typearrow \True \OrTypeError\\\\ + \annotateextrafields(\tenv, \tty, \vs) \typearrow (\tenvone, \vtone)\\ + \annotatetype{\True, \tenvone, \vtone} \typearrow \vttwo \OrTypeError\\\\ + \tenvtwo \eqdef (G^\tenvone.\declaredtypes[\name\mapsto\vttwo], L^\tenvone)\\ + \astlabel(\vttwo) \neq \TEnum +}{ + \declaretype(\tenv, \name, \tty, \vs) \typearrow \overname{\tenvtwo}{\newtenv} +} +\end{mathpar}\lrmcomment{This is related to \identr{DHRC}, \identd{YZBQ}, \identr{DWSP}, \identi{MZXL}, \identr{MDZD}, \identr{CHKR}.} + +\subsubsection{TypingRuleAnnotateExtraFields \label{sec:TypingRule.AnnotateExtraFields}} +\hypertarget{def-annotateextrafields}{} +The function +\[ +\begin{array}{r} +\annotateextrafields(\overname{\staticenvs}{\tenv} \aslsep + \overname{\ty}{\tty} \aslsep + \overname{\langle(\overname{\identifier}{\vsuper}\times\overname{\field^*}{\extrafields})\rangle}{\vs} +) +\aslto \\ +(\overname{\staticenvs}{\newtenv} \times \overname{\ty}{\newty}) +\cup \overname{\TTypeError}{\TypeErrorConfig} +\end{array} +\] +annotates the type $\tty$ with the \optional\ extra fields $\vs$ in $\tenv$, yielding +the modified environment $\newtenv$ and type $\newty$. +\ProseOtherwiseTypeError + +\subsection{Prose} +One of the following applies: +\begin{itemize} + \item All of the following apply (\textsc{none}): + \begin{itemize} + \item $\vs$ is $\None$; + \item $\newtenv$ is $\tenv$; + \item $\newty$ is $\tty$. + \end{itemize} + + \item All of the following apply (\textsc{empty\_fields}): + \begin{itemize} + \item $\vs$ is $\langle(\vsuper, \extrafields)\rangle$; + \item checking that $\tty$ \subtypesatisfies\ the named type $\vsuper$ (that is, \\ $\TNamed(\vsuper)$) yields + $\True$\ProseOrTypeError; + \item $\extrafields$ is the empty list; + \item $\newtenv$ is $\tenv$; + \item $\newty$ is $\tty$. + \end{itemize} + + \item All of the following apply (\textsc{no\_super}): + \begin{itemize} + \item $\vs$ is $\langle(\vsuper, \extrafields)\rangle$; + \item checking that $\tty$ \subtypesatisfies\ the named type $\vsuper$ (that is, \\ $\TNamed(\vsuper)$) yields + $\True$\ProseOrTypeError; + \item $\extrafields$ is not an empty list; + \item $\vsuper$ is not bound to a type in $\tenv$; + \item the result is a type error indicating that $\vsuper$ is not a declared type. + \end{itemize} + + \item All of the following apply (\textsc{structured}): + \begin{itemize} + \item $\vs$ is $\langle(\vsuper, \extrafields)\rangle$; + \item checking that $\tty$ \subtypesatisfies\ the named type $\vsuper$ (that is,\\ $\TNamed(\vsuper)$) yields + $\True$\ProseOrTypeError; + \item $\extrafields$ is not an empty list; + \item $\vsuper$ is bound to a type $\vt$ in $\tenv$; + \item checking that $\vt$ is a \structuredtype\ yields $\True$ or a type error + indicating that a \structuredtype\ was expected, thereby short-circuiting the entire rule; + \item $\vt$ has AST label $L$ and fields $\fields$; + \item $\newty$ is the type with AST label $L$ and list fields that is the concatenation of $\fields$ and $\extrafields$; + \item $\newtenv$ is $\tenv$ with its $\subtypes$ component updated by binding $\name$ to $\vsuper$. + \end{itemize} +\end{itemize} + +\subsection{Formally} +\begin{mathpar} +\inferrule[none]{}{ + \annotateextrafields(\tenv, \tty, \overname{\None}{\vs}) \typearrow (\overname{\tenv}{\newtenv}, \overname{\tty}{\newty}) +} +\end{mathpar} + +\begin{mathpar} +\inferrule[empty\_fields]{ + \subtypesat(\tty, \TNamed(\vsuper)) \typearrow \vb\\ + \checktrans{\vb}{TypeConflict} \typearrow \True \OrTypeError\\\\ + \extrafields = \emptylist +}{ + \annotateextrafields(\tenv, \tty, \overname{\langle(\vsuper, \extrafields)\rangle}{\vs}) \typearrow (\overname{\tenv}{\newtenv}, \overname{\tty}{\newty}) +} +\end{mathpar} + +\begin{mathpar} +\inferrule[no\_super]{ + \subtypesat(\tty, \TNamed(\vsuper)) \typearrow \vb\\ + \checktrans{\vb}{TypeConflict} \typearrow \True \OrTypeError\\\\ + \extrafields \neq \emptylist\\\\ + G^\tenv.\declaredtypes(\vsuper) = \bot +}{ + \annotateextrafields(\tenv, \tty, \overname{\langle(\vsuper, \extrafields)\rangle}{\vs}) \typearrow + \TypeErrorVal{\UndefinedIdentifier} +} +\end{mathpar} + +\begin{mathpar} +\inferrule[structured]{ + \subtypesat(\tty, \TNamed(\vsuper)) \typearrow \vb\\ + \checktrans{\vb}{TypeConflict} \typearrow \True \OrTypeError\\\\ + \extrafields \neq \emptylist\\\\ + G^\tenv.\declaredtypes(\vsuper) = \vt\\ + { + \begin{array}{r} + \checktrans{\astlabel(\vt) \in \{\TRecord, \TException\}}{ExpectedStructuredType} \typearrow \\ \True \OrTypeError + \end{array} + }\\ + \vt \eqname L(\fields)\\ + \newty \eqdef L(\fields \concat \extrafields)\\ + \newtenv \eqdef (G^\tenv.\subtypes[\name\mapsto\vsuper], L^\tenv) +}{ + \annotateextrafields(\tenv, \tty, \overname{\langle(\vsuper, \extrafields)\rangle}{\vs}) \typearrow (\newtenv, \newty) +} +\end{mathpar} + +\subsubsection{TypingRuleAnnotateTypeOpt \label{sec:TypingRule.AnnotateTypeOpt}} +\hypertarget{def-annotatetypeopt}{} +The function +\[ +\annotatetypeopt(\overname{\staticenvs}{\tenv} \aslsep \overname{\langle\overname{\ty}{\vt}\rangle}{\tyopt}) +\typearrow \overname{\langle\ty\rangle}{\tyoptp} +\cup \overname{\TTypeError}{\TypeErrorConfig} +\] +annotates the type $\vt$ inside an \optional\ $\tyopt$, if there is one, and leaves it as is if $\tyopt$ is $\None$. +\ProseOtherwiseTypeError + +\subsection{Prose} +One of the following applies: +\begin{itemize} + \item All of the following apply (\textsc{none}): + \begin{itemize} + \item $\tyopt$ is $\None$; + \item $\tyoptp$ is $\tyopt$. + \end{itemize} + + \item All of the following apply (\textsc{some}): + \begin{itemize} + \item $\tyopt$ contains the type $\vt$; + \item annotating $\vt$ in $\tenv$ yields $\vtone$\ProseOrTypeError; + \item $\tyoptp$ is $\langle\vtone\rangle$. + \end{itemize} +\end{itemize} + +\subsection{Formally} +\begin{mathpar} +\inferrule[none]{}{ + \annotatetypeopt(\tenv, \overname{\None}{\tyopt}) \typearrow \overname{\tyopt}{\tyoptp} +} +\and +\inferrule[some]{ + \annotatetype{\tenv, \vt} \typearrow \vtone \OrTypeError +}{ + \annotatetypeopt(\tenv, \overname{\langle\vt\rangle}{\tyopt}) \typearrow\overname{\langle\vtone\rangle}{\tyoptp} +} +\end{mathpar} + +\subsubsection{TypingRuleAnnotateExprOpt \label{sec:TypingRule.AnnotateExprOpt}} +\hypertarget{def-annotateexpropt}{} +The function +\[ + \annotateexpropt(\overname{\staticenvs}{\tenv} \aslsep \overname{\langle\ve\rangle}{\expropt}) + \aslto \overname{(\langle\expr\rangle \times \langle\ty\rangle)}{\vres} + \cup \overname{\TTypeError}{\TypeErrorConfig} +\] +annotates the \optional\ expression $\expropt$ in $\tenv$ and returns a pair of \optional\ expressions +for the type and annotated expression in $\vres$. +\ProseOtherwiseTypeError + +\subsection{Prose} +One of the following applies: +\begin{itemize} + \item All of the following apply (\textsc{none}): + \begin{itemize} + \item $\expropt$ is $\None$; + \item $\vres$ is $(\None, \None)$. + \end{itemize} + + \item All of the following apply (\textsc{some}): + \begin{itemize} + \item $\expropt$ contains the expression $\ve$; + \item annotating $\ve$ in $\tenv$ yields $(\vt, \vep)$\ProseOrTypeError; + \item $\vres$ is $(\langle\vt\rangle, \langle\vep\rangle)$. + \end{itemize} +\end{itemize} + +\subsection{Formally} +\begin{mathpar} +\inferrule[none]{}{ + \annotateexpropt(\tenv, \overname{\None}{\expropt}) \typearrow (\None, \None) +} +\and +\inferrule[some]{ + \annotateexpr{\tenv, \ve} \typearrow (\vt, \vep)\OrTypeError +}{ + \annotateexpropt(\tenv, \overname{\langle\ve\rangle}{\expropt}) \typearrow \overname{(\langle\vt\rangle, \langle\vep\rangle)}{\vres} +} +\end{mathpar} + +\subsubsection{TypingRuleAnnotateInitType \label{sec:TypingRule.AnnotateInitType}} +\hypertarget{def-annotateinittype}{} +The function +\[ + \annotateinittype(\overname{\staticenvs}{\tenv} \aslsep + \overname{\langle\ty\rangle}{\initialvaluetype} \aslsep + \overname{\langle\ty\rangle}{\typeannotation} + ) + \aslto \overname{\ty}{\declaredtype} + \cup \overname{\TTypeError}{\TypeErrorConfig} +\] +takes the \optional\ type associated with the initialization value of a global storage declaration --- $\initialvaluetype$ --- +and the \optional\ type annotation for the same global storage declaration --- $\typeannotation$ --- +and chooses the type that should be associated with the declaration --- $\declaredtype$ -- in $\tenv$. +\ProseOtherwiseTypeError + +The ASL parser ensures that at least one of $\initialvaluetype$ and \\ +$\typeannotation$ should not be $\None$. + +\subsection{Prose} +One of the following applies: +\begin{itemize} + \item All of the following apply (\textsc{both}): + \begin{itemize} + \item $\initialvaluetype$ is $\langle\vtone\rangle$ and $\typeannotation$ is $\langle\vttwo\rangle$; + \item checking that $\vtone$ \typesatisfies\ $\vttwo$ in $\tenv$ yields $\True$\ProseOrTypeError; + \item $\declaredtype$ is $\vtone$. + \end{itemize} + + \item All of the following apply (\textsc{annotated}): + \begin{itemize} + \item $\initialvaluetype$ is $\None$ and $\typeannotation$ is $\langle\vttwo\rangle$; + \item $\declaredtype$ is $\vttwo$. + \end{itemize} + + \item All of the following apply (\textsc{initial}): + \begin{itemize} + \item $\initialvaluetype$ is $\langle\vtone\rangle$ and $\typeannotation$ is $\None$; + \item $\declaredtype$ is $\vtone$. + \end{itemize} +\end{itemize} + +\begin{mathpar} +\inferrule[both]{ + \checktypesat(\tenv, \vtone, \vttwo) \typearrow \True \OrTypeError +}{ + \annotateinittype(\tenv, \overname{\langle\vtone\rangle}{\initialvaluetype}, \overname{\langle\vttwo\rangle}{\typeannotation}) + \typearrow \vttwo +} +\and +\inferrule[annotated]{}{ + \annotateinittype(\tenv, \overname{\None}{\initialvaluetype}, \overname{\langle\vttwo\rangle}{\typeannotation}) + \typearrow \vttwo +} +\and +\inferrule[initial]{}{ + \annotateinittype(\tenv, \overname{\langle\vtone\rangle}{\initialvaluetype}, \overname{\None}{\typeannotation}) + \typearrow \vtone +} +\end{mathpar} + +\hypertarget{def-declaredtype}{} +\subsection{TypingRule.DeclaredType \label{sec:TypingRule.DeclaredType}} + +The function +\[ + \declaredtype(\overname{\staticenvs}{\tenv} \aslsep \overname{\identifier}{\id}) \aslto \overname{\ty}{\vt} \cup \TTypeError +\] +retrieves the type associated with the identifier $\id$ in the static environment $\tenv$. +If the identifier is not associated with a declared type, a type error is returned. + +\subsubsection{Prose} +One of the following applies: +\begin{itemize} + \item All of the following apply (\textsc{exists}): + \begin{itemize} + \item $\id$ is bound in the global environment to the type $\vt$. + \end{itemize} + + \item All of the following apply (\textsc{type\_not\_declared}): + \begin{itemize} + \item $\id$ is not bound in the global environment to any type; + \item the result is a type error indicating the lack of a type declaration for $\id$. + \end{itemize} +\end{itemize} + +\subsubsection{Formally} +\begin{mathpar} +\inferrule[exists]{ + G^\tenv.\declaredtypes(\id) = \vt +} +{ + \declaredtype(\tenv, \id) \typearrow \vt +} +\and +\inferrule[type\_not\_declared]{ + G^\tenv.\declaredtypes(\id) = \bot +} +{ + \declaredtype(\tenv, \id) \typearrow \TypeErrorVal{TypeNotDeclared} +} +\end{mathpar} + +\subsubsection{TypingRuleAnnotateEnumLabels \label{sec:TypingRule.AnnotateEnumLabels}} +\hypertarget{def-annotateenumlabels}{} +The function +\[ +\declareenumlabels(\overname{\staticenvs}{\tenv} \aslsep + \overname{\identifier}{\name} \aslsep + \overname{\identifier^+}{\ids} \aslsep + \aslto \overname{\staticenvs}{\newtenv} + \cup \overname{\TTypeError}{\TypeErrorConfig} +) +\] +updates the static environment $\tenv$ with the identifiers $\ids$ listed by an enumeration type, +yielding the modified environment $\newtenv$. +\ProseOtherwiseTypeError + +\subsection{Prose} +All of the following apply: +\begin{itemize} + \item $\ids$ is the (non-empty) list of labels $\id_{1..k}$; + \item $\tenv_0$ is $\tenv$; + \item declaring the constant $\id_i$ with the type $\TNamed(\name)$ and literal \lint(i-1) in $\tenv_{i-1}$ + via $\declareconst$ + yields $\tenv_i$, for $i=1 $ to $k$ (if $k>1$)\ProseOrTypeError; + \item $\newtenv$ is $\tenv_k$. +\end{itemize} + +\subsection{Formally} +\begin{mathpar} +\inferrule{ + \ids \eqname \id_{1..k}\\ + \tenv_0 \eqdef \tenv\\ + \vi=1..k: \declareconst(\tenv_{\vi-1}, \id_\vi, \TNamed(\name), \lint(\vi-1)) \typearrow \tenv_{\vi} \OrTypeError +}{ + \declareenumlabels(\tenv, \name, \ids) \typearrow \overname{\tenv_k}{\newtenv} +} +\end{mathpar} + +\subsubsection{TypingRuleDeclareConst \label{sec:TypingRule.DeclareConst}} +\hypertarget{def-declareconst}{} +The function +\[ +\declareconst(\overname{\staticenvs}{\tenv} \aslsep + \overname{\identifier}{\name} \aslsep + \overname{\ty}{\tty} \aslsep + \overname{\literal}{vv}) + \aslto + \overname{\staticenvs}{\newtenv} \cup \overname{\TTypeError}{\TypeErrorConfig} +\] +adds a constant given by the identifier $\name$, type $\tty$, and literal $\vv$ to the +static environment $\tenv$, yielding the modified environment $\newtenv$. +\ProseOtherwiseTypeError + +\subsection{Prose} +All of the following apply: +\begin{itemize} + \item adding the global storage given by the identifier $\name$, global declaration keyword $\GDKConstant$, + and type $\tty$ to $\tenv$ yields $\tenvone$; + \item $\newtenv$ is $\tenvone$ with its $\constantvalues$ component updated by binding $\name$ to $\vv$. +\end{itemize} + +\begin{mathpar} +\inferrule{ + \addglobalstorage(\tenv, \name, \GDKConstant, \tty) \typearrow \tenvone\\ + \newtenv \eqdef (G^\tenvone.\constantvalues[\name, \vv], L^\tenvone) +}{ + \declareconst(\tenv, \name, \tty, \vv) \typearrow \newtenv +} +\end{mathpar} diff --git a/asllib/doc/TypeDomains.tex b/asllib/doc/TypeDomains.tex new file mode 100644 index 000000000..889e47fcf --- /dev/null +++ b/asllib/doc/TypeDomains.tex @@ -0,0 +1,492 @@ +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +\section{Domain of Values for Types\label{sec:DomainOfValuesForTypes}} +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +This section formalizes the concept of the set of values for a given type. +The formalism is given in the form of rules. +% +The section also defines the concept of checking whether the set of values +for one type is included in the set of values for another type. + +\subsection{Dynamic Domain of a Type\label{sec:DynDomain}} +\hypertarget{def-dyndomain}{} + +We now define the concept of a \emph{dynamic domain} of a type +and the \emph{static domain} of a type. +Intuitively, domains assign potentially infinite sets of \nativevalues\ to types. +Dynamic domains are used by the semantics to evaluate expressions of the form \texttt{UNKNOWN: t} +by choosing a single value from the dynamic domain of $\vt$. +Static domains are used to define subtype satisfaction in \secref{TypingRule.SubtypeSatisfaction}. + +Formally, the partial function +\[ + \dynamicdomain : \overname{\envs}{\env} \times \overname{\ty}{\vt} + \partialto \overname{\pow{\vals}}{\vd} +\] +assigns the set of values that a type $\vt$ can hold in a given environment $\env$. +% +We say that $\dynamicdomain(\env, \vt)$ is the \emph{dynamic domain} of $\vt$ +in the environment $\env$. +% +The \emph{static domain} of a type is the set of values which storage elements of that type may hold +\underline{across all possible dynamic environments}. +% +The reason for this distinction is that the sets of values +of integer types, bitvector types, and array types can depend on the dynamic values of variables. + +Types that do not refer to variables whose values are only known dynamically have +a static domain that is equal to any of their dynamic domains. +In those cases, we simply refer to their \emph{domain}. + +Associating a set of values to a type is done by evaluating any expression appearing +in the type definitions. Evaluation is defined by the relation $\evalexprsef$. +which evaluates side-effect-free expressions and either returns +a configuration of the form $\Normal(\vv,\vg)$ or a dynamic error configuration $\ErrorConfig$. +In the first case, $\vv$ is a \nativevalue\ and $\vg$ +is an \emph{execution graph}. Execution graphs are related to the concurrent semantics +and can be ignored in the context of defining dynamic domains. +In the latter case (which can occur if, for example, an expression attempts to divide +\texttt{8} by \texttt{0}), a dynamic error configuration, for which we use the notation +$\ErrorConfig$, is returned. +% +The dynamic domain is empty in cases where evaluating side-effect-free expressions +results in a dynamic error. +% +The dynamic domain is undefined if the type $\vt$ is not well-typed in $\tenv$. +That is, if $\annotatetype{\tenv, \vt} \typearrow \TypeErrorConfig$. + +As part of the definition, we also associate dynamic domains to integer constraints +by overloading $\dynamicdomain$: +\[ + \dynamicdomain : \overname{\envs}{\env} \times \overname{\intconstraint}{\vc} + \partialto \overname{\pow{\vals}}{\vd} +\] + +\subsection{Prose} +For an environment $\env \in \envs$ and a type $\vt$, the domain is $\vd$ and one of the following applies: +\begin{itemize} + \item All of the following apply (\textsc{t\_bool}): + \begin{itemize} + \item $\vt$ is the Boolean type, $\TBool$; + \item $\vd$ is the set of native Boolean values, $\tbool$. + \end{itemize} + + \item All of the following apply (\textsc{t\_string}): + \begin{itemize} + \item $\vt$ is the string type, $\TString$; + \item $\vd$ is the set of all native string values, $\tstring$. + \end{itemize} + + \item All of the following apply (\textsc{t\_real}): + \begin{itemize} + \item $\vt$ is the real type, $\TReal$; + \item $\vd$ is the set of all native real values, $\treal$. + \end{itemize} + + \item All of the following apply (\textsc{t\_enumeration}): + \begin{itemize} + \item $\vt$ is the enumeration type with labels $\id_{1..k}$, that is $\TEnum(\id_{1..k})$; + \item $\vd$ is the set of all native integer values for $1..k$.\\ + \textbf{Why represent enumeration domains via integers:} + Conceptually, enumeration labels carry two pieces of information --- the identifiers themselves + and their position in the list of identifiers, which are used for accessing arrays. + For the purpose of type-checking, we use the identifiers, but for the purpose of the semantics + and the domain of values, only the positions are relevant. + \end{itemize} + + \item All of the following apply (\textsc{t\_int\_unconstrained}): + \begin{itemize} + \item $\vt$ is the unconstrained integer type, $\unconstrainedinteger$; + \item $\vd$ is the set of all native integer values, $\tint$. + \end{itemize} + + \item All of the following apply (\textsc{t\_int\_well\_constrained}): + \begin{itemize} + \item $\vt$ is the well-constrained integer type $\TInt(\wellconstrained(\vc_{1..k}))$; + \item $\vd$ is the union of the dynamic domains of each of the constraints $\vc_{1..k}$ in $\env$. + \end{itemize} + + \item All of the following apply (\textsc{constraint\_exact\_okay}): + \begin{itemize} + \item $\vc$ is a constraint consisting of a single side-effect-free expression $\ve$, that is, $\ConstraintExact(\ve)$; + \item evaluating $\ve$ in $\env$, results in a configuration with the native integer for $n$; + \item $\vd$ is the set containing the single native integer value for $n$. + \end{itemize} + + \item All of the following apply (\textsc{constraint\_exact\_dynamic\_error}): + \begin{itemize} + \item $\vc$ is a constraint consisting of a single side-effect-free expression $\ve$, that is, $\ConstraintExact(\ve)$; + \item evaluating $\ve$ in $\env$, results in a dynamic error configuration; + \item $\vd$ is the empty set. + \end{itemize} + + \item All of the following apply (\textsc{constraint\_range\_okay}): + \begin{itemize} + \item $\vc$ is a range constraint consisting of a two side-effect-free expressions $\veone$ and $\vetwo$, that is, $\ConstraintRange(\veone, \vetwo)$; + \item evaluating $\veone$ in $\env$, results in a configuration with the native integer for $a$; + \item evaluating $\vetwo$ in $\env$, results in a configuration with the native integer for $b$; + \item $\vd$ is the set containing all native integer values for integers greater or equal to $a$ and less than or equal to $b$. + \end{itemize} + + \item All of the following apply (\textsc{constraint\_range\_dynamic\_error1}): + \begin{itemize} + \item $\vc$ is a range constraint consisting of a two side-effect-free expressions $\veone$ and $\vetwo$, that is, $\ConstraintRange(\veone, \vetwo)$; + \item evaluating $\veone$ in $\env$, results in a dynamic error configuration; + \item $\vd$ is the empty set. + \end{itemize} + + \item All of the following apply (\textsc{constraint\_range\_dynamic\_error2}): + \begin{itemize} + \item $\vc$ is a range constraint consisting of a two side-effect-free expressions $\veone$ and $\vetwo$, that is, $\ConstraintRange(\veone, \vetwo)$; + \item evaluating $\veone$ in $\env$, results in a configuration with the native integer for $a$; + \item evaluating $\vetwo$ in $\env$, results in a dynamic error configuration; + \item $\vd$ is the empty set. + \end{itemize} + + \item All of the following apply (\textsc{t\_int\_parameterized}): + \begin{itemize} + \item $\vt$ is a \parameterizedintegertype\ for parameter $\id$, \\ $\TInt(\parameterized(\id))$; + \item the \nativevalue\ associated with $\id$ in the local dynamic environment is the native integer value for $n$; + \item $\vd$ is the set containing the single integer value for $n$. + \end{itemize} + + \item All of the following apply (\textsc{t\_bits\_dynamic\_error}): + \begin{itemize} + \item $\vt$ is a bitvector type with size expression $\ve$, $\TBits(\ve, \Ignore)$; + \item evaluating $\ve$ in $\env$, results in a dynamic error configuration; + \item $\vd$ is the empty set. + \end{itemize} + + \item All of the following apply (\textsc{t\_bits\_negative\_width\_error}): + \begin{itemize} + \item $\vt$ is a bitvector type with size expression $\ve$, $\TBits(\ve, \Ignore)$; + \item evaluating $\ve$ in $\env$, results in a configuration with the native integer for $k$; + \item $k$ is negative; + \item $\vd$ is the empty set. + \end{itemize} + + \item All of the following apply (\textsc{t\_bits\_empty}): + \begin{itemize} + \item $\vt$ is a bitvector type with size expression $\ve$, $\TBits(\ve, \Ignore)$; + \item evaluating $\ve$ in $\env$, results in a configuration with the native integer for $0$; + \item $\vd$ is the set containing the single \nativevalue\ for an empty bitvector. + \end{itemize} + + \item All of the following apply (\textsc{t\_bits\_non\_empty}): + \begin{itemize} + \item $\vt$ is a bitvector type with size expression $\ve$, $\TBits(\ve, \Ignore)$; + \item evaluating $\ve$ in $\env$, results in a configuration with the native integer for $k$; + \item $k$ is greater than $0$; + \item $\vd$ is the set containing all \nativevalues\ for bitvectors of size exactly $k$. + \end{itemize} + + \item All of the following apply (\textsc{t\_tuple}): + \begin{itemize} + \item $\vt$ is a tuple type over types $\vt_i$, for $i=1..k$, $\TTuple(\vt_{1..k})$; + \item the domain of each element $\vt_i$ is $D_i$, for $i=1..k$; + \item evaluating $\ve$ in $\env$, results in a configuration with the native integer for $k$; + \item $\vd$ is the set containing all native vectors of $k$ values, where the value at position $i$ + is from $D_i$. + \end{itemize} + + \item All of the following apply (\textsc{t\_array\_dynamic\_error}): + \begin{itemize} + \item $\vt$ is an array type with length expression $\ve$ and element type $\vt_i$, for $i=1..k$, $\TArray(\ve, \vtone)$; + \item evaluating $\ve$ in $\env$, results in a dynamic error configuration; + \item $\vd$ is the empty set. + \end{itemize} + + \item All of the following apply (\textsc{t\_array\_negative\_length\_error}): + \begin{itemize} + \item $\vt$ is an array type with length expression $\ve$ and element type $\vt_i$, for $i=1..k$, $\TArray(\ve, \vtone)$; + \item evaluating $\ve$ in $\env$, results in a configuration with the native integer for $k$; + \item $k$ is negative; + \item $\vd$ is the empty set. + \end{itemize} + + \item All of the following apply (\textsc{t\_array\_okay}): + \begin{itemize} + \item $\vt$ is an array type with length expression $\ve$ and element type $\vt_i$, for $i=1..k$, $\TArray(\ve, \vtone)$; + \item evaluating $\ve$ in $\env$, results in a configuration with the native integer for $k$; + \item $k$ is greater than or equal to $0$; + \item the domain of $\vtone$ is $D_\vtone$; + \item $\vd$ is the set containing all native vectors of $k$ values taken from $D_\vtone$. + \end{itemize} + + \item All of the following apply (\textsc{t\_structured}): + \begin{itemize} + \item $\vt$ is a \structuredtype\ with typed fields $(\id_i, \vt_i$, for $i=1..k$, that is $L([i=1..k: (\id_i,\vt_i))]$ + where $L\in\{\TRecord, \TException\}$; + \item the domain of each type $\vt_i$ is $D_i$, for $i=1..k$; + \item $\vd$ is the set containing all native records where $\id_i$ is mapped to a value taken from $D_i$. + \end{itemize} + + \item All of the following apply (\textsc{t\_named}): + \begin{itemize} + \item $\vt$ is a named type with name $\id$, $\TNamed(\id)$; + \item the type associated with $\id$ in $\tenv$ is $\tty$; + \item $\vd$ is the domain of $\tty$ in $\env$. + \end{itemize} +\end{itemize} + +\subsubsection{Formally} + +\begin{mathpar} +\inferrule[t\_bool]{}{ \dynamicdomain(\env, \overname{\TBool}{\vt}) = \overname{\tbool}{\vd} } +\and +\inferrule[t\_string]{}{ \dynamicdomain(\env, \overname{\TString}{\vt}) = \overname{\tstring}{\vd} } +\and +\inferrule[t\_real]{}{ \dynamicdomain(\env, \overname{\TReal}{\vt}) = \overname{\treal}{\vd} } +\and +\inferrule[t\_enumeration]{}{ + \dynamicdomain(\env, \overname{\TEnum(\id_{1..k})}{\vt}) = \overname{\{\nvint(1),\ldots,\nvint(k)\}}{\vd} +} +\end{mathpar} + +\begin{mathpar} + \inferrule[t\_int\_unconstrained]{}{ + \dynamicdomain(\env, \overname{\unconstrainedinteger}{\vt}) = \overname{\tint}{\vd} +} +\end{mathpar} + +\begin{mathpar} +\inferrule[t\_int\_well\_constrained]{}{ + \dynamicdomain(\env, \overname{\TInt(\wellconstrained(\vc_{1..k}))}{\vt}) = \overname{\bigcup_{i=1}^k \dynamicdomain(\env, \vc_i)}{\vd} +} +\end{mathpar} + +\begin{mathpar} +\inferrule[constraint\_exact\_okay]{ + \evalexprsef{\env, \ve} \evalarrow \Normal(\nvint(n), \Ignore) +}{ + \dynamicdomain(\env, \overname{\ConstraintExact(\ve)}{\vc}) = \overname{\{ \nvint(n) \}}{\vd} +} +\and +\inferrule[constraint\_exact\_dynamic\_error]{ + \evalexprsef{\env, \ve} \evalarrow \ErrorConfig +}{ + \dynamicdomain(\env, \overname{\ConstraintExact(\ve)}{\vc}) = \overname{\emptyset}{\vd} +} +\end{mathpar} + +\begin{mathpar} +\inferrule[constraint\_range\_okay]{ + \evalexprsef{\env, \veone} \evalarrow \Normal(\nvint(a), \Ignore)\\ + \evalexprsef{\env, \vetwo} \evalarrow \Normal(\nvint(b), \Ignore) +}{ + \dynamicdomain(\env, \overname{\ConstraintRange(\veone, \vetwo)}{\vc}) = \overname{\{ \nvint(n) \;|\; a \leq n \land n \leq b\}}{\vd} +} +\and +\inferrule[constraint\_range\_dynamic\_error1]{ + \evalexprsef{\env, \veone} \evalarrow \ErrorConfig +}{ + \dynamicdomain(\env, \overname{\ConstraintRange(\veone, \vetwo)}{\vc}) = \overname{\emptyset}{\vd} +} +\and +\inferrule[constraint\_range\_dynamic\_error2]{ + \evalexprsef{\env, \veone} \evalarrow \Normal(\Ignore, \Ignore)\\ + \evalexprsef{\env, \vetwo} \evalarrow \ErrorConfig +}{ + \dynamicdomain(\env, \overname{\ConstraintRange(\veone, \vetwo)}{\vc}) = \overname{\emptyset}{\vd} +} +\end{mathpar} + +The notation $L^\denv(\id)$ denotes the \nativevalue\ associated with the identifier $\id$ +in the \emph{local dynamic environment} of $\denv$. +\begin{mathpar} + \inferrule[t\_int\_parameterized]{ + L^\denv(\id) = \nvint(n) +}{ + \dynamicdomain(\env, \overname{\TInt(\parameterized(\id))}{\vt}) = \overname{\{ \nvint(n) \}}{\vd} +} +\end{mathpar} + +\begin{mathpar} +\inferrule[t\_bits\_dynamic\_error]{ + \evalexprsef{\env, \ve} \evalarrow \ErrorConfig +}{ + \dynamicdomain(\env, \overname{\TBits(\ve, \Ignore)}{\vt}) = \overname{\emptyset}{\vd} +} +\and +\inferrule[t\_bits\_negative\_width\_error]{ + \evalexprsef{\env, \ve} \evalarrow \Normal(\nvint(k), \Ignore)\\ + k < 0 +}{ + \dynamicdomain(\env, \overname{\TBits(\ve, \Ignore)}{\vt}) = \overname{\emptyset}{\vd} +} +\and +\inferrule[t\_bits\_empty]{ + \evalexprsef{\env, \ve} \evalarrow \Normal(\nvint(0), \Ignore) +}{ + \dynamicdomain(\env, \overname{\TBits(\ve, \Ignore)}{\vt}) = \overname{\{ \nvbitvector(\emptylist) \}}{\vd} +} +\and +\inferrule[t\_bits\_non\_empty]{ + \evalexprsef{\env, \ve} \evalarrow \Normal(\nvint(k), \Ignore)\\ + k > 0 +}{ + \dynamicdomain(\env, \overname{\TBits(\ve, \Ignore)}{\vt}) = \overname{\{ \nvbitvector(\vb_{1..k}) \;|\; \vb_1,\ldots,\vb_k \in \{0,1\} \}}{\vd} +} +\end{mathpar} + +\begin{mathpar} +\inferrule[t\_tuple]{ + i=1..k: \dynamicdomain(\env, \vt_i) = D_i +}{ + \dynamicdomain(\env, \overname{\TTuple(\vt_{1..k})}{\vt}) = + \overname{\{ \nvvector{\vv_{1..k}} \;|\; \vv_i \in D_i \}}{\vd} +} +\end{mathpar} + +\begin{mathpar} +\inferrule[t\_array\_dynamic\_error]{ + \evalexprsef{\env, \ve} \evalarrow \ErrorConfig +}{ + \dynamicdomain(\env, \overname{\TArray(\ve, \vtone)}{\vt}) = \overname{\emptyset}{\vd} +} +\and +\inferrule[t\_array\_negative\_length\_error]{ + \evalexprsef{\env, \ve} \evalarrow \Normal(\nvint(k), \Ignore)\\ + k < 0 +}{ + \dynamicdomain(\env, \overname{\TArray(\ve, \vtone)}{\vt}) = \overname{\emptyset}{\vd} +} +\and +\inferrule[t\_array\_okay]{ + \evalexprsef{\env, \ve} \evalarrow \Normal(\nvint(k), \Ignore)\\ + k \geq 0\\ + \dynamicdomain(\env, \vtone) = D_\vtone +}{ + \dynamicdomain(\env, \overname{\TArray(\ve, \vtone)}{\vt}) = + \overname{\{ \nvvector{\vv_{1..k}} \;|\; \vv_{1..k} \in D_{\vtone} \}}{\vd} +} +\end{mathpar} + +\begin{mathpar} +\inferrule[structured]{ + L \in \{\TRecord, \TException\}\\ + i=1..k: \dynamicdomain(\env, \vt_i) = D_i +}{ + \dynamicdomain(\env, \overname{L([i=1..k: (\id_i,\vt_i))]}{\vt}) = \\ + \overname{\{ \nvrecord{\{i=1..k: \id_i\mapsto \vv_i\}} \;|\; \vv_i \in D_i \}}{\vd} +} +\end{mathpar} + +\begin{mathpar} +\inferrule[t\_named]{ + G^\tenv.\declaredtypes(\id)=\tty +}{ + \dynamicdomain(\env, \overname{\TNamed(\id)}{\vt}) = \overname{\dynamicdomain(\env, \tty)}{\vd} +} +\end{mathpar} + +\subsubsection{Examples} +The domain of \texttt{integer} is the infinite set of all integers. + +The domain of \verb|integer {2,16}| is the set $\{\nvint(2), \nvint(16)\}$. + +The domain of \verb|integer{1..3}| is the set $\{\nvint(1), \nvint(2), \nvint(3)\}$. + +The domain of \verb|integer{10..1}| is the empty set as there are no integers that are +both greater than $10$ and smaller than $1$. + +The domain of \texttt{bits(2)} is the set $\{\nvbitvector(00)$, $\nvbitvector(01),$ +$\nvbitvector(10)$, $\nvbitvector(11)\}$. + +The domain of \verb|enumeration {GREEN, ORANGE, RED}| is the set \\ +$\{\nvint(1), \nvint(2), \nvint(3)\}$ and so is the domain +of \\ +\verb|type TrafficLights of enumeration {GREEN, ORANGE, RED}|. + +The domain of \texttt{bits({2,16})} is the set containing native bitvectors of all 2-bit and all 16-bit binary sequences. + +The domain of \texttt{(integer, integer)} is the set containing all pairs of native integer values. + +The domain of \verb|record {a: integer; b: boolean}| contains all native records +that map \texttt{a} to a native integer value and \texttt{b} to a native Boolean value. + +The dynamic domain of a subprogram parameter \texttt{N: integer} is the (singleton) set containing +the native integer value $c$, +which is assigned to \texttt{N} by a given dynamic environment. The static domain of that parameter +is the infinite set of all native integer values. + +\lrmcomment{ +This is related to \identd{BMGM}, \identr{PHRL}, \identr{PZNR}, +\identr{RLQP}, \identr{LYDS}, \identr{SVDJ}, \identi{WLPJ}, \identr{FWMM}, +\identi{WPWL}, \identi{CDVY}, \identi{KFCR}, \identi{BBQR}, \identr{ZWGH}, +\identr{DKGQ}, \identr{DHZT}, \identi{HSWR}, \identd{YZBQ}. +} + +\subsection{Subsumption Testing\label{sec:subsumptiontesting}} +Whether an assignment statement is well-typed depends on whether the dynamic domain of the +right hand side type is contained in the dynamic domain of the left hand side type, +for any given dynamic environment +(see \secref{TypingRule.SubtypeSatisfaction} where this is checked). + +\begin{definition}[Subsumption] +For any given types $\vt$ and $\vs$ and static environment $\tenv$, +we say that $\vt$ \emph{subsumes} $\vs$ in $\tenv$, +if the following condition holds: +\hypertarget{def-subsumes}{} +\begin{equation} + \subsumes(\tenv, \vt, \vs) \triangleq \forall \denv\in\dynamicenvs.\ \dynamicdomain((\tenv, \denv), \vt) \supseteq \dynamicdomain((\tenv, \denv), \vs) \enspace. +\end{equation} +\end{definition} + +For example, consider the assignment +\begin{center} +\verb|var x : integer{1,2,3} = UNKNOWN : integer{1,2};| +\end{center} + +It is legal, since (in any static environment), the domain of \verb|integer{1,2,3}| +is \\ +$\{\nvint(1), \nvint(2), \nvint(3)\}$, which subsumes +the domain of \verb|integer{1,2}|, which is \\ $\{\nvint(1), \nvint(2)\}$. + +Since dynamic domains are potentially infinite, this requires \emph{symbolic reasoning}. +Furthermore, since any (statically evaluable) expressions may appear inside integer and bitvector +types, testing subsumption is undecidable. +We therefore approximate subsumption testing \emph{conservatively} via the predicate $\symsubsumes(\tenv, \vt, \vs)$. + +\hypertarget{def-soundsubsumptiontest}{} +\begin{definition}[Sound Subsumption Test] +A predicate +\[ + \symsubsumes(\overname{\staticenvs}{\tenv} \aslsep \overname{\ty}{\vt} \aslsep \overname{\ty}{\vs}) \aslto \Bool +\] +is \emph{sound} if the following condition holds: +\begin{equation} + \begin{array}{l} + \forall \vt,\vs\in\ty.\ \tenv\in\staticenvs. \\ + \;\;\;\; \symsubsumes(\tenv, \vt, \vs) \typearrow \True \;\Longrightarrow\; \subsumes(\tenv, \vt, \vs) \enspace. + \end{array} +\end{equation} +\end{definition} + +That is, if a sound subsumption test returns a positive answer, it means that +$\vt$ definitely \emph{subsumes} $\vs$ in the static environment $\tenv$. +This is referred to as a \emph{true positive}. +However, a negative answer means one of two things: +\begin{description} + \item[True Negative:] indeed, $\vt$ does not subsume $\vs$ in the static environment $\tenv$; or + \item[False Negative:] the symbolic reasoning is unable to decide. +\end{description} + +In other words, $\symsubsumes(\tenv, \vt, \vs)$ errs on the \emph{safe side} --- +it never answers $\True$ when the real answer is $\False$, which would (undesirably) +determine the following statement as well-typed: +\begin{center} + \verb|var x : integer{1,2} = UNKNOWN: integer;| +\end{center} + +A sound but trivial subsumption test is one that always returns $\False$. +However, that would make all assignments be considered as not well-typed. +Indeed, it has the maximal set of false negatives. +Reducing the set of false negatives requires stronger symbolic reasoning algorithms, +which inevitably leads to higher computational complexity. +% +The symbolic subsumption test in \chapref{SymbolicSubsumptionTesting} +attempts to accept a large enough set of true positives, based on empirical trial and error, +while maintaining the computational complexity of the symbolic reasoning relatively low. +% +In particular, it serves as the definitive subsumption test that must be utilized +by any implementation of the ASL type system. \ No newline at end of file diff --git a/asllib/doc/TypeSystemUtilities.tex b/asllib/doc/TypeSystemUtilities.tex new file mode 100644 index 000000000..f255a6c78 --- /dev/null +++ b/asllib/doc/TypeSystemUtilities.tex @@ -0,0 +1,568 @@ +\chapter{Type System Utility Rules\label{chap:TypeSystemUtilityRules}} + +\subsection{Checked Transitions} +\hypertarget{def-checktrans}{} +We define the following rules to allow us asserting that a condition holds, +returning a type error otherwise: +\begin{mathpar} + \inferrule[check\_trans\_true]{}{ \checktrans{\True}{} \checktransarrow \True } + \and + \inferrule[check\_trans\_false]{}{ \checktrans{\False}{} \checktransarrow \TypeErrorVal{\texttt{}} } +\end{mathpar} + +\hypertarget{def-pairstomap}{} +\subsection{Converting a List of Pairs to a Map \label{sec:PairsToMap}} +The parametric function +\[ + \pairstomap(\overname{(\identifier\times T)^*}{\pairs}) \aslto \overname{(\identifier\partialto T)}{f} \cup \TTypeError +\] +converts a list of pairs --- $\pairs$ --- where each pair consists of an identifier and a value +of type $T$ into a function mapping each identifier to its respective value in the list. +If a duplicate identifier exists in $\pairs$ then a type error is returned. + +\subsubsection{Prose} +One of the following applies: +\begin{itemize} + \item All of the following apply (\textsc{empty}): + \begin{itemize} + \item $\pairs$ is empty; + \item $f$ is the empty function. + \end{itemize} + + \item All of the following apply (\textsc{error}): + \begin{itemize} + \item there exist two different positions in the list where the identifier is the same; + \item the result is a type error indicating the existence of a duplicate identifier. + \end{itemize} + + \item All of the following apply (\textsc{okay}): + \begin{itemize} + \item all identifiers occurring in the list are unique; + \item $f$ is a function that associates to each identifier the value appearing with it in $\pairs$. + \end{itemize} +\end{itemize} + +\begin{mathpar} +\inferrule[empty]{}{ \pairstomap(\emptylist) \typearrow \emptyfunc } +\and +\inferrule[error]{ + i,j \in 1..k\\ + i \neq j\\ + \id_i = \id_j +} +{ + \pairstomap([i=1..k: (\id_i,t_i)]) \typearrow \TypeErrorVal{DuplicateIdentifier} +} +\and +\inferrule[okay]{ + \forall i,j \in 1..k. \id_i \neq \id_j\\ + { + f \eqdef \lambda \id.\ \begin{cases} + t_i & \text{ if }i\in1..k \land \id = \id_i\\ + \bot & \text{ otherwise} + \end{cases} + } +} +{ + \pairstomap([i=1..k: (\id_i,t_i)]) \typearrow f +} +\end{mathpar} + +\hypertarget{def-checknoduplicates}{} +\subsubsection{TypingRule.CheckNoDuplicates \label{sec:TypingRule.CheckNoDuplicates}} +The function +\[ + \checknoduplicates(\overname{\identifier^*}{\id_{1..k}}) \aslto \{\True\} \cup \TTypeError +\] +checks whether a non-empty list of identifiers contains a duplicate identifier. If it does not, the result +is $\True$ and otherwise the result is a type error. + +\subsubsection{Prose} +One of the following applies: +\begin{itemize} + \item All of the following apply (\textsc{okay}): + \begin{itemize} + \item the set containing all identifiers in the list has the same cardinality as the length of the list; + \item the result is $\True$. + \end{itemize} + + \item All of the following apply (\textsc{error}): + \begin{itemize} + \item there exist two different positions in the list where the identifier is the same; + \item the result is a type error indicating the existence of a duplicate identifier. + \end{itemize} +\end{itemize} + +\begin{mathpar} + \inferrule[okay]{ + \cardinality{\{\id_{1..k}\}} = k + } + { + \checknoduplicates(\id_{1..k}) \typearrow \True + } +\and +\inferrule[error]{ + i,j \in 1..k\\ + i \neq j\\ + \id_i = \id_j +} +{ + \checknoduplicates(\id_{1..k}) \typearrow \TypeErrorVal{DuplicateIdentifier} +} +\end{mathpar} + +\hypertarget{def-checkvarnotinenv}{} +\hypertarget{def-varinenv}{} +\subsubsection{TypingRule.CheckVarNotInEnv} +The function +\[ + \varinenv{\overname{\staticenvs}{\tenv} \aslsep \overname{\identifier}{\id}} + \aslto \overname{\Bool}{\vb} +\] +determines whether an identifier $\id$ is declared in the static environment $\tenv$. + +The function +\[ + \checkvarnotinenv{\overname{\staticenvs}{\tenv} \aslsep \overname{\Strings}{\id}} + \aslto \{\True\} \cup \TTypeError +\] +checks whether $\id$ is already declared in $\tenv$. If it is, the result is a type error, +and otherwise the result is $\True$. + +\subsubsection{Prose} +$\varinenv{\tenv, \id}$ is true if and only if one of the following applies: +\begin{itemize} + \item $\id$ is declared as a local identifier in $\tenv$; + \item $\id$ is declared as a global identifier in $\tenv$; + \item $\id$ is declared as a subprogram in $\tenv$; + \item $\id$ is declared as a type in $\tenv$. +\end{itemize} + +\subsubsection{Formally} +\begin{mathpar} +\inferrule{ + { + \begin{array}{rl} + \vb \eqdef & L^\tenv.\localstoragetypes(\id) \neq \bot\ \lor\\ + & G^\tenv.\globalstoragetypes(\id) \neq \bot \lor\\ + & G^\tenv.\subprograms(\id) \neq \bot\ \lor\\ + & G^\tenv.\declaredtypes(\id) \neq \bot + \end{array} +} +}{ + \varinenv{\tenv, \id} \typearrow \vb +} +\end{mathpar} + +\begin{mathpar} +\inferrule[okay]{ + \varinenv{\tenv, \id} \typearrow \False +}{ + \checkvarnotinenv{\tenv, \id} \typearrow \True +} +\and + \inferrule[error]{ + \varinenv{\tenv, \id} \typearrow \True +}{ + \checkvarnotinenv{\tenv, \id} \typearrow \TypeErrorVal{AlreadyDeclared} +} +\end{mathpar} + +\hypertarget{def-addlocal}{} +\subsubsection{TypingRule.AddLocal \label{sec:TypingRule.AddLocal}} +The function +\[ + \addlocal( + \overname{\staticenvs}{\tenv} \aslsep + \overname{\identifier}{\id} \aslsep + \overname{\ty}{\tty} \aslsep + \overname{\localdeclkeyword}{\ldk}) + \aslto + \overname{\staticenvs}{\newtenv} +\] +adds the identifier $\id$ as a local storage element with type $\tty$ and local declaration keyword $\ldk$ +to the local environment of $\tenv$, resulting in the static environment $\newtenv$. + +\subsubsection{Prose} +All of the following apply: +\begin{itemize} + \item the map $\newlocalstoragetypes$ is defined by updating the map \\ + $\localstoragetypes$ of $\tenv$ + with the binding $\id$ to the type $\tty$ and local declaration keyword $\ldk$, that is, $(\tty,\ldk)$; + \item $\newtenv$ is defined by updating the local environment with the binding of \\ + $\localstoragetypes$ to $\newlocalstoragetypes$. +\end{itemize} + +\subsubsection{Formally} +\begin{mathpar} +\inferrule{ + \newlocalstoragetypes \eqdef L^\tenv.\localstoragetypes[\id \mapsto (\tty, \ldk)]\\ + \newtenv \eqdef (G^\tenv, L^\tenv[\localstoragetypes \mapsto \newlocalstoragetypes]) +} +{ + \addlocal(\tenv, \id, \tty, \ldk) \typearrow \newtenv +} +\end{mathpar} + +\subsubsection{TypingRule.FindBitfieldOpt} +\hypertarget{def-findbitfieldopt}{} +The function +\[ + \findbitfieldopt(\overname{\identifier}{\name} \aslsep \overname{\bitfield^*}{\bitfields}) + \aslto \overname{\langle\bitfield\rangle}{\vr} +\] +returns the bitfield associated with the name $\name$ in the list of bitfields $\bitfields$, +if there is one. Otherwise, the result is $\None$. + +\subsubsection{Prose} +One of the following applies: +\begin{itemize} + \item All of the following apply (\textsc{match}): + \begin{itemize} + \item $\bitfields$ starts with a bitfield $\vbf$; + \item obtaining the name associated with $\vbf$ yields $\name$; + \item the result if $\vbf$. + \end{itemize} + + \item All of the following apply (\textsc{tail}): + \begin{itemize} + \item $\bitfields$ starts with a bitfield $\vbf$ and continues with the tail list $\bitfieldsp$; + \item obtaining the name associated with $\vbf$ yields $\namep$, which is different than $\name$; + \item finding the bitfield associated with $\name$ in $\bitfieldsp$ yields the result $\vr$. + \end{itemize} + + \item All of the following apply (\textsc{empty}): + \begin{itemize} + \item $\bitfields$ is an empty list; + \item the result is $\None$. + \end{itemize} +\end{itemize} + +\begin{mathpar} +\inferrule[match]{ + \bitfieldgetname(\vbf) \typearrow \name +}{ + \findbitfieldopt(\name, \overname{\vbf \concat \bitfieldsp}{\bitfields}) \typearrow \overname{\langle\vbf\rangle}{\vr} +} +\and +\inferrule[tail]{ + \bitfieldgetname(\vbf) \typearrow \namep\\ + \name \neq \namep\\ + \findbitfieldopt(\name, \bitfieldsp) \typearrow \vr +}{ + \findbitfieldopt(\name, \overname{\vbf \concat \bitfieldsp}{\bitfields}) \typearrow \vr +} +\and +\inferrule[empty]{}{ + \findbitfieldopt(\name, \overname{\emptylist}{\bitfields}) \typearrow \None +} +\end{mathpar} + +\hypertarget{def-typeofarraylength}{} +\subsubsection{TypingRule.TypeOfArrayLength \label{sec:TypingRule.TypeOfArrayLength}} +The function +\[ + \typeofarraylength(\overname{\staticenvs}{\tenv} \aslsep \overname{\arrayindex}{\size}) \aslto + \overname{\ty}{\vt} +\] +returns the type for the array index $\size$ in the static environment $\tenv$. + +\subsubsection{Prose} +One of the following applies: +\begin{itemize} + \item All of the following apply (\textsc{enum}): + \begin{itemize} + \item $\size$ is an enumeration index over the enumeration $\vs$, that is, \\ $\ArrayLengthEnum(\vs, \Ignore)$; + \item $\vt$ is the named type for $\vs$, that is, $\TNamed(\vs)$. + \end{itemize} + + \item All of the following apply (\textsc{expr}): + \begin{itemize} + \item $\size$ is an expression index for $\ve$, that is, $\ArrayLengthExpr(\ve)$; + \item applying $\normalize$ to simplify the expression corresponding to $\ve - 1$ in $\tenv$ + yields the expression $\vm$; + \item $\vc$ is the range constraint for $0..\vm$, that is, $\ConstraintRange(\eliteral{0}, \vm)$; + \item $\vt$ is the well-constrained integer with the single constraint $\vc$. + \end{itemize} +\end{itemize} + +\CodeSubsection{\TypeOfArrayLengthBegin}{\TypeOfArrayLengthEnd}{../types.ml} +\subsubsection{Formally} +\begin{mathpar} +\inferrule[enum]{} +{ + \typeofarraylength(\tenv, \ArrayLengthEnum(\vs, \Ignore)) \typearrow \TNamed(\vs) +} +\and +\inferrule[expr]{ + \normalize(\tenv, \EBinop(\MINUS, \ve, \eliteral{1})) \typearrow \vm\\ + \vc \eqdef \ConstraintRange(\eliteral{0}, \vm) +}{ + \typeofarraylength(\tenv, \ArrayLengthExpr(\ve)) \typearrow \TInt(\wellconstrained([\vc])) +} +\end{mathpar} + +\hypertarget{def-storageispure}{} +\subsubsection{TypingRule.StorageIsPure \label{sec:TypingRule.StorageIsPure}} +The function +\[ + \storageispure(\overname{\staticenvs}{\tenv} \aslsep \overname{\identifier}{\vs}) \aslto + \overname{\Bool}{\vb} \cup \TTypeError +\] +$\vb$ is true if and only if the identifier $\vs$ corresponds to a \pure\ storage element +in the static environment $\tenv$. + +\subsubsection{Prose} +One of the following applies: +\begin{itemize} + \item All of the following apply (\textsc{local}): + \begin{itemize} + \item $\vs$ is a locally declared storage element; + \item $\vb$ is true if and only if $\vs$ is declared as a constant or as an immutable variable (\texttt{let}). + \end{itemize} + + \item All of the following apply (\textsc{global}): + \begin{itemize} + \item $\vs$ is a globally declared storage element; + \item $\vb$ is true if and only if $\vs$ is declared as a constant, a configuration variable, or an immutable variable. + \end{itemize} + + \item All of the following apply (\textsc{error}): + \begin{itemize} + \item $\vs$ is not defined in the environment as a storage element; + \item the result is a type error indicating that $\vs$ is not defined as a storage element. + \end{itemize} +\end{itemize} + +\CodeSubsection{\StorageIsPureBegin}{\StorageIsPureEnd}{../Typing.ml} + +\subsubsection{Formally} +\begin{mathpar} +\inferrule[local]{ + L^\tenv.\localstoragetypes(\vs) = (\Ignore, \ldk)\\ + \vb \eqdef \ldk \in \{\LDKConstant, \LDKLet\} +} +{ + \storageispure(\tenv, \vs) \typearrow \vb +} +\and +\inferrule[global]{ + L^\tenv.\localstoragetypes(\vs) = \bot\\ + G^\tenv.\globalstoragetypes(\vs) = (\Ignore, \gdk)\\ + \vb \eqdef \gdk \in \{\GDKConstant, \GDKConfig, \GDKLet\} +} +{ + \storageispure(\tenv, \vs) \typearrow \vb +} +\and +\inferrule[error]{ + L^\tenv.\localstoragetypes(\vs) = \bot\\ + G^\tenv.\globalstoragetypes(\vs) = \bot +} +{ + \storageispure(\tenv, \vs) \typearrow \TypeErrorVal{UndefinedIdentifier} +} +\end{mathpar} + +\hypertarget{def-checkstaticallyevaluable}{} +\hypertarget{def-staticallyevaluable}{} +\subsubsection{TypingRule.CheckStaticallyEvaluable \label{sec:TypingRule.CheckStaticallyEvaluable}} +The function +\[ + \checkstaticallyevaluable(\overname{\staticenvs}{\tenv} \aslsep \overname{\expr}{\ve}) \aslto + \{\True\} \cup \TTypeError +\] +returns $\True$ if $\ve$ is a \staticallyevaluable\ expression in the static environment $\tenv$ and a type error otherwise. + +\subsubsection{Prose} +All of the following applies: +\begin{itemize} + \item symbolically simplifying $\ve$ in $\tenv$ via $\normalize$ yields $\veone$; + \item determining the set of used identifiers in $\veone$ yields $\useset$; + \item $\vb$ is true if and only if every identifier in $\useset$ is pure; + \item the result is $\True$ is $\vb$ is $\True$, otherwise it is a type error indicating that the expression + is not statically evaluable. +\end{itemize} + +\CodeSubsection{\CheckStaticallyEvaluableBegin}{\CheckStaticallyEvaluableEnd}{../Typing.ml} + +\subsubsection{Formally} +\begin{mathpar} +\inferrule{ + \normalize(\tenv, \ve) \typearrow \veone\\ + \useexpr(\veone) \typearrow \useset\\ + \id\in\useset: \storageispure(\tenv, \id) \typearrow \vb_\id\\ + \vb \eqdef \bigwedge_{\id\in\useset} \vb_\id\\ + \checktrans{\vb}{NotStaticallyEvaluable} \checktransarrow \True \OrTypeError +} +{ + \checkstaticallyevaluable(\tenv, \ve) \typearrow \True +} +\end{mathpar} + +\subsection{AssocOpt} +\hypertarget{def-assocopt}{} +The function +\[ + \assocopt(\overname{(\identifier\times T)^*}{\vli} \aslsep \overname{\identifier}{\id}) \typearrow \langle \overname{T}{\vv} \rangle +\] +returns the value $\vv$ associated with the identifier $\id$ in the list of pairs $\vli$ or $\None$, if no such association exists. + +\subsubsection{Prose} +One of the following applies: +\begin{itemize} + \item All of the following apply (\textsc{member}): + \begin{itemize} + \item a pair $(\id,\vv)$ exists in the list $\vli$; + \item the result is $\langle\vv\rangle$. + \end{itemize} + + \item All of the following apply (\textsc{not\_member}): + \begin{itemize} + \item every pair $(\vx,\Ignore)$ in the list $\vli$ has $\vx\neq\id$; + \item the result is $\None$. + \end{itemize} +\end{itemize} + +\subsubsection{Formally} +\begin{mathpar} +\inferrule[not\_member]{ + (\vx, \vv) \in \vli: \vx \neq \id +}{ + \assocopt(\vli, \id) \typearrow \None +} +\and +\inferrule[member]{ + (\id, \vv) \in \vli +}{ + \assocopt(\vli, \id) \typearrow \langle \vv \rangle +} +\end{mathpar} + +\subsubsection{TypingRule.IsUndefined \label{sec:TypingRule.IsUndefined}} +\hypertarget{def-isundefined}{} +The function +\[ +\isundefined(\overname{\staticenvs}{\tenv} \aslsep \overname{\identifier}{\vx}) +\aslto \overname{\Bool}{\vb} +\] +checks whether the identifier $\vx$ is defined as a storage element in the static environment $\tenv$. + +\subsubsection{Prose} +$\vb$ is $\True$ if and only if $\vx$ is not bound in to a global storage in $\tenv$ and +$\vx$ is not bound to a local storage in $\tenv$. + +\subsubsection{Formally} +\begin{mathpar} +\inferrule{ + \vb \eqdef G^\tenv.\globalstoragetypes(\vx) = \bot \land L^\tenv.\localstoragetypes(\vx) = \bot +}{ + \isundefined(\tenv, \vx) \typearrow \vb +} +\end{mathpar} + +\subsubsection{TypingRule.LookupImmutableExpr\label{sec:TypingRule.LookupImmutableExpr}} +\hypertarget{def-lookupimmutableexpr}{} +The function +\[ +\lookupimmutableexpr(\overname{\staticenvs}{\tenv}, \overname{\identifier}{\vx}) \aslto \overname{\expr}{\ve} \cup \{\bot\} +\] +looks up the static environment $\tenv$ for an immutable expression associated with the identifier $\vx$, +returning $\bot$ if there is none. + +\subsubsection{Prose} +One of the following applies: +\begin{itemize} + \item All of the following apply (\textsc{local}): + \begin{itemize} + \item applying $\exprequiv$ to $\vx$ in the local component of $\tenv$, yields $\ve$. + \end{itemize} + + \item All of the following apply (\textsc{global}): + \begin{itemize} + \item applying $\exprequiv$ to $\vx$ in the local component of $\tenv$, yields $\bot$; + \item applying $\exprequiv$ to $\vx$ in the global component of $\tenv$, yields $\ve$. + \end{itemize} + + \item All of the following apply (\textsc{none}): + \begin{itemize} + \item applying $\exprequiv$ to $\vx$ in the local component of $\tenv$, yields $\bot$; + \item applying $\exprequiv$ to $\vx$ in the global component of $\tenv$, yields $\bot$; + \item $\ve$ is $\bot$. + \end{itemize} +\end{itemize} +\subsubsection{Formally} +\begin{mathpar} +\inferrule[local]{ + L^\tenv.\exprequiv(\vx) = \ve +}{ + \lookupimmutableexpr(\tenv, \vx) \typearrow \ve +} +\end{mathpar} + +\begin{mathpar} +\inferrule[global]{ + L^\tenv.\exprequiv(\vx) = \bot\\ + G^\tenv.\exprequiv(\vx) = \ve\\ +}{ + \lookupimmutableexpr(\tenv, \vx) \typearrow \ve +} +\end{mathpar} + +\begin{mathpar} +\inferrule[none]{ + L^\tenv.\exprequiv(\vx) = \bot\\ + G^\tenv.\exprequiv(\vx) = \bot\\ +}{ + \lookupimmutableexpr(\tenv, \vx) \typearrow \bot +} +\end{mathpar} + +\subsubsection{TypingRule.Sort\label{sec:sortinglists}} +\hypertarget{def-sort}{} +The parametric function +\[ +\sort(\overname{T^*}{\vlone}, \overname{(T\times T)\rightarrow \{-1,0,1\}}{\compare}) \typearrow \overname{T^*}{\vltwo} +\] +sorts a list of elements of type $T$ --- $\vlone$ --- using the comparison function $\compare$, +resulting in the sorted list $\vltwo$. +$\compare(a, b)$ returns $1$ to mean that $a$ should be ordered before $b$, +$0$ to mean that $a$ and $b$ can be ordered in any way, +and $-1$ to mean that $b$ should be ordered before $a$. + +\subsubsection{Prose} +One of the following applies: +\begin{itemize} + \item All of the following apply (\textsc{empty\_or\_single}): + \begin{itemize} + \item $\vlone$ is either empty or contains a single element; + \item $\vltwo$ is $\vlone$. + \end{itemize} + + \item All of the following apply (\textsc{two\_or\_more}): + \begin{itemize} + \item $\vlone$ contains at least two elements; + \item $f$ is a permutation of $1..n$; + \item $\vltwo$ is the application of the permutation $f$ to $\vlone$; + \item applying $\compare$ to every pair of consecutive elements in $\vltwo$ yields either $0$ or $1$. + \end{itemize} +\end{itemize} + +\subsubsection{Formally} +\begin{mathpar} +\inferrule[empty\_or\_single]{ + \listlen{\vlone} = n\\ + n < 2 +}{ + \sort(\vlone, \compare) \typearrow \overname{\vlone}{\vltwo} +} +\and +\inferrule[two\_or\_more]{ + \listlen{\vlone} = n\\ + f : 1..n \rightarrow 1..n \text{ is a bijection}\\ + \vltwo \eqdef [\ i=1..n: \vlone[f(i)]\ ]\\ + i=1..n-1: \compare(\vltwo[i], \vltwo[i+1]) \geq 0 +}{ + \sort(\vlone, \compare) \typearrow \vltwo +} +\end{mathpar} \ No newline at end of file diff --git a/asllib/doc/Types.tex b/asllib/doc/Types.tex new file mode 100644 index 000000000..639fd8426 --- /dev/null +++ b/asllib/doc/Types.tex @@ -0,0 +1,992 @@ +\chapter{Types\label{chap:Types}} + +Types describe the allowed values of variables, constants, function arguments, etc. +\lrmcomment{\identi{BYVL}} +This chapter first defines for each type how it is represented by the ASL syntax, +by the abstract syntax, and how it is type checked: +\begin{itemize} + \item Integer types (see \secref{IntegerTypes}) + \item The real type (see \secref{IntegerTypes}) + \item The string type (see \secref{StringType}) + \item The Boolean type (see \secref{BooleanType}) + \item Bitvector types (see \secref{BitvectorTypes}) + \item Tuple types (see \secref{TupleTypes}) + \item Array types (see \secref{ArrayTypes}) + \item Enumeration types (see \secref{EnumerationTypes}) + \item Record types (see \secref{RecordTypes}) + \item Exception types (see \secref{ExceptionTypes}) + \item Named types (see \secref{NamedTypes}) +\end{itemize} + +\Anonymoustypes\ are grammatically derived from the non-terminal $\Nty$ +and types that must be declared and named are grammatically derived from the non-terminal $\Ntydecl$. +All types are represented as ASTs derived from the AST non-terminal $\ty$. + +\hypertarget{build-ty}{} +The function +\[ + \buildty(\overname{\parsenode{\Nty}}{\vparsednode}) \;\aslto\; \overname{\ty}{\vastnode} +\] +transforms an anonymous type parse node $\vparsednode$ into a type AST node $\vastnode$. + +\hypertarget{build-tydecl}{} +The function +\[ + \buildtydecl(\overname{\parsenode{\Ntydecl}}{\vparsednode}) \;\aslto\; \overname{\ty}{\vastnode} +\] +transforms a \namedtype\ parse node $\vparsednode$ into an AST node $\vastnode$. + +\hypertarget{def-annotatetype}{} +The function +\[ + \annotatetype{\overname{\Bool}{\vdecl} \aslsep \overname{\staticenvs}{\tenv} \aslsep \overname{\ty}{\tty}} + \aslto \overname{\ty}{\newty} \cup \overname{\TTypeError}{\TypeErrorConfig} +\] +typechecks a type $\tty$ in an environment $\tenv$, resulting in a \typedast\ $\newty$. +The flag $\decl$ indicates whether $\tty$ is a type currently being declared, +and makes a difference only when $\tty$ is an enumeration type or a \structuredtype. +\ProseOtherwiseTypeError + +Types are not associated with a semantic relation. + +The rest of this chapter defines the following aspects of types: +\begin{itemize} +\item \secref{DomainOfValuesForTypes} defines how values are associated with each type. +\item \secref{BasicTypeAttributes} assigns basic properties to types, which are useful +in classifying them. +\item \secref{RelationsOnTypes} defines relations on types that are needed to typecheck +expressions and statements. +\end{itemize} + +\section{Integer Types\label{sec:IntegerTypes}} +\begin{center} +\begin{tabular}{lll} +\hline +\secreflink{IntegerTypesSyntax} & \secreflink{IntegerTypesAST} & \secreflink{TypingIntegerTypes}\\ +& \secreflink{ASTRule.Ty.TInt} & \secreflink{TypingRule.TInt}\\ +& \secreflink{ASTRule.IntConstraintsOpt} & \secreflink{TypingRule.AnnotateConstraint}\\ +& \secreflink{ASTRule.IntConstraints} & \\ +& \secreflink{ASTRule.IntConstraint} &\\ +\hline +\end{tabular} +\end{center} + +\subsection{Syntax\label{sec:IntegerTypesSyntax}} +\begin{flalign*} +\Nty \derives\ & \Tinteger \parsesep \Nintconstraintsopt &\\ +\Nintconstraintsopt \derivesinline\ & \Nintconstraints \;|\; \emptysentence &\\ +\Nintconstraints \derivesinline\ & \Tlbrace \parsesep \NClist{\Nintconstraint} \parsesep \Trbrace &\\ +\Nintconstraint \derivesinline\ & \Nexpr &\\ +|\ & \Nexpr \parsesep \Tslicing \parsesep \Nexpr & +\end{flalign*} + +\subsection{Abstract Syntax\label{sec:IntegerTypesAST}} +\begin{flalign*} +\ty \derives\ & \TInt(\intconstraints)\\ +\intconstraints \derives\ & \unconstrained +& \\ +|\ & \wellconstrained(\intconstraint^{+}) +& \\ +|\ & \parameterized(\overtext{\identifier}{parameter}) &\\ +\intconstraint \derives\ & \ConstraintExact(\expr) +& \\ +|\ & \ConstraintRange(\overtext{\expr}{start}, \overtext{\expr}{end})& +\end{flalign*} + +\subsubsection{ASTRule.Ty.TInt\label{sec:ASTRule.Ty.TInt}} +\begin{mathpar} +\inferrule[integer]{}{ + \buildty(\Nty(\Tinteger, \punnode{\Nintconstraintsopt})) \astarrow + \overname{\TInt(\astof{\vintconstraintsopt})}{\vastnode} +} +\end{mathpar} + +\subsubsection{ASTRule.IntConstraintsOpt\label{sec:ASTRule.IntConstraintsOpt}} +\hypertarget{build-intconstraintsopt}{} +The function +\[ + \buildintconstraintsopt(\overname{\parsenode{\Nintconstraintsopt}}{\vparsednode}) \;\aslto\; \overname{\intconstraints}{\vastnode} +\] +transforms a parse node $\vparsednode$ into an AST node $\vastnode$. + +\begin{mathpar} +\inferrule[constrained]{}{ + { + \begin{array}{r} + \buildintconstraintsopt(\Nintconstraintsopt(\punnode{\Nintconstraints})) \astarrow \\ + \overname{\astof{\vintconstraints}}{\vastnode} + \end{array} + } +} +\end{mathpar} + +\begin{mathpar} +\inferrule[unconstrained]{}{ + \buildintconstraintsopt(\Nintconstraintsopt(\emptysentence)) \astarrow + \overname{\unconstrained}{\vastnode} +} +\end{mathpar} + +\subsection{ASTRule.IntConstraints\label{sec:ASTRule.IntConstraints}} +\hypertarget{build-intconstraints}{} +The function +\[ + \buildintconstraints(\overname{\parsenode{\Nintconstraints}}{\vparsednode}) \;\aslto\; \overname{\intconstraints}{\vastnode} +\] +transforms a parse node $\vparsednode$ into an AST node $\vastnode$. + +\begin{mathpar} +\inferrule{ + \buildclist[\buildintconstraint](\vconstraintasts) \astarrow \vconstraintasts +}{ + { + \begin{array}{r} + \buildintconstraints(\Nintconstraints(\Tlbrace, \namednode{\vconstraints}{\NClist{\Nintconstraint}}, \Trbrace)) \astarrow\\ + \overname{\wellconstrained(\vconstraintasts)}{\vastnode} + \end{array} + } +} +\end{mathpar} + +\subsubsection{ASTRule.IntConstraint\label{sec:ASTRule.IntConstraint}} +\hypertarget{build-intconstraint}{} +The function +\[ + \buildintconstraint(\overname{\parsenode{\Nintconstraint}}{\vparsednode}) \;\aslto\; \overname{\intconstraint}{\vastnode} +\] +transforms a parse node $\vparsednode$ into an AST node $\vastnode$. + +\begin{mathpar} +\inferrule[exact]{}{ + \buildintconstraint(\Nintconstraint(\punnode{\Nexpr})) \astarrow + \overname{\ConstraintExact(\astof{\vexpr})}{\vastnode} +} +\end{mathpar} + +\begin{mathpar} +\inferrule[range]{ + \buildexpr(\vfromexpr) \astarrow \astversion{\vfromexpr}\\ + \buildexpr(\vtoexpr) \astarrow \astversion{\vtoexpr}\\ +}{ + { + \begin{array}{r} + \buildintconstraint(\Nintconstraint(\namednode{\vfromexpr}{\Nexpr}, \Tslicing, \namednode{\vtoexpr}{\Nexpr})) \astarrow\\ + \overname{\ConstraintRange(\astversion{\vfromexpr}, \astversion{\vtoexpr})}{\vastnode} + \end{array} + } +} +\end{mathpar} + +\subsection{Typing Integer Types\label{sec:TypingIntegerTypes}} +\subsubsection{TypingRule.TInt\label{sec:TypingRule.TInt}} + +\subsubsection{Prose} +One of the following applies: +\begin{itemize} + \item All of the following apply (\textsc{not\_well\_constrained}): + \begin{itemize} + \item $\tty$ is an integer type that is not well-constrained; + \item $\newty$ is the unconstrained integer type. + \end{itemize} + \item All of the following apply (\textsc{well\_constrained}): + \begin{itemize} + \item $\tty$ is the well-constrained integer type constrained by + constraints $\vc_i$, for $u=1..k$; + \item annotating each constraint $\vc_i$, for $i=1..k$, + yields $\newc_i$\ProseOrTypeError; + \item $\newconstraints$ is the list of annotated constraints $\newc_i$, + for $i=1..k$; + \item $\newty$ is the well-constrained integer type constrained + by $\newconstraints$. + \end{itemize} +\end{itemize} + +\subsubsection{Example} +In the following examples, all the uses of integer types are well-typed: +\ASLExample{\typingtests/TypingRule.TIntUnConstrained.asl} +\ASLExample{\typingtests/TypingRule.TIntWellConstrained.asl} +\ASLExample{\typingtests/TypingRule.TIntUnderConstrained.asl} + +\CodeSubsection{\TIntBegin}{\TIntEnd}{../Typing.ml} + +\subsubsection{Formally} +\begin{mathpar} +\inferrule[not\_well\_constrained]{ + \tty \eqname \TInt(\vc)\\ + \astlabel(\vc) \neq \wellconstrained +}{ + \annotatetype{\overname{\Ignore}{\vdecl}, \tenv, \tty} \typearrow \overname{\tty}{\newty} +} +\end{mathpar} + +\begin{mathpar} +\inferrule[well\_constrained]{ + \constraints \eqname \vc_{1..k}\\ + i=1..k: \annotateconstraint(\vc_i) \typearrow\newc_i \OrTypeError\\\\ + \newconstraints \eqdef \newc_{1..k} +}{ + { + \begin{array}{r} + \annotatetype{\overname{\Ignore}{\vdecl}, \tenv, \overname{\TInt(\wellconstrained(\constraints))}{\tty}} \typearrow \\ + \overname{\TInt(\wellconstrained(\newconstraints))}{\newty} + \end{array} + } +} +\end{mathpar} + +\subsubsection{TypingRule.AnnotateConstraint\label{sec:TypingRule.AnnotateConstraint}} +\hypertarget{def-annotateconstraint}{} +The function +\[ +\annotateconstraint(\overname{\staticenvs}{\tenv} \aslsep \overname{\intconstraint}{\vc}) +\aslto \overname{\intconstraint}{\newc} \cup \overname{\TTypeError}{\TypeErrorConfig} +\] +annotates an integer constraint $\vc$ in the static environment $\tenv$ yielding the annotated +integer constraint $\newc$. +\ProseOtherwiseTypeError + +\subsubsection{Prose} +One of the following applies: +\begin{itemize} + \item All of the following apply (\textsc{exact}): + \begin{itemize} + \item $\vc$ is the exact integer constraint for the expression $\ve$, that is, \\ $\ConstraintExact(\ve)$; + \item applying $\annotatestaticconstrainedinteger$ to $\ve$ in $\tenv$ yields $\vep$\ProseOrTypeError; + \item define $\newc$ as the exact integer constraint for $\vep$, that is, $\ConstraintExact(\vep)$. + \end{itemize} + + \item All of the following apply (\textsc{range}): + \begin{itemize} + \item $\vc$ is the range integer constraint for expressions $\veone$ and $\vetwo$, that is, \\ $\ConstraintRange(\veone, \vetwo)$; + \item applying $\annotatestaticconstrainedinteger$ to $\veone$ in $\tenv$ yields $\veonep$\ProseOrTypeError; + \item applying $\annotatestaticconstrainedinteger$ to $\vetwo$ in $\tenv$ yields $\vetwop$\ProseOrTypeError; + \item define $\newc$ as the range integer constraint for expressions $\veonep$ and $\vetwop$, that is, $\ConstraintRange(\veonep, \vetwop)$. + \end{itemize} +\end{itemize} + +\subsubsection{Formally} +\begin{mathpar} +\inferrule[exact]{ + \annotatestaticconstrainedinteger(\tenv, \ve) \typearrow \vep \OrTypeError +}{ + \annotateconstraint(\tenv, \overname{\ConstraintExact(\ve)}{\vc}) \typearrow \overname{\ConstraintExact(\vep)}{\newc} +} +\and +\inferrule[range]{ + \annotatestaticconstrainedinteger(\tenv, \veone) \typearrow \veonep \OrTypeError\\\\ + \annotatestaticconstrainedinteger(\tenv, \vetwo) \typearrow \vetwop \OrTypeError +}{ + \annotateconstraint(\tenv, \overname{\ConstraintRange(\veone, \vetwo)}{\vc}) \typearrow \overname{\ConstraintRange(\veonep, \vetwop)}{\newc} +} +\end{mathpar} + +\section{The Real Type\label{sec:RealType}} +\subsection{Syntax} +\begin{flalign*} +\Nty \derives\ & \Treal & +\end{flalign*} + +\subsection{Abstract Syntax} +\begin{flalign*} +\ty \derives\ & \TReal & +\end{flalign*} + +\subsubsection{ASTRule.TReal} +\begin{mathpar} +\inferrule{}{ + \buildty(\Nty(\Treal)) \astarrow + \overname{\TReal}{\vastnode} +} +\end{mathpar} + +\subsection{Typing the Real Type\label{sec:TypingRealType}} +\subsubsection{TypingRule.TReal\label{sec:TypingRule.TReal}} +\subsubsection{Prose} +All of the following apply: +\begin{itemize} + \item $\tty$ is the real type \TReal. + \item $\newty$ is the real type \TReal. +\end{itemize} + +\subsubsection{Example} +In the following example, all the uses of \texttt{real} are well-typed: +\ASLExample{\typingtests/TypingRule.TReal.asl} + +\subsubsection{Formally} +\begin{mathpar} +\inferrule{} +{ + \annotatetype{\overname{\Ignore}{\vdecl}, \tenv, \overname{\TReal}{\tty}} \typearrow \overname{\TReal}{\newty} +} +\end{mathpar} + +\CodeSubsection{\TRealBegin}{\TRealEnd}{../Typing.ml} + +\section{The String Type\label{sec:StringType}} +\subsection{Syntax} +\begin{flalign*} +\Nty \derives\ & \Tstring & +\end{flalign*} + +\subsection{Abstract Syntax} +\begin{flalign*} +\ty \derives\ & \TString& +\end{flalign*} + +\subsubsection{ASTRule.Ty.String} +\begin{mathpar} +\inferrule{}{ + \buildty(\Nty(\Tstring)) \astarrow + \overname{\TString}{\vastnode} +} +\end{mathpar} + +\subsection{Typing the String Type\label{sec:TypingStringType}} +\subsubsection{TypingRule.TString\label{sec:TypingRule.TString}} +\subsubsection{Prose} +All of the following apply: +\begin{itemize} + \item $\tty$ is the string type \TString. + \item $\newty$ is the string type \TString. +\end{itemize} + +\subsubsection{Example} +In the following example, all the uses of \texttt{string} are well-typed: +\ASLExample{\typingtests/TypingRule.TString.asl} + +\CodeSubsection{\TStringBegin}{\TStringEnd}{../Typing.ml} + +\subsubsection{Formally} +\begin{mathpar} +\inferrule{} +{ + \annotatetype{\overname{\Ignore}{\vdecl}, \tenv, \overname{\TString}{\tty}} \typearrow \overname{\TString}{\newty} +} +\end{mathpar} + +\section{The Boolean Type\label{sec:BooleanType}} +\subsection{Syntax} +\begin{flalign*} +\Nty \derives\ & \Tboolean & +\end{flalign*} + +\subsection{Abstract Syntax} +\begin{flalign*} +\ty \derives\ & \TBool & +\end{flalign*} + +\subsubsection{ASTRule.Ty.BoolType} +\begin{mathpar} +\inferrule{}{ + \buildty(\Nty(\Tboolean)) \astarrow + \overname{\TBool}{\vastnode} +} +\end{mathpar} + +\subsection{Typing the Boolean Type\label{sec:TypingBooleanType}} +\subsubsection{TypingRule.TBool\label{sec:TypingRule.TBool}} +\subsubsection{Prose} +All of the following apply: +\begin{itemize} + \item $\tty$ is the boolean type, \TBool; + \item $\newty$ is the boolean type, \TBool. +\end{itemize} + +\subsubsection{Example} +In the following example, all the uses of \texttt{boolean} are well-typed: +\ASLExample{\typingtests/TypingRule.TBool.asl} + +\CodeSubsection{\TBoolBegin}{\TBoolEnd}{../Typing.ml} + +\subsubsection{Formally} +\begin{mathpar} +\inferrule{} +{ + \annotatetype{\overname{\Ignore}{\vdecl}, \tenv, \overname{\TBool}{\tty}} \typearrow \overname{\TBool}{\newty} +} +\end{mathpar} + +\section{Bitvector Types\label{sec:BitvectorTypes}} +\subsection{Syntax} +\begin{flalign*} +\Nty \derives\ & \Tbit &\\ + |\ & \Tbits \parsesep \Tlpar \parsesep \Nexpr \parsesep \Trpar \parsesep \maybeemptylist{\Nbitfields} &\\ +\Nbitfields \derivesinline\ & \Tlbrace \parsesep \TClist{\Nbitfield} \parsesep \Trbrace &\\ +\Nbitfield \derivesinline\ & \Nnamedslices \parsesep \Tidentifier &\\ + |\ & \Nnamedslices \parsesep \Tidentifier \parsesep \Nbitfields &\\ + |\ & \Nnamedslices \parsesep \Tidentifier \parsesep \Tcolon \parsesep \Nty &\\ +\Nnamedslices \derivesinline\ & \Tlbracket \parsesep \NClist{\Nslice} \parsesep \Trbracket & +\end{flalign*} + +\subsection{Abstract Syntax} +\begin{flalign*} +\ty \derives\ & \TBits(\overtext{\expr}{width}, \bitfield^{*}) & +\end{flalign*} + +\subsubsection{ASTRule.Ty.TBits} +\begin{mathpar} +\inferrule[bit]{}{ + \buildty(\Nty(\Tbit)) \astarrow + \overname{\TBits(\ELiteral(\lint(1)), \emptylist)}{\vastnode} +} +\end{mathpar} + +\begin{mathpar} +\inferrule[bits]{ + \buildlist[\buildbitfield](\vbitfields) \astarrow \vbitfieldasts +}{ + { + \begin{array}{r} + \buildty(\Nty(\Tbits, \Tlpar, \punnode{\Nexpr}, \Trpar, \namednode{\vbitfields}{\maybeemptylist{\Nbitfields}})) \astarrow\\ + \overname{\TBits(\astof{\vexpr}, \vbitfieldasts)}{\vastnode} + \end{array} + } +} +\end{mathpar} + +\subsection{Typing} +\subsection{TypingRule.TBits\label{sec:TypingRule.TBits}} +\subsubsection{Prose} +All of the following apply: +\begin{itemize} + \item $\tty$ is the bit-vector type with width given by the expression + $\ewidth$ and the bitfields given by $\bitfields$, that is, $\TBits(\ewidth, \bitfields)$; + \item annotating the \staticallyevaluable\ integer expression $\ewidth$ yields $\ewidthp$\ProseOrTypeError; + \item annotating the bitfields $\bitfields$ yields $\bitfieldsp$\ProseOrTypeError; + \item $\newty$ is the bit-vector type with width given by the expression + $\ewidthp$ and the bitfields given by $\bitfieldsp$, that is, $\TBits(\ewidthp, \bitfieldsp)$ +\end{itemize} + +\subsubsection{Formally} +\begin{mathpar} +\inferrule{ + \annotatestaticconstrainedinteger(\tenv, \ewidth) \typearrow \ewidthp \OrTypeError\\\\ + \annotatebitfields(\tenv, \ewidthp, \bitfields) \typearrow \bitfieldsp \OrTypeError +}{ + { + \begin{array}{r} + \annotatetype{\overname{\Ignore}{\vdecl}, \tenv, \TBits(\ewidth, \bitfields)} \typearrow \\ + \TBits(\ewidthp, \bitfieldsp) + \end{array} + } +} +\end{mathpar} +\CodeSubsection{\TBitsBegin}{\TBitsEnd}{../Typing.ml} + +\subsubsection{Example} +In the following example, all the uses of bitvector types are well-typed: +\ASLExample{\typingtests/TypingRule.TBits.asl} + +\subsubsection{Comments} +The width of a bitvector type $\TBits(\ewidth, \bitfields)$, given by the expression \\ +$\ewidth$, +must be non-negative. + +\section{Tuple Types\label{sec:TupleTypes}} +\subsection{Syntax} +\begin{flalign*} +\Nty \derives\ & \Plist{\Nty} & +\end{flalign*} + +\subsection{Abstract Syntax} +\begin{flalign*} +\ty \derives\ & \TTuple(\ty^{*}) & +\end{flalign*} + +\subsubsection{ASTRule.Ty.TTuple} +\begin{mathpar} +\inferrule{ + \buildplist[\buildty](\vtypes) \astarrow \vtypeasts +}{ + \buildty(\Nty(\namednode{\vtypes}{\Plist{\Nty}})) \astarrow + \overname{\TTuple(\vtypeasts)}{\vastnode} +} +\end{mathpar} + +\subsection{Typing Tuple Types\label{sec:TypingTupleTypes}} +\subsubsection{TypingRule.TTuple\label{sec:TypingRule.TTuple}} +\subsubsection{Prose} +All of the following apply: +\begin{itemize} + \item $\tty$ is the tuple type with member types $\tys$, that is, $\TTuple(\tys)$; + \item $\tys$ is the list $\tty_i$, for $i=1..k$; + \item annotating each type $\tty_i$ in $\tenv$, for $i=1..k$, + yields $\ttyp_i$\ProseOrTypeError; + \item $\newty$ is the tuple type with member types $\ttyp$, for $i=1..k$. +\end{itemize} + +\subsubsection{Formally} +\begin{mathpar} +\inferrule{ + k \geq 2\\ + \tys \eqname \tty_{1..k}\\ + i=1..k: \annotatetype{\False, \tenv, \tty_i} \typearrow \ttyp_i \OrTypeError +}{ + \annotatetype{\overname{\Ignore}{\vdecl}, \tenv, \TTuple(\tys)} \typearrow \TTuple(\tysp) +} +\end{mathpar} +\CodeSubsection{\TTupleBegin}{\TTupleEnd}{../Typing.ml} + +In the following example, all the uses of tuple types are well-typed: +\ASLExample{\typingtests/TypingRule.TTuple.asl} +\subsubsection{Example} + +\section{Array Types\label{sec:ArrayTypes}} +\subsection{Syntax} +\begin{flalign*} +\Nty \derives\ & \Tarray \parsesep \Tlbracket \parsesep \Nexpr \parsesep \Trbracket \parsesep \Tof \parsesep \Nty & +\end{flalign*} + +\subsection{Abstract Syntax} +\begin{flalign*} +\ty \derives\ & \TArray(\arrayindex, \ty) &\\ +\arrayindex \derives\ & \ArrayLengthExpr(\overtext{\expr}{array length}) & +\end{flalign*} + +\subsubsection{ASTRule.Ty.TArray} +\begin{mathpar} +\inferrule{}{ + \buildty(\Nty(\Tarray, \Tlbracket, \punnode{\Nexpr}, \Trbracket, \Tof, \punnode{\Nty})) \astarrow + \overname{\TArray(\ArrayLengthExpr(\astof{\vexpr}), \astof{\tty})}{\vastnode} +} +\end{mathpar} +\subsection{Typing Array Types\label{sec:TypingArrayTypes}} +\subsubsection{Example} +In the following example, all the uses of array types are well-typed: +\ASLExample{\typingtests/TypingRule.TArray.asl} + +\subsubsection{TypingRule.TArray\label{sec:TypingRule.TArray}} +\subsubsection{Prose} +All of the following apply: +\begin{itemize} + \item $\tty$ is the array type with element type $\vt$; + \item Annotating the type $\vt$ in $\tenv$ yields $\vtp$\ProseOrTypeError; + \item One of the following applies: + \begin{itemize} + \item All of the following apply (\textsc{expr\_is\_enum}): + \begin{itemize} + \item the array index is $\ve$ and determining whether $\ve$ corresponds to an enumeration in $\tenv$ + via $\getvariableenum$ yields the enumeration variable + name $\vs$ of size $\vi$, that is, $\langle \vs, \vi \rangle$\ProseOrTypeError; + \item $\newty$ is the array type indexed by an enumeration type + named $\vs$ of length $\vi$ and of elements of type $\vtp$, that is, $\TArray(\ArrayLengthEnum(\vs, \vi), \vtp)$. + \end{itemize} + + \item All of the following apply (\textsc{expr\_not\_enum}): + \begin{itemize} + \item the array index is $\ve$ and determining whether $\ve$ corresponds to an enumeration in $\tenv$ + via $\getvariableenum$ yields $\None$ (meaning it does not + correspond to an enumeration)\ProseOrTypeError; + \item annotating the statically evaluable integer expression $\ve$ yields + $\vep$\ProseOrTypeError; + \item $\newty$ the array type indexed by integer bounded by + the expression $\vep$ and of elements of type $\vtp$, that is, + $\TArray(\ArrayLengthExpr(\vep), \vtp)$. + \end{itemize} + \end{itemize} +\end{itemize} +\subsubsection{Formally} +\begin{mathpar} +\inferrule[expr\_is\_enum]{ + \annotatetype{\False, \tenv, \vt} \typearrow \vtp \OrTypeError\\\\ + \commonprefixline\\\\ + \getvariableenum(\tenv, \ve) \typearrow \langle \vs, \vi \rangle\OrTypeError +}{ + \annotatetype{\overname{\Ignore}{\vdecl}, \tenv, \overname{\AbbrevTArrayLengthExpr{\ve}{\vt}}{\tty}} \typearrow + \overname{\AbbrevTArrayLengthEnum{\ve}{\vi}{\vtp}}{\newty} +} +\end{mathpar} + +\begin{mathpar} +\inferrule[expr\_not\_enum]{ + \annotatetype{\False, \tenv, \vt} \typearrow \vtp \OrTypeError\\\\ + \commonprefixline\\\\ + \getvariableenum(\tenv, \ve) \typearrow \None \OrTypeError\\\\ + \annotatestaticinteger(\tenv, \ve) \typearrow \vep \OrTypeError +}{ + \annotatetype{\overname{\Ignore}{\vdecl}, \tenv, \overname{\AbbrevTArrayLengthExpr{\ve}{\vt}}{\tty}} \typearrow + \overname{\AbbrevTArrayLengthExpr{\vep}{\vtp}}{\newty} +} +\end{mathpar} +\CodeSubsection{\TArrayBegin}{\TArrayEnd}{../Typing.ml} + +\subsubsection{TypingRule.GetVariableEnum\label{sec:TypingRule.GetVariableEnum}} +\hypertarget{def-getvariableenum}{} +The function +\[ +\getvariableenum(\overname{\staticenvs}{\tenv} \aslsep \overname{\expr}{\ve}) \aslto +\langle (\overname{\identifier}{\vx}, \overname{\N}{n})\rangle +\] +tests whether the expression $\ve$ represents a variable of an enumeration type. +If so, the result is $\vx$ --- the name of the variable and the number of labels defined for the enumeration type. +Otherwise, the result is $\None$. + +\subsubsection{Prose} +One of the following applies: +\begin{itemize} + \item All of the following apply (\textsc{not\_evar}): + \begin{itemize} + \item $\ve$ is not a variable expression; + \item the result is $\None$. + \end{itemize} + + \item All of the following apply (\textsc{no\_declared\_type}): + \begin{itemize} + \item $\ve$ is a variable expression for $\vx$, that is, $\EVar(\vx)$; + \item $\vx$ is not associated with a type in the global environment of $\tenv$; + \item the result is $\None$. + \end{itemize} + + \item All of the following apply (\textsc{declared\_enum}): + \begin{itemize} + \item $\ve$ is a variable expression for $\vx$, that is, $\EVar(\vx)$; + \item $\vx$ is associated with a type $\vt$ in the global environment of $\tenv$; + \item obtaining the \underlyingtype\ of $\vt$ in $\tenv$ yields an enumeration type with labels $\vli$\ProseOrTypeError; + \item the result is the pair consisting of $\vx$ and the length of $\vli$. + \end{itemize} + + \item All of the following apply (\textsc{declared\_not\_enum}): + \begin{itemize} + \item $\ve$ is a variable expression for $\vx$, that is, $\EVar(\vx)$; + \item $\vx$ is associated with a type $\vt$ in the global environment of $\tenv$; + \item obtaining the \underlyingtype\ of $\vt$ in $\tenv$ yields a type that is not an enumeration type; + \item the result is $\None$. + \end{itemize} +\end{itemize} + +\subsubsection{Formally} +\begin{mathpar} +\inferrule[not\_evar]{ + \astlabel(\ve) \neq \EVar +}{ + \getvariableenum(\tenv, \ve) \typearrow \None +} +\end{mathpar} + +\begin{mathpar} +\inferrule[no\_declared\_type]{ + G^\tenv.\declaredtypes(\vx) \typearrow \None +}{ + \getvariableenum(\tenv, \overname{\EVar(\vx)}{\ve}) \typearrow \None +} +\end{mathpar} + +\begin{mathpar} +\inferrule[declared\_enum]{ + G^\tenv.\declaredtypes(\vx) \typearrow \langle\vt\rangle\\ + \makeanonymous(\tenv, \vt) \typearrow \TEnum(\vli) \OrTypeError +}{ + \getvariableenum(\tenv, \overname{\EVar(\vx)}{\ve}) \typearrow \langle(\vx, |\vli|)\rangle +} +\end{mathpar} + +\begin{mathpar} +\inferrule[declared\_not\_enum]{ + G^\tenv.\declaredtypes(\vx) \typearrow \langle\vt\rangle\\ + \makeanonymous(\tenv, \vt) \typearrow \vtone\\ + \astlabel(\vtone) \neq \TEnum +}{ + \getvariableenum(\tenv, \overname{\EVar(\vx)}{\ve}) \typearrow \None +} +\end{mathpar} + +\subsubsection{TypingRule.AnnotateStaticInteger\label{sec:TypingRule.AnnotateStaticInteger}} +\hypertarget{def-annotatestaticinteger}{} +The function +\[ + \annotatestaticinteger(\overname{\staticenvs}{\tenv} \aslsep \overname{\expr}{\ve}) \aslto + \overname{\expr}{\vepp} \cup \overname{\TTypeError}{\TypeErrorConfig} +\] +annotates a \staticallyevaluable\ integer expression $\ve$ in the static environment $\tenv$ +and returns the annotated expression $\vepp$. +\ProseOtherwiseTypeError + +\subsubsection{Prose} +All of the following apply: +\begin{itemize} + \item annotating the expression $\ve$ in $\tenv$ yields $ (\vt, \vep)$\ProseOrTypeError; + \item determining whether $\vt$ has the structure of an integer yields $\True$\ProseOrTypeError; + \item determining whether $\vep$ is \staticallyevaluable\ in $\tenv$ yields $\True$\ProseOrTypeError; + \item applying $\normalize$ to $\vep$ in $\tenv$ yields $\vepp$. +\end{itemize} +\subsubsection{Formally} +\begin{mathpar} +\inferrule{ + \annotateexpr{\tenv, \ve} \typearrow (\vt, \vep) \OrTypeError\\\\ + \checkstructureinteger(\tenv, \vt) \typearrow \True \OrTypeError\\\\ + \checkstaticallyevaluable(\tenv, \vep) \typearrow \True \OrTypeError\\\\ + \normalize(\tenv, \vep) \typearrow \vepp +}{ + \annotatestaticinteger(\tenv, \ve) \typearrow \vepp +} +\end{mathpar} +\CodeSubsection{\AnnotateStaticIntegerBegin}{\AnnotateStaticIntegerEnd}{../Typing.ml} + +\hypertarget{def-checkstructureinteger}{} +\subsubsection{TypingRule.CheckStructureInteger \label{sec:TypingRule.CheckStructureInteger}} +The function +\[ + \checkstructureinteger(\overname{\staticenvs}{\tenv} \aslsep \overname{\ty}{\vt}) \aslto + \{\True\} \cup \TTypeError +\] +returns $\True$ is $\vt$ is has the \structure\ an integer type and a type error otherwise. + +\subsubsection{Prose} +One of the following applies: +\begin{itemize} + \item All of the following apply (\textsc{okay}): + \begin{itemize} + \item determining the \structure\ of $\vt$ yields $\vtp$\ProseOrTypeError; + \item $\vtp$ is an integer type; + \item the result is $\True$; + \end{itemize} + + \item All of the following apply (\textsc{error}): + \begin{itemize} + \item determining the \structure\ of $\vt$ yields $\vtp$\ProseOrTypeError; + \item $\vtp$ is not an integer type; + \item the result is a type error indicating that $\vt$ was expected to have the \structure\ of an integer. + \end{itemize} +\end{itemize} + +\CodeSubsection{\CheckStructureIntegerBegin}{\CheckStructureIntegerEnd}{../Typing.ml} + +\subsubsection{Formally} +\begin{mathpar} +\inferrule[okay]{ + \tstruct(\vt) \typearrow \vtp \OrTypeError\\\\ + \astlabel(\vtp) = \TInt +} +{ + \checkstructureinteger(\tenv, \vt) \typearrow \True +} +\and +\inferrule[error]{ + \tstruct(\vt) \typearrow \vtp\\ + \astlabel(\vtp) \neq \TInt +} +{ + \checkstructureinteger(\tenv, \vt) \typearrow \TypeErrorVal{ExpectedIntegerStructure} +} +\end{mathpar} + +\section{Enumeration Types\label{sec:EnumerationTypes}} +\subsection{Syntax} +\begin{flalign*} +\Ntydecl \derives\ & \Tenumeration \parsesep \Tlbrace \parsesep \NTClist{\Tidentifier} \parsesep \Trbrace & +\end{flalign*} + +\subsection{Abstract Syntax} +\begin{flalign*} +\ty \derives\ & \TEnum(\overtext{\identifier^{*}}{labels}) & +\end{flalign*} + +\subsubsection{ASTRule.TyDecl.TEnum} +\begin{mathpar} +\inferrule{ + \buildtclist[\buildidentity](\vids) \astarrow \vidasts +}{ + { + \begin{array}{r} + \buildtydecl(\Ntydecl(\Tenumeration, \Tlbrace, \namednode{\vids}{\NTClist{\Tidentifier}}, \Trbrace)) \astarrow\\ + \overname{\TEnum(\vidasts)}{\vastnode} +\end{array} + } +} +\end{mathpar} + +\subsection{Typing Enumeration Types\label{sec:TypingEnumerationTypes}} +\subsubsection{TypingRule.TEnumDecl\label{sec:TypingRule.TEnumDecl}} + +\subsubsection{Prose} +All of the following apply: +\begin{itemize} + \item $\tty$ is the enumeration type with enumeration literals + $\vli$, that is, $\TEnum(\vli)$; + \item $\decl$ is $\True$, indicating that $\tty$ should be considered in the context of a declaration; + \item determining that $\vli$ does not contain duplicates yields $\True$\ProseOrTypeError; + \item determining that none of the labels in $\vli$ is declared in the global environment + yields $\True$\ProseOrTypeError; + \item $\newty$ is the enumeration type $\tty$. +\end{itemize} +\subsubsection{Formally} +\begin{mathpar} +\inferrule{ + \checknoduplicates(\vli) \typearrow \True \OrTypeError\\\\ + \vl \in \vli: \checkvarnotingenv{\tenv, \vl} \typearrow \True \OrTypeError +}{ + \annotatetype{\True, \tenv, \TEnum(\vli)} \typearrow \TEnum(\vli) +} +\CodeSubsection{\TEnumDeclBegin}{\TEnumDeclEnd}{../Typing.ml} + +\end{mathpar} +\lrmcomment{This is related to \identd{YZBQ}, \identr{DWSP}, \identi{MZXL}.} +\subsubsection{Example} +The following example declares a valid enumeration type: +\ASLExample{\typingtests/TypingRule.TEnumDecl.asl} + +\section{Record Types\label{sec:RecordTypes}} +\subsection{Syntax} +\begin{flalign*} +\Ntydecl \derives\ & \Trecord \parsesep \Nfieldsopt & +\end{flalign*} + +\subsection{Abstract Syntax} +\begin{flalign*} +\ty \derives\ & \TRecord(\Field^{*}) & +\end{flalign*} + +\subsubsection{ASTRule.TyDecl.TRecord} +\begin{mathpar} +\inferrule{}{ + \buildtydecl(\Ntydecl(\Trecord, \punnode{\Nfieldsopt})) \astarrow + \overname{\TRecord(\astof{\vfieldsopt})}{\vastnode} +} +\end{mathpar} + +\subsection{Typing Record Types\label{sec:TypingRecordTypes}} +\subsubsection{TypingRule.TStructuredDecl\label{sec:TypingRule.TStructuredDecl}} +\subsubsection{Prose} +All of the following apply: +\begin{itemize} + \item $\tty$ is a \structuredtype\ with AST label $L$; + \item the list of fields of $\tty$ is $\fields$; + \item $\decl$ is $\True$, indicating that $\tty$ should be considered in the context of a declaration; + \item $\fields$ is a list of pairs where the first element is an identifier and the second is a type --- $(\vx_i, \vt_i)$, for $i=1..k$; + \item checking that the list of field identifiers $\vx_{1..k}$ does not contain duplicates + yields $\True$\ProseOrTypeError; + \item annotating each field type $\vt_i$, for $i=1..k$, yields an annotated type $\vtp_i$ + \ProseOrTypeError; + \item $\fieldsp$ is the list with $(\vx_i, \vtp_i)$, for $i=1..k$; + \item $\newty$ is the AST node with AST label $L$ (either record type or exception type, + corresponding to the type $\tty$) and fields $\fieldsp$. +\end{itemize} + +\subsubsection{Formally} +\begin{mathpar} +\inferrule{ + L \in \{\TRecord, \TException\}\\ + \fields \eqname [i=1..k: (\vx_i, \vt_i)]\\ + \checknoduplicates(\vx_{1..k}) \typearrow \True \OrTypeError\\\\ + i=1..k: \annotatetype{\False, \tenv, \vt_i} \typearrow \vtp_i \OrTypeError\\\\ + \fieldsp \eqdef [i=1..k: (\vx_i, \vtp_i)] +}{ + \annotatetype{\True, \tenv, L(\fields)} \typearrow L(\fieldsp) +} +\end{mathpar} +\CodeSubsection{\TStructuredDeclBegin}{\TStructuredDeclEnd}{../Typing.ml} + +\subsubsection{Example} +In the following example, all the uses of record or exception types are well-typed: +\ASLExample{\typingtests/TypingRule.TRecordExceptionDecl.asl} + +\section{Exception Types\label{sec:ExceptionTypes}} +\subsection{Syntax} +\begin{flalign*} +\Ntydecl \derives\ & \Texception \parsesep \Nfieldsopt & +\end{flalign*} + +\subsection{Abstract Syntax} +\begin{flalign*} +\ty \derives\ & \TException(\Field^{*}) & +\end{flalign*} + +\subsubsection{ASTRule.TyDecl.TException} +\begin{mathpar} +\inferrule{}{ + \buildtydecl(\Ntydecl(\Texception, \punnode{\Nfieldsopt})) \astarrow + \overname{\TException(\astof{\vfieldsopt})}{\vastnode} +} +\end{mathpar} + +\section{Named Types\label{sec:NamedTypes}} +\subsection{Syntax} +\begin{flalign*} +\Nty \derives\ & \Tidentifier & +\end{flalign*} + +\subsection{Abstract Syntax} +\begin{flalign*} +\ty \derives\ & \TNamed(\overtext{\identifier}{type name}) & +\end{flalign*} + +\subsection{Typing Exception Types} +The rule for typing exception type is \nameref{sec:TypingRule.TStructuredDecl}. + +\subsubsection{ASTRule.Ty.TNamed} +\begin{mathpar} +\inferrule{}{ + \buildty(\Nty(\Tidentifier(\id))) \astarrow + \overname{\TNamed(\id)}{\vastnode} +} +\end{mathpar} + +\subsection{Typing Named Types\label{sec:TypingNamedTypes}} +\subsubsection{TypingRule.TNamed\label{sec:TypingRule.TNamed}} +\subsubsection{Prose} +All of the following apply: +\begin{itemize} + \item $\tty$ is the named type $\vx$, that is $\TNamed(\vx)$; + \item checking whether $\vx$ is associated with a declared type in $\tenv$ yields $\True$\ProseOrTypeError; + \item $\newty$ is $\tty$. +\end{itemize} +\subsubsection{Formally} +\begin{mathpar} +\inferrule{ + \checktrans{G^\tenv(\vx) \neq \bot}{\UndefinedIdentifier} \typearrow \True \OrTypeError +}{ + \annotatetype{\overname{\Ignore}{\vdecl}, \tenv, \overname{\TNamed(\vx)}{\tty}} \typearrow \overname{\TNamed(\vx)}{\newty} +} +\end{mathpar} +\CodeSubsection{\TNamedBegin}{\TNamedEnd}{../Typing.ml} + +\subsubsection{Example} +In the following example, all the uses of \texttt{MyType} are well-typed: +\ASLExample{\typingtests/TypingRule.TNamed.asl} + +\section{Declared Types} +A declared type can be ab enumeration type, a record type, an exception type, or an \anonymoustype. +\subsection{Syntax} +\begin{flalign*} +\Ntydecl \derives\ & \Nty & +\end{flalign*} + +\subsection{Abstract Syntax} +\subsubsection{ASTRule.TyDecl \label{sec:ASTRule.TyDecl}} +\begin{mathpar} +\inferrule[ty]{}{ + \buildtydecl(\Ntydecl(\punnode{\Nty})) \astarrow + \overname{\astof{\tty}}{\vastnode} +} +\end{mathpar} + +\subsection{Typing Declared Types} +\subsubsection{TypingRule.TNonDecl\label{sec:TypingRule.TNonDecl}} +\subsubsection{Prose} +All of the following apply: +\begin{itemize} + \item $\tty$ is a \structuredtype\ or an enumeration type; + \item $\decl$ is $\False$, indicating that $\tty$ should be considered to be outside the context of a declaration + of $\tty$; + \item a type error is returned, indicating that the use of anonymous form of enumerations, record, + and exceptions types is not allowed here. +\end{itemize} + +\subsubsection{Example} +In the following example, the use of a record type outside of a declaration is erroneous: +\ASLExample{\typingtests/TypingRule.TNonDecl.asl} + +\CodeSubsection{\TNonDeclBegin}{\TNonDeclEnd}{../Typing.ml} + +\subsubsection{Formally} +\begin{mathpar} +\inferrule{ + \astlabel(\tty) \in \{\TEnum, \TRecord, \TException\} +}{ + \annotatetype{\False, \tenv, \tty} \typearrow \TypeErrorVal{\AnnonymousFormNotAllowedHere} +} +\end{mathpar} + +\input{TypeDomains.tex} +\input{TypeAttributes.tex} +\input{RelationsOnTypes.tex} diff --git a/asllib/doc/introduction.tex b/asllib/doc/introduction.tex new file mode 100644 index 000000000..7f2ff3612 --- /dev/null +++ b/asllib/doc/introduction.tex @@ -0,0 +1,115 @@ +\chapter{Introduction\label{chap:Introduction}} + +The increasing importance of the Arm architecture coupled with the increasing use of formal verification of both +hardware and software make it important to have a readable, precise way of describing the majority of the Arm +architecture. This reference defines Arm’s Architecture Specification Language (ASL), which is the language +used in Arm’s architecture reference manuals to describe the Arm architecture. + +ASL is designed and used to specify architectures. As a formal +specification language it is designed to be accessible, understandable, and unambiguous to programmers, hardware +engineers, and hardware verification engineers, who collectively have quite a small intersection of languages they +all understand. It can intentionally under specify behaviors in the architecture being described. + +ASL is: +\begin{itemize} + \item a first-order language with strong static type-checking. + \item whitespace-insensitive. + \item imperative. +\end{itemize} + +ASL has support for: +\begin{itemize} + \item bitvectors: + \begin{itemize} + \item as a type. + \item as a literal constant. + \item bitvector concatenation. + \item bitvector constants with wildcards. + \item bitslices. + \item dependent types to support function overloading using bitvector lengths. + \item dependent types to reason about lengths of bitvectors. + \end{itemize} + \item unbounded arithmetic types “integer” and “real”. + \item exceptions. + \item enumerations. + \item arrays. + \item records. + \item call-by-value. + \item type inference. +\end{itemize} + +ASL does not have support for: +\begin{itemize} + \item references or pointers. + \item macros. + \item templates. + \item virtual functions. +\end{itemize} + +A \emph{specification} consists of a self-contained collection of ASL code. +\lrmcomment{\identd{GVBK}} +More specifically, a specification is the set of declarations written in ASL code which describe an architecture. + +\section{Example Specification 1} +\figref{spec1} shows a small example of a specification written in ASL. It consists of the following declarations: +\begin{itemize} + \item Global bitvectors \texttt{R0}, \texttt{R1}, and \texttt{R2} representing the state of the system. + \item A function \texttt{MyOR} demonstrating a simple bit-wise OR function of 2 bitvectors. + \item Initialization of \texttt{R0} and \texttt{R1} bitvectors. + \item Assignment of bitvector \texttt{R2} with the result of a function call. +\end{itemize} + +\begin{center} +\lstinputlisting[caption=Example specification 1\label{fi:spec1}]{\definitiontests/spec1.asl} +\end{center} + +\section{Example Specification 2} +\figref{spec2} shows a small example of a specification written in ASL. It consists of the following declarations: +\begin{itemize} +\item A global variable \texttt{COUNT} representing the state of the system. +\item A procedure \texttt{ColdReset} to initialize the state of the system when power is applied and the system is reset. + This interpretation of the function is a convention used in this particular specification. It is up to each + specification to decide the role of each function. +\item A procedure \texttt{Step} to advance the state of the system. That is, it defines the \emph{transition relation} of the system. + Again, this interpretation is a convention used in this particular specification, not part of the ASL language + itself. +\end{itemize} + +\begin{center} +\lstinputlisting[caption=Example specification 2\label{fi:spec2}]{\definitiontests/spec2.asl} +\end{center} + +\section{Example Specification 3} +\figref{spec3} shows a small example of a specification in ASL. It consists of the following declarations: +\begin{itemize} + \item A function \texttt{Dot8} which operates on 2 bitvectors a byte at a time. + \item A global variable \texttt{COUNT} to indicate the number of calls to the \texttt{Fib} function. + \item A function \texttt{Fib} demonstrating recursion. + \item Assignment of a global bitvector \texttt{X} with a call to the \texttt{Dot8} function. + \item Assignment of a variable from the result of a call to the recursive function \texttt{Fib}. + \item A function \texttt{main}. +\end{itemize} + +\begin{center} +\lstinputlisting[caption=Example specification 3\label{fi:spec3}]{\definitiontests/spec3.asl} +\end{center} + +The ASL type system and its semantics are defined in terms of +the the ASL abstract syntax (\chapref{AbstractSyntax}). +Familiarity with the AST is \underline{required} to understand both. +The mathematical background needed to understand the formalization +of the ASL type system and ASL semantics appears in \chapref{FormalSystem}, +\chapref{TypeChecking}, and \chapref{Semantics}. + +% \section{The Language Pipeline} +% \begin{description} +% \item[Lexical Analysis] The text is first transformed into a list of \emph{tokens}. +% This stage is defined in \secref{lexicalanalysis}; +% \item[Parsing] The list of tokens is transformed into a \emph{parse tree}. +% This stage is defined in \secref{parsing}; +% \item[Abstraction] The parse tree is transformed into an abstract syntax tree. This is a conceptual stage. In actuality, +% the parsing stage transforms the list of tokens directly into an abstract syntax tree. However, it is useful to +% distinguish between the parsing state and the abstraction stage. +% ASL abstract syntax trees are defined in \chapref{ASLAbstractSyntax}. +% This stage is defined in \chapref{BuildingAbstractSyntaxTrees}. +% \end{description} \ No newline at end of file diff --git a/asllib/env.ml b/asllib/env.ml index aa0e7ba13..8debcc35d 100644 --- a/asllib/env.ml +++ b/asllib/env.ml @@ -98,11 +98,13 @@ module RunTime (C : RunTimeConf) = struct type 'a env_result = Local of 'a | Global of 'a | NotFound + (* Begin SemanticsRule.EnvFind *) let find x env = try Local (Storage.find x env.local.storage) with Not_found -> ( try Global (Storage.find x env.global.storage) with Not_found -> NotFound) + (* End *) let mem x env = Storage.mem x env.local.storage || Storage.mem x env.global.storage diff --git a/asllib/instrumentation.ml b/asllib/instrumentation.ml index 29282589c..85e0ef023 100644 --- a/asllib/instrumentation.ml +++ b/asllib/instrumentation.ml @@ -24,15 +24,13 @@ module SemanticsRule = struct type t = - | Lit + | ELit | Call | ATC | EExprList | EExprListM | ESideEffectFreeExpr - | ELocalVar - | EGlobalVar - | EUndefIdent + | EVar | Binop | BinopAnd | BinopOr @@ -52,8 +50,7 @@ module SemanticsRule = struct | EUnknown | EPattern | LEDiscard - | LELocalVar - | LEGlobalVar + | LEVar | LEMultiAssign | LEUndefIdentV0 | LEUndefIdentV1 @@ -63,10 +60,7 @@ module SemanticsRule = struct | LESetFields | LEDestructuring | Slices - | SliceSingle - | SliceLength - | SliceRange - | SliceStar + | Slice | PAll | PAny | PGeq @@ -80,13 +74,10 @@ module SemanticsRule = struct | LDVar | LDTyped | LDTuple - | LDUninitialisedTyped | SPass | SAssignCall | SAssign - | SReturnOne - | SReturnSome - | SReturnNone + | SReturn | SSeq | SCall | SCond @@ -95,12 +86,9 @@ module SemanticsRule = struct | SWhile | SRepeat | SFor - | SThrowNone - | SThrowSomeTyped - | SThrowSome + | SThrow | STry - | SDeclSome - | SDeclNone + | SDecl | SDebug | FUndefIdent | FPrimitive @@ -121,14 +109,13 @@ module SemanticsRule = struct | BuildGlobalEnv let to_string : t -> string = function - | Lit -> "Lit" + | ELit -> "ELit" | Call -> "Call" | ATC -> "CTC" | EExprList -> "EExprList" | EExprListM -> "EExprListM" | ESideEffectFreeExpr -> "ESideEffectFreeExpr" - | ELocalVar -> "ELocalVar" - | EGlobalVar -> "EGlobalVar" + | EVar -> "EVar" | Binop -> "Binop" | BinopAnd -> "BinopAnd" | BinopOr -> "BinopOr" @@ -142,15 +129,13 @@ module SemanticsRule = struct | EGetBitFields -> "EGetBitFields" | EConcat -> "EConcat" | ETuple -> "ETuple" - | EUndefIdent -> "EUndefIdent" | ECondSimple -> "ECondSimple" | EGetArray -> "EGetArray" | ESliceOrEGetArrayError -> "ESliceOrEGetArrayError" | EUnknown -> "EUnknown" | EPattern -> "EPattern" | LEDiscard -> "LEDiscard" - | LELocalVar -> "LELocalVar" - | LEGlobalVar -> "LEGlobalVar" + | LEVar -> "LEVar" | LEMultiAssign -> "LEMultiAssign" | LESlice -> "LESlice" | LESetArray -> "LESetArray" @@ -160,10 +145,7 @@ module SemanticsRule = struct | LEUndefIdentV0 -> "LEUndefIdentV0" | LEUndefIdentV1 -> "LEUndefIdentV1" | Slices -> "Slices" - | SliceSingle -> "SliceSingle" - | SliceLength -> "SliceLength" - | SliceRange -> "SliceRange" - | SliceStar -> "SliceStar" + | Slice -> "Slice" | PAll -> "PAll" | PAny -> "PAny" | PGeq -> "PGeq" @@ -177,13 +159,10 @@ module SemanticsRule = struct | LDVar -> "LDVar" | LDTyped -> "LDTyped" | LDTuple -> "LDTuple" - | LDUninitialisedTyped -> "LDUninitialisedTyped" | SPass -> "SPass" | SAssignCall -> "SAssignCall" | SAssign -> "SAssign" - | SReturnOne -> "SReturnOne" - | SReturnNone -> "SReturnNone" - | SReturnSome -> "SReturnSome" + | SReturn -> "SReturn" | SSeq -> "SThen" | SCall -> "SCall" | SCond -> "SCond" @@ -192,12 +171,9 @@ module SemanticsRule = struct | SWhile -> "SWhile" | SRepeat -> "SRepeat" | SFor -> "SFor" - | SThrowNone -> "SThrowNone" - | SThrowSomeTyped -> "SThrowSomeTyped" - | SThrowSome -> "SThrowSome" + | SThrow -> "SThrow" | STry -> "STry" - | SDeclSome -> "SDeclSome" - | SDeclNone -> "SDeclNone" + | SDecl -> "SDecl" | SDebug -> "SDebug" | FUndefIdent -> "FUndefIdent" | FPrimitive -> "FPrimitive" @@ -221,15 +197,13 @@ module SemanticsRule = struct let all = [ - Lit; + ELit; Call; ATC; EExprList; EExprListM; ESideEffectFreeExpr; - ELocalVar; - EGlobalVar; - EUndefIdent; + EVar; Binop; BinopAnd; BinopOr; @@ -249,8 +223,7 @@ module SemanticsRule = struct EUnknown; EPattern; LEDiscard; - LELocalVar; - LEGlobalVar; + LEVar; LEMultiAssign; LEUndefIdentV0; LEUndefIdentV1; @@ -260,10 +233,7 @@ module SemanticsRule = struct LESetFields; LEDestructuring; Slices; - SliceSingle; - SliceLength; - SliceRange; - SliceStar; + Slice; PAll; PAny; PGeq; @@ -277,13 +247,10 @@ module SemanticsRule = struct LDVar; LDTyped; LDTuple; - LDUninitialisedTyped; SPass; SAssignCall; SAssign; - SReturnOne; - SReturnSome; - SReturnNone; + SReturn; SSeq; SCall; SCond; @@ -292,12 +259,9 @@ module SemanticsRule = struct SWhile; SRepeat; SFor; - SThrowNone; - SThrowSomeTyped; - SThrowSome; + SThrow; STry; - SDeclSome; - SDeclNone; + SDecl; SDebug; FUndefIdent; FPrimitive; @@ -409,10 +373,7 @@ module TypingRule = struct | LESetBadField | LESetFields | LEConcat - | SliceSingle - | SliceLength - | SliceRange - | SliceStar + | Slice | PAll | PAny | PGeq @@ -432,9 +393,7 @@ module TypingRule = struct | SPass | SAssignCall | SAssign - | SReturnOne - | SReturnSome - | SReturnNone + | SReturn | SSeq | SCall | SCond @@ -443,9 +402,7 @@ module TypingRule = struct | SWhile | SRepeat | SFor - | SThrowNone - | SThrowSomeTyped - | SThrowSome + | SThrow | STry | SDeclSome | SDeclNone @@ -459,8 +416,7 @@ module TypingRule = struct | Block | Loop | For - | CatcherNone - | CatcherSome + | Catcher | Subprogram | DeclareOneFunc | DeclareGlobalStorage @@ -475,7 +431,7 @@ module TypingRule = struct | TTuple | TArray | TEnumDecl - | TRecordExceptionDecl + | TStructuredDecl | TNonDecl | TBitField | TBitFields @@ -503,6 +459,10 @@ module TypingRule = struct | FoldEnvAndFs | AnnotateLoopLimit | CheckATC + | CheckSlicesInWidth + | DisjointSlicesToPositions + | CheckPositionsInWidth + | ShouldReduceToCall let to_string : t -> string = function | BuiltinSingularType -> "BuiltinSingularType" @@ -569,10 +529,7 @@ module TypingRule = struct | LEDestructuring -> "LEDestructuring" | LEUndefIdentV0 -> "LEUndefIdentV0" | LEUndefIdentV1 -> "LEUndefIdentV1" - | SliceSingle -> "SliceSingle" - | SliceLength -> "SliceLength" - | SliceRange -> "SliceRange" - | SliceStar -> "SliceStar" + | Slice -> "Slice" | PAll -> "PAll" | PAny -> "PAny" | PGeq -> "PGeq" @@ -592,9 +549,7 @@ module TypingRule = struct | SPass -> "SPass" | SAssignCall -> "SAssignCall" | SAssign -> "SAssign" - | SReturnOne -> "SReturnOne" - | SReturnNone -> "SReturnNone" - | SReturnSome -> "SReturnSome" + | SReturn -> "SReturn" | SSeq -> "SThen" | SCall -> "SCall" | SCond -> "SCond" @@ -603,9 +558,7 @@ module TypingRule = struct | SWhile -> "SWhile" | SRepeat -> "SRepeat" | SFor -> "SFor" - | SThrowNone -> "SThrowNone" - | SThrowSomeTyped -> "SThrowSomeTyped" - | SThrowSome -> "SThrowSome" + | SThrow -> "SThrow" | STry -> "STry" | SDeclSome -> "SDeclSome" | SDeclNone -> "SDeclNone" @@ -619,8 +572,7 @@ module TypingRule = struct | Block -> "Block" | Loop -> "Loop" | For -> "For" - | CatcherNone -> "CatcherNone" - | CatcherSome -> "CatcherSome" + | Catcher -> "Catcher" | Subprogram -> "Subprogram" | DeclareOneFunc -> "DeclareOneFunc" | DeclareGlobalStorage -> "DeclareGlobalStorage" @@ -635,7 +587,7 @@ module TypingRule = struct | TTuple -> "TTuple" | TArray -> "TArray" | TEnumDecl -> "TEnumDecl" - | TRecordExceptionDecl -> "TRecordExceptionDecl" + | TStructuredDecl -> "TStructuredDecl" | TNonDecl -> "TNonDecl" | TBitField -> "TBitField" | TBitFields -> "TBitFields" @@ -663,6 +615,10 @@ module TypingRule = struct | FoldEnvAndFs -> "FoldEnvAndFs" | AnnotateLoopLimit -> "AnnotateLoopLimit" | CheckATC -> "CheckATC" + | CheckSlicesInWidth -> "CheckSlicesInWidth" + | DisjointSlicesToPositions -> "DisjointSlicesToPositions" + | CheckPositionsInWidth -> "CheckPositionsInWidth" + | ShouldReduceToCall -> "ShouldReduceToCall" let pp f r = to_string r |> Format.pp_print_string f @@ -731,16 +687,11 @@ module TypingRule = struct LESetFields; LEDestructuring; LEConcat; - SliceLength; - SliceSingle; - SliceRange; - SliceStar; + Slice; SPass; SAssignCall; SAssign; - SReturnOne; - SReturnSome; - SReturnNone; + SReturn; SSeq; SCall; SCond; @@ -749,9 +700,7 @@ module TypingRule = struct SWhile; SRepeat; SFor; - SThrowNone; - SThrowSomeTyped; - SThrowSome; + SThrow; STry; SDeclSome; SDeclNone; @@ -765,8 +714,7 @@ module TypingRule = struct Block; Loop; For; - CatcherNone; - CatcherSome; + Catcher; Subprogram; TString; TReal; @@ -777,7 +725,7 @@ module TypingRule = struct TTuple; TArray; TEnumDecl; - TRecordExceptionDecl; + TStructuredDecl; TNonDecl; TBitField; TBitFields; @@ -805,6 +753,10 @@ module TypingRule = struct FoldEnvAndFs; AnnotateLoopLimit; CheckATC; + CheckSlicesInWidth; + DisjointSlicesToPositions; + CheckPositionsInWidth; + ShouldReduceToCall; ] let all_nb = List.length all diff --git a/asllib/tests/ASLDefinition.t/Bitfields.asl b/asllib/tests/ASLDefinition.t/Bitfields.asl new file mode 100644 index 000000000..c996dd76b --- /dev/null +++ b/asllib/tests/ASLDefinition.t/Bitfields.asl @@ -0,0 +1,5 @@ +var myData: bits(16) { + [4] flag, + [3:0, 8:5] data, + [9:0] value +}; diff --git a/asllib/tests/ASLDefinition.t/Bitfields_nested.asl b/asllib/tests/ASLDefinition.t/Bitfields_nested.asl new file mode 100644 index 000000000..4edb753e8 --- /dev/null +++ b/asllib/tests/ASLDefinition.t/Bitfields_nested.asl @@ -0,0 +1,33 @@ +type Nested_Type of bits(32) { + [31:15] fmt0 { + [15] common, + [14] moving + }, + [31:15] fmt1 { + [15] common, + [0] moving + }, + [31] common, + [0] fmt // format choice +}; + +var nested : Nested_Type = '10101010101010101010101010101010'; + +// select the correct view of moving +// nested.fmt is '0' +// nested.fmt0.moving is nested[30] +// nested.fmt is '1' +// nested.fmt1.moving is nested[16] +let moving = if nested.fmt == '0' then nested.fmt0.moving + else nested.fmt1.moving; + +func main() => integer +begin +// below are all equivalent to nested[31] + let common = nested.common; + let common_fmt0 = nested.fmt0.common; + let common_fmt1 = nested.fmt1.common; + assert common == common_fmt0; + assert common == common_fmt1; + return 0; +end \ No newline at end of file diff --git a/asllib/tests/ASLDefinition.t/run.t b/asllib/tests/ASLDefinition.t/run.t index 093805eb0..1055f765a 100644 --- a/asllib/tests/ASLDefinition.t/run.t +++ b/asllib/tests/ASLDefinition.t/run.t @@ -2,3 +2,5 @@ Examples used in ASL High-level Definition: $ aslref --no-exec spec1.asl $ aslref --no-exec spec2.asl $ aslref spec3.asl + + $ aslref --no-exec Bitfields.asl diff --git a/asllib/tests/ASLSemanticsReference.t/SemanticsRule.ATCVariousErrors.asl b/asllib/tests/ASLSemanticsReference.t/SemanticsRule.ATCVariousErrors.asl index a020488e3..ed405c656 100644 --- a/asllib/tests/ASLSemanticsReference.t/SemanticsRule.ATCVariousErrors.asl +++ b/asllib/tests/ASLSemanticsReference.t/SemanticsRule.ATCVariousErrors.asl @@ -4,7 +4,8 @@ begin var b: integer{4, 5, 6} = 2; // static error var c: integer{4, 5, 6} = 2 as integer{4, 5, 6}; // dynamic error if FALSE then - var d: integer{4, 5, 6} = 2; // static error - var e: integer{4, 5, 6} = 2 as integer{4, 5, 6}; // not a dynamic error as will never be evaluated + var d: integer{4, 5, 6} = 2; // static error. + // The following is not a dynamic error as will never be evaluated, + var e: integer{4, 5, 6} = 2 as integer{4, 5, 6}; end end diff --git a/asllib/tests/ASLSyntaxReference.t/expr1.asl b/asllib/tests/ASLSyntaxReference.t/expr1.asl index afabe9ba5..81d080dd8 100644 --- a/asllib/tests/ASLSyntaxReference.t/expr1.asl +++ b/asllib/tests/ASLSyntaxReference.t/expr1.asl @@ -1,12 +1,6 @@ -getter g_no_args => integer -begin - return 0; -end +getter g_no_args => integer begin return 0; end -getter g0_bits[] => bits(4) -begin - return '1000'; -end +getter g0_bits[] => bits(4) begin return '1000'; end getter g1_bits[p: integer] => bits(4) begin @@ -30,16 +24,16 @@ begin // E_Slice 4: g1_bits[3] is a call to a getter. assert b0 == g1_bits[3]; var bits_arr : array [1] of bits(4); - // E_Binop: 1: b0 == b1 is a binary expression for ==. + // E_Binop 1: b0 == b1 is a binary expression for ==. // E_Cond 1: the right-hand side of the assignment is // a conditional expression. bits_arr[0] = if (b0 == b1) then '1000' else '0000'; // E_Slice 5: bits_arr[0] stands for an array access assert b0 == bits_arr[0]; - // E_Unop 1 : (NOT b8) negate the bits of b8. - // E_Binop 2 : the right-hand side of the assignment is - // a binay AND expression. - // E_Concat 1 : [b0, b1] concatenates two bitvectors. + // E_Unop 1: (NOT b8) negates the bits of b8. + // E_Binop 2: the right-hand side of the assignment is + // a binay AND expression. + // E_Concat 1: [b0, b1] concatenates two bitvectors. // E_Unknown 1: UNKNOWN: bits(8) represents an arbitrary // 8-bits bitvector var b8 = [b0, b1]; diff --git a/asllib/tests/ASLTypingReference.t/TypingRule.TArray.asl b/asllib/tests/ASLTypingReference.t/TypingRule.TArray.asl index a8f9271c8..9d5dd7465 100644 --- a/asllib/tests/ASLTypingReference.t/TypingRule.TArray.asl +++ b/asllib/tests/ASLTypingReference.t/TypingRule.TArray.asl @@ -1,6 +1,11 @@ -type MyType of array [4] of integer; +// Declare an array of reals from arr1[0] to arr1[3] +type arr1 of array [4] of real; -func foo (x: array [4] of integer) => array [4] of integer +// Declare an array with two entries arr2[big] and arr2[little] +type labels of enumeration {big, little}; +type arr2 of array [labels] of bits(4); + +func foo(x: array [4] of integer) => array [4] of integer begin var y = x; y[3] = 2; @@ -10,13 +15,9 @@ end func main () => integer begin var x: array [4] of integer; - x[1] = 1; print(x); x = foo (x as array [4] of integer); - let y: array [4] of integer = x; - - return 0; end diff --git a/asllib/tests/ASLTypingReference.t/TypingRule.TBitField.asl b/asllib/tests/ASLTypingReference.t/TypingRule.TBitField.asl index fa2ad33fb..001ce7604 100644 --- a/asllib/tests/ASLTypingReference.t/TypingRule.TBitField.asl +++ b/asllib/tests/ASLTypingReference.t/TypingRule.TBitField.asl @@ -1,6 +1,7 @@ type MyType of bits(4) { [3:2] A, [1] B }; -func foo (x: bits(4) { [3:2] A, [1] B }) => bits(4) { [3:2] A, [1] B } +func foo (x: bits(4) { [3:2] A, [1] B }) => + bits(4) { [3:2] A, [1] B } begin return x; end @@ -11,7 +12,7 @@ begin x = '1010'; x = foo (x as bits(4) { [3:2] A, [1] B }); - + let y: bits(4) { [3:2] A, [1] B } = x; assert x as bits(4) { [3:2] A, [1] B } == x;