summaryrefslogtreecommitdiff
path: root/src
AgeCommit message (Collapse)Author
2017-11-21Check non-constraint liftable assertions in blocks correctlyAlasdair Armstrong
2017-11-21Merge Thomas' suggested changesBrian Campbell
Use overloading to find eq/neq Track range/atom split Missing type expansion
2017-11-20Merge branch 'experiments' of https://bitbucket.org/Peter_Sewell/sail into ↵Alasdair Armstrong
experiments
2017-11-20Fix a bug with constraint generation in flow typing.Alasdair Armstrong
This bug manifested as the ARM example elf executable printing the wrong characters... but otherwise doing not failing and exiting cleanly. It didn't trigger the test suite at all. I tracked it down to this line using git-bisect, and while returning nc_true is a bit suspect I'm still not 100% sure how this caused such a subtle and annoying bug in the generated ocaml code - it took several hours to track down the breakage to this line.
2017-11-20Tidy last upBrian Campbell
2017-11-20Constant propagation in guardsBrian Campbell
2017-11-20Basic handling of recursive calls in monomorphisation analysisBrian Campbell
2017-11-20Look up the right type variables in monomorphisation analysisBrian Campbell
2017-11-20Support new nexp in monoBrian Campbell
2017-11-17Fix Makefile for interpreter and update instruction_extractorAlasdair Armstrong
Instruction extractor code that I commented out in this commit seems buggy anyway - it will claim that the length of all bitvectors is 64?!
2017-11-17Fix interpreter to work with new typecheckerAlasdair Armstrong
Need to map sail type annotations to interpreter type annotations in lem_ast ouput. This doesn't seem too hard.
2017-11-16Make the generation of the lem_ast numeric constants automatic for all ↵Alasdair Armstrong
numbers below 129
2017-11-16Made l2.ott generate an ast.lem which is is valid w.r.t. -lem_ast output.Alasdair Armstrong
This is the first step towards getting the interpreter working on this branch
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-15Simplify flow typing code in typecheckerAlasdair Armstrong
2017-11-15Merge branch 'smt' into experimentsAlasdair Armstrong
2017-11-15Fix atom - range unification againAlasdair Armstrong
2017-11-15Fix rule for allowing atom to unify with rangeAlasdair Armstrong
2017-11-15Allow user defined operations in nexps (experimental)Alasdair Armstrong
There are several key changes here: 1) This commit allows for user defined operations in n-expressions using the Nexp_app constructor. These operations are linked to operators in the SMT solver, by using the smt extern when defining operations. Notably, this allows integer division and modular arithmetic to be used in types. This is best demonstrated with an example: infixl 7 / infixl 7 % val operator / = { smt: "div", ocaml: "quotient" } : forall 'n 'm, 'm != 0. (atom('n), atom('m)) -> {'o, 'o = 'n / 'm. atom('o)} val mod_atom = { smt: "mod", ocaml: "modulus" } : forall 'n 'm. (atom('n), atom('m)) -> {'o, 'o = mod_atom('n, 'm). atom('o)} val "print_int" : (string, int) -> unit overload operator % = mod_atom val main : unit -> unit function main () = { let 'm : {'x, 'x % 3 = 1. atom('x)} = 4; let 'n = m / 3; _prove(constraint(('m - 1) % 3 = 0)); _prove(constraint('n * 3 + 1 = 'm)); (* let x = 3 / 0; (* Will fail *) *) print_int("n = ", n); () } As can be seen, these nexp ops can be arbitrary user defined operators and even operator overloading works (although there are some caveats). This feature is very experimental, and some things won't work very well once you use custom operators - notably unification. However, this not necissarily a downside, because if restrict yourself to the subset of sail types that correspond to liquid types, then there is never a need to unify n-expressions. Looking further ahead, if we switch to a liquid type system a la minisail, then we no longer need to treat + - and * specially in n-expressions. So possible future refactorings could involve collapsing the Nexp datatype. 2) The typechecker is stricter about valspecs (and other types) being well-formed. This is a breaking change because previously we allowed things like: val f : atom('n) -> atom('n) and now this must be val f : forall 'n. atom('n) -> atom('n) if we want to allow the first syntax, then initial-check should desugar it this way - but it must be well-formed by the time it hits the type-checker, otherwise it's not clear that we do the right thing. Note we can actually have top-level type variables by using top-level let bindings with P_var. There's a future line of refactoring that would make it so that type variables can shadow each other properly (we should do this) - currently they all have to have unique names. 3) atom('n) is no longer syntactic sugar for range('n, 'n). The reason why we want to do this is that if we wanted to be smart about what sail operations can be translated into SMT operations at the type level we care very much that they talk about atoms and not ranges. Why? Because atom is the term level representation of a specific type variable so it's clear how to map between term level functions and type level functions, i.e. (atom('n) -> atom('n)) can be reflected at the type level by a type level function with kind Int -> Int, but the same is not true for range. Furthermore, both are interdefinable as atom('n) -> range('n, 'n) range('n, 'm) -> {'o, 'n <= 'o <= 'm. atom('n)} and I think the second is actually slightly more elegant. This change *should* be backwards compatible, as the type-checker knows how to convert from atom to ranges and unify them with each other, but there may be bugs introduced here...
2017-11-15Report all monomorphisation problemsBrian Campbell
2017-11-15For loops bind a type variableBrian Campbell
2017-11-15Remove untested infix monomorphisation (removed by type checker)Brian Campbell
2017-11-15Tidy up in monomorphisationBrian Campbell
2017-11-14During monomorphisation always refine constructors,Brian Campbell
not just when there's been a case split
2017-11-14Fix existential union typing problem in monomorphisationBrian Campbell
2017-11-14Remove some obsolete codeBrian Campbell
2017-11-14Automatic analysis for monomorphisationBrian Campbell
2017-11-13Record where existentials were created in their names.Alasdair Armstrong
Possibly useful for Brian's monomorphisation code
2017-11-10Fixed ocaml backend so it correctly compiles registers passed by name.Alasdair Armstrong
Added a test case for this behavior
2017-11-10Fixed some tricky typechecking bugsAlasdair Armstrong
2017-11-08Allow functions to be selectively declared external only for some backendsThomas Bauereiss
For example, val test = { ocaml: "test_ocaml" } : unit -> unit will only be external for OCaml. For other backends, it will have to be defined.
2017-11-08Merge branch 'experiments' of https://bitbucket.org/Peter_Sewell/sail into ↵Alasdair Armstrong
experiments
2017-11-08Allow for different extern names for different backendsAlasdair Armstrong
For example: val test = { ocaml: "test_ocaml", lem: "test_lem" } : unit -> unit val main : unit -> unit function main () = { test (); } for a backend not explicitly provided, the extern name would be simply "test" in this case, i.e. the string version of the id. Also fixed some bugs in the ocaml backend.
2017-11-07Fix typo in constraint rewriterThomas Bauereiss
2017-11-07Add builtin for reversing endiannessThomas Bauereiss
2017-11-07Declare prelude functions as externThomas Bauereiss
Also, rename a few functions for uniformity, e.g. bool_and -> and_bool
2017-11-07Fix vector_subrange typoBrian Campbell
2017-11-03Fix ocaml test suiteAlasdair Armstrong
2017-11-03Merge branch 'experiments' of https://bitbucket.org/Peter_Sewell/sail into ↵Alasdair Armstrong
experiments
2017-11-03Fixed a bug where true and false get mixed up in rewriterAlasdair Armstrong
2017-11-03Fix a bug where sail would throw an exception with empty file listAlasdair Armstrong
2017-11-03Make sure simple parameter sizes appear in Lem mwords outputBrian Campbell
2017-11-03Make nexp_simp a little smarterBrian Campbell
2017-11-02Added monomorphism restriction to undefined values.Alasdair Armstrong
What does this mean? Basically undefined values can't be created for types that contain free type variables, so for example: undefined : list(int) is good, but undefined : list('a) is bad. The reason we want to do this is because we can't compile them away statically, and this leads to situations where type-checkable code fails in the rewriter and gives horribly confusing error messages that don't relate to code the user wrote at all. As an example the following used to typecheck, but fail in the rewriter with a confusing error message, whereas now the typechecker should reject all cases which would trigger that failure in rewriting. val test : forall ('a:Type). list('a) -> unit effect {wreg, undef} function test xs = { xs_mut = xs; xs_mut = undefined; (* We don't know what kind of undefined 'a is *) () } There's a slight hitch, namely that in the undefined_type functions created by the -undefined_gen option, we do want to allow functions that have polymorphic undefined values, so that we can generate undefined generators for polymorphic datatypes such as: union option ('a:Type) = { Some : 'a, None } These functions are always have a specific form that allows the rewriter to succesfully remove the polymorphic undefined value for the 'a argument for Sone. As such there's a flag in the typechecking environment for polymorphic undefineds that is enabled when it sees a function with the undefined_ name prefix. Also: Fixed some test cases that were broken due to escape effect being added to assert.
2017-11-02Merge branch 'experiments'Thomas Bauereiss
2017-11-02Fix a few AST and parsing-related bugsThomas Bauereiss
2017-11-02Optionally generate an initial register state for the sequential Lem shallow ↵Thomas Bauereiss
embedding Checks for command-line flag -undefined_gen and uses the undefined value generator functions of the form undefined_typ to initialise registers
2017-11-02Fix translation of repeat-until loops to LemThomas Bauereiss
2017-11-02Handle "undefined" type-level sizes in monomorphisationBrian Campbell