LibASL.TcheckSourceType inference and checker for ASL language
val mk_eq_int :
LibASL.Asl_utils.AST.expr ->
LibASL.Asl_utils.AST.expr ->
LibASL.Asl_utils.AST.exprConstruct expression "eq_int(x, y)"
val mk_add_int :
LibASL.Asl_utils.AST.expr ->
LibASL.Asl_utils.AST.expr ->
LibASL.Asl_utils.AST.exprConstruct expression "add_int(x, y)"
val mk_sub_int :
LibASL.Asl_utils.AST.expr ->
LibASL.Asl_utils.AST.expr ->
LibASL.Asl_utils.AST.exprConstruct expression "sub_int(x, y)"
Construct expression "(0 + x1) + ... + xn"
val mk_concat_ty :
LibASL.Asl_utils.AST.ty ->
LibASL.Asl_utils.AST.ty ->
LibASL.Asl_utils.AST.tyTable of binary operators used for resugaring expressions when printing error messages.
Very pretty print type (resugaring expressions)
type funtype =
LibASL.Asl_utils.AST.ident
* bool
* LibASL.Asl_utils.AST.ident list
* LibASL.Asl_utils.AST.expr list
* (LibASL.Asl_utils.AST.ty * LibASL.Asl_utils.AST.ident) list
* LibASL.Asl_utils.AST.tytype sfuntype =
LibASL.Asl_utils.AST.ident
* LibASL.Asl_utils.AST.ident list
* LibASL.Asl_utils.AST.expr list
* LibASL.Asl_utils.AST.sformal list
* LibASL.Asl_utils.AST.tyval formal_of_sformal :
LibASL.Asl_utils.AST.sformal ->
LibASL.Asl_utils.AST.ty * LibASL.Asl_utils.AST.identdereference typedef
compare index types
structural match on two types - ignoring the dependent type part
type fieldtypes = | FT_Record of (AST.ty * AST.ident) list| FT_Register of (LibASL.Asl_utils.AST.slice list * AST.ident) listField accesses can be either record fields or fields of registers
This type captures the information needed to typecheck either of these
Get fieldtype information for a record/register type
val get_recordfield :
LibASL.Asl_utils.AST.l ->
(AST.ty * AST.ident) list ->
AST.ident ->
LibASL.Asl_utils.AST.tyGet fieldtype information for a named field of a record
val get_regfield_info :
LibASL.Asl_utils.AST.l ->
(LibASL.Asl_utils.AST.slice list * AST.ident) list ->
AST.ident ->
LibASL.Asl_utils.AST.slice listGet fieldtype information for a named field of a slice
val get_regfield :
LibASL.Asl_utils.AST.l ->
(LibASL.Asl_utils.AST.slice list * AST.ident) list ->
AST.ident ->
LibASL.Asl_utils.AST.slice list * LibASL.Asl_utils.AST.tyGet named field of a register and calculate type
val get_regfields :
LibASL.Asl_utils.AST.l ->
(LibASL.Asl_utils.AST.slice list * AST.ident) list ->
AST.ident list ->
LibASL.Asl_utils.AST.slice list * LibASL.Asl_utils.AST.tyGet named fields of a register and calculate type of concatenating them
val declare_implicits :
LibASL.Asl_utils.AST.l ->
implicitVars ->
LibASL.Asl_utils.AST.stmt listPerform simple constant folding of expression
It's primary role is to enable the 'DIV' hacks in z3_of_expr which rely on shallow syntactic transforms. It has a secondary benefit of sometimes causing constraints to become so trivial that we don't even need to invoke Z3 which gives a performance benefit.
Perform simple constant folding of expressions within a type
Convert ASL expression to Z3 expression. This only copes with a limited set of operations: ==, +, -, * and DIV. (It is possible that we will need to extend this list in the future but it is sufficient for the current ASL specifications.)
The support for DIV is not sound - it is a hack needed to cope with the way ASL code is written and generally needs a side condition that the division is exact (no remainder).
ufs is a mutable list of conversions used to handle subexpressions that cannot be translated. We treat such subexpressions as uninterpreted functions and add them to the 'ufs' list so that we can reason that "F(x) == F(x)" without knowing "F".
val z3_of_expr :
Z3.context ->
(LibASL.Asl_utils.AST.expr * Z3.Expr.expr) list ref ->
LibASL.Asl_utils.AST.expr ->
Z3.Expr.exprUnifier
val with_unify :
Env.t ->
LibASL.Asl_utils.AST.l ->
(unifier -> 'a) ->
AST.expr Asl_utils.Bindings.t * 'aCreate a fresh unifier, invoke a function that uses the unifier and check that the constraints are satisfied. Returns the synthesized bindings and result of function
Notes on how type inference works:
Note that there is a choice of what type arguments to add to a function
bits(N) ZeroExtend(bits(M) x, integer N)
We can either:
val unify_ixtype :
unifier ->
LibASL.Asl_utils.AST.ixtype ->
LibASL.Asl_utils.AST.ixtype ->
unitUnify two index types
val unify_type :
GlobalEnv.t ->
unifier ->
LibASL.Asl_utils.AST.ty ->
LibASL.Asl_utils.AST.ty ->
unitUnify two types
This performs a structural match on two types - ignoring the dependent type part
val unify_subst_e :
AST.expr Asl_utils.Bindings.t ->
LibASL.Asl_utils.AST.expr ->
LibASL.Asl_utils.AST.exprApply substitutions to an expression
val unify_subst_le :
AST.expr Asl_utils.Bindings.t ->
LibASL.Asl_utils.AST.lexpr ->
LibASL.Asl_utils.AST.lexprApply substitutions to an L-expression
val unify_subst_ty :
AST.expr Asl_utils.Bindings.t ->
LibASL.Asl_utils.AST.ty ->
LibASL.Asl_utils.AST.tyApply substitutions to a type
Replace all type variables in function type with fresh variables
Replace all type variables in setter function type with fresh variables
val check_type :
Env.t ->
unifier ->
LibASL.Asl_utils.AST.l ->
LibASL.Asl_utils.AST.ty ->
LibASL.Asl_utils.AST.ty ->
unitCheck that ty2 is a subtype of ty1: ty1 >= ty2
val check_type_exact :
Env.t ->
LibASL.Asl_utils.AST.l ->
LibASL.Asl_utils.AST.ty ->
LibASL.Asl_utils.AST.ty ->
unitCheck that ty1 is identical to ty2
val reportChoices :
LibASL.Asl_utils.AST.l ->
string ->
string ->
LibASL.Asl_utils.AST.ty list ->
funtype list ->
unitGenerate error message when function disambiguation fails
val isCompatibleFunction :
GlobalEnv.t ->
bool ->
LibASL.Asl_utils.AST.ty list ->
funtype ->
boolCheck whether a list of function argument types is compatible with the type of a function.
One function type is compatible with another if they have the same number of arguments and each argument has the same base type
val chooseFunction :
GlobalEnv.t ->
LibASL.Asl_utils.AST.l ->
string ->
string ->
bool ->
LibASL.Asl_utils.AST.ty list ->
funtype list ->
funtype optionDisambiguate a function name based on the number and type of arguments
val isCompatibleSetterFunction :
GlobalEnv.t ->
LibASL.Asl_utils.AST.ty list ->
sfuntype ->
boolCheck whether a list of function argument types is compatible with the type of a setter function.
One function type is compatible with another if they have the same number of arguments and each argument has the same base type
val chooseSetterFunction :
GlobalEnv.t ->
LibASL.Asl_utils.AST.l ->
string ->
AST.ident ->
LibASL.Asl_utils.AST.ty list ->
sfuntype list ->
sfuntype optionDisambiguate a setter function name based on the number and type of arguments
val instantiate_fun :
GlobalEnv.t ->
unifier ->
LibASL.Asl_utils.AST.l ->
funtype ->
LibASL.Asl_utils.AST.expr list ->
LibASL.Asl_utils.AST.ty list ->
LibASL.Asl_utils.AST.ident
* LibASL.Asl_utils.AST.expr list
* LibASL.Asl_utils.AST.tyInstantiate type of function using unifier 'u'
val instantiate_sfun :
GlobalEnv.t ->
unifier ->
LibASL.Asl_utils.AST.l ->
sfuntype ->
LibASL.Asl_utils.AST.expr list ->
LibASL.Asl_utils.AST.ty list ->
LibASL.Asl_utils.AST.ty ->
LibASL.Asl_utils.AST.ident * LibASL.Asl_utils.AST.expr listInstantiate type of setter function using unifier 'u'
val tc_apply :
GlobalEnv.t ->
unifier ->
LibASL.Asl_utils.AST.l ->
string ->
LibASL.Asl_utils.AST.ident ->
LibASL.Asl_utils.AST.expr list ->
LibASL.Asl_utils.AST.ty list ->
LibASL.Asl_utils.AST.ident
* LibASL.Asl_utils.AST.expr list
* LibASL.Asl_utils.AST.tyDisambiguate and typecheck application of a function to a list of arguments
val tc_unop :
GlobalEnv.t ->
unifier ->
LibASL.Asl_utils.AST.l ->
AST.unop ->
LibASL.Asl_utils.AST.expr ->
LibASL.Asl_utils.AST.ty ->
LibASL.Asl_utils.AST.ident
* LibASL.Asl_utils.AST.expr list
* LibASL.Asl_utils.AST.tyDisambiguate and typecheck application of a unary operator to argument
val tc_binop :
GlobalEnv.t ->
unifier ->
LibASL.Asl_utils.AST.l ->
AST.binop ->
LibASL.Asl_utils.AST.expr ->
LibASL.Asl_utils.AST.expr ->
LibASL.Asl_utils.AST.ty ->
LibASL.Asl_utils.AST.ty ->
LibASL.Asl_utils.AST.ident
* LibASL.Asl_utils.AST.expr list
* LibASL.Asl_utils.AST.tyDisambiguate and typecheck application of a binary operator to arguments
val check_var :
Env.t ->
LibASL.Asl_utils.AST.l ->
LibASL.Asl_utils.AST.ident ->
LibASL.Asl_utils.AST.ident * LibASL.Asl_utils.AST.tyLookup a variable in environment
val tc_exprs :
Env.t ->
unifier ->
LibASL.Asl_utils.AST.l ->
LibASL.Asl_utils.AST.expr list ->
(LibASL.Asl_utils.AST.expr * LibASL.Asl_utils.AST.ty) listTypecheck list of expressions
val check_expr :
Env.t ->
LibASL.Asl_utils.AST.l ->
LibASL.Asl_utils.AST.ty ->
LibASL.Asl_utils.AST.expr ->
LibASL.Asl_utils.AST.exprTypecheck expression and check that it is a subtype of ty
val tc_e_elsif :
Env.t ->
unifier ->
LibASL.Asl_utils.AST.l ->
LibASL.Asl_utils.AST.e_elsif ->
LibASL.Asl_utils.AST.e_elsif * LibASL.Asl_utils.AST.tyTypecheck 'if c then expr'
val tc_slice :
Env.t ->
unifier ->
LibASL.Asl_utils.AST.l ->
LibASL.Asl_utils.AST.slice ->
LibASL.Asl_utils.AST.slice * LibASL.Asl_utils.AST.tyTypecheck bitslice indices
val tc_pattern :
Env.t ->
LibASL.Asl_utils.AST.l ->
LibASL.Asl_utils.AST.ty ->
LibASL.Asl_utils.AST.pattern ->
LibASL.Asl_utils.AST.patternTypecheck pattern against type ty
val tc_slice_expr :
Env.t ->
unifier ->
LibASL.Asl_utils.AST.l ->
AST.expr ->
(LibASL.Asl_utils.AST.slice * LibASL.Asl_utils.AST.ty) list ->
LibASL.Asl_utils.AST.expr * LibASL.Asl_utils.AST.tyTypecheck bitslice syntax This primarily consists of disambiguating between array indexing and bitslicing Note that this function is almost identical to tc_slice_lexpr
val tc_expr :
Env.t ->
unifier ->
LibASL.Asl_utils.AST.l ->
LibASL.Asl_utils.AST.expr ->
LibASL.Asl_utils.AST.expr * LibASL.Asl_utils.AST.tyTypecheck expression
Typecheck list of types
Typecheck type
val tc_slice_lexpr :
Env.t ->
unifier ->
LibASL.Asl_utils.AST.l ->
AST.lexpr ->
(LibASL.Asl_utils.AST.slice * LibASL.Asl_utils.AST.ty) list ->
LibASL.Asl_utils.AST.lexpr * LibASL.Asl_utils.AST.tyTypecheck bitslice syntax
This primarily consists of disambiguating between array indexing and bitslicing Note that this function is almost identical to tc_slice_expr
val tc_lexpr2 :
Env.t ->
unifier ->
LibASL.Asl_utils.AST.l ->
AST.lexpr ->
LibASL.Asl_utils.AST.lexpr * LibASL.Asl_utils.AST.tyTypecheck left hand side of expression in context where type of right hand side is not yet known
val tc_lexpr :
Env.t ->
unifier ->
LibASL.Asl_utils.AST.l ->
LibASL.Asl_utils.AST.ty ->
LibASL.Asl_utils.AST.lexpr ->
LibASL.Asl_utils.AST.lexpr * implicitVarsTypecheck left hand side of expression and check that rhs type 'ty' is compatible. Return set of variables assigned to in this expression
val tc_stmts :
Env.t ->
LibASL.Asl_utils.AST.l ->
LibASL.Asl_utils.AST.stmt list ->
AST.stmt listTypecheck list of statements
val tc_s_elsif :
Env.t ->
LibASL.Asl_utils.AST.l ->
LibASL.Asl_utils.AST.s_elsif ->
LibASL.Asl_utils.AST.s_elsifTypecheck 'if expr then stmt'
val tc_alt :
Env.t ->
LibASL.Asl_utils.AST.l ->
LibASL.Asl_utils.AST.ty ->
LibASL.Asl_utils.AST.alt ->
LibASL.Asl_utils.AST.altTypecheck case alternative
val tc_catcher :
Env.t ->
LibASL.Asl_utils.AST.l ->
LibASL.Asl_utils.AST.catcher ->
LibASL.Asl_utils.AST.catcherTypecheck exception catcher 'when expr stmt'
Typecheck statement
val tc_body :
Env.t ->
LibASL.Asl_utils.AST.l ->
LibASL.Asl_utils.AST.stmt list ->
LibASL.Asl_utils.AST.stmt listTypecheck function body (list of statements)
val tc_argument :
Env.t ->
LibASL.Asl_utils.AST.l ->
(LibASL.Asl_utils.AST.ty * LibASL.Asl_utils.AST.ident) ->
LibASL.Asl_utils.AST.ty * LibASL.Asl_utils.AST.identTypecheck function argument
val tc_arguments :
Env.t ->
LibASL.Asl_utils.AST.l ->
(LibASL.Asl_utils.AST.ty * LibASL.Asl_utils.AST.ident) list ->
(LibASL.Asl_utils.AST.ty * LibASL.Asl_utils.AST.ident) listTypecheck list of function arguments
Typecheck setter procedure argument
Typecheck list of setter procedure arguments
val addFunction :
GlobalEnv.t ->
LibASL.Asl_utils.AST.l ->
LibASL.Asl_utils.AST.ident ->
bool ->
Asl_utils.IdentSet.t ->
(LibASL.Asl_utils.AST.ty * LibASL.Asl_utils.AST.ident) list ->
LibASL.Asl_utils.AST.ty ->
funtypeAdd function definition to environment
val addSetterFunction :
GlobalEnv.t ->
LibASL.Asl_utils.AST.l ->
LibASL.Asl_utils.AST.ident ->
Asl_utils.IdentSet.t ->
LibASL.Asl_utils.AST.sformal list ->
LibASL.Asl_utils.AST.ty ->
sfuntypeval tc_encoding :
Env.t ->
AST.encoding ->
AST.encoding * (LibASL.Asl_utils.AST.ident * LibASL.Asl_utils.AST.ty) listTypecheck instruction encoding
val tc_decode_slice :
int Asl_utils.Bindings.t ->
LibASL.Asl_utils.AST.l ->
LibASL.Asl_utils.AST.decode_slice ->
LibASL.Asl_utils.AST.decode_slice * intTypecheck bitslice of instruction opcode
val tc_decode_pattern :
LibASL.Asl_utils.AST.l ->
int ->
AST.decode_pattern ->
AST.decode_patternTypecheck instruction decode pattern match
Typecheck instruction decode body
val tc_decode_alt :
GlobalEnv.t ->
LibASL.Asl_utils.AST.l ->
int list ->
AST.decode_alt ->
AST.decode_altTypecheck instruction decode case alternative
val tc_decode_case :
GlobalEnv.t ->
AST.l ->
AST.instr_field list ->
AST.decode_case ->
AST.decode_caseTypecheck instruction decode case
val tc_declaration :
GlobalEnv.t ->
LibASL.Asl_utils.AST.declaration ->
LibASL.Asl_utils.AST.declaration listTypecheck global declaration, extending environment as needed
val genPrototypes :
LibASL.Asl_utils.AST.declaration list ->
LibASL.Asl_utils.AST.declaration list * LibASL.Asl_utils.AST.declaration listGenerate function prototype declarations.
This allows function declarations within a translation unit to be placed in any order.
Overall typechecking environment shared by all invocations of typechecker
val tc_declarations :
bool ->
LibASL.Asl_utils.AST.declaration list ->
LibASL.Asl_utils.AST.declaration listTypecheck a list of declarations - main entrypoint into typechecker