Skip to content

v0.7.0

Choose a tag to compare

@github-actions github-actions released this 13 Aug 18:56
· 164 commits to main since this release

Added

  • Rational numbers: 1r3 literals in the Extended and Modern modes (strict ISO lexing is
    unchanged), rdiv/2 as a 400 yfx operator, exact arithmetic mixing integers and rationals
    with float contagion, rounding functions over rationals, the numerator/1, denominator/1,
    rational/1, and rationalize/1 evaluables, the rational/1 type test, must_be(rational, X),
    number conversion of the NrM spelling, standard-order ranking beside integers, and canonical
    demotion so a denominator of 1 is always an integer. Rationals reach both execution paths and
    the embedding API (PrologRational, PrologInput.Rational), and are verified against
    SWI-Prolog by the differential corpus.

  • Unbounded integers: arithmetic promotes past the 60-bit tagged range to interned big
    integers and normalizes back when results fit, literals of any length read to their exact value
    in source text and runtime term input, and number conversion, formatting (~d, ~D, ~r,
    ~R), ordering, first-argument indexing, the dynamic database, generated C#, and the embedding
    API (PrologBigInteger, PrologInput.Big, PrologMarshal.ToBigInteger) all carry the new
    representation. The bounded flag is now false; max_integer and min_integer keep
    reporting the fixnum promotion threshold. evaluation_error(int_overflow) and
    representation_error(max_integer|min_integer) no longer occur; a shift count or exponent
    whose result would exceed the representation raises resource_error(memory). Verified against
    SWI-Prolog by the differential corpus; the pinned independent ISO corpus now counts 763
    applicable declarations, with five bounded-arithmetic cases correctly gated out by their
    upstream condition(current_prolog_flag(bounded, true)) option.

  • print_message/2 with SWI's message system sized to this machine: the message term is
    translated to Format-Args lines, a user-defined message_hook/3 may intercept them, and what
    remains is written to user_error behind SWI's kind prefixes (ERROR: , Warning: , % ).
    The error(Formal, Context) translations follow SWI 10's wording — including the culprit
    classification of type errors and the special-cased permission and existence messages — and are
    verified against SWI-Prolog by the differential corpus. silent and debug(_) messages are
    not printed; SWI's source-location and thread decorations are not reproduced.

  • A string term type: "..." reads as a distinct interned string under
    set_prolog_flag(double_quotes, string) — an extension value available in the Extended and
    Modern modes and gated out of StrictIso; no mode defaults to it. string/1 is true of a
    string, atom/1 false, atomic/1 true; unification is identity; write/1 emits the bare text
    and writeq/1 the "..." spelling with ISO escapes; the standard order places strings between
    numbers and atoms, as SWI-Prolog 10 sorts them. Strings survive assertz/1, findall/3,
    copy_term/2, nb_setval/2, build-time compiled code, and the embedding API (PrologString),
    and the DotPrologFlags/--flag override surface accepts double_quotes=string.

  • The string library: string_length/2, string_concat/3 with split enumeration,
    atom_string/2, string_to_atom/2, string_chars/2, string_codes/2, number_string/2,
    term_string/2, sub_string/5, split_string/4, string_code/3, string_lower/2,
    string_upper/2; string(S) sinks for format/3 and with_output_to/2; ~s and format
    text accepting strings; and must_be(string, X) with text admitting strings. Verified
    against SWI-Prolog by the differential corpus. The atom predicates deliberately keep ISO's
    type_error(atom, …) for strings.

  • The SWI-aligned library surface: library(error) (must_be/2, is_of_type/2, and the
    error-raising helpers), library(assoc) as AVL trees, library(ordsets), foldl/6,
    findall/4, numbervars/3, atom_to_term/3, and tab/2 — available in the Extended and
    Modern modes, rejected by StrictIso.

  • A SWI compatibility ledger recording, feature by feature,
    which parts of the SWI-Prolog surface the extended modes implement, which are later roadmap
    phases, and which are out of charter.

  • More SWI-aligned predicates: del_assoc/4, transpose_pairs/2, ord_union/2,
    ord_intersection/2, aggregate/3,4 and aggregate_all/4 for the simple specs, variant/2,
    ?=/2, char_type/2 and code_type/2 for bound characters, between/3 with an inf upper
    bound, and the ~r/~R radix format directives.

  • An opt-in differential suite that runs a shared goal corpus against a locally installed
    SWI-Prolog and asserts the outputs agree (DOTPROLOG_RUN_SWI_DIFFERENTIAL_TESTS=1); the corpus
    also runs unconditionally against DotProlog alone.

  • Engine-scoped global variables: nb_setval/2 and nb_getval/2 store and read a detached copy
    that survives backtracking, while b_setval/2 and b_getval/2 hold the live term and the
    assignment is undone when execution backtracks past it, including through catch/3 and at the
    end of the top-level goal.

  • setup_call_cleanup/3 and call_cleanup/2: the cleanup runs exactly once on deterministic
    exit (including the redo that exhausts the alternatives), failure, or a thrown ball, with SWI's
    ball precedence. A surrounding cut that discards pending alternatives does not fire the
    deferred cleanup; once(Goal) gives commit semantics.

  • setarg/3 and nb_setarg/3: destructive argument assignment, undone on backtracking for the
    first form through a value-undo stack interleaved with trail unwinding. nb_setarg/3 accepts
    atomic replacement values only, which the counter idiom needs and heap truncation allows.

  • The occurs_check flag (false, true, error) in the Extended and Modern modes,
    guarding general unification with SWI's occurs_check(Var, Term) error term. Write-mode head
    unification is a documented unchecked window; StrictIso keeps the ISO flag set unchanged.

  • A natural-language processing sample in Modern mode (samples/NaturalLanguage), and the
    DotProlog logo on the project landing pages.

  • nb_current/2, which fails for an unset name and enumerates the set variables when the name
    is unbound; ord_seteq/2 and ord_symdiff/3, completing library(ordsets); and the witnessed
    max/2 and min/2 aggregation specs across aggregate/3,4 and aggregate_all/3,4, which
    compare arithmetically, keep the first solution on a tie, and answer max(Value, Witness) /
    min(Value, Witness). All verified against SWI-Prolog by the differential corpus.

  • The rest of SWI's library(assoc) surface: is_assoc/1, gen_assoc/3, get_assoc/5,
    map_assoc/2,3, del_min_assoc/4, and del_max_assoc/4.

  • Compound aggregation templates: aggregate_all(r(sum(X), count), Goal, r(Sum, Count)) and the
    same shape in aggregate/3,4 and aggregate_all/4, each template argument a spec, with SWI's
    instantiation, type, and domain errors for invalid templates.

  • The ~@ and ~W format directives: ~@ runs a goal once and inserts its output in place —
    a failing or throwing goal still emits the text before it, as SWI's streaming does — and ~W
    writes a term under a write_term/2 option list. write_term itself gains SWI's
    spacing(standard|next_argument) option.

  • portray_clause/1,2 with SWI's listing layout — one goal per line, bracketed disjunction,
    if-then-else, and soft-cut blocks, A, B, ... variable names, _ singletons — byte-identical
    to SWI-Prolog 10 for the covered constructs, pinned by the differential corpus.

  • char_type/2 and code_type/2 enumerate an unbound character over a bound type in code
    order; characters are UTF-16 code units, so Unicode-wide classes cover the BMP.

  • term_size/2: the cells of a detached copy of a term, counting shared subterms once per
    occurrence and raising representation_error(cyclic_term) for a cyclic one.

  • Project-level initial flag overrides: the DotPrologFlags property in a .dplproj (and the
    repeatable --flag option on dotnet prolog run and lint) layers an initial flag value over
    the language mode, e.g. double_quotes=chars while staying in extended mode. The mode remains
    the curated profile; double_quotes (codes, chars, atom) is the first overridable flag.
    Generated code records the initial double_quotes value and refuses to install into an engine
    that starts elsewhere, the same way it already guards the language mode.

Fixed

  • Meta-called control goals now operate on the caller's live terms: the runtime lowering compiles
    only the control skeleton and passes every leaf-goal argument through a register instead of
    rebuilding bound terms, which destructive assignment made observable.
  • A compiled predicate that lowered a meta-called control goal could crash the dispatch loop with
    an index error when appending the lowered bytecode grew the program's code array; the loop now
    refreshes its cached arrays after compiled execution returns.
  • A build-time-compiled source containing :- set_prolog_flag(double_quotes, ...) no longer leaks
    that value into the host engine when its generated Install replays the directive: the flag is
    restored to its entering value afterwards, matching what consulting the same file leaves behind.

Changed

  • An aggregation template that is unknown (aggregate_all(foo, ...)), a variable, or a compound
    mixing specs with other terms now raises the error SWI raises instead of failing silently.
  • char_type/2 and code_type/2 with an unbound character now enumerate instead of raising an
    instantiation error; the error remains when the type is unbound.
  • Modern mode is chartered as the SWI-aligned dialect: an ISO-conforming core, double_quotes
    seeded at chars, and SWI-Prolog as the documented reference for extension behavior.
  • Documentation no longer states that ISO/IEC 13211-1 fixes the initial double_quotes value at
    codes; the standard leaves it implementation defined (7.11.2.5), and codes is DotProlog's
    documented choice for the Extended and StrictIso modes.