Episteme.Builtins.Strings (Episteme v0.2.0)

Copy Markdown View Source

The atom/number/string conversion family: atom_codes/2 atom_chars/2 atom_length/2 atom_concat/3 char_code/2 number_codes/2 number_chars/2 upcase_atom/2 downcase_atom/2 atomic_list_concat/2,3 (classic ISO/de-facto predicates, working over atoms) plus atom_string/2 string_to_atom/2 string_concat/3 string_chars/2 string_codes/2 string_length/2 number_string/2 split_string/4 (SWI-style predicates producing/consuming real strings), all built on the shared atomic_text/1/require_atomic_text/2 "coerce an atomic term (atom, number, or real string) to its text" primitive. string/1's own type check lives in Episteme.Engine directly, alongside every other type check (atom/1, var/1, ...), not here.

atom_codes/2/number_codes/2/string_codes/2 produce plain Elixir charlists (String.to_charlist/1), which already are Episteme code lists -- no wrapping needed, same as everywhere else a Prolog list is just a native Elixir list. atom_chars/2/number_chars/2 instead produce single-character atoms (classic ISO char_list semantics), while string_chars/2 produces single-character strings -- the two are not interchangeable.

Summary

Functions

Atomic's text, if it's an atom, a number, or a real string -- :error for anything else (a compound, a list, or an unbound variable -- callers needing an instantiation_error specifically should check for %Var{} themselves before calling this, same as require_atomic_text/2 does).

Resolves term and returns its text, raising instantiation_error/type_error(atomic, _) as appropriate -- the shared entry point every predicate here uses to read a bound atomic argument.

Like require_atomic_text/2, but fails (instead of raising type_error) for an unbound variable -- callers that already have their own instantiation-error handling, or that want a plain proper-list-of-elements shape check first.

Unifies every {term, value} pair against bindings in order, failing outright the moment one doesn't -- the shared "generate one candidate, let unify filter it" tail every enumerating predicate here (atom_concat/3, string_concat/3, sub_atom/5) ends in.

Functions

atomic_text(a)

@spec atomic_text(term()) :: {:ok, String.t()} | :error

Atomic's text, if it's an atom, a number, or a real string -- :error for anything else (a compound, a list, or an unbound variable -- callers needing an instantiation_error specifically should check for %Var{} themselves before calling this, same as require_atomic_text/2 does).

dispatch(arg1, arg2, arg3)

@spec dispatch(atom(), non_neg_integer(), [term()]) ::
  Ichor.Backtrack.goal() | :not_handled

require_atomic_text(term, bindings)

@spec require_atomic_text(term(), Ichor.Backtrack.Bindings.t()) :: String.t()

Resolves term and returns its text, raising instantiation_error/type_error(atomic, _) as appropriate -- the shared entry point every predicate here uses to read a bound atomic argument.

unify_goal(a, b, bindings)

Like require_atomic_text/2, but fails (instead of raising type_error) for an unbound variable -- callers that already have their own instantiation-error handling, or that want a plain proper-list-of-elements shape check first.

unify_pairs(pairs, bindings)

@spec unify_pairs([{term(), term()}], Ichor.Backtrack.Bindings.t()) ::
  Ichor.Backtrack.Tree.t()

Unifies every {term, value} pair against bindings in order, failing outright the moment one doesn't -- the shared "generate one candidate, let unify filter it" tail every enumerating predicate here (atom_concat/3, string_concat/3, sub_atom/5) ends in.