diff options
Diffstat (limited to 'language')
| -rw-r--r-- | language/Makefile | 10 | ||||
| -rw-r--r-- | language/l2.ml | 481 | ||||
| -rw-r--r-- | language/l2.ott | 645 | ||||
| -rw-r--r-- | language/l2_parse2.ott | 1424 | ||||
| -rw-r--r-- | language/l2_rules.ott | 1565 | ||||
| -rw-r--r-- | language/sil.ott | 451 |
6 files changed, 2521 insertions, 2055 deletions
diff --git a/language/Makefile b/language/Makefile index 9167d65f..081d90a7 100644 --- a/language/Makefile +++ b/language/Makefile @@ -4,7 +4,7 @@ OTT=../../../github/ott/src/ott OTTLIB=$(dir $(shell which ott))../hol .PHONY: all -all: l2.ml l2_parse.ml l2.lem +all: l2.ml l2_parse.ml l2.lem l2_parse2.ml l2_parse2_parser.mly docs: l2.pdf l2_parse.pdf @@ -18,7 +18,7 @@ type_system.pdf: doc_in.tex type_system.tex pdflatex type_system.tex pdflatex type_system.tex -l2.tex: l2.ott l2_terminals_non_tt.ott l2_typ.ott l2_rules.ott +l2.tex: l2.ott l2_rules.ott # l2_terminals_non_tt.ott l2_typ.ott l2_rules.ott $(OTT) -sort false -generate_aux_rules false -o $@ -picky_multiple_parses true $^ doc_in.tex: l2.ott primitive_doc.ott l2_terminals_tt.ott l2_typ.ott l2_rules.ott @@ -36,6 +36,12 @@ doc_in.tex: l2.ott primitive_doc.ott l2_terminals_tt.ott l2_typ.ott l2_rules.ott l2.lem: l2.ott $(OTT) -sort false -generate_aux_rules true -o $@ -picky_multiple_parses true $^ +ROOT=l2_parse2 +# generate the ocaml AST type, ocamllex lexer, menhir parser, and ocaml pretty printers for the AST, all from the Ott soruce +$(ROOT)_ast.ml $(ROOT)_lexer.mll $(ROOT)_parser.mly $(ROOT)_parser_pp.ml $(ROOT)_ast.tex : $(ROOT).ott Makefile + $(OTT) -quotient_rules false -generate_aux_rules false -i $(ROOT).ott -o $(ROOT)_parser.mly -o $(ROOT)_lexer.mll -o $(ROOT)_ast.ml -o $(ROOT).tex + + clean: rm -rf *~ rm -rf *.uo *.ui *.sig *.sml .HOLMK diff --git a/language/l2.ml b/language/l2.ml index 13cb2567..c59ce838 100644 --- a/language/l2.ml +++ b/language/l2.ml @@ -1,18 +1,33 @@ -(* generated by Ott 0.25 from: l2.ott *) +(* generated by Ott 0.26 from: l2.ott *) +type text = string + +type l = Parse_ast.l + type 'a annot = l * 'a +type loop = While | Until + -type x = string (* identifier *) -type ix = string (* infix identifier *) +type x = text (* identifier *) +type ix = text (* infix identifier *) type base_kind_aux = (* base kind *) BK_type (* kind of types *) | BK_nat (* kind of natural number size expressions *) | BK_order (* kind of vector order specifications *) - | BK_effect (* kind of effect sets *) + + +type +base_kind = + BK_aux of base_kind_aux * Parse_ast.l + + +type +kind_aux = (* kinds *) + K_kind of (base_kind) list type @@ -21,14 +36,14 @@ kid_aux = (* kinded IDs: $_$, $_$, $_$, and $_$ variables *) type -id_aux = (* identifier *) +id_aux = (* Identifier *) Id of x | DeIid of x (* remove infix status *) type -base_kind = - BK_aux of base_kind_aux * Parse_ast.l +kind = + K_aux of kind_aux * Parse_ast.l type @@ -42,31 +57,6 @@ id = type -kind_aux = (* kinds *) - K_kind of (base_kind) list - - -type -nexp_aux = (* numeric expression, of kind $_$ *) - Nexp_id of id (* abbreviation identifier *) - | Nexp_var of kid (* variable *) - | Nexp_constant of int (* constant *) - | Nexp_times of nexp * nexp (* product *) - | Nexp_sum of nexp * nexp (* sum *) - | Nexp_minus of nexp * nexp (* subtraction *) - | Nexp_exp of nexp (* exponential *) - | Nexp_neg of nexp (* for internal use only *) - -and nexp = - Nexp_aux of nexp_aux * Parse_ast.l - - -type -kind = - K_aux of kind_aux * Parse_ast.l - - -type base_effect_aux = (* effect *) BE_rreg (* read register *) | BE_wreg (* write register *) @@ -88,6 +78,21 @@ base_effect_aux = (* effect *) type +nexp_aux = (* numeric expression, of kind $_$ *) + Nexp_id of id (* abbreviation identifier *) + | Nexp_var of kid (* variable *) + | Nexp_constant of int (* constant *) + | Nexp_times of nexp * nexp (* product *) + | Nexp_sum of nexp * nexp (* sum *) + | Nexp_minus of nexp * nexp (* subtraction *) + | Nexp_exp of nexp (* exponential *) + | Nexp_neg of nexp (* for internal use only *) + +and nexp = + Nexp_aux of nexp_aux * Parse_ast.l + + +type base_effect = BE_aux of base_effect_aux * Parse_ast.l @@ -116,27 +121,30 @@ effect = type -n_constraint_aux = (* constraint over kind $_$ *) - NC_fixed of nexp * nexp - | NC_bounded_ge of nexp * nexp - | NC_bounded_le of nexp * nexp - | NC_nat_set_bounded of kid * (int) list - - -type kinded_id_aux = (* optionally kind-annotated identifier *) KOpt_none of kid (* identifier *) | KOpt_kind of kind * kid (* kind-annotated variable *) type -n_constraint = - NC_aux of n_constraint_aux * Parse_ast.l +kinded_id = + KOpt_aux of kinded_id_aux * Parse_ast.l type -kinded_id = - KOpt_aux of kinded_id_aux * Parse_ast.l +n_constraint_aux = (* constraint over kind $_$ *) + NC_equal of nexp * nexp + | NC_bounded_ge of nexp * nexp + | NC_bounded_le of nexp * nexp + | NC_not_equal of nexp * nexp + | NC_set of kid * (int) list + | NC_or of n_constraint * n_constraint + | NC_and of n_constraint * n_constraint + | NC_true + | NC_false + +and n_constraint = + NC_aux of n_constraint_aux * Parse_ast.l type @@ -146,19 +154,23 @@ quant_item_aux = (* kinded identifier or $_$ constraint *) type -quant_item = - QI_aux of quant_item_aux * Parse_ast.l - - -type -typquant_aux = (* type quantifiers and constraints *) - TypQ_tq of (quant_item) list - | TypQ_no_forall (* empty *) +lit_aux = (* literal constant *) + L_unit (* $() : _$ *) + | L_zero (* $_ : _$ *) + | L_one (* $_ : _$ *) + | L_true (* $_ : _$ *) + | L_false (* $_ : _$ *) + | L_num of int (* natural number constant *) + | L_hex of string (* bit vector constant, C-style *) + | L_bin of string (* bit vector constant, C-style *) + | L_string of string (* string constant *) + | L_undef (* undefined-value constant *) + | L_real of string type -typquant = - TypQ_aux of typquant_aux * Parse_ast.l +quant_item = + QI_aux of quant_item_aux * Parse_ast.l type @@ -168,6 +180,7 @@ typ_aux = (* type expressions, of kind $_$ *) | Typ_var of kid (* type variable *) | Typ_fn of typ * typ * effect (* Function (first-order only in user code) *) | Typ_tup of (typ) list (* Tuple *) + | Typ_exist of (kid) list * n_constraint * typ | Typ_app of id * (typ_arg) list (* type constructor application *) and typ = @@ -177,49 +190,20 @@ and typ_arg_aux = (* type constructor arguments of all kinds *) Typ_arg_nexp of nexp | Typ_arg_typ of typ | Typ_arg_order of order - | Typ_arg_effect of effect and typ_arg = Typ_arg_aux of typ_arg_aux * Parse_ast.l type -lit_aux = (* literal constant *) - L_unit (* $() : _$ *) - | L_zero (* $_ : _$ *) - | L_one (* $_ : _$ *) - | L_true (* $_ : _$ *) - | L_false (* $_ : _$ *) - | L_num of int (* natural number constant *) - | L_hex of string (* bit vector constant, C-style *) - | L_bin of string (* bit vector constant, C-style *) - | L_string of string (* string constant *) - | L_undef (* undefined-value constant *) - - -type -typschm_aux = (* type scheme *) - TypSchm_ts of typquant * typ - - -type -index_range_aux = (* index specification, for bitfields in register types *) - BF_single of int (* single index *) - | BF_range of int * int (* index range *) - | BF_concat of index_range * index_range (* concatenation of index ranges *) - -and index_range = - BF_aux of index_range_aux * Parse_ast.l - - -type lit = L_aux of lit_aux * Parse_ast.l type -typschm = - TypSchm_aux of typschm_aux * Parse_ast.l +typquant_aux = (* type quantifiers and constraints *) + TypQ_tq of (quant_item) list + | TypQ_no_forall (* empty *) type @@ -229,13 +213,14 @@ type | P_as of 'a pat * id (* named pattern *) | P_typ of typ * 'a pat (* typed pattern *) | P_id of id (* identifier *) + | P_var of 'a pat * kid (* bind pattern to type variable *) | P_app of id * ('a pat) list (* union constructor pattern *) | P_record of ('a fpat) list * bool (* struct pattern *) | P_vector of ('a pat) list (* vector pattern *) - | P_vector_indexed of ((int * 'a pat)) list (* vector pattern (with explicit indices) *) | P_vector_concat of ('a pat) list (* concatenated vector pattern *) | P_tup of ('a pat) list (* tuple pattern *) | P_list of ('a pat) list (* list pattern *) + | P_cons of 'a pat * 'a pat (* Cons patterns *) and 'a pat = P_aux of 'a pat_aux * 'a annot @@ -248,6 +233,11 @@ and 'a fpat = type +typquant = + TypQ_aux of typquant_aux * Parse_ast.l + + +type name_scm_opt_aux = (* optional variable naming-scheme constraint *) Name_sect_none | Name_sect_some of string @@ -260,6 +250,11 @@ type_union_aux = (* type union constructors *) type +typschm_aux = (* type scheme *) + TypSchm_ts of typquant * typ + + +type name_scm_opt = Name_sect_aux of name_scm_opt_aux * Parse_ast.l @@ -270,17 +265,27 @@ type_union = type +typschm = + TypSchm_aux of typschm_aux * Parse_ast.l + + +type +index_range_aux = (* index specification, for bitfields in register types *) + BF_single of int (* single index *) + | BF_range of int * int (* index range *) + | BF_concat of index_range * index_range (* concatenation of index ranges *) + +and index_range = + BF_aux of index_range_aux * Parse_ast.l + + +type 'a kind_def_aux = (* Definition body for elements of kind *) KD_nabbrev of kind * id * name_scm_opt * nexp (* $_$-expression abbreviation *) - | KD_abbrev of kind * id * name_scm_opt * typschm (* type abbreviation *) - | KD_record of kind * id * name_scm_opt * typquant * ((typ * id)) list * bool (* struct type definition *) - | KD_variant of kind * id * name_scm_opt * typquant * (type_union) list * bool (* union type definition *) - | KD_enum of kind * id * name_scm_opt * (id) list * bool (* enumeration type definition *) - | KD_register of kind * id * nexp * nexp * ((index_range * id)) list (* register mutable bitfield type definition *) type -'a type_def_aux = (* type definition body *) +type_def_aux = (* type definition body *) TD_abbrev of id * name_scm_opt * typschm (* type abbreviation *) | TD_record of id * name_scm_opt * typquant * ((typ * id)) list * bool (* struct type definition *) | TD_variant of id * name_scm_opt * typquant * (type_union) list * bool (* tagged union type definition *) @@ -293,146 +298,8 @@ type KD_aux of 'a kind_def_aux * 'a annot -type -'a type_def = - TD_aux of 'a type_def_aux * 'a annot - - -type -ne = (* internal numeric expressions *) - Ne_id of x - | Ne_var of x - | Ne_const of int - | Ne_inf - | Ne_mult of ne * ne - | Ne_add of (ne) list - | Ne_minus of ne * ne - | Ne_exp of ne - | Ne_unary of ne - - -type -t = (* Internal types *) - T_id of x - | T_var of x - | T_fn of t * t * effect - | T_tup of (t) list - | T_app of x * t_args - | T_abbrev of t * t - -and t_arg = (* Argument to type constructors *) - T_arg_typ of t - | T_arg_nexp of ne - | T_arg_effect of effect - | T_arg_order of order - -and t_args = (* Arguments to type constructors *) - T_args of (t_arg) list - - -type -k = (* Internal kinds *) - Ki_typ - | Ki_nat - | Ki_ord - | Ki_efct - | Ki_ctor of (k) list * k - | Ki_infer (* Representing an unknown kind, inferred by context *) - - -type -tid = (* A type identifier or type variable *) - Tid_id of id - | Tid_var of kid - - -type -kinf = (* Whether a kind is default or from a local binding *) - Kinf_k of k - | Kinf_def of k - - -type -nec = (* Numeric expression constraints *) - Nec_lteq of ne * ne - | Nec_eq of ne * ne - | Nec_gteq of ne * ne - | Nec_in of x * (int) list - | Nec_cond of (nec) list * (nec) list - | Nec_branch of (nec) list - - -type -tag = (* Data indicating where the identifier arises and thus information necessary in compilation *) - Tag_empty - | Tag_intro (* Denotes an assignment and lexp that introduces a binding *) - | Tag_set (* Denotes an expression that mutates a local variable *) - | Tag_tuple_assign (* Denotes an assignment with a tuple lexp *) - | Tag_global (* Globally let-bound or enumeration based value/variable *) - | Tag_ctor (* Data constructor from a type union *) - | Tag_extern of string option (* External function, specied only with a val statement *) - | Tag_default (* Type has come from default declaration, identifier may not be bound locally *) - | Tag_spec - | Tag_enum of int - | Tag_alias - | Tag_unknown of string option (* Tag to distinguish an unknown path from a non-analysis non deterministic path *) - - -type -tinf = (* Type variables, type, and constraints, bound to an identifier *) - Tinf_typ of t - | Tinf_quant_typ of e_k * s_N * tag * t - - -type -conformsto = (* how much conformance does overloading need *) - Conformsto_full - | Conformsto_parm - - -type -widennum = - Widennum_widen - | Widennum_dont - | Widennum_dontcare - - -type -widenvec = - Widenvec_widen - | Widenvec_dont - | Widenvec_dontcare - - -type -widening = (* Should we widen vector start locations, should we widen atoms and ranges *) - Widening_w of widennum * widenvec - - -type -tinflist = (* In place so that a list of tinfs can be referred to without the dot form *) - Tinfs_empty - | Tinfs_ls of (tinf) list - - -type -i = (* Information given by type checking an expression *) - I of s_N * effect - | Iempty (* Empty constraints, effect *) - | Singleunion of i * i - | Iunion of (i) list (* Unions the constraints and effect *) - - -type -e = (* Definition environment and lexical environment *) - E of e_t * e_d - | E_union of e * e - - -type -i_direction = - IInc - | IDec +type +'a type_def = TD_aux of type_def_aux * 'a annot type @@ -441,23 +308,6 @@ type type -ctor_kind = - C_Enum of nat - | C_Union - - -type -reg_form = - Form_Reg of id * tannot * i_direction - | Form_SubReg of id * reg_form * index_range - - -type -'a reg_id = - RI_aux of 'a reg_id_aux * 'a annot - - -type 'a exp_aux = (* expression *) E_block of ('a exp) list (* sequential block *) | E_nondet of ('a exp) list (* nondeterministic block *) @@ -468,6 +318,8 @@ type | E_app_infix of 'a exp * id * 'a exp (* infix function application *) | E_tuple of ('a exp) list (* tuple *) | E_if of 'a exp * 'a exp * 'a exp (* conditional *) + | E_loop of loop * 'a exp * 'a exp + | E_until of 'a exp * 'a exp | E_for of id * 'a exp * 'a exp * 'a exp * order * 'a exp (* loop *) | E_vector of ('a exp) list (* vector (indexed from 0) *) | E_vector_indexed of ((int * 'a exp)) list * 'a opt_default (* vector (indexed consecutively) *) @@ -484,10 +336,12 @@ type | E_case of 'a exp * ('a pexp) list (* pattern matching *) | E_let of 'a letbind * 'a exp (* let expression *) | E_assign of 'a lexp * 'a exp (* imperative assignment *) - | E_sizeof of nexp (* the value of nexp at run time *) - | E_return of 'a exp (* return 'a exp from current function *) + | E_sizeof of nexp (* the value of $nexp$ at run time *) + | E_return of 'a exp (* return $'a exp$ from current function *) | E_exit of 'a exp (* halt all current execution *) - | E_assert of 'a exp * 'a exp (* halt with error 'a exp when not 'a exp *) + | E_throw of 'a exp + | E_try of 'a exp * ('a pexp) list + | E_assert of 'a exp * 'a exp (* halt with error $'a exp$ when not $'a exp$ *) | E_internal_cast of 'a annot * 'a exp (* This is an internal cast, generated during type checking that will resolve into a syntactic cast after *) | E_internal_exp of 'a annot (* This is an internal use for passing nexp information to library functions, postponed for constraint solving *) | E_sizeof_internal of 'a annot (* For sizeof during type checking, to replace nexp with internal n *) @@ -497,25 +351,11 @@ type | E_internal_let of 'a lexp * 'a exp * 'a exp (* This is an internal node for compilation that demonstrates the scope of a local mutable variable *) | E_internal_plet of 'a pat * 'a exp * 'a exp (* This is an internal node, used to distinguised some introduced lets during processing from original ones *) | E_internal_return of 'a exp (* For internal use to embed into monad definition *) - | E_internal_value of value (* For internal use in interpreter to wrap pre-evaluated values when returning an action *) + | E_constraint of n_constraint and 'a exp = E_aux of 'a exp_aux * 'a annot -and value = (* interpreter evaluated value *) - V_boxref of nat * t - | V_lit of lit - | V_tuple of (value) list - | V_list of (value) list - | V_vector of nat * i_direction * (value) list - | V_vector_sparse of nat * nat * i_direction * ((nat * value)) list * value - | V_record of t * ((id * value)) list - | V_ctor of id * t * ctor_kind * value - | V_unknown - | V_register of reg_form - | V_register_alias of tannot alias_spec * tannot - | V_track of value * reg_form_set - and 'a lexp_aux = (* lvalue expression *) LEXP_id of id (* identifier *) | LEXP_memory of id * ('a exp) list (* memory or register write via function call *) @@ -549,30 +389,21 @@ and 'a opt_default = and 'a pexp_aux = (* pattern match *) Pat_exp of 'a pat * 'a exp + | Pat_when of 'a pat * 'a exp * 'a exp and 'a pexp = Pat_aux of 'a pexp_aux * 'a annot and 'a letbind_aux = (* let binding *) - LB_val_explicit of typschm * 'a pat * 'a exp (* let, explicit type ('a pat must be total) *) - | LB_val_implicit of 'a pat * 'a exp (* let, implicit type ('a pat must be total) *) + LB_val of 'a pat * 'a exp (* let, implicit type ($'a pat$ must be total) *) and 'a letbind = LB_aux of 'a letbind_aux * 'a annot -and 'a alias_spec_aux = (* register alias expression forms *) - AL_subreg of 'a reg_id * id - | AL_bit of 'a reg_id * 'a exp - | AL_slice of 'a reg_id * 'a exp * 'a exp - | AL_concat of 'a reg_id * 'a reg_id - -and 'a alias_spec = - AL_aux of 'a alias_spec_aux * 'a annot - type -'a funcl_aux = (* function clause *) - FCL_Funcl of id * 'a pat * 'a exp +'a reg_id = + RI_aux of 'a reg_id_aux * 'a annot type @@ -582,19 +413,28 @@ rec_opt_aux = (* optional recursive annotation for functions *) type +effect_opt_aux = (* optional effect annotation for functions *) + Effect_opt_pure (* sugar for empty effect set *) + | Effect_opt_effect of effect + + +type tannot_opt_aux = (* optional type annotation for functions *) - Typ_annot_opt_some of typquant * typ + Typ_annot_opt_none + | Typ_annot_opt_some of typquant * typ type -effect_opt_aux = (* optional effect annotation for functions *) - Effect_opt_pure (* sugar for empty effect set *) - | Effect_opt_effect of effect +'a funcl_aux = (* function clause *) + FCL_Funcl of id * 'a pat * 'a exp type -'a funcl = - FCL_aux of 'a funcl_aux * 'a annot +'a alias_spec_aux = (* register alias expression forms *) + AL_subreg of 'a reg_id * id + | AL_bit of 'a reg_id * 'a exp + | AL_slice of 'a reg_id * 'a exp * 'a exp + | AL_concat of 'a reg_id * 'a reg_id type @@ -603,25 +443,23 @@ rec_opt = type -tannot_opt = - Typ_annot_opt_aux of tannot_opt_aux * Parse_ast.l +effect_opt = + Effect_opt_aux of effect_opt_aux * Parse_ast.l type -effect_opt = - Effect_opt_aux of effect_opt_aux * Parse_ast.l +tannot_opt = + Typ_annot_opt_aux of tannot_opt_aux * Parse_ast.l type -'a val_spec_aux = (* value type specification *) - VS_val_spec of typschm * id (* specify the type of an upcoming definition *) - | VS_extern_no_rename of typschm * id (* specify the type of an external function *) - | VS_extern_spec of typschm * id * string (* specify the type of a function from Lem *) +'a funcl = + FCL_aux of 'a funcl_aux * 'a annot type -'a fundef_aux = (* function definition *) - FD_function of rec_opt * tannot_opt * effect_opt * ('a funcl) list +'a alias_spec = + AL_aux of 'a alias_spec_aux * 'a annot type @@ -634,37 +472,38 @@ type type -'a default_spec_aux = (* default kinding or typing assumption *) - DT_order of order - | DT_kind of base_kind * kid - | DT_typ of typschm * id - - -type 'a dec_spec_aux = (* register declarations *) DEC_reg of typ * id | DEC_alias of id * 'a alias_spec | DEC_typ_alias of typ * id * 'a alias_spec +type +val_spec_aux = VS_val_spec of typschm * id * string option * bool + + type -'a val_spec = - VS_aux of 'a val_spec_aux * 'a annot +'a fundef_aux = (* function definition *) + FD_function of rec_opt * tannot_opt * effect_opt * ('a funcl) list type -'a fundef = - FD_aux of 'a fundef_aux * 'a annot +default_spec_aux = (* default kinding or typing assumption *) + DT_order of order + | DT_kind of base_kind * kid + | DT_typ of typschm * id type -'a scattered_def = - SD_aux of 'a scattered_def_aux * 'a annot +prec = + Infix + | InfixL + | InfixR type -'a default_spec = - DT_aux of 'a default_spec_aux * Parse_ast.l +'a scattered_def = + SD_aux of 'a scattered_def_aux * 'a annot type @@ -672,6 +511,20 @@ type DEC_aux of 'a dec_spec_aux * 'a annot +type +'a val_spec = VS_aux of val_spec_aux * 'a annot + + +type +'a fundef = + FD_aux of 'a fundef_aux * 'a annot + + +type +default_spec = + DT_aux of default_spec_aux * Parse_ast.l + + type 'a dec_comm = (* top-level generated comments *) DC_comm of string (* generated unstructured comment *) @@ -683,7 +536,9 @@ and 'a def = (* top-level definition *) | DEF_fundef of 'a fundef (* function definition *) | DEF_val of 'a letbind (* value definition *) | DEF_spec of 'a val_spec (* top-level type constraint *) - | DEF_default of 'a default_spec (* default kind and type assumptions *) + | DEF_fixity of prec * int * id (* fixity declaration *) + | DEF_overload of id * (id) list (* operator overload specification *) + | DEF_default of default_spec (* default kind and type assumptions *) | DEF_scattered of 'a scattered_def (* scattered function and type definition *) | DEF_reg_dec of 'a dec_spec (* register declaration *) | DEF_comm of 'a dec_comm (* generated comments *) diff --git a/language/l2.ott b/language/l2.ott index c78c66f8..76fc0c77 100644 --- a/language/l2.ott +++ b/language/l2.ott @@ -1,3 +1,7 @@ +%% +%% Grammar for user language. Generates ./src/ast.ml +%% + indexvar n , m , i , j ::= {{ phantom }} {{ com Index variables for meta-lists }} @@ -5,13 +9,14 @@ indexvar n , m , i , j ::= metavar num,numZero,numOne ::= {{ phantom }} {{ lex numeric }} - {{ ocaml int }} + {{ ocaml big_int }} {{ hol num }} {{ lem integer }} {{ com Numeric literals }} metavar nat ::= {{ phantom }} + {{ ocaml int }} {{ lex numeric }} {{ lem nat }} @@ -27,7 +32,7 @@ metavar bin ::= {{ lex numeric }} {{ ocaml string }} {{ lem string }} - {{ com Bit vector literal, specified by C-style binary number }} + {{ com Bit vector literal, specified by C-style binary number }} metavar string ::= {{ phantom }} @@ -43,11 +48,26 @@ metavar regexp ::= {{ hol string }} {{ com Regular expresions, as a string literal }} +metavar real ::= + {{ phantom }} + {{ ocaml string }} + {{ lem string }} + {{ hol string }} + {{ com Real number literal }} + embed {{ ocaml +open Big_int + +type text = string + +type l = Parse_ast.l + type 'a annot = l * 'a +type loop = While | Until + }} embed @@ -72,10 +92,12 @@ val set_from_list : forall 'a. list 'a -> set 'a val subst : forall 'a. list 'a -> list 'a -> bool +type loop = While | Until + }} metavar x , y , z ::= - {{ ocaml string }} + {{ ocaml text }} {{ lem string }} {{ hol string }} {{ com identifier }} @@ -84,7 +106,7 @@ metavar x , y , z ::= metavar ix ::= {{ lex alphanum }} - {{ ocaml string }} + {{ ocaml text }} {{ lem string }} {{ hol string }} {{ com infix identifier }} @@ -112,7 +134,7 @@ annot :: '' ::= {{ hol unit }} id :: '' ::= - {{ com identifier }} + {{ com Identifier }} {{ aux _ l }} | x :: :: id | ( deinfix x ) :: D :: deIid {{ com remove infix status }} @@ -120,6 +142,7 @@ id :: '' ::= | bit :: M :: bit {{ ichlo (Id "bit") }} | unit :: M :: unit {{ ichlo (Id "unit") }} | nat :: M :: nat {{ ichlo (Id "nat") }} + | int :: M :: int {{ ichlo (Id "int") }} | string :: M :: string {{ tex \ottkw{string} }} {{ ichlo (Id "string") }} | range :: M :: range {{ ichlo (Id "range") }} | atom :: M :: atom {{ ichlo (Id "atom") }} @@ -135,8 +158,21 @@ id :: '' ::= % variable, and field name. We don't enforce any lexical convention % on type variables (or variables of other kinds) % We don't enforce a lexical convention on infix operators, as some of the -% targets use alphabetical infix operators. - +% targets use alphabetical infix operators. + +% Vector builtins + | vector_access :: M :: vector_access {{ ichlo (Id "vector_access") }} + | vector_update :: M :: vector_update {{ ichlo (Id "vector_update") }} + | vector_update_subrange :: M :: vector_update_subrange {{ ichlo (Id "vector_update_subrange") }} + | vector_subrange :: M :: vector_subrange {{ ichlo (Id "vector_subrange") }} + | vector_append :: M :: vector_append {{ ichlo (Id "vector_append") }} + +% Comparison builtins + | lteq_atom_atom :: M :: lteq_atom_atom {{ ichlo (Id "lteq_atom_atom") }} + | gteq_atom_atom :: M :: gteq_atom_atom {{ ichlo (Id "gteq_atom_atom") }} + | lt_atom_atom :: M :: lt_atom_atom {{ ichlo (Id "lt_atom_atom") }} + | gt_atom_atom :: M :: gt_atom_atom {{ ichlo (Id "gt_atom_atom") }} + kid :: '' ::= {{ com kinded IDs: $[[Type]]$, $[[Nat]]$, $[[Order]]$, and $[[Effect]]$ variables }} {{ aux _ l }} @@ -153,10 +189,10 @@ grammar base_kind :: 'BK_' ::= {{ com base kind}} {{ aux _ l }} - | Type :: :: type {{ com kind of types }} - | Nat :: :: nat {{ com kind of natural number size expressions }} + | Type :: :: type {{ com kind of types }} + | Nat :: :: nat {{ com kind of natural number size expressions }} | Order :: :: order {{ com kind of vector order specifications }} - | Effect :: :: effect {{ com kind of effect sets }} + kind :: 'K_' ::= {{ com kinds}} @@ -167,14 +203,15 @@ kind :: 'K_' ::= nexp :: 'Nexp_' ::= {{ com numeric expression, of kind $[[Nat]]$ }} {{ aux _ l }} - | id :: :: id {{ com abbreviation identifier }} - | kid :: :: var {{ com variable }} - | num :: :: constant {{ com constant }} - | nexp1 * nexp2 :: :: times {{ com product }} - | nexp1 + nexp2 :: :: sum {{ com sum }} - | nexp1 - nexp2 :: :: minus {{ com subtraction }} - | 2** nexp :: :: exp {{ com exponential }} - | neg nexp :: I :: neg {{ com for internal use only}} + | id :: :: id {{ com abbreviation identifier }} + | kid :: :: var {{ com variable }} + | num :: :: constant {{ com constant }} + | id ( nexp1 , ... , nexpn ) :: :: app {{ com app }} + | nexp1 * nexp2 :: :: times {{ com product }} + | nexp1 + nexp2 :: :: sum {{ com sum }} + | nexp1 - nexp2 :: :: minus {{ com subtraction }} + | 2** nexp :: :: exp {{ com exponential }} + | neg nexp :: I :: neg {{ com for internal use only}} | ( nexp ) :: S :: paren {{ ichlo [[nexp]] }} order :: 'Ord_' ::= @@ -231,8 +268,6 @@ grammar typ :: 'Typ_' ::= {{ com type expressions, of kind $[[Type]]$ }} {{ aux _ l }} - | _ :: :: wild - {{ com unspecified type }} | id :: :: id {{ com defined type }} | kid :: :: var @@ -243,6 +278,7 @@ typ :: 'Typ_' ::= % TODO: concrete syntax for effects in a function type? needed only for pp, not in user syntax. | ( typ1 , .... , typn ) :: :: tup {{ com Tuple }} + | exist kid1 , .. , kidn , n_constraint . typ :: :: exist % TODO union in the other kind grammars? or make a syntax of argument? or glom together the grammars and leave o the typechecker | id < typ_arg1 , .. , typ_argn > :: :: app {{ com type constructor application }} @@ -258,11 +294,12 @@ typ :: 'Typ_' ::= % probably some sugar for vector types, using [ ] similarly to enums: % (but with .. not : in the former, to avoid confusion...) | typ [ nexp ] :: S :: vector2 {{ichlo vector < [[nexp]],0,inc,[[typ]] > }} -{{ com sugar for vector indexed by \texttt{[|} [[nexp]] \texttt{|]} }} +{{ com sugar for vector indexed by \texttt{[|} $[[nexp]]$ \texttt{|]} }} | typ [ nexp : nexp' ] :: S :: vector3 {{ ichlo vector < [[nexp]],[[nexp']],inc,[[typ]] }} -{{ com sugar for vector indexed by \texttt{[|} [[nexp]]..[[nexp']] \texttt{|]} }} +{{ com sugar for vector indexed by \texttt{[|} $[[nexp]]$..$[[nexp']]$ \texttt{|]} }} | typ [ nexp <: nexp' ] :: S :: vector4 {{ ichlo vector < [[nexp]],[[nexp']],inc,[[typ]] }} {{ com sugar for increasing vector }} | typ [ nexp :> nexp' ] :: S :: vector5 {{ ichlo vector < [[nexp]],[[nexp']],dec,[[typ]] }} {{ com sugar for decreasing vector }} +% | register [ id ] :: S :: register {{ ichlo (Typ_app Id "lteq_atom_atom") }} % ...so bit [ nexp ] etc is just an instance of that % | List < typ > :: :: list {{ com list of [[typ]] }} % | Set < typ > :: :: set {{ com finite set of [[typ]] }} @@ -271,14 +308,13 @@ typ :: 'Typ_' ::= % not sure how first-class it should be, though % use "reg word32" etc for the types of vanilla registers - + typ_arg :: 'Typ_arg_' ::= {{ com type constructor arguments of all kinds }} {{ aux _ l }} | nexp :: :: nexp | typ :: :: typ | order :: :: order - | effect :: :: effect % plus more for l-value/r-value pairs, as introduced by the L3 'compound' declarations ... ref typ @@ -307,10 +343,15 @@ grammar n_constraint :: 'NC_' ::= {{ com constraint over kind $[[Nat]]$ }} {{ aux _ l }} - | nexp = nexp' :: :: fixed + | nexp = nexp' :: :: equal | nexp >= nexp' :: :: bounded_ge | nexp '<=' nexp' :: :: bounded_le - | kid 'IN' { num1 , ... , numn } :: :: nat_set_bounded + | nexp != nexp' :: :: not_equal + | kid 'IN' { num1 , ... , numn } :: :: set + | n_constraint \/ n_constraint' :: :: or + | n_constraint /\ n_constraint' :: :: and + | true :: :: true + | false :: :: false % Note only id on the left and constants on the right in a % finite-set-bound, as we don't think we need anything more @@ -384,9 +425,13 @@ grammar %%% OR, IN C STYLE -type_def :: 'TD_' ::= +type_def {{ ocaml 'a type_def }} {{ lem type_def 'a }} :: 'TD_' ::= + {{ ocaml TD_aux of type_def_aux * 'a annot }} + {{ lem TD_aux of type_def_aux * annot 'a }} + | type_def_aux :: :: aux + +type_def_aux :: 'TD_' ::= {{ com type definition body }} - {{ aux _ annot }} {{ auxparam 'a }} | typedef id name_scm_opt = typschm :: :: abbrev {{ com type abbreviation }} {{ texlong }} | typedef id name_scm_opt = const struct typquant { typ1 id1 ; ... ; typn idn semi_opt } :: :: record @@ -412,17 +457,17 @@ kind_def :: 'KD_' ::= {{ aux _ annot }} {{ auxparam 'a }} | Def kind id name_scm_opt = nexp :: :: nabbrev {{ com $[[Nat]]$-expression abbreviation }} - | Def kind id name_scm_opt = typschm :: D :: abbrev - {{ com type abbreviation }} {{ texlong }} - | Def kind id name_scm_opt = const struct typquant { typ1 id1 ; ... ; typn idn semi_opt } :: D :: record - {{ com struct type definition }} {{ texlong }} - | Def kind id name_scm_opt = const union typquant { type_union1 ; ... ; type_unionn semi_opt } :: D :: variant - {{ com union type definition}} {{ texlong }} - | Def kind id name_scm_opt = enumerate { id1 ; ... ; idn semi_opt } :: D :: enum - {{ com enumeration type definition}} {{ texlong }} - - | Def kind id = register bits [ nexp : nexp' ] { index_range1 : id1 ; ... ; index_rangen : idn } -:: D :: register {{ com register mutable bitfield type definition }} {{ texlong }} +% | Def kind id name_scm_opt = typschm :: D :: abbrev +% {{ com type abbreviation }} {{ texlong }} +% | Def kind id name_scm_opt = const struct typquant { typ1 id1 ; ... ; typn idn semi_opt } :: D :: record +% {{ com struct type definition }} {{ texlong }} +% | Def kind id name_scm_opt = const union typquant { type_union1 ; ... ; type_unionn semi_opt } :: D :: variant +% {{ com union type definition}} {{ texlong }} +% | Def kind id name_scm_opt = enumerate { id1 ; ... ; idn semi_opt } :: D :: enum +% {{ com enumeration type definition}} {{ texlong }} +% +% | Def kind id = register bits [ nexp : nexp' ] { index_range1 : id1 ; ... ; index_rangen : idn } +%:: D :: register {{ com register mutable bitfield type definition }} {{ texlong }} @@ -467,7 +512,8 @@ lit :: 'L_' ::= % Should undefined be of type bit[alpha] or alpha[beta] or just alpha? | string :: :: string {{ com string constant }} | undefined :: :: undef {{ com undefined-value constant }} - + | real :: :: real + semi_opt {{ tex \ottnt{;}^{?} }} :: 'semi_' ::= {{ phantom }} {{ ocaml bool }} {{ lem bool }} @@ -503,11 +549,10 @@ pat :: 'P_' ::= % C-style | ( typ ) pat :: :: typ {{ com typed pattern }} - | id :: :: id {{ com identifier }} - -% + | pat kid :: :: var + {{ com bind pattern to type variable }} | id ( pat1 , .. , patn ) :: :: app {{ com union constructor pattern }} @@ -525,8 +570,8 @@ pat :: 'P_' ::= | [ pat1 , .. , patn ] :: :: vector {{ com vector pattern }} - | [ num1 = pat1 , .. , numn = patn ] :: :: vector_indexed - {{ com vector pattern (with explicit indices) }} +% | [ num1 = pat1 , .. , numn = patn ] :: :: vector_indexed +% {{ com vector pattern (with explicit indices) }} % cf ntoes for this | pat1 : .... : patn :: :: vector_concat @@ -537,9 +582,9 @@ pat :: 'P_' ::= | [|| pat1 , .. , patn ||] :: :: list {{ com list pattern }} | ( pat ) :: S :: paren -{{ ichlo [[pat]] }} -% | pat1 '::' pat2 :: :: cons -% {{ com Cons patterns }} + {{ ichlo [[pat]] }} + | pat1 '::' pat2 :: :: cons + {{ com Cons patterns }} % XXX Is this still useful? fpat :: 'FP_' ::= @@ -580,37 +625,11 @@ let rec disjoint_all sets = end }} - -grammar - -k :: 'Ki_' ::= -{{ com Internal kinds }} - | K_Typ :: :: typ - | K_Nat :: :: nat - | K_Ord :: :: ord - | K_Efct :: :: efct - | K_Lam ( k0 .. kn -> k' ) :: :: ctor - | K_infer :: :: infer {{ com Representing an unknown kind, inferred by context }} - -t , u :: 'T_' ::= -{{ com Internal types }} - | x :: :: id - | ' x :: :: var - | t1 -> t2 effect :: :: fn - | ( t1 , .... , tn ) :: :: tup - | x < t_args > :: :: app - | t |-> t1 :: :: abbrev - | register < t_arg > :: S :: reg_app {{ ichlo T_app "register" [[t_arg]] }} - | range < ne ne' > :: S :: range_app {{ ichlo T_app "range" [[ [ ne ; ne' ] ]] }} - | atom < ne > :: S :: atom_app {{ ichlo T_app "atom" [ [[ne]] ] }} - | vector < ne ne' order t > :: S :: vector_app {{ ichlo T_app "vector" [[ [ ne; ne'; ord; t ] ]] }} - | list < t > :: S :: list_app {{ ichlo T_app "list" [[t]] }} - | reg < t > :: S :: box_app {{ ichlo T_app "reg" [[t]] }} - | implicit < ne > :: S :: implicit_app {{ ichlo T_app "implicit" [[ne]] }} - | bit :: S :: bit_typ {{ ichlo T_id "bit" }} - | string :: S :: string_typ {{ ichlo T_id "string" }} - | unit :: S :: unit_typ {{ ichlo T_id "unit" }} - | t [ t_arg1 / tid1 .. t_argn / tidn ] :: M :: subst {{ ichlo "todo" }} +grammar + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% Interpreter specific things % +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% optx :: '' ::= {{ phantom }} {{ lem maybe string }} {{ ocaml string option }} | x :: :: optx_x @@ -618,14 +637,13 @@ optx :: '' ::= {{ phantom }} {{ lem maybe string }} {{ ocaml string option }} | :: :: optx_none {{ lem Nothing }} {{ ocaml None }} - -tag :: 'Tag_' ::= +tag :: 'Tag_' ::= {{ com Data indicating where the identifier arises and thus information necessary in compilation }} | None :: :: empty | Intro :: :: intro {{ com Denotes an assignment and lexp that introduces a binding }} | Set :: :: set {{ com Denotes an expression that mutates a local variable }} | Tuple :: :: tuple_assign {{ com Denotes an assignment with a tuple lexp }} - | Global :: :: global {{ com Globally let-bound or enumeration based value/variable }} + | Global :: :: global {{ com Globally let-bound or enumeration based value/variable }} | Ctor :: :: ctor {{ com Data constructor from a type union }} | Extern optx :: :: extern {{ com External function, specied only with a val statement }} | Default :: :: default {{ com Type has come from default declaration, identifier may not be bound locally }} @@ -634,323 +652,66 @@ tag :: 'Tag_' ::= | Alias :: :: alias | Unknown_path optx :: :: unknown {{ com Tag to distinguish an unknown path from a non-analysis non deterministic path}} -ne :: 'Ne_' ::= - {{ com internal numeric expressions }} - | x :: :: id - | ' x :: :: var - | num :: :: const - | infinity :: :: inf - | ne1 * ne2 :: :: mult - | ne1 + ... + nen :: :: add - | ne1 - ne2 :: :: minus - | 2 ** ne :: :: exp - | ( - ne ) :: :: unary - | zero :: S :: zero - {{ ichlo (Ne_const 0) }} - | one :: S :: one - {{ ichlo (Ne_const 1) }} - | bitlength ( bin ) :: M :: cbin - {{ ocaml (asssert false) }} - {{ hol ARB }} - {{ lem (blength [[bin]]) }} - | bitlength ( hex ) :: M :: chex - {{ ocaml (assert false) }} - {{ hol ARB }} - {{ lem (hlength [[hex]]) }} - | count ( num0 ... numi ) :: M :: length {{ichlo "todo" }} - | length ( pat1 ... patn ) :: M :: cpat - {{ ocaml (assert false) }} - {{ hol ARB }} - {{ lem (Ne_const (List.length [[pat1...patn]])) }} - | length ( exp1 ... expn ) :: M :: cexp - {{ hol ARB }} - {{ ocaml (assert false) }} - {{ lem (Ne_const (List.length [[exp1...expn]])) }} - - t_arg :: 't_arg_' ::= - {{ com Argument to type constructors }} - | t :: :: typ - | ne :: :: nexp - | effect :: :: effect - | order :: :: order - | fresh :: M :: freshvar {{ ichlo T_arg (T_var "fresh") }} - - t_args :: '' ::= {{ lem list t_arg }} - {{ com Arguments to type constructors }} - | t_arg1 ... t_argn :: :: T_args - - nec :: 'Nec_' ::= - {{ com Numeric expression constraints }} - | ne <= ne' :: :: lteq - | ne = ne' :: :: eq - | ne >= ne' :: :: gteq - | ' x 'IN' { num1 , ... , numn } :: :: in - | nec0 .. necn -> nec'0 ... nec'm :: :: cond - | nec0 ... necn :: :: branch - -S_N {{ tex {\Sigma^{\textsc{N} } } }} :: '' ::= {{ phantom }} - {{ hol nec list }} - {{ lem list nec }} - {{ com nexp constraint lists }} - | { nec1 , .. , necn } :: :: Sn_concrete - {{ hol [[nec1 .. necn]] }} - {{ lem [[nec1 .. necn]] }} - | S_N1 u+ .. u+ S_Nn :: M :: SN_union - {{ hol (FOLDR FUNION FEMPTY [[S_N1..S_Nn]]) }} - {{ lem (List.foldr (++) [] [[S_N1..S_Nn]]) }} - {{ ocaml (assert false) }} - | consistent_increase ne1 ne'1 ... nen ne'n :: M :: SN_increasing - {{ com Generates constraints from pairs of constraints, where the first of each pair is always larger than the sum of the previous pair }} - {{ ocaml (assert false) }} - {{ ichl todo }} - | consistent_decrease ne1 ne'1 ... nen ne'n :: M :: SN_decreasing - {{ com Generates constraints from pairs of constraints, where the first of each pair is always smaller than the difference of the previous pair }} - {{ ocaml assert false }} - {{ ichl todo }} - | resolve ( S_N ) :: :: resolution - {{ lem [[S_N]] (* Write constraint solver *) }} - - - E_d {{ tex {\ottnt{E}^{\textsc{d} } } }} :: 'E_d_' ::= {{ phantom }} - {{ lem definition_env }} - {{ com Environments storing top level information, such as defined abbreviations, records, enumerations, and kinds }} - | < E_k , E_a , E_r , E_e > :: :: base - {{ hol arb }} - {{ lem (Denv [[E_k]] [[E_r]] [[E_e]]) }} - | empty :: :: empty - {{ hol arb }} - {{ lem DenvEmp }} - | E_d u+ E_d' :: :: union - {{ hol arb }} - {{ lem (denv_union [[E_d]] [[E_d']]) }} - - kinf :: 'kinf_' ::= - {{ com Whether a kind is default or from a local binding }} - | k :: :: k - | k default :: :: def - - tid :: 'tid_' ::= - {{ com A type identifier or type variable }} - | id :: :: id - | kid :: :: var - - E_k {{ tex {\ottnt{E}^{\textsc{k} } } }} :: 'E_k_' ::= {{ phantom }} - {{ hol (tid-> kinf) }} - {{ lem (map tid kinf) }} - {{ com Kind environments }} - | { tid1 |-> kinf1 , .. , tidn |-> kinfn } :: :: concrete - {{ hol (FOLDR (\(k1,k2) E. E |+ (k1,k2)) FEMPTY [[tid1 kinf1 .. tidn kinfn]]) }} - {{ lem (List.foldr (fun (x,v) m -> Map.insert x v m) Map.empty [[tid1 kinf1 .. tidn kinfn]]) }} - | E_k1 u+ .. u+ E_kn :: M :: union - {{ com In a unioning kinf, {k default} u {k} results in {k} (i.e. the default is locally forgotten) }} - {{ hol (FOLDR FUNION FEMPTY [[E_k1..E_kn]]) }} - {{ lem (List.foldr (union) Map.empty [[E_k1..E_kn]]) }} - {{ ocaml (assert false) }} - | E_k u- E_k1 .. E_kn :: M :: multi_set_minus - {{ hol arb }} - {{ lem (Map.fromList (remove_from (Set_extra.toList (Map.toSet [[E_k]])) - (Set_extra.toList (Map.toSet (List.foldr (union) Map.empty [[E_k1..E_kn]]))))) }} - {{ ocaml assert false }} - - tinf :: 'tinf_' ::= - {{ com Type variables, type, and constraints, bound to an identifier }} - | t :: :: typ - | E_k , S_N , tag , t :: :: quant_typ - -tinflist :: 'tinfs_' ::= - {{ com In place so that a list of tinfs can be referred to without the dot form }} - | empty :: :: empty - | tinf1 ... tinfn :: :: ls - -conformsto :: 'conformsto_' ::= - {{ com how much conformance does overloading need }} - | full :: :: full - | parm :: :: parm - -widenvec :: 'widenvec_' ::= - | vectors :: :: widen - | none :: :: dont - | _ :: :: dontcare - -widennum :: 'widennum_' ::= - | nums :: :: widen - | none :: :: dont - | _ :: :: dontcare - -widening :: 'widening_' ::= - {{ com Should we widen vector start locations, should we widen atoms and ranges }} - | ( widennum , widenvec ) :: :: w - - E_a {{ tex \ottnt{E}^{\textsc{a} } }} :: 'E_a_' ::= {{ phantom }} - {{ hol tid |-> tinf}} - {{ lem map tid tinf }} - | { tid1 |-> tinf1 , .. , tidn |-> tinfn } :: :: concrete - | E_a1 u+ .. u+ E_an :: :: union - - field_typs :: 'FT_' ::= {{ phantom }} - {{ lem list (id * t) }} - {{ com Record fields }} - | id1 : t1 , .. , idn : tn :: :: fields - {{ lem [[id1 t1..idn tn]] }} - - E_r {{ tex \ottnt{E}^{\textsc{r} } }} :: 'E_r_' ::= {{ phantom }} - {{ hol (id*t) |-> tinf) }} - {{ lem map (list (id*t)) tinf }} - {{ com Record environments }} - | { { field_typs1 } |-> tinf1 , .. , { field_typsn } |-> tinfn } :: :: concrete - {{ hol (FOLDR (\x E. E |+ x) FEMPTY) }} - {{ lem (List.foldr (fun (x,f) m -> Map.insert x f m) Map.empty [[field_typs1 tinf1..field_typsn tinfn]]) }} - | E_r1 u+ .. u+ E_rn :: M :: union - {{ hol (FOLDR FUNION FEMPTY [[E_r1..E_rn]]) }} - {{ lem (List.foldr (union) Map.empty [[E_r1..E_rn]]) }} - {{ ocaml (assert false) }} - - enumerate_map :: '' ::= {{ phantom }} - {{ lem (list (nat*id)) }} - | { num1 |-> id1 ... numn |-> idn } :: :: enum_map - {{ lem [[num1 id1...numn idn]] }} - - E_e {{ tex \ottnt{E}^{\textsc{e} } }} :: 'E_e_' ::= {{ phantom }} - {{ lem (map t (list (nat*id))) }} - {{ com Enumeration environments }} - | { t1 |-> enumerate_map1 , .. , tn |-> enumerate_mapn } :: :: base - {{ lem (List.foldr (fun (x,f) m -> Map.insert x f m) Map.empty [[t1 enumerate_map1..tn enumerate_mapn]]) }} - | E_e1 u+ .. u+ E_en :: :: union - {{ lem (List.foldr (union) Map.empty [[E_e1..E_en]]) }} - - embed {{ lem - type definition_env = - | DenvEmp - | Denv of (map tid kinf) * (map (list (id*t)) tinf) * (map t (list (nat*id))) + +type tannot = maybe (typ * tag * list unit * effect * effect) }} -grammar +embed +{{ ocaml - E_t {{ tex {\ottnt{E}^{\textsc{t} } } }} :: 'E_t_' ::= {{ phantom }} - {{ hol (id |-> tinf) }} - {{ lem map id tinf }} - {{ com Type environments }} - | { id1 |-> tinf1 , .. , idn |-> tinfn } :: :: base - {{ hol (FOLDR (\x E. E |+ x) FEMPTY [[id1 tinf1 .. idn tinfn]]) }} - {{ lem (List.foldr (fun (x,f) m -> Map.insert x f m) Map.empty [[id1 tinf1 .. idn tinfn]]) }} - | { id |-> overload tinf conformsto : tinf1 , ... , tinfn } :: :: overload - | ( E_t1 u+ .... u+ E_tn ) :: M :: union - {{ hol (FOLDR FUNION FEMPTY [[E_t1....E_tn]]) }} - {{ lem (List.foldr (union) Map.empty [[E_t1....E_tn]]) }} - {{ ocaml (assert false) }} - | u+ E_t1 .. E_tn :: M :: multi_union - {{ hol arb }} - {{ lem (List.foldr (union) Map.empty [[E_t1..E_tn]]) }} - {{ ocaml assert false }} - | E_t u- id1 .. idn :: M :: multi_set_minus - {{ hol arb }} - {{ lem (Map.fromList (remove_from (Set_extra.toList (Map.toSet [[E_t]])) - (Set_extra.toList (Map.toSet (List.foldr (union) Map.empty [[id1..idn]]))))) }} - {{ ocaml assert false }} - | ( E_t1 inter .... inter E_tn ) :: M :: intersect - {{ hol arb }} - {{ lem (List.foldr (fun a b -> (Map.fromList (Set_extra.toList ((Map.toSet a) inter (Map.toSet b))))) Map.empty [[E_t1....E_tn]]) }} - {{ ocaml (assert false) }} - | inter E_t1 .. E_tn :: M :: multi_inter - {{ hol arb }} - {{ lem (List.foldr (fun a b -> (Map.fromList (Set_extra.toList ((Map.toSet a) inter (Map.toSet b))))) Map.empty [[E_t1..E_tn]]) }} - {{ ocaml assert false }} - - -ts :: ts_ ::= {{ phantom }} - {{ lem list t }} - | t1 , .. , tn :: :: lst +(* Interpreter specific things are just set to unit here *) +type tannot = unit -embed -{{ lem -let blength (bit) = Ne_const 8 -let hlength (bit) = Ne_const 8 - - type env = - | EnvEmp - | Env of (map id tinf) * definition_env - - type inf = - | Iemp - | Inf of (list nec) * effect - - val denv_union : definition_env -> definition_env -> definition_env - let denv_union de1 de2 = - match (de1,de2) with - | (DenvEmp,de2) -> de2 - | (de1,DenvEmp) -> de1 - | ((Denv ke1 re1 ee1),(Denv ke2 re2 ee2)) -> - Denv (ke1 union ke2) (re1 union re2) (ee1 union ee2) - end - - val env_union : env -> env -> env - let env_union e1 e2 = - match (e1,e2) with - | (EnvEmp,e2) -> e2 - | (e1,EnvEmp) -> e1 - | ((Env te1 de1),(Env te2 de2)) -> - Env (te1 union te2) (denv_union de1 de2) - end - -let inf_union i1 i2 = - match (i1,i2) with - | (Iemp,i2) -> i2 - | (i1,Iemp) -> i1 - | (Inf n1 e1,Inf n2 e2) -> (Inf (n1++n2) (effect_union e1 e2)) - end - -let fresh_kid denv = Var "x" (*TODO When strings can be manipulated, this should actually build a fresh string*) +type reg_form_set = unit }} grammar +tannot :: '' ::= + {{ phantom }} + {{ ocaml unit }} + {{ lem tannot }} - E :: '' ::= - {{ hol ((string,env_body) fmaptree) }} - {{ lem env }} - {{ com Definition environment and lexical environment }} - | < E_t , E_d > :: :: E - {{ hol arb }} - {{ lem (Env [[E_t]] [[E_d]]) }} - | empty :: M :: E_empty - {{ hol arb }} - {{ lem EnvEmp }} - {{ ocaml assert false }} - | E u+ E' :: :: E_union - {{ lem (env_union [[E]] [[E']]) }} - - I :: '' ::= {{ lem inf }} - {{ com Information given by type checking an expression }} - | < S_N , effect > :: :: I - {{ lem (Inf [[S_N]] [[effect]]) }} - | Ie :: :: Iempty {{ com Empty constraints, effect }} {{ tex {\ottnt{I}_{\epsilon} } }} - {{ lem Iemp }} - | ( I1 u+ I2 ) :: :: singleunion {{ tex [[I1]] [[u+]] [[I2]] }} - | I1 u+ .. u+ In :: :: Iunion {{ com Unions the constraints and effect }} - {{ lem (List.foldr inf_union Iemp [[I1..In]]) }} - +i_direction :: 'I' ::= + | IInc :: :: Inc + | IDec :: :: Dec -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -% Expressions % -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +ctor_kind :: 'C_' ::= + | C_Enum nat :: :: Enum + | C_Union :: :: Union -embed -{{ lem +reg_form :: 'Form_' ::= + | Reg id tannot i_direction :: :: Reg + | SubReg id reg_form index_range :: :: SubReg -type tannot = maybe (t * tag * list nec * effect * effect) +reg_form_set :: '' ::= {{ phantom }} {{ lem set reg_form }} -}} +alias_spec_tannot :: '' ::= {{ phantom }} {{ lem alias_spec tannot }} {{ ocaml tannot alias_spec }} -grammar -tannot :: '' ::= - {{ phantom }} - {{ ocaml tannot }} - {{ lem tannot }} +value :: 'V_' ::= {{ com interpreter evaluated value }} + | Boxref nat typ :: :: boxref + | Lit lit :: :: lit + | Tuple ( value1 , ... , valuen ) :: :: tuple + | List ( value1 , ... , valuen ) :: :: list + | Vector nat i_direction ( value1 , ... , valuen ) :: :: vector + | Vector_sparse nat' nat'' i_direction ( nat1 value1 , ... , natn valuen ) value' :: :: vector_sparse + | Record typ ( id1 value1 , ... , idn valuen ) :: :: record + | V_ctor id typ ctor_kind value1 :: :: ctor + | Unknown :: :: unknown + | Register reg_form :: :: register + | Register_alias alias_spec_tannot tannot :: :: register_alias + | Track value reg_form_set :: :: track +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% Expressions % +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +loop :: loop ::= {{ phantom }} + | while :: :: while + | until :: :: until exp :: 'E_' ::= {{ com expression }} @@ -987,7 +748,9 @@ exp :: 'E_' ::= {{ com conditional }} | if exp1 then exp2 :: S :: ifnoelse {{ ichlo [[ if exp1 then exp2 else ( ) ]] }} - + | loop exp1 exp2 :: :: loop + | while exp1 do exp2 :: S :: while {{ ichlo [[ loop while exp1 exp2 ]] }} + | repeat exp1 until exp2 :: S :: until {{ ichlo [[ loop until exp2 exp1 ]] }} | foreach ( id from exp1 to exp2 by exp3 in order ) exp4 :: :: for {{ com loop }} | foreach ( id from exp1 to exp2 by exp3 ) exp4 :: S :: forup {{ ichlo [[ foreach id from exp1 to exp2 by exp3 in inc exp4 ]] }} | foreach ( id from exp1 to exp2 ) exp3 :: S :: forupbyone {{ ichlo [[ foreach id from exp1 to exp2 by 1 in inc exp4 ]] }} @@ -1000,9 +763,6 @@ exp :: 'E_' ::= % here the expi are of type 'a and the result is a vector of 'a, whereas in exp1 : ... : expn % the expi and the result are both of type vector of 'a - | [ num1 = exp1 , ... , numn = expn opt_default ] :: :: vector_indexed {{ com vector (indexed consecutively) }} -% num1 .. numn must be a consecutive list of naturals - % we pick [ ] not { } for vector literals for consistency with their % array-like access syntax, in contrast to the C which has funny % syntax for array literals. We don't have to preserve [ ] for lists @@ -1069,15 +829,17 @@ exp :: 'E_' ::= {{ com imperative assignment }} | sizeof nexp :: :: sizeof - {{ com the value of [[nexp]] at run time }} + {{ com the value of $[[nexp]]$ at run time }} - | return exp :: :: return {{ com return [[exp]] from current function }} + | return exp :: :: return {{ com return $[[exp]]$ from current function }} % this can be used to break out of for loops | exit exp :: :: exit {{ com halt all current execution }} + | throw exp :: :: throw + | try exp catch pexp1 .. pexpn :: :: try %, potentially calling a system, trap, or interrupt handler with exp | assert ( exp , exp' ) :: :: assert - {{ com halt with error [[exp']] when not [[exp]] }} + {{ com halt with error $[[exp']]$ when not $[[exp]]$ }} % exp' is optional? | ( exp ) :: S :: paren {{ ichlo [[exp]] }} | ( annot ) exp :: I :: internal_cast {{ com This is an internal cast, generated during type checking that will resolve into a syntactic cast after }} @@ -1088,38 +850,26 @@ exp :: 'E_' ::= | comment exp :: I :: comment_struc {{ com For generated structured comments }} | let lexp = exp in exp' :: I :: internal_let {{ com This is an internal node for compilation that demonstrates the scope of a local mutable variable }} | let pat = exp in exp' :: I :: internal_plet {{ com This is an internal node, used to distinguised some introduced lets during processing from original ones }} - | return_int ( exp ) :: I :: internal_return {{ com For internal use to embed into monad definition }} + | return_int ( exp ) :: :: internal_return {{ com For internal use to embed into monad definition }} | value :: I :: internal_value {{ com For internal use in interpreter to wrap pre-evaluated values when returning an action }} + | constraint n_constraint :: :: constraint -i_direction :: 'I' ::= - | IInc :: :: Inc - | IDec :: :: Dec +%i_direction :: 'I' ::= +% | IInc :: :: Inc +% | IDec :: :: Dec -ctor_kind :: 'C_' ::= - | C_Enum nat :: :: Enum - | C_Union :: :: Union +%ctor_kind :: 'C_' ::= +% | C_Enum nat :: :: Enum +% | C_Union :: :: Union -reg_form :: 'Form_' ::= - | Reg id tannot i_direction :: :: Reg - | SubReg id reg_form index_range :: :: SubReg +%reg_form :: 'Form_' ::= +% | Reg id tannot i_direction :: :: Reg +% | SubReg id reg_form index_range :: :: SubReg -reg_form_set :: '' ::= {{ phantom }} {{ lem set reg_form }} +%reg_form_set :: '' ::= {{ phantom }} {{ lem set reg_form }} -alias_spec_tannot :: '' ::= {{ phantom }} {{ lem alias_spec tannot }} {{ ocaml tannot alias_spec }} +%alias_spec_tannot :: '' ::= {{ phantom }} {{ lem alias_spec tannot }} {{ ocaml tannot alias_spec }} -value :: 'V_' ::= {{ com interpreter evaluated value }} - | Boxref nat t :: :: boxref - | Lit lit :: :: lit - | Tuple ( value1 , ... , valuen ) :: :: tuple - | List ( value1 , ... , valuen ) :: :: list - | Vector nat i_direction ( value1 , ... , valuen ) :: :: vector - | Vector_sparse nat' nat'' i_direction ( nat1 value1 , ... , natn valuen ) value' :: :: vector_sparse - | Record t ( id1 value1 , ... , idn valuen ) :: :: record - | V_ctor id t ctor_kind value1 :: :: ctor - | Unknown :: :: unknown - | Register reg_form :: :: register - | Register_alias alias_spec_tannot tannot :: :: register_alias - | Track value reg_form_set :: :: track lexp :: 'LEXP_' ::= {{ com lvalue expression }} {{ aux _ annot }} {{ auxparam 'a }} @@ -1127,7 +877,7 @@ lexp :: 'LEXP_' ::= {{ com lvalue expression }} {{ com identifier }} | id ( exp1 , .. , expn ) :: :: memory {{ com memory or register write via function call }} | id exp :: S :: mem_tup {{ ichlo [[id (exp)]] }} -{{ com sugared form of above for explicit tuple [[exp]] }} +{{ com sugared form of above for explicit tuple $[[exp]]$ }} | ( typ ) id :: :: cast {{ com cast }} | ( lexp0 , .. , lexpn ) :: :: tup {{ com multiple (non-memory) assignment }} @@ -1156,7 +906,8 @@ opt_default :: 'Def_val_' ::= pexp :: 'Pat_' ::= {{ com pattern match }} {{ aux _ annot }} {{ auxparam 'a }} - | pat -> exp :: :: exp + | pat -> exp :: :: exp + | pat when exp1 -> exp :: :: when % apparently could use -> or => for this. %% % psexp :: 'Pats' ::= @@ -1233,7 +984,7 @@ grammar tannot_opt :: 'Typ_annot_opt_' ::= {{ com optional type annotation for functions}} {{ aux _ l }} -% | :: :: none + | :: :: none % Currently not optional; one issue, do the type parameters apply over the argument types, or should this be the type of the function and not just the return | typquant typ :: :: some @@ -1270,27 +1021,34 @@ fundef :: 'FD_' ::= letbind :: 'LB_' ::= {{ com let binding }} {{ aux _ annot }} {{ auxparam 'a }} - | let typschm pat = exp :: :: val_explicit - {{ com let, explicit type ([[pat]] must be total)}} -% at the moment, we cannot parse the following, so perhaps we shouldn't keep this form here - | let pat = exp :: :: val_implicit - {{ com let, implicit type ([[pat]] must be total)}} - - -val_spec :: 'VS_' ::= - {{ com value type specification }} - {{ aux _ annot }} {{ auxparam 'a }} - | val typschm id :: :: val_spec + | let pat = exp :: :: val + {{ com let, implicit type ($[[pat]]$ must be total)}} + +val_spec {{ ocaml 'a val_spec }} {{ lem val_spec 'a }} :: 'VS_' ::= + {{ ocaml VS_aux of val_spec_aux * 'a annot }} + {{ lem VS_aux of val_spec_aux * annot 'a }} + | val_spec_aux :: :: aux + +val_spec_aux :: 'VS_' ::= + {{ com value type specification }} + {{ ocaml VS_val_spec of typschm * id * (string -> string option) * bool }} + {{ lem VS_val_spec of typschm * id * maybe string * bool }} + | val typschm id :: S :: val_spec {{ com specify the type of an upcoming definition }} - | val extern typschm id :: :: extern_no_rename + {{ ocaml (VS_val_spec [[typschm]] [[id]] None false) }} {{ lem }} + | val cast typschm id :: S :: cast + {{ ocaml (VS_val_spec [[typschm]] [[id]] None true) }} {{ lem }} + | val extern typschm id :: S :: extern_no_rename {{ com specify the type of an external function }} - | val extern typschm id = string :: :: extern_spec + {{ ocaml (VS_val_spec [[typschm]] [[id]] ([[Some id]]) false) }} {{ lem }} + | val extern typschm id = string :: S :: extern_spec {{ com specify the type of a function from Lem }} + {{ ocaml (VS_val_spec [[typschm]] [[id]] ([[Some string]]) false) }} {{ lem }} %where the string must provide an explicit path to the required function but will not be checked default_spec :: 'DT_' ::= {{ com default kinding or typing assumption }} - {{ aux _ l }} {{ auxparam 'a }} + {{ aux _ l }} | default Order order :: :: order | default base_kind kid :: :: kind | default typschm id :: :: typ @@ -1346,6 +1104,11 @@ dec_comm :: 'DC_' ::= {{ com top-level generated comments }} {{auxparam 'a}} % Top-level definitions % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +prec :: '' ::= + | infix :: :: Infix + | infixl :: :: InfixL + | infixr :: :: InfixR + def :: 'DEF_' ::= {{ com top-level definition }} {{ auxparam 'a }} @@ -1359,6 +1122,10 @@ def :: 'DEF_' ::= {{ com value definition }} | val_spec :: :: spec {{ com top-level type constraint }} + | fix prec num id :: :: fixity + {{ com fixity declaration }} + | overload id [ id1 ; ... ; idn ] :: :: overload + {{ com operator overload specification }} | default_spec :: :: default {{ com default kind and type assumptions }} | scattered_def :: :: scattered @@ -1367,6 +1134,8 @@ def :: 'DEF_' ::= {{ com register declaration }} | dec_comm :: I :: comm {{ com generated comments }} + | fundef1 .. fundefn :: I :: internal_mutrec + {{ com internal representation of mutually recursive functions }} defs :: '' ::= {{ com definition sequence }} @@ -1379,16 +1148,16 @@ terminals :: '' ::= | ** :: :: starstar {{ tex \ensuremath{\mathop{\mathord{*}\mathord{*} } } }} {{ com \texttt{**} }} -% | >= :: :: geq -% % {{ tex \ensuremath{\geq} }} + | >= :: :: geq + {{ tex \ensuremath{\geq} }} % {{ tex \ottsym{\textgreater=} }} % {{ com \texttt{>=} }} -% | '<=' :: :: leq -% % {{ tex \ensuremath{\leq} }} + | '<=' :: :: leq + {{ tex \ensuremath{\leq} }} % {{ tex \ottsym{\textless=} }} % {{ com \texttt{<=} }} -% | -> :: :: arrow -% % {{ tex \ensuremath{\rightarrow} }} + | -> :: :: arrow + {{ tex \ensuremath{\rightarrow} }} % {{ tex \ottsym{-\textgreater} }} % {{ com \texttt{->} }} | ==> :: :: Longrightarrow @@ -1415,10 +1184,10 @@ terminals :: '' ::= | emptyset :: :: emptyset {{ tex \ensuremath{\emptyset} }} % | < :: :: lt -% % {{ tex \ensuremath{\langle} }} + {{ tex \ensuremath{\langle} }} % {{ tex \ottsym{<} }} % | > :: :: gt -% % {{ tex \ensuremath{\rangle} }} + {{ tex \ensuremath{\rangle} }} % {{ tex \ottsym{>} }} | lt :: :: mathlt {{ tex < }} @@ -1472,5 +1241,3 @@ terminals :: '' ::= % {{ tex \mbox{$\ottsym{[\textbar\textbar}$} }} % | ||] :: :: list_end % {{ tex \mbox{$\ottsym{\textbar\textbar]}$} }} - - diff --git a/language/l2_parse2.ott b/language/l2_parse2.ott new file mode 100644 index 00000000..0f8dc8e7 --- /dev/null +++ b/language/l2_parse2.ott @@ -0,0 +1,1424 @@ +indexvar n , i , j , k ::= + {{ phantom }} + {{ com Index variables for meta-lists }} + +metavar num ::= + {{ phantom }} + {{ lex numeric }} + {{ ocaml int }} + {{ hol num }} + {{ lem integer }} + {{ com Numeric literals }} + {{ ocamllex ['0'-'9']+ }} + +metavar hex ::= + {{ phantom }} + {{ lex numeric }} + {{ ocaml string }} + {{ lem string }} +{{ ocamllex '0''x'['0'-'9' 'A' - 'F' 'a'-'f' '_']+ }} + {{ com Bit vector literal, specified by C-style hex number }} + +metavar bin ::= + {{ phantom }} + {{ lex numeric }} + {{ ocaml string }} + {{ lem string }} +{{ ocamllex '\'' ['0' '1' ' ']* '\'' }} + {{ com Bit vector literal, specified by C-style binary number }} + +metavar string ::= + {{ phantom }} + {{ ocaml string }} + {{ lem string }} + {{ hol string }} + {{ ocamllex "a" }} {{ phantom }} + {{ com String literals }} + +metavar regexp ::= + {{ phantom }} + {{ ocaml string }} + {{ lem string }} + {{ hol string }} + {{ ocamllex "a" }} {{ phantom }} + {{ com Regular expresions, as a string literal }} + +embed +{{ ocaml + +type l = + | Unknown + | Int of string * l option + | Generated of l + | Range of Lexing.position * Lexing.position + +type 'a annot = l * 'a + +exception Parse_error_locn of l * string + +}} + +embed +{{ lem +open import Map +open import Maybe +open import Pervasives + +type l = + | Unknown + | Trans of string * maybe l + | Range of nat * nat + +val duplicates : forall 'a. list 'a -> list 'a + +val union_map : forall 'a 'b. map 'a 'b -> map 'a 'b -> map 'a 'b + +val set_from_list : forall 'a. list 'a -> set 'a + +val subst : forall 'a. list 'a -> list 'a -> bool + +}} + +metavar x , y , z ::= + {{ ocaml string }} + {{ lem string }} + {{ hol string }} + {{ com identifier }} + {{ ocamlvar "[[x]]" }} + {{ lemvar "[[x]]" }} + {{ ocamllex "a" }} {{ phantom }} + +metavar ix ::= + {{ lex alphanum }} + {{ ocaml string }} + {{ lem string }} + {{ hol string }} + {{ com infix identifier }} + {{ ocamlvar "[[ix]]" }} + {{ lemvar "[[ix]]" }} + {{ ocamllex "a" }} {{ phantom }} + + +grammar + +l :: '' ::= {{ phantom }} + {{ ocaml l }} + {{ lem l }} + {{ hol unit }} + {{ com Source location }} + | :: :: Unknown + {{ ocaml Unknown }} + {{ lem Unknown }} + {{ hol () }} + + +id :: '' ::= + {{ com Identifier }} + {{ aux _ l }} + | x :: :: id + | op x :: :: deIid {{ com remove infix status }} + + +kid :: '' ::= + {{ com identifiers with kind, ticked to differntiate from program variables }} + {{ aux _ l }} + | ' x :: :: var + +% Note: we have just a single namespace. We don't want the same +% identifier to be reused as a type name or variable, expression +% variable, and field name. We don't enforce any lexical convention +% on type variables (or variables of other kinds) +% We don't enforce a lexical convention on infix operators, as some of the +% targets use alphabetical infix operators. + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% Kinds and Types % +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + + +grammar + +base_kind :: 'BK_' ::= + {{ com base kind}} + {{ aux _ l }} + | Type :: :: type {{ com kind of types }} + | Nat :: :: nat {{ com kind of natural number size expressions }} + | Order :: :: order {{ com kind of vector order specifications }} + | Effect :: :: effect {{ com kind of effect sets }} + +kind :: 'K_' ::= + {{ com kinds}} + {{ aux _ l }} + | base_kind1 -> ... -> base_kindn :: :: kind +% we'll never use ...-> Nat + +base_effect :: 'BE_' ::= + {{ com effect }} + {{ aux _ l }} + | rreg :: :: rreg {{ com read register }} + | wreg :: :: wreg {{ com write register }} + | rmem :: :: rmem {{ com read memory }} + | wmem :: :: wmem {{ com write memory }} + | wmv :: :: wmv {{ com write memory value }} + | eamem :: :: eamem {{ com address for write signaled }} + | barr :: :: barr {{ com memory barrier }} + | depend :: :: depend {{ com dynmically dependent footprint }} + | undef :: :: undef {{ com undefined-instruction exception }} + | unspec :: :: unspec {{ com unspecified values }} + | nondet :: :: nondet {{ com nondeterminism from intra-instruction parallelism }} + | escape :: :: escape + + + +atomic_typ :: 'ATyp_' ::= + {{ quotient-with atyp }} + | id :: :: id + | kid :: :: var + | num :: :: constant + | dec :: :: dec + | inc :: :: inc + | id ( atyp1 , ... , atypn ) :: :: app + | ( atyp ) :: S :: paren {{ ocaml [[atyp]] }} + | ( atyp1 , .... , atypn ) :: :: tup + | {| num_list |} :: S :: existential_set {{ ocaml + { let v = mk_kid "n" $startpos $endpos in + let atom_id = mk_id (Id "atom") $startpos $endpos in + let atom_of_v = mk_typ (ATyp_app (atom_id, [mk_typ (ATyp_var v) $startpos $endpos])) $startpos $endpos in + mk_typ (ATyp_exist ([v], NC_aux (NC_set (v, [[num_list]]), loc $startpos($2) $endpos($2)), atom_of_v)) $startpos $endpos } }} + | { kid_list . atyp } :: S :: existential_true {{ ocaml + { mk_typ (ATyp_exist ([[kid_list]], NC_aux (NC_true, loc $startpos $endpos), [[atyp]])) $startpos $endpos } }} + | { kid_list , nc . atyp } :: :: exist + | { base_effect1 , .. , base_effectn } :: :: set {{ com effect set }} + | pure :: M :: pure {{ com sugar for empty effect set }} {{ icho [] }} + + +atyp :: 'ATyp_' ::= + {{ com expressions of all kinds, to be translated to types, nats, orders, and effects after parsing }} + {{ aux _ l }} + | atomic_typ :: S :: atomic {{ ocaml [[atomic_typ]] }} {{ quotient-remove }} + | atyp1 * atyp2 :: :: times {{ com product }} + | atyp1 + atyp2 :: :: sum {{ com sum }} + | atyp1 - atyp2 :: :: minus {{ com subtraction }} + | 2** atyp :: :: exp {{ com exponential }} + | neg atyp :: :: neg {{ com Internal (but not M as I want a datatype constructor) negative nexp }} + | atyp1 -> atyp2 effect atyp3 :: :: fn + {{ com Function type (first-order only in user code), last atyp is an effect }} + + +% plus more for l-value/r-value pairs, as introduced by the L3 'compound' declarations ... ref typ + +%typ_lib :: 'Typ_lib_' ::= +% {{ com library types and syntactic sugar for them }} +% {{ aux _ l }} %{{ auxparam 'a }} +% boring base types: +% | unit :: :: unit {{ com unit type with value $()$ }} +% | bool :: :: bool {{ com booleans $[[true]]$ and $[[false]]$ }} +% | bit :: :: bit {{ com pure bit values (not mutable bits) }} +% experimentally trying with two distinct types of bool and bit ... +% | nat :: :: nat {{ com natural numbers 0,1,2,... }} +% | string :: :: string {{ com UTF8 strings }} +% finite subranges of nat +% | enum nexp1 nexp2 order :: :: enum {{ com natural numbers [[atyp2]] .. [[atyp2]]+[[atyp1]]-1, ordered by order }} +% | [ nexp ] :: :: enum1 {{ com sugar for \texttt{enum nexp 0 inc} }} +% | [ nexp : nexp' ] :: :: enum2 {{ com sugar for \texttt{enum (nexp'-nexp+1) nexp inc} or \texttt{enum (nexp-nexp'+1) nexp' dec} }} +% use .. not - to avoid ambiguity with nexp - +% total maps and vectors indexed by finite subranges of nat +% | vector nexp1 nexp2 order atyp :: :: vector {{ com vector of [[atyp]], indexed by natural range }} +% probably some sugar for vector types, using [ ] similarly to enums: +% (but with .. not : in the former, to avoid confusion...) +% | atyp [ nexp ] :: :: vector2 {{ com sugar for vector indexed by [ [[atyp]] ] }} +% | atyp [ nexp : nexp' ] :: :: vector3 {{ com sugar for vector indexed by [ [[atyp]]..[[atyp']] ] }} +% ...so bit [ nexp ] etc is just an instance of that +% | list atyp :: :: list {{ com list of [[atyp]] }} +% | set atyp :: :: set {{ com finite set of [[atyp]] }} +% | reg atyp :: :: reg {{ com mutable register components holding [[atyp]] }} +% "reg t" is basically the ML "t ref" +% not sure how first-class it should be, though +% use "reg word32" etc for the types of vanilla registers + +% parsing +% +% ATyp_tup <= ATyp_tup +% ATyp_fn right ATyp_fn +% ATyp_fn <= ATyp_tup + +grammar + +n_constraint :: 'NC_' ::= + {{ com constraint over kind $[[Nat]]$ }} + {{ aux _ l }} + | atyp = atyp' :: :: fixed + | atyp >= atyp' :: :: bounded_ge + | atyp '<=' atyp' :: :: bounded_le + | kid 'IN' { num1 , ... , numn } :: :: nat_set_bounded + +% Note only id on the left and constants on the right in a +% finite-set-bound, as we don't think we need anything more + +kinded_id :: 'KOpt_' ::= + {{ com optionally kind-annotated identifier }} + {{ aux _ l }} + | kid :: :: none {{ com identifier }} + | kind kid :: :: kind {{ com kind-annotated variable }} + +quant_item :: 'QI_' ::= + {{ com Either a kinded identifier or a nexp constraint for a typquant }} + {{ aux _ l }} + | kinded_id :: :: id {{ com An optionally kinded identifier }} + | n_constraint :: :: const {{ com A constraint for this type }} + +typquant :: 'TypQ_' ::= + {{ com type quantifiers and constraints}} + {{ aux _ l }} + | forall quant_item1 , ... , quant_itemn . :: :: tq {{ texlong }} + | :: :: no_forall {{ com sugar, omitting quantifier and constraints }} + +typschm :: 'TypSchm_' ::= + {{ com type scheme }} + {{ aux _ l }} + | typquant atyp :: :: ts + + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% Type definitions % +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +grammar +%ctor_def :: 'CT_' ::= +% {{ com Datatype constructor definition clause }} +% {{ aux _ l }} +% | id : typschm :: :: ct +% but we could get away with disallowing constraints in typschm, we +% think - if it's useful to do that + + name_scm_opt :: 'Name_sect_' ::= + {{ com Optional variable-naming-scheme specification for variables of defined type }} + {{ aux _ l }} + | :: :: none + | [ name = regexp ] :: :: some + +type_union :: 'Tu_' ::= + {{ com Type union constructors }} + {{ aux _ l }} + | id :: :: id + | atyp id :: :: ty_id + +type_def :: 'TD_' ::= + {{ com Type definition body }} + {{ aux _ l }} + | typedef id name_scm_opt = typschm :: :: abbrev + {{ com type abbreviation }} {{ texlong }} + | typedef id name_scm_opt = const struct typquant { atyp1 id1 ; ... ; atypn idn semi_opt } :: :: record + {{ com struct type definition }} {{ texlong }} + | typedef id name_scm_opt = const union typquant { type_union1 ; ... ; type_unionn semi_opt } :: :: variant + {{ com union type definition}} {{ texlong }} + | typedef id name_scm_opt = enumerate { id1 ; ... ; idn semi_opt } :: :: enum + {{ com enumeration type definition}} {{ texlong }} + + | typedef id = register bits [ atyp : atyp' ] { index_range1 : id1 ; ... ; index_rangen : idn } +:: :: register {{ com register mutable bitfield type definition }} {{ texlong }} + +kind_def :: 'KD_' ::= + {{ com Definition body for elements of kind; many are shorthands for type\_defs }} + {{ aux _ l }} + | Def kind id name_scm_opt = typschm :: :: abbrev + {{ com type abbreviation }} {{ texlong }} + | Def kind id name_scm_opt = const struct typquant { atyp1 id1 ; ... ; atypn idn semi_opt } :: :: record + {{ com struct type definition }} {{ texlong }} + | Def kind id name_scm_opt = const union typquant { type_union1 ; ... ; type_unionn semi_opt } :: :: variant + {{ com union type definition}} {{ texlong }} + | Def kind id name_scm_opt = enumerate { id1 ; ... ; idn semi_opt } :: :: enum + {{ com enumeration type definition}} {{ texlong }} + + | Def kind id = register bits [ atyp : atyp' ] { index_range1 : id1 ; ... ; index_rangen : idn } +:: :: register {{ com register mutable bitfield type definition }} {{ texlong }} + + +% also sugar [ nexp ] + + +index_range :: 'BF_' ::= {{ com index specification, for bitfields in register types}} + {{ aux _ l }} + | num :: :: 'single' {{ com single index }} + | num1 : num2 :: :: range {{ com index range }} + | index_range1 , index_range2 :: :: concat {{ com concatenation of index ranges }} + +% + + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% Literals % +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + + +grammar + +lit :: 'L_' ::= + {{ com Literal constant }} + {{ aux _ l }} + | ( ) :: :: unit {{ com $() : [[unit]]$ }} +%Presumably we want to remove bitzero and bitone ? + | bitzero :: :: zero {{ com $[[bitzero]] : [[bit]]$ }} + | bitone :: :: one {{ com $[[bitone]] : [[bit]]$ }} + | true :: :: true {{ com $[[true]] : [[bool]]$ }} + | false :: :: false {{ com $[[false]] : [[bool]]$ }} + | num :: :: num {{ com natural number constant }} + | hex :: :: hex {{ com bit vector constant, C-style }} + {{ com hex and bin are constant bit vectors, C-style }} + | bin :: :: bin {{ com bit vector constant, C-style }} + | undefined :: :: undef {{ com undefined value }} + | string :: :: string {{ com string constant }} + +semi_opt {{ tex \ottnt{;}^{?} }} :: 'semi_' ::= {{ phantom }} + {{ ocaml bool }} + {{ lem bool }} + {{ hol bool }} + {{ com Optional semi-colon }} + | :: :: no + {{ hol F }} + {{ ocaml false }} + {{ lem false }} + | ';' :: :: yes + {{ hol T }} + {{ ocaml true }} + {{ lem true }} + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% Patterns % +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + + +pat :: 'P_' ::= + {{ com Pattern }} + {{ aux _ l }} + | lit :: :: lit + {{ com literal constant pattern }} + | _ :: :: wild + {{ com wildcard }} + | ( pat as id ) :: :: as + {{ com named pattern }} + | ( atyp ) pat :: :: typ + {{ com typed pattern }} + + | id :: :: id + {{ com identifier }} + + | id ( pat1 , .. , patn ) :: :: app + {{ com union constructor pattern }} + + | { fpat1 ; ... ; fpatn semi_opt } :: :: record + {{ com struct pattern }} + + | [ pat1 , .. , patn ] :: :: vector + {{ com vector pattern }} + + | [ num1 = pat1 , .. , numn = patn ] :: :: vector_indexed + {{ com vector pattern (with explicit indices) }} + + | pat1 : .... : patn :: :: vector_concat + {{ com concatenated vector pattern }} + + | ( pat1 , .... , patn ) :: :: tup + {{ com tuple pattern }} + | [|| pat1 , .. , patn ||] :: :: list + {{ com list pattern }} + | ( pat ) :: S :: paren +{{ ichlo [[pat]] }} + +fpat :: 'FP_' ::= + {{ com Field pattern }} + {{ aux _ l }} + | id = pat :: :: Fpat + +parsing +P_app <= P_app +P_app <= P_as + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% Expressions % +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + + + +grammar + +exp :: 'E_' ::= + {{ com Expression }} + {{ aux _ l }} + + | { exp1 ; ... ; expn } :: :: block {{ com block (parsing conflict with structs?) }} +% maybe we really should have indentation-sensitive syntax :-) (given that some of the targets do) + + | nondet { exp1 ; ... ; expn } :: :: nondet {{ com block that can evaluate the contained expressions in any ordering }} + + | id :: :: id + {{ com identifier }} + + | lit :: :: lit + {{ com literal constant }} + + | ( atyp ) exp :: :: cast + {{ com cast }} + + + | id exp :: S :: tup_app {{ ichlo [[id]] ( [[exp]] ) }} {{ com No extra parens needed when exp is a tuple }} + | id ( exp1 , .. , expn ) :: :: app + {{ com function application }} +% Note: fully applied function application only + + | exp1 id exp2 :: :: app_infix + {{ com infix function application }} + + | ( exp1 , .... , expn ) :: :: tuple + {{ com tuple }} + + | if exp1 then exp2 else exp3 :: :: if + {{ com conditional }} + + | if exp1 then exp2 :: S :: ifnoelse {{ icho [[ if exp1 then exp2 else unit ]] }} + + | foreach id from exp1 to exp2 by exp3 in atyp exp4 :: :: for {{ com loop }} + | foreach id from exp1 to exp2 by exp3 exp4 :: S :: forup {{ ichlo [[ foreach id from exp1 to exp2 by exp3 in inc exp4 ]] }} + | foreach id from exp1 to exp2 exp3 :: S :: forupbyone {{ icho [[ foreach id from exp1 to exp2 by 1 exp4 ]] }} + | foreach id from exp1 downto exp2 by exp3 exp4 :: S :: fordown {{ icho [[ foreach id from exp1 to exp2 by ( - exp3 ) exp4 ]] }} + | foreach id from exp1 downto exp2 exp3 :: S :: fordownbyone {{ icho [[ foreach id from exp1 downto exp2 by 1 exp4 ]] }} + +% vectors + | [ exp1 , ... , expn ] :: :: vector {{ com vector (indexed from 0) }} +% order comes from global command-line option??? +% here the expi are of type 'a and the result is a vector of 'a, whereas in exp1 : ... : expn +% the expi and the result are both of type vector of 'a + + | [ exp1 , ... , expn opt_default ] :: :: vector_indexed {{ com vector (indexed consecutively) }} +% num1 .. numn must be a consecutive list of naturals + +% we pick [ ] not { } for vector literals for consistency with their +% array-like access syntax, in contrast to the C which has funny +% syntax for array literals. We don't have to preserve [ ] for lists +% as we don't expect to use lists very much. + + | exp [ exp' ] :: :: vector_access + {{ com vector access }} + + | exp [ exp1 '..' exp2 ] :: :: vector_subrange + {{ com subvector extraction }} + % do we want to allow a comma-separated list of such thingies? + + | [ exp with exp1 = exp2 ] :: :: vector_update + {{ com vector functional update }} + + | [ exp with exp1 : exp2 = exp3 ] :: :: vector_update_subrange + {{ com vector subrange update (with vector)}} + % do we want a functional update form with a comma-separated list of such? + + | exp : exp2 :: :: vector_append + {{ com vector concatenation }} + +% lists + | [|| exp1 , .. , expn ||] :: :: list + {{ com list }} + | exp1 '::' exp2 :: :: cons + {{ com cons }} + + +% const unions + +% const structs + +% TODO + + | { fexps } :: :: record + {{ com struct }} + | { exp with exp1 ; .. ; expn } :: :: record_update + {{ com functional update of struct }} + | exp . id :: :: field + {{ com field projection from struct }} + +%Expressions for creating and accessing vectors + + + +% map : forall 'x 'y ''N. ('x -> 'y) -> vector ''N 'x -> vector ''N 'y +% zip : forall 'x 'y ''N. vector ''N 'x -> vector ''N 'y -> vector ''N ('x*'y) +% foldl : forall 'x 'y ''N. ('x 'y -> 'y) -> vector ''N 'x -> 'y -> 'y +% foldr : forall 'x 'y ''N. ('x 'y -> 'y) -> 'y -> vector ''N 'x -> 'y +% foldmap : forall 'x 'y 'z ''N. ((x,y) -> (x,z)) -> x -> vector ''N y -> vector ''N z +%(or unzip) + +% and maybe with nice syntax + + | switch exp { case pexp1 ... case pexpn } :: :: case + {{ com pattern matching }} + | letbind in exp :: :: let + {{ com let expression }} + + | exp := exp' :: :: assign + {{ com imperative assignment }} + + | sizeof atyp :: :: sizeof + | exit exp :: :: exit + | return exp :: :: return + | assert ( exp , exp' ) :: :: assert + + | ( exp ) :: S :: paren {{ ichlo [[exp]] }} + + +lexp :: 'LEXP_' ::= {{ com lvalue expression, can't occur out of the parser }} + {{ aux _ l }} +% {{ aux _ annot }} {{ auxparam 'a }} + | id :: :: id + {{ com identifier }} + | id ( exp1 , .. , expn ) :: :: mem + | id exp :: S :: mem_tup {{ ichlo [[id (exp)]] }} + | lexp [ exp ] :: :: vector {{ com vector element }} + | lexp [ exp1 : exp2 ] :: :: vector_range {{ com subvector }} + % maybe comma-sep such lists too + | lexp . id :: :: field {{ com struct field }} + + +fexp :: 'FE_' ::= + {{ com Field-expression }} + {{ aux _ l }} +% {{ aux _ annot }} {{ auxparam 'a }} + | id = exp :: :: Fexp + +fexps :: 'FES_' ::= + {{ com Field-expression list }} + {{ aux _ l }} +% {{ aux _ annot }} {{ auxparam 'a }} + | fexp1 ; ... ; fexpn semi_opt :: :: Fexps + +opt_default :: 'Def_val_' ::= + {{ com Optional default value for indexed vectors, to define a defualt value for any unspecified positions in a sparse map }} + {{ aux _ l }} + | :: :: empty + | ; default = exp :: :: dec + +pexp :: 'Pat_' ::= + {{ com Pattern match }} + {{ aux _ l }} +% {{ aux _ annot }} {{ auxparam 'a }} + | pat -> exp :: :: exp +% apparently could use -> or => for this. + +%% % psexp :: 'Pats' ::= +%% % {{ com Multi-pattern matches }} +%% % {{ aux _ l }} +%% % | pat1 ... patn -> exp :: :: exp + + +parsing + +%P_app right LB_Let_val + +%%P_app <= Fun + +%%Fun right App +%%Function right App +E_case right E_app +E_let right E_app + +%%Fun <= Field +%%Function <= Field +E_app <= E_field +E_case <= E_field +E_let <= E_field + +E_app left E_app + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% Function definitions % +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +%%%% old Lem style %%%%%% +grammar +%% % lem_tannot_opt_aux :: 'LEM_Typ_annot_' ::= +%% % {{ com Optional type annotations }} +%% % | :: :: none +%% % | : typ :: :: some +%% % +%% % lem_tannot_opt {{ tex \ottnt{tannot}^? }} :: 'LEM_Typ_annot_' ::= +%% % {{ com location-annotated optional type annotations }} +%% % | tannot_opt_aux l :: :: aux +%% % +%% % lem_funcl :: 'LEM_FCL' ::= +%% % {{ com Function clauses }} +%% % {{ aux _ l }} +%% % | id pat1 ... patn tannot_opt = exp :: :: Funcl +%% % +%% % lem_letbind :: 'LEM_LB_' ::= +%% % {{ com Let bindings }} +%% % {{ aux _ l }} +%% % | pat tannot_opt = exp :: :: Let_val +%% % {{ com Value bindings }} +%% % | lem_funcl :: :: Let_fun +%% % {{ com Function bindings }} +%% % +%% % +%% % grammar +%% % lem_val_def :: 'LEM_VD' ::= +%% % {{ com Value definitions }} +%% % {{ aux _ l }} +%% % | let lem_letbind :: :: Let_def +%% % {{ com Non-recursive value definitions }} +%% % | let rec lem_funcl1 and ... and lem_funcln :: :: Let_rec +%% % {{ com Recursive function definitions }} +%% % +%% % lem_val_spec :: 'LEM_VS' ::= +%% % {{ com Value type specifications }} +%% % {{ aux _ l }} +%% % | val x_l : typschm :: :: Val_spec + +%%%%% C-ish style %%%%%%%%%% + +tannot_opt :: 'Typ_annot_opt_' ::= + {{ com Optional type annotation for functions}} + {{ aux _ l }} +% {{ aux _ annot }} {{ auxparam 'a }} + | :: :: none + | typquant atyp :: :: some + +rec_opt :: 'Rec_' ::= + {{ com Optional recursive annotation for functions }} + {{ aux _ l }} + | :: :: nonrec {{ com non-recursive }} + | rec :: :: rec {{ com recursive }} + +effect_opt :: 'Effect_opt_' ::= + {{ com Optional effect annotation for functions }} + {{ aux _ l }} +% {{ aux _ annot }} {{ auxparam 'a }} + | :: :: pure {{ com sugar for empty effect set }} + | effectkw atyp :: :: effect + +funcl :: 'FCL_' ::= + {{ com Function clause }} + {{ aux _ l }} +% {{ aux _ annot }} {{ auxparam 'a }} + | id pat = exp :: :: Funcl + + +fundef :: 'FD_' ::= + {{ com Function definition}} + {{ aux _ l }} +% {{ aux _ annot }} {{ auxparam 'a }} + | function rec_opt tannot_opt effect_opt funcl1 and ... and funcln :: :: function {{ texlong }} +% {{ com function definition }} +% TODO note that the typ in the tannot_opt is the *result* type, not +% the type of the whole function. The argument type comes from the +% pattern in the funcl +% TODO the above is ok for single functions, but not for mutually +% recursive functions - the tannot_opt scopes over all the funcli, +% which is ok for the typ_quant part but not for the typ part + +letbind :: 'LB_' ::= + {{ com Let binding }} + {{ aux _ l }} +% {{ aux _ annot }} {{ auxparam 'a }} + | let typschm pat = exp :: :: val_explicit + {{ com value binding, explicit type ([[pat]] must be total)}} + | let pat = exp :: :: val_implicit + {{ com value binding, implicit type ([[pat]] must be total)}} + + +val_spec :: 'VS_' ::= + {{ com Value type specification }} + {{ aux _ l }} +% {{ aux _ annot }} {{ auxparam 'a }} + | val typschm id :: :: val_spec + | val extern typschm id :: :: extern_no_rename + | val extern typschm id = string :: :: extern_spec + +default_typing_spec :: 'DT_' ::= + {{ com Default kinding or typing assumption, and default order for literal vectors and vector shorthands }} + {{ aux _ l }} +% {{ aux _ annot }} {{ auxparam 'a }} + | default base_kind kid :: :: kind + | default base_kind atyp :: :: order + | default typschm id :: :: typ +% The intended semantics of these is that if an id in binding position +% doesn't have a kind or type annotation, then we look through the +% default regexps (in order from the beginning) and pick the first +% assumption for which id matches the regexp, if there is one. +% Otherwise we try to infer. Perhaps warn if there are multiple matches. +% For example, we might often have default Type ['alphanum] + +scattered_def :: 'SD_' ::= + {{ com Function and type union definitions that can be spread across + a file. Each one must end in $[[end id]]$ }} + {{ aux _ l }} + | scattered function rec_opt tannot_opt effect_opt id :: :: scattered_function {{ texlong }} {{ com scattered function definition header }} + + | function clause funcl :: :: scattered_funcl +{{ com scattered function definition clause }} + + | scattered typedef id name_scm_opt = const union typquant :: :: scattered_variant {{ texlong }} {{ com scattered union definition header }} + + | union id member type_union :: :: scattered_unioncl {{ com scattered union definition member }} + | end id :: :: scattered_end +{{ com scattered definition end }} + +dec_spec :: 'DEC_' ::= + {{ com Register declarations }} + {{ aux _ l }} + | register atyp id :: :: reg + | register alias id = exp :: :: alias + | register alias atyp id = exp :: :: typ_alias + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% Top-level definitions % +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +def :: 'DEF_' ::= + {{ com Top-level definition }} + | kind_def :: :: kind + {{ com definition of named kind identifiers }} + | type_def :: :: type + {{ com type definition }} + | fundef :: :: fundef + {{ com function definition }} + | letbind :: :: val + {{ com value definition }} + | val_spec :: :: spec + {{ com top-level type constraint }} + | default_typing_spec :: :: default + {{ com default kind and type assumptions }} + | scattered_def :: :: scattered + {{ com scattered definition }} + | dec_spec :: :: reg_dec + {{ com register declaration }} + +defs :: '' ::= + {{ com Definition sequence }} + | def1 .. defn :: :: Defs + + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% Machinery for typing rules % +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +%% %% +%% %% +%% %% grammar +%% %% +%% %% +%% %% p :: 'Path_' ::= +%% %% {{ com Unique paths }} +%% %% | x1 . .. xn . x :: :: def +%% %% | __list :: :: list +%% %% {{ tex \ottkw{\_\_list} }} +%% %% | __bool :: :: bool +%% %% {{ tex \ottkw{\_\_bool} }} +%% %% | __num :: :: num +%% %% {{ tex \ottkw{\_\_num} }} +%% %% | __set :: :: set +%% %% {{ tex \ottkw{\_\_set} }} +%% %% | __string :: :: string +%% %% {{ tex \ottkw{\_\_string} }} +%% %% | __unit :: :: unit +%% %% {{ tex \ottkw{\_\_unit} }} +%% %% | __bit :: :: bit +%% %% {{ tex \ottkw{\_\_bit} }} +%% %% | __vector :: :: vector +%% %% {{ tex \ottkw{\_\_vector} }} +%% %% %TODO morally, delete the above - but what are the __ things for? +%% %% % cleaner to declare early in the library? +%% %% +%% %% t_subst {{ tex \ensuremath{\sigma} }} :: '' ::= {{ phantom }} +%% %% {{ hol (a # t) list }} +%% %% {{ lem list (tnvar * t) }} +%% %% {{ com Type variable substitutions }} +%% %% | { tnvar1 |-> t1 .. tnvarn |-> tn } :: :: T_subst +%% %% {{ ocaml (assert false) }} +%% %% {{ lem ([[tnvar1 t1 .. tnvarn tn]]) }} +%% %% {{ hol ([[tnvar1 t1 .. tnvarn tn]]) }} +%% %% +%% %% t , u :: 'T_' ::= +%% %% {{ com Internal types }} +%% %% | a :: :: var +%% %% | t1 -> t2 :: :: fn +%% %% | t1 * .... * tn :: :: tup +%% %% | p t_args :: :: app +%% %% | ne :: :: len +%% %% | t_subst ( t ) :: M :: subst_app +%% %% {{ com Multiple substitutions }} +%% %% {{ ocaml (assert false) }} +%% %% {{ hol (t_subst_t [[t_subst]] [[t]]) }} +%% %% {{ lem (t_subst_t [[t_subst]] [[t]]) }} +%% %% | t_subst ( tnv ) :: M :: var_subst_app +%% %% {{ com Single variable substitution }} +%% %% {{ ocaml (assert false) }} +%% %% {{ hol (t_subst_tnv [[t_subst]] [[tnv]]) }} +%% %% {{ lem (t_subst_tnv [[t_subst]] [[tnv]]) }} +%% %% | curry ( t_multi , t ) :: M :: multifn +%% %% {{ com Curried, multiple argument functions }} +%% %% {{ ocaml (assert false) }} +%% %% {{ hol (FOLDR T_fn [[t]] [[t_multi]]) }} +%% %% {{ lem (List.fold_right T_fn [[t_multi]] [[t]]) }} +%% %% +%% %% ne :: 'Ne_' ::= +%% %% {{ com internal numeric expressions }} +%% %% | N :: :: var +%% %% | nat :: :: const +%% %% | ne1 * ne2 :: :: mult +%% %% | ne1 + ne2 :: :: add +%% %% | ( - ne ) :: :: unary +%% %% | normalize ( ne ) :: M :: normalize +%% %% {{ ocaml (assert false) }} +%% %% {{ hol ARB }} +%% %% {{ lem (normalize [[ne]] ) }} +%% %% | ne1 + ... + nen :: M :: addmany +%% %% {{ ocaml (assert false) }} +%% %% {{ hol ARB }} +%% %% {{ lem (sumation_nes [[ne1...nen]]) }} +%% %% | bitlength ( bin ) :: M :: cbin +%% %% {{ ocaml (asssert false) }} +%% %% {{ hol ARB }} +%% %% {{ lem (blength [[bin]]) }} +%% %% | bitlength ( hex ) :: M :: chex +%% %% {{ ocaml (assert false) }} +%% %% {{ hol ARB }} +%% %% {{ lem (hlength [[hex]]) }} +%% %% | length ( pat1 ... patn ) :: M :: cpat +%% %% {{ ocaml (assert false) }} +%% %% {{ hol ARB }} +%% %% {{ lem (Ne_const (List.length [[pat1...patn]])) }} +%% %% | length ( exp1 ... expn ) :: M :: cexp +%% %% {{ hol ARB }} +%% %% {{ ocaml (assert false) }} +%% %% {{ lem (Ne_const (List.length [[exp1...expn]])) }} +%% %% +%% %% t_args :: '' ::= +%% %% {{ com Lists of types }} +%% %% | t1 .. tn :: :: T_args +%% %% | t_subst ( t_args ) :: M :: T_args_subst_app +%% %% {{ com Multiple substitutions }} +%% %% {{ ocaml (assert false) }} +%% %% {{ hol (t_subst_t_args [[t_subst]] [[t_args]]) }} +%% %% {{ lem (t_subst_t_args [[t_subst]] [[t_args]]) }} +%% %% +%% %% t_multi :: '' ::= {{ phantom }} +%% %% {{ hol t list }} +%% %% {{ ocaml t list }} +%% %% {{ lem list t }} +%% %% {{ com Lists of types }} +%% %% | ( t1 * .. * tn ) :: :: T_multi +%% %% {{ hol [[t1..tn]] }} +%% %% {{ lem [[t1..tn]] }} +%% %% | t_subst ( t_multi ) :: M :: T_multi_subst_app +%% %% {{ com Multiple substitutions }} +%% %% {{ ocaml (assert false) }} +%% %% {{ hol (MAP (t_subst_t [[t_subst]]) [[t_multi]]) }} +%% %% {{ lem (List.map (t_subst_t [[t_subst]]) [[t_multi]]) }} +%% %% +%% %% nec :: '' ::= +%% %% {{ com Numeric expression constraints }} +%% %% | ne < nec :: :: lessthan +%% %% | ne = nec :: :: eq +%% %% | ne <= nec :: :: lteq +%% %% | ne :: :: base +%% %% +%% %% parsing +%% %% T_fn right T_fn +%% %% T_tup <= T_multi +%% %% +%% %% embed +%% %% {{ lem +%% %% +%% %% val t_subst_t : list (tnv * t) -> t -> t +%% %% val t_subst_tnv : list (tnv * t) -> tnv -> t +%% %% val ftv_t : t -> list tnv +%% %% val ftv_tm : list t -> list tnv +%% %% val ftv_s : list (p*tnv) -> list tnv +%% %% val compatible_overlap : list (x*t) -> bool +%% %% +%% %% (*TODO Should this normalize following the implementation? And blength and hlength need a means of implementation*) +%% %% let normalize n = n +%% %% +%% %% let blength (_,bit) = Ne_const 8 +%% %% let hlength (_,bit) = Ne_const 8 +%% %% +%% %% let rec sumation_nes nes = match nes with +%% %% | [ a; b] -> Ne_add a b +%% %% | x :: y -> Ne_add x (sumation_nes y) +%% %% end +%% %% +%% %% }} +%% %% +%% %% grammar +%% %% +%% %% +%% %% names :: '' ::= {{ phantom }} +%% %% {{ hol x set }} +%% %% {{ lem set x }} +%% %% {{ ocaml Set.Make(String).t }} +%% %% {{ com Sets of names }} +%% %% | { x1 , .. , xn } :: :: Names +%% %% {{ hol (LIST_TO_SET [[x1..xn]]) }} +%% %% {{ lem (set_from_list [[x1..xn]]) }} +%% %% +%% %% semC {{ tex \ensuremath{\mathcal{C} } }} :: '' ::= +%% %% {{ hol (p#tnv) list }} +%% %% {{ lem list (p*tnv) }} +%% %% % {{ com Typeclass constraint lists }} +%% %% % | ( p1 tnv1 ) .. ( pn tnvn ) :: :: SemC_concrete +%% %% % {{ hol ([[p1 tnv1..pn tnvn]]) }} +%% %% % {{ lem ([[p1 tnv1..pn tnvn]]) }} +%% %% +%% %% env_tag :: '' ::= +%% %% {{ com Tags for the (non-constructor) value descriptions }} +%% %% % | method :: :: method +%% %% % {{ com Bound to a method }} +%% %% | val :: :: spec +%% %% {{ com Specified with val }} +%% %% | let :: :: def +%% %% {{ com Defined with let or indreln }} +%% %% +%% %% v_desc :: 'V_' ::= +%% %% {{ com Value descriptions }} +%% %% | < forall tnvs . t_multi -> p , ( x of names ) > :: :: constr +%% %% {{ com Constructors }} +%% %% | < forall tnvs . semC => t , env_tag > :: :: val +%% %% {{ com Values }} +%% %% +%% %% f_desc :: 'F_' ::= +%% %% | < forall tnvs . p -> t , ( x of names ) > :: :: field +%% %% {{ com Fields }} +%% %% +%% %% embed +%% %% {{ hol +%% %% load "fmaptreeTheory"; +%% %% val _ = +%% %% Hol_datatype +%% %% `env_body = <| env_p : x|->p; env_f : x|->f_desc; env_v : x|->v_desc |>`; +%% %% +%% %% val _ = Define ` +%% %% env_union e1 e2 = +%% %% let i1 = item e1 in +%% %% let m1 = map e1 in +%% %% let i2 = item e2 in +%% %% let m2 = map e2 in +%% %% FTNode <| env_p:=FUNION i1.env_p i2.env_p; +%% %% env_f:=FUNION i1.env_f i2.env_f; +%% %% env_v:=FUNION i1.env_v i2.env_v |> +%% %% (FUNION m1 m2)`; +%% %% }} +%% %% {{ lem +%% %% type env = +%% %% | EnvEmp +%% %% | Env of (map x env) * (map x p) * (map x f_desc) * (map x v_desc) +%% %% +%% %% val env_union : env -> env -> env +%% %% let env_union e1 e2 = +%% %% match (e1,e2) with +%% %% | (EnvEmp,e2) -> e2 +%% %% | (e1,EnvEmp) -> e1 +%% %% | ((Env Em1 Ep1 Ef1 Ev1),(Env Em2 Ep2 Ef2 Ev2)) -> +%% %% Env(union_map Em1 Em2) (union_map Ep1 Ep2) (union_map Ef1 Ef2) (union_map Ev1 Ev2) +%% %% end +%% %% +%% %% }} +%% %% +%% %% grammar +%% %% +%% %% xs :: '' ::= {{ phantom }} +%% %% {{ hol string list }} +%% %% {{ lem list string }} +%% %% | x1 .. xn :: :: Xs +%% %% {{ hol [[x1..xn]] }} +%% %% {{ lem [[x1..xn]] }} +%% %% +%% %% %TODO: no clue what the following are: +%% %% S_c {{ tex {\ensuremath{ {\Sigma}^{\mathcal{C} } } } }} :: '' ::= {{ phantom }} +%% %% {{ hol (p#t) list }} +%% %% {{ lem list (p*t) }} +%% %% {{ com Typeclass constraints }} +%% %% | { ( p1 t1 ) , .. , ( pn tn ) } :: :: S_concrete +%% %% {{ hol [[p1 t1 .. pn tn]] }} +%% %% {{ lem [[p1 t1 .. pn tn]] }} +%% %% | S_c1 union .. union S_cn :: M :: S_union +%% %% {{ hol (FLAT [[S_c1..S_cn]]) }} +%% %% {{ lem (List.flatten [[S_c1..S_cn]]) }} +%% %% {{ ocaml assert false }} +%% %% +%% %% S_N {{ tex { \ensuremath{ {\Sigma}^{\mathcal{N} } } } }} :: '' ::= {{ phantom }} +%% %% {{ hol nec list }} +%% %% {{ lem list nec }} +%% %% {{ com nexp constraint lists }} +%% %% | { nec1 , .. , necn } :: :: Sn_concrete +%% %% {{ hol [[nec1 .. necn]] }} +%% %% {{ lem [[nec1 .. necn]] }} +%% %% | S_N1 union .. union S_Nn :: M :: SN_union +%% %% {{ hol (FLAT [[S_N1..S_Nn]]) }} +%% %% {{ lem (List.flatten [[S_N1..S_Nn]]) }} +%% %% {{ ocaml assert false }} +%% %% +%% %% +%% %% E :: '' ::= {{ phantom }} +%% %% {{ hol ((string,env_body) fmaptree) }} +%% %% +%% %% +%% %% %TODO: simplify by removing E_m throughout? And E_p?? +%% %% {{ lem env }} +%% %% {{ com Environments }} +%% %% | < E_m , E_p , E_f , E_x > :: :: E +%% %% {{ hol (FTNode <|env_p:=[[E_p]]; env_f:=[[E_f]]; env_v:=[[E_x]]|> ([[E_m]])) }} +%% %% {{ lem (Env [[E_m]] [[E_p]] [[E_f]] [[E_x]]) }} +%% %% | E1 u+ E2 :: M :: E_union +%% %% {{ hol (env_union [[E1]] [[E2]]) }} +%% %% {{ lem (env_union [[E1]] [[E2]]) }} +%% %% {{ ocaml assert false }} +%% %% | empty :: M :: E_empty +%% %% {{ hol (FTNode <|env_p:=FEMPTY; env_f:=FEMPTY; env_v:=FEMPTY|> FEMPTY) }} +%% %% {{ lem EnvEmp }} +%% %% {{ ocaml assert false }} +%% %% +%% %% E_x {{ tex \ottnt{E}^{\textsc{x} } }} :: 'E_x_' ::= {{ phantom }} +%% %% {{ hol (x|-> v_desc) }} +%% %% {{ lem map x v_desc }} +%% %% {{ com Value environments }} +%% %% | { x1 |-> v_desc1 , .. , xn |-> v_descn } :: :: concrete +%% %% {{ hol (FOLDR (\(k1,k2) E. E |+ (k1,k2)) FEMPTY [[x1 v_desc1 .. xn v_descn]]) }} +%% %% {{ lem (List.fold_right (fun (x,v) m -> Pmap.add x v m) [[x1 v_desc1 .. xn v_descn]] Pmap.empty) }} +%% %% | E_x1 u+ .. u+ E_xn :: M :: union +%% %% {{ hol (FOLDR FUNION FEMPTY [[E_x1..E_xn]]) }} +%% %% {{ lem (List.fold_right union_map [[E_x1..E_xn]] Pmap.empty) }} +%% %% {{ ocaml (assert false) }} +%% %% +%% %% E_f {{ tex \ottnt{E}^{\textsc{f} } }} :: 'E_f_' ::= {{ phantom }} +%% %% {{ hol (x |-> f_desc) }} +%% %% {{ lem map x f_desc }} +%% %% {{ com Field environments }} +%% %% | { x1 |-> f_desc1 , .. , xn |-> f_descn } :: :: concrete +%% %% {{ hol (FOLDR (\x E. E |+ x) FEMPTY [[x1 f_desc1 .. xn f_descn]]) }} +%% %% {{ lem (List.fold_right (fun (x,f) m -> Pmap.add x f m) [[x1 f_desc1 .. xn f_descn]] Pmap.empty) }} +%% %% | E_f1 u+ .. u+ E_fn :: M :: union +%% %% {{ hol (FOLDR FUNION FEMPTY [[E_f1..E_fn]]) }} +%% %% {{ lem (List.fold_right union_map [[E_f1..E_fn]] Pmap.empty) }} +%% %% {{ ocaml (assert false) }} +%% %% +%% %% E_m {{ tex \ottnt{E}^{\textsc{m} } }} :: 'E_m_' ::= {{ phantom }} +%% %% {{ hol (string |-> (string,env_body) fmaptree) }} +%% %% {{ lem map x env }} +%% %% % {{ com Module environments }} +%% %% % | { x1 |-> E1 , .. , xn |-> En } :: :: concrete +%% %% % {{ hol (FOLDR (\x E. E |+ x) FEMPTY [[x1 E1 .. xn En]]) }} +%% %% % {{ lem (List.fold_right (fun (x,e) m -> Pmap.add x e m) [[x1 E1 .. xn En]] Pmap.empty) }} +%% %% % +%% %% % _p {{ tex \ottnt{E}^{\textsc{p} } }} :: 'E_p_' ::= {{ phantom }} +%% %% % {{ hol (x |-> p) }} +%% %% % {{ lem map x p }} +%% %% % {{ com Path environments }} +%% %% % | { x1 |-> p1 , .. , xn |-> pn } :: :: concrete +%% %% % {{ hol (FOLDR (\x E. E |+ x) FEMPTY [[x1 p1 .. xn pn]]) }} +%% %% % {{ lem (List.fold_right (fun (x,p) m -> Pmap.add x p m) [[x1 p1 .. xn pn]] Pmap.empty) }} +%% %% % | E_p1 u+ .. u+ E_pn :: M :: union +%% %% % {{ hol (FOLDR FUNION FEMPTY [[E_p1..E_pn]]) }} +%% %% % {{ lem (List.fold_right union_map [[E_p1..E_pn]] Pmap.empty) }} +%% %% % +%% %% % {{ ocaml (assert false) }} +%% %% E_l {{ tex \ottnt{E}^{\textsc{l} } }} :: 'E_l_' ::= {{ phantom }} +%% %% {{ hol (x |-> t) }} +%% %% {{ lem map x t }} +%% %% {{ com Lexical bindings }} +%% %% | { x1 |-> t1 , .. , xn |-> tn } :: :: concrete +%% %% {{ hol (FOLDR (\x E. E |+ x) FEMPTY [[x1 t1 .. xn tn]]) }} +%% %% {{ lem (List.fold_right (fun (x,t) m -> Pmap.add x t m) [[x1 t1 .. xn tn]] Pmap.empty) }} +%% %% | E_l1 u+ .. u+ E_ln :: M :: union +%% %% {{ hol (FOLDR FUNION FEMPTY [[E_l1..E_ln]]) }} +%% %% {{ lem (List.fold_right union_map [[E_l1..E_ln]] Pmap.empty) }} +%% %% {{ ocaml (assert false) }} +%% %% +%% %% tc_abbrev :: 'Tc_abbrev_' ::= {{ phantom }} +%% %% {{ hol t option }} +%% %% {{ lem option t }} +%% %% {{ ocaml t option }} +%% %% {{ com Type abbreviations }} +%% %% | . t :: :: some +%% %% {{ hol (SOME [[t]]) }} +%% %% {{ lem (Some [[t]]) }} +%% %% | :: :: none +%% %% {{ hol NONE }} +%% %% {{ lem None }} +%% %% +%% %% tc_def :: '' ::= +%% %% {{ com Type and class constructor definitions }} +%% %% | tnvs tc_abbrev :: :: Tc_def +%% %% {{ com Type constructors }} +%% %% +%% %% TD {{ tex \ensuremath{\Delta} }} :: 'TD_' ::= {{ phantom }} +%% %% {{ hol p |-> tc_def }} +%% %% {{ lem map p tc_def }} +%% %% {{ com Type constructor definitions }} +%% %% | { p1 |-> tc_def1 , .. , pn |-> tc_defn } :: :: concrete +%% %% {{ hol (FOLDR (\x E. E |+ x) FEMPTY [[p1 tc_def1 .. pn tc_defn]]) }} +%% %% {{ lem (List.fold_right (fun (p,t) m -> Pmap.add p t m) [[p1 tc_def1 .. pn tc_defn]] Pmap.empty) }} +%% %% {{ ocaml (assert false) }} +%% %% | TD1 u+ TD2 :: M :: union +%% %% {{ hol (FUNION [[TD1]] [[TD2]]) }} +%% %% {{ lem (union_map [[TD1]] [[TD2]]) }} +%% %% {{ ocaml (assert false) }} +%% %% +%% %% +%% %% +%% %% D :: 'D_' ::= {{ phantom }} +%% %% {{ hol ((p |-> tc_def) # (p |-> x list) # (inst list)) }} +%% %% {{ lem tdefs}} +%% %% {{ com Global type definition store }} +%% %% | < TD , TC , I > :: :: concrete +%% %% {{ hol ([[TD]], [[TC]], [[I]]) }} +%% %% {{ lem (D [[TD]] [[TC]] [[I]]) }} +%% %% | D1 u+ D2 :: M :: union +%% %% {{ hol (case ([[D1]],[[D2]]) of ((x1,x2,x3),(y1,y2,y3)) => (FUNION x1 y1, FUNION x2 y2, x3 ++ y3)) }} +%% %% {{ lem (union_tcdefs [[D1]] [[D2]]) }} +%% %% {{ ocaml (assert false) }} +%% %% | empty :: M :: empty +%% %% {{ hol (FEMPTY, FEMPTY, []) }} +%% %% {{ lem DEmp }} +%% %% {{ ocaml assert false }} +%% %% +%% %% parsing +%% %% E_union left E_union +%% %% +%% %% embed +%% %% {{ lem +%% %% type tdefs = +%% %% | DEmp +%% %% | D of (map p tc_def) * (map p (list x)) * (set inst) +%% %% +%% %% val union_tcdefs : tdefs -> tdefs -> tdefs +%% %% +%% %% }} + +grammar + +terminals :: '' ::= + | ** :: :: starstar + {{ tex \ensuremath{\mathop{\mathord{*}\mathord{*} } } }} + {{ com \texttt{**} }} + | >= :: :: geq + {{ tex \ensuremath{\geq} }} + {{ com \texttt{>=} }} + | '<=' :: :: leq + {{ tex \ensuremath{\leq} }} + {{ com \texttt{<=} }} + | -> :: :: arrow + {{ tex \ensuremath{\rightarrow} }} + {{ com \texttt{->} }} + | ==> :: :: Longrightarrow + {{ tex \ensuremath{\Longrightarrow} }} + {{ com \texttt{==>} }} + | <| :: :: startrec + {{ tex \ensuremath{\langle|} }} + {{ com \texttt{<|} }} + | |> :: :: endrec + {{ tex \ensuremath{|\rangle} }} + {{ com \texttt{|>} }} + | inter :: :: inter + {{ tex \ensuremath{\cap} }} +% | union :: :: union +% {{ tex \ensuremath{\cup} }} + | u+ :: :: uplus + {{ tex \ensuremath{\uplus} }} + | NOTIN :: :: notin + {{ tex \ensuremath{\not\in} }} + | SUBSET :: :: subset + {{ tex \ensuremath{\subset} }} + | NOTEQ :: :: noteq + {{ tex \ensuremath{\not=} }} + | emptyset :: :: emptyset + {{ tex \ensuremath{\emptyset} }} + | < :: :: lt + {{ tex \ensuremath{\langle} }} + | > :: :: gt + {{ tex \ensuremath{\rangle} }} + | |- :: :: vdash + {{ tex \ensuremath{\vdash} }} + | ' :: :: quote + {{ tex \mbox{'} }} + | |-> :: :: mapsto + {{ tex \ensuremath{\mapsto} }} + | gives :: :: gives + {{ tex \ensuremath{\triangleright} }} + | ~> :: :: leadsto + {{ tex \ensuremath{\leadsto} }} + | => :: :: Rightarrow + {{ tex \ensuremath{\Rightarrow} }} + | -- :: :: dashdash + {{ tex \mbox{--} }} + | empty :: :: empty + {{ tex \ensuremath{\epsilon} }} + | effectkw :: :: effectkw + {{ tex \ottkw{effect} }} + + +formula :: formula_ ::= + | judgement :: :: judgement + + | formula1 .. formulan :: :: dots + +% | E_m ( x ) gives E :: :: lookup_m +% {{ com Module lookup }} +% {{ hol (FLOOKUP [[E_m]] [[x]] = SOME [[E]]) }} +% {{ lem (Pmap.find [[x]] [[E_m]]) = [[E]] }} +% +% | E_p ( x ) gives p :: :: lookup_p +% {{ com Path lookup }} +% {{ hol (FLOOKUP [[E_p]] [[x]] = SOME [[p]]) }} +% {{ lem Pmap.find [[x]] [[E_p]] = [[p]] }} + +%% %% | E_f ( x ) gives f_desc :: :: lookup_f +%% %% {{ com Field lookup }} +%% %% {{ hol (FLOOKUP [[E_f]] [[x]] = SOME [[f_desc]]) }} +%% %% {{ lem Pmap.find [[x]] [[E_f]] = [[f_desc]] }} +%% %% +%% %% | E_x ( x ) gives v_desc :: :: lookup_v +%% %% {{ com Value lookup }} +%% %% {{ hol (FLOOKUP [[E_x]] [[x]] = SOME [[v_desc]]) }} +%% %% {{ lem Pmap.find [[x]] [[E_x]] = [[v_desc]] }} +%% %% +%% %% | E_l ( x ) gives t :: :: lookup_l +%% %% {{ com Lexical binding lookup }} +%% %% {{ hol (FLOOKUP [[E_l]] [[x]] = SOME [[t]]) }} +%% %% {{ lem Pmap.find [[x]] [[E_l]] = [[t]] }} +%% %% +%% %% % | TD ( p ) gives tc_def :: :: lookup_tc +%% %% % {{ com Type constructor lookup }} +%% %% % {{ hol (FLOOKUP [[TD]] [[p]] = SOME [[tc_def]]) }} +%% %% % {{ lem Pmap.find [[p]] [[TD]] = [[tc_def]] }} +%% %% % +%% %% % | TC ( p ) gives xs :: :: lookup_class +%% %% % {{ com Type constructor lookup }} +%% %% % {{ hol (FLOOKUP [[TC]] [[p]] = SOME [[xs]]) }} +%% %% % {{ lem Pmap.find [[p]] [[TC]] = [[xs]] }} +%% %% +%% %% | dom ( E_m1 ) inter dom ( E_m2 ) = emptyset :: :: E_m_disjoint +%% %% {{ hol (DISJOINT (FDOM [[E_m1]]) (FDOM [[E_m2]])) }} +%% %% {{ lem disjoint (Pmap.domain [[E_m1]]) (Pmap.domain [[E_m2]]) }} +%% %% +%% %% | dom ( E_x1 ) inter dom ( E_x2 ) = emptyset :: :: E_x_disjoint +%% %% {{ hol (DISJOINT (FDOM [[E_x1]]) (FDOM [[E_x2]])) }} +%% %% {{ lem disjoint (Pmap.domain [[E_x1]]) (Pmap.domain [[E_x2]]) }} +%% %% +%% %% | dom ( E_f1 ) inter dom ( E_f2 ) = emptyset :: :: E_f_disjoint +%% %% {{ hol (DISJOINT (FDOM [[E_f1]]) (FDOM [[E_f2]])) }} +%% %% {{ lem disjoint (Pmap.domain [[E_f1]]) (Pmap.domain [[E_f2]]) }} +%% %% +%% %% % | dom ( E_p1 ) inter dom ( E_p2 ) = emptyset :: :: E_p_disjoint +%% %% % {{ hol (DISJOINT (FDOM [[E_p1]]) (FDOM [[E_p2]])) }} +%% %% % {{ lem disjoint (Pmap.domain [[E_p1]]) (Pmap.domain [[E_p2]]) }} +%% %% % +%% %% | disjoint doms ( E_l1 , .... , E_ln ) :: :: E_l_disjoint +%% %% {{ hol (FOLDR (\E b. case b of NONE => NONE | SOME s => if DISJOINT (FDOM +%% %% E) s then SOME (FDOM E UNION s) else NONE) (SOME {}) [[E_l1....E_ln]] <> NONE) }} +%% %% {{ lem disjoint_all (List.map Pmap.domain [[E_l1 .... E_ln]]) }} +%% %% {{ com Pairwise disjoint domains }} +%% %% +%% %% | disjoint doms ( E_x1 , .... , E_xn ) :: :: E_x_disjoint_many +%% %% {{ hol (FOLDR (\E b. case b of NONE => NONE | SOME s => if DISJOINT (FDOM +%% %% E) s then SOME (FDOM E UNION s) else NONE) (SOME {}) [[E_x1....E_xn]] <> NONE) }} +%% %% {{ lem disjoint_all (List.map Pmap.domain [[E_x1 .... E_xn]]) }} +%% %% {{ com Pairwise disjoint domains }} +%% %% +%% %% | compatible overlap ( x1 |-> t1 , .. , xn |-> tn ) :: :: E_l_compat +%% %% {{ hol (!__n __m. MEM __m [[x1 t1 .. xn tn]] /\ MEM __n [[x1 t1..xn tn]] /\ (FST __m = FST __n) ==> (SND __m = SND __n)) }} +%% %% {{ lem (compatible_overlap [[x1 t1 .. xn tn]]) }} +%% %% {{ com $(\ottnt{x}_i = \ottnt{x}_j) \ensuremath{\Longrightarrow} (\ottnt{t}_i = \ottnt{t}_j)$ }} +%% %% +%% %% | duplicates ( tnvs ) = emptyset :: :: no_dups_tnvs +%% %% {{ hol (ALL_DISTINCT [[tnvs]]) }} +%% %% {{ lem (duplicates [[tnvs]]) = [ ] }} +%% %% +%% %% | duplicates ( x1 , .. , xn ) = emptyset :: :: no_dups +%% %% {{ hol (ALL_DISTINCT [[x1..xn]]) }} +%% %% {{ lem (duplicates [[x1..xn]]) = [ ] }} +%% %% +%% %% | x NOTIN dom ( E_l ) :: :: notin_dom_l +%% %% {{ hol ([[x]] NOTIN FDOM [[E_l]]) }} +%% %% {{ lem Pervasives.not (Pmap.mem [[x]] [[E_l]]) }} +%% %% +%% %% | x NOTIN dom ( E_x ) :: :: notin_dom_v +%% %% {{ hol ([[x]] NOTIN FDOM [[E_x]]) }} +%% %% {{ lem Pervasives.not (Pmap.mem [[x]] [[E_x]]) }} +%% %% +%% %% | x NOTIN dom ( E_f ) :: :: notin_dom_f +%% %% {{ hol ([[x]] NOTIN FDOM [[E_f]]) }} +%% %% {{ lem Pervasives.not (Pmap.mem [[x]] [[E_f]]) }} +%% %% +%% %% % | p NOTIN dom ( TC ) :: :: notin_dom_tc +%% %% % {{ hol ([[p]] NOTIN FDOM [[TC]]) }} +%% %% % {{ lem Pervasives.not (Pmap.mem [[p]] [[TC]]) }} +%% %% +%% %% | p NOTIN dom ( TD ) :: :: notin_dom_td +%% %% {{ hol ([[p]] NOTIN FDOM [[TD]]) }} +%% %% {{ lem Pervasives.not (Pmap.mem [[p]] [[TD]]) }} +%% %% +%% %% | FV ( t ) SUBSET tnvs :: :: FV_t +%% %% {{ com Free type variables }} +%% %% {{ hol (LIST_TO_SET (ftv_t [[t]]) SUBSET LIST_TO_SET [[tnvs]]) }} +%% %% {{ lem subst (ftv_t [[t]]) [[tnvs]] }} +%% %% +%% %% | FV ( t_multi ) SUBSET tnvs :: :: FV_t_multi +%% %% {{ com Free type variables }} +%% %% {{ hol (LIST_TO_SET (FLAT (MAP ftv_t [[t_multi]])) SUBSET LIST_TO_SET [[tnvs]]) }} +%% %% {{ lem subst (ftv_tm [[t_multi]]) [[tnvs]] }} +%% %% +%% %% | FV ( semC ) SUBSET tnvs :: :: FV_semC +%% %% {{ com Free type variables }} +%% %% {{ hol (LIST_TO_SET (MAP SND [[semC]]) SUBSET LIST_TO_SET [[tnvs]]) }} +%% %% {{ lem subst (ftv_s [[semC]]) [[tnvs]] }} +%% %% +%% %% | inst 'IN' I :: :: inst_in +%% %% {{ hol (MEM [[inst]] [[I]]) }} +%% %% {{ lem ([[inst]] IN [[I]]) }} +%% %% +%% %% | ( p t ) NOTIN I :: :: notin_I +%% %% {{ hol (~?__semC__. MEM (Inst __semC__ [[p]] [[t]]) [[I]]) }} +%% %% {{ lem (Pervasives.not ((Inst [] [[p]] [[t]]) IN [[I]])) }} +%% %% +%% %% | E_l1 = E_l2 :: :: E_l_eqn +%% %% {{ ichl ([[E_l1]] = [[E_l2]]) }} +%% %% +%% %% | E_x1 = E_x2 :: :: E_x_eqn +%% %% {{ ichl ([[E_x1]] = [[E_x2]]) }} +%% %% +%% %% | E_f1 = E_f2 :: :: E_f_eqn +%% %% {{ ichl ([[E_f1]] = [[E_f2]]) }} +%% %% +%% %% | E1 = E2 :: :: E_eqn +%% %% {{ ichl ([[E1]] = [[E2]]) }} +%% %% +%% %% | TD1 = TD2 :: :: TD_eqn +%% %% {{ ichl ([[TD1]] = [[TD2]]) }} +%% %% +%% %% | TC1 = TC2 :: :: TC_eqn +%% %% {{ ichl ([[TC1]] = [[TC2]]) }} +%% %% +%% %% | I1 = I2 :: :: I_eqn +%% %% {{ ichl ([[I1]] = [[I2]]) }} +%% %% +%% %% | names1 = names2 :: :: names_eq +%% %% {{ ichl ([[names1]] = [[names2]]) }} +%% %% +%% %% | t1 = t2 :: :: t_eq +%% %% {{ ichl ([[t1]] = [[t2]]) }} +%% %% +%% %% | t_subst1 = t_subst2 :: :: t_subst_eq +%% %% {{ ichl ([[t_subst1]] = [[t_subst2]]) }} +%% %% +%% %% | p1 = p2 :: :: p_eq +%% %% {{ ichl ([[p1]] = [[p2]]) }} +%% %% +%% %% | xs1 = xs2 :: :: xs_eq +%% %% {{ ichl ([[xs1]] = [[xs2]]) }} +%% %% +%% %% | tnvs1 = tnvs2 :: :: tnvs_eq +%% %% {{ ichl ([[tnvs1]] = [[tnvs2]]) }} + diff --git a/language/l2_rules.ott b/language/l2_rules.ott index 7fb54c9a..9e1b79fb 100644 --- a/language/l2_rules.ott +++ b/language/l2_rules.ott @@ -1,1461 +1,424 @@ -grammar - -formula :: formula_ ::= - | judgement :: :: judgement - - | formula1 .. formulan :: :: dots - - | E_k ( tid ) gives kinf :: :: lookup_k - {{ com Kind lookup }} - {{ hol (FLOOKUP [[E_k]] [[tid]] = SOME [[kinf]]) }} - {{ lem Map.lookup [[tid]] [[E_k]] = Just [[kinf]] }} - - | E_a ( tid ) gives tinf :: :: lookup_a_t - | E_a ( tid ) gives ne :: :: lookup_a_ne - - - | E_t ( id ) gives tinf :: :: lookup_t - {{ com Type lookup }} - {{ hol (FLOOKUP [[E_t]] [[id]] = SOME [[tinf]]) }} - {{ lem Map.lookup [[id]] [[E_t]] = Just [[tinf]] }} - | E_t ( id ) gives overload tinf : tinf1 ... tinfn :: :: lookup_over_t - {{ com Overloaded type lookup }} - - | E_k ( tid ) <-| k :: :: update_k - {{ com Update the kind associated with id to k }} - {{ lem [[true]] (*TODO: update_k needs to be rewritten*) }} - - | E_r ( id0 .. idn ) gives t , ts :: :: lookup_r - {{ com Record lookup }} - {{ lem [[true]] (*TODO write a proper lookup for E_r *) }} - - | E_r ( t ) gives id0 : t0 .. idn : tn :: :: lookup_rt - {{ com Record looup by type }} - {{ lem [[true]] (* write a proper lookup for E_r *) }} - - | E_e ( t ) gives enumerate_map :: :: lookup_e - {{ com Enumeration lookup by type }} - {{ lem Map.lookup [[t]] [[E_e]] = Just [[enumerate_map]] }} - - | dom ( E_t1 ) inter dom ( E_t2 ) = emptyset :: :: E_t_disjoint - {{ hol (DISJOINT (FDOM [[E_t1]]) (FDOM [[E_t2]])) }} - {{ lem disjoint (Map.domain [[E_t1]]) (Map.domain [[E_t2]]) }} - - | dom ( E_k1 ) inter dom ( E_k2 ) = emptyset :: :: E_k_disjoint - {{ hol (DISJOINT (FDOM [[E_f1]]) (FDOM [[E_f2]])) }} - {{ lem disjoint (Map.domain [[E_f1]]) (Map.domain [[E_f2]]) }} - - | disjoint doms ( E_t1 , .... , E_tn ) :: :: E_x_disjoint_many - {{ hol (FOLDR (\E b. case b of NONE => NONE | SOME s => if DISJOINT (FDOM - E) s then SOME (FDOM E UNION s) else NONE) (SOME {}) [[E_t1....E_tn]] <> NONE) }} - {{ lem disjoint_all (List.map Map.domain [[E_t1 .... E_tn]]) }} - {{ com Pairwise disjoint domains }} - | id NOTIN dom ( E_k ) :: :: notin_dom_k - {{ hol ([[id]] NOTIN FDOM [[E_k]]) }} - {{ lem Pervasives.not (Map.member [[id]] [[E_k]]) }} - | id NOTIN dom ( E_t ) :: :: notin_dom_t - {{ hol ([[id]] NOTIN FDOM [[E_t]]) }} - {{ lem Pervasives.not (Map.member [[id]] [[E_t]]) }} - - | id0 : t0 .. idn : tn SUBSET id'0 : t'0 .. id'i : t'i :: :: subsetFields - {{ lem ((Set.fromList [[id0 t0..idn tn]]) subset (Set.fromList [[id'0 t'0..id'i t'i]])) }} - - | num1 lt ... lt numn :: :: increasing - - | num1 gt ... gt numn :: :: decreasing - - | exp1 == exp2 :: :: exp_eqn - {{ ichl ([[exp1]] = [[exp2]]) }} - - | E_k1 == E_k2 :: :: E_k_eqn - {{ ichl ([[E_k1]] = [[E_k2]]) }} +grammar - | E_k1 ~= E_k2 :: :: E_k_approx - {{ lem ([[E_k1]] = [[E_k2]]) (* Todo, not quite equality *) }} - {{ ich arb }} +mut :: 'mut_' ::= + | immutable :: :: immutable + | mutable :: :: mutable - | E_t1 == E_t2 :: :: E_t_eqn - {{ ichl ([[E_t1]] = [[E_t2]]) }} +lvar :: 'lvar_' ::= + | register typ :: :: register + | enum typ :: :: enum + | local mut typ :: :: local + | union typquant typ :: :: union + | unbound :: :: unbound + - | E_r1 == E_r2 :: :: E_r_eqn - {{ ichl ([[E_r1]] = [[E_r2]]) }} - | E_e1 == E_e2 :: :: E_e_eqn - {{ ichl ([[E_e1]] = [[E_e2]]) }} - - | E_d1 == E_d2 :: :: E_d_eqn - {{ ichl ([[E_d1]] = [[E_d2]]) }} +G {{ tex \Gamma }}, D {{ tex \Delta }} :: 'G_' ::= {{ com Type environment }} + | empty :: :: empty {{ tex \epsilon }} {{ com Empty context }} + | G , x1 : typ1 , .. , xn : typn :: :: type_list {{ com List of variables and their types }} +% | G , x1 : k1 , .. , xn : kn :: :: kind_list {{ com List of variables and their kinds }} + | G , kid1 , .. , kidn :: :: kid_list +% | G , quant_item1 , .. , quant_itemn :: :: quant_list +% | G , { nec1 , .. , necn } :: :: constraint_list {{ com Constraints }} + | G , G1 .. Gn :: :: merge {{ com Merge or disjoint union }} + | G , id : lvar :: :: add_local - | E1 == E2 :: :: E_eqn - {{ ichl ([[E1]] = [[E2]]) }} - | S_N1 == S_N2 :: :: S_N_eqn - {{ ichl ([[S_N1]] = [[S_N2]]) }} - - | id == 'id :: :: id_eq - | x1 NOTEQ x2 :: :: id_neq - | lit1 NOTEQ lit2 :: ::lit_neq - | I1 == I2 :: :: I_eqn - {{ ichl ([[I1]] = [[I2]]) }} - - | effect1 == effect2 :: :: Ef_eqn - {{ ichl ([[effect1]] = [[effect2]]) }} - - | t1 == t2 :: :: t_eq - {{ ichl ([[t1]] = [[t2]]) }} - | ne == ne' :: :: ne_eq - {{ ichl ([[ne]] = [[ne']]) }} - | kid == fresh_kid ( E_d ) :: :: kid_eq - {{ ichl ([[kid]] = fresh_kid [[E_d]]) }} +formula :: formula_ ::= + | judgement :: :: judgement + | formula1 .. formulan :: :: dots + | G ( id ) = lvar :: :: lookup_id + | G ( typ1 , id ) = typ2 :: :: lookup_record_field + | G ( typ1 ) = typ2 :: :: lookup_typ + | nexp = length [|| exp , exp1 , .. , expn ||] :: :: vector_length + | order_inc :: :: default_order_inc + | order_dec :: :: default_order_dec + | G |= nexp1 <= nexp2 :: :: prove_lteq defns -check_t :: '' ::= + declarative :: '' ::= defn -E_k |-t t ok :: :: check_t :: check_t_ -{{ lemwcf witness type check_t_witness; check check_t_w_check; }} -{{ com Well-formed types }} - by - - E_k('x) gives K_Typ - ------------------------------------------------------------ :: var - E_k |-t 'x ok - - E_k('x) gives K_infer - E_k('x) <-| K_Typ - ------------------------------------------------------------ :: varInfer - E_k |-t 'x ok - - E_k |-t t1 ok - E_k |-t t2 ok - E_k |-e effect ok - ------------------------------------------------------------ :: fn - E_k |-t t1 -> t2 effect ok - - E_k |-t t1 ok .... E_k |-t tn ok - ------------------------------------------------------------ :: tup - E_k |-t (t1 , .... , tn) ok - - E_k(x) gives K_Lam(k1..kn -> K_Typ) - E_k,k1 |- t_arg1 ok .. E_k,kn |- t_argn ok - ------------------------------------------------------------ :: app - E_k |-t x < t_arg1 .. t_argn > ok - -defn -E_k |-e effect ok :: :: check_ef :: check_ef_ -{{ com Well-formed effects }} -{{ lemwcf witness type check_ef_witness; check check_ef_w_check; }} -by - -E_k('x) gives K_Efct ------------------------------------------------------------ :: var -E_k |-e 'x ok - -E_k('x) gives K_infer -E_k('x) <-| K_Efct ------------------------------------------------------------- :: varInfer -E_k |-e 'x ok - -------------------------------------------------------------- :: set -E_k |-e { base_effect1 , .. , base_effectn } ok - -defn -E_k |-n ne ok :: :: check_n :: check_n_ -{{ com Well-formed numeric expressions }} -{{ lemwcf witness type check_n_witness; check check_n_w_check; }} -by - -E_k(x) gives K_Nat ------------------------------------------------------------ :: id -E_k |-n x ok - -E_k('x) gives K_Nat ------------------------------------------------------------ :: var -E_k |-n 'x ok - -E_k('x) gives K_infer -E_k('x) <-| K_Nat ------------------------------------------------------------- :: varInfer -E_k |-n 'x ok - ------------------------------------------------------------ :: num -E_k |-n num ok - -E_k |-n ne1 ok -E_k |-n ne2 ok ------------------------------------------------------------ :: sum -E_k |-n ne1 + ne2 ok - -E_k |-n ne1 ok -E_k |-n ne2 ok ------------------------------------------------------------ :: minus -E_k |-n ne1 - ne2 ok - -E_k |-n ne1 ok -E_k |-n ne2 ok ------------------------------------------------------------- :: mult -E_k |-n ne1 * ne2 ok - -E_k |-n ne ok ------------------------------------------------------------- :: exp -E_k |-n 2 ** ne ok - -defn -E_k |-o order ok :: :: check_ord :: check_ord_ -{{ com Well-formed numeric expressions }} -{{ lemwcf witness type check_ord_witness; check check_ord_w_check; }} + G |- typ1 ~< typ2 :: :: subtype :: subtype_ + {{ com $[[typ1]]$ is a subtype of $[[typ2]]$ }} + {{ tex [[G]] \vdash [[typ1]] \preccurlyeq [[typ2]] }} by -E_k('x) gives K_Ord ------------------------------------------------------------ :: var -E_k |-o 'x ok - -E_k('x) gives K_infer -E_k('x) <-| K_Ord ------------------------------------------------------------- :: varInfer -E_k |-o 'x ok +----------------- :: refl +G |- typ ~< typ ------------------------------------------------------------- :: inc -E_k |-o inc ok +--------------------- :: wild +G |- _ ~< _ ------------------------------------------------------------- :: dec -E_k |-o dec ok -defn -E_k , k |- t_arg ok :: :: check_targs :: check_targs_ -{{ com Well-formed type arguments kind check matching the application type variable }} -{{ lemwcf witness type check_targs_witness; check check_targs_w_check; }} -by -E_k |-t t ok ---------------------------------------------------------- :: typ -E_k , K_Typ |- t ok +------------- :: id +G |- id ~< id -E_k |-e effect ok ---------------------------------------------------------- :: eff -E_k , K_Efct |- effect ok +G |- typ1 ~< typ'1 .. G |- typn ~< typ'n +--------------------------------------------------- :: tuple +G |- (typ1 , .. , typn ) ~< (typ'1, .. , typ'n) -E_k |-n ne ok ---------------------------------------------------------- :: nat -E_k , K_Nat |- ne ok - -E_k |-o order ok ---------------------------------------------------------- :: ord -E_k, K_Ord |- order ok - -defns -convert_kind :: '' ::= defn -E_k |- kind ~> k :: :: convert_kind :: convert_kind_ -{{ lemwcf witness type convert_kind_witness; check convert_kind_w_check; }} +G |-l lit => typ :: :: infer_lit :: infer_lit_ +{{ com Infer that type of $[[lit]]$ is $[[typ]]$ }} +{{ tex [[G]] \vdash_l [[lit]] \Rightarrow [[typ]] }} by --------------------- :: Typ -E_k |- Type ~> K_Typ -defns -convert_typ :: '' ::= +----------------------------- :: unit +G |-l () => unit -defn -E_d |- quant_item ~> E_k1 , S_N :: :: convert_quants :: convert_quants_ -{{ com Convert source quantifiers to kind environments and constraints }} -{{ lemwcf witness type convert_quants_witness; check convert_quants_w_check; }} -by - -E_k |- kind ~> k ------------------------------------------------------------ :: kind -<E_k,E_a,E_r,E_e> |- kind 'x ~> {'x |-> k}, {} +-------------------- :: zero +G |-l bitzero => bit -E_k('x) gives k ------------------------------------------------------------ :: nokind -<E_k,E_a,E_r,E_e> |- 'x ~> {'x |-> k},{} +-------------------- :: one +G |-l bitone => bit -|- nexp1 ~> ne1 -|- nexp2 ~> ne2 ------------------------------------------------------------ :: eq -E_d |- nexp1 = nexp2 ~> {}, {ne1 = ne2} -|- nexp1 ~> ne1 -|- nexp2 ~> ne2 ------------------------------------------------------------ :: gteq -E_d |- nexp1 >= nexp2 ~> {}, {ne1 >= ne2} +---------------------- :: num +G |-l num => atom < num > -|- nexp1 ~> ne1 -|- nexp2 ~> ne2 ------------------------------------------------------------ :: lteq -E_d |- nexp1 <= nexp2 ~> {}, {ne1 <= ne2} ------------------------------------------------------------ :: in -E_d |- 'x IN {num1 , ... , numn} ~> {}, {'x IN {num1 , ..., numn}} +---------------------- :: true +G |-l true => bool -defn -E_d |- typschm ~> t , E_k , S_N :: :: convert_typschm :: convert_typschm_ -{{ com Convert source types with typeschemes to internal types and kind environments }} -{{ lemwcf witness type convert_typschm_witness; check convert_typschm_w_check; }} -by -E_d |- typ ~> t ------------------------------------------------------------ :: noquant -E_d |- typ ~> t,{},{} - -E_d |- quant_item1 ~> E_k1, S_N1 ... E_d |- quant_itemn ~> E_kn, S_Nn -E_k == E_k1 u+ ... u+ E_kn -E_d u+ <E_k,{},{},{}> |- typ ~> t ------------------------------------------------------------ :: quant -E_d |- forall quant_item1 , ... , quant_itemn . typ ~> t, E_k, S_N1 u+ ... u+ S_Nn +---------------------- :: false +G |-l false => bool defn -E_d |- typ ~> t :: :: convert_typ :: convert_typ_ -{{ com Convert source types to internal types }} -{{ lemwcf witness type convert_typ_witness; check convert_typ_w_check; }} +G |- lexp := exp => typ -| D :: :: bind_assignment :: bind_assignment_ +{{ com Bind assignment returning updated environment }} +{{ tex [[G]] \vdash [[lexp]] := [[exp]] \Rightarrow [[typ]] \dashv [[D]] }} by - -E_k('x) gives K_Typ ------------------------------------------------------------- :: var -<E_k,E_a,E_r,E_e> |- 'x ~> 'x - -E_k(x) gives K_Typ ------------------------------------------------------------- :: id -<E_k,E_a,E_r,E_e> |- x ~> x - -E_d |- typ1 ~> t1 -E_d |- typ2 ~> t2 ------------------------------------------------------------- :: fn -E_d |- typ1->typ2 effectkw effect ~> t1->t2 effect - -E_d |- typ1 ~> t1 .... E_d |- typn ~> tn ------------------------------------------------------------- :: tup -E_d |- ( typ1 , .... , typn ) ~> (t1 , .... , tn) -E_k(x) gives K_Lam (k1..kn -> K_Typ) -<E_k,E_a,E_r,E_e>,k1 |- typ_arg1 ~> t_arg1 .. <E_k,E_a,E_r,E_e>,kn |- typ_argn ~> t_argn ------------------------------------------------------------- :: app -<E_k,E_a,E_r,E_e> |- x <typ_arg1, .. ,typ_argn> ~> x <t_arg1 .. t_argn> + +G |- exp => typ +G |- id <= typ -| D +------------------------------- :: id +G |- id := exp => unit -| D defn -E_d , k |- typ_arg ~> t_arg :: :: convert_targ :: convert_targ_ -{{ com Convert source type arguments to internals }} -{{ lemwcf witness type convert_targ_witness; check convert_targ_w_check; }} +G |- pat <= typ -| D :: :: bind_pat :: bind_pat_ +{{ tex [[G]] \vdash [[pat]] \Leftarrow [[typ]] \dashv [[D]] }} by - -E_d |- typ ~> t -------------------------------------- :: typ -E_d, K_Typ |- typ ~> t - -defn -|- nexp ~> ne :: :: convert_nexp :: convert_nexp_ -{{ com Convert and normalize numeric expressions }} -{{ lemwcf witness type convert_nexp_witness; check convert_nexp_w_check; }} -by - -------------------------------------------------------------- :: id -|- x ~> x ------------------------------------------------------------- :: var -|- 'x ~> 'x +G |- lit <= typ +------------------- :: lit +G |- lit <= typ -| G ------------------------------------------------------------- :: num -|- num ~> num +%% FIXME do add_local +G(id) = local mutable typ' +---------------------- :: local +G |- id <= typ -| G -|- nexp1 ~> ne1 -|- nexp2 ~> ne2 ------------------------------------------------------------- :: mult -|- nexp1 * nexp2 ~> ne1 * ne2 +G(id) = unbound +---------------------- :: unbound +G |- id <= typ -| G -|- nexp1 ~> ne1 -|- nexp2 ~> ne2 ------------------------------------------------------------ :: add -|- nexp1 + nexp2 ~> ne1 + ne2 -|- nexp1 ~> ne1 -|- nexp2 ~> ne2 ------------------------------------------------------------ :: sub -|- nexp1 - nexp2 ~> ne1 - ne2 +G(id) = enum typ' +G |- typ' ~< typ +---------------------- :: enum +G |- id <= typ -| G -|- nexp ~> ne ------------------------------------------------------------- :: exp -|- 2** nexp ~> 2 ** ne -defn -E_d |-n ne ~= ne' :: :: conforms_to_ne :: conforms_to_ne_ -by - -E_k |-n ne ok ------------------------------------------------------------- :: refl -<E_k,E_a,E_r,E_e> |-n ne ~= ne - -E_d |-n ne1 ~= ne2 -E_d |-n ne2 ~= ne3 ------------------------------------------------------------- :: trans -E_d |-n ne1 ~= ne3 +---------------------- :: wild +G |- _ <= typ -| G -E_d |-n ne2 ~= ne1 -------------------------------------------------------------- :: assoc -E_d |-n ne1 ~= ne2 -E_a(x) gives ne -<E_k,E_a,E_r,E_e> |-n ne ~= ne' ------------------------------------------------------------- :: abbrev -<E_k,E_a,E_r,E_e> |-n x ~= ne' +%% FIXME Should be fold? +G |- pat1 <= typ1 -| G1 .. G |- patn <= typn -| Gn +------------------------------------------------------- :: tup +G |- (pat1 , .. , patn ) <= (typ1 , .. , typn ) -| G , G1 .. Gn -:formula_ne_eq: num == num' ------------------------------------------------------------ :: constants -E_d |-n num ~= num' ------------------------------------------------------------- :: rest -E_d |-n ne ~= ne' defn -E_d |- t ~= t' :: :: conforms_to :: conforms_to_ -{{ com Relate t and t' when t can be used where t' is expected without consideration for non-constant nats }} +G |- pat => typ -| D :: :: infer_pat :: infer_pat_ +{{ tex [[G]] \vdash [[pat]] \Leftarrow [[typ]] \dashv [[D]] }} by -E_k |-t t ok ------------------------------------------------------------- :: refl -<E_k,E_a,E_r,E_e> |- t ~= t - -E_d |- t1 ~= t2 -E_d |- t2 ~= t3 ------------------------------------------------------------- :: trans -E_d |- t1 ~= t3 +G(id) = enum typ +-------------------- :: id +G |- id => typ -| G ------------------------------------------------------------- :: var -E_d |- 'x ~= t ------------------------------------------------------------- :: var2 -E_d |- t ~= 'x +G |- pat <= typ -| D +------------------------------- :: typ +G |- (typ) pat => typ -| D -E_a(x) gives u -<E_k,E_a,E_r,E_e> |- u ~= t ------------------------------------------------------------- :: abbrev -<E_k,E_a,E_r,E_e> |- x ~= t -E_a(x) gives u -<E_k,E_a,E_r,E_e> |- t ~= u ------------------------------------------------------------- :: abbrev2 -<E_k,E_a,E_r,E_e> |- t ~= x +G |-l lit => typ +----------------------- :: lit +G |- lit => typ -| G - -E_d |- t1 ~= u1 .... E_d |- tn ~= un ------------------------------------------------------------- :: tup -E_d |- (t1,....,tn) ~= (u1,....,un) -E_k(x) gives K_Lam (k1 .. kn -> K_Typ) -<E_k,E_a,E_r,E_e>,k1 |- t_arg1 ~= t_arg'1 .. <E_k,E_a,E_r,E_e>,kn |- t_argn ~= t_arg'n ------------------------------------------------------------- :: app -<E_k,E_a,E_r,E_e> |- x <t_arg1 .. t_argn> ~= x <t_arg'1 .. t_arg'n> +defn +G |-i id => typ :: :: infer_id :: infer_id_ +{{ com Infer type of indentifier }} +{{ tex [[G]] \vdash_i [[id]] \Rightarrow [[typ]] }} +by ------------------------------------------------------------- :: atom -E_d |- atom<ne> ~= range<ne1 ne2> +G(id) = local mut typ +---------------------- :: local +G |-i id => typ ------------------------------------------------------------- :: atom2 -E_d |- range<ne1 ne2> ~= atom<ne> -x' NOTEQ x -E_a(x') gives {tid1|->kinf1, .. ,tidm|->kinfm}, S_N, tag, u -<E_k,E_a,E_r,E_e> |- x <t_arg1 .. t_argn> ~= u [ t_arg'1/tid1 .. t_arg'm/tidm ] ------------------------------------------------------------- :: appAbbrev -<E_k,E_a,E_r,E_e> |- x < t_arg1 .. t_argn> ~= x' <t_arg'1 .. t_arg'm> +G(id) = enum typ +---------------------- :: enum +G |-i id => typ -x' NOTEQ x -E_a(x') gives {tid1|->kinf1, .. ,tidn|->kinfn}, S_N, tag, u -<E_k,E_a,E_r,E_e> |- u [ t_arg1/tid1 .. t_argn/tidn ] ~= x <t_arg'1 .. t_arg'm> ------------------------------------------------------------- :: appAbbrev2 -<E_k,E_a,E_r,E_e> |- x' < t_arg1 .. t_argn> ~= x <t_arg'1 .. t_arg'm> -E_d |- t ~= u ------------------------------------------------------------- :: register -E_d |- register<t> ~= u +G(id) = register typ +---------------------- :: register +G |-i id => typ -E_d |- t ~= u ------------------------------------------------------------- :: reg -E_d |- reg<t> ~= u +G(id) = union typquant typ +------------------------------------- :: union +G |-i id => typ defn -E_d , k |- t_arg ~= t_arg' :: :: targconforms :: targconforms_ -{{ lemwcf witness type check_targeq_witness; check check_targeq_w_check; }} +G |-f exp . id => typ :: :: infer_field :: infer_field_ +{{ tex [[G]] \vdash_f [[exp]] . [[id]] \Rightarrow [[typ]] }} by -E_d |- t ~= t' ------------------------------------------------------------- :: typ -E_d, K_Typ |- t ~= t' - -E_d |-n ne ~= ne' ------------------------------------------------------------ :: nexp -E_d, K_Nat |- ne ~= ne' -defn -E_d |-c t ~= t' :: :: conforms_to_upto_coerce :: conforms_to_upto_coerce_ -{{ com Relate t and t' when t can be used where t' is expected upto applying coercions to t }} -by +G |- exp => typ1 +G ( typ1 ) = register [ id2 ] +G ( id2 ) = (base,top,ranges) +ranges ( id ) = vec_typ +---------------------------- :: register +G |-f exp . id => vec_typ -E_d |- t ~= t' -------------------------------------------------------------- :: base -E_d |-c t ~= t' -E_d |-n ne2 ~= one -------------------------------------------------------------- :: bitToVec -E_d |-c bit ~= vector<ne ne2 order bit> -E_d |-n ne2 ~= one -------------------------------------------------------------- :: vecToBit -E_d |-c vector<ne ne2 order bit> ~= bit +G |- exp => typ1 +G ( typ1 , id ) = typ +---------------------------- :: record +G |-f exp . id => typ -------------------------------------------------------------- :: vecToAtom -E_d |-c vector<ne ne2 order bit> ~= atom<ne3> -------------------------------------------------------------- :: vecToRange -E_d |-c vector<ne ne2 order bit> ~= range<ne3 ne4> +defn +G |- exp1 => n_constraint :: :: infer_flow :: infer_flow_ +by -E_e(x) gives enumerate_map -------------------------------------------------------------- :: enumToRange -<E_k,E_a,E_r,E_e> |-c x ~= range<ne1 ne2> -E_e(x) gives enumerate_map -------------------------------------------------------------- :: rangeToEnum -<E_k,E_a,E_r,E_e> |-c range<ne1 ne2> ~= x +G |- x => atom < nexp1 > +G |- y => atom < nexp2 > +---------------------------- :: lteq +G |- :E_app: lteq_atom_atom ( x , y ) => nexp1 <= nexp2 -E_e(x) gives enumerate_map -------------------------------------------------------------- :: enumToAtom -<E_k,E_a,E_r,E_e> |-c x ~= atom<ne> -E_e(x) gives enumerate_map -------------------------------------------------------------- :: atomToEnum -<E_k,E_a,E_r,E_e> |-c atom<ne> ~= x +G |- x => atom < nexp1 > +G |- y => atom < nexp2 > +---------------------------- :: gteq +G |- :E_app: gteq_atom_atom ( x , y ) => nexp1 >= nexp2 -E_d |-c t1 ~= u1 .... E_d |-c tn ~= un ------------------------------------------------------------- :: tup -E_d |-c (t1,....,tn) ~= (u1,....,un) +G |- x => atom < nexp1 > +G |- y => atom < nexp2 > +---------------------------- :: lt +G |- :E_app: lt_atom_atom ( x , y ) => nexp1 + numOne <= nexp2 -E_k(x) gives K_Lam (k1 .. kn -> K_Typ) -<E_k,E_a,E_r,E_e>,k1 |-c t_arg1 ~= t_arg'1 .. <E_k,E_a,E_r,E_e>,kn |-c t_argn ~= t_arg'n ------------------------------------------------------------- :: app -<E_k,E_a,E_r,E_e> |-c x <t_arg1 .. t_argn> ~= x <t_arg'1 .. t_arg'n> +G |- x => atom < nexp1 > +G |- y => atom < nexp2 > +---------------------------- :: gt +G |- :E_app: lteq_atom_atom ( x , y ) => nexp1 >= nexp2 + numOne -x' NOTEQ x -E_a(x') gives {tid1|->kinf1, .. ,tidm|->kinfm}, S_N, tag, u -<E_k,E_a,E_r,E_e> |-c x <t_arg1 .. t_argn> ~= u [ t_arg'1/tid1 .. t_arg'm/tidm ] ------------------------------------------------------------- :: appAbbrev -<E_k,E_a,E_r,E_e> |-c x < t_arg1 .. t_argn> ~= x' <t_arg'1 .. t_arg'm> +G |- id => range <nexp1 , nexp2 > +G |- y => atom < nexp > +------------------------------------------------------------------------------- :: lt_range_atom +G |- :E_app: lt_range_atom ( id , y ) => range < nexp1 , min (nexp - 1 , nexp2 ) > -x' NOTEQ x -E_a(x') gives {tid1|->kinf1, .. ,tidn|->kinfn}, S_N, tag, u -<E_k,E_a,E_r,E_e> |-c u [ t_arg1/tid1 .. t_argn/tidn ] ~= x <t_arg'1 .. t_arg'm> ------------------------------------------------------------- :: appAbbrev2 -<E_k,E_a,E_r,E_e> |-c x' < t_arg1 .. t_argn> ~= x <t_arg'1 .. t_arg'm> -E_d |-c t ~= u ------------------------------------------------------------- :: register -E_d |-c register<t> ~= u -E_d |-c t ~= u ------------------------------------------------------------- :: reg -E_d |-c reg<t> ~= u defn -E_d , k |-c t_arg ~= t_arg' :: :: targconforms_coerce :: targconforms_coerce_ + G |- exp => typ :: :: infer_exp :: infer_exp_ +{{ com Infer that type of $[[exp]]$ is $[[typ]]$ }} +{{ tex [[G]] \vdash [[exp]] \Rightarrow [[typ]] }} by -E_d |-c t ~= t' ------------------------------------------------------------- :: typ -E_d, K_Typ |-c t ~= t' -E_d |-n ne ~= ne' ------------------------------------------------------------ :: nexp -E_d, K_Nat |-c ne ~= ne' +G |- exp1 <= unit ... G |- expn <= unit +------------------------------------------ :: nondet +G |- nondet { exp1 ; ... ; expn } => unit -defn -E_d |- select ( conformsto ( t , t' ) ) of tinflist gives tinflist' :: :: selectoverload :: so_ -{{ tex [[select]]_{[[conformsto]] ([[t]],[[t']])} ([[tinflist]]) [[gives]] [[tinflist']] }} -by +G |-i id => typ +---------------- :: id +G |- id => typ -E_d |- ti ~= ti' -E_d |- tj' ~= tj -E_d |- select (full(ti,tj)) of tinf0 .. tinfm tinf'0 .. tinf'n gives empty ---------------------------------------------------------- :: full -E_d |- select (full( ti, tj)) of tinf0 .. tinfm E_k,S_N,tag, ti' -> tj' effect tinf'0 .. tinf'n gives E_k,S_N,tag,ti' -> tj' -E_d |- ti ~= ti' -E_d |- select (parm(ti,tj)) of tinf0 .. tinfm gives empty --------------------------------------------------------- :: parm -E_d |- select (parm( ti, tj)) of tinf0 .. tinfm E_k,S_N,tag,ti' -> t effect tinf'0 .. tinf'n gives E_k,S_N,tag,ti' -> t +G |-l lit => typ +---------------- :: lit +G |- lit => typ -defn -E_d , widening |- t ~< t' : t'' , S_N :: :: consistent_typ :: consistent_typ_ -{{ com t is consistent with t' if they match if t can be used where t' is needed after the constraints are solved, with no coercions needed. t'' is the consistent type when widening is required }} -by -E_k |-t t ok ------------------------------------------------------------- :: refl -<E_k,E_a,E_r,E_e>,widening |- t ~< t:t,{} - -E_d,widening |- t1 ~< t3:t4, S_N1 -E_d,widening |- t4 ~< t2: t5, S_N2 ------------------------------------------------------------- :: trans -E_d,widening |- t1 ~< t2: t5, S_N1 u+ S_N2 - -E_a(x) gives {},S_N1,tag,u -<E_k,E_a,E_r,E_e>,widening |- u ~< t:t', S_N ------------------------------------------------------------- :: abbrev -<E_k,E_a,E_r,E_e>,widening |- x ~< t : t', S_N u+ S_N1 - -E_a(x) gives {},S_N1,tag,u -<E_k,E_a,E_r,E_e>,widening |- t ~< u: t', S_N' ------------------------------------------------------------- :: abbrev2 -<E_k,E_a,E_r,E_e>,widening |- t ~< x : t', S_N u+ S_N1 - ------------------------------------------------------------- :: var -E_d,widening |- 'x ~< t:t, {} - ------------------------------------------------------------- :: var2 -E_d,widening |- t ~< 'x: t, {} - -E_d,widening |- t1 ~< u1:u'1, S_N1 .... E_d,widening |- tn ~< un:u'n, S_Nn ------------------------------------------------------------- :: tup -E_d,widening |- (t1,....,tn) ~< (u1,....,un): (u'1,....,u'n), S_N1 u+ .... u+ S_Nn +----------------------------------- :: sizeof +G |- sizeof nexp => atom < nexp > ------------------------------------------------------------ :: range -E_d,widening |- range <ne1 ne2> ~< range<ne3 ne4>: range<ne3 ne4>, { ne3 <= ne1, ne2 <= ne4 } +-------------------------------------------- :: constraint +G |- constraint n_constraint => bool ----------------------------------------------------------- :: atomRange -E_d,(nums,_) |- atom <ne> ~< range<ne1 ne2>: atom<ne>, { ne1 <= ne, ne <= ne2 } +G |-f exp . id => typ +------------------------ :: field +G |- exp . id => typ ----------------------------------------------------------- :: atom -E_d,(none,_) |- atom <ne1> ~< atom<ne2>: atom<ne2>, { ne1 = ne2 } +G |- exp1 => typ1 .... G |- expn => typn +---------------------------------------------------------- :: tuple +G |- ( exp1 , .... , expn ) => (typ1 , .... , typn ) -num1 lt num2 ----------------------------------------------------------- :: atomWidenConst -E_d,(nums,_) |- atom <num1> ~< atom<num2>: range<num1 num2>, {} -num2 lt num1 ---------------------------------------------------------- :: atomWidenConst2 -E_d,(nums,_) |- atom <num1> ~< atom<num2>: range<num2 num1>, {} ----------------------------------------------------------- :: rangeAtom -E_d,widening |- range<ne1 ne2> ~< atom<'x>: atom<'x>, { ne1 <= 'x, 'x <= ne2 } -E_d,(nums,none) |- t ~< t': t'', S_N ----------------------------------------------------------- :: vector -E_d,(_,none) |- vector <ne1 ne2 order t> ~< vector <ne3 ne4 order t'>: vector<ne3 ne4 order t''>, {ne2=ne4, ne1=ne3} u+ S_N +G |- lexp := exp => typ -| D +-------------------- :: assign +G |- lexp := exp => typ -E_d,(nums,none) |- t ~< t': t'', S_N ----------------------------------------------------------- :: vectorWiden -E_d,(_,vectors) |- vector <ne1 ne2 order t> ~< vector <ne3 ne4 order t'>: vector<ne3 ne4 order t''>, {ne2=ne4} u+ S_N -E_k(x) gives K_Lam (k1 .. kn -> K_Typ) -<E_k,E_a,E_r,E_e>,widening,k1 |- t_arg1 ~< t_arg'1,S_N1 .. <E_k,E_a,E_r,E_e>,widening,kn |- t_argn ~< t_arg'n,S_Nn ------------------------------------------------------------- :: app -<E_k,E_a,E_r,E_e>,widening |- x <t_arg1 .. t_argn> ~< x <t_arg'1 .. t_arg'n>:x<t_arg'1 .. t_arg'n>, S_N1 u+ .. u+ S_Nn -x' NOTEQ x -E_a(x') gives {tid1|->kinf1, .. ,tidm|->kinfm}, S_N, tag, u -<E_k,E_a,E_r,E_e>,widening |- x <t_arg1 .. t_argn> ~< u [ t_arg'1/tid1 .. t_arg'm/tidm ]: t ,S_N2 ------------------------------------------------------------- :: appAbbrev -<E_k,E_a,E_r,E_e>,widening |- x < t_arg1 .. t_argn> ~< x' <t_arg'1 .. t_arg'm>: x'<t_arg'1 .. t_arg'm>, S_N u+ S_N2 +---------------------------- :: record_update +G |- lexp . id := exp => typ -x' NOTEQ x -E_a(x') gives {tid1|->kinf1, .. ,tidm|->kinfm}, S_N, tag, u -<E_k,E_a,E_r,E_e>,widening |- u [ t_arg'1/tid1 .. t_arg'm/tidm ] ~< x <t_arg1 .. t_argn>: t ,S_N2 ------------------------------------------------------------- :: appAbbrev2 -<E_k,E_a,E_r,E_e>,widening |- x' <t_arg'1 .. t_arg'm> ~< x < t_arg1 .. t_argn> :x<t_arg1 .. t_argn>, S_N u+ S_N2 -defn -E_d , widening , k |- t_arg ~< t_arg' , S_N :: :: targ_consistent :: targ_consistent_ -by +G |- exp <= typ +----------------------- :: cast +G |- ( typ ) exp => typ -E_d,widening |- t ~< t': t'', S_N ------------------------------------------------------------- :: typ -E_d,widening, K_Typ |- t ~< t',S_N ------------------------------------------------------------ :: nexp -E_d,widening, K_Nat |- ne ~< ne',{ne=ne'} -defn -E_d , widening, t' |- exp : t gives t'' , exp' , S_N , effect :: :: coerce_typ :: coerce_typ_ -{{ lemwcf witness type coerce_typ_witness; check coerce_typ_w_check; }} -by +G |- :E_app: id ( exp1 , exp2 ) => typ +-------------------------------- :: app_infix +G |- exp1 id exp2 => typ -E_d, widening, u1 |- id1 : t1 gives u1, exp1, S_N1,effect1 .. E_d,widening, un|- idn: tn gives un,expn, S_Nn,effectn -exp' == switch exp { case (id1, .., idn) -> (exp1,..,expn) } --------------------------------------- :: tuple -E_d, widening, (u1 , .. , un) |- exp : (t1 , .. , tn) gives (u1 , .. , un), exp', S_N1 u+ .. u+ S_Nn, pure - -E_d,(nums,vectors) |- u ~< t: t',S_N -exp' == (annot) exp -------------------------------------------------- :: vectorUpdateStart -E_d, widening, vector< ne1 ne2 order t > |- exp : vector <ne3 ne4 order u> gives vector <ne3 ne4 order t'>, exp', S_N u+ {ne2=ne4}, pure - -E_d, (none,none) |- u ~< bit:bit, S_N -exp' == to_num exp --------------------------------------------------- :: toNum -E_d,widening, range<ne1 ne2> |- exp : vector <ne3 ne4 order u> gives range<ne1 ne2>, exp', S_N u+ {ne1=zero, ne2 >= 2**ne4}, pure - -exp' == to_vec exp --------------------------------------- :: fromNum -E_d,widening, vector<ne1 ne2 order bit> |- exp: range<ne3 ne4> gives vector<ne1 ne2 order bit>,exp', {ne3 = zero, ne4 <= 2** ne2}, pure - -E_d |- typ ~> t -exp' == (typ) exp -E_d,widening, u |- exp':t gives t',exp'', S_N, pure --------------------------------------- :: readReg -E_d,widening, u |- exp : register<t> gives t', exp'', S_N, {rreg} - -exp' == :E_tup_app: msb(exp) --------------------------------------- :: accessVecBit -E_d,widening, bit |- exp : vector<ne1 ne2 order bit> gives bit,exp', { ne1=one},pure - -E_d,widening |- range<zero one> ~< range<ne1 ne2>: t,S_N -exp' == switch exp { case bitzero -> numZero case bitone -> numOne} --------------------------------------- :: bitToNum -E_d,widening, range<ne1 ne2> |- exp : bit gives range<ne1 ne2>, exp',S_N,pure - -E_d,widening |- range<ne1 ne2> ~< range<zero one>: t,S_N -exp' == switch exp { case numZero -> bitzero case numOne -> bitone } -------------------------------------- :: numToBit -E_d, widening, bit |- exp : range<ne1 ne2> gives bit, exp',S_N,pure - -E_d,(nums,none) |- atom<ne> ~< range<zero one>: t,S_N -exp' == switch exp { case numZero -> bitzero case numOne -> bitone } -------------------------------------- :: numToBitAtom -E_d,widening, bit |- exp : atom<ne> gives bit, exp',S_N,pure - -E_e(x) gives { </numi |-> idi//i/> } -exp' == switch exp { </case numi -> idi//i/> } -ne3 == count( </numi//i/>) ------------------------------------------------- :: toEnumerate -<E_k,E_a,E_r,E_e>,widening, x |- exp : range<ne1 ne2> gives x,exp', {ne1<=zero,ne2<=ne3},pure - -E_e(x) gives { </numi |-> idi//i/> } -exp' == switch exp { </case idi -> numi//i/> } -ne3 == count( </numi//i/>) -<E_k,E_a,E_r,E_e>,(nums,none) |- range<zero ne3> ~< range<ne1 ne2>:t, S_N ------------------------------------------------- :: fromEnumerate -<E_k,E_a,E_r,E_e>,widening,range<ne1 ne2> |- exp: x gives range<zero ne3>, exp', S_N,pure - -E_d,widening |- t ~< u: u', S_N --------------------------------------- :: eq -E_d,widening, u |- exp: t gives u', exp, S_N,pure +--------------------------------------- :: app +G |- :E_app: id (exp1 , .. , expn ) => typ -defns -check_lit :: '' ::= - -defn -widening , t |- lit : t' => exp , S_N :: :: check_lit :: check_lit_ -{{ com Typing literal constants, coercing to expected type t }} -by - - ------------------------------------------------------------ :: num -widening, range <ne ne'> |- num : atom < num > => num , { ne <= num, num <= ne' } - ------------------------------------------------------------ :: numToVec -widening, vector <ne ne' order bit> |- num : atom < num > => to_vec num , { num + one <= 2**ne' } +G |- exp1 => bool +G |- exp2 => unit +------------------------------- :: while_loop +G |- while exp1 do exp2 => unit - ------------------------------------------------------------ :: numbitzero -widening, bit |- numZero : atom < zero > => bitzero, {} +G |- exp1 => unit +G |- exp2 => bool +------------------------------- :: until_loop +G |- repeat exp1 until exp2 => unit - ------------------------------------------------------------ :: numbitone -widening, bit |- numOne : atom < one > => bitone, {} - - ------------------------------------------------------------- :: string -widening, string |- :L_string: string : :T_string_typ: string => :E_lit: string, {} +G |- exp1 => range <nexp1,nexp1'> +G |- exp2 => range <nexp2,nexp2'> +G |= nexp1' <= nexp2 +G |- exp3 <= int +G |- exp4 => unit +----------------------------------------------------------------------- :: for_inc +G |- foreach ( id from exp1 to exp2 by exp3 in inc ) exp4 => unit - ne == bitlength(hex) - ------------------------------------------------------------ :: hex -widening, vector<ne1 ne2 order bit> |- hex : vector< ne1 ne order bit> => hex, {ne=ne2} +G |- exp1 => range <nexp1,nexp1'> +G |- exp2 => range <nexp2,nexp2'> +G |= nexp2' <= nexp1 +G |- exp3 <= int +G |- exp4 => unit +----------------------------------------------------------------------- :: for_dec +G |- foreach ( id from exp1 to exp2 by exp3 in dec ) exp4 => unit -ne == bitlength(bin) - ------------------------------------------------------------ :: bin -widening,vector<ne1 ne2 order bit> |- bin : vector< ne1 ne order bit> => bin, {ne=ne2} - ------------------------------------------------------------ :: unit -widening, unit |- () : unit => unit, {} +G |- foreach ( id from exp1 to exp2 by exp3 in inc) exp4 => typ +----------------------------------------------------------------------- :: forup +G |- foreach ( id from exp1 to exp2 by exp3 ) exp4 => typ - ------------------------------------------------------------ :: bitzero -widening, bit |- bitzero : bit => bitzero, {} - ------------------------------------------------------------ :: bitone -widening, bit |- bitone : bit => bitzero, {} +G |- foreach ( id from exp1 to exp2 by numOne in inc) exp3 => typ +----------------------------------------------------------------------- :: forupbyone +G |- foreach ( id from exp1 to exp2 ) exp3 => typ ------------------------------------------------------------- :: undef -widening, t |- undefined : t => undefined, {} -defns -check_pat :: '' ::= - -defn -E , t |- pat : t' gives pat' , E_t , S_N :: :: check_pat :: check_pat_ -{{ com Typing patterns, building their binding environment }} -by +G |- foreach ( id from exp1 to exp2 by exp3 in dec) exp4 => typ +--------------------------------------------------------------------------- :: fordown +G |- foreach ( id from exp1 downto exp2 by exp3 ) exp4 => typ -lit NOTEQ undefined -(none,none),t |- lit : u => lit',S_N -E_d,(nums,none) |- u ~< t: t', S_N' ------------------------------------------------------------- :: lit -<E_t,E_d>, t |- lit : t' gives lit', {}, S_N u+ S_N' - ------------------------------------------------------------- :: wild -E, t |- _ : t gives _, {}, {} - -E,t |- pat : u gives pat',E_t1,S_N -id NOTIN dom(E_t1) ------------------------------------------------------------- :: as -E,t |- (pat as id) : u gives (pat' as id), (E_t1 u+ {id|->t}),S_N - -E_t(id) gives {}, {}, Default, t' -<E_t,E_d>,t' |- pat : t gives pat', E_t1,S_N -E_d,(none,none) |- t' ~< u : u', S_N' ------------------------------------------------------------- :: asDefault -<E_t,E_d>,u |- (pat as id) : t gives (pat' as id), (E_t1 u+ {id|->t'}),S_N u+ S_N' - -E_d |- typ ~> t -<E_t,E_d>,t |- pat : t gives pat',E_t1,S_N ------------------------------------------------------------- :: typ -<E_t,E_d>,u |- (typ) pat : t gives pat',E_t1,S_N - -E_t(id) gives {tid1 |-> kinf1 , .. , tidm|-> kinfm}, S_N, Ctor, (u'1,..,u'n) -> x < t_arg1 .. t_argm > pure -(u1,..,un) -> x <t_args'> pure == (u'1,..,u'n) -> x <t_args> pure [t_arg1/tid1 .. t_argm/tidm] -<E_t,E_d>,u1 |- pat1 : t1 gives pat'1,E_t1,S_N1 .. <E_t,E_d>,un |- patn : tn gives pat'n,E_tn,S_Nn -disjoint doms(E_t1,..,E_tn) -E_d,(nums,vectors) |- x <t_args'> ~< t: t', S_N ------------------------------------------------------------- :: constr -<E_t,E_d>,t |- id(pat1, .., patn) : x<t_args'> gives id(pat'1, ..,pat'n), u+ E_t1 .. E_tn, S_N u+ S_N1 u+ .. u+ S_Nn - - -E_t(id) gives {tid1 |-> kinf1 , .. , tidm|-> kinfm}, S_N, Ctor, unit -> x < t_arg1 .. t_argm > pure -unit -> x <t_args'> pure == unit -> x <t_args> pure [t_arg1/tid1 .. t_argm/tidm] -E_d,(nums,vectors) |- x <t_args'> ~< t: t', S_N -------------------------------------------------------------- :: identConstr -<E_t,E_d>, t |- :P_id: id : t gives :P_id: id, {}, S_N - -E_t(id) gives {},{},Default,t -E_d,(nums,vectors) |- t ~< u: u', S_N ------------------------------------------------------------- :: varDefault -<E_t,E_d>,u |- :P_id: id : t gives :P_id: id, (E_t u+ {id|->t}),S_N - ------------------------------------------------------------- :: var -<E_t,E_d>,t |- :P_id: id : t gives :P_id: id, (E_t u+ {id|->t}),{} - -E_r(</idi//i/>) gives x< t_args>, (</ti//i/>) -</<E_t,<E_k,E_a,E_r,E_e>>,ti |- pati : ui gives pat'i, E_ti,S_Ni//i/> -disjoint doms(</E_ti//i/>) -<E_k,E_a,E_r,E_e>,(nums,vectors) |- x<t_args> ~< t: t', S_N ------------------------------------------------------------- :: record -<E_t,<E_k,E_a,E_r,E_e>>,t |- { </idi = pati//i/> semi_opt } : x<t_args> gives {</idi=pat'i//i/> semi_opt }, :E_t_multi_union: u+ </E_ti//i/>, S_N u+ </S_Ni//i/> - -<E_t,E_d>,t |- pat1 : u1 gives pat'1, E_t1,S_N1 ... <E_t,E_d>,t |- patn : un gives pat'n, E_tn,S_Nn -disjoint doms(E_t1, ... ,E_tn) -E_d,(nums,vectors) |- u1 ~< t:t',S_N'1 ... E_d,(nums,vectors) |- un ~< t:t',S_N'n -ne4==length(pat1 ... patn) -S_N ==S_N1 u+ ... u+ S_Nn -S_N' == S_N'1 u+ ... u+ S_N'n ------------------------------------------------------------ :: vector -<E_t,E_d>, vector<ne1 ne2 order t> |- [ pat1, ..., patn ] : vector< ne3 ne4 order u> gives [ pat'1, ..., pat'n ], (E_t1 u+ ... u+ E_tn), S_N u+ S_N' u+ {ne2=ne4} - -<E_t,E_d>,t |- pat1 : u1 gives pat'1, E_t1,S_N1 ... <E_t,E_d>,t |- patn : un gives pat'n, E_tn,S_Nn -E_d,(nums,vectors) |- u1 ~< t:t',S_N'1 ... E_d,(nums,vectors) |- un ~< t:t',S_N'n -ne4 == length(pat1 ... patn) -disjoint doms(E_t1 , ... , E_tn) -num1 lt ... lt numn -S_N == S_N1 u+ ... u+ S_Nn -S_N' == S_N'1 u+ ... u+ S_N'n ------------------------------------------------------------ :: indexedVectorInc -<E_t,E_d>, vector<ne1 ne2 inc t> |- [ num1 = pat1 , ... , numn = patn ] : vector< ne3 ne4 inc t> gives [num1 = pat'1 , ... , numn = pat'n], (E_t1 u+ ... u+ E_tn), {ne1<=num1, ne2 >= ne4} u+ S_N1 u+ ... u+ S_Nn - -<E_t,E_d>,t |- pat1 : u1 gives pat'1, E_t1,S_N1 ... <E_t,E_d>,t |- patn : un gives pat'n, E_tn,S_Nn -E_d,(nums,vectors) |- u1 ~< t:t',S_N'1 ... E_d,(nums,vectors) |- un ~< t:t',S_N'n -ne4 == length(pat1 ... patn) -disjoint doms(E_t1 , ... , E_tn) -num1 gt ... gt numn -S_N == S_N1 u+ ... u+ S_Nn -S_N' == S_N'1 u+ ... u+ S_N'n ------------------------------------------------------------ :: indexedVectorDec -<E_t,E_d>, vector<ne1 ne2 dec t> |- [ num1 = pat1 , ... , numn = patn ] : vector< ne3 ne4 dec t> gives [num1 = pat'1 , ... , numn = pat'n], (E_t1 u+ ... u+ E_tn), {ne1>=num1, ne2 >= ne4} u+ S_N1 u+ ... u+ S_Nn - -<E_t,E_d>, vector<ne''1 ne'''1 order t> |- pat1 : vector< ne''1 ne'1 order u1> gives pat'1, E_t1,S_N1 ... <E_t,E_d>, vector<ne''n ne'''n order t> |- pat1 : vector< ne''n ne'n order u1> gives pat'n, E_tn,S_Nn -E_d,(nums,vectors) |- u1 ~< t:t',S_N'1 ... E_d,(nums,vectors) |- un ~< t:t',S_N'n -disjoint doms(E_t1 , ... , E_tn) -S_N == S_N1 u+ ... u+ S_Nn -S_N' == S_N'1 u+ ... u+ S_N'n ------------------------------------------------------------ :: vectorConcat -<E_t,E_d>, vector<ne1 ne2 order t> |- pat1 : ... : patn : vector<ne1 ne4 order t> gives pat'1 : ... : pat'n, (E_t1 u+ ... u+ E_tn),{ne'1 + ... + ne'n <= ne2} u+ S_N u+ S_N' - -E,t1 |- pat1 : u1 gives pat'1,E_t1,S_N1 .... E,tn |- patn : un gives pat'n,E_tn,S_Nn -disjoint doms(E_t1,....,E_tn) ------------------------------------------------------------- :: tup -E,(t1, .... , tn) |- (pat1, ...., patn) : (u1 , .... , un) gives (pat'1, .... , pat'n), (E_t1 u+ .... u+ E_tn),S_N1 u+ .... u+ S_Nn - -<E_t,E_d>,t |- pat1 : u1 gives pat'1,E_t1,S_N1 .. <E_t,E_d>,t |- patn : un gives pat'n,E_tn,S_Nn -disjoint doms(E_t1,..,E_tn) -E_d,(nums,none) |- u1 ~< t:t',S_N'1 .. E_d,(nums,none) |- un ~< t:t',S_N'n -disjoint doms(E_t1 , .. , E_tn) -S_N == S_N1 u+ .. u+ S_Nn -S_N' == S_N'1 u+ .. u+ S_N'n ------------------------------------------------------------- :: list -<E_t,E_d>, list<t> |- [||pat1, .., patn ||] : list< t> gives [|| pat'1, .. , pat'n ||],(E_t1 u+ .. u+ E_tn),S_N u+ S_N' +G |- foreach ( id from exp1 to exp2 by numOne in dec) exp3 => typ +------------------------------------------------------------------------- :: fordownbyone +G |- foreach ( id from exp1 downto exp2 ) exp3 => typ -defns -check_exp :: '' ::= - -defn -E , t , widening |- exp : t' gives exp' , I , E_t :: :: check_exp :: check_exp_ -{{ com Typing expressions, collecting nexp constraints, effects, and new bindings }} -by - -E_t(id) gives {tid0|->kinf0, .., tidn |-> kinfn}, {},Ctor, unit -> x <t_args> pure -u == x<t_args> [ t_arg0/tid0 .. t_argn/tidn] -E_d,widening |- u ~< t:t',S_N ------------------------------------------------------------ :: unaryCtor -<E_t,E_d>,t,widening |- id : x gives id, <S_N,pure>,{} - -E_t(id) gives {}, {},tag,u -E_d,widening,t |- id : u gives t', exp, S_N, effect ------------------------------------------------------------- :: localVar -<E_t,E_d>,t,widening |- id : u gives id, <S_N,effect>,{} - -E_t(id) gives {tid1|->kinf1, .., tidn |-> kinfn}, S_N,tag,u' -u == u'[t_arg1/tid1 .. t_argn/tidn] -E_d,widening,t |- id : u gives t', exp, S_N', effect ------------------------------------------------------------- :: otherVar -<E_t,E_d>,t,widening |- id : u gives id,<S_N u+ S_N' ,effect>,{} - -E_t(id) gives {tid0|->kinf0, .., tidn |-> kinfn}, {},Ctor, t'' -> x <t_args> pure -t' -> u pure == t'' -> x<t_args> pure [ t_arg0/tid0 .. t_argn/tidn] -E_d,widening |- u ~< t:t',S_N -<E_t,E_d>,t,widening |- exp : u' gives exp, <S_N',effect>,E_t' ------------------------------------------------------------- :: ctor -<E_t,E_d>,t,widening |- :E_app: id(exp) : t gives :E_app: id(exp'), <S_N u+ S_N, effect>,{} - -E_t(id) gives {tid0 |-> kinf0, .., tidn |-> kinfn}, S_N, tag, u -u [t_arg0/tid0 .. t_argn/tidn] == ui -> uj effect -ui == ( implicit<ne>, t0 , .. , tm ) -<E_t,E_d>,(t0,..,tm),widening |- (exp0,..,expm) : ui' gives (exp0',..,expm'),I,E_t' -E_d,widening,t |- :E_app: id (annot, exp'0, .., exp'm) : uj gives uj', exp'',S_N',effect' ------------------------------------------------------------- :: appImplicit -<E_t,E_d>,t,widening |- :E_app: id(exp0,..,expm) : uj gives exp'', I u+ <S_N,effect>u+ <S_N',effect'>, E_t - - -E_t(id) gives {tid0 |-> kinf0, .., tidn |-> kinfn}, S_N, tag, u -u [t_arg0/tid0 .. t_argn/tidn] == ui -> uj effect -<E_t,E_d>,ui,widening |- exp : ui' gives exp',I,E_t' -E_d,widening,t |- :E_app: id (exp') : uj gives uj', exp'',S_N',effect' ------------------------------------------------------------- :: app -<E_t,E_d>,t,widening |- :E_app: id(exp) : uj gives exp'', I u+ <S_N,effect>u+ <S_N',effect'>, E_t - -E_t(id) gives overload {tid0 |-> kinf0, .., tidn |-> kinfn}, S_N, tag, u : tinf1 ... tinfn -u [t_arg0/tid0 .. t_argn/tidn] == ui -> uj effect -<E_t,E_d>,ui,widening |- exp : ui' gives exp',I,E_t' -E_d |- select (full( ui', t)) of tinf1 ... tinfn gives tinf -<({id |-> tinf} u+ E_t), E_d>, t,widening |- :E_app: id (exp) : t' gives exp'',I', E_t'' ------------------------------------------------------------- :: appOverload -<E_t,E_d>,t,widening |- :E_app: id(exp) : uj gives exp'', I u+ I' u+ <S_N,effect>u+ <S_N',effect'>, E_t - -E_t(id) gives {tid0 |-> kinf0, .. ,tidn |-> kinfn}, S_N, tag, u -u [t_arg0/tid0 .. t_argn/tidn] == ui -> uj effect -<E_t,E_d>,ui,widening |- (exp1,exp2) : ui' gives (exp1', exp2'), I,E_t' -E_d,widening,t |- :E_app_infix: exp1' id exp2' : uj gives uj', exp, S_N', effect' ------------------------------------------------------------- :: infix_app -<E_t,E_d>,t,widening |- :E_app_infix: exp1 id exp2 : t gives exp, I u+ <S_N, effect> u+ <S_N',effect'>, E_t - -E_t(id) gives overload {tid0 |-> kinf0, .., tidn |-> kinfn}, S_N, tag, u : tinf1 ... tinfn -u [t_arg0/tid0 .. t_argn/tidn] == ui -> uj effect -<E_t,E_d>,ui,widening |- (exp1,exp2) : ui' gives (exp1', exp2'), I,E_t' -E_d |- select (full( ui', t)) of tinf1 ... tinfn gives tinf -<({id |-> tinf} u+ E_t), E_d>, t, widening |- :E_app_infix: exp1 id exp2 : t' gives exp, I',E_t'' ------------------------------------------------------------- :: infix_appOverload -<E_t,E_d>,t,widening |- :E_app_infix: exp1 id exp2 : t gives exp, I u+ I u+ <S_N, effect> u+ <S_N',effect'>, E_t - - -E_r(</idi//i/>) gives x<t_args>, </ti//i/> -</ <E_t,<E_k,E_a,E_r,E_e>>,ti,widening |- expi : ui gives exp'i,<S_Ni,effecti>,E_t//i/> -</<E_k,E_a,E_r,E_e>,widening |- ui ~< ti: t'i,S_N'i//i/> -S_N == u+ </S_Ni//i/> -S_N' == u+ </S_N'i//i/> ------------------------------------------------------------- :: record -<E_t,<E_k,E_a,E_r,E_e>>,t,widening |- { </idi = expi//i/> semi_opt} : x<t_args> gives{ </idi=exp'i//i/> semi_opt}, u+ <S_N u+ S_N', u+ </effecti//i/>>, {} - -<E_t,<E_k,E_a,E_r,E_e>>,t,widening |- exp : x<t_args> gives exp', I,E_t -E_r(x<t_args>) gives </ id'n:t'n//n/> -</ <E_t,<E_k,E_a,E_r,E_e>>,ti,widening |- expi : ui gives expi',Ii,E_t//i/> -</idi:ti//i/> SUBSET </id'n : t'n//n/> -</<E_k,E_a,E_r,E_e>,widening |- ui ~< ti: t''i,S_N'i//i/> ------------------------------------------------------------- :: recup -<E_t,<E_k,E_a,E_r,E_e>> ,t,widening |- { exp with </idi = expi//i/> semi_opt } : x<t_args> gives {exp' with </idi = exp'i//i/>}, I u+ </Ii//i/>, E_t - -<E_t,E_d>,t,(nums,none) |- exp1 : u1 gives exp'1,I1,E_t' ... <E_t,E_d>,t,(nums,none) |- expn : un gives exp'n,In,E_t' -E_d,(nums,none) |- u1 ~< t: t', S_N1 ... E_d,(nums,none) |- un ~< t: t', S_Nn -length(exp1 ... expn) == ne -S_N == {ne=ne2} u+ S_N1 u+ ... u+ S_Nn ------------------------------------------------------------- :: vector -E, vector<ne1 ne2 order t>, widening |- [ exp1 , ... , expn ] : vector<ne1 num order t> gives [exp'1,...,exp'n], <S_N,pure> u+ I1 u+ ... u+ In , E_t - -E, vector<ne ne' order t>,(nums,none) |- exp1 : vector<ne1 ne1' inc u> gives exp'1,I1,E_t -E, range<ne2 ne2'>,(none,vectors) |- exp2 : range<ne3 ne3'> gives exp'2, I2,E_t -------------------------------------------------------------- :: vectorgetInc -E, t,widening |- :E_vector_access: exp1 [ exp2 ] : u gives exp'1 [ exp'2], I1 u+ I2 u+ <{ne1<=ne3,ne3+ne3'<=ne1+ne1'},pure>,E_t - -E, vector<ne ne' order t>,(nums,none) |- exp1 : vector<ne1 ne1' dec u> gives exp'1,I1,E_t -E, range<ne2 ne2'>,(none,vectors) |- exp2 : range<ne3 ne3'> gives exp'2, I2,E_t -------------------------------------------------------------- :: vectorgetDec -E, t,widening |- :E_vector_access: exp1 [ exp2 ] : u gives exp'1 [ exp'2], I1 u+ I2 u+ <{ne1>=ne3,ne3+(-ne3')<=ne1+(-ne1')},pure>,E_t - -E, vector<ne1 ne'1 inc t>,(nums,none) |- exp1 : vector<ne2 ne'2 inc u> gives exp'1, I1,E_t -E, range<ne3 ne3'>,(none,vectors) |- exp2 : range< ne4 ne'4> gives exp'2, I2,E_t -E,range <ne5 ne5'>,(none,vectors) |- exp3 : range< ne6 ne'6> gives exp'3, I3,E_t -------------------------------------------------------------- :: vectorsubInc -E, vector<ne ne' inc t>,widening |- :E_vector_subrange: exp1[ exp2 .. exp3 ] : vector<ne7 ne'7 inc u> gives exp'1[exp'2:exp'3], I1 u+ I2 u+ I3 u+ <{ne >= ne4, ne <= ne'4,ne'<=ne4+ne'6,ne4 <= ne2, ne4+ne6' <= ne'2},pure>,E_t - -E, vector<ne1 ne'1 dec t>,(nums,none) |- exp1 : vector< ne2 ne'2 dec u> gives exp'1, I1,E_t -E, range<ne3 ne3'>,(none,vectors) |- exp2 : range< ne4 ne'4> gives exp'2, I2,E_t -E,range <ne5 ne5'>,(none,vectors) |- exp3 : range< ne6 ne'6> gives exp'3, I3,E_t -------------------------------------------------------------- :: vectorsubDec -E, vector<ne ne' dec t>,widening |- :E_vector_subrange: exp1[ exp2 .. exp3 ] : vector<ne7 ne'7 dec u> gives exp'1[exp'2:exp'3], I1 u+ I2 u+ I3 u+ <{ne <= ne4, ne >= ne'4,ne'<=ne'6+(-ne4),ne4' >= ne2, ne'6+(-ne4) <= ne'2},pure>,E_t - -E, vector<ne ne' inc t>,(nums,none) |- exp : vector< ne1 ne2 inc u> gives exp',I,E_t -E, range<ne'1 ne'2>,(none,vectors) |- exp1 : range<ne3 ne4> gives exp'1,I1,E_t -E,t,(nums,vectors) |- exp2 : u gives exp'2,I2,E_t ------------------------------------------------------------- :: vectorupInc -E, vector<ne ne' inc t>,widening |- [ exp with exp1 = exp2 ] : vector< ne1 ne2 inc u> gives [exp' with exp'1 = exp'2], I u+ I1 u+ I2 u+ <{ne1 <= ne3, ne2 >= ne4},pure>,E_t - -E, vector<ne ne' dec t>,(nums,none) |- exp : vector <ne1 ne2 dec u> gives exp',I,E_t -E, range<ne'1 ne'2>,(none,vectors) |- exp1 : range<ne3 ne4> gives exp'1,I1,E_t -E,t,(nums,vectors) |- exp2 : u gives exp'2,I2,E_t ------------------------------------------------------------- :: vectorupDec -E, vector<ne ne' dec t>,widening |- [ exp with exp1 = exp2 ] : vector< ne1 ne2 dec u> gives [exp' with exp'1 = exp'2], I u+ I1 u+ I2 u+ <{ne1 >= ne3, ne2 >= ne4},pure>,E_t - -E,vector<ne1 ne2 order t>,(nums,none) |- exp : vector< ne3 ne4 inc u> gives exp',I,E_t -E,atom<ne5>,(none,vectors) |- exp1 : atom<ne6> gives exp1',I1,E_t -E,atom<ne7>,(none,vectors) |- exp2 : atom<ne8> gives exp2', I2,E_t -E,vector<ne9 ne10 inc t>,(nums,vectors) |- exp3 : vector <ne11 ne12 inc u> gives exp3',I3,E_t -I4 == <{ ne3 <= ne5, ne3+ne4 <= ne7, ne12 = ne8 + (-ne6) , ne6 + one <= ne8},pure> ------------------------------------------------------------- :: vecrangeupInc -E,vector<ne1 ne2 order t>,widening |- :E_vector_update_subrange: [ exp with exp1 : exp2 = exp3 ] : vector <ne3 ne4 inc u> gives :E_vector_update_subrange:[ exp' with exp1' : exp2' = exp3'], (I u+ (I1 u+ (I2 u+ (I3 u+ I4)))),E_t - -E,vector<ne1 ne2 order t>,(nums,none) |- exp : vector< ne3 ne4 inc u> gives exp',I,E_t -E,atom<ne5>,(none,vectors) |- exp1 : atom<ne6> gives exp1',I1,E_t -E,atom<ne7>,(none,vectors) |- exp2 : atom<ne8> gives exp2', I2,E_t -E,u,(nums,vectors) |- exp3 : u' gives exp3',I3,E_t -I4 == <{ ne3 <= ne5, ne3+ne4 <= ne7 },pure> ------------------------------------------------------------- :: vecrangeupvalueInc -E,vector<ne1 ne2 order t>,widening |- :E_vector_update_subrange: [ exp with exp1 : exp2 = exp3 ] : vector <ne3 ne4 inc u> gives :E_vector_update_subrange:[ exp' with exp1' : exp2' = exp3'], (I u+ (I1 u+ (I2 u+ (I3 u+ I4)))),E_t - -E,vector<ne1 ne2 order t>,(nums,none) |- exp : vector< ne3 ne4 dec u> gives exp',I,E_t -E,atom<ne5>,(none,vectors) |- exp1 : atom<ne6> gives exp1',I1,E_t -E,atom<ne7>,(none,vectors) |- exp2 : atom<ne8> gives exp2', I2,E_t -E,vector<ne9 ne10 dec t>,(nums,vectors) |- exp3 : vector <ne11 ne12 dec u> gives exp3',I3,E_t -I4 == <{ ne5 <= ne3, ne3+(-ne4) <= ne6+(-ne8), ne8+one<=ne6 },pure> ------------------------------------------------------------- :: vecrangeupDec -E,vector<ne1 ne2 order t>,widening |- :E_vector_update_subrange: [ exp with exp1 : exp2 = exp3 ] : vector <ne3 ne4 dec u> gives :E_vector_update_subrange:[ exp' with exp1' : exp2' = exp3'], (I u+ (I1 u+ (I2 u+ (I3 u+ I4)))),E_t - -E,vector<ne1 ne2 order t>,(nums,none) |- exp : vector< ne3 ne4 dec u> gives exp',I,E_t -E,atom<ne5>,(none,vectors) |- exp1 : atom<ne6> gives exp1',I1,E_t -E,atom<ne7>,(none,vectors) |- exp2 : atom<ne8> gives exp2', I2,E_t -E,u,(nums,vectors) |- exp3 : u' gives exp3',I3,E_t -I4 == <{ ne5 <= ne3, ne3+(-ne4) <= ne6+(-ne8), ne8+one<=ne6 },pure> ------------------------------------------------------------- :: vecrangeupvalueDec -E,vector<ne1 ne2 order t>,widening |- :E_vector_update_subrange: [ exp with exp1 : exp2 = exp3 ] : vector <ne3 ne4 dec u> gives :E_vector_update_subrange:[ exp' with exp1' : exp2' = exp3'], (I u+ (I1 u+ (I2 u+ (I3 u+ I4)))),E_t - -E_r (x<t_args>) gives </idi : ti//i/> id : u </id'j : t'j//j/> -<E_t,<E_k,E_a,E_r,E_e>>,t'',widening |- exp : x< t_args> gives exp', I,E_t -E_d,widening,t |- exp'.id : u gives t', exp1', S_N', effect ------------------------------------------------------------- :: field -<E_t,<E_k,E_a,E_r,E_e>>,t,widening |- exp.id : u gives exp1',I u+ <S_N',effect>,E_t - -<E_t,E_d>,t'',widening |- exp : u gives exp',I,E_t -</<E_t,E_d>,u |- pati : u'i gives pat'i,E_ti,S_Ni//i/> -</<(E_t u+ E_ti),E_d>,t,widening |- expi : u''i gives exp'i,Ii,E_t'i//i/> ------------------------------------------------------------- :: case -<E_t,E_d>,t,widening |- switch exp { </case pati -> expi//i/> }: u gives switch exp' { </case pat'i -> exp'i//i/> }, I u+ </Ii u+ <S_Ni,pure>//i/>, E_t - -<E_t,E_d>,t'',widening |- exp : u gives exp',I,E_t -E_d |- typ ~> t' -E_d,widening,t' |- exp' : u gives u', exp'', S_N,effect -E_d,widening,t |- exp'' : t' gives u'', exp''', S_N', effect' ------------------------------------------------------------- :: typed -<E_t,E_d>,t,widening |- (typ) exp : t gives exp''',I u+ <S_N u+ S_N',effect u+ effect'>,E_t - -<E_t,E_d> |- letbind gives letbind', E_t1, S_N, effect, {} -<(E_t u+ E_t1),E_d>,t,widening |- exp : u gives exp', I2, E_t2 ------------------------------------------------------------- :: let -<E_t,E_d>,t,widening |- letbind in exp : t gives letbind' in exp', <S_N,effect> u+ I2, E_t - -E,t1,widening |- exp1 : u1 gives exp1',I1,E_t1 .... E,tn,widening |- expn : un gives expn',In,E_tn ------------------------------------------------------------- :: tup -E,(t1, ...., tn),widening |- (exp1, .... , expn) : (u1 , .... , un) gives (exp1', ...., expn'), I1 u+ .... u+ In,E_t - -<E_t,E_d>,t,(nums,none) |- exp1 : u1 gives exp1', I1,E_t1 .. <E_t,E_d>,t,(nums,none) |- expn : un gives expn', In,E_tn -E_d,(nums,none) |- u1 ~< t:t',S_N1 .. E_d,(nums,none) |- un ~< t:t',S_Nn ------------------------------------------------------------- :: list -<E_t,E_d>,list<t>,widening |- [||exp1, .., expn ||] : list<u> gives [|| exp1', .., expn' ||], <S_N1 u+ .. u+ S_Nn,pure> u+ I1 u+ .. u+ In, E_t - -E,bit,widening |- exp1 : bit gives exp1',I1,E_t' -E,t,widening |- exp2 : u1 gives exp2',I2,E_t2 -E,t,widening |- exp3 : u2 gives exp3',I3,E_t3 -E_d,widening |- u1 ~< t:t',S_N1 -E_d,widening |- u2 ~< t:t',S_N2 ------------------------------------------------------------- :: if -<E_t,E_d>,t,widening |- if exp1 then exp2 else exp3 : u gives if exp1' then exp2' else exp3', <S_N1 u+ S_N2,pure> u+ I1 u+ I2 u+ I3,(E_t2 inter E_t3) - -<E_t,E_d>,range<ne1 ne2>,widening |- exp1 : range< ne7 ne8> gives exp1', I1,E_t -<E_t,E_d>,range<ne3 ne4>,widening |- exp2 : range< ne9 ne10> gives exp2', I2,E_t -<E_t,E_d>,range<ne5 ne6>,widening |- exp3 : range< ne11 ne12> gives exp3',I3,E_t -<(E_t u+ {id |-> range< ne1 ne4>}),E_d>,unit,widening |- exp4 : t gives exp4',I4,E_t' ------------------------------------------------------------ :: for -<E_t,E_d>,unit,widening |- foreach (id from exp1 to exp2 by exp3) exp4 : t gives foreach (id from exp1' to exp2' by exp3') exp4', I1 u+ I2 u+ I3 u+ I4 u+ <{ne1 <= ne3+ne4},pure>,E_t - -E,t,widening |- exp1 : u gives exp1',I1,E_t -E,list<t>,widening |- exp2 : list<u> gives exp2',I2,E_t ------------------------------------------------------------- :: cons -E,list<t>,widening |- exp1 :: exp2 : list<u> gives exp1'::exp2', I1 u+ I2,E_t - -widening,t |- lit : u => exp,S_N ------------------------------------------------------------- :: lit -E,t,widening |- lit : u gives exp,<S_N,pure>,E_t - -<E_t,E_d>,unit,widening |- exp : unit gives exp', I, E_t1 ------------------------------------------------------------- :: blockbase -<E_t,E_d>,unit,widening |- { exp } : unit gives {exp'}, I, E_t - -<E_t,E_d>,unit,widening |- exp : unit gives exp', I1, E_t1 -<(E_t u+ E_t1),E_d>,unit,widening |- { </expi//i/> } : unit gives {</expi'//i/>}, I2, E_t2 ------------------------------------------------------------- :: blockrec -<E_t,E_d>,unit,widening |- { exp ; </expi//i/> } : unit gives {exp'; </expi'//i/>}, I1 u+ I2, E_t - -<E_t,E_d>,unit,widening |- exp : unit gives exp', I, E_t1 ------------------------------------------------------------- :: nondetbase -<E_t,E_d>,unit,widening |- nondet { exp } : unit gives {exp'}, I, E_t - -<E_t,E_d>,unit,widening |- exp : unit gives exp', I1, E_t1 -<(E_t u+ E_t1),E_d>,unit,widening |- nondet { </expi//i/> } : unit gives {</expi'//i/>}, I2, E_t2 ------------------------------------------------------------- :: nondetrec -<E_t,E_d>,unit,widening |- nondet { exp ; </expi//i/> } : unit gives {exp'; </expi'//i/>}, I1 u+ I2, E_t - -E,t,widening |- exp:u gives exp', I1, E_t1 -E,widening |- lexp:t gives lexp', I2, E_t2 ------------------------------------------------------------- :: assign -E,unit,widening |- lexp := exp : unit gives lexp' := exp', I u+ I2, E_t2 - -defn -E , widening |- lexp : t gives lexp' , I , E_t :: :: check_lexp :: check_lexp_ -{{ com Check the left hand side of an assignment }} -by +G |- exp1 => n_constraint +%G , flows , constrs |- exp2 => typ +%G , flows , negate constrs |- exp3 <= typ +-------------------------------------------- :: if +G |- if exp1 then exp2 else exp3 => typ -E_t(id) gives register<t> ----------------------------------------------------------- :: wreg -<E_t,E_d>,widening |- id : t gives id,<{},{ wreg }>, E_t - -E_t(id) gives reg<t> ----------------------------------------------------------- :: wlocl -<E_t,E_d>,widening |- id : t gives id,Ie, E_t - -E_t(id) gives t ----------------------------------------------------------- :: var -<E_t,E_d>,widening |- id : t gives id,Ie,E_t - -id NOTIN dom(E_t) ----------------------------------------------------------- :: wnew -<E_t,E_d>,widening |- id : t gives id,Ie, {id |-> reg<t>} - -E_t(id) gives register<t> -E_d |- typ ~> u -E_d,widening |- u ~< t : u, S_N ----------------------------------------------------------- :: wregCast -<E_t,E_d>,widening |- (typ) id : t gives id,<S_N,{ wreg }>, E_t - -E_t(id) gives reg<t> -E_d |- typ ~> u -E_d,widening |- u ~< t : u, S_N ----------------------------------------------------------- :: wloclCast -<E_t,E_d>,widening |- (typ) id : t gives id,<S_N,pure>, E_t - -E_t(id) gives t -E_d |- typ ~> u -E_d,widening |- u ~< t : u, S_N ----------------------------------------------------------- :: varCast -<E_t,E_d>,widening |- (typ) id : t gives id,<S_N,pure>,E_t - -id NOTIN dom(E_t) -E_d |- typ ~> t ----------------------------------------------------------- :: wnewCast -<E_t,E_d>, widening |- (typ) id : t gives id,Ie, {id |-> reg<t>} - - -E_t(id) gives E_k, S_N, Extern, (t1, .. ,tn, t) -> t' {</base_effecti//i/>, wmem, </base_effect'j//j/>} -<E_t,E_d>,(t1, .. , tn),widening |- exp : u1 gives exp',I,E_t1 ----------------------------------------------------------- :: wmem -<E_t,E_d>,widening |- :LEXP_memory: id(exp) : t gives :LEXP_memory: id(exp'),I u+ <S_N,{wmem}>,E_t - -E_t(id) gives E_k, S_N, Extern, (t1, ..,tn,t) -> t' {</base_effecti//i/>, wreg, </base_effect'j//j/>} -<E_t,E_d>,(t1,..,tn),widening |- exp : u1 gives exp',I,E_t1 ----------------------------------------------------------- :: wregCall -<E_t,E_d>,widening |- :LEXP_memory: id(exp) : t gives :LEXP_memory: id(exp'),I u+ <S_N,{wreg}>,E_t - -E,atom<ne>,(nums,none) |- exp : u gives exp',I1,E_t -E,(none,vectors) |- lexp : vector<ne1 ne2 inc t> gives lexp',I2,E_t ----------------------------------------------------------- :: wbitInc -E,widening |- lexp [exp] : t gives lexp'[exp'], I1 u+ I2 u+ <{ne1 <= ne, ne1 + ne2 >= ne},pure>,E_t - -E,atom<ne>,(nums,none) |- exp : u gives exp',I1,E_t -E,(none,vectors) |- lexp : vector<ne1 ne2 dec t> gives lexp',I2,E_t ----------------------------------------------------------- :: wbitDec -E,widening |- lexp [exp] : t gives lexp'[exp'], I1 u+ I2 u+ <{ne <= ne1, ne1 + (-ne2) <= ne},pure>,E_t - -E,atom<ne1>,(nums,none) |- exp1 : u1 gives exp1',I1,E_t -E,atom<ne2>,(nums,none) |- exp2 : u2 gives exp2',I2,E_t -E,(none,vectors) |- lexp : vector<ne3 ne4 inc t> gives lexp',I3,E_t ----------------------------------------------------------- :: wsliceInc -E,widening |- lexp [exp1 : exp2] : vector< ne1 ne2 + (-ne1) inc t> gives lexp'[exp1':exp2'],I1 u+ I2 u+ I3 u+ <{ne3<=ne1, ne3+ne4<= ne2 + (-ne1)},pure> ,E_t - -E,atom<ne1>,(nums,none) |- exp1 : u1 gives exp1',I1,E_t -E,atom<ne2>,(nums,none) |- exp2 : u2 gives exp2',I2,E_t -E,(none,vectors) |- lexp : vector<ne3 ne4 inc t> gives lexp',I3,E_t ----------------------------------------------------------- :: wsliceDec -E,widening |- lexp [exp1 : exp2] : vector< ne1 ne2 + (-ne1) inc t> gives lexp'[exp1':exp2'],I1 u+ I2 u+ I3 u+ <{ne1<=ne3, ne3 + (-ne4)<= ne1 + (-ne2)},pure> ,E_t - - -E_r (x<t_args>) gives </idi : ti//i/> id : t </id'j : t'j//j/> -<E_t,<E_k,E_a,E_r,E_e>>,widening |- lexp : x<t_args> gives lexp',I,E_t ----------------------------------------------------------- :: wrecord -<E_t,<E_k,E_a,E_r,E_e>>,widening |- lexp.id : t gives lexp'.id,I,E_t +G |- :E_app: vector_access ( exp , exp' ) => typ +------------------------------ :: vector_access +G |- exp [ exp' ] => typ -defn -E |- letbind gives letbind' , E_t , S_N , effect , E_k :: :: check_letbind :: check_letbind_ -{{ com Build the environment for a let binding, collecting index constraints }} -by -<E_k,E_a,E_r,E_e> |- typschm ~> t,E_k2,S_N -<E_t,<E_k u+ E_k2,E_a,E_r,E_e>>,t |- pat : u gives pat',E_t1, S_N1 -<E_t,<E_k u+ E_k2,E_a,E_r,E_e>>,t,(none,none) |- exp : u' gives exp', <S_N2,effect>,E_t2 -<E_k u+ E_k2,E_a,E_r,E_e>,(none,none) |- u' ~< u, S_N3 ------------------------------------------------------------- :: val_annot -<E_t,<E_k,E_a,E_r,E_e>> |- let typschm pat = exp gives let typschm pat' = exp', E_t1, S_N u+ S_N1 u+ S_N2 u+ S_N3, effect, E_k2 - -<E_t,E_d>,t |- pat : u gives pat',E_t1,S_N1 -<(E_t u+ E_t1),E_d>,u |- exp : u' gives exp',<S_N2,effect>,E_t2 ------------------------------------------------------------- :: val_noannot -<E_t,E_d> |- let pat = exp gives let pat' = exp', E_t1, S_N1 u+ S_N2, effect,{} +G |- :E_app: vector_subrange ( exp , exp1 , exp2 ) => typ +--------------------------- :: vector_subrange +G |- exp [ exp1 .. exp2 ] => typ -defns -check_defs :: '' ::= -defn -E_d |- type_def gives E :: :: check_td :: check_td_ -{{ com Check a type definition }} -by +G |- :E_app: vector_update ( exp , exp1 , exp2 ) => typ +---------------------------------- :: vector_update +G |- :E_vector_update: [ exp with exp1 = exp2] => typ -E_d |- typschm ~> t,E_k,S_N ------------------------------------------------------------ :: abbrev -E_d |- typedef id name_scm_opt = typschm gives <{},<{},{id |-> E_k, S_N, None,t},{},{}>> - -E_d |- typ1 ~> t1 .. E_d |- typn ~> tn -E_r == { {id1:t1, .., idn:tn} |-> x } ------------------------------------------------------------ :: unquant_record -E_d |- typedef x name_scm_opt = const struct { typ1 id1 ; .. ; typn idn semi_opt } gives <{},<{x |-> K_Typ},{},E_r,{}>> - -</ <E_k,E_a,E_r,E_e> |- quant_itemi ~>E_ki, S_Ni//i/> -<E_k u+ </E_ki//i/>,E_a,E_r,E_e> |- typ1 ~> t1 .. <E_k u+ </E_ki//i/>,E_a,E_r,E_e> |- typn ~> tn -{ x'1 |-> k1, .. ,x'm |-> km } == u+ </E_ki//i/> -E_r1 == { {id1:t1, .., idn:tn} |-> {x'1 |-> k1, ..,x'm |-> km}, u+</S_Ni//i/>, None, x< :t_arg_typ: x'1 .. :t_arg_typ: x'm> } -E_k1' == { x |-> K_Lam (k1 .. km -> K_Typ) } ------------------------------------------------------------ :: quant_record -<E_k,E_a,E_r,E_e> |- typedef x name_scm_opt = const struct forall </quant_itemi//i/> . { typ1 id1 ; .. ; typn idn semi_opt } gives <{},<E_k',{},E_r1,{}>> - -E_t == { id1 |-> {},{},Ctor,t1 -> x pure , ..., idn |-> {},{},Ctor, tn -> x pure } -E_k1 == { x |-> K_Typ } -<E_k u+ E_k1,E_a,E_r,E_e> |- typ1 ~> t1 ... <E_k u+ E_k1,E_a,E_r,E_e> |- typn ~> tn ------------------------------------------------------------- :: unquant_union -<E_k,E_a,E_r,E_e> |- typedef x name_scm_opt = const union { typ1 id1 ; ... ; typn idn semi_opt } gives <E_t,<E_k1,{},{},{}>> - -</ <E_k,E_a,E_r,E_e> |- quant_itemi ~> E_ki, S_Ni//i/> -{ x'1 |-> k1, ... , x'm |-> km } == u+ </E_ki//i/> -E_k' == { x |-> K_Lam (k1 ... km -> K_Typ) } u+ </E_ki//i/> -<E_k u+ E_k',E_a,E_r,E_e> |- typ1 ~> t1 ... <E_k u+ E_k',E_a,E_r,E_e> |- typn ~> tn -t == x < :t_arg_typ: x'1 ... :t_arg_typ: x'm> -E_t == { id1 |-> E_k', u+</S_Ni//i/>, Ctor, t1 -> t pure, ... , idn |-> E_k', u+</S_Ni//i/>, Ctor, tn -> t pure } ------------------------------------------------------------- :: quant_union -<E_k,E_a,E_r,E_e> |- typedef id name_scm_opt = const union forall </quant_itemi//i/> . { typ1 id1 ; ... ; typn idn semi_opt } gives <E_t,<E_k',{},{},{}>> - -% Save these as enumerations for coercion -E_t == {id1 |-> x, ..., idn |-> x} -E_e == { x |-> { num1 |-> id1 ... numn |-> idn} } -------------------------------------------------------------- :: enumerate -E_d |- typedef x name_scm_opt = enumerate { id1 ; ... ; idn semi_opt } gives <E_t,<{id |-> K_Typ},{},{},E_e>> -defn -E |- fundef gives fundef' , E_t , S_N :: :: check_fd :: check_fd_ -{{ com Check a function definition }} -by +G |- :E_app: vector_update_subrange ( exp , exp1 , exp2 , exp3 ) => typ +------------------------------------------ :: vector_update_subrange +G |- :E_vector_update_subrange: [ exp with exp1 : exp2 = exp3 ] => typ -E_t(id) gives E_k',S_N',Global, t1 -> t effect -</E_d |- quant_itemi ~> E_ki,S_Ni//i/> -S_N'' == u+ </S_Ni//i/> -E_k' == </E_ki//i/> -E_d1 == <E_k',{},{},{}> u+ E_d -E_d1 |- typ ~> u -E_d1 |- u ~< t, S_N2 -</<E_t,E_d1>,t1 |- patj : uj gives patj',E_tj,S_N'''j//j/> -</<(E_t u+ E_tj),E_d1>,u |- expj : u' gives expj',<S_N''''j,effect'j>,E_t'j//j/> -S_N''''' == S_N2 u+ </S_N'''j u+ S_N''''j//j/> -effect == u+ </effect'j//j/> -S_N == resolve ( S_N' u+ S_N'' u+ S_N''''') -------------------------------------------------------------- :: rec_function -<E_t,E_d> |- function rec forall </quant_itemi//i/> . typ effectkw effect </id patj = expj//j/> gives function rec forall </quant_itemi//i/>. typ effectkw effect </id patj' = expj'//j/>,E_t, S_N - -E_t(id) gives E_k', S_N', Global, t1 -> t effect -E_d |- typ ~> u -E_d |- u ~< t, S_N2 -</<E_t,E_d>,t1 |- patj : uj gives pat',E_tj,S_N''j//j/> -</<(E_t u+ E_tj),E_d>,u |- expj : uj' gives expj',<S_N'''j,effect'j>,E_t'j//j/> -effect == u+ </effect'j//j/> -S_N == resolve (S_N2 u+ S_N' u+ </S_N''j u+ S_N'''j//j/>) -------------------------------------------------------------- :: rec_function2 -<E_t,E_d> |- function rec typ effectkw effect </id patj = expj//j/> gives function rec typ effectkw effect </id patj'=expj'//j/>,E_t, S_N - -</<E_k,E_a,E_r,E_e> |- quant_itemi ~> E_ki,S_Ni//i/> -S_N' == u+ </S_Ni//i/> -E_k' == E_k u+ </E_ki//i/> -<E_k',E_a,E_r,E_e> |- typ ~> t -</<E_t,<E_k',E_a,E_r,E_e>>, t1 |- patj : uj gives patj', E_tj,S_N''j//j/> -E_t' == (E_t u+ {id |-> E_k', S_N', Global, t1 -> t effect}) -</<(E_t' u+ E_tj),<E_k',E_a,E_r,E_e>>,t |- expj : u'j gives expj', <S_N'''j,effect'j>,E_t'j//j/> -effect == u+ </effect'j//j/> -S_N == resolve (S_N' u+ </S_N''j u+ S_N'''j//j/>) -------------------------------------------------------------- :: rec_function_no_spec -<E_t,<E_k,E_a,E_r,E_e>> |- function rec forall </quant_itemi//i/> . typ effectkw effect </id patj = expj//j/> gives function rec forall </quant_itemi//i/> . typ effectkw effect </id patj' = expj'//j/>, E_t', S_N - -E_d |- typ ~> t -</<E_t,E_d>, t1 |- patj : uj gives patj', E_tj,S_N'j//j/> -E_t' == (E_t u+ {id |-> {}, {}, Global, t1 -> t effect}) -</<(E_t' u+ E_tj),E_d>,t |- expj : uj' gives expj', <S_N'j,effect'j>,E_t'j//j/> -effect == u+ </effect'j//j/> -S_N == resolve (u+ </S_N'j u+ S_N''j//j/>) -------------------------------------------------------------- :: rec_function_no_spec2 -<E_t,E_d> |- function rec typ effectkw effect </id patj = expj//j/> gives function rec typ effectkw effect </id patj' = expj'//j/>, E_t', S_N - -E_t(id) gives E_k',S_N',Global, t1 -> t effect -</<E_k,E_a,E_r,E_e> |- quant_itemi ~> E_ki,S_Ni//i/> -S_N'' == u+ </S_Ni//i/> -E_k'' == </E_ki//i/> -<E_k'' u+ E_k,E_a,E_r,E_e> |- typ ~> u -<E_k'' u+ E_k, E_a,E_r,E_e> |- u ~< t, S_N2 -</<E_t,<E_k u+ E_k'',E_a,E_r,E_e>>, t1 |- patj : uj gives patj', E_tj,S_N''j//j/> -</<(E_t u- id u+ E_tj),<E_k u+ E_k'',E_a,E_r,E_e>>,t |- expj : uj' gives expj', <S_N'''j,effect'j>,E_t'j//j/> -S_N'''' == u+ </S_N''j u+ S_N'''j//j/> -effect == u+ </effect'j//j/> -S_N == resolve ( S_N' u+ S_N'' u+ S_N'''') -------------------------------------------------------------- :: function -<E_t,<E_k,E_a,E_r,E_e>> |- function forall </quant_itemi//i/> . typ effectkw effect </id patj = expj//j/> gives function forall </quant_itemi//i/> . typ effectkw effect </id patj' = expj'//j/>, E_t, S_N - -E_t(id) gives {}, S_N1, Global, t1 -> t effect -E_d |- typ ~> u -E_d |- u ~< t, S_N2 -</<E_t,E_d>,t1 |- patj : uj gives patj,E_tj,S_N'j//j/> -</<(E_t u- id u+ E_tj),E_d>, u |- expj : uj' gives expj', <S_N''j,effect'j>,E_t'j//j/> -effect == u+ </effect'j//j/> -S_N == resolve (S_N1 u+ S_N2 u+ </S_N'j u+ S_N''j//j/>) -------------------------------------------------------------- :: function2 -<E_t,E_d> |- function typ effectkw effect </id patj = expj//j/> gives function typ effectkw effect </id patj' = expj'//j/>, E_t, S_N - -</<E_k,E_a,E_r,E_e> |- quant_itemi ~> E_ki,S_Ni//i/> -S_N' == u+ </S_Ni//i/> -E_k'' == E_k u+ </E_ki//i/> -<E_k'',E_a,E_r,E_e> |- typ ~> t -</<E_t,<E_k'',E_a,E_r,E_e>>,t1 |- patj : uj gives patj,E_tj,S_N''j//j/> -E_t' == (E_t u+ {id |-> E_k'', S_N', Global, t1 -> t effect}) -</<(E_t u+ E_tj),<E_k'',E_a,E_r,E_e>>,t |- expj : uj' gives expj', <S_N''j,effect'j>,E_t'j//j/> -effect == u+ </effect'j//j/> -S_N == resolve (S_N' u+ </S_N'j u+ S_N''j//j/>) -------------------------------------------------------------- :: function_no_spec -<E_t,<E_k,E_a,E_r,E_e>> |- function forall </quant_itemi//i/> . typ effectkw effect </id patj = expj//j/> gives function forall </quant_itemi//i/>. typ effectkw effect </id patj' = expj'//j/>, E_t', S_N - -E_d |- typ ~> t -</<E_t,E_d>,t1 |- patj : uj gives patj', E_tj,S_N'j//j/> -E_t' == (E_t u+ {id |-> {},S_N, Global, t1 -> t effect}) -</<(E_t u+ E_tj),E_d>,t |- expj : uj' gives exp', <S_N'j,effect'j>,E_t'j//j/> -effect == u+ </effect'j//j/> -S_N == resolve (u+ </S_N'j u+ S_N''j//j/>) -------------------------------------------------------------- :: function_no_spec2 -<E_t,E_d> |- function typ effectkw effect </id patj = expj//j/> gives function typ effectkw effect </id patj' = expj'//j/>, E_t', S_N +G |- :E_app: vector_append ( exp1 , exp2 ) => typ +----------------------------------- :: vector_append +G |- exp1 : exp2 => typ -defn -E |- val_spec gives E_t :: :: check_spec :: check_spec_ -{{ com Check a value specification }} -by -E_d |- typschm ~> t, E_k1, S_N --------------------------------------------------------- :: val_spec -<E_t,E_d> |- val typschm id gives {id |-> E_k1,S_N,Global,t } +order_inc +G |- exp => typ +G |- exp1 <= typ .. G |- expn <= typ +nexp = length [|| exp , exp1 , .. , expn ||] +-------------------------------------------- :: vector_inc +G |- [|| exp , exp1 , .. , expn ||] => typ [ numZero <: nexp ] -E_d |- typschm ~> t, E_k1, S_N --------------------------------------------------------- :: extern -<E_t,E_d> |- val extern typschm id = string gives {id |-> E_k1,S_N,Extern,t} +order_dec +G |- exp => typ +G |- exp1 <= typ .. G |- expn <= typ +nexp = length [|| exp , exp1 , .. , expn ||] +-------------------------------------------- :: vector_dec +G |- [|| exp , exp1 , .. , expn ||] => typ [ nexp :> numZero ] -defn -E_d |- default_spec gives E_t , E_k1 :: :: check_default :: check_default_ -{{ com Check a default typing specification }} -by -E_k |- base_kind ~> k ------------------------------------------------------------- :: kind -<E_k,E_a,E_r,E_e> |- default base_kind 'x gives {}, {'x |-> k default } +G |- exp1 <= bool +G |- exp2 <= string +----------------------------------- :: assert +G |- assert (exp1, exp2 ) => unit -E_d |- typschm ~> t,E_k1,S_N ------------------------------------------------------------- :: typ -E_d |- default typschm id gives {id |-> E_k1,S_N,Default,t},{} defn - -E |- def gives def' , E' :: :: check_def :: check_def_ -{{ com Check a definition }} + G |- exp <= typ :: :: check_exp :: check_exp_ +{{ com Check that type of $[[exp]]$ is $[[typ]]$ }} +{{ tex [[G]] \vdash [[exp]] \Leftarrow [[typ]] }} by -E_d |- type_def gives E ---------------------------------------------------------- :: tdef -<E_t,E_d>|- type_def gives type_def, <E_t,E_d> u+ E -E |- fundef gives fundef', E_t,S_N ---------------------------------------------------------- :: fdef -E |- fundef gives fundef', E u+ <E_t,empty> +G |- exp1 <= unit ... G |- expn <= unit +G |- exp <= typ +----------------------------------- :: block +G |- { exp1; ... ; expn ; exp } <= typ -E |- letbind gives letbind', {id1 |-> t1 , .. , idn |-> tn},S_N,pure,E_k -S_N1 == resolve(S_N) ---------------------------------------------------------- :: vdef -E |- letbind gives letbind', E u+ <{id1 |-> E_k,S_N,None,t1 , .. , idn |-> E_k,S_N,None,tn},empty> -E |- val_spec gives E_t ---------------------------------------------------------- :: vspec -E |- val_spec gives val_spec, E u+ <E_t,empty> -E_d |- default_spec gives E_t1, E_k1 ---------------------------------------------------------- :: default -<E_t,E_d> |- default_spec gives default_spec, <(E_t u+ E_t1),E_d u+ <E_k1,{},{},{}>> - -E_d |- typ ~> t ----------------------------------------------------------- :: register -<E_t,E_d> |- register typ id gives register typ id, <(E_t u+ {id |-> register<t>}),E_d> - -%TODO Add alias checking - -defn -E |- defs gives defs' , E' :: :: check_defs :: check_defs_ -{{ com Check definitions, potentially given default environment of built-in library }} -by - -:check_def: E |- def gives def', E1 -E u+ E1 |- </defi// i/> gives </defi'//i/>, E2 ------------------------------------------------------------- :: defs -E |- def </defi// i/> gives def' </defi'//i/>, E2 + diff --git a/language/sil.ott b/language/sil.ott new file mode 100644 index 00000000..40adfc4d --- /dev/null +++ b/language/sil.ott @@ -0,0 +1,451 @@ +%%% Sail Intermediate Language %%% + +% An attempt to precisely document the subset of sail that the +% rewriter is capable of re-writing sail into. It is intended to be a +% strict subset of the Sail AST, and be typecheckable with the full +% typechecker. +% +% Notably, it lacks: +% - Special (bit)vector syntax. +% - Complex l-values. +% - Existential types. +% - Polymorphism, of any kind. + +indexvar n , m , i , j ::= + {{ phantom }} + {{ com Index variables for meta-lists }} + +metavar num,numZero,numOne ::= + {{ phantom }} + {{ lex numeric }} + {{ ocaml int }} + {{ hol num }} + {{ lem integer }} + {{ com Numeric literals }} + +metavar nat ::= + {{ phantom }} + {{ ocaml int }} + {{ lex numeric }} + {{ lem nat }} + +metavar string ::= + {{ phantom }} + {{ ocaml string }} + {{ lem string }} + {{ hol string }} + {{ com String literals }} + +metavar real ::= + {{ phantom }} + {{ ocaml string }} + {{ lem string }} + {{ hol string }} + {{ com Real number literal }} + +embed +{{ ocaml + +type text = string + +type l = Parse_ast.l + +type 'a annot = l * 'a + +type loop = While | Until + +}} + +embed +{{ lem +open import Pervasives +open import Pervasives_extra +open import Map +open import Maybe +open import Set_extra + +type l = + | Unknown + | Int of string * maybe l (*internal types, functions*) + | Range of string * nat * nat * nat * nat + | Generated of l (*location for a generated node, where l is the location of the closest original source*) + +type annot 'a = l * 'a + +val duplicates : forall 'a. list 'a -> list 'a + +val set_from_list : forall 'a. list 'a -> set 'a + +val subst : forall 'a. list 'a -> list 'a -> bool + +type loop = While | Until + +}} + +metavar x , y , z ::= + {{ ocaml text }} + {{ lem string }} + {{ hol string }} + {{ com identifier }} + {{ ocamlvar "[[x]]" }} + {{ lemvar "[[x]]" }} + +grammar + +l :: '' ::= {{ phantom }} + {{ ocaml Parse_ast.l }} + {{ lem l }} + {{ hol unit }} + {{ com source location }} + | :: :: Unknown + {{ ocaml Unknown }} + {{ lem Unknown }} + {{ hol () }} + + +id :: '' ::= + {{ com Identifier }} + {{ aux _ l }} + | x :: :: id + | ( deinfix x ) :: D :: deIid {{ com remove infix status }} + +base_effect :: 'BE_' ::= + {{ com effect }} + {{ aux _ l }} + | rreg :: :: rreg {{ com read register }} + | wreg :: :: wreg {{ com write register }} + | rmem :: :: rmem {{ com read memory }} + | rmemt :: :: rmemt {{ com read memory and tag }} + | wmem :: :: wmem {{ com write memory }} + | wmea :: :: eamem {{ com signal effective address for writing memory }} + | exmem :: :: exmem {{ com determine if a store-exclusive (ARM) is going to succeed }} + | wmv :: :: wmv {{ com write memory, sending only value }} + | wmvt :: :: wmvt {{ com write memory, sending only value and tag }} + | barr :: :: barr {{ com memory barrier }} + | depend :: :: depend {{ com dynamic footprint }} + | undef :: :: undef {{ com undefined-instruction exception }} + | unspec :: :: unspec {{ com unspecified values }} + | nondet :: :: nondet {{ com nondeterminism, from $[[nondet]]$ }} + | escape :: :: escape {{ com potential call of $[[exit]]$ }} + | lset :: :: lset {{ com local mutation; not user-writable }} + | lret :: :: lret {{ com local return; not user-writable }} + +effect :: 'Effect_' ::= + {{ com effect set, of kind $[[Effect]]$ }} + {{ aux _ l }} + | { base_effect1 , .. , base_effectn } :: :: set {{ com effect set }} + | pure :: M :: pure {{ com sugar for empty effect set }} + {{ lem (Effect_set []) }} {{icho [[{}]] }} + | effect1 u+ .. u+ effectn :: M :: union {{ com union of sets of effects }} {{ icho [] }} + {{ lem (List.foldr effect_union (Effect_aux (Effect_set []) Unknown) [[effect1..effectn]]) }} + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% Types % +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +typ :: 'Typ_' ::= + {{ com type expressions, of kind $[[Type]]$ }} + {{ aux _ l }} + | id :: :: id + {{ com defined type }} + | typ1 -> typ2 effectkw effect :: :: fn + {{ com Function (first-order only in user code) }} + | ( typ1 , .... , typn ) :: :: tup + {{ com Tuple }} + | id < typ_arg1 , .. , typ_argn > :: :: app + {{ com type constructor application }} + +typ_arg :: 'Typ_arg_' ::= + {{ com type constructor arguments of all kinds }} + {{ aux _ l }} + | typ :: :: typ + +typquant :: 'TypQ_' ::= + {{ com type quantifiers and constraints}} + {{ aux _ l }} + | :: :: no_forall {{ com empty }} + +typschm :: 'TypSchm_' ::= + {{ com type scheme }} + {{ aux _ l }} + | typquant typ :: :: ts + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% Type definitions % +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +type_def {{ ocaml 'a type_def }} {{ lem type_def 'a }} :: 'TD_' ::= + {{ ocaml TD_aux of type_def_aux * 'a annot }} + {{ lem TD_aux of type_def_aux * annot 'a }} + | type_def_aux :: :: aux + +type_def_aux :: 'TD_' ::= + {{ com type definition body }} + | typedef id = typschm :: :: abbrev + {{ com type abbreviation }} {{ texlong }} + | typedef id = const struct typquant { typ1 id1 ; ... ; typn idn } :: :: record + {{ com struct type definition }} {{ texlong }} + | typedef id = const union typquant { type_union1 ; ... ; type_unionn } :: :: variant + {{ com tagged union type definition}} {{ texlong }} + | typedef id = enumerate { id1 ; ... ; idn } :: :: enum + {{ com enumeration type definition}} {{ texlong }} + +% This one is a bit unusual - I think all nexps here must be constant, so replace with num. + | typedef id = register bits [ num : num' ] { index_range1 : id1 ; ... ; index_rangen : idn } + :: :: register {{ com register mutable bitfield type definition }} {{ texlong }} + +type_union :: 'Tu_' ::= + {{ com type union constructors }} + {{ aux _ l }} + | id :: :: id + | typ id :: :: ty_id + +index_range :: 'BF_' ::= {{ com index specification, for bitfields in register types}} + {{ aux _ l }} + | num :: :: 'single' {{ com single index }} + | num1 '..' num2 :: :: range {{ com index range }} + | index_range1 , index_range2 :: :: concat {{ com concatenation of index ranges }} + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% Literals % +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +lit :: 'L_' ::= + {{ com literal constant }} + {{ aux _ l }} + | ( ) :: :: unit {{ com $() : [[unit]]$ }} + | bitzero :: :: zero {{ com $[[bitzero]] : [[bit]]$ }} + | bitone :: :: one {{ com $[[bitone]] : [[bit]]$ }} + | true :: :: true {{ com $[[true]] : [[bool]]$ }} + | false :: :: false {{ com $[[false]] : [[bool]]$ }} + | num :: :: num {{ com natural number constant }} +% Need to represent as a function call, e.g. sil#hex_string "0xFFFF". +% | hex :: :: hex {{ com bit vector constant, C-style }} +% | bin :: :: bin {{ com bit vector constant, C-style }} + | string :: :: string {{ com string constant }} + | undefined :: :: undef {{ com undefined-value constant }} + | real :: :: real {{ com real number }} + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% Patterns % +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +pat :: 'P_' ::= + {{ com pattern }} + {{ aux _ annot }} {{ auxparam 'a }} + | _ :: :: wild + {{ com wildcard }} + | ( pat as id ) :: :: as + {{ com named pattern }} + | ( typ ) pat :: :: typ + {{ com typed pattern }} + | id :: :: id + {{ com identifier }} + | id ( pat1 , .. , patn ) :: :: app + {{ com union constructor pattern }} + | { fpat1 ; ... ; fpatn } :: :: record + {{ com struct pattern }} + | ( pat1 , .... , patn ) :: :: tup + {{ com tuple pattern }} + | [|| pat1 , .. , patn ||] :: :: list + {{ com list pattern }} + | ( pat ) :: S :: paren + {{ ichlo [[pat]] }} + | pat1 '::' pat2 :: :: cons + {{ com Cons patterns }} + +fpat :: 'FP_' ::= + {{ com field pattern }} + {{ aux _ annot }} {{ auxparam 'a }} + | id = pat :: :: Fpat + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% Expressions % +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +loop :: loop ::= {{ phantom }} + | while :: :: while + | until :: :: until + +exp :: 'E_' ::= + {{ com expression }} + {{ aux _ annot }} {{ auxparam 'a }} + | { exp1 ; ... ; expn } :: :: block {{ com sequential block }} + | nondet { exp1 ; ... ; expn } :: :: nondet {{ com nondeterministic block }} + | id :: :: id + {{ com identifier }} + | lit :: :: lit + {{ com literal constant }} +% Purely an annotation as all casting is resolved by type checker, can +% be evaluated by simply dropping the type. + | ( typ ) exp :: :: cast + {{ com cast }} + | id ( exp1 , .. , expn ) :: :: app + {{ com function application }} + | ( exp1 , .... , expn ) :: :: tuple + {{ com tuple }} + | if exp1 then exp2 else exp3 :: :: if + {{ com conditional }} + | loop exp1 exp2 :: :: loop + {{ com while or until loop }} + | foreach ( id from exp1 to exp2 by exp3 in order ) exp4 :: :: for + {{ com for loop }} + | [|| exp1 , .. , expn ||] :: :: list + {{ com list }} + | exp1 '::' exp2 :: :: cons + {{ com cons }} + | { fexps } :: :: record + {{ com struct }} + | { exp with fexps } :: :: record_update + {{ com functional update of struct }} + | exp . id :: :: field + {{ com field projection from struct }} + | switch exp { case pexp1 ... case pexpn } :: :: case + {{ com pattern matching }} + | letbind in exp :: :: let + {{ com let expression }} + | lexp := exp :: :: assign + {{ com imperative assignment }} + | return exp :: :: return + {{ com return $[[exp]]$ from current function }} + | exit exp :: :: exit + {{ com halt all current execution }} + | value :: I :: value + {{ com For internal use in interpreter to wrap pre-evaluated values when returning an action }} + +lexp :: 'LEXP_' ::= {{ com lvalue expression }} + {{ aux _ annot }} {{ auxparam 'a }} + | id :: :: id + {{ com identifier }} + | ( typ ) id :: :: cast + {{ com cast }} + | ( lexp0 , .. , lexpn ) :: :: tup {{ com multiple (non-memory) assignment }} +% SIL: Not sure how much to rewrite L-expressions. +% | lexp [ exp ] :: :: vector {{ com vector element }} +% | lexp [ exp1 '..' exp2 ] :: :: vector_range {{ com subvector }} +% | lexp . id :: :: field {{ com struct field }} + +fexp :: 'FE_' ::= + {{ com field expression }} + {{ aux _ annot }} {{ auxparam 'a }} + | id = exp :: :: Fexp + +fexps :: 'FES_' ::= + {{ com field expression list }} + {{ aux _ annot }} {{ auxparam 'a }} + | fexp1 ; ... ; fexpn :: :: Fexps + +pexp :: 'Pat_' ::= + {{ com pattern match }} + {{ aux _ annot }} {{ auxparam 'a }} + | pat -> exp :: :: exp + | pat when exp1 -> exp :: :: when + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% Function definitions % +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +tannot_opt :: 'Typ_annot_opt_' ::= + {{ com optional type annotation for functions}} + {{ aux _ l }} + | :: :: none + | typquant typ :: :: some + +rec_opt :: 'Rec_' ::= + {{ com optional recursive annotation for functions }} + {{ aux _ l }} + | :: :: nonrec {{ com non-recursive }} + | rec :: :: rec {{ com recursive }} + +effect_opt :: 'Effect_opt_' ::= + {{ com optional effect annotation for functions }} + {{ aux _ l }} + | :: :: pure {{ com sugar for empty effect set }} + | effectkw effect :: :: effect + +funcl :: 'FCL_' ::= + {{ com function clause }} + {{ aux _ annot }} {{ auxparam 'a }} + | id pat = exp :: :: Funcl + +fundef :: 'FD_' ::= + {{ com function definition}} + {{ aux _ annot }} {{ auxparam 'a }} + | function rec_opt tannot_opt effect_opt funcl1 and ... and funcln :: :: function {{ texlong }} + +letbind :: 'LB_' ::= + {{ com let binding }} + {{ aux _ annot }} {{ auxparam 'a }} + | let pat = exp :: :: val + {{ com let, implicit type ($[[pat]]$ must be total)}} + +val_spec {{ ocaml 'a val_spec }} {{ lem val_spec 'a }} :: 'VS_' ::= + {{ ocaml VS_aux of val_spec_aux * 'a annot }} + {{ lem VS_aux of val_spec_aux * annot 'a }} + | val_spec_aux :: :: aux + +val_spec_aux :: 'VS_' ::= + {{ com value type specification }} + {{ ocaml VS_val_spec of typschm * id * (string -> string option) * bool }} + {{ lem VS_val_spec of typschm * id * maybe string * bool }} + | val typschm id :: S :: val_spec + {{ com specify the type of an upcoming definition }} + {{ ocaml (VS_val_spec [[typschm]] [[id]] None false) }} {{ lem }} + +default_spec :: 'DT_' ::= + {{ com default kinding or typing assumption }} + {{ aux _ l }} + | default Order order :: :: order + +reg_id :: 'RI_' ::= + {{ aux _ annot }} {{ auxparam 'a }} + | id :: :: id + +alias_spec :: 'AL_' ::= + {{ com register alias expression forms }} + {{ aux _ annot }} {{ auxparam 'a }} + | reg_id . id :: :: subreg + | reg_id [ exp ] :: :: bit + | reg_id [ exp '..' exp' ] :: :: slice + | reg_id : reg_id' :: :: concat + +dec_spec :: 'DEC_' ::= + {{ com register declarations }} + {{ aux _ annot }} {{ auxparam 'a }} + | register typ id :: :: reg + | register alias id = alias_spec :: :: alias + | register alias typ id = alias_spec :: :: typ_alias + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% Top-level definitions % +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +prec :: '' ::= + | infix :: :: Infix + | infixl :: :: InfixL + | infixr :: :: InfixR + +def :: 'DEF_' ::= + {{ com top-level definition }} + {{ auxparam 'a }} + | type_def :: :: type + {{ com type definition }} + | fundef :: :: fundef + {{ com function definition }} + | letbind :: :: val + {{ com value definition }} + | val_spec :: :: spec + {{ com top-level type constraint }} + | fix prec num id :: :: fixity + {{ com fixity declaration }} + | overload id [ id1 ; ... ; idn ] :: :: overload + {{ com operator overload specification }} + | default_spec :: :: default + {{ com default kind and type assumptions }} + | dec_spec :: :: reg_dec + {{ com register declaration }} + +defs :: '' ::= + {{ com definition sequence }} + {{ auxparam 'a }} + | def1 .. defn :: :: Defs |
