Requires Menhir 20211230 and OCaml 4.08 or above.
Parser:
API:
RawQuery.compile_ast, lets one set up the initial state in which the query is run, even if the query is given as an ast.solution.relocate_assignment_to_runtime to pass a query result to another queryBuiltInPredicate.FullHO for higher order external predicatesBuiltInPredicate.HOAdaptors for map and filter like HO predicatesCalc.register to register operators for calc (aka infix is)Library:
std.fold-rightRuntime:
:index directive selects only one argument with a depth > 1.Requires Menhir 20211230 and OCaml 4.08 or above. Camlp5 8.0 or above is optional.
API:
Setup.init takes a ?state, ?quotations and ?hooks descriptors so that each elpi handle is completely independent.State.declare is deprecated in favor of State.declare_componentState.declare_component like State.declare but takes a ~descriptorState.new_state_descriptorQuotations.register_named_quotation now takes a ?descriptorQuotations.set_default_quotation now takes a ?descriptorQuotations.declare_backtick now takes a ?descriptorQuotations.declare_singlequote now takes a ?descriptorQuotations.new_quotations_descriptorRawData.set_extra_goals_postprocessing now takes a ?descriptorRawData.new_hoas_descriptorRequires Menhir 20211230 and OCaml 4.08 or above. Camlp5 8.0 or above is optional.
Parser:
Requires Menhir 20211230 and OCaml 4.08 or above. Camlp5 8.0 or above is optional.
Builtins:
unix.process really disabled on OCaml 4.12Requires Menhir 20211230 and OCaml 4.08 or above. Camlp5 8.0 or above is optional.
Builtins:
unix.process disabled on OCaml 4.12Requires Menhir 20211230 and OCaml 4.08 or above. Camlp5 8.0 or above is optional.
Builtins:
unix.process datatype and unix.process.open/close APIsRequires Menhir 20211230 and OCaml 4.08 or above. Camlp5 8.0 or above is optional.
Compiler:
Parser:
) misleading the user)Builtins:
declare_constraint to any -> any -> variadic any prop making it explicitly take at least two argumentsTrace browser:
Requires Menhir 20211230 and OCaml 4.08 or above. Camlp5 8.0 or above is optional.
Elpi:
:replace which replaces a named clause by an unnamed oneTrace browser:
Requires Menhir 20211230 and OCaml 4.08 or above. Camlp5 8.0 or above is optional.
Trace browser:
Requires Menhir 20211230 and OCaml 4.08 or above. Camlp5 8.0 or above is optional.
Dependencies:
Requires Menhir 20211230 and OCaml 4.08 or above. Camlp5 8.0 or above is optional.
Tests:
Requires Menhir 20211230 and OCaml 4.08 or above. Camlp5 8.0 or above is optional.
API:
FlexData.Elpi.make when called with a name after compilation is overRawQuery.mk_Arg can only be called at compile timeQuery.compileTrace:
Doc:
Requires Menhir 20211230 and OCaml 4.08 or above. Camlp5 8.0 or above is optional.
Apis in the Builtin module:
string_set, int_set and loc_set conversionsocaml_set_conv giving both the declarations and the conversion for the provided OCaml Set moduleRequires Menhir 20211230 and OCaml 4.08 or above. Camlp5 8.0 or above is optional.
Tace Elaborator:
Trace:
file:// and tcp:// to disambiguate host:port on windows (old syntax still supported)Requires Menhir 20211230 and OCaml 4.08 or above. Camlp5 8.0 or above is optional.
Requires Menhir 20211230 and OCaml 4.08 or above. Camlp5 8.0 or above is optional.
Trace Elaborator:
Requires Menhir 20211230 and OCaml 4.08 or above. Camlp5 8.0 or above is optional.
Tests:
Requires Menhir 20211230 and OCaml 4.08 or above. Camlp5 8.0 or above is optional.
Parser:
Printer:
Doc:
InOut and ioarg doc in the API fileTrace:
src/trace.atd data type description for tracessrc/trace_atd.ts read/write the trace in TypeScriptelpi-trace-elaborator tool to turn raw traces into cards to be displayed by a GUI. Work is in progress on the elpi-lang VS Code extension.Requires Menhir 20211230 and OCaml 4.07 or above. Camlp5 8.0 or above is optional.
warning: The parser used by default is not backward compatible with 1.14.x
Parser:
pred foo i:A o:B is valid, pred foo i:A o :B is not. This change restores backward compatibility of existing code.Requires Menhir 20211230 and OCaml 4.07 or above. Camlp5 8.0 or above is optional.
warning: The parser used by default is not backward compatible with 1.14.x
Build:
make config LEGACY_PARSER=1 to enable itelpi-option-legacy-parser to install elpi with the legacy parser enabledParser:
& (synonym of ,)pred declarations, eg pred i:A o:B. is valid syntaxRequires Menhir 20211230 and OCaml 4.07 or above. Camlp5 is now optional.
warning: The parser used by default is not backward compatible
Parser:
New parser based on Menhir
Old parser available via -legacy-parser
camlp5 is availableinfix and similar mixfix directivesAPI:
Parse.goal_from_stream -> Parse.goal_fromParse.program_from_stream -> Parse.program_fromParse.resolve_file now takes an ~elpi argumentSetup.init resolver argument takes a ~unit instead of ~fileSetup.init takes ?legacy_parserSetup.legacy_parser_avaiablePp.query -> Pp.program and Pp.goalREPL:
-parse-term-legacy-parser-legacy-parser-available-print-accumulated-filesTests:
test.exe understands --skip-catmake tests understands SKIP for the categories to skipDependencies:
Runtime:
AppArg (regression in 1.14.0)Runtime/FFI:
Rawdata.Constants.eqc to a builtinRawdata.Constants.cutc has always been a builtinPtrMapAPI:
FlexibleData.WeakMap to link unification variables with host data based on OCaml's EphemeronConversion.extra_goals is now an extensible data type with one standard constructor Conversion.Unify taking two termsRawData.set_extra_goals_postprocessing can be used to post process the extra goals generated by an FFI call. One has to translate extensions to the extra_goals datatype to RawData.RawGoal (or Conversion.Unify), but can also take global actions like cancelling out useless or duplicate goalsSetup.init to take in input a ~file_resolver rather than a list of ~paths and a ~basedir. A custom file resolver can use some logic from the host application to find files, rather than an hardcoded oneParse.std_resolver building a standard resolver (based on paths)Parse.resolve_file making ?cwd explicitLibrary:
std.nthdeclare_constraint is now variadic any prop, so that one can pass variables of different types as keys for the constraint. A list of variables (of the same type) is still supported.Build:
camlp5.gramlib as part of elpi.cmxs so that the plugin can be loaded via findlib.Compiler:
API:
std.findall is now calling a builtin which is able to produce solutions which contain eigenvariables and uvars as well.loc is now printed using / as a path separator also on Windowsloc.fields to project a loc into the file, line, etc...API:
prune which can be used to prune a unification variabledistinct_names which checks if a list of arguments is in the pattern fragmentioargC_flex which considers flexible terms as Datawhile_compiling even when execution is over, since the API to allocate a new Elpi uvar needs it and Coq-Elpi may call this API while translating the solution to CoqBuild:
API:
gc.get and gc.set for reading and writing GC settingsgc.minorgc.majorgc.fullgc.compactgc.statgc.quick-statmin and max operators for the is builtin, they work on int and floatrex_match -> rex.matchrex_replace -> rex.replacerex_split -> rex.splitcounter -> trace.counterFFI:
Builtin.unspec type to express optional inputAPI:
open_append was messing up file permissionsParse.resolve_file to find where the parser would find (or not) an accumulated fileCompile.unit, Compile.assemble and Compile.extend and improve their implementation. Units are now smaller and link/relocate faster (making ~follows not worth it)CI:
Library:
if2std.map-okstd.fold-mapstd.interspersestd.omapstd.take-laststd.string.concatFFI:
RawOpaqueData.cin now returns a term and takes constants into account. Whenever a value is represented with a named constant, the API grants that:
API:
Compile.extend to (quickly) add clauses to a program?follows:program to Compile.unit to have the unit be compiled using the very same symbol table (no new symbols can be declared by the unit in this case)Library:
map2_filter -> map2-filtermap-filterBuild:
shasum instead of sha1sum-print* options to the elpi command line utilityrex_split (like OCaml's Str.split)Builtin:
var now accepts 3 arguments, as constant and name.Trace:
user and devBuild system:
src/.ppcache that Elpi can be buildt without ppx_deriving.std and elpi.trace.ppx using a new tool in ppxfindcache/ppx_deriving_runtime (suffix _proxy) to be used when ppx_deriving is not installedmerlinppx.exe for src/ and and patch .merlin file so that one can have decent merlin supporttest-noppx to compile on an alternative opam switchBuiltin:
API:
Compiler:
API:
Tests:
Parser:
\n inside quotations were not taken into account.Typing:
typeabbrev x int does not take over int, while typeabbrev x (list int) does over list int.Stdlib:
is function int_of_string to do what it saysis function rhc : string -> int computes the inverse of chrTyping:
typeabbrev declarations are now taken into account and unfolded by the compiler. The type checker refolds abbreviations when printing error messages with the following caveat: when two type abbreviations can be refolded the last declared one wins.Compiler:
@macro are no more accepted in types, since typeabbrev provides the same functionality.accumulate is idempotent: accumulating the same file a second time has no effect.FFI:
Conversion.t of type 'a ioarg, and recommended to wrap any nested type not able to represent variables in ioarg. Eg int option should be int ioarg option ioarg. In this way one can safely call these builtins with non-ground terms, such as some _, for example to assert the result is not none but without providing a ground term such as some 3.MLData declarations for OpaqueData are no more named using a macro but rather using a type abbreviation. This can break user code. The fix is to substitute @myopaquetype with myopaquetype everywhere.Stdlib:
diagnostic data type to be used as an ioarg for builtins that can fail with a relevant error message. On the ML side one can used Elpi.Builtin.mkOK and Elpi.Builtin.mkERROR "msg" to build its values.std.assert-ok!, std.forall-ok, std.do-ok!, std.lift-ok and std.while-ok-do! commodity predicates.calc (infix _ is _) now come with a type declaration.Bugfix:
shorten foo.{ bar }. when foo.bar is a builtin used to be miscompiled.elpi-typechecker.elpi now correclty stops printing warnings after it printed 10 (used to stop after he processed 10, that may not be the same thing, since some warnings are suppressed).Parser:
-2 (with no space) as the negative 2 not as the constant -2. This way X is 3 - 2 and Y is 3 + -2 are both valid.FFI:
OpaqueData now requires a ternary comparison, not just equality.Stdlib:
cmp for ternary comparison.std.set and std.map now based on ternary comparison.Builtin:
cmp_term giving an order on ground terms.ground_term to check if a term is ground.Parser:
, in lists, eg [1,2,3,] is now parsed as [1,2,3].Parse.goal_from_string contains extra tokens& is now turned on the fly into the nary one ,.Bugfix:
Discard is now considered a stack term, and is turned into an unification variable on heapification.API.RawData.look now expands UVar correctlyStdlib:
set and map for arbitrary terms equipped with an order relation. Based on the code of OCaml's Map and Set library.map.remove for maps on builtin data.FFI:
ContextualConversion module and ctx_readback type. In an FFI call one can specify a readback for the hypothetical context that is run once and its output is give to the ML code instead of the "raw" constraints and hyp list.API:
Elpi.Builtin to export as built-in OCaml's Set.S and Map.S interfaces (the output of Set.Make and Map.Make). All data is limited to be a closed term.Constants.andc2 was removedFlexibleData.Elpi.make takes no ~lvl argument (it is always 0)RawData.view no more contains Discard since it is not an heap termMisc:
.elpi files fixed after the switch to duneBuiltin:
same_term (infix ==) for Prolog's non-logical comparison (without instantiation).set and map A (A only allowed to be a closed term) on string, int and loc keys.Compiler:
FFI:
AlgebraicData declarations to mix M and MS constructorsConversion.t for closed terms (no unification variable and no variables bound by the program)Tests:
Elpi 1.5 requires OCaml 4.04 or newer
REPL:
-no-tc to skip type checking.-version flag to the command line utility.Runtime:
FFI:
readback is now as powerful as embed and can generate extra goals. The two types are now dual.Elpi 1.4 requires OCaml 4.04 or newer
elpi_x.ml to x.ml, and each module Elpi_X is now available as Elpi.X. In particular clients must now use Elpi.API and Elpi.Builtin.FFI:
Conversion.TypeErr now carries the depth at which the error is found, so that the term payload can be correctly printed.BuiltInPredicate.Full now returns a list of extra_goals, exactly as Conversion.embed does making conversion code easy to call in the body of a predicate.Elpi 1.3 requires OCaml 4.04 or newer
AlgebraicData, OpaqueData, FlexibleData or for low level access RawOpaqueData or RawData for naked terms.FFI:
RawData.mkAppL and RawData.mkAppSL handy constructorscustom_state renamed statesolution in the type of builtin predicates but rather constraints and state explicitlyMLCData and MLADT into MLDataAlgebraicData.t supports C for containers, so that one can model
type t = A | B of list tas
K("a", N, ..
K("b",(C ((fun x -> list x),N)), ..FlexibleTerm.Elpi.t and FlexibleTerm.Map to represent Elpi's unification variables and keep a bijective map between them and any host application data.RawData.term contains no more UVar, AppUVar, Arg and AppArg but only UnifVar of FlexibleTerm.Elpi.t * term list.solution contains an output field holding data of the type described by the query.Library:
mode (std.mem i i) with (std.mem i o): member can be assignedstd.mem! and std.memFix:
expand_* in charge of putting unification variables in canonical form was sometimes omitting some lambdas in one of its outputsLanguage:
shorten directive to give short names to symbols that live in namespaces, e.g. shorten std.{ rev } lets one write rev instead of std.revg { h => (a, f) } becomes (h => (a, f X)), g X.. as X to bind subterms in the head of a clause changed precedence. In particular lam x\ B as X binds lam x\ B to X (instead of just B, as it was the case in previous versions):index(...) attribute for predicates to select which argument(s) should be indexed and at which depth. Multi-argument indexing and deep-indexing are based on unification hashes, see ELPI.md for more detailsLibrary:
predefined types:
bool with tt and ffoption A with none and some Apair A B with pr A B, fst and sndpredefined control structure:
if C T Estandard library (taken from coq-elpi) in the std namespace.
Conventions:
fatal-error and fatal-error-w-data! suffix is for (variants) of predicates that generate only the first solutionR suffixSymbols: debug-print, ignore-failure!, assert!, spy, spy!, unsafe-cast, length, rev, last, append, appendR, take, drop, drop-last, split-at, fold, fold2, map, map-i, map2, map2_filter, nth, lookup, lookup!, mem, exists, exists2, forall, forall2, filter, zip, unzip, flatten, null, iota, flip, time, do!, spy-do!, any->string, random.init, random.self_init, random.int
While the predicates in the library are reasonably tested, their names and name spaces may change in the future, e.g. a specific name space for list related code may be created (as well for strings, debug, etc).
Builtin:
name is now typed as any -> variadic any prop to support the following two use cases:
name T succeeds if T is an eigenvariable (even if it is applied)name T HD ARGS relates T (an applied eigenvariable) to its head and arguments (as a list): pi f x y\ name (f x y) f [x,y]constant working as name but for non-eigenvariableshalt now accepts any term, not just stringsgetenv is now typed as string -> option string and never fails. The old semantics can be obtained by just writing getenv Name (some Value)API:
Ast.Loc.tParseError(loc, message) systematically used in the parsing API (no more leak of exceptions or data types from the internal parsing engine, i.e. no more NotInProlog or Stream.Error exceptions)simplified term constructors:
mkConst split into mkGlobal and mkBoundS taking a string rather than a global constant, e.g. mkAppS, mkGlobalS, mkBuiltinSmkBuiltinName removed (replace by mkBuiltinS)spillc exported: one can not build a term such as f {g a} by writing mkAppS "f" (mkApp spillc (mkAppS "g" (mkGlobalS "a") []) []FFI:
to_term and of_term renamed to embed and readback and made stateful. They can access the state, the hypothetical context and the constraint store (exactly as Full ffi builtins do) and can return an updated state. Moreover embed can generate new goals (eg declaration of constraints) so that data that requires companion constraints fits the capabilities of the FFI (no need to simulate that by using a Full predicate with arguments of type any, as coq-elpi was doing)Arguments to builtin predicates now distinguish between
In ML code must receive the data, type error is the data cannot be represented in MLOut ML code received Keep or Discard so that it can avoid generating data the caller is not binding backInOut ML code receives Data of 'a or NoData. The latter case is when the caller passed _, while the former contains the actual dataty field is no more a string but an AST, so that containers (eg val list : 'a data -> 'a list data) can more easily generate the composite typeCompiler:
REPL:
--help including hints for the tracing options-print-passes to debug the compilerTest Suite:
dune, cmdliner and ANSITerminal in order to buildFix:
beta was not calling deref_* in all cases, possibly terminating reduction too early (and raising an anomaly)Language:
CHR semantics conformed to the "revised operational semantics", that is roughly the following:
1 for each active constraint (just declared via declare_constraint)
2 for each rule
3 for each position j of the active constraint (from 0 to n)
4 for each permutation of constraints having the active at j
5 try apply the rule
In Elpi 1.0 loops 3 and 2 were swapped (by mistake)
CHR keys refined. In declare_constraints C KEYS:
KEYS must be a list of variables (no more special case KEYS = Var)KEYS = [_,...] labels the constraint with the unique variable _. In other words _ is a master key one can use to label constraints that share no other variable and that have to be combined together. The master key will never be assigned, hence it does not count for resumptionKEYS = [] is accepted with the following meaning: constraints with no key are never resumed automatically and are never combined with other constraintsBuiltin:
halt is now typed as variadic string prop and the strings passed are printed when the interpreter haltsAesthetic:
c0, c1, ... instead of x0, x1, ... to avoid ambiguity with X0, X1, ... on small/far-away screensAPI changes:
rename:
custom_constraints -> state (record field)syntactic_constraints -> constraints (type)CustomConstraint -> CustomState (module)add:
StrMap and StrSet: expose pp and showalias:
Data.Extend.solution ~ Data.solution (cast: Data.Extend.of_solution)Compilation:
Re_str -> Re.str)Misc:
Second public release, developed in tandem with coq-elpi and matita-elpi.
The programming language features syntactic constraints (suspended goals) and a meta language (inspired by CHR) to manipulate the constrain store.
There is an API for clients letting one drive the interpreter and extend the set of built-in predicates, register quotations and anti-quotations, etc.
The software is now built using findlib into a library. The standalone interpreter is just a regular client of the API.
First public release accompanying the paper ELPI: fast, Embeddable, λProlog Interpreter