package asli
- Exceptions thrown by typechecker
- AST construction utilities
- Prettyprinting support
- Environment representing global and local objects
- Unification
- Disambiguation of functions and operators
- Typecheck expressions
- Typecheck L-expressions
- Typecheck statements
- Typecheck function definition
- Typecheck instruction
- Typecheck global declaration
Install
dune-project
Dependency
Authors
Maintainers
Sources
md5=f4581fd209256823fa4d569ac96c8cee
sha512=fd4a74294beb9eeeafa80c9224b5dc30f5e5ebde4d53fa601929d283b6ca72154de313874321774914f738ac6f0d640e59452f7d03cb1db7b3a019b48b82e0d4
doc/asli.libASL/LibASL/Tcheck/index.html
Module LibASL.TcheckSource
Type inference and checker for ASL language
Exceptions thrown by typechecker
AST construction utilities
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.tyPrettyprinting support
Table of binary operators used for resugaring expressions when printing error messages.
Very pretty print type (resugaring expressions)
Environment representing global and local objects
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.identGlobal Environment (aka the Global Symbol Table)
dereference typedef
compare index types
structural match on two types - ignoring the dependent type part
Field typechecking support
type fieldtypes = | FT_Record of (AST.ty * AST.ident) list| FT_Register of (LibASL.Asl_utils.AST.slice list * AST.ident) list
Field accesses can be either record fields or fields of registers
This type captures the information needed to typecheck either of these
- a list of fieldname/type pairs for records
- a list of fieldname/slice pairs for registers
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
Environment (aka the Local+Global Symbol Table)
val declare_implicits :
LibASL.Asl_utils.AST.l ->
implicitVars ->
LibASL.Asl_utils.AST.stmt listUnification
Expression simplification
Perform 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
Z3 support code
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.exprUnification support code
Unifier
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
Type Unification
Notes on how type inference works:
- we use structural matching (ignoring the dependent type) to disambiguate each binop/unop/function/procedure call/getter/setter
- as we construct each TApply node,
- we insert fresh type variables $0, $1, ... for each of the type arguments (these are things we are going to solve for)
- unification generates two kinds of constraints: 1. bindings for type variables whenever unification requires "$i == e" or "e == $i" for some type variable $i 2. constraints where there are multiple bindings for a single variable 3. constraints on type variables whenever unification requires "e1 == e2" where e1 is not a variable
- after scanning an entire assignment/expression, we check: 1. do we have at least one binding for each variable? 2. are the bindings consistent with the constraints? Note that we could potentially give better (more localized) type errors if we check for consistency as we go along and if we check that a variable is bound as soon as the result type could not possibly involve the variable. (e.g., when checking "(e1 == e2 && Q) || R", any type variables associated with the equality check do not impact the && or || because "boolean" does not have any type parameters.)
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:
- add only the missing information "M" In effect, we are saying that missing type parameters are implicit parameters that are added by the type inference process and that the "type parameters" are basically just value expressions that are added by type inference.
- add type arguments for both "M" and "N". In effect we are saying that type parameters are distinct from value parameters and we are in the strange situation that a function could have both a value parameter M and a type parameter N and they might be bound to different (but equivalent) arguments. This is what archex does.
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
Disambiguation of functions and operators
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
Typecheck expressions
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
Typecheck L-expressions
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
Typecheck statements
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
Typecheck function definition
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 ->
sfuntypeTypecheck instruction
val 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
Typecheck global declaration
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
- Exceptions thrown by typechecker
- AST construction utilities
- Prettyprinting support
- Environment representing global and local objects
- Unification
- Disambiguation of functions and operators
- Typecheck expressions
- Typecheck L-expressions
- Typecheck statements
- Typecheck function definition
- Typecheck instruction
- Typecheck global declaration