eyeling 1.34.6 → 2.35.0
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 +33 -0
- package/dist/browser/eyeling.browser.js +284 -14
- package/examples/collatz-1000.n3 +4 -0
- package/examples/fibonacci.n3 +13 -8
- package/examples/fundamental-theorem-arithmetic.n3 +6 -0
- package/eyeling.js +284 -14
- package/lib/cli.js +2 -2
- package/lib/engine.js +269 -4
- package/lib/multisource.js +1 -1
- package/lib/parser.js +12 -7
- package/package.json +1 -1
- package/test/eyelang/conformance/README.md +0 -43
- package/test/eyelang/conformance/cases/001_fact_output.pl +0 -4
- package/test/eyelang/conformance/cases/002_rule_recursion.pl +0 -7
- package/test/eyelang/conformance/cases/002_rule_recursion.query +0 -1
- package/test/eyelang/conformance/cases/003_terms_and_readback.pl +0 -16
- package/test/eyelang/conformance/cases/003_terms_and_readback.query +0 -1
- package/test/eyelang/conformance/cases/004_conjunction_and_parentheses.pl +0 -5
- package/test/eyelang/conformance/cases/004_conjunction_and_parentheses.query +0 -1
- package/test/eyelang/conformance/cases/005_list_deconstruction.pl +0 -6
- package/test/eyelang/conformance/cases/005_list_deconstruction.query +0 -1
- package/test/eyelang/conformance/cases/006_comma_formula_data.pl +0 -4
- package/test/eyelang/conformance/cases/006_comma_formula_data.query +0 -1
- package/test/eyelang/conformance/cases/007_anonymous_variables.pl +0 -5
- package/test/eyelang/conformance/cases/007_anonymous_variables.query +0 -1
- package/test/eyelang/conformance/cases/008_graphic_atoms.pl +0 -6
- package/test/eyelang/conformance/cases/008_graphic_atoms.query +0 -1
- package/test/eyelang/conformance/cases/009_comments_and_whitespace.pl +0 -5
- package/test/eyelang/conformance/cases/009_comments_and_whitespace.query +0 -1
- package/test/eyelang/conformance/cases/010_variable_scope_and_reuse.pl +0 -8
- package/test/eyelang/conformance/cases/010_variable_scope_and_reuse.query +0 -1
- package/test/eyelang/conformance/cases/011_predicate_arity.pl +0 -6
- package/test/eyelang/conformance/cases/011_predicate_arity.query +0 -1
- package/test/eyelang/conformance/cases/012_nested_compound_unification.pl +0 -5
- package/test/eyelang/conformance/cases/012_nested_compound_unification.query +0 -1
- package/test/eyelang/conformance/cases/013_multiple_clauses_order.pl +0 -6
- package/test/eyelang/conformance/cases/013_multiple_clauses_order.query +0 -1
- package/test/eyelang/conformance/cases/014_failure_filters_answers.pl +0 -7
- package/test/eyelang/conformance/cases/014_failure_filters_answers.query +0 -1
- package/test/eyelang/conformance/cases/015_improper_list_unification.pl +0 -6
- package/test/eyelang/conformance/cases/015_improper_list_unification.query +0 -1
- package/test/eyelang/conformance/cases/016_zero_arity_compound.pl +0 -4
- package/test/eyelang/conformance/cases/016_zero_arity_compound.query +0 -1
- package/test/eyelang/conformance/cases/017_three_step_recursion.pl +0 -8
- package/test/eyelang/conformance/cases/017_three_step_recursion.query +0 -1
- package/test/eyelang/conformance/cases/018_quoted_atom_readback.pl +0 -6
- package/test/eyelang/conformance/cases/018_quoted_atom_readback.query +0 -1
- package/test/eyelang/conformance/cases/019_parenthesized_three_conjuncts.pl +0 -7
- package/test/eyelang/conformance/cases/019_parenthesized_three_conjuncts.query +0 -1
- package/test/eyelang/conformance/cases/020_nested_list_terms.pl +0 -5
- package/test/eyelang/conformance/cases/020_nested_list_terms.query +0 -1
- package/test/eyelang/conformance/cases/021_repeated_variable_head.pl +0 -7
- package/test/eyelang/conformance/cases/022_rule_head_structure.pl +0 -5
- package/test/eyelang/conformance/cases/023_quoted_escapes_readback.pl +0 -5
- package/test/eyelang/conformance/cases/024_numeric_literal_readback.pl +0 -6
- package/test/eyelang/conformance/cases/025_body_parentheses_with_formula_data.pl +0 -5
- package/test/eyelang/conformance/cases/026_underscore_named_variable_reuse.pl +0 -5
- package/test/eyelang/conformance/cases/027_default_derived_output.pl +0 -5
- package/test/eyelang/conformance/cases/028_materialize_focus.pl +0 -5
- package/test/eyelang/conformance/cases/029_arithmetic_and_comparison.pl +0 -11
- package/test/eyelang/conformance/cases/029_arithmetic_and_comparison.query +0 -1
- package/test/eyelang/conformance/cases/030_strings_and_atoms.pl +0 -4
- package/test/eyelang/conformance/cases/030_strings_and_atoms.query +0 -1
- package/test/eyelang/conformance/cases/031_lists_aggregation_ordering.pl +0 -10
- package/test/eyelang/conformance/cases/031_lists_aggregation_ordering.query +0 -1
- package/test/eyelang/conformance/cases/032_holds_parts.pl +0 -4
- package/test/eyelang/conformance/cases/033_negation_once_generators.pl +0 -7
- package/test/eyelang/conformance/cases/033_negation_once_generators.query +0 -1
- package/test/eyelang/conformance/cases/034_equality_and_inequality.pl +0 -6
- package/test/eyelang/conformance/cases/034_equality_and_inequality.query +0 -1
- package/test/eyelang/conformance/cases/035_list_relations.pl +0 -5
- package/test/eyelang/conformance/cases/035_list_relations.query +0 -1
- package/test/eyelang/conformance/cases/036_append_splits.pl +0 -3
- package/test/eyelang/conformance/cases/036_append_splits.query +0 -1
- package/test/eyelang/conformance/cases/037_matching_and_comparison.pl +0 -7
- package/test/eyelang/conformance/cases/037_matching_and_comparison.query +0 -1
- package/test/eyelang/conformance/cases/038_memoize_declaration.pl +0 -8
- package/test/eyelang/conformance/cases/038_memoize_declaration.query +0 -1
- package/test/eyelang/conformance/cases/039_numeric_functions.pl +0 -9
- package/test/eyelang/conformance/cases/039_numeric_functions.query +0 -1
- package/test/eyelang/conformance/cases/040_between_enumeration.pl +0 -3
- package/test/eyelang/conformance/cases/040_between_enumeration.query +0 -1
- package/test/eyelang/conformance/cases/041_smallest_divisor.pl +0 -3
- package/test/eyelang/conformance/cases/041_smallest_divisor.query +0 -1
- package/test/eyelang/conformance/cases/042_negation_filter.pl +0 -7
- package/test/eyelang/conformance/cases/042_negation_filter.query +0 -1
- package/test/eyelang/conformance/cases/043_once_user_predicate.pl +0 -5
- package/test/eyelang/conformance/cases/043_once_user_predicate.query +0 -1
- package/test/eyelang/conformance/cases/044_findall_user_goal.pl +0 -6
- package/test/eyelang/conformance/cases/044_findall_user_goal.query +0 -1
- package/test/eyelang/conformance/cases/045_sort_deduplicates_atoms.pl +0 -3
- package/test/eyelang/conformance/cases/045_sort_deduplicates_atoms.query +0 -1
- package/test/eyelang/conformance/cases/046_append_bound_prefix_suffix.pl +0 -4
- package/test/eyelang/conformance/cases/046_append_bound_prefix_suffix.query +0 -1
- package/test/eyelang/conformance/cases/047_nth0_index_generation.pl +0 -3
- package/test/eyelang/conformance/cases/047_nth0_index_generation.query +0 -1
- package/test/eyelang/conformance/cases/048_set_nth0_edges.pl +0 -4
- package/test/eyelang/conformance/cases/048_set_nth0_edges.query +0 -1
- package/test/eyelang/conformance/cases/049_select_duplicate_occurrences.pl +0 -3
- package/test/eyelang/conformance/cases/049_select_duplicate_occurrences.query +0 -1
- package/test/eyelang/conformance/cases/050_not_member_filter.pl +0 -6
- package/test/eyelang/conformance/cases/050_not_member_filter.query +0 -1
- package/test/eyelang/conformance/cases/051_nested_holds_parts.pl +0 -4
- package/test/eyelang/conformance/cases/052_holds_member.pl +0 -3
- package/test/eyelang/conformance/cases/053_materialize_excludes_source_fact.pl +0 -6
- package/test/eyelang/conformance/cases/054_numeric_and_lexical_comparison.pl +0 -5
- package/test/eyelang/conformance/cases/054_numeric_and_lexical_comparison.query +0 -1
- package/test/eyelang/conformance/cases/055_string_matching_filters.pl +0 -6
- package/test/eyelang/conformance/cases/055_string_matching_filters.query +0 -1
- package/test/eyelang/conformance/cases/056_string_and_atom_concat.pl +0 -3
- package/test/eyelang/conformance/cases/056_string_and_atom_concat.query +0 -1
- package/test/eyelang/conformance/cases/057_countall_empty_and_nonempty.pl +0 -4
- package/test/eyelang/conformance/cases/057_countall_empty_and_nonempty.query +0 -1
- package/test/eyelang/conformance/cases/058_sumall_numeric_template.pl +0 -5
- package/test/eyelang/conformance/cases/058_sumall_numeric_template.query +0 -1
- package/test/eyelang/conformance/cases/059_aggregate_min_template.pl +0 -5
- package/test/eyelang/conformance/cases/059_aggregate_min_template.query +0 -1
- package/test/eyelang/conformance/cases/060_aggregate_max_compound_key.pl +0 -5
- package/test/eyelang/conformance/cases/060_aggregate_max_compound_key.query +0 -1
- package/test/eyelang/conformance/cases/061_date_difference.pl +0 -4
- package/test/eyelang/conformance/cases/062_reusable_numeric_builtins.pl +0 -10
- package/test/eyelang/conformance/cases/063_reusable_list_builtins.pl +0 -11
- package/test/eyelang/conformance/cases/064_reusable_string_builtins.pl +0 -12
- package/test/eyelang/conformance/cases/065_reusable_term_control_builtins.pl +0 -11
- package/test/eyelang/conformance/cases/066_numeric_edges.pl +0 -14
- package/test/eyelang/conformance/cases/067_list_edges.pl +0 -10
- package/test/eyelang/conformance/cases/068_list_generation_order.pl +0 -7
- package/test/eyelang/conformance/cases/069_list_summaries_and_sets.pl +0 -9
- package/test/eyelang/conformance/cases/070_matches_named_captures.pl +0 -13
- package/test/eyelang/conformance/cases/071_string_edges.pl +0 -10
- package/test/eyelang/conformance/cases/072_string_conversions.pl +0 -10
- package/test/eyelang/conformance/cases/073_term_introspection_edges.pl +0 -10
- package/test/eyelang/conformance/cases/074_forall_edges.pl +0 -10
- package/test/eyelang/conformance/cases/075_aggregation_edges.pl +0 -12
- package/test/eyelang/conformance/cases/076_composed_reusable_builtins.pl +0 -8
- package/test/eyelang/conformance/cases/077_recursive_path_with_lists.pl +0 -10
- package/test/eyelang/conformance/cases/078_mutual_recursion_with_arithmetic.pl +0 -7
- package/test/eyelang/conformance/cases/079_big_integer_arithmetic.pl +0 -8
- package/test/eyelang/conformance/cases/080_rounding_modes.pl +0 -10
- package/test/eyelang/conformance/cases/081_zero_safe_numeric_functions.pl +0 -9
- package/test/eyelang/conformance/cases/082_comparison_semantics.pl +0 -10
- package/test/eyelang/conformance/cases/083_between_modes_and_empty_ranges.pl +0 -8
- package/test/eyelang/conformance/cases/084_append_and_select_composition.pl +0 -7
- package/test/eyelang/conformance/cases/085_nth_and_update_edges.pl +0 -8
- package/test/eyelang/conformance/cases/086_slicing_pipeline.pl +0 -10
- package/test/eyelang/conformance/cases/087_sort_reverse_length.pl +0 -8
- package/test/eyelang/conformance/cases/088_list_summaries_failures.pl +0 -8
- package/test/eyelang/conformance/cases/089_string_split_join_pipeline.pl +0 -7
- package/test/eyelang/conformance/cases/090_string_substring_replace_edges.pl +0 -9
- package/test/eyelang/conformance/cases/091_string_case_and_trim.pl +0 -7
- package/test/eyelang/conformance/cases/092_scalar_string_conversions.pl +0 -9
- package/test/eyelang/conformance/cases/093_regex_named_captures_context.pl +0 -8
- package/test/eyelang/conformance/cases/094_context_holds_enumeration.pl +0 -7
- package/test/eyelang/conformance/cases/095_term_introspection_roundtrip.pl +0 -8
- package/test/eyelang/conformance/cases/096_functor_scalar_edges.pl +0 -8
- package/test/eyelang/conformance/cases/097_control_negation_once_forall.pl +0 -13
- package/test/eyelang/conformance/cases/098_aggregation_nested_templates.pl +0 -11
- package/test/eyelang/conformance/cases/099_materialize_multiple_arities.pl +0 -8
- package/test/eyelang/conformance/cases/100_reusable_builtin_workflow.pl +0 -10
- package/test/eyelang/conformance/cases/core/001_fact_output.pl +0 -4
- package/test/eyelang/conformance/cases/core/001_fact_query.query +0 -1
- package/test/eyelang/conformance/cases/core/002_rule_recursion.pl +0 -7
- package/test/eyelang/conformance/cases/core/002_rule_recursion.query +0 -1
- package/test/eyelang/conformance/cases/core/003_terms_and_readback.pl +0 -16
- package/test/eyelang/conformance/cases/core/003_terms_and_readback.query +0 -1
- package/test/eyelang/conformance/cases/core/004_conjunction_and_parentheses.pl +0 -5
- package/test/eyelang/conformance/cases/core/004_conjunction_and_parentheses.query +0 -1
- package/test/eyelang/conformance/cases/core/005_list_deconstruction.pl +0 -6
- package/test/eyelang/conformance/cases/core/005_list_deconstruction.query +0 -1
- package/test/eyelang/conformance/cases/core/006_comma_formula_data.pl +0 -4
- package/test/eyelang/conformance/cases/core/006_comma_formula_data.query +0 -1
- package/test/eyelang/conformance/cases/core/007_anonymous_variables.pl +0 -5
- package/test/eyelang/conformance/cases/core/007_anonymous_variables.query +0 -1
- package/test/eyelang/conformance/cases/core/008_graphic_atoms.pl +0 -6
- package/test/eyelang/conformance/cases/core/008_graphic_atoms.query +0 -1
- package/test/eyelang/conformance/cases/core/009_comments_and_whitespace.pl +0 -5
- package/test/eyelang/conformance/cases/core/009_comments_and_whitespace.query +0 -1
- package/test/eyelang/conformance/cases/core/010_variable_scope_and_reuse.pl +0 -8
- package/test/eyelang/conformance/cases/core/010_variable_scope_and_reuse.query +0 -1
- package/test/eyelang/conformance/cases/core/011_predicate_arity.pl +0 -6
- package/test/eyelang/conformance/cases/core/011_predicate_arity.query +0 -1
- package/test/eyelang/conformance/cases/core/012_nested_compound_unification.pl +0 -5
- package/test/eyelang/conformance/cases/core/012_nested_compound_unification.query +0 -1
- package/test/eyelang/conformance/cases/core/013_multiple_clauses_order.pl +0 -6
- package/test/eyelang/conformance/cases/core/013_multiple_clauses_order.query +0 -1
- package/test/eyelang/conformance/cases/core/014_failure_filters_answers.pl +0 -7
- package/test/eyelang/conformance/cases/core/014_failure_filters_answers.query +0 -1
- package/test/eyelang/conformance/cases/core/015_improper_list_unification.pl +0 -6
- package/test/eyelang/conformance/cases/core/015_improper_list_unification.query +0 -1
- package/test/eyelang/conformance/cases/core/016_zero_arity_compound.pl +0 -4
- package/test/eyelang/conformance/cases/core/016_zero_arity_compound.query +0 -1
- package/test/eyelang/conformance/cases/core/017_three_step_recursion.pl +0 -8
- package/test/eyelang/conformance/cases/core/017_three_step_recursion.query +0 -1
- package/test/eyelang/conformance/cases/core/018_quoted_atom_readback.pl +0 -6
- package/test/eyelang/conformance/cases/core/018_quoted_atom_readback.query +0 -1
- package/test/eyelang/conformance/cases/core/019_parenthesized_three_conjuncts.pl +0 -7
- package/test/eyelang/conformance/cases/core/019_parenthesized_three_conjuncts.query +0 -1
- package/test/eyelang/conformance/cases/core/020_nested_list_terms.pl +0 -5
- package/test/eyelang/conformance/cases/core/020_nested_list_terms.query +0 -1
- package/test/eyelang/conformance/cases/core/021_repeated_variable_head.pl +0 -7
- package/test/eyelang/conformance/cases/core/022_rule_head_structure.pl +0 -5
- package/test/eyelang/conformance/cases/core/023_quoted_escapes_readback.pl +0 -5
- package/test/eyelang/conformance/cases/core/024_numeric_literal_readback.pl +0 -6
- package/test/eyelang/conformance/cases/core/025_body_parentheses_with_formula_data.pl +0 -5
- package/test/eyelang/conformance/cases/core/026_underscore_named_variable_reuse.pl +0 -5
- package/test/eyelang/conformance/cases/extension/001_default_derived_output.pl +0 -5
- package/test/eyelang/conformance/cases/extension/002_materialize_focus.pl +0 -5
- package/test/eyelang/conformance/cases/extension/003_arithmetic_and_comparison.pl +0 -11
- package/test/eyelang/conformance/cases/extension/003_arithmetic_and_comparison.query +0 -1
- package/test/eyelang/conformance/cases/extension/004_strings_and_atoms.pl +0 -4
- package/test/eyelang/conformance/cases/extension/004_strings_and_atoms.query +0 -1
- package/test/eyelang/conformance/cases/extension/005_lists_aggregation_ordering.pl +0 -10
- package/test/eyelang/conformance/cases/extension/005_lists_aggregation_ordering.query +0 -1
- package/test/eyelang/conformance/cases/extension/006_formula_terms.query +0 -1
- package/test/eyelang/conformance/cases/extension/006_holds_parts.pl +0 -4
- package/test/eyelang/conformance/cases/extension/007_negation_once_generators.pl +0 -7
- package/test/eyelang/conformance/cases/extension/007_negation_once_generators.query +0 -1
- package/test/eyelang/conformance/cases/extension/008_equality_and_inequality.pl +0 -6
- package/test/eyelang/conformance/cases/extension/008_equality_and_inequality.query +0 -1
- package/test/eyelang/conformance/cases/extension/009_list_relations.pl +0 -5
- package/test/eyelang/conformance/cases/extension/009_list_relations.query +0 -1
- package/test/eyelang/conformance/cases/extension/010_append_splits.pl +0 -3
- package/test/eyelang/conformance/cases/extension/010_append_splits.query +0 -1
- package/test/eyelang/conformance/cases/extension/011_matching_and_comparison.pl +0 -7
- package/test/eyelang/conformance/cases/extension/011_matching_and_comparison.query +0 -1
- package/test/eyelang/conformance/cases/extension/012_memoize_declaration.pl +0 -8
- package/test/eyelang/conformance/cases/extension/012_memoize_declaration.query +0 -1
- package/test/eyelang/conformance/cases/extension/013_numeric_functions.pl +0 -9
- package/test/eyelang/conformance/cases/extension/013_numeric_functions.query +0 -1
- package/test/eyelang/conformance/cases/extension/014_between_enumeration.pl +0 -3
- package/test/eyelang/conformance/cases/extension/014_between_enumeration.query +0 -1
- package/test/eyelang/conformance/cases/extension/015_smallest_divisor.pl +0 -3
- package/test/eyelang/conformance/cases/extension/015_smallest_divisor.query +0 -1
- package/test/eyelang/conformance/cases/extension/016_negation_filter.pl +0 -7
- package/test/eyelang/conformance/cases/extension/016_negation_filter.query +0 -1
- package/test/eyelang/conformance/cases/extension/017_once_user_predicate.pl +0 -5
- package/test/eyelang/conformance/cases/extension/017_once_user_predicate.query +0 -1
- package/test/eyelang/conformance/cases/extension/018_findall_user_goal.pl +0 -6
- package/test/eyelang/conformance/cases/extension/018_findall_user_goal.query +0 -1
- package/test/eyelang/conformance/cases/extension/019_sort_deduplicates_atoms.pl +0 -3
- package/test/eyelang/conformance/cases/extension/019_sort_deduplicates_atoms.query +0 -1
- package/test/eyelang/conformance/cases/extension/020_append_bound_prefix_suffix.pl +0 -4
- package/test/eyelang/conformance/cases/extension/020_append_bound_prefix_suffix.query +0 -1
- package/test/eyelang/conformance/cases/extension/021_nth0_index_generation.pl +0 -3
- package/test/eyelang/conformance/cases/extension/021_nth0_index_generation.query +0 -1
- package/test/eyelang/conformance/cases/extension/022_set_nth0_edges.pl +0 -4
- package/test/eyelang/conformance/cases/extension/022_set_nth0_edges.query +0 -1
- package/test/eyelang/conformance/cases/extension/023_select_duplicate_occurrences.pl +0 -3
- package/test/eyelang/conformance/cases/extension/023_select_duplicate_occurrences.query +0 -1
- package/test/eyelang/conformance/cases/extension/024_not_member_filter.pl +0 -6
- package/test/eyelang/conformance/cases/extension/024_not_member_filter.query +0 -1
- package/test/eyelang/conformance/cases/extension/026_nested_formula_terms.query +0 -1
- package/test/eyelang/conformance/cases/extension/026_nested_holds_parts.pl +0 -4
- package/test/eyelang/conformance/cases/extension/027_formula_member.query +0 -1
- package/test/eyelang/conformance/cases/extension/027_holds_member.pl +0 -3
- package/test/eyelang/conformance/cases/extension/027_materialize_excludes_source_fact.pl +0 -6
- package/test/eyelang/conformance/cases/extension/028_numeric_and_lexical_comparison.pl +0 -5
- package/test/eyelang/conformance/cases/extension/028_numeric_and_lexical_comparison.query +0 -1
- package/test/eyelang/conformance/cases/extension/029_string_matching_filters.pl +0 -6
- package/test/eyelang/conformance/cases/extension/029_string_matching_filters.query +0 -1
- package/test/eyelang/conformance/cases/extension/030_string_and_atom_concat.pl +0 -3
- package/test/eyelang/conformance/cases/extension/030_string_and_atom_concat.query +0 -1
- package/test/eyelang/conformance/cases/extension/031_countall_empty_and_nonempty.pl +0 -4
- package/test/eyelang/conformance/cases/extension/031_countall_empty_and_nonempty.query +0 -1
- package/test/eyelang/conformance/cases/extension/032_sumall_numeric_template.pl +0 -5
- package/test/eyelang/conformance/cases/extension/032_sumall_numeric_template.query +0 -1
- package/test/eyelang/conformance/cases/extension/033_aggregate_min_template.pl +0 -5
- package/test/eyelang/conformance/cases/extension/033_aggregate_min_template.query +0 -1
- package/test/eyelang/conformance/cases/extension/034_aggregate_max_compound_key.pl +0 -5
- package/test/eyelang/conformance/cases/extension/034_aggregate_max_compound_key.query +0 -1
- package/test/eyelang/conformance/cases/extension/035_date_difference.pl +0 -4
- package/test/eyelang/conformance/cases/extension/036_reusable_numeric_builtins.pl +0 -10
- package/test/eyelang/conformance/cases/extension/037_reusable_list_builtins.pl +0 -11
- package/test/eyelang/conformance/cases/extension/038_reusable_string_builtins.pl +0 -12
- package/test/eyelang/conformance/cases/extension/039_reusable_term_control_builtins.pl +0 -11
- package/test/eyelang/conformance/cases/extension/044_matches_named_captures.pl +0 -13
- package/test/eyelang/conformance/expected/001_fact_output.pl +0 -1
- package/test/eyelang/conformance/expected/002_rule_recursion.pl +0 -2
- package/test/eyelang/conformance/expected/003_terms_and_readback.pl +0 -13
- package/test/eyelang/conformance/expected/004_conjunction_and_parentheses.pl +0 -1
- package/test/eyelang/conformance/expected/005_list_deconstruction.pl +0 -2
- package/test/eyelang/conformance/expected/006_comma_formula_data.pl +0 -1
- package/test/eyelang/conformance/expected/007_anonymous_variables.pl +0 -1
- package/test/eyelang/conformance/expected/008_graphic_atoms.pl +0 -3
- package/test/eyelang/conformance/expected/009_comments_and_whitespace.pl +0 -2
- package/test/eyelang/conformance/expected/010_variable_scope_and_reuse.pl +0 -2
- package/test/eyelang/conformance/expected/011_predicate_arity.pl +0 -2
- package/test/eyelang/conformance/expected/012_nested_compound_unification.pl +0 -2
- package/test/eyelang/conformance/expected/013_multiple_clauses_order.pl +0 -2
- package/test/eyelang/conformance/expected/014_failure_filters_answers.pl +0 -1
- package/test/eyelang/conformance/expected/015_improper_list_unification.pl +0 -3
- package/test/eyelang/conformance/expected/016_zero_arity_compound.pl +0 -1
- package/test/eyelang/conformance/expected/017_three_step_recursion.pl +0 -3
- package/test/eyelang/conformance/expected/018_quoted_atom_readback.pl +0 -3
- package/test/eyelang/conformance/expected/019_parenthesized_three_conjuncts.pl +0 -1
- package/test/eyelang/conformance/expected/020_nested_list_terms.pl +0 -2
- package/test/eyelang/conformance/expected/021_repeated_variable_head.pl +0 -2
- package/test/eyelang/conformance/expected/022_rule_head_structure.pl +0 -2
- package/test/eyelang/conformance/expected/023_quoted_escapes_readback.pl +0 -2
- package/test/eyelang/conformance/expected/024_numeric_literal_readback.pl +0 -3
- package/test/eyelang/conformance/expected/025_body_parentheses_with_formula_data.pl +0 -1
- package/test/eyelang/conformance/expected/026_underscore_named_variable_reuse.pl +0 -1
- package/test/eyelang/conformance/expected/027_default_derived_output.pl +0 -3
- package/test/eyelang/conformance/expected/028_materialize_focus.pl +0 -1
- package/test/eyelang/conformance/expected/029_arithmetic_and_comparison.pl +0 -9
- package/test/eyelang/conformance/expected/030_strings_and_atoms.pl +0 -2
- package/test/eyelang/conformance/expected/031_lists_aggregation_ordering.pl +0 -9
- package/test/eyelang/conformance/expected/032_holds_parts.pl +0 -3
- package/test/eyelang/conformance/expected/033_negation_once_generators.pl +0 -2
- package/test/eyelang/conformance/expected/034_equality_and_inequality.pl +0 -4
- package/test/eyelang/conformance/expected/035_list_relations.pl +0 -4
- package/test/eyelang/conformance/expected/036_append_splits.pl +0 -3
- package/test/eyelang/conformance/expected/037_matching_and_comparison.pl +0 -5
- package/test/eyelang/conformance/expected/038_memoize_declaration.pl +0 -2
- package/test/eyelang/conformance/expected/039_numeric_functions.pl +0 -7
- package/test/eyelang/conformance/expected/040_between_enumeration.pl +0 -3
- package/test/eyelang/conformance/expected/041_smallest_divisor.pl +0 -1
- package/test/eyelang/conformance/expected/042_negation_filter.pl +0 -2
- package/test/eyelang/conformance/expected/043_once_user_predicate.pl +0 -1
- package/test/eyelang/conformance/expected/044_findall_user_goal.pl +0 -1
- package/test/eyelang/conformance/expected/045_sort_deduplicates_atoms.pl +0 -1
- package/test/eyelang/conformance/expected/046_append_bound_prefix_suffix.pl +0 -2
- package/test/eyelang/conformance/expected/047_nth0_index_generation.pl +0 -1
- package/test/eyelang/conformance/expected/048_set_nth0_edges.pl +0 -2
- package/test/eyelang/conformance/expected/049_select_duplicate_occurrences.pl +0 -2
- package/test/eyelang/conformance/expected/050_not_member_filter.pl +0 -1
- package/test/eyelang/conformance/expected/051_nested_holds_parts.pl +0 -3
- package/test/eyelang/conformance/expected/052_holds_member.pl +0 -2
- package/test/eyelang/conformance/expected/053_materialize_excludes_source_fact.pl +0 -1
- package/test/eyelang/conformance/expected/054_numeric_and_lexical_comparison.pl +0 -3
- package/test/eyelang/conformance/expected/055_string_matching_filters.pl +0 -2
- package/test/eyelang/conformance/expected/056_string_and_atom_concat.pl +0 -1
- package/test/eyelang/conformance/expected/057_countall_empty_and_nonempty.pl +0 -1
- package/test/eyelang/conformance/expected/058_sumall_numeric_template.pl +0 -1
- package/test/eyelang/conformance/expected/059_aggregate_min_template.pl +0 -1
- package/test/eyelang/conformance/expected/060_aggregate_max_compound_key.pl +0 -1
- package/test/eyelang/conformance/expected/061_date_difference.pl +0 -2
- package/test/eyelang/conformance/expected/062_reusable_numeric_builtins.pl +0 -8
- package/test/eyelang/conformance/expected/063_reusable_list_builtins.pl +0 -9
- package/test/eyelang/conformance/expected/064_reusable_string_builtins.pl +0 -10
- package/test/eyelang/conformance/expected/065_reusable_term_control_builtins.pl +0 -6
- package/test/eyelang/conformance/expected/066_numeric_edges.pl +0 -12
- package/test/eyelang/conformance/expected/067_list_edges.pl +0 -8
- package/test/eyelang/conformance/expected/068_list_generation_order.pl +0 -10
- package/test/eyelang/conformance/expected/069_list_summaries_and_sets.pl +0 -7
- package/test/eyelang/conformance/expected/070_matches_named_captures.pl +0 -1
- package/test/eyelang/conformance/expected/071_string_edges.pl +0 -8
- package/test/eyelang/conformance/expected/072_string_conversions.pl +0 -8
- package/test/eyelang/conformance/expected/073_term_introspection_edges.pl +0 -8
- package/test/eyelang/conformance/expected/074_forall_edges.pl +0 -5
- package/test/eyelang/conformance/expected/075_aggregation_edges.pl +0 -7
- package/test/eyelang/conformance/expected/076_composed_reusable_builtins.pl +0 -5
- package/test/eyelang/conformance/expected/077_recursive_path_with_lists.pl +0 -3
- package/test/eyelang/conformance/expected/078_mutual_recursion_with_arithmetic.pl +0 -7
- package/test/eyelang/conformance/expected/079_big_integer_arithmetic.pl +0 -6
- package/test/eyelang/conformance/expected/080_rounding_modes.pl +0 -8
- package/test/eyelang/conformance/expected/081_zero_safe_numeric_functions.pl +0 -7
- package/test/eyelang/conformance/expected/082_comparison_semantics.pl +0 -8
- package/test/eyelang/conformance/expected/083_between_modes_and_empty_ranges.pl +0 -8
- package/test/eyelang/conformance/expected/084_append_and_select_composition.pl +0 -10
- package/test/eyelang/conformance/expected/085_nth_and_update_edges.pl +0 -8
- package/test/eyelang/conformance/expected/086_slicing_pipeline.pl +0 -7
- package/test/eyelang/conformance/expected/087_sort_reverse_length.pl +0 -6
- package/test/eyelang/conformance/expected/088_list_summaries_failures.pl +0 -6
- package/test/eyelang/conformance/expected/089_string_split_join_pipeline.pl +0 -4
- package/test/eyelang/conformance/expected/090_string_substring_replace_edges.pl +0 -7
- package/test/eyelang/conformance/expected/091_string_case_and_trim.pl +0 -5
- package/test/eyelang/conformance/expected/092_scalar_string_conversions.pl +0 -7
- package/test/eyelang/conformance/expected/093_regex_named_captures_context.pl +0 -5
- package/test/eyelang/conformance/expected/094_context_holds_enumeration.pl +0 -8
- package/test/eyelang/conformance/expected/095_term_introspection_roundtrip.pl +0 -6
- package/test/eyelang/conformance/expected/096_functor_scalar_edges.pl +0 -6
- package/test/eyelang/conformance/expected/097_control_negation_once_forall.pl +0 -5
- package/test/eyelang/conformance/expected/098_aggregation_nested_templates.pl +0 -5
- package/test/eyelang/conformance/expected/099_materialize_multiple_arities.pl +0 -4
- package/test/eyelang/conformance/expected/100_reusable_builtin_workflow.pl +0 -6
- package/test/eyelang/conformance/expected/core/001_fact_output.out +0 -1
- package/test/eyelang/conformance/expected/core/002_rule_recursion.out +0 -2
- package/test/eyelang/conformance/expected/core/003_terms_and_readback.out +0 -13
- package/test/eyelang/conformance/expected/core/004_conjunction_and_parentheses.out +0 -1
- package/test/eyelang/conformance/expected/core/005_list_deconstruction.out +0 -2
- package/test/eyelang/conformance/expected/core/006_comma_formula_data.out +0 -1
- package/test/eyelang/conformance/expected/core/007_anonymous_variables.out +0 -1
- package/test/eyelang/conformance/expected/core/008_graphic_atoms.out +0 -3
- package/test/eyelang/conformance/expected/core/009_comments_and_whitespace.out +0 -2
- package/test/eyelang/conformance/expected/core/010_variable_scope_and_reuse.out +0 -2
- package/test/eyelang/conformance/expected/core/011_predicate_arity.out +0 -2
- package/test/eyelang/conformance/expected/core/012_nested_compound_unification.out +0 -2
- package/test/eyelang/conformance/expected/core/013_multiple_clauses_order.out +0 -2
- package/test/eyelang/conformance/expected/core/014_failure_filters_answers.out +0 -1
- package/test/eyelang/conformance/expected/core/015_improper_list_unification.out +0 -3
- package/test/eyelang/conformance/expected/core/016_zero_arity_compound.out +0 -1
- package/test/eyelang/conformance/expected/core/017_three_step_recursion.out +0 -3
- package/test/eyelang/conformance/expected/core/018_quoted_atom_readback.out +0 -3
- package/test/eyelang/conformance/expected/core/019_parenthesized_three_conjuncts.out +0 -1
- package/test/eyelang/conformance/expected/core/020_nested_list_terms.out +0 -2
- package/test/eyelang/conformance/expected/core/021_repeated_variable_head.out +0 -2
- package/test/eyelang/conformance/expected/core/022_rule_head_structure.out +0 -2
- package/test/eyelang/conformance/expected/core/023_quoted_escapes_readback.out +0 -2
- package/test/eyelang/conformance/expected/core/024_numeric_literal_readback.out +0 -3
- package/test/eyelang/conformance/expected/core/025_body_parentheses_with_formula_data.out +0 -1
- package/test/eyelang/conformance/expected/core/026_underscore_named_variable_reuse.out +0 -1
- package/test/eyelang/conformance/expected/extension/001_default_derived_output.out +0 -3
- package/test/eyelang/conformance/expected/extension/002_materialize_focus.out +0 -1
- package/test/eyelang/conformance/expected/extension/003_arithmetic_and_comparison.out +0 -9
- package/test/eyelang/conformance/expected/extension/004_strings_and_atoms.out +0 -2
- package/test/eyelang/conformance/expected/extension/005_lists_aggregation_ordering.out +0 -9
- package/test/eyelang/conformance/expected/extension/006_holds_parts.out +0 -3
- package/test/eyelang/conformance/expected/extension/007_negation_once_generators.out +0 -2
- package/test/eyelang/conformance/expected/extension/008_equality_and_inequality.out +0 -4
- package/test/eyelang/conformance/expected/extension/009_list_relations.out +0 -4
- package/test/eyelang/conformance/expected/extension/010_append_splits.out +0 -3
- package/test/eyelang/conformance/expected/extension/011_matching_and_comparison.out +0 -5
- package/test/eyelang/conformance/expected/extension/012_memoize_declaration.out +0 -2
- package/test/eyelang/conformance/expected/extension/013_numeric_functions.out +0 -7
- package/test/eyelang/conformance/expected/extension/014_between_enumeration.out +0 -3
- package/test/eyelang/conformance/expected/extension/015_smallest_divisor.out +0 -1
- package/test/eyelang/conformance/expected/extension/016_negation_filter.out +0 -2
- package/test/eyelang/conformance/expected/extension/017_once_user_predicate.out +0 -1
- package/test/eyelang/conformance/expected/extension/018_findall_user_goal.out +0 -1
- package/test/eyelang/conformance/expected/extension/019_sort_deduplicates_atoms.out +0 -1
- package/test/eyelang/conformance/expected/extension/020_append_bound_prefix_suffix.out +0 -2
- package/test/eyelang/conformance/expected/extension/021_nth0_index_generation.out +0 -1
- package/test/eyelang/conformance/expected/extension/022_set_nth0_edges.out +0 -2
- package/test/eyelang/conformance/expected/extension/023_select_duplicate_occurrences.out +0 -2
- package/test/eyelang/conformance/expected/extension/024_not_member_filter.out +0 -1
- package/test/eyelang/conformance/expected/extension/026_nested_holds_parts.out +0 -3
- package/test/eyelang/conformance/expected/extension/027_holds_member.out +0 -2
- package/test/eyelang/conformance/expected/extension/027_materialize_excludes_source_fact.out +0 -1
- package/test/eyelang/conformance/expected/extension/028_numeric_and_lexical_comparison.out +0 -3
- package/test/eyelang/conformance/expected/extension/029_string_matching_filters.out +0 -2
- package/test/eyelang/conformance/expected/extension/030_string_and_atom_concat.out +0 -1
- package/test/eyelang/conformance/expected/extension/031_countall_empty_and_nonempty.out +0 -1
- package/test/eyelang/conformance/expected/extension/032_sumall_numeric_template.out +0 -1
- package/test/eyelang/conformance/expected/extension/033_aggregate_min_template.out +0 -1
- package/test/eyelang/conformance/expected/extension/034_aggregate_max_compound_key.out +0 -1
- package/test/eyelang/conformance/expected/extension/035_date_difference.out +0 -2
- package/test/eyelang/conformance/expected/extension/036_reusable_numeric_builtins.out +0 -8
- package/test/eyelang/conformance/expected/extension/037_reusable_list_builtins.out +0 -9
- package/test/eyelang/conformance/expected/extension/038_reusable_string_builtins.out +0 -10
- package/test/eyelang/conformance/expected/extension/039_reusable_term_control_builtins.out +0 -6
- package/test/eyelang/conformance/expected/extension/044_matches_named_captures.out +0 -1
- package/test/eyelang/run-all.mjs +0 -20
- package/test/eyelang/run-conformance.mjs +0 -78
- package/test/eyelang/run-examples.mjs +0 -125
- package/test/eyelang/run-regression.mjs +0 -612
- package/test/eyelang/test-style.mjs +0 -94
- package/test/eyelang.test.js +0 -58
package/README.md
CHANGED
|
@@ -224,6 +224,25 @@ The CLI renders the `log:outputString` values directly:
|
|
|
224
224
|
hello
|
|
225
225
|
```
|
|
226
226
|
|
|
227
|
+
### Predicate memoization
|
|
228
|
+
|
|
229
|
+
Eyeling supports a predicate-local performance directive for backward rules:
|
|
230
|
+
|
|
231
|
+
```n3
|
|
232
|
+
@prefix log: <http://www.w3.org/2000/10/swap/log#> .
|
|
233
|
+
|
|
234
|
+
:predicate log:memoize true .
|
|
235
|
+
```
|
|
236
|
+
|
|
237
|
+
A top-level `log:memoize true` triple is treated as an engine directive rather than an RDF fact. It asks the backward prover to reuse completed answers for that predicate during the current reasoning run. This is especially useful for recursive predicates with overlapping subgoals, such as the direct Fibonacci recurrence or Collatz trajectories where many starting values share suffixes:
|
|
238
|
+
|
|
239
|
+
```n3
|
|
240
|
+
:fibonacci log:memoize true .
|
|
241
|
+
:collatz log:memoize true .
|
|
242
|
+
```
|
|
243
|
+
|
|
244
|
+
Memoization is intentionally selective. It can slow down pure generators, predicates with mostly unique states, or small linear recursions because maintaining the table costs more than recomputation. Prefer it for dynamic-programming-shaped predicates that are called repeatedly with the same bound subject or object. The examples `examples/fibonacci.n3`, `examples/collatz-1000.n3`, and `examples/fundamental-theorem-arithmetic.n3` show cases where the directive helps.
|
|
245
|
+
|
|
227
246
|
---
|
|
228
247
|
|
|
229
248
|
## Command-line interface
|
|
@@ -743,6 +762,8 @@ Eyeling supports both native N3 list terms and materialized RDF collections. Ano
|
|
|
743
762
|
|
|
744
763
|
Formula-aware built-ins make Eyeling useful for meta-reasoning. `log:includes`, `log:notIncludes`, `log:collectAllIn`, and `log:forAllIn` prove goals inside formula scopes. `log:query` selects output triples, while `log:outputString` writes selected string values directly to stdout.
|
|
745
764
|
|
|
765
|
+
`log:memoize` is a top-level performance directive for backward predicates, not an RDF-producing fact and not a general-purpose built-in. Use it when a recursive predicate has overlapping subgoals whose completed answers are likely to be requested again.
|
|
766
|
+
|
|
746
767
|
`log:semantics`, `log:content`, and related built-ins may dereference sources. Use `--enforce-https` or `{ enforceHttps: true }` in environments where HTTP-to-HTTPS rewriting is required.
|
|
747
768
|
|
|
748
769
|
|
|
@@ -901,6 +922,8 @@ The backward prover solves rule bodies. It can match current facts, use backward
|
|
|
901
922
|
{ :example :works true } .
|
|
902
923
|
```
|
|
903
924
|
|
|
925
|
+
For selected predicates, `:predicate log:memoize true .` enables tabling of completed backward answers. This preserves the normal declarative reading of the backward rules but can turn repeated recursive work into table lookups. The directive is removed from the data facts before reasoning, so it does not appear in normal output.
|
|
926
|
+
|
|
904
927
|
### Dynamic rules
|
|
905
928
|
|
|
906
929
|
Eyeling treats top-level `log:implies` and `log:impliedBy` as rule forms and can activate derived implication facts as live rules during reasoning. This supports programs that derive rules as part of their logic.
|
|
@@ -1042,6 +1065,16 @@ The repository contains more than two hundred N3 examples under `examples/`, RDF
|
|
|
1042
1065
|
| `examples/rdf-messages.n3` | RDF Message Log replay. |
|
|
1043
1066
|
| `examples/context-schema-audit.n3` | Quoted-context schema validation with `log:includes` and list arity checks. |
|
|
1044
1067
|
|
|
1068
|
+
### Memoization examples
|
|
1069
|
+
|
|
1070
|
+
These examples demonstrate `log:memoize` on predicates that benefit from reusing completed backward-rule answers:
|
|
1071
|
+
|
|
1072
|
+
| Example | Memoized predicate | Why it helps |
|
|
1073
|
+
|---|---|---|
|
|
1074
|
+
| `examples/fibonacci.n3` | `:fibonacci` | The direct recurrence repeatedly asks for the same smaller Fibonacci numbers. |
|
|
1075
|
+
| `examples/collatz-1000.n3` | `:collatz` | Many starting values share Collatz suffix trajectories. |
|
|
1076
|
+
| `examples/fundamental-theorem-arithmetic.n3` | `:smallestDivisorFrom`, `:factorSmallest` | Factorization and independent checks reuse trial-division and factor-list subgoals. |
|
|
1077
|
+
|
|
1045
1078
|
### Running all examples through tests
|
|
1046
1079
|
|
|
1047
1080
|
```bash
|
|
@@ -6242,7 +6242,7 @@ function runParsedDocumentOnce(mergedDocument, { rdfMode = false, outputPrefixes
|
|
|
6242
6242
|
let outTriples = [];
|
|
6243
6243
|
let queryDerived = [];
|
|
6244
6244
|
if (hasQueries) {
|
|
6245
|
-
const res = engine.forwardChainAndCollectLogQueryConclusions(facts, frules, brules, qrules, { prefixes });
|
|
6245
|
+
const res = engine.forwardChainAndCollectLogQueryConclusions(facts, frules, brules, qrules, null, { captureExplanations: false, prefixes });
|
|
6246
6246
|
derived = res.derived;
|
|
6247
6247
|
outTriples = res.queryTriples;
|
|
6248
6248
|
queryDerived = res.queryDerived || [];
|
|
@@ -6929,7 +6929,7 @@ function factsContainOutputStrings(triplesForOutput) {
|
|
|
6929
6929
|
let outDerived = [];
|
|
6930
6930
|
|
|
6931
6931
|
if (hasQueries) {
|
|
6932
|
-
const res = engine.forwardChainAndCollectLogQueryConclusions(facts, frules, brules, qrules, { prefixes });
|
|
6932
|
+
const res = engine.forwardChainAndCollectLogQueryConclusions(facts, frules, brules, qrules, null, { captureExplanations: engine.getProofCommentsEnabled(), prefixes });
|
|
6933
6933
|
derived = res.derived;
|
|
6934
6934
|
outTriples = res.queryTriples;
|
|
6935
6935
|
outDerived = res.queryDerived;
|
|
@@ -7507,6 +7507,7 @@ const LOG_COLLECT_ALL_IN_IRI = LOG_NS + 'collectAllIn';
|
|
|
7507
7507
|
const LOG_FOR_ALL_IN_IRI = LOG_NS + 'forAllIn';
|
|
7508
7508
|
const LOG_INCLUDES_IRI = LOG_NS + 'includes';
|
|
7509
7509
|
const LOG_NOT_INCLUDES_IRI = LOG_NS + 'notIncludes';
|
|
7510
|
+
const LOG_MEMOIZE_IRI = LOG_NS + 'memoize';
|
|
7510
7511
|
const LOG_IMPLIES_IRI = LOG_NS + 'implies';
|
|
7511
7512
|
const LOG_IMPLIED_BY_IRI = LOG_NS + 'impliedBy';
|
|
7512
7513
|
|
|
@@ -7608,6 +7609,7 @@ const FACT_INDEX_ARRAY_MAP_FIELDS = ['__byPred', '__byPNonFastS', '__byPNonFastO
|
|
|
7608
7609
|
const FACT_INDEX_NESTED_ARRAY_MAP_FIELDS = ['__byPS', '__byPO'];
|
|
7609
7610
|
const FACT_INDEX_MAP_FIELDS = FACT_INDEX_ARRAY_MAP_FIELDS.concat(FACT_INDEX_NESTED_ARRAY_MAP_FIELDS);
|
|
7610
7611
|
const FACT_INDEX_REQUIRED_FIELDS = FACT_INDEX_ARRAY_FIELDS.concat(FACT_INDEX_MAP_FIELDS, ['__keySet']);
|
|
7612
|
+
const FACT_INDEX_ALL_FIELDS = FACT_INDEX_REQUIRED_FIELDS.concat(['__keySetComplete']);
|
|
7611
7613
|
|
|
7612
7614
|
let version = 'dev';
|
|
7613
7615
|
try {
|
|
@@ -8675,7 +8677,13 @@ function termLookupKey(t) {
|
|
|
8675
8677
|
return t.__tid;
|
|
8676
8678
|
}
|
|
8677
8679
|
if (t instanceof Blank) return t.__tid;
|
|
8678
|
-
if (t instanceof Literal)
|
|
8680
|
+
if (t instanceof Literal) {
|
|
8681
|
+
const cached = t.__lookupKey;
|
|
8682
|
+
if (cached !== undefined) return cached;
|
|
8683
|
+
const key = literalLookupKey(t);
|
|
8684
|
+
Object.defineProperty(t, '__lookupKey', { value: key, enumerable: false });
|
|
8685
|
+
return key;
|
|
8686
|
+
}
|
|
8679
8687
|
|
|
8680
8688
|
if (t instanceof ListTerm) {
|
|
8681
8689
|
const cached = t.__lookupKey;
|
|
@@ -8713,6 +8721,13 @@ function tripleFastKey(tr) {
|
|
|
8713
8721
|
return ks + '\t' + kp + '\t' + ko;
|
|
8714
8722
|
}
|
|
8715
8723
|
|
|
8724
|
+
function resetFactIndexes(facts) {
|
|
8725
|
+
if (!facts) return;
|
|
8726
|
+
for (const name of FACT_INDEX_ALL_FIELDS) {
|
|
8727
|
+
try { delete facts[name]; } catch {}
|
|
8728
|
+
}
|
|
8729
|
+
}
|
|
8730
|
+
|
|
8716
8731
|
function ensureFactIndexes(facts) {
|
|
8717
8732
|
if (FACT_INDEX_REQUIRED_FIELDS.every((name) => facts[name])) return;
|
|
8718
8733
|
|
|
@@ -9143,6 +9158,157 @@ function isLogImpliedBy(p) {
|
|
|
9143
9158
|
return p instanceof Iri && p.value === LOG_IMPLIED_BY_IRI;
|
|
9144
9159
|
}
|
|
9145
9160
|
|
|
9161
|
+
function isLogMemoize(p) {
|
|
9162
|
+
return p instanceof Iri && p.value === LOG_MEMOIZE_IRI;
|
|
9163
|
+
}
|
|
9164
|
+
|
|
9165
|
+
function isTruthyMemoizeObject(o) {
|
|
9166
|
+
if (!(o instanceof Literal)) return false;
|
|
9167
|
+
if (o.value === 'true') return true;
|
|
9168
|
+
const info = parseBooleanLiteralInfo(o);
|
|
9169
|
+
return !!(info && info.value === true);
|
|
9170
|
+
}
|
|
9171
|
+
|
|
9172
|
+
// ===========================================================================
|
|
9173
|
+
// Predicate memoization declarations
|
|
9174
|
+
// ===========================================================================
|
|
9175
|
+
//
|
|
9176
|
+
// Eyeling accepts top-level declarations of the form:
|
|
9177
|
+
// :predicate log:memoize true.
|
|
9178
|
+
// They are engine directives, not data facts. Each declaration asks the
|
|
9179
|
+
// backward prover to table completed answers for that predicate during the
|
|
9180
|
+
// current reasoning scope. The hint is deliberately predicate-local and
|
|
9181
|
+
// conservative: unbound calls and finite-result probes still use the normal
|
|
9182
|
+
// path, and cached answers are invalidated when the fact/rule scope changes.
|
|
9183
|
+
|
|
9184
|
+
function __extractLogMemoizeDeclarations(facts) {
|
|
9185
|
+
const memoized = new Set();
|
|
9186
|
+
if (!Array.isArray(facts) || facts.length === 0) return memoized;
|
|
9187
|
+
|
|
9188
|
+
let write = 0;
|
|
9189
|
+
let removed = false;
|
|
9190
|
+
for (let read = 0; read < facts.length; read++) {
|
|
9191
|
+
const tr = facts[read];
|
|
9192
|
+
if (tr && isLogMemoize(tr.p) && tr.s instanceof Iri && isTruthyMemoizeObject(tr.o)) {
|
|
9193
|
+
memoized.add(tr.s.__tid);
|
|
9194
|
+
removed = true;
|
|
9195
|
+
continue;
|
|
9196
|
+
}
|
|
9197
|
+
if (write !== read) facts[write] = tr;
|
|
9198
|
+
write++;
|
|
9199
|
+
}
|
|
9200
|
+
|
|
9201
|
+
if (removed) {
|
|
9202
|
+
facts.length = write;
|
|
9203
|
+
resetFactIndexes(facts);
|
|
9204
|
+
}
|
|
9205
|
+
return memoized;
|
|
9206
|
+
}
|
|
9207
|
+
|
|
9208
|
+
function __attachMemoizedPredicates(scopeCarrier, memoized) {
|
|
9209
|
+
if (!scopeCarrier || !memoized || memoized.size === 0) return;
|
|
9210
|
+
__setHiddenWritable(scopeCarrier, 'memoizedPredicates', memoized);
|
|
9211
|
+
}
|
|
9212
|
+
|
|
9213
|
+
function __memoizedPredicateSet(facts, backRules) {
|
|
9214
|
+
return (facts && facts.memoizedPredicates) || (backRules && backRules.memoizedPredicates) || null;
|
|
9215
|
+
}
|
|
9216
|
+
|
|
9217
|
+
function __predicateIsMemoized(facts, backRules, p) {
|
|
9218
|
+
if (!(p instanceof Iri)) return false;
|
|
9219
|
+
const memoized = __memoizedPredicateSet(facts, backRules);
|
|
9220
|
+
return !!(memoized && memoized.has(p.__tid));
|
|
9221
|
+
}
|
|
9222
|
+
|
|
9223
|
+
function __makePredicateMemoTable() {
|
|
9224
|
+
return {
|
|
9225
|
+
scopeVersion: null,
|
|
9226
|
+
entries: new Map(),
|
|
9227
|
+
};
|
|
9228
|
+
}
|
|
9229
|
+
|
|
9230
|
+
function __ensurePredicateMemoTable(facts, backRules) {
|
|
9231
|
+
let table = (facts && facts.predicateMemoTable) || (backRules && backRules.predicateMemoTable) || null;
|
|
9232
|
+
if (!table) table = __makePredicateMemoTable();
|
|
9233
|
+
__setHiddenWritable(facts, 'predicateMemoTable', table);
|
|
9234
|
+
__setHiddenWritable(backRules, 'predicateMemoTable', table);
|
|
9235
|
+
|
|
9236
|
+
const version = goalTableScopeVersion(facts, backRules);
|
|
9237
|
+
if (table.scopeVersion !== version) {
|
|
9238
|
+
table.scopeVersion = version;
|
|
9239
|
+
table.entries.clear();
|
|
9240
|
+
}
|
|
9241
|
+
return table;
|
|
9242
|
+
}
|
|
9243
|
+
|
|
9244
|
+
function __memoKeyPart(t) {
|
|
9245
|
+
if (__termHasVarOrBlank(t)) return { bound: false, text: '_' };
|
|
9246
|
+
const fast = termLookupKey(t);
|
|
9247
|
+
if (fast !== null) return { bound: true, text: encodeLookupKeyPart(fast) };
|
|
9248
|
+
return { bound: true, text: skolemKeyFromTerm(t) };
|
|
9249
|
+
}
|
|
9250
|
+
|
|
9251
|
+
function __predicateMemoKey(goal) {
|
|
9252
|
+
if (!(goal && goal.p instanceof Iri)) return null;
|
|
9253
|
+
const sPart = __memoKeyPart(goal.s);
|
|
9254
|
+
const oPart = __memoKeyPart(goal.o);
|
|
9255
|
+
if (!sPart.bound && !oPart.bound) return null;
|
|
9256
|
+
return `${goal.p.__tid}|${sPart.text}|${oPart.text}`;
|
|
9257
|
+
}
|
|
9258
|
+
|
|
9259
|
+
function __makePredicateMemoEntry() {
|
|
9260
|
+
return {
|
|
9261
|
+
computing: false,
|
|
9262
|
+
complete: false,
|
|
9263
|
+
unsafe: false,
|
|
9264
|
+
answers: [],
|
|
9265
|
+
answerKeys: new Set(),
|
|
9266
|
+
};
|
|
9267
|
+
}
|
|
9268
|
+
|
|
9269
|
+
function __getPredicateMemoEntry(facts, backRules, key) {
|
|
9270
|
+
const table = __ensurePredicateMemoTable(facts, backRules);
|
|
9271
|
+
let entry = table.entries.get(key);
|
|
9272
|
+
if (!entry) {
|
|
9273
|
+
entry = __makePredicateMemoEntry();
|
|
9274
|
+
table.entries.set(key, entry);
|
|
9275
|
+
}
|
|
9276
|
+
return entry;
|
|
9277
|
+
}
|
|
9278
|
+
|
|
9279
|
+
function __canStorePredicateMemo(maxResults) {
|
|
9280
|
+
return !(typeof maxResults === 'number' && maxResults > 0);
|
|
9281
|
+
}
|
|
9282
|
+
|
|
9283
|
+
function __canMemoizeAnswerTerm(t) {
|
|
9284
|
+
if (t instanceof Var || t instanceof OpenListTerm) return false;
|
|
9285
|
+
if (t instanceof ListTerm) return t.elems.every(__canMemoizeAnswerTerm);
|
|
9286
|
+
if (t instanceof GraphTerm) return t.triples.every((tr) => __canMemoizeAnswerTerm(tr.s) && __canMemoizeAnswerTerm(tr.p) && __canMemoizeAnswerTerm(tr.o));
|
|
9287
|
+
return true;
|
|
9288
|
+
}
|
|
9289
|
+
|
|
9290
|
+
function __memoAnswerKeyPart(t) {
|
|
9291
|
+
const fast = termLookupKey(t);
|
|
9292
|
+
if (fast !== null) return encodeLookupKeyPart(fast);
|
|
9293
|
+
return skolemKeyFromTerm(t);
|
|
9294
|
+
}
|
|
9295
|
+
|
|
9296
|
+
function __memoAnswerKey(tr) {
|
|
9297
|
+
return __memoAnswerKeyPart(tr.s) + '\t' + __memoAnswerKeyPart(tr.p) + '\t' + __memoAnswerKeyPart(tr.o);
|
|
9298
|
+
}
|
|
9299
|
+
|
|
9300
|
+
function __storePredicateMemoAnswer(entry, rawGoal, subst) {
|
|
9301
|
+
const answer = applySubstTriple(rawGoal, subst || {});
|
|
9302
|
+
if (!__canMemoizeAnswerTerm(answer.s) || !__canMemoizeAnswerTerm(answer.p) || !__canMemoizeAnswerTerm(answer.o)) {
|
|
9303
|
+
entry.unsafe = true;
|
|
9304
|
+
return;
|
|
9305
|
+
}
|
|
9306
|
+
const key = __memoAnswerKey(answer);
|
|
9307
|
+
if (entry.answerKeys.has(key)) return;
|
|
9308
|
+
entry.answerKeys.add(key);
|
|
9309
|
+
entry.answers.push(answer);
|
|
9310
|
+
}
|
|
9311
|
+
|
|
9146
9312
|
// ===========================================================================
|
|
9147
9313
|
// Completed-goal answer tables (minimal tabling)
|
|
9148
9314
|
// ===========================================================================
|
|
@@ -10056,6 +10222,47 @@ function proveGoals(goals, subst, facts, backRules, depth, visited, varGen, maxR
|
|
|
10056
10222
|
continue;
|
|
10057
10223
|
}
|
|
10058
10224
|
|
|
10225
|
+
if (frame.kind === 'memoComplete') {
|
|
10226
|
+
frame.entry.computing = false;
|
|
10227
|
+
if (frame.entry.unsafe) {
|
|
10228
|
+
frame.table.entries.delete(frame.key);
|
|
10229
|
+
} else {
|
|
10230
|
+
frame.entry.complete = true;
|
|
10231
|
+
}
|
|
10232
|
+
continue;
|
|
10233
|
+
}
|
|
10234
|
+
|
|
10235
|
+
if (frame.kind === 'memoAnswerIter') {
|
|
10236
|
+
const answers = frame.entry.answers;
|
|
10237
|
+
while (frame.idx < answers.length && results.length < max) {
|
|
10238
|
+
const answer = answers[frame.idx++];
|
|
10239
|
+
const mark = trail.length;
|
|
10240
|
+
if (!unifyTripleTrail(frame.goal0, answer)) {
|
|
10241
|
+
undoTo(mark);
|
|
10242
|
+
continue;
|
|
10243
|
+
}
|
|
10244
|
+
|
|
10245
|
+
if (!frame.restGoals.length) {
|
|
10246
|
+
results.push(gcCompactForGoals(substMut, [], answerVars));
|
|
10247
|
+
undoTo(mark);
|
|
10248
|
+
if (results.length >= max) return results;
|
|
10249
|
+
continue;
|
|
10250
|
+
}
|
|
10251
|
+
|
|
10252
|
+
stack.push(frame);
|
|
10253
|
+
stack.push({ kind: 'undo', substMark: mark, visitedMark: visitedTrail.length });
|
|
10254
|
+
stack.push({
|
|
10255
|
+
kind: 'node',
|
|
10256
|
+
goalsNow: frame.restGoals,
|
|
10257
|
+
curDepth: frame.curDepth + 1,
|
|
10258
|
+
canDeferBuiltins: frame.canDeferBuiltins,
|
|
10259
|
+
deferCount: 0,
|
|
10260
|
+
});
|
|
10261
|
+
break;
|
|
10262
|
+
}
|
|
10263
|
+
continue;
|
|
10264
|
+
}
|
|
10265
|
+
|
|
10059
10266
|
if (frame.kind === 'deltaIter') {
|
|
10060
10267
|
const deltas = frame.deltas;
|
|
10061
10268
|
while (frame.idx < deltas.length && results.length < max) {
|
|
@@ -10197,7 +10404,21 @@ function proveGoals(goals, subst, facts, backRules, depth, visited, varGen, maxR
|
|
|
10197
10404
|
}
|
|
10198
10405
|
|
|
10199
10406
|
const rawGoal = goalsNow[0];
|
|
10200
|
-
|
|
10407
|
+
let restGoals = goalsNow.length > 1 ? goalsNow.slice(1) : [];
|
|
10408
|
+
|
|
10409
|
+
if (rawGoal && rawGoal.__kind === 'memoStore') {
|
|
10410
|
+
__storePredicateMemoAnswer(rawGoal.entry, rawGoal.goal, substMut);
|
|
10411
|
+
if (rawGoal.stop && restGoals.length === 0) continue;
|
|
10412
|
+
stack.push({
|
|
10413
|
+
kind: 'node',
|
|
10414
|
+
goalsNow: restGoals,
|
|
10415
|
+
curDepth: frame.curDepth,
|
|
10416
|
+
canDeferBuiltins: frame.canDeferBuiltins,
|
|
10417
|
+
deferCount: 0,
|
|
10418
|
+
});
|
|
10419
|
+
continue;
|
|
10420
|
+
}
|
|
10421
|
+
|
|
10201
10422
|
const goal0 = applySubstTriple(rawGoal, substMut);
|
|
10202
10423
|
|
|
10203
10424
|
// 1) Builtins
|
|
@@ -10293,8 +10514,46 @@ function proveGoals(goals, subst, facts, backRules, depth, visited, varGen, maxR
|
|
|
10293
10514
|
const goalKey = tripleKeyForVisited(goal0);
|
|
10294
10515
|
const goalWasVisited = visitedCounts.has(goalKey);
|
|
10295
10516
|
|
|
10517
|
+
let memoCompleteFrame = null;
|
|
10518
|
+
let memoReplayFrame = null;
|
|
10519
|
+
if (__predicateIsMemoized(facts, backRules, goal0.p)) {
|
|
10520
|
+
const memoKey = __predicateMemoKey(goal0);
|
|
10521
|
+
if (memoKey !== null) {
|
|
10522
|
+
const memoEntry = __getPredicateMemoEntry(facts, backRules, memoKey);
|
|
10523
|
+
if (memoEntry.complete) {
|
|
10524
|
+
stack.push({
|
|
10525
|
+
kind: 'memoAnswerIter',
|
|
10526
|
+
entry: memoEntry,
|
|
10527
|
+
idx: 0,
|
|
10528
|
+
goal0,
|
|
10529
|
+
restGoals,
|
|
10530
|
+
curDepth: frame.curDepth,
|
|
10531
|
+
canDeferBuiltins: frame.canDeferBuiltins,
|
|
10532
|
+
});
|
|
10533
|
+
continue;
|
|
10534
|
+
}
|
|
10535
|
+
if (!memoEntry.computing && __canStorePredicateMemo(maxResults)) {
|
|
10536
|
+
memoEntry.computing = true;
|
|
10537
|
+
const table = __ensurePredicateMemoTable(facts, backRules);
|
|
10538
|
+
memoReplayFrame = {
|
|
10539
|
+
kind: 'memoAnswerIter',
|
|
10540
|
+
entry: memoEntry,
|
|
10541
|
+
idx: 0,
|
|
10542
|
+
goal0,
|
|
10543
|
+
restGoals,
|
|
10544
|
+
curDepth: frame.curDepth,
|
|
10545
|
+
canDeferBuiltins: frame.canDeferBuiltins,
|
|
10546
|
+
};
|
|
10547
|
+
memoCompleteFrame = { kind: 'memoComplete', entry: memoEntry, table, key: memoKey };
|
|
10548
|
+
restGoals = [{ __kind: 'memoStore', entry: memoEntry, goal: rawGoal, stop: true }];
|
|
10549
|
+
}
|
|
10550
|
+
}
|
|
10551
|
+
}
|
|
10552
|
+
|
|
10296
10553
|
// 3) Backward rules (indexed by head predicate) — explored first
|
|
10297
10554
|
if (goal0.p instanceof Iri) {
|
|
10555
|
+
if (memoReplayFrame) stack.push(memoReplayFrame);
|
|
10556
|
+
if (memoCompleteFrame) stack.push(memoCompleteFrame);
|
|
10298
10557
|
ensureBackRuleIndexes(backRules);
|
|
10299
10558
|
const candRules = (backRules.__byHeadPred.get(goal0.p.__tid) || []).concat(backRules.__wildHeadPred);
|
|
10300
10559
|
|
|
@@ -10326,6 +10585,8 @@ function proveGoals(goals, subst, facts, backRules, depth, visited, varGen, maxR
|
|
|
10326
10585
|
});
|
|
10327
10586
|
}
|
|
10328
10587
|
} else {
|
|
10588
|
+
if (memoReplayFrame) stack.push(memoReplayFrame);
|
|
10589
|
+
if (memoCompleteFrame) stack.push(memoCompleteFrame);
|
|
10329
10590
|
// No IRI predicate: rule indexing doesn't apply; only try all facts.
|
|
10330
10591
|
stack.push({
|
|
10331
10592
|
kind: 'factIter',
|
|
@@ -10531,6 +10792,10 @@ function __exitReasoning(code, message /* optional */) {
|
|
|
10531
10792
|
function forwardChain(facts, forwardRules, backRules, onDerived /* optional */, opts = {}) {
|
|
10532
10793
|
enterReasoningRun();
|
|
10533
10794
|
try {
|
|
10795
|
+
const memoizedPredicates = __extractLogMemoizeDeclarations(facts);
|
|
10796
|
+
__attachMemoizedPredicates(facts, memoizedPredicates);
|
|
10797
|
+
__attachMemoizedPredicates(backRules, memoizedPredicates);
|
|
10798
|
+
|
|
10534
10799
|
ensureFactIndexes(facts);
|
|
10535
10800
|
ensureBackRuleIndexes(backRules);
|
|
10536
10801
|
|
|
@@ -11169,7 +11434,7 @@ function reasonStream(input, opts = {}) {
|
|
|
11169
11434
|
if (Array.isArray(logQueryRules) && logQueryRules.length) {
|
|
11170
11435
|
// Query-selection mode: derive full closure, then output only the unique
|
|
11171
11436
|
// instantiated conclusion triples of the log:query directives.
|
|
11172
|
-
const res = forwardChainAndCollectLogQueryConclusions(facts, frules, brules, logQueryRules, { prefixes });
|
|
11437
|
+
const res = forwardChainAndCollectLogQueryConclusions(facts, frules, brules, logQueryRules, null, { captureExplanations: proof, prefixes });
|
|
11173
11438
|
derived = res.derived;
|
|
11174
11439
|
queryTriples = res.queryTriples;
|
|
11175
11440
|
queryDerived = res.queryDerived;
|
|
@@ -11203,7 +11468,7 @@ function reasonStream(input, opts = {}) {
|
|
|
11203
11468
|
onDerived(payload);
|
|
11204
11469
|
}
|
|
11205
11470
|
},
|
|
11206
|
-
{ prefixes },
|
|
11471
|
+
{ captureExplanations: proof, prefixes },
|
|
11207
11472
|
);
|
|
11208
11473
|
}
|
|
11209
11474
|
|
|
@@ -14850,7 +15115,7 @@ function parseN3Text(text, opts = {}) {
|
|
|
14850
15115
|
}
|
|
14851
15116
|
|
|
14852
15117
|
const tokens = lex(text, { rdf });
|
|
14853
|
-
const parser = new Parser(tokens);
|
|
15118
|
+
const parser = new Parser(tokens, { sourceOffsets: sourceLocations });
|
|
14854
15119
|
if (baseIri) parser.prefixes.setBase(baseIri);
|
|
14855
15120
|
const [prefixes, triples, frules, brules, logQueryRules] = parser.parseDocument();
|
|
14856
15121
|
|
|
@@ -15125,7 +15390,7 @@ function annotateSourceOffset(obj, offset) {
|
|
|
15125
15390
|
}
|
|
15126
15391
|
|
|
15127
15392
|
class Parser {
|
|
15128
|
-
constructor(tokens) {
|
|
15393
|
+
constructor(tokens, options = {}) {
|
|
15129
15394
|
this.toks = tokens;
|
|
15130
15395
|
this.pos = 0;
|
|
15131
15396
|
this.prefixes = PrefixEnv.newDefault();
|
|
@@ -15139,6 +15404,7 @@ class Parser {
|
|
|
15139
15404
|
// makes derived output read naturally, e.g. ':s :p _:b.' preceding
|
|
15140
15405
|
// '_:b :q :r.'
|
|
15141
15406
|
this.pendingTriplesAfter = [];
|
|
15407
|
+
this.trackSourceOffsets = !!(options && options.sourceOffsets);
|
|
15142
15408
|
}
|
|
15143
15409
|
|
|
15144
15410
|
peek() {
|
|
@@ -15151,6 +15417,10 @@ class Parser {
|
|
|
15151
15417
|
return tok;
|
|
15152
15418
|
}
|
|
15153
15419
|
|
|
15420
|
+
annotateSourceOffset(obj, offset) {
|
|
15421
|
+
return this.trackSourceOffsets ? annotateSourceOffset(obj, offset) : obj;
|
|
15422
|
+
}
|
|
15423
|
+
|
|
15154
15424
|
fail(message, tok = this.peek()) {
|
|
15155
15425
|
const off = tok && typeof tok.offset === 'number' ? tok.offset : null;
|
|
15156
15426
|
throw new N3SyntaxError(message, off);
|
|
@@ -15255,12 +15525,12 @@ class Parser {
|
|
|
15255
15525
|
this.next();
|
|
15256
15526
|
const second = this.parseTerm();
|
|
15257
15527
|
this.expectDot();
|
|
15258
|
-
forwardRules.push(annotateSourceOffset(this.makeRule(first, second, true), statementOffset));
|
|
15528
|
+
forwardRules.push(this.annotateSourceOffset(this.makeRule(first, second, true), statementOffset));
|
|
15259
15529
|
} else if (this.peek().typ === 'OpImpliedBy') {
|
|
15260
15530
|
this.next();
|
|
15261
15531
|
const second = this.parseTerm();
|
|
15262
15532
|
this.expectDot();
|
|
15263
|
-
backwardRules.push(annotateSourceOffset(this.makeRule(first, second, false), statementOffset));
|
|
15533
|
+
backwardRules.push(this.annotateSourceOffset(this.makeRule(first, second, false), statementOffset));
|
|
15264
15534
|
} else {
|
|
15265
15535
|
let more;
|
|
15266
15536
|
|
|
@@ -15279,16 +15549,16 @@ class Parser {
|
|
|
15279
15549
|
|
|
15280
15550
|
// normalize explicit log:implies / log:impliedBy at top-level
|
|
15281
15551
|
for (const tr0 of more) {
|
|
15282
|
-
const tr = annotateSourceOffset(tr0, statementOffset);
|
|
15552
|
+
const tr = this.annotateSourceOffset(tr0, statementOffset);
|
|
15283
15553
|
if (isLogImplies(tr.p) && tr.s instanceof GraphTerm && tr.o instanceof GraphTerm) {
|
|
15284
|
-
forwardRules.push(annotateSourceOffset(this.makeRule(tr.s, tr.o, true), statementOffset));
|
|
15554
|
+
forwardRules.push(this.annotateSourceOffset(this.makeRule(tr.s, tr.o, true), statementOffset));
|
|
15285
15555
|
} else if (isLogImpliedBy(tr.p) && tr.s instanceof GraphTerm && tr.o instanceof GraphTerm) {
|
|
15286
|
-
backwardRules.push(annotateSourceOffset(this.makeRule(tr.s, tr.o, false), statementOffset));
|
|
15556
|
+
backwardRules.push(this.annotateSourceOffset(this.makeRule(tr.s, tr.o, false), statementOffset));
|
|
15287
15557
|
} else if (isLogQuery(tr.p) && tr.s instanceof GraphTerm && tr.o instanceof GraphTerm) {
|
|
15288
15558
|
// Output-selection directive: { premise } log:query { conclusion }.
|
|
15289
15559
|
// When present at top-level, eyeling prints only the instantiated conclusion
|
|
15290
15560
|
// triples (unique) instead of all newly derived facts.
|
|
15291
|
-
logQueries.push(annotateSourceOffset(this.makeRule(tr.s, tr.o, true), statementOffset));
|
|
15561
|
+
logQueries.push(this.annotateSourceOffset(this.makeRule(tr.s, tr.o, true), statementOffset));
|
|
15292
15562
|
} else {
|
|
15293
15563
|
triples.push(tr);
|
|
15294
15564
|
}
|
package/examples/collatz-1000.n3
CHANGED
|
@@ -19,6 +19,10 @@
|
|
|
19
19
|
@prefix : <http://example.org/collatz#> .
|
|
20
20
|
@prefix math: <http://www.w3.org/2000/10/swap/math#> .
|
|
21
21
|
@prefix list: <http://www.w3.org/2000/10/swap/list#> .
|
|
22
|
+
@prefix log: <http://www.w3.org/2000/10/swap/log#> .
|
|
23
|
+
|
|
24
|
+
# Memoize the overlapping Collatz suffixes shared by many starting values.
|
|
25
|
+
:collatz log:memoize true .
|
|
22
26
|
|
|
23
27
|
# -----------------------------------------
|
|
24
28
|
# Query / materialization of the test suite
|
package/examples/fibonacci.n3
CHANGED
|
@@ -3,18 +3,24 @@
|
|
|
3
3
|
# See https://en.wikipedia.org/wiki/Fibonacci_number
|
|
4
4
|
# ==================================================
|
|
5
5
|
|
|
6
|
+
@prefix log: <http://www.w3.org/2000/10/swap/log#>.
|
|
6
7
|
@prefix math: <http://www.w3.org/2000/10/swap/math#>.
|
|
7
8
|
@prefix : <https://eyereasoner.github.io/eye/reasoning#>.
|
|
8
9
|
|
|
9
|
-
|
|
10
|
+
# Memoize the overlapping recursive subproblems. The direct definition below
|
|
11
|
+
# intentionally exposes the classic recurrence so repeated calls such as
|
|
12
|
+
# F(10000), F(1000), F(100), ... can reuse completed :fibonacci answers.
|
|
13
|
+
:fibonacci log:memoize true.
|
|
10
14
|
|
|
11
|
-
{
|
|
12
|
-
{
|
|
13
|
-
{
|
|
15
|
+
{0 :fibonacci 0} <= true.
|
|
16
|
+
{1 :fibonacci 1} <= true.
|
|
17
|
+
{?X :fibonacci ?Y} <= {
|
|
14
18
|
?X math:greaterThan 1.
|
|
15
|
-
(?X 1) math:difference ?
|
|
16
|
-
(?
|
|
17
|
-
|
|
19
|
+
(?X 1) math:difference ?X1.
|
|
20
|
+
(?X 2) math:difference ?X2.
|
|
21
|
+
?X1 :fibonacci ?Y1.
|
|
22
|
+
?X2 :fibonacci ?Y2.
|
|
23
|
+
(?Y1 ?Y2) math:sum ?Y.
|
|
18
24
|
}.
|
|
19
25
|
|
|
20
26
|
{
|
|
@@ -34,4 +40,3 @@
|
|
|
34
40
|
10000 :fibonacci ?F10000.
|
|
35
41
|
}.
|
|
36
42
|
}.
|
|
37
|
-
|
|
@@ -34,6 +34,12 @@
|
|
|
34
34
|
# Backward helper relations
|
|
35
35
|
# -------------------------
|
|
36
36
|
|
|
37
|
+
# Memoize repeated factorization subgoals. The example asks for the same
|
|
38
|
+
# smallest-divisor and factor-list computations through several independent
|
|
39
|
+
# checks, so tabling completed answers avoids recomputing trial division.
|
|
40
|
+
:smallestDivisorFrom log:memoize true .
|
|
41
|
+
:factorSmallest log:memoize true .
|
|
42
|
+
|
|
37
43
|
# divides0(A,B): A divides B in the positive integers.
|
|
38
44
|
{ (?A ?B) :divides0 true }
|
|
39
45
|
<=
|