summaryrefslogtreecommitdiff
path: root/src/ast_util.mli
AgeCommit message (Collapse)Author
2018-10-11Change the function type in the ASTAlasdair
Changes the representation of function types in the ast from Typ_fn : typ -> typ to Typ_fn : typ list -> typ to more accurately represent their use in the various backends, where we often compile functions to either their curried representations as in Lem and Isabelle, or just multiple argument functions in C. There's still some oddity because a single pattern in a function clause can bind against multiple arguments, and maybe we want to forbid this in the future. The syntax also hasn't changed (yet), so in theory this change shouldn't break anything (but it invariably will...). In the future we would ideally require that a function with N arguments has exactly N patterns in its declaration, one for each argument so f : (x, y) -> z f _ = ... would be disallowed (as _ matches both x and y), forcing f(_, _) = z this would simply quite a few things, Also we could have a different syntax for function argument lists and tuples, because it's rather hard to define a function that actually takes a tuple with the syntax how it is now. Some issues I noticed when doing this refactoring: Line 1926 of Coq translation. untuple_args_pat is maybe no longer needed? However there's still some funnyness where a pattern can be used to bind multiple function arguments so maybe it still is. Line 2306 of monomorphisation. I simplified the logic here. I think it's equivalent now, but I could be wrong. Line 4517 of rewrites. I'm not sure what make_cstr_mappings is doing here, but hopefully the simpler version is the same.
2018-09-28Fix optimisation bug for certain if statementsAlasdair Armstrong
When converting to A-normal form I just used the type of the then branch of if statements to get the type of the whole if statement - usually they'd be the same, but with flow typing one of the branches can have a false constraint, which then allows the optimizer to fit any integer into a 64-bit integer causing an overflow. The fix is to correctly use the type the typechecker gives for the whole if statement. Also add decimal_string_of_bits to the C output. Rename is_reftyp to is_ref_typ to be more consistent with other is_X_typ functions in Ast_util.
2018-09-27Add new functions in ast_util.ml for working with locationsAlasdair Armstrong
When constructing expressions, we need to provide locations for the generated expressions to give useful error messages. However adding these at every mk_X function in ast_util would be very verbose, especially for complex expressions. Add new locate_X functions (with the one for expressions simply being called locate), which take a location and recursively apply it to every child node, e.g. locate (gen_loc l) (mk_exp (... (mk_exp ..., mk_exp ...))) would mark every part of the constructed expression as being generated from code at location l.
2018-09-18Fix issues with tuple Constructors taking multiple argumentsAlasdair Armstrong
This really demonstrates why we should switch to Typ_fn being a typ list * typ constructor because the implementation here feels *really* hacky with dummy Typ_tup constructors being used to enforce single arguments for constructors.
2018-08-16Remove unused ref typeAlasdair Armstrong
2018-07-27Make type annotations abstract in type_check.mliAlasdair Armstrong
Rather than exporting the implementation of type annotations as type tannot = (Env.t * typ * effect) option we leave it abstract as type tannot Some additional functions have been added to type_check.mli to work with these abstract type annotations. Most use cases where the type was constructed explicitly can be handled by using either mk_tannot or empty_tannot. For pattern matching on a tannot there is a function val destruct_tannot : tannot -> (Env.t * typ * effect) option Note that it is specifically not guaranteed that using mk_tannot on the elements returned by destruct_tannot re-constructs the same tannot, as destruct_tannot is only used to give the old view of a type annotation, and we may add additional information that will not be returned by destruct_tannot.
2018-06-29Try to fix some tricky C compilation bugs, break everything insteadAlasdair Armstrong
2018-06-28Deduplicate arguments for different constructors in undefined fnsBrian Campbell
Makes the generated undefined functions smaller, easier to read, and avoids excessive memory usage in Coq (e.g., for large AST types).
2018-06-26Add configuration registers so __SetConfig ASL can be translatedAlasdair Armstrong
Registers can now be marked as configuration registers, for example: register configuration CFG_RVBAR = 0x1300000 They work like ordinary registers except they can only be set by functions with the 'configuration' effect and have no effect when read. They also have an initialiser, like a let-binding. Internally there is a new reg_dec constructor DEC_config. They are intended to represent configuration parameters for the model, which can change between runs, but don't change during execution. Currently they'll only work when compiled to C. Internally registers can now have custom effects for reads and writes rather than just rreg and wreg, so the type signatures of Env.add_register and Env.get_register have changed, as well as the Register lvar, so in the type checker we now write: Env.add_register id read_effect write_effect typ rather than Env.add_register id typ For the corresponding change to ASL parser there's a function is_config in asl_to_sail.ml which controls what becomes a configuration register for ARM. Some things we have to keep as let-bindings because Sail can't handle them changing at runtime - e.g. the length of vectors in other top-level definitions. Luckily __SetConfig doesn't (yet) try to change those options. Together these changes allow us to translate the ASL __SetConfig function, which means we should get command-line option compatibility with ArchEx for running the ARM conformance tests.
2018-06-08type checking mappings: allow inferring based on the other side's id inferencesJon French
2018-05-01further progressJon French
2018-05-01mostly added mappings to type-checker and pretty-printerJon French
2018-05-01utils mapping over mpats/mpexpsJon French
2018-04-26Fix bug in rewriting of loopsThomas Bauereiss
Take into account existential types when determining bounds for the loop variable
2018-04-09Stop vector_typ_args_of from failing when order is a variableBrian Campbell
Now it just returns the actual arguments and a separate function calculates the start index when required.
2018-03-22Tune Lem pretty-printingThomas Bauereiss
In particular, improve indentation of if-expressions, and provide infix syntax for monadic binds in Isabelle, allowing Lem to preserve source whitespace.
2018-03-14Add rewriting step for moving execute clauses into auxiliary functionsThomas Bauereiss
For example, generates an auxiliary function execute_ADD (rs, rt, rd) for the clause execute (ADD (rs,rt,rd)) = ... Without this rewriting, the execute function easily becomes too large to be handled by Isabelle (e.g., for CHERI-MIPS; for MIPS alone, it seems to be just about small enough). This used to be implemented in the pretty-printer, but that code was commented out recently in order to support a recursive execute function for RISC-V compressed instructions.
2018-03-07Make union types consistent in the ASTAlasdair Armstrong
Previously union types could have no-argument constructors, for example the option type was previously: union option ('a : Type) = { Some : 'a, None } Now every union constructor must have a type, so option becomes: union option ('a : Type) = { Some : 'a, None : unit } The reason for this is because previously these two different types of constructors where very different in the AST, constructors with arguments were used the E_app AST node, and no-argument constructors used the E_id node. This was particularly awkward, because it meant that E_id nodes could have polymorphic types, i.e. every E_id node that was also a union constructor had to be annotated with a type quantifier, in constrast with all other identifiers that have unquantified types. This became an issue when monomorphising types, because the machinery for figuring out function instantiations can't be applied to identifier nodes. The same story occurs in patterns, where previously unions were split across P_id and P_app nodes - now the P_app node alone is used solely for unions. This is a breaking change because it changes the syntax for union constructors - where as previously option was matched as: function is_none opt = match opt { Some(_) => false, None => true } it is now matched as function is_none opt = match opt { Some(_) => false, None() => true } note that constructor() is syntactic sugar for constructor(()), i.e. a one argument constructor with unit as it's value. This is exactly the same as for functions where a unit-function can be called as f() and not as f(()). (This commit also makes exit() work consistently in the same way) An attempt to pattern match a variable with the same name as a union-constructor now gives an error as a way to guard against mistakes made because of this change. There is probably an argument for supporting the old syntax via some syntactic sugar, as it is slightly prettier that way, but for now I have chosen to keep the implementation as simple as possible. The RISCV spec, ARM spec, and tests have been updated to account for this change. Furthermore the option type can now be included from $SAIL_DIR/lib/ using $include <option.sail>
2018-03-02Fix a bug in rewriting of loops for Lem backendThomas Bauereiss
The rewriter ignored loops that were not contained within some let-binding, which later caused the Lem pretty-printer to fail (see #8).
2018-02-21Implement more builtins in constant propagationBrian Campbell
2018-02-20Rework atom-to-itself transformation to check for equivalent size nexpsBrian Campbell
2018-02-15Re-engineer prompt monad of Lem shallow embeddingThomas Bauereiss
- Use simplified monad type (e.g., without the with_aux constructors that are not needed by the shallow embedding). - Add support for registers with arbitrary types (e.g., records, enumerations, vectors of vectors). Instead of using bit lists as the common representation of register values at the monad interface, use a register_value type that is generated per spec as a union of all register types that occur in the spec. Conversion functions between register_value and concrete types are generated. - Use the same representation of register references as the state monad, in preparation of rebasing the state monad onto the prompt monad. - Split out those types from sail_impl_base.lem that are used by the shallow embedding into a new module sail_instr_kinds.lem, and import that. Removing the dependency on Sail_impl_base from the shallow embedding avoids name clashes between the different monad types. Not yet done: - Support for reading/writing register slices. Currently, a rewriting pass pushes register slices in l-expressions to the right-hand side, turning a write to a register slice into a read-modify-write. For interfacing with the concurreny model, we will want to be more precise than that (in particular since some specs represent register files as big single registers containing a vector of bitvectors). - Lemmas about the conversion functions to/from register_value should be generated automatically.
2018-02-15Update duopod spec so it has no address translationAlasdair Armstrong
Also update the main aarch64 (no_vector) spec with latest asl_parser
2018-02-13Try to replace generated kids with user-defined ones from the environmentThomas Bauereiss
Solves a problem where generated kids crept into type annotations during rewriting and caused later typechecking passes to fail.
2018-02-06Improve destructuring existential typesAlasdair Armstrong
Make destructuring existentials less arcane by allowing them to be destructured via type patterns (typ_pat in ast.ml). This allows the following code for example: val mk_square : unit -> {'n 'm, 'n = 'm. vector('n, dec, vector('m, dec, bit))} function test (() : unit) -> unit = { let matrix as vector('width, _, 'height) = mk_square (); _prove(constraint('width = 'height)); () } where 'width we become 'n from mk_square, and 'height becomes 'm. The old syntax let vector as 'length = ... or even let 'vector = ... still works under this new scheme in a uniform way, so this is backwards compatible The way this works is when a kind identifier in a type pattern is bound against a type, e.g. 'height being bound against vector('m, dec, bit) in the example, then we get a constraint that 'height is equal to the first and only n-expression in the type, in this case 'm. If the type has two or more n-expressions (or zero) then this is a type error.
2018-01-30Generate functions from enums to numbers and vice versaAlasdair Armstrong
For an enumeration type T, we can create a function T_of_num and num_of_T which convert from the enum to and from a numeric type. The numeric type is range(0, n) where n is the number of constructors in the enum minus one. This makes sure the conversion is type safe, but maybe this is too much of a hassle. It would be possible to automatically overload all these functions into generic to_enum and from_enum as in Haskell's Enum typeclass, but we don't do this yet. Currently these functions affect a few lem test cases, but I think that is only because they are tested without any prelude functions and pattern rewrites require a few functions to be defined What is really broken is if one tries to generate these functions like enum x = A | B | C function f A = 0 function f B = 1 function f C = 2 the rewriter really doesn't like function clauses like this, and it seems really hard to fix properly (I tried and gave up), this is a shame as the generation code is much more succinct with definitions like above
2018-01-29Move subst to ast_util, use for guarded clauses rewriteBrian Campbell
2018-01-25Merge branch 'sail2' of https://bitbucket.org/Peter_Sewell/sail into sail2Alasdair Armstrong
2018-01-25Add pattern completness check for match statementsAlasdair Armstrong
Gives warnings when pattern matches are incomplete, when matches are redundant (in certain cases), or when no unguarded patterns exist. For example the following file: enum Test = {A, C, D} val test1 : Test -> string function test1 x = match x { A => "match A", B => "this will match anything, because B is unbound!", C => "match C", D => "match D" } val test2 : Test -> string function test2 x = match x { A => "match A", C => "match C" /* No match for D */ } val test3 : Test -> string function test3 x = match x { A if false => "never match A", C => "match C", D => "match D" } val test4 : Test -> string function test4 x = match x { A if true => "match A", C if true => "match C", D if true => "match D" } will produce the following warnings Warning: Possible redundant pattern match at file "test.sail", line 10, character 5 to line 10, character 5 C => "match C", Warning: Possible redundant pattern match at file "test.sail", line 11, character 5 to line 11, character 5 D => "match D" Warning: Possible incomplete pattern match at file "test.sail", line 17, character 3 to line 17, character 7 match x { Most general matched pattern is A_|C_ Warning: Possible incomplete pattern match at file "test.sail", line 26, character 3 to line 26, character 7 match x { Most general matched pattern is C_|D_ Warning: No non-guarded patterns at file "test.sail", line 35, character 3 to line 35, character 7 match x { warnings can be turned of with the -no_warn flag.
2018-01-25Implement basic case splitting based on found case expressionsBrian Campbell
(makes some of the monomorphisation case splits smaller)
2018-01-23Started working on C backend for sailAlasdair Armstrong
Also updated some of the documentation in the sail source code
2018-01-22Added rewriter that specializes all function calls in a specification.Alasdair Armstrong
This removes all type polymorphism, so we can generate optimized bitvector code and compile to languages without parametric polymorphism.
2018-01-18Merge remote-tracking branch 'origin/experiments' into sail2Alasdair Armstrong
2018-01-18Modified unification so Type_check.instantiation_of works after sizeof rewritingAlasdair Armstrong
This change allows the AST to be type-checked after sizeof re-writing. It modifies the unification algorithm to better support checking multiplication in constraints, by using division and modulus SMT operators if they are defined. Also made sure the typechecker doesn't re-introduce E_constraint nodes, otherwise re-checking after sizeof-rewriting will re-introduce constraint nodes.
2018-01-15Check monomorphisation case split size once for each patternBrian Campbell
(rather than for each argument separately)
2018-01-12Merge remote-tracking branch 'origin/experiments' into sail2Alasdair Armstrong
2018-01-03Updates to interpreterAlasdair Armstrong
Experimenting with porting riscv model to new typechecker
2017-12-19Support user-defined exceptions in Lem shallow embeddingThomas Bauereiss
The type-checker already supports a user-defined "exception" type that can be used in throw and try-catch expressions. This patch adds support for that to the Lem shallow embedding by adapting the existing exception mechanisms of the state and prompt monads. User-defined exceptions are distinguished from builtin exception cases. For example, the state monad uses type ex 'e = | Exit | Assert of string | Throw of 'e to distinguish between calls to "exit", failed assertions, and user-defined exceptions, respectively. Early return is also handled using the exception mechanism, by lifting to a monad with "either 'r exception" as the exception type, where 'r is the expected return type and "exception" is the user-defined exception type.
2017-12-14An experimental version of sail without bitvector start indexes.Alasdair Armstrong
Works with the vector branch of asl_parser
2017-12-13Use big_nums from LemAlasdair Armstrong
2017-12-06Add top-level pattern match guards internallyBrian Campbell
Also fix bug in mono analysis with generated variables Breaks lots of typechecking tests because it generates unnecessary equality tests on units (and the tests don't have generic equality), which I'll fix next.
2017-12-06Merge remote branch 'experiments' into experimentsThomas Bauereiss
2017-12-06Make AST after rewriting for Lem backend type-checkableThomas Bauereiss
- Add support for some internal nodes to type checker - Add more explicit type annotations during rewriting - Remove hardcoded rewrites for E_vector_update etc from Lem pretty-printer; these will be resolved by the type checker during rewriting now
2017-12-05Update license headers for Sail sourceAlasdair Armstrong
2017-11-27Utility functions in ast_util for asl_parserAlasdair Armstrong
2017-11-27Split rewriter into separate rewriting library and rewrite passesAlasdair Armstrong
As discussed previously, we wanted to start refactoring the re-writer to make it a bit less monolithic, and in the future potentially break it into separate files for backend-specific rewrites and stuff. - rewriter.ml now contains the generic re-writing code - rewrites.ml contains the rewriting passes themselves It would be nice if the generic rewriting code didn't depend on the typechecker, because then it could be used in ASL parser on untyped code.
2017-11-24Use unbound precision big_ints throughout sail.Alasdair Armstrong
Alastair's test cases revealed that using regular ints causes issues throughout sail, where all kinds of things can internally overflow in edge cases. This either causes crashes (e.g. int_of_string fails for big ints) or bizarre inexplicable behaviour. This patch switches the sail AST to use big_int rather than int, and updates everything accordingly. This touches everything and there may be bugs where I mistranslated things, and also n = m will still typecheck with big_ints but fail at runtime (ocaml seems to have decided that static typing is unnecessary for equality...), as it needs to be changed to eq_big_int. I also got rid of the old unused ocaml backend while I was updating things, so as to not have to fix it.
2017-11-16Remove unused Typ_wild constructorAlasdair Armstrong
2017-11-16Fixed some longstanding issues regarding constraints on type constructors.Alasdair Armstrong
Now constraints on type constructors are checked correctly when checking that types are well formed using Env.wf_typ. The arity and kind of type constructor arguments are also checked in the same way. Also some general cleanups to the type checker code, with some auxillary functions being moved to more appropriate files.
2017-11-13Record where existentials were created in their names.Alasdair Armstrong
Possibly useful for Brian's monomorphisation code