eyeprolog 0.5.13 → 0.5.15
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +2 -0
- package/conformance-report.md +2 -2
- package/examples/auroracare.pl +26 -0
- package/examples/bmi.pl +20 -1
- package/examples/cdcl-sat-solver.pl +6 -6
- package/examples/composition-of-injective-functions-is-injective.pl +4 -1
- package/examples/deep-taxonomy-10.pl +2 -0
- package/examples/deep-taxonomy-100.pl +2 -0
- package/examples/deep-taxonomy-1000.pl +2 -0
- package/examples/deep-taxonomy-10000.pl +2 -0
- package/examples/exoplanet-validation-worlds.pl +3 -0
- package/examples/family-cousins.pl +2 -0
- package/examples/fastpow.pl +6 -6
- package/examples/flandor.pl +14 -0
- package/examples/gd-step-certified.pl +3 -0
- package/examples/group-inverse-uniqueness.pl +9 -9
- package/examples/illegitimate-reasoning.pl +6 -0
- package/examples/input/odrl-dpv-fpv-trust-flow-rules.pl +3 -9
- package/examples/list-collection.pl +6 -6
- package/examples/lldm.pl +2 -0
- package/examples/odrl-dpv-fpv-trust-flow.pl +3 -9
- package/examples/output/aliases-and-namespaces.pl +1 -1
- package/examples/output/bmi.pl +9 -0
- package/examples/output/dijkstra-findall-sort.pl +1 -1
- package/examples/output/dijkstra.pl +16 -16
- package/examples/output/drone-corridor-planner.pl +17 -17
- package/examples/output/iso-atomic-conversion.pl +1 -1
- package/examples/output/list-collection.pl +6 -6
- package/examples/pointer-analysis.pl +3 -0
- package/examples/proof/aliases-and-namespaces.pl +5 -5
- package/examples/proof/composition-of-injective-functions-is-injective.pl +80 -97
- package/examples/proof/graph-reachability.pl +22 -22
- package/examples/proof/group-inverse-uniqueness.pl +4 -4
- package/examples/proof/list-collection.pl +73 -29
- package/examples/proof/spacecraft-battery-diagnosis.pl +8 -8
- package/examples/proof/term-tools.pl +1 -1
- package/examples/relational-cube-lookup.pl +2002 -2000
- package/examples/riemann-hypothesis.pl +5 -0
- package/examples/spacecraft-battery-diagnosis.pl +8 -8
- package/examples/vulnerability-impact.pl +4 -0
- package/index.d.ts +5 -2
- package/package.json +1 -1
- package/src/cli.js +17 -9
- package/src/index.js +15 -5
- package/src/iso.js +1 -0
- package/src/parser.js +57 -12
- package/src/program.js +8 -5
- package/src/solver.js +11 -3
- package/src/term.js +41 -10
- package/src/write.js +6 -0
- package/test/conformance/README.md +1 -1
- package/test/conformance/cases/arithmetic/082_comparison_semantics.pl +2 -2
- package/test/conformance/cases/arithmetic/extra_le_equal_string.pl +1 -1
- package/test/conformance/cases/context/extra_context_ignores_string_parts.pl +1 -1
- package/test/conformance/cases/iso/double_quoted_lists.pl +27 -0
- package/test/conformance/cases/strings/023_quoted_escapes_readback.pl +2 -3
- package/test/conformance/cases/terms/003_terms_and_readback.pl +1 -1
- package/test/conformance/cases/terms/073_term_introspection_edges.pl +1 -1
- package/test/conformance/cases/terms/096_functor_scalar_edges.pl +2 -2
- package/test/conformance/cases/terms/extra_functor_string_scalar.pl +1 -1
- package/test/conformance/cases/terms/functor_number_and_string.pl +1 -1
- package/test/conformance/cases/unification/extra_eq_scalar_string_number.pl +1 -1
- package/test/conformance/cases/unification/scalar_cross_type_same_lexical_value.pl +2 -2
- package/test/conformance/expected/aggregation/044_findall_user_goal.pl +1 -1
- package/test/conformance/expected/arithmetic/082_comparison_semantics.pl +1 -1
- package/test/conformance/expected/arithmetic/extra_le_equal_string.pl +1 -1
- package/test/conformance/expected/context/extra_context_atom_parts.pl +1 -1
- package/test/conformance/expected/context/extra_context_ignores_string_parts.pl +1 -0
- package/test/conformance/expected/context/extra_context_list_parts.pl +1 -1
- package/test/conformance/expected/iso/atomic_term_processing.pl +1 -1
- package/test/conformance/expected/iso/double_quoted_lists.pl +8 -0
- package/test/conformance/expected/iso/exceptions_and_flags.pl +1 -1
- package/test/conformance/expected/iso/grouped_solutions_and_clauses.pl +1 -1
- package/test/conformance/expected/iso/logtalk_atom_chars.pl +1 -1
- package/test/conformance/expected/iso/logtalk_number_chars.pl +1 -1
- package/test/conformance/expected/iso/logtalk_prolog_flags.pl +1 -1
- package/test/conformance/expected/iso/logtalk_univ.pl +1 -1
- package/test/conformance/expected/iso/scryer_lexical_terms.pl +1 -1
- package/test/conformance/expected/lists/005_list_deconstruction.pl +1 -1
- package/test/conformance/expected/lists/031_lists_aggregation_ordering.pl +4 -4
- package/test/conformance/expected/lists/035_list_relations.pl +3 -3
- package/test/conformance/expected/lists/036_append_splits.pl +3 -3
- package/test/conformance/expected/lists/045_sort_deduplicates_atoms.pl +1 -1
- package/test/conformance/expected/lists/046_append_bound_prefix_suffix.pl +2 -2
- package/test/conformance/expected/lists/048_set_nth0_edges.pl +2 -2
- package/test/conformance/expected/lists/049_select_duplicate_occurrences.pl +2 -2
- package/test/conformance/expected/lists/067_list_edges.pl +1 -1
- package/test/conformance/expected/lists/068_list_generation_order.pl +6 -6
- package/test/conformance/expected/lists/084_append_and_select_composition.pl +9 -9
- package/test/conformance/expected/lists/085_nth_and_update_edges.pl +1 -1
- package/test/conformance/expected/lists/087_sort_reverse_length.pl +2 -2
- package/test/conformance/expected/lists/extra_append_all_splits_three.pl +4 -4
- package/test/conformance/expected/lists/extra_list_to_set_stable_order.pl +1 -1
- package/test/conformance/expected/lists/extra_reverse_nested_terms.pl +1 -1
- package/test/conformance/expected/lists/extra_slice_end.pl +1 -1
- package/test/conformance/expected/lists/extra_take_all.pl +1 -1
- package/test/conformance/expected/lists/list_pattern_last.pl +1 -1
- package/test/conformance/expected/lists/select_all_occurrences.pl +3 -3
- package/test/conformance/expected/lists/set_nth0_middle.pl +1 -1
- package/test/conformance/expected/rules/077_recursive_path_with_lists.pl +3 -3
- package/test/conformance/expected/strings/023_quoted_escapes_readback.pl +1 -1
- package/test/conformance/expected/strings/071_string_edges.pl +1 -1
- package/test/conformance/expected/strings/extra_split_empty_separator.pl +1 -1
- package/test/conformance/expected/terms/003_terms_and_readback.pl +3 -3
- package/test/conformance/expected/terms/065_reusable_term_control_builtins.pl +1 -1
- package/test/conformance/expected/terms/073_term_introspection_edges.pl +2 -2
- package/test/conformance/expected/terms/095_term_introspection_roundtrip.pl +1 -1
- package/test/conformance/expected/terms/096_functor_scalar_edges.pl +1 -1
- package/test/conformance/expected/terms/extra_compound_name_arguments_decompose_list.pl +1 -1
- package/test/conformance/expected/terms/extra_functor_string_scalar.pl +1 -1
- package/test/conformance/expected/terms/functor_number_and_string.pl +1 -1
- package/test/conformance/expected/unification/012_nested_compound_unification.pl +1 -1
- package/test/conformance/expected/unification/034_equality_and_inequality.pl +1 -1
- package/test/conformance/expected/unification/extra_eq_list_tail_binding.pl +1 -1
- package/test/conformance/expected/unification/list_tail_binding.pl +1 -1
- package/test/conformance/expected-proofs/proofs/bindings_nested_term.pl +5 -5
- package/test/conformance/expected-proofs/proofs/extra_compound_name_arguments.pl +4 -4
- package/test/conformance/expected-proofs/proofs/extra_findall_builtin.pl +5 -5
- package/test/conformance/expected-proofs/proofs/extra_nested_list_binding.pl +5 -5
- package/test/conformance/expected-proofs/proofs/extra_once_member.pl +2 -2
- package/test/conformance/expected-proofs/proofs/list_builtin.pl +1 -1
- package/test/run-playground.mjs +2 -2
- package/test/run-regression.mjs +69 -11
- package/the-art-of-eyeprolog.md +297 -38
package/test/run-regression.mjs
CHANGED
|
@@ -142,7 +142,7 @@ why(
|
|
|
142
142
|
bindings([binding("X", a)]),
|
|
143
143
|
uses([
|
|
144
144
|
proof(
|
|
145
|
-
goal(member(a,
|
|
145
|
+
goal(member(a, "a")),
|
|
146
146
|
by(library(member, 2))
|
|
147
147
|
)
|
|
148
148
|
])
|
|
@@ -491,18 +491,22 @@ why(
|
|
|
491
491
|
const univPath = path.join(tmp, `read-univ-${++tmpCounter}.term`);
|
|
492
492
|
const customPath = path.join(tmp, `read-custom-${++tmpCounter}.term`);
|
|
493
493
|
const invalidPath = path.join(tmp, `read-invalid-${++tmpCounter}.term`);
|
|
494
|
+
const quotesPath = path.join(tmp, `read-quotes-${++tmpCounter}.term`);
|
|
494
495
|
fs.writeFileSync(univPath, 'foo =.. [bar]/* term end */.\n');
|
|
495
496
|
fs.writeFileSync(customPath, 'alice likes bob.\n');
|
|
496
497
|
fs.writeFileSync(invalidPath, 'a..b.\n');
|
|
498
|
+
fs.writeFileSync(quotesPath, '"ab".\n');
|
|
497
499
|
const source = [
|
|
498
500
|
`read_univ(T) :- open(${sourceAtom(univPath)}, read, S, []), read(S, T), close(S).`,
|
|
499
501
|
`read_custom(T) :- op(500, xfx, likes), open(${sourceAtom(customPath)}, read, S, []), read(S, T), close(S).`,
|
|
500
502
|
`read_invalid(ok) :- open(${sourceAtom(invalidPath)}, read, S, []), catch(read(S, _), error(syntax_error(read_term), _), true), close(S).`,
|
|
503
|
+
`read_codes(ok) :- set_prolog_flag(double_quotes, codes), open(${sourceAtom(quotesPath)}, read, S, []), read(S, [97, 98]), close(S).`,
|
|
501
504
|
'',
|
|
502
505
|
].join('\n');
|
|
503
506
|
assertEqual(run(source, { goal: 'read_univ(T)' }).stdout, "read_univ('=..'(foo, [bar])).\n", 'univ term');
|
|
504
507
|
assertEqual(run(source, { goal: 'read_custom(T)' }).stdout, 'read_custom(likes(alice, bob)).\n', 'custom operator term');
|
|
505
508
|
assertEqual(run(source, { goal: 'read_invalid(ok)' }).stdout, 'read_invalid(ok).\n', 'invalid dotted term');
|
|
509
|
+
assertEqual(run(source, { goal: 'read_codes(ok)' }).stdout, 'read_codes(ok).\n', 'double_quotes read flag');
|
|
506
510
|
},
|
|
507
511
|
},
|
|
508
512
|
{
|
|
@@ -779,7 +783,7 @@ function apiCases() {
|
|
|
779
783
|
' assertz(edge(b, c)),',
|
|
780
784
|
' findall(Y, path(a, Y), After).',
|
|
781
785
|
].join('\n'));
|
|
782
|
-
assertEqual(result.stdout, 'test(
|
|
786
|
+
assertEqual(result.stdout, 'test("b", "bc").\n', 'stdout');
|
|
783
787
|
},
|
|
784
788
|
},
|
|
785
789
|
{
|
|
@@ -959,7 +963,7 @@ open(X) :- candidate(X), \\+ closed(X).
|
|
|
959
963
|
name: 'run loads the EyeProlog library by default',
|
|
960
964
|
run: () => {
|
|
961
965
|
const result = run('answer(X) :- append([a], [b], X).', { goal: 'answer(X)' });
|
|
962
|
-
assertEqual(result.stdout, 'answer(
|
|
966
|
+
assertEqual(result.stdout, 'answer("ab").\n', 'stdout');
|
|
963
967
|
},
|
|
964
968
|
},
|
|
965
969
|
{
|
|
@@ -969,7 +973,7 @@ open(X) :- candidate(X), \\+ closed(X).
|
|
|
969
973
|
const solver = new Solver(program);
|
|
970
974
|
const goal = parseGoalText('answer(X)');
|
|
971
975
|
const answers = [...solver.solve([goal], new Env(), 0)].map((env) => termToString(goal, env, true));
|
|
972
|
-
assertEqual(answers.join('\n'), 'answer(
|
|
976
|
+
assertEqual(answers.join('\n'), 'answer("ab")', 'answers');
|
|
973
977
|
},
|
|
974
978
|
},
|
|
975
979
|
{
|
|
@@ -1051,7 +1055,7 @@ open(X) :- candidate(X), \\+ closed(X).
|
|
|
1051
1055
|
assertEqual(fs.existsSync(path.join(packageRoot, 'src', 'eyeprolog-common-library.pl')), true, 'pure-Prolog common library exists');
|
|
1052
1056
|
assertEqual(fs.existsSync(path.join(packageRoot, 'src', 'library-source.js')), false, 'duplicate source loader is absent');
|
|
1053
1057
|
assertEqual(fs.existsSync(path.join(packageRoot, 'src', 'portable-library.js')), false, 'obsolete duplicate module remains absent');
|
|
1054
|
-
assertEqual(run(program, { goal: 'answer(X)' }).stdout, 'answer(
|
|
1058
|
+
assertEqual(run(program, { goal: 'answer(X)' }).stdout, 'answer("ab").\n', 'autoloaded append execution');
|
|
1055
1059
|
assertEqual(Boolean(program.findGroup('random', 3)), true, 'random/3 is autoloaded as a clause group');
|
|
1056
1060
|
},
|
|
1057
1061
|
},
|
|
@@ -1067,7 +1071,7 @@ portable_check(A, B, C) :- lowercase('HELLO', A), replace('banana', 'na', 'NA',
|
|
|
1067
1071
|
const solver = new Solver(program, { registry: createDefaultRegistry() });
|
|
1068
1072
|
const goal = parseGoalText('portable_check(A, B, C)');
|
|
1069
1073
|
const answers = [...solver.solve([goal], new Env(), 0)].map((env) => termToString(goal, env, true));
|
|
1070
|
-
assertEqual(answers.join('\n'),
|
|
1074
|
+
assertEqual(answers.join('\n'), 'portable_check(hello, baNANA, "xy")', 'ISO-only portable execution');
|
|
1071
1075
|
assertEqual(Boolean(program.findGroup('uuid', 3)), true, 'uuid/3 is implemented in the portable file');
|
|
1072
1076
|
assertEqual(program.findGroup('uuid', 1), null, 'obsolete uuid/1 is absent');
|
|
1073
1077
|
assertEqual(program.findGroup('local_time', 1), null, 'local_time/1 is absent from the library');
|
|
@@ -1085,9 +1089,9 @@ portable_check(A, B, C) :- lowercase('HELLO', A), replace('banana', 'na', 'NA',
|
|
|
1085
1089
|
'',
|
|
1086
1090
|
].join('\n'));
|
|
1087
1091
|
assertEqual(result.stdout, [
|
|
1088
|
-
'answer([],
|
|
1089
|
-
'answer(
|
|
1090
|
-
'answer(
|
|
1092
|
+
'answer([], "ab", 5, 9007199254740993).',
|
|
1093
|
+
'answer("a", "b", 5, 9007199254740993).',
|
|
1094
|
+
'answer("ab", [], 5, 9007199254740993).',
|
|
1091
1095
|
'',
|
|
1092
1096
|
].join('\n'), 'EyeProlog library behavior');
|
|
1093
1097
|
},
|
|
@@ -1197,14 +1201,68 @@ function whiteBoxCases() {
|
|
|
1197
1201
|
name: 'parser preserves list syntax readback',
|
|
1198
1202
|
run: () => {
|
|
1199
1203
|
const goal = parseGoalText('member(X, [a, b])');
|
|
1200
|
-
assertEqual(termToString(goal, new Env(), true), 'member(X,
|
|
1204
|
+
assertEqual(termToString(goal, new Env(), true), 'member(X, "ab")', 'goal');
|
|
1205
|
+
},
|
|
1206
|
+
},
|
|
1207
|
+
{
|
|
1208
|
+
name: 'double-quoted lists honor every ISO double_quotes value',
|
|
1209
|
+
run: () => {
|
|
1210
|
+
const chars = parseGoalText('p("aλ")').args[0];
|
|
1211
|
+
const charItems = properListItems(chars, new Env());
|
|
1212
|
+
assertEqual(charItems.map((item) => `${item.type}:${item.name}`).join('|'), 'atom:a|atom:λ', 'chars');
|
|
1213
|
+
|
|
1214
|
+
const codes = parseGoalText('p("aλ")', { doubleQuotes: 'codes' }).args[0];
|
|
1215
|
+
const codeItems = properListItems(codes, new Env());
|
|
1216
|
+
assertEqual(codeItems.map((item) => `${item.type}:${item.name}`).join('|'), 'number:97|number:955', 'codes');
|
|
1217
|
+
|
|
1218
|
+
const quotedAtom = parseGoalText('p("aλ")', { doubleQuotes: 'atom' }).args[0];
|
|
1219
|
+
assertEqual(`${quotedAtom.type}:${quotedAtom.name}`, 'atom:aλ', 'atom');
|
|
1220
|
+
},
|
|
1221
|
+
},
|
|
1222
|
+
{
|
|
1223
|
+
name: 'double_quotes directives affect subsequent source text',
|
|
1224
|
+
run: () => {
|
|
1225
|
+
const clauses = parseProgramText([
|
|
1226
|
+
'chars("a").',
|
|
1227
|
+
':- set_prolog_flag(double_quotes, codes).',
|
|
1228
|
+
'codes("a").',
|
|
1229
|
+
':- set_prolog_flag(double_quotes, atom).',
|
|
1230
|
+
'quoted_atom("a").',
|
|
1231
|
+
'',
|
|
1232
|
+
].join('\n'), { sourceMetadata: false });
|
|
1233
|
+
const facts = clauses.filter((clause) => clause.head.name !== ':-');
|
|
1234
|
+
assertEqual(termToString(facts[0].head), 'chars("a")', 'chars fact');
|
|
1235
|
+
assertEqual(termToString(facts[1].head, new Env(), true, { doubleQuotes: 'codes' }), 'codes("a")', 'codes fact');
|
|
1236
|
+
assertEqual(termToString(facts[2].head), 'quoted_atom(a)', 'atom fact');
|
|
1237
|
+
},
|
|
1238
|
+
},
|
|
1239
|
+
{
|
|
1240
|
+
name: 'double_quotes parser state flows across source files',
|
|
1241
|
+
run: () => {
|
|
1242
|
+
const program = Program.parseSources([
|
|
1243
|
+
':- set_prolog_flag(double_quotes, codes).',
|
|
1244
|
+
'value("A").',
|
|
1245
|
+
], { sourceMetadata: false });
|
|
1246
|
+
const value = program.findGroup('value', 1).clauses[0].head.args[0];
|
|
1247
|
+
assertEqual(properListItems(value, new Env())[0].name, '65', 'code in second source');
|
|
1248
|
+
assertEqual(program.doubleQuotes, 'codes', 'final parser flag');
|
|
1249
|
+
},
|
|
1250
|
+
},
|
|
1251
|
+
{
|
|
1252
|
+
name: 'parser double_quotes option flows into solver flags',
|
|
1253
|
+
run: () => {
|
|
1254
|
+
const result = run('answer(atom) :- atom("text").', {
|
|
1255
|
+
goal: 'answer(X)',
|
|
1256
|
+
doubleQuotes: 'atom',
|
|
1257
|
+
});
|
|
1258
|
+
assertEqual(result.stdout, 'answer(atom).\n', 'atom-mode execution');
|
|
1201
1259
|
},
|
|
1202
1260
|
},
|
|
1203
1261
|
{
|
|
1204
1262
|
name: 'parser accepts ISO-style uppercase variables',
|
|
1205
1263
|
run: () => {
|
|
1206
1264
|
const goal = parseGoalText('member(X, [a, b])');
|
|
1207
|
-
assertEqual(termToString(goal, new Env(), true), 'member(X,
|
|
1265
|
+
assertEqual(termToString(goal, new Env(), true), 'member(X, "ab")', 'goal');
|
|
1208
1266
|
},
|
|
1209
1267
|
},
|
|
1210
1268
|
{
|
package/the-art-of-eyeprolog.md
CHANGED
|
@@ -447,7 +447,8 @@ grandparents, then only the grandparents of `diego`.
|
|
|
447
447
|
Prolog programs accepted by EyeProlog are built from terms:
|
|
448
448
|
|
|
449
449
|
- atom constants: `ada`, `accepted`, `'atom with spaces'`;
|
|
450
|
-
-
|
|
450
|
+
- double-quoted character lists: `"sensor too hot"` (the default shorthand for
|
|
451
|
+
`[s,e,n,s,o,r,' ',t,o,o,' ',h,o,t]`);
|
|
451
452
|
- numbers: `42`, `-7`, `3.14159`, `1.2e3`;
|
|
452
453
|
- variables: `X`, `Person`, `_temporary`;
|
|
453
454
|
- compound terms: `point(3, 4)`, `reading(temp, 91)`;
|
|
@@ -504,8 +505,9 @@ route(a, d, path([a, b, d], cost(9))).
|
|
|
504
505
|
As a fact head, `measurement(...)` is an atomic formula. Nested terms are data.
|
|
505
506
|
The same surface form serves both roles; context decides which.
|
|
506
507
|
|
|
507
|
-
`ready` is an atom constant and `"ready"` is a
|
|
508
|
-
|
|
508
|
+
`ready` is an atom constant and `"ready"` is, by default, a proper list of
|
|
509
|
+
one-character atoms. Keep symbolic vocabulary as atoms and use character lists
|
|
510
|
+
when text must be inspected relationally. Quoted atoms remain atoms:
|
|
509
511
|
|
|
510
512
|
```eyeprolog
|
|
511
513
|
label(sensor_1, "Cabin temperature").
|
|
@@ -632,7 +634,7 @@ book rather than appearing only as historical attribution.
|
|
|
632
634
|
The declarative reading needs a precise answer to a deceptively simple
|
|
633
635
|
question: what can a term denote? EyeProlog uses **Herbrand semantics**. Its
|
|
634
636
|
universe contains exactly the ground terms that can be constructed from the
|
|
635
|
-
program's atom constants,
|
|
637
|
+
program's atom constants, numbers, list constructors, and compound
|
|
636
638
|
functors. There are no unnamed elements hiding behind the notation. A ground
|
|
637
639
|
term denotes itself.
|
|
638
640
|
|
|
@@ -1179,10 +1181,9 @@ normalized(Input, Words) :-
|
|
|
1179
1181
|
|
|
1180
1182
|
Conversions include `number_string/2`, `atom_string/2`, and `term_string/2`.
|
|
1181
1183
|
Pattern operations include `contains/2`, `matches/2`, and named-capture
|
|
1182
|
-
`matches/3`. Turn text into structured terms early
|
|
1183
|
-
relational. Double-quoted
|
|
1184
|
-
|
|
1185
|
-
API.
|
|
1184
|
+
`matches/3`. Turn text into structured terms early and keep central rules
|
|
1185
|
+
relational. Double-quoted source notation follows the ISO `double_quotes` flag;
|
|
1186
|
+
it does not create a separate Prolog string type.
|
|
1186
1187
|
|
|
1187
1188
|
Parenthesized comma terms can serve as context data:
|
|
1188
1189
|
|
|
@@ -4868,9 +4869,9 @@ Atomic conversion predicates expose reversible representations:
|
|
|
4868
4869
|
- `char_code/2` converts one character; and
|
|
4869
4870
|
- `number_chars/2` and `number_codes/2` parse or render ISO numbers.
|
|
4870
4871
|
|
|
4871
|
-
These are atom relations,
|
|
4872
|
-
|
|
4873
|
-
|
|
4872
|
+
These are atom relations, distinct from the EyeProlog library predicates whose
|
|
4873
|
+
historical names contain `string`. Quoted atoms such as `'λ'` remain atoms;
|
|
4874
|
+
with the default flag, `"λ"` denotes the character list `['λ']`.
|
|
4874
4875
|
|
|
4875
4876
|
[`iso-reflective-terms.pl`](https://github.com/eyereasoner/eyeprolog/blob/main/examples/iso-reflective-terms.pl)
|
|
4876
4877
|
walks through shape, rebuilding, fresh copying, variables, and order.
|
|
@@ -5043,23 +5044,23 @@ conforming processor.
|
|
|
5043
5044
|
Prolog source accepted by EyeProlog is UTF-8. `%` starts a line comment and
|
|
5044
5045
|
`/* ... */` delimits a block comment. Plain atoms begin with a
|
|
5045
5046
|
lowercase ASCII letter. Variables begin with uppercase or underscore. The bare
|
|
5046
|
-
`_` is fresh each time. Single quotes delimit quoted atoms; double quotes
|
|
5047
|
-
|
|
5047
|
+
`_` is fresh each time. Single quotes delimit quoted atoms; double quotes use
|
|
5048
|
+
ISO double-quoted-list notation. Integers, decimals, scientific notation, binary/octal/
|
|
5048
5049
|
hexadecimal integers, and character-code constants are accepted.
|
|
5049
5050
|
|
|
5050
5051
|
Unquoted names deliberately use ASCII spelling. Unicode belongs inside quoted
|
|
5051
|
-
atoms and
|
|
5052
|
+
atoms and double-quoted lists:
|
|
5052
5053
|
|
|
5053
5054
|
```eyeprolog
|
|
5054
5055
|
city('München').
|
|
5055
5056
|
message("café").
|
|
5056
5057
|
```
|
|
5057
5058
|
|
|
5058
|
-
Inside a quoted atom, a single quote is doubled: `'don''t'`.
|
|
5059
|
+
Inside a quoted atom, a single quote is doubled: `'don''t'`. Double-quoted lists support
|
|
5059
5060
|
the common escapes `\n`, `\t`, `\"`, and `\\`. Whitespace is insignificant
|
|
5060
5061
|
between tokens, and a `%` comment continues to the end of its line. Doubling
|
|
5061
5062
|
the active delimiter is also accepted inside either quoted form, so `""`
|
|
5062
|
-
inside
|
|
5063
|
+
inside double-quoted notation denotes one literal double quote character.
|
|
5063
5064
|
|
|
5064
5065
|
Graphic atoms may contain `#$&*+-/<=>@^~\;`. Colon names and unquoted
|
|
5065
5066
|
angle-bracket IRIs are not syntax; quote names containing such punctuation.
|
|
@@ -5074,11 +5075,12 @@ clause ::= head "."
|
|
|
5074
5075
|
| head ":-" goal-list "."
|
|
5075
5076
|
head ::= term
|
|
5076
5077
|
goal-list ::= term { "," term }
|
|
5077
|
-
term ::= variable | atom-constant |
|
|
5078
|
+
term ::= variable | atom-constant | double-quoted-list | number
|
|
5078
5079
|
| compound | list | curly-term | parenthesized-term
|
|
5079
5080
|
compound ::= atom-constant "(" term { "," term } ")"
|
|
5080
5081
|
list ::= "[" "]"
|
|
5081
5082
|
| "[" term { "," term } [ "|" term ] "]"
|
|
5083
|
+
double-quoted-list ::= '"' { quoted-character } '"'
|
|
5082
5084
|
curly-term ::= "{}" | "{" term "}"
|
|
5083
5085
|
parenthesized-term ::= "(" term [ "," term { "," term } ] ")"
|
|
5084
5086
|
variable ::= "_"
|
|
@@ -5221,19 +5223,257 @@ contains 115 name/arity entries across 94 names.
|
|
|
5221
5223
|
`false/0` and `fail/0` both fail as goals. `false/0` is a protected static
|
|
5222
5224
|
procedure and cannot be defined by source clauses or declared dynamic.
|
|
5223
5225
|
|
|
5226
|
+
### Reading the built-in reference
|
|
5227
|
+
|
|
5228
|
+
The call patterns below use `+` for an argument that must be sufficiently
|
|
5229
|
+
instantiated, `-` for a result normally produced by the call, and `?` for an
|
|
5230
|
+
argument that may be supplied or returned. These are principal operational
|
|
5231
|
+
modes, not a separate mode system enforced by the parser. A call described as
|
|
5232
|
+
*semidet* succeeds at most once; a *nondet* call may yield further answers on
|
|
5233
|
+
backtracking. Unless stated otherwise, checking a result that does not unify
|
|
5234
|
+
simply fails.
|
|
5235
|
+
|
|
5236
|
+
Built-in dispatch is authoritative and built-in procedures cannot be modified
|
|
5237
|
+
through the dynamic database predicates. Source clauses with the same indicator
|
|
5238
|
+
do not replace a built-in implementation. `clause/2` and `op/3` are the two
|
|
5239
|
+
dispatch exceptions: when a program defines a source predicate with that same
|
|
5240
|
+
indicator, EyeProlog uses the source clauses. `false/0` is stricter still and is
|
|
5241
|
+
rejected as a source-clause head. Portable programs should avoid every such
|
|
5242
|
+
collision because other Prolog systems commonly reject it while loading.
|
|
5243
|
+
|
|
5244
|
+
### Control, search, and exceptions
|
|
5245
|
+
|
|
5246
|
+
| Predicate and principal call | Behavior |
|
|
5247
|
+
| --- | --- |
|
|
5248
|
+
| `true` | Succeeds once without binding variables. |
|
|
5249
|
+
| `fail`, `false` | Always fail. `false/0` is provided as a compatibility alias and is also forbidden as a source-clause head. |
|
|
5250
|
+
| `!` | Commits to choices made since entry into the current predicate invocation. It does not erase alternatives belonging to an enclosing caller. |
|
|
5251
|
+
| `call(+Goal)` | Calls an atom or compound goal. An unbound argument raises *instantiation_error*; another non-callable term raises *type_error(callable)*. |
|
|
5252
|
+
| `\+(+Goal)` | Negation as finite failure. It succeeds once when `Goal` has no solution and never exports bindings made while testing `Goal`. Bind variables needed by the test first. |
|
|
5253
|
+
| `once(+Goal)` | Returns only the first solution of `Goal`, or fails when there is none. |
|
|
5254
|
+
| `repeat` | Produces an unbounded sequence of successes; normally paired with a test, cut, exception, or `halt/0`. |
|
|
5255
|
+
| `Left ; Right` | Enumerates `Left`, then `Right`, restoring the incoming environment between branches. |
|
|
5256
|
+
| `If -> Then` | Commits to the first solution of `If` and runs `Then`; it does not provide an else branch by itself. |
|
|
5257
|
+
| `(If -> Then ; Else)` | Runs `Then` from the first solution of `If`, otherwise runs `Else`. Alternatives of `If` are discarded. |
|
|
5258
|
+
| `catch(+Goal,?Catcher,+Recovery)` | Runs `Goal`; on a matching thrown ball or `PrologError`, unifies it with `Catcher` and calls `Recovery`. Runtime errors are exposed as *error(Formal,eyeprolog)*. |
|
|
5259
|
+
| `throw(+Ball)` | Throws a copied nonvariable term. An unbound ball raises `instantiation_error`. |
|
|
5260
|
+
| `halt`, `halt(+Status)` | Stops the processor with status `0` or the supplied integer. The JavaScript API reports the status without terminating its host process. |
|
|
5261
|
+
|
|
5262
|
+
`;/2` recognizes an `->/2` term on its left and implements the ISO
|
|
5263
|
+
if-then-else commitment described above. Cuts and committed conditions are
|
|
5264
|
+
operational controls; use ordinary relations when all alternatives should
|
|
5265
|
+
remain observable.
|
|
5266
|
+
|
|
5267
|
+
### Unification, type tests, and term order
|
|
5268
|
+
|
|
5269
|
+
| Predicate and principal call | Behavior |
|
|
5270
|
+
| --- | --- |
|
|
5271
|
+
| `?Left = ?Right` | Unifies two terms and returns the resulting bindings. EyeProlog rejects direct and indirect cyclic bindings. |
|
|
5272
|
+
| `unify_with_occurs_check(?Left,?Right)` | Performs occurs-check-safe unification. Because ordinary EyeProlog unification is already cycle-safe, it has the same successful bindings as `=/2`. |
|
|
5273
|
+
| `?Left \= ?Right` | Succeeds only when the terms cannot unify at call time. It is a test, not a delayed disequality constraint. |
|
|
5274
|
+
| `?Left == ?Right`, `?Left \== ?Right` | Test term identity or non-identity without binding variables. Two distinct unbound variables are not identical. |
|
|
5275
|
+
| `var(?Term)`, `nonvar(?Term)` | Test whether the dereferenced term is or is not an unbound variable. |
|
|
5276
|
+
| `atom(?Term)`, `integer(?Term)`, `float(?Term)`, `number(?Term)` | Test the corresponding scalar category. Integer values retain arbitrary precision; finite noninteger numeric values are floats. |
|
|
5277
|
+
| `atomic(?Term)`, `compound(?Term)`, `callable(?Term)`, `ground(?Term)` | Test for an ISO atomic term, a compound, a callable atom/compound, or a term containing no unbound variables. A default double-quoted value is a list and is therefore compound unless it is empty. |
|
|
5278
|
+
| `compare(?Order,+Left,+Right)` | Unifies `Order` with `<`, `=`, or `>` according to profile term order. A supplied order must be one of those atoms. |
|
|
5279
|
+
| `Left @< Right`, `Left @=< Right`, `Left @> Right`, `Left @>= Right` | Compare terms without arithmetic evaluation or bindings. These calls are semidet. |
|
|
5280
|
+
|
|
5281
|
+
For ISO terms, the profile term order is variables, numbers, atoms, then compounds;
|
|
5282
|
+
compound terms compare by arity, functor, and arguments. Within the numeric
|
|
5283
|
+
category, floats precede integers; floats compare by finite numeric value and
|
|
5284
|
+
integers compare exactly. This is intentionally documented as EyeProlog's
|
|
5285
|
+
profile order rather than claimed as the complete ISO term order. Host-created
|
|
5286
|
+
RDF lexical strings are an internal extension ranked between atoms and
|
|
5287
|
+
compounds; double-quoted Prolog source never creates that extension.
|
|
5288
|
+
|
|
5289
|
+
### Term construction and inspection
|
|
5290
|
+
|
|
5291
|
+
| Predicate and principal call | Behavior |
|
|
5292
|
+
| --- | --- |
|
|
5293
|
+
| `functor(+Term,?Name,?Arity)` | Decomposes a term. Scalars have arity zero. |
|
|
5294
|
+
| `functor(-Term,+Name,+Arity)` | Constructs a scalar when `Arity` is zero or a compound with fresh arguments otherwise. Arity must be a nonnegative representable integer and a positive-arity name must be an atom. |
|
|
5295
|
+
| `arg(+Index,+Term,?Argument)` | Selects the one-based argument of a compound. Index zero or an index beyond the arity fails; a negative index is a domain error. |
|
|
5296
|
+
| `?Term =.. ?List` | Converts a term to `[Functor\|Arguments]` or constructs a term from a nonempty proper list. A one-item list constructs its atomic item. |
|
|
5297
|
+
| `copy_term(+Term,-Copy)` | Copies the dereferenced term while replacing every distinct unbound variable with a fresh variable and preserving variable sharing. |
|
|
5298
|
+
| `term_variables(+Term,?Variables)` | Returns distinct variables in first-occurrence traversal order. A supplied result may be a proper or partial list. |
|
|
5299
|
+
|
|
5300
|
+
Construction calls raise `instantiation_error` when neither side supplies the
|
|
5301
|
+
required shape. `=../2` distinguishes an incomplete list
|
|
5302
|
+
(`instantiation_error`) from an improper list (`type_error(list)`).
|
|
5303
|
+
|
|
5304
|
+
### Solution collection
|
|
5305
|
+
|
|
5306
|
+
| Predicate and principal call | Behavior |
|
|
5307
|
+
| --- | --- |
|
|
5308
|
+
| `findall(+Template,+Goal,?Bag)` | Collects a fresh copy of `Template` for every solution of `Goal`, preserving solution order. It succeeds with `[]` when there are no solutions and treats all free variables existentially. |
|
|
5309
|
+
| `bagof(+Template,+Goal,?Bag)` | Groups answers by free variables not present in `Template`. It yields one nonempty bag per witness group and fails when no group exists. Prefix variables with `^` in `Goal` to quantify them existentially. |
|
|
5310
|
+
| `setof(+Template,+Goal,?Set)` | Has the grouping behavior of `bagof/3`, then sorts each group by profile term order and removes identical duplicates. |
|
|
5311
|
+
|
|
5312
|
+
Each collector runs its goal in an isolated inner search while sharing the
|
|
5313
|
+
current logical program and stream state. Collected terms are copied, so local
|
|
5314
|
+
variables do not escape accidentally. The bag argument must be a proper or
|
|
5315
|
+
partial list.
|
|
5316
|
+
|
|
5317
|
+
### Dynamic database and procedure information
|
|
5318
|
+
|
|
5319
|
+
| Predicate and principal call | Behavior |
|
|
5320
|
+
| --- | --- |
|
|
5321
|
+
| `clause(+Head,?Body)` | Enumerates fresh copies of source clauses matching the callable `Head`; facts have body `true`. Access to built-ins raises *permission_error(access,private_procedure)*. |
|
|
5322
|
+
| `asserta(+Clause)`, `assertz(+Clause)` | Insert a copied fact or rule at the beginning or end of a predicate declared *dynamic/1*. Static and built-in procedures cannot be modified. |
|
|
5323
|
+
| `retract(+Clause)` | Removes matching dynamic clauses one at a time on backtracking. A call sees the logical update view captured when it began. A fact pattern matches facts only. |
|
|
5324
|
+
| `abolish(+Name/+Arity)` | Removes a dynamic procedure and its clauses. The indicator must contain an atom and a nonnegative representable integer. |
|
|
5325
|
+
| `current_predicate(?Name/?Arity)` | Enumerates predicate groups present in the loaded program, including empty dynamic groups. It does not enumerate registry-only built-ins. |
|
|
5326
|
+
|
|
5327
|
+
Declare mutable predicates explicitly, including empty ones:
|
|
5328
|
+
|
|
5329
|
+
```text
|
|
5330
|
+
:- dynamic(cache/2).
|
|
5331
|
+
|
|
5332
|
+
remember(Key, Value) :- retract(cache(Key, _)), !, assertz(cache(Key, Value)).
|
|
5333
|
+
remember(Key, Value) :- assertz(cache(Key, Value)).
|
|
5334
|
+
```
|
|
5335
|
+
|
|
5336
|
+
Assertions and retractions invalidate affected reasoning tables. Mutating a
|
|
5337
|
+
predicate that was not declared dynamic raises a permission error rather than
|
|
5338
|
+
silently changing a static program.
|
|
5339
|
+
|
|
5340
|
+
### Operators, character conversion, and flags
|
|
5341
|
+
|
|
5342
|
+
| Predicate and principal call | Behavior |
|
|
5343
|
+
| --- | --- |
|
|
5344
|
+
| `op(+Priority,+Specifier,+NameOrNames)` | Defines or removes operators in the current program. Priority is `0..1200`; specifiers are `fx`, `fy`, `xf`, `yf`, `xfx`, `xfy`, or `yfx`; names may be one atom or a proper list. Priority zero removes the definition. `,` and `\|` cannot be modified. |
|
|
5345
|
+
| `current_op(?Priority,?Specifier,?Name)` | Enumerates active operator definitions and filters supplied arguments. |
|
|
5346
|
+
| `char_conversion(+Input,+Output)` | Installs a one-character atom conversion for subsequent term input. Mapping a character to itself removes its custom mapping. |
|
|
5347
|
+
| `current_char_conversion(?Input,?Output)` | Enumerates installed nonidentity conversions. |
|
|
5348
|
+
| `current_prolog_flag(?Flag,?Value)` | Enumerates flags or retrieves one named flag. An unknown bound flag raises *domain_error(prolog_flag)*. |
|
|
5349
|
+
| `set_prolog_flag(+Flag,+Value)` | Changes a supported mutable flag after validating its allowed atom value. Read-only flags raise a permission error. |
|
|
5350
|
+
|
|
5351
|
+
| Flag | Default in normal EyeProlog | Allowed values | Mutable |
|
|
5352
|
+
| --- | --- | --- | --- |
|
|
5353
|
+
| `bounded` | `false` | `false` | no |
|
|
5354
|
+
| `integer_rounding_function` | `toward_zero` | `toward_zero` | no |
|
|
5355
|
+
| `char_conversion` | `on` | `on`, `off` | yes |
|
|
5356
|
+
| `debug` | `off` | `on`, `off` | yes |
|
|
5357
|
+
| `max_arity` | `unbounded` | `unbounded` | no |
|
|
5358
|
+
| `unknown` | `fail` | `error`, `fail`, `warning` | yes |
|
|
5359
|
+
| `double_quotes` | `chars` | `chars`, `codes`, `atom` | yes |
|
|
5360
|
+
|
|
5361
|
+
The isolated ISO-only registry defaults `unknown` to `error`; the normal
|
|
5362
|
+
autoloaded EyeProlog environment defaults it to `fail`. Operator and flag
|
|
5363
|
+
directives are processed per program rather than changing global JavaScript
|
|
5364
|
+
state. The `double_quotes` setting affects subsequent source text, included
|
|
5365
|
+
files, command-line and API goal text, and terms read by `read_term/*`:
|
|
5366
|
+
|
|
5367
|
+
```text
|
|
5368
|
+
% Default: a list of one-character atoms.
|
|
5369
|
+
chars("ab"). % chars([a,b])
|
|
5370
|
+
|
|
5371
|
+
:- set_prolog_flag(double_quotes, codes).
|
|
5372
|
+
codes("ab"). % codes([97,98])
|
|
5373
|
+
|
|
5374
|
+
:- set_prolog_flag(double_quotes, atom).
|
|
5375
|
+
quoted_atom("ab"). % quoted_atom(ab)
|
|
5376
|
+
```
|
|
5377
|
+
|
|
5378
|
+
### Atomic-term operations and conversions
|
|
5379
|
+
|
|
5380
|
+
| Predicate and principal call | Behavior |
|
|
5381
|
+
| --- | --- |
|
|
5382
|
+
| `atom_length(+Atom,?Length)` | Counts Unicode code points, not UTF-16 code units. A supplied length must be a nonnegative integer. |
|
|
5383
|
+
| `atom_concat(?Prefix,?Suffix,?Whole)` | Concatenates two atoms, removes a supplied prefix or suffix, or enumerates every split when only `Whole` is bound. At least `Whole`, or both parts, must determine the operation. |
|
|
5384
|
+
| `sub_atom(+Atom,?Before,?Length,?After,?SubAtom)` | Enumerates substrings and their Unicode-code-point offsets. Supplied counts must be nonnegative integers. |
|
|
5385
|
+
| `atom_chars(?Atom,?Chars)`, `atom_codes(?Atom,?Codes)` | Convert between an atom and a proper list of one-character atoms or Unicode scalar codes. At least one side must be instantiated. |
|
|
5386
|
+
| `char_code(?Character,?Code)` | Converts one character atom and one Unicode scalar code. Surrogates and values outside `0..0x10ffff` raise a representation error. |
|
|
5387
|
+
| `number_chars(?Number,?Chars)`, `number_codes(?Number,?Codes)` | Convert finite numbers to canonical text or parse a proper character/code list. At least one side must be instantiated; malformed numeric input raises *syntax_error(number)*. |
|
|
5388
|
+
|
|
5389
|
+
Conversions accept partial output lists when the atomic input is known, but
|
|
5390
|
+
constructing an atom or number requires a complete proper list with no unbound
|
|
5391
|
+
elements. Numeric parsing accepts leading ISO layout characters, an optional
|
|
5392
|
+
sign, decimal fractions, and decimal exponents; it rejects trailing material
|
|
5393
|
+
and non-finite values.
|
|
5394
|
+
|
|
5395
|
+
### Streams and unit I/O
|
|
5396
|
+
|
|
5397
|
+
Stream arguments accept an alias atom or the opaque handle returned by
|
|
5398
|
+
`open/3` or `open/4`. Omitting a stream argument selects the current standard
|
|
5399
|
+
input or output.
|
|
5400
|
+
|
|
5401
|
+
| Predicate and principal call | Behavior |
|
|
5402
|
+
| --- | --- |
|
|
5403
|
+
| `open(+Source,+Mode,-Stream)`, `open(+Source,+Mode,-Stream,+Options)` | Opens an atom path in `read`, `write`, or `append` mode. Options are *type(text or binary)*, *alias(Atom)*, *reposition(true or false)*, and *eof_action(error, eof_code, or reset)*. |
|
|
5404
|
+
| `close(+Stream)`, `close(+Stream,+Options)` | Closes a nonstandard stream. The only close option is *force(true or false)*; standard streams remain available. |
|
|
5405
|
+
| `current_input(?Stream)`, `current_output(?Stream)` | Return or test the current input or output handle. |
|
|
5406
|
+
| `set_input(+Stream)`, `set_output(+Stream)` | Select an existing stream with the required direction. |
|
|
5407
|
+
| `flush_output`, `flush_output(+Stream)` | Completes successfully for the current output or validates and flushes the selected output stream. EyeProlog writes synchronously. |
|
|
5408
|
+
| `stream_property(?Stream,?Property)` | Enumerates streams and their properties: *mode/1*, *type/1*, *reposition/1*, *eof_action/1*, *position/1*, *input*, *output*, *end_of_stream/1*, and optional *alias/1* and *file_name/1*. |
|
|
5409
|
+
| `set_stream_position(+Stream,+Position)` | Repositions a stream opened with *reposition(true)*. `Position` is a nonnegative integer or *position(Integer)* within the stream content. |
|
|
5410
|
+
| `at_end_of_stream`, `at_end_of_stream(+Stream)` | Succeeds when the current or selected input position is at or beyond its content. |
|
|
5411
|
+
| `get_char(?Character)`, `get_char(+Stream,?Character)` | Reads one text character; end of input is `end_of_file`. |
|
|
5412
|
+
| `peek_char(?Character)`, `peek_char(+Stream,?Character)` | Observes the next text character without advancing. |
|
|
5413
|
+
| `get_code(?Code)`, `get_code(+Stream,?Code)` | Reads a Unicode code point; end of input is `-1`. |
|
|
5414
|
+
| `peek_code(?Code)`, `peek_code(+Stream,?Code)` | Observes the next Unicode code point without advancing. |
|
|
5415
|
+
| `get_byte(?Byte)`, `get_byte(+Stream,?Byte)` | Reads one unit from a binary stream; end of input is `-1`. |
|
|
5416
|
+
| `peek_byte(?Byte)`, `peek_byte(+Stream,?Byte)` | Observes the next binary unit without advancing. |
|
|
5417
|
+
| `put_char(+Character)`, `put_char(+Stream,+Character)` | Writes one character atom to a text stream. |
|
|
5418
|
+
| `put_code(+Code)`, `put_code(+Stream,+Code)` | Writes one Unicode scalar code to a text stream. |
|
|
5419
|
+
| `put_byte(+Byte)`, `put_byte(+Stream,+Byte)` | Writes an integer in `0..255` to a binary stream. |
|
|
5420
|
+
| `nl`, `nl(+Stream)` | Writes a newline to a text stream. |
|
|
5421
|
+
|
|
5422
|
+
Text operations on binary streams and byte operations on text streams raise
|
|
5423
|
+
permission errors. After EOF, `eof_action(error)` rejects another consuming
|
|
5424
|
+
read, `eof_code` continues returning the EOF value, and `reset` resumes from
|
|
5425
|
+
the beginning. A peek does not mark the stream as past-end.
|
|
5426
|
+
|
|
5427
|
+
### Term input and output
|
|
5428
|
+
|
|
5429
|
+
| Predicate and principal call | Behavior |
|
|
5430
|
+
| --- | --- |
|
|
5431
|
+
| `read(?Term)`, `read(+Stream,?Term)` | Reads one full-stop-terminated Prolog term from a text stream. Returns `end_of_file` when no term remains. |
|
|
5432
|
+
| `read_term(?Term,+Options)`, `read_term(+Stream,?Term,+Options)` | Reads a term and supports *variables(List)*, *variable_names(Pairs)*, and *singletons(Pairs)*. Unknown options raise *domain_error(read_option)*. |
|
|
5433
|
+
| `write(+Term)`, `write(+Stream,+Term)` | Writes readable operator notation without quoting atoms merely because quoting would be required for reparsing. Number variables are enabled. |
|
|
5434
|
+
| `writeq(+Term)`, `writeq(+Stream,+Term)` | Like `write`, but quotes atoms when required for unambiguous input syntax. |
|
|
5435
|
+
| `write_canonical(+Term)`, `write_canonical(+Stream,+Term)` | Writes quoted canonical functor notation while ignoring operators and without interpreting *$VAR/1*. |
|
|
5436
|
+
| `write_term(+Term,+Options)`, `write_term(+Stream,+Term,+Options)` | Writes with *quoted(true or false)*, *ignore_ops(true or false)*, *numbervars(true or false)*, and *variable_names([Name=Variable,...])*. |
|
|
5437
|
+
|
|
5438
|
+
Term input uses the program's current operator table and applies installed
|
|
5439
|
+
character conversions outside quoted text when the `char_conversion` flag is
|
|
5440
|
+
`on`. `variable_names/1` and `singletons/1` omit anonymous variables. Output
|
|
5441
|
+
predicates do not append a period or newline; call `write/1`, then `write('.')`
|
|
5442
|
+
and `nl/0` when emitting a complete source term manually.
|
|
5443
|
+
|
|
5224
5444
|
### Arithmetic expressions
|
|
5225
5445
|
|
|
5226
|
-
|
|
5227
|
-
|
|
5228
|
-
|
|
5229
|
-
`
|
|
5230
|
-
`
|
|
5446
|
+
| Predicate and principal call | Behavior |
|
|
5447
|
+
| --- | --- |
|
|
5448
|
+
| `is(?Result,+Expression)` | Evaluates `Expression` once and unifies its numeric value with `Result`. It is evaluation plus unification, not mutable assignment. |
|
|
5449
|
+
| `Left =:= Right`, `Left =\= Right` | Evaluate both sides and test numeric equality or inequality. Integer/float representation differences do not by themselves make values unequal. |
|
|
5450
|
+
| `Left < Right`, `Left =< Right`, `Left > Right`, `Left >= Right` | Evaluate both sides and perform the indicated numeric comparison. |
|
|
5451
|
+
|
|
5452
|
+
Every variable in an arithmetic expression must already be bound to a number
|
|
5453
|
+
or evaluable expression. Integers use arbitrary-precision arithmetic while an
|
|
5454
|
+
operation remains in the integer domain; operations requiring floating point
|
|
5455
|
+
convert their operands to finite JavaScript numbers.
|
|
5456
|
+
|
|
5457
|
+
| Expression family | Supported forms and result rules |
|
|
5458
|
+
| --- | --- |
|
|
5459
|
+
| Literals and constants | Integer and finite floating-point literals; `pi` and `e` produce floating-point constants. |
|
|
5460
|
+
| Unary arithmetic | Unary `+`, unary `-`, and integer bitwise complement `\`. |
|
|
5461
|
+
| Basic binary arithmetic | `+`, `-`, and `*` preserve integers when both operands are integers. `/` produces a float and rejects a zero divisor. |
|
|
5462
|
+
| Exponentiation | `Base ^ Exponent` remains an integer for nonnegative integer operands; otherwise `^` and `**` use floating-point exponentiation. |
|
|
5463
|
+
| Integer division | `//` and `div` require integers, reject zero divisors, and round toward zero as reported by `integer_rounding_function`. |
|
|
5464
|
+
| Integer remainder | `rem` is the truncating remainder; `mod` normalizes the result with the divisor's sign. Both require integers and a nonzero divisor. |
|
|
5465
|
+
| Bit operations | Integer `\/\`, `\\/`, `<<`, and `>>`, plus unary `\`. |
|
|
5466
|
+
| Numeric normalization | `abs`, `sign`, and `float`. Integer `abs` and `sign` preserve integer results; `float` produces a float. |
|
|
5467
|
+
| Rounding | `truncate`, `round`, `ceiling`, and `floor` produce integers. |
|
|
5468
|
+
| Float decomposition | `float_integer_part` and `float_fractional_part` require a float and return floats. |
|
|
5469
|
+
| Transcendental functions | `sin`, `cos`, `atan`, `exp`, `log`, and `sqrt` produce finite floats. |
|
|
5231
5470
|
|
|
5232
5471
|
Arithmetic comparisons evaluate both operands. Standard term-order predicates
|
|
5233
5472
|
(`@<`, `@=<`, `@>`, `@>=`) compare terms without arithmetic evaluation.
|
|
5234
|
-
EyeProlog's documented profile order
|
|
5235
|
-
|
|
5236
|
-
|
|
5473
|
+
EyeProlog's documented profile order distinguishes floats from integers rather
|
|
5474
|
+
than applying arithmetic equality across representations. Double-quoted text
|
|
5475
|
+
does not introduce another ISO term-order category: it becomes the list or atom
|
|
5476
|
+
selected by `double_quotes` before comparison.
|
|
5237
5477
|
|
|
5238
5478
|
### Errors
|
|
5239
5479
|
|
|
@@ -5243,6 +5483,22 @@ instantiation raises `instantiation_error`; wrong argument categories raise
|
|
|
5243
5483
|
`evaluation_error`. JavaScript embedders receive these as `PrologError`
|
|
5244
5484
|
instances whose message contains the corresponding Prolog error term.
|
|
5245
5485
|
|
|
5486
|
+
| Error class | Typical cause |
|
|
5487
|
+
| --- | --- |
|
|
5488
|
+
| *instantiation_error* | A required callable, stream, number, list, option value, or construction input is still unbound. |
|
|
5489
|
+
| *type_error(Expected,Culprit)* | A bound value has the wrong term category, such as a noninteger index or non-callable goal. |
|
|
5490
|
+
| *domain_error(Domain,Culprit)* | The type is correct but the value is outside the supported domain, such as a bad stream option or operator priority. |
|
|
5491
|
+
| *representation_error(Flag)* | A value cannot be represented by the profile, such as an invalid Unicode scalar code. |
|
|
5492
|
+
| *evaluation_error(zero_divisor)* | Integer or floating-point division was attempted with a zero divisor. |
|
|
5493
|
+
| *evaluation_error(undefined)* | Floating-point evaluation produced a non-finite or undefined result. |
|
|
5494
|
+
| *permission_error(Operation,Permission,Culprit)* | A static procedure was modified, a stream was used in the wrong mode, or a protected resource was accessed. |
|
|
5495
|
+
| *existence_error(Object,Culprit)* | A stream, source sink, or required procedure does not exist. |
|
|
5496
|
+
| *syntax_error(number)*, *syntax_error(read_term)* | Lexical number conversion or streamed term parsing failed. |
|
|
5497
|
+
|
|
5498
|
+
`catch/3` converts a `PrologError` into a catchable
|
|
5499
|
+
`error(Formal,eyeprolog)` term. A user ball from `throw/1` is delivered as-is.
|
|
5500
|
+
An unmatched ball or error continues outward.
|
|
5501
|
+
|
|
5246
5502
|
Streams belong to one solver run and are shared by nested calls, exceptions,
|
|
5247
5503
|
and solution collectors. `user_input` and `user_output` are always present.
|
|
5248
5504
|
`open/4` supports `type/1`, `alias/1`, `reposition/1`, and `eof_action/1`;
|
|
@@ -5405,12 +5661,14 @@ eyeprolog --goal 'answer(Kind, Value)' program.pl
|
|
|
5405
5661
|
#### Portable text, lexical values, and pattern matching
|
|
5406
5662
|
|
|
5407
5663
|
The portable text API uses **ISO atoms or proper lists of one-character atoms**.
|
|
5408
|
-
A generated text result defaults to an atom.
|
|
5409
|
-
|
|
5410
|
-
|
|
5411
|
-
|
|
5412
|
-
|
|
5413
|
-
|
|
5664
|
+
A generated text result defaults to an atom. Double-quoted source text uses the
|
|
5665
|
+
ISO representation selected by `double_quotes`; with the default `chars`, it is
|
|
5666
|
+
already a proper character list accepted by this API. The RDF tools emit lexical
|
|
5667
|
+
forms as atoms while preserving RDF distinctions in the surrounding `iri/1`,
|
|
5668
|
+
`literal/2`, datatype, language, and direction terms. Their private host adapter
|
|
5669
|
+
may encounter an internal RDF string value, but that value is converted at the
|
|
5670
|
+
boundary and is never produced by double-quoted Prolog syntax. The 48-predicate
|
|
5671
|
+
portable file itself has no STRING or JavaScript dependency.
|
|
5414
5672
|
|
|
5415
5673
|
| Predicate and principal mode | Behavior |
|
|
5416
5674
|
| --- | --- |
|
|
@@ -6136,7 +6394,7 @@ proof terms, warnings, answer formatting, embedding, and external data
|
|
|
6136
6394
|
adapters.
|
|
6137
6395
|
|
|
6138
6396
|
The executable corpus under `test/conformance/` tests the JavaScript
|
|
6139
|
-
implementation. Positive programs and exact output cover arithmetic,
|
|
6397
|
+
implementation. Positive programs and exact output cover arithmetic, text relations,
|
|
6140
6398
|
lists, terms, atoms, variables, negation, queries, rules, and
|
|
6141
6399
|
syntax. Separate corpora cover expected errors, warnings, and proofs:
|
|
6142
6400
|
|
|
@@ -6146,7 +6404,7 @@ node test/run-conformance-report.mjs
|
|
|
6146
6404
|
```
|
|
6147
6405
|
|
|
6148
6406
|
The complete suite must pass before release. The file-based conformance corpus
|
|
6149
|
-
contains
|
|
6407
|
+
contains 686 cases, including 280 focused ISO
|
|
6150
6408
|
cases derived from the success, failure, mode, and error behavior in
|
|
6151
6409
|
ISO/IEC 13211-1 clauses 7 and 8. Separate exact-output suites check 204 normal
|
|
6152
6410
|
examples, 71 proof examples, and extracted book displays. The seven-case
|
|
@@ -6190,15 +6448,15 @@ additional compatibility conveniences.
|
|
|
6190
6448
|
|
|
6191
6449
|
This breadth is not a formal certification of every processor requirement.
|
|
6192
6450
|
The executable examples are EyeProlog-profile programs using host-supplied goals,
|
|
6193
|
-
|
|
6451
|
+
character lists, explicit integrity relations, automatic tabling, and the EyeProlog library.
|
|
6194
6452
|
The remaining qualifications are:
|
|
6195
6453
|
|
|
6196
6454
|
- zero-arity compound syntax such as `ready()` is represented by the atom
|
|
6197
6455
|
`ready`;
|
|
6198
6456
|
- modules and DCG notation are outside this Part 1 profile;
|
|
6199
6457
|
- variables cannot occupy functor or predicate position;
|
|
6200
|
-
- double-quoted text
|
|
6201
|
-
|
|
6458
|
+
- double-quoted text follows `double_quotes` exactly; the default `chars` value
|
|
6459
|
+
matches Trealla and Scryer and may be changed to `codes` or `atom`;
|
|
6202
6460
|
- `write_term/2-3` implements `quoted/1`, `ignore_ops/1`, `numbervars/1`,
|
|
6203
6461
|
and `variable_names/1`; other write options and some option/error precedence
|
|
6204
6462
|
combinations remain outside the profile;
|
|
@@ -6567,8 +6825,9 @@ replaces those variables consistently throughout a term or clause.
|
|
|
6567
6825
|
**Tabling.** Evaluation that shares recursive calls and accumulates their
|
|
6568
6826
|
answers toward a fixed point.
|
|
6569
6827
|
|
|
6570
|
-
**Term.** An atom constant,
|
|
6571
|
-
parenthesized comma term.
|
|
6828
|
+
**Term.** An atom constant, number, variable, compound term, list, or
|
|
6829
|
+
parenthesized comma term. Double-quoted notation denotes a list or atom as
|
|
6830
|
+
selected by the ISO `double_quotes` flag.
|
|
6572
6831
|
|
|
6573
6832
|
**Termination measure.** A value in a well-founded order that strictly
|
|
6574
6833
|
decreases along every recursive branch in a stated mode.
|