diff --git a/NEWS b/NEWS index 09a5afa71e22f3f3766dfc9ea6a1ee558f68d857..083891fa83a4bc7805f13253d062afe795d8c7a2 100644 --- a/NEWS +++ b/NEWS @@ -19,24 +19,21 @@ Version 0.4.1 * Fixed some compiler bugs * Fixed bug in stall -Version 0.5, TODO -* Improved parsing tool (guile-log) +Version 0.5, +* Improved parsing tool - Factorized and enabled for customized streams flow e.g. current indentation level in python - f-cons and similar tools for functional AST creation. - - Debug features +* Debug features +* Tabling or memoisation +* rational datastructures +* scheme Keyword objects and logic values +* GC of prolog variables +* Attributed variables +* corouttines +* tracing +* Better compilation error handling -* Tablating (all) DONE -* Circular datastructures (all) DONE -* Improved documentation (all) -* Keyword objects and logic values (prolog) DONE -* GC of prolog variables (all) DONE -* Attributed variables (all) DONE -* corouttines (prolog) DONE -* Debugging facilities (prolog) DONE -* Better error messages (prolog) DONE -* Better compilation errors (prolog) DONE -* Use guile variables when possible (prolog) DONE Version 0.6, TODO * GC of the (almost) unreachable tail of a stream (all) @@ -46,6 +43,7 @@ Version 0.6, TODO * Ordinary hash maps (all) * Faster compilation (prolog) * Better compilation errors (prolog) +* Improved documentation (all) * Improved matcher (prolog) * vectors (prolog) * structs (prolog) diff --git a/doc/guile-log.texi b/doc/guile-log.texi index 945dbdd6a70e18547e68598e60c33f1ddc5f2c43..992fd583d97f1a2f0eb81a7551da2735e4758227 100644 --- a/doc/guile-log.texi +++ b/doc/guile-log.texi @@ -1270,7 +1270,9 @@ Finally the last section conserns the ability to compile the dynamic function fo @node rational data @chapter Memoizing -it is possible to perform most operation in guile-log using ratioanl datastructures, The printer supports printing recursive data structures in guile-log and prolog. Generally the handling of ratoinal datstructures are expensive, therefore a mechanism to turn this feture on and off have been designed. +it is possible to perform most operation in guile-log using ratioanl datastructures, The printer supports printing recursive data structures in guile-log and prolog. Generally the handling of rational datstructures are expensive, therefore mechanisms to turn this feture on and off have been designed. Yoy may use the @code{.rec} interactive directive. Or you can use the @code{-functorize(recursive)} functor to tell that the function shall be evaluated with recursives on. Or in code use + +@code{prolog recursive(Code)}. @node memoizing @chapter Memoizing diff --git a/doc/guile-log/Index.html b/doc/guile-log/Index.html index eded42f509358caff0786b7f6b80e1dff4fbf590..75b1d84d61e94e114961da7ce1735596a9376468 100644 --- a/doc/guile-log/Index.html +++ b/doc/guile-log/Index.html @@ -1,413 +1,598 @@ - + + + + -Index - Preliminary Manual - - - - - - +Preliminary Manual: Index + + + + + + + + + + + + +a.summary-letter {text-decoration: none} +blockquote.smallquotation {font-size: smaller} +div.display {margin-left: 3.2em} +div.example {margin-left: 3.2em} +div.indentedblock {margin-left: 3.2em} +div.lisp {margin-left: 3.2em} +div.smalldisplay {margin-left: 3.2em} +div.smallexample {margin-left: 3.2em} +div.smallindentedblock {margin-left: 3.2em; font-size: smaller} +div.smalllisp {margin-left: 3.2em} +kbd {font-style:oblique} +pre.display {font-family: inherit} +pre.format {font-family: inherit} +pre.menu-comment {font-family: serif} +pre.menu-preformatted {font-family: serif} +pre.smalldisplay {font-family: inherit; font-size: smaller} +pre.smallexample {font-size: smaller} +pre.smallformat {font-family: inherit; font-size: smaller} +pre.smalllisp {font-size: smaller} +span.nocodebreak {white-space:nowrap} +span.nolinebreak {white-space:nowrap} +span.roman {font-family:serif; font-weight:normal} +span.sansserif {font-family:sans-serif; font-weight:normal} +ul.no-bullet {list-style: none} +--> + + + - -
+ + +

-Previous: garbage-collect, -Up: Top -


+Previous: , Up: Top   [Index]

- +
+

15 Index of the guile-log api

- +

Index

+ +
Jump to:   * +   +< +   += +   +_ +   +
+A +   +B +   +C +   +D +   +E +   +F +   +G +   +I +   +L +   +M +   +N +   +O +   +P +   +Q +   +R +   +S +   +T +   +U +   +V +   +W +   +Z +   +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Index Entry  Section

*
*current-stack*: umatch
*equal?: kanren
*gp-var-tr*: guile-log
*kanren-assq*: guile-log

<
</.>: guile-log
<//>: guile-log
<<case-lambda>>: guile-log
<<define->>: guile-log
<<define>>: guile-log
<<lambda>>: guile-log
<==>: guile-log
<=>: guile-log
<abort>: dynamics
<and!!>: guile-log
<and!>: guile-log
<and-i>: guile-log
<and>: guile-log
<append-dynamic>: dynamic-functions
<apply>: guile-log
<ask>: guile-log
<attvar-raw?>: attributes
<attvar?>: attributes
<call>: guile-log
<car>: guile-log
<case-lambda>: guile-log
<catch>: dynamics
<cc>: guile-log
<cdr>: guile-log
<clear>: guile-log
<code>: guile-log
<collect-2>: acumulators/generators
<collect-step-2>: acumulators/generators
<collect-step>: acumulators/generators
<collect>: acumulators/generators
<cond>: guile-log
<cons>: guile-log
<continue>: guile-log
<cut>: guile-log
<def->: guile-log
<def>: guile-log
<define-guile-log-rule>: guile-log
<define>: guile-log
<del-attr>: attributes
<dynamic-compile>: dynamic-functions
<dynwind>: guile-log
<eval>: guile-log
<fail>: guile-log
<fix-fold-step>: guile-log
<fix-fold>: guile-log
<fold-step>: guile-log
<fold>: guile-log
<format>: guile-log
<funcall>: guile-log
<get-attr>: attributes
<guard-dynamic-functions>: dynamic-functions
<hvar>: guile-log
<if-some>: guile-log
<if>: guile-log
<lambda-dyn>: dynamic-functions
<lambda>: guile-log
<let*>: guile-log
<let-with-guard>: guile-log
<let-with-lr-guard>: guile-log
<let>: guile-log
<letrec>: guile-log
<letrec>: guile-log
<logical++>: guile-log
<logical-->: guile-log
<match>: guile-log
<max-2>: acumulators/generators
<max-step-2>: acumulators/generators
<max-step>: acumulators/generators
<max>: acumulators/generators
<min-2>: acumulators/generators
<min-step-2>: acumulators/generators
<min-step>: acumulators/generators
<min>: acumulators/generators
<next>: guile-log
<not>: guile-log
<or-i>: guile-log
<or-union>: guile-log
<or>: guile-log
<peek-fail>: guile-log
<pp-dyn>: guile-log
<pp>: guile-log
<prod-2>: acumulators/generators
<prod-step-2>: acumulators/generators
<prod-step>: acumulators/generators
<prod>: acumulators/generators
<prompt>: dynamics
<push-dynamic>: dynamic-functions
<put-attr>: attributes
<r=>: guile-log
<raw-attvar>: attributes
<recur>: guile-log
<remove-dynamic>: dynamic-functions
<ret>: guile-log
<return>: guile-log
<run>: guile-log
<scm>: guile-log
<soland-2>: acumulators/generators
<soland-step-2>: acumulators/generators
<soland-step>: acumulators/generators
<soland>: acumulators/generators
<solor-2>: acumulators/generators
<solor-step-2>: acumulators/generators
<solor-step>: acumulators/generators
<solor>: acumulators/generators
<stall>: guile-log
<state-ref>: guile-log
<state-set!>: guile-log
<succeeds>: guile-log
<sum-2>: acumulators/generators
<sum-step-2>: acumulators/generators
<sum-step>: acumulators/generators
<sum>: acumulators/generators
<tail-code>: guile-log
<take>: guile-log
<update>: guile-log
<values>: guile-log
<var>: guile-log
<when>: guile-log
<with-cc>: guile-log
<with-cut>: guile-log
<with-dynamic-functions>: dynamic-functions
<with-fail>: guile-log
<with-guile-log>: guile-log
<with-s>: guile-log
<zip>: guile-log

=
==: kanren

_
_: kanren

A
abort_to_pompt: prolog continuations
add-operator: expressions
all: kanren
all!: kanren
all!!: kanren
all-interleave: kanren
always_state_guard_dynamic_object: dynamic-features
and-interleave: guile-log
and_i: prolog interleaving
any: kanren
any-interleave: kanren
any-union: kanren
attvar: prolog attributes
auto: prolog coroutines

B
backtrack_dynamic_object: dynamic-features

C
call_k: prolog continuations
canonize: prolog canonical
case: guile-log
CC: guile-log
close_error_false: closures
close_error_true: closures
closure_code_ref: closures
closure_is_closed: closures
closure_p: closures
closure_state_ref: closures
compile-prolog-file: running
compile-prolog-string: running
cond: guile-log
copy_dynamic_object: dynamic-features
CUT: guile-log

D
define-and-log: guile-log
define-dynamic: dynamic-functions
define-guile-log: guile-log
define-guile-log-parser: stream ideom
del_attr: prolog attributes
do[]: scheme
Ds: parser combinators

E
error_at_closed_p_handle: closures
error_on_namespace_switch: modules
extend-relation: kanren
extend-relation-with-recur-limit: kanren

F
f*: parser combinators
f+: parser combinators
f-and: parser combinators
f-and!: parser combinators
f-and!!: parser combinators
f-append: parser combinators
f-cons: parser combinators
f-cons*: parser combinators
f-eof: parser combinators
f-false: parser combinators
f-id: parser combinators
f-list: parser combinators
f-nl: parser combinators
f-nl!: parser combinators
f-nl-pr: parser combinators
f-not: parser combinators
f-not!: parser combinators
f-not*: parser combinators
f-not-pr: parser combinators
f-or: parser combinators
f-or!: parser combinators
f-out: parser combinators
f-reg: parser combinators
f-reg!: parser combinators
f-reg-pr: parser combinators
f-seq: parser combinators
f-seq!: parser combinators
f-seq!!: parser combinators
f-tag: parser combinators
f-tag!: parser combinators
f-tag-pr: parser combinators
f-true: parser combinators
fact: kanren
fail: kanren
fails: kanren
fail_on_namespace_switch: modules
ff*: parser combinators
ff+: parser combinators
ff?: parser combinators
fluid_guard_dynamic_object: dynamic-features
fn: parser combinators
freeze: prolog coroutines
freezeBig: prolog coroutines
freezeId: prolog coroutines
frozen: prolog coroutines
functorize: functors

G
get_attr: prolog attributes
get_namespace_switch_handle: modules
get_prolog_conversion_handle: dynamic-features
get_prolog_flags_handle: dynamic-features
get_prolog_operators_handle: dynamic-features
gp->scm: umatch
gp-budy: umatch
gp-car: umatch
gp-cdr: umatch
gp-clear: umatch
gp-cons!: umatch
gp-copy: umatch
gp-dynwind: umatch
gp-fluid-set: umatch
gp-get-stack: umatch
gp-lookup: umatch
gp-m-unify!: umatch
gp-make-stack: umatch
gp-make-var: umatch
gp-newframe: umatch
gp-pair?: umatch
gp-print: umatch
gp-printer: umatch
gp-restore-state: umatch
gp-restore-wind: umatch
gp-set!: umatch
gp-stack-set: umatch
gp-store-state: umatch
gp-undo-safe-variable-guard: umatch
gp-undo-safe-variable-lguard: umatch
gp-undo-safe-variable-rguard: umatch
gp-unify!: umatch
gp-unify-raw!: umatch
gp-unwind: umatch
gp-var!: umatch
gp-var-number: umatch
gp-var-ref: umatch
gp-var-set!: umatch
gp-var?: umatch

I
if: guile-log
if-only: kanren
if-some: kanren
interleave: guile-log
interleave-union: guile-log
intersect-relation: kanren

L
leave-logical: umatch
let-gls: kanren
let-lv: kanren
let-with-guard: guile-log
let-with-lr-guard: guile-log
let<>: guile-log
Level: debugging
lift-to-relations: kanren
log-code-macro: guile-log

M
make-opdata: expressions
make_vhash: prolog hash
memo: memoizing
memo-rec: memoizing
mk-operator-expression: expressions
mk-token: parser combinators

N
namespace_white_list_handle: modules
namespace_white_list_ref: modules
namespace_white_list_set: modules
not_backtrack_dynamic_object: dynamic-features

O
ok_on_namespece_switch: modules
or_i: prolog interleaving
or_union: prolog interleaving

P
P: guile-log
p-freeze: parser combinators
parse: parser combinators
parse<>: guile-log
partially-eval-sgl: kanren
postpone: postpone
postpone-frame: postpone
postpone_frame: prolog postpone
predicate: kanren
project: kanren
project/no-check: kanren
prolog-run: running
push-setup: umatch
put_attr: prolog attributes

Q
que-setup: umatch
query: kanren

R
raw_attvar: prolog attributes
rec: memoizing
rec-00: memoizing
rec-action: memoizing
rec-action00: memoizing
rec-lam: memoizing
rec-lam-00: memoizing
rec-lam-once: memoizing
rec-once: memoizing
rec=: memoizing
rec==: memoizing
recursive: memoizing
recursive_canonize: prolog canonical
reify: kanren
relation: kanren
rem-operator: expressions
reset-char-conversion: running
reset-flags: running
reset-operator-map: running
reset-prolog: running
re_prompt: prolog continuations

S
S: guile-log
scm[]: scheme
setup-parser: parser tooling
set_dynamic_object: dynamic-features
set_no_whitelist: modules
sfail: kanren
solution: kanren
solve: kanren
stall: interpreter
state_guard_dynamic_object: dynamic-features
state_guard_dynamic_object_zip: dynamic-features
succeed: kanren
succeeds: kanren

T
tok-ws*: parser combinators
tok-ws+: parser combinators
tr: guile-log
Trace: debugging
trace: debugging
trace-level: debugging
trace-vars: kanren

U
umatch: umatch
update: prolog zip
use-logical: umatch
usr_ref: interpreter
usr_set: interpreter
usr_zip: prolog zip

V
var?: kanren
vhashp: prolog hash
vhash_cons: prolog hash
vhash_fo_each: prolog hash
vhash_ref: prolog hash

W
when: prolog coroutines
whenBig: prolog coroutines
with-gp-vars: umatch
with[]: scheme
with_always_state_guard_dynamic_object: dynamic-features
with_backtrack_dynamic_object: dynamic-features
with_coroutine: prolog coroutines
with_fluid_guard_dynamic_object: dynamic-features
with_fluid_guard_dynamic_object_once: dynamic-features
with_not_backtrack_dynamic_object: dynamic-features
with_prompt: prolog continuations
with_state_guard_dynamic_object: dynamic-features
with_state_guard_dynamic_object_zip: dynamic-features

Z
zip: prolog zip

+
Jump to:   * +   +< +   += +   +_ +   +
+A +   +B +   +C +   +D +   +E +   +F +   +G +   +I +   +L +   +M +   +N +   +O +   +P +   +Q +   +R +   +S +   +T +   +U +   +V +   +W +   +Z +   +
+ +
+
+

+Previous: , Up: Top   [Index]

+
- - - - + + diff --git a/doc/guile-log/acumulators_002fgenerators.html b/doc/guile-log/acumulators_002fgenerators.html index fa83a2abcf8897afada6b8ca126ab018c205e604..52e3f610a5fa898430350bcd7222fde617d52509 100644 --- a/doc/guile-log/acumulators_002fgenerators.html +++ b/doc/guile-log/acumulators_002fgenerators.html @@ -1,142 +1,202 @@ - + + + + -acumulators/generators - Preliminary Manual - - - - - - - +Preliminary Manual: acumulators/generators + + + + + + + + + + + + + +a.summary-letter {text-decoration: none} +blockquote.smallquotation {font-size: smaller} +div.display {margin-left: 3.2em} +div.example {margin-left: 3.2em} +div.indentedblock {margin-left: 3.2em} +div.lisp {margin-left: 3.2em} +div.smalldisplay {margin-left: 3.2em} +div.smallexample {margin-left: 3.2em} +div.smallindentedblock {margin-left: 3.2em; font-size: smaller} +div.smalllisp {margin-left: 3.2em} +kbd {font-style:oblique} +pre.display {font-family: inherit} +pre.format {font-family: inherit} +pre.menu-comment {font-family: serif} +pre.menu-preformatted {font-family: serif} +pre.smalldisplay {font-family: inherit; font-size: smaller} +pre.smallexample {font-size: smaller} +pre.smallformat {font-family: inherit; font-size: smaller} +pre.smalllisp {font-size: smaller} +span.nocodebreak {white-space:nowrap} +span.nolinebreak {white-space:nowrap} +span.roman {font-family:serif; font-weight:normal} +span.sansserif {font-family:sans-serif; font-weight:normal} +ul.no-bullet {list-style: none} +--> + + + - -
- + + +

-Next: , -Previous: guile-log, -Up: Top -


+Next: , Previous: , Up: Top   [Index]

- +
+

3 Acumulators/generators

- -

In the guile-log chapter we defined the basic framework to fold a sequence of solutions into a variable. With this we can support e.g prolog's bagof and similar constructs. In the module (guile-log logic collects), we have defined a few specialisations of the fold operator in order to standardize these common abstractions. - +

In the guile-log chapter we defined the basic framework to fold a sequence of solutions into a variable. With this we can support e.g prolog’s bagof and similar constructs. In the module (guile-log logic collects), we have defined a few specialisations of the fold operator in order to standardize these common abstractions. +

+

3.1 Acumulators API

-

To explain the Api we have a gl-thunk, e.g. a guile-log lambda with zero arguments. it, will be the pattern to store. when it successes typically this variable will be copied and added to the resulting data structure which is list, sum, .... There is a possibility to keep some elements fixed and this is the -2 forms with the variable fixed naming the variable that needs to be fixated. e.g. first all solutions for the first found representation of the variable fixed will be found and added, then the then all solutions with the next found variant of the fixed will be used and so on, very much like how bagof in prolog is working. The -step versions of the acumulators will produce produce all the intermediate acumulator solutions. +

-

The following forms will cons all solutions to a list e.g. prodice lists in + + + + +

The following forms will cons all solutions to a list e.g. prodice lists in reverse order. - -

G.L. (<collect> gl-thunk it list) - -

G.L. (<collect-2> gl-thunk it fixed list) - -

G.L. (<collect-step> gl-thunk it list) - -

G.L. (<collect-step-2> gl-thunk it fixed list) - -

—————————————————————————————————– - -

The following forms will sum all solutions. - -

G.L. (<collect> gl-thunk it sum) - -

G.L. (<collect-2> gl-thunk it fixed sum) - -

G.L. (<collect-step> gl-thunk it sum) - -

G.L. (<collect-step-2> gl-thunk it fixed sum) - -

————————————————————————————————— - -

The following forms will take the product of all solutins - -

G.L. (<collect> gl-thunk it prod) - -

G.L. (<collect-2> gl-thunk it fixed prod) - -

G.L. (<collect-step> gl-thunk it prod) - -

G.L. (<collect-step-2> gl-thunk it fixed prod) - -

—————————————————————————————————– - -

The following forms will take the max of all solutions. - -

G.L. (<max> gl-thunk it max) - -

G.L. (<max-2> gl-thunk it fixed max) - -

G.L. (<max-step> gl-thunk it max) - -

G.L. (<max-step-2> gl-thunk it fixed max) - -

—————————————————————————————————– - -

The following forms will take the max of all solutions. - -

G.L. (<min> gl-thunk it min) - -

G.L. (<min-2> gl-thunk it fixed min) - -

G.L. (<min-step> gl-thunk it min) - -

G.L. (<min-step-2> gl-thunk it fixed min) - -

—————————————————————————————————– - -

The following forms will take the and of all operations returning the last one +

+

G.L. (<collect> gl-thunk it list) +

+

G.L. (<collect-2> gl-thunk it fixed list) +

+

G.L. (<collect-step> gl-thunk it list) +

+

G.L. (<collect-step-2> gl-thunk it fixed list) +

+

——————————————————————– +

+ + + + +

The following forms will sum all solutions. +

+

G.L. (<collect> gl-thunk it sum) +

+

G.L. (<collect-2> gl-thunk it fixed sum) +

+

G.L. (<collect-step> gl-thunk it sum) +

+

G.L. (<collect-step-2> gl-thunk it fixed sum) +

+

——————————————————————- +

+ + + + +

The following forms will take the product of all solutins +

+

G.L. (<collect> gl-thunk it prod) +

+

G.L. (<collect-2> gl-thunk it fixed prod) +

+

G.L. (<collect-step> gl-thunk it prod) +

+

G.L. (<collect-step-2> gl-thunk it fixed prod) +

+

——————————————————————– +

+ + + + +

The following forms will take the max of all solutions. +

+

G.L. (<max> gl-thunk it max) +

+

G.L. (<max-2> gl-thunk it fixed max) +

+

G.L. (<max-step> gl-thunk it max) +

+

G.L. (<max-step-2> gl-thunk it fixed max) +

+

——————————————————————– +

+ + + + +

The following forms will take the max of all solutions. +

+

G.L. (<min> gl-thunk it min) +

+

G.L. (<min-2> gl-thunk it fixed min) +

+

G.L. (<min-step> gl-thunk it min) +

+

G.L. (<min-step-2> gl-thunk it fixed min) +

+

——————————————————————– +

+ + + + +

The following forms will take the and of all operations returning the last one as a solution. - -

G.L. (<soland> gl-thunk it and) - -

G.L. (<soland-2> gl-thunk it fixed and) - -

G.L. (<soland-step> gl-thunk it and) - -

G.L. (<soland-step-2> gl-thunk it fixed and) - -

—————————————————————————————————– - -

The following forms will take the or of all operations returning the first solution. - -

G.L. (<solor> gl-thunk it or) - -

G.L. (<solor-2> gl-thunk it fixed or) - -

G.L. (<solor-step> gl-thunk it or) - -

G.L. (<solor-step-2> gl-thunk it fixed or) - +

+

G.L. (<soland> gl-thunk it and) +

+

G.L. (<soland-2> gl-thunk it fixed and) +

+

G.L. (<soland-step> gl-thunk it and) +

+

G.L. (<soland-step-2> gl-thunk it fixed and) +

+

——————————————————————– +

+ + + + +

The following forms will take the or of all operations returning the first solution. +

+

G.L. (<solor> gl-thunk it or) +

+

G.L. (<solor-2> gl-thunk it fixed or) +

+

G.L. (<solor-step> gl-thunk it or) +

+

G.L. (<solor-step-2> gl-thunk it fixed or) +

+

3.2 Local Non backtracking Genrators API

-

This tool is found directly in the module (logic guile-log), +

+

G.L. (<with-generators> ((var init) ...) code ...), This will bound the variables var ... initiated to init ... inside code .... +

+

These variables can then be changed by using set! and if the updating is functional, the state of the variables will be managed and store and restore will be managed in such a way that jumping below the initiation with <with-generators> and back will produce the same values, but inside this form it will not be restored to the old value. Especially a simple generator can be applied by using, +

+

G.L. (<next-generator-value> sum var val), e.g. perform var <- (sum var val) each time this line is executed and no backtracking will be done. +——————————————————————– +

-

G.L. (<with-generators> ((var init) ...) code ...), This will bound the variables var ... initiated to init ... inside code .... -

These variables can then be changed by using set! and if the updating is functional, the state of the variables will be managed and store and restore will be managed in such a way that jumping below the initiation with <with-generators> and back will produce the same values, but inside this form it will not be restored to the old value. Especially a simple generator can be applied by using, +


+
+

+Next: , Previous: , Up: Top   [Index]

+
-

G.L. (<next-generator-value> sum var val), e.g. perform var <- (sum var val) each time this line is executed and no backtracking will be done. -—————————————————————————————————– - + + diff --git a/doc/guile-log/dynamic_002dfunctions.html b/doc/guile-log/dynamic_002dfunctions.html index ae599e176a13a1d72f17c9a27653ba3b18ebfe82..e076ed55ea2e70fe0a754954ac6d778209588aac 100644 --- a/doc/guile-log/dynamic_002dfunctions.html +++ b/doc/guile-log/dynamic_002dfunctions.html @@ -1,74 +1,112 @@ - + + + + -dynamic-functions - Preliminary Manual - - - - - - - +Preliminary Manual: dynamic-functions + + + + + + + + + + + + + +a.summary-letter {text-decoration: none} +blockquote.smallquotation {font-size: smaller} +div.display {margin-left: 3.2em} +div.example {margin-left: 3.2em} +div.indentedblock {margin-left: 3.2em} +div.lisp {margin-left: 3.2em} +div.smalldisplay {margin-left: 3.2em} +div.smallexample {margin-left: 3.2em} +div.smallindentedblock {margin-left: 3.2em; font-size: smaller} +div.smalllisp {margin-left: 3.2em} +kbd {font-style:oblique} +pre.display {font-family: inherit} +pre.format {font-family: inherit} +pre.menu-comment {font-family: serif} +pre.menu-preformatted {font-family: serif} +pre.smalldisplay {font-family: inherit; font-size: smaller} +pre.smallexample {font-size: smaller} +pre.smallformat {font-family: inherit; font-size: smaller} +pre.smalllisp {font-size: smaller} +span.nocodebreak {white-space:nowrap} +span.nolinebreak {white-space:nowrap} +span.roman {font-family:serif; font-weight:normal} +span.sansserif {font-family:sans-serif; font-weight:normal} +ul.no-bullet {list-style: none} +--> + + + - -

- + + +

-Next: , -Previous: dynamics, -Up: Top -


+Next: , Previous: , Up: Top   [Index]

- +
+

6 Dynamic functions

- -

An interesting category of functionality in prolog is their dynamic function framework. They are a generalization of databases and allow to do matching in a scalable manner through indexing. Guile log also support a full indexer for a simplified matcher. And for all matched clauses they will be executed in order acording to how the database is setuped. One can add clauses to the head or to the end, remove clauses according to a pattern and also store states for later rewinding. The state guarding mechanism is either cheap (weak) e.g. it will not remember states as long as the action is above in the stack, else if it backtracks below the stack, state will be stored and restored at reentrence. We also support strong state storage at e.g. postpone support. - -

To use the api use (use-modules (logic guile-log functional-database)). - +

An interesting category of functionality in prolog is their dynamic function framework. They are a generalization of databases and allow to do matching in a scalable manner through indexing. Guile log also support a full indexer for a simplified matcher. And for all matched clauses they will be executed in order acording to how the database is setuped. One can add clauses to the head or to the end, remove clauses according to a pattern and also store states for later rewinding. The state guarding mechanism is either cheap (weak) e.g. it will not remember states as long as the action is above in the stack, else if it backtracks below the stack, state will be stored and restored at reentrence. We also support strong state storage at e.g. postpone support. +

+

To use the api use (use-modules (logic guile-log functional-database)). +

+

6.1 Api

- -

SCM (define-dynamic f), this will make a dynamic function object and bind it to f - -

G.L. (<push-dynamic> f lambda-dyn), push a match onto the head of dynamic function f. lambda-dyn is a special lambda typically created through, - -

SCM (<lambda-dyn> pat ... code), here pat ... will be simplified patterns only supporting quote,unquote all else directive is not allowed. code is evaluated in guile-log mode. - -

Similarly we can add code to the end of the dynamic function, e.g. - -

G.L. (<append-dynamic> f lambda-dyn). - -

Also to remove elements one can use, - -

G.L. (<remove-dynamic> (f a ...)), where f is the dynamic function and a ... the patterns for the arguments that, which matches will be retracted. - -

The previous set of API is typically what you get to use in prolog. The + + + + + +

SCM (define-dynamic f), this will make a dynamic function object and bind it to f +

+

G.L. (<push-dynamic> f lambda-dyn), push a match onto the head of dynamic function f. lambda-dyn is a special lambda typically created through, +

+

SCM (<lambda-dyn> pat ... code), here pat ... will be simplified patterns only supporting quote,unquote all else directive is not allowed. code is evaluated in guile-log mode. +

+

Similarly we can add code to the end of the dynamic function, e.g. +

+

G.L. (<append-dynamic> f lambda-dyn). +

+ +

Also to remove elements one can use, +

+

G.L. (<remove-dynamic> (f a ...)), where f is the dynamic function and a ... the patterns for the arguments that, which matches will be retracted. +

+ + +

The previous set of API is typically what you get to use in prolog. The downside is that they posses problem w.r.t. leaking data and therefor the next ideom is preferable to use in order to make sure both that one undo any changes to the dynamic variable, but also at reinstation of a state inside the form, it will resore to the same state as when control left the inner of the ideom e.g. The design is to favor fast lookup and adding and removing information is a bit expensive. +

+

G.L. (<with-dynamic-functions> (f ...) code ...), for this form f ..., will be weakly guarded throughout the form e.g. if control leaves the form then the state is stored if needed and at reinstation of state inside code ..., the old state of the dynamic variable will be reinstated. But inside the form state of the dynamic functions is not saved or restored. +

+

A stronger form of guard can be used in case one would like to make sure that the dynamic functions state can be reinstated in case of e.g. postpone is used, then use, +

+

G.L. (<guard-dynamic-functions> (f ...) code ...), +

+

Finally the last section conserns the ability to compile the dynamic function for as fast lookup as possible, use +

+ +

G.L. (<dynamic-compile> f ...), comiles the dynamic functions f ... for fast lookup. This ideom takes time and if used freely can cause a high memory consumption. +

+
+
+

+Next: , Previous: , Up: Top   [Index]

+
-

G.L. (<with-dynamic-functions> (f ...) code ...), for this form f ..., will be weakly guarded throughout the form e.g. if control leaves the form then the state is stored if needed and at reinstation of state inside code ..., the old state of the dynamic variable will be reinstated. But inside the form state of the dynamic functions is not saved or restored. - -

A stronger form of guard can be used in case one would like to make sure that the dynamic functions state can be reinstated in case of e.g. postpone is used, then use, - -

G.L. (<guard-dynamic-functions> (f ...) code ...), - -

Finally the last section conserns the ability to compile the dynamic function for as fast lookup as possible, use - -

G.L. (<dynamic-compile> f ...), comiles the dynamic functions f ... for fast lookup. This ideom takes time and if used freely can cause a high memory consumption. - + + diff --git a/doc/guile-log/dynamics.html b/doc/guile-log/dynamics.html index 86db450519b5bc68ced1b336bdc260553d90b8f9..01ac6a52a33bbf14c68df1cff8da16f96ea03819 100644 --- a/doc/guile-log/dynamics.html +++ b/doc/guile-log/dynamics.html @@ -1,94 +1,130 @@ - + + + + -dynamics - Preliminary Manual - - - - - - - +Preliminary Manual: dynamics + + + + + + + + + + + + + +a.summary-letter {text-decoration: none} +blockquote.smallquotation {font-size: smaller} +div.display {margin-left: 3.2em} +div.example {margin-left: 3.2em} +div.indentedblock {margin-left: 3.2em} +div.lisp {margin-left: 3.2em} +div.smalldisplay {margin-left: 3.2em} +div.smallexample {margin-left: 3.2em} +div.smallindentedblock {margin-left: 3.2em; font-size: smaller} +div.smalllisp {margin-left: 3.2em} +kbd {font-style:oblique} +pre.display {font-family: inherit} +pre.format {font-family: inherit} +pre.menu-comment {font-family: serif} +pre.menu-preformatted {font-family: serif} +pre.smalldisplay {font-family: inherit; font-size: smaller} +pre.smallexample {font-size: smaller} +pre.smallformat {font-family: inherit; font-size: smaller} +pre.smalllisp {font-size: smaller} +span.nocodebreak {white-space:nowrap} +span.nolinebreak {white-space:nowrap} +span.roman {font-family:serif; font-weight:normal} +span.sansserif {font-family:sans-serif; font-weight:normal} +ul.no-bullet {list-style: none} +--> + + + - -

+ + +

-Next: , -Previous: postpone, -Up: Top -


+Next: , Previous: , Up: Top   [Index]

- +
+

5 Dynamics

- -

The main work has been to enable delimeted continuation in guile-log. To do this is not easy because we want to support interleaving, postponing, store/restore, zip like construct as well as acumulation all in one theoretically and computationally sound environment. It's not just to store and restore a stack as in scheme. Guile log is targetted to be effective reinstating states and keep a huge number of states in memory, to do this we note 1. we store a tree of states to compress the overall memory need and keep consing to a lower degree. 2. reinstating state information multiple times is cheap because there is no consing the second time for the main stack (we keep another dynamic stack where we need to reinstate new datastructures at each reinstation. All this means that we must reinstate the same datastructure. Also generally the cc and p fields at the in and out of the generated continuation needs to be patched and in order to support all of guile-log seamlessly one need to make use of guarded variables. In all stackless dynamics like kanren employ is not well suited because this is a nonfunctional modification. The resulting continuation will work almost as one would expect, but one can imagine problematics if the evaluation of the continuation returns a failure thunk intended to jump back into the continuation without normal backtracking. This is not a serious flaw and we do not try to add functionality to support this more than that we would implement new versions of the frameworks, looking at that source code it would be clear how to proceed. - +

The main work has been to enable delimeted continuation in guile-log. To do this is not easy because we want to support interleaving, postponing, store/restore, zip like construct as well as acumulation all in one theoretically and computationally sound environment. It’s not just to store and restore a stack as in scheme. Guile log is targetted to be effective reinstating states and keep a huge number of states in memory, to do this we note 1. we store a tree of states to compress the overall memory need and keep consing to a lower degree. 2. reinstating state information multiple times is cheap because there is no consing the second time for the main stack (we keep another dynamic stack where we need to reinstate new datastructures at each reinstation. All this means that we must reinstate the same datastructure. Also generally the cc and p fields at the in and out of the generated continuation needs to be patched and in order to support all of guile-log seamlessly one need to make use of guarded variables. In all stackless dynamics like kanren employ is not well suited because this is a nonfunctional modification. The resulting continuation will work almost as one would expect, but one can imagine problematics if the evaluation of the continuation returns a failure thunk intended to jump back into the continuation without normal backtracking. This is not a serious flaw and we do not try to add functionality to support this more than that we would implement new versions of the frameworks, looking at that source code it would be clear how to proceed. +

+

5.1 Api

- -

-G.L. (<prompt> tag data thunk handler), This will evaluate the guile-log version of a thunk and continue just as with any other thunk. But if an abort with a tag that matches the prompt tag or if the prompt tag is true, any abort will be catched. data will be guile-log dynamic data that will be captured at the abort and transferd back to the prompts context. The handler is of the form - -

(handler tag next kk args ...), tag is the abort tag, next is a guile-log thunk, that evaluated will try the next handler in the stack. kk is a meta continuation. typically to get the continuaiton k, you do - -

(let ((k (kk))) ...) - -

But we can also do - -

(let ((k (kk new-handler))) ...), in cases where one want to use a new -handler for the continuation which is a common pattern in producing generators. -Technically this is not needed, but doing so means the difference between dog + + + + +

G.L. (<prompt> tag data thunk handler), This will evaluate the guile-log version of a thunk and continue just as with any other thunk. But if an abort with a tag that matches the prompt tag or if the prompt tag is true, any abort will be catched. data will be guile-log dynamic data that will be captured at the abort and transferd back to the prompts context. The handler is of the form +

+

(handler tag next kk args ...), tag is the abort tag, next is a guile-log thunk, that evaluated will try the next handler in the stack. kk is a meta continuation. typically to get the continuaiton k, you do +

+

(let ((k (kk))) ...) +

+

But we can also do +

+

(let ((k (kk new-handler))) ...), in cases where one want to use a new +handler for the continuation which is a common pattern in producing generators. +Technically this is not needed, but doing so means the difference between dog slow code and performant code. Finally we can use, +

-

(let ((k (kk tag new-handler))) ...), with the obvious interpretation. The return continuation k will have a few arguments that represents the arguments used in the continuation of the abort. +

(let ((k (kk tag new-handler))) ...), with the obvious interpretation. The return continuation k will have a few arguments that represents the arguments used in the continuation of the abort. +

+

The arguments (args ...) are the arguments returned by the abort. +

-

The arguments (args ...) are the arguments returned by the abort. -

G.L. (<catch> tag data thunk handler) this is exactly the same interface +

G.L. (<catch> tag data thunk handler) this is exactly the same interface as with prompts, but with the difference that the handler has the form - -

(handler tag next args ...), This is the same as prompts, but does not have any continuation argument. This ideom has significantly lower overhead. - -

G.L. (<abort> tag lambda args ...), will look for a handler matching +

+

(handler tag next args ...), This is the same as prompts, but does not have any continuation argument. This ideom has significantly lower overhead. +

+

G.L. (<abort> tag lambda args ...), will look for a handler matching the tag and then call the handler with (args ...), see the doc for <prompt>. The lambda should be a guile-log lambda and defines the signature that the continuation inside the handler have. - +

+

5.2 Example

(use-modules (logic guile-log))
 (use-modules (logic guile-log umatch))
 
-(<define> (f)
-  (<values> (i x) (<abort> 'tag (<lambda> (i x) (<cc> i x))))  
-  (<or-i>
-   (<or> (<=> x i)      (<=> x ,(+ i i)))
-   (<or> (<=> x ,(- i)) (<=> x ,(- (+ i i))))))
+(<define> (f)
+  (<values> (i x) (<abort> 'tag (<lambda> (i x) (<cc> i x))))  
+  (<or-i>
+   (<or> (<=> x i)      (<=> x ,(+ i i)))
+   (<or> (<=> x ,(- i)) (<=> x ,(- (+ i i))))))
 
 
-(<define> (test x y)
-  (<prompt> 'tag #f f
-    (<lambda> (tag next kk)
-        (<let> ((k (kk)))
-	   (<zip> (x (k 1  x))
+(<define> (test x y)
+  (<prompt> 'tag #f f
+    (<lambda> (tag next kk)
+        (<let> ((k (kk)))
+	   (<zip> (x (k 1  x))
 		  (y (k 10 y)))))))
 
-(<run> 10 (x y) (test x y))
+(<run> 10 (x y) (test x y))
 
---> $1 = ((1 10) (-1 -10) (2 20) (-2 -20))
+--> $1 = ((1 10) (-1 -10) (2 20) (-2 -20))
 
+
+
+

+Next: , Previous: , Up: Top   [Index]

+
+ - + + diff --git a/doc/guile-log/expressions.html b/doc/guile-log/expressions.html index 5d688048ffe9a7576e82259f8cff36c66ff91d09..b3a08421c65fedea323ff9ae314861d741160ce1 100644 --- a/doc/guile-log/expressions.html +++ b/doc/guile-log/expressions.html @@ -1,71 +1,102 @@ - + + + + -expressions - Preliminary Manual - - - - - - - - +Preliminary Manual: expressions + + + + + + + + + + + + + +a.summary-letter {text-decoration: none} +blockquote.smallquotation {font-size: smaller} +div.display {margin-left: 3.2em} +div.example {margin-left: 3.2em} +div.indentedblock {margin-left: 3.2em} +div.lisp {margin-left: 3.2em} +div.smalldisplay {margin-left: 3.2em} +div.smallexample {margin-left: 3.2em} +div.smallindentedblock {margin-left: 3.2em; font-size: smaller} +div.smalllisp {margin-left: 3.2em} +kbd {font-style:oblique} +pre.display {font-family: inherit} +pre.format {font-family: inherit} +pre.menu-comment {font-family: serif} +pre.menu-preformatted {font-family: serif} +pre.smalldisplay {font-family: inherit; font-size: smaller} +pre.smallexample {font-size: smaller} +pre.smallformat {font-family: inherit; font-size: smaller} +pre.smalllisp {font-size: smaller} +span.nocodebreak {white-space:nowrap} +span.nolinebreak {white-space:nowrap} +span.roman {font-family:serif; font-weight:normal} +span.sansserif {font-family:sans-serif; font-weight:normal} +ul.no-bullet {list-style: none} +--> + + + - -
+ + +

-Next: , -Previous: parser combinators, -Up: parsing -


+Next: , Previous: , Up: parsing   [Index]

- +
+

10.3 Expressions

-

This is a configureable expression parser that can be used for prolog parsing as well as parsing C and C++ expressions. To note is that the data is functionally updated and hence one can store the state at will and later reinstate the parser. The parser ideom is a direct translation of the commonly described prolog parser written in prolog to guile-log. It is then extended to allow ternial operators like ? in c as well. To use it load the module (logic guile-log parsing operator-parser) - +

+

10.3.1 Api

- -

(make-opdata), initiates a datastructure to containe needed operator data. The result is a fluid pointing to a functional datastructure. - -

(add-operator data type name level lf), This will add operator data to the opdata fluid data. type is the type of operator e.g. any of xf,yf,fx,fy,xfx,xfy,yfx, as of the standard meaning of these operators in prolog. name is a string or symbol representing the name of the operator and level is the anti binding strength of the operator e.g. higher value bind less. lf is a parser function that represents possible values to the right of the op-symbol matched, typically this will be tok-ws, but also for e.g. ? it can be a parser function matching the middle part of in this operayor which ends with :. - -

(rem-operator data type name), removes from the opdata fluid data, the slot represented by the type type and the operator name name. - -

(mk-operator-expression atom rest-atom data), will return a parser meta function representing the operator configuration in data, with atom parser function atom and a secondary choised atom if that fails in rest-atom. The returned meta parser function, say ff is typically turned into a parser function for the expression through: - -

(ff high-level), with high-level, the highes level found in the table. - -

The generator parser f can then be used to match an expression and outpits a syntactic tree with nodes according to e.g. -

(parse ``1 + -2'' f)
-
--->
+
+

(make-opdata), initiates a datastructure to containe needed operator data. The result is a fluid pointing to a functional datastructure. +

+ +

(add-operator data type name level lf), This will add operator data to the opdata fluid data. type is the type of operator e.g. any of xf,yf,fx,fy,xfx,xfy,yfx, as of the standard meaning of these operators in prolog. name is a string or symbol representing the name of the operator and level is the anti binding strength of the operator e.g. higher value bind less. lf is a parser function that represents possible values to the right of the op-symbol matched, typically this will be tok-ws, but also for e.g. ? it can be a parser function matching the middle part of in this operayor which ends with :. +

+ +

(rem-operator data type name), removes from the opdata fluid data, the slot represented by the type type and the operator name name. +

+ +

(mk-operator-expression atom rest-atom data), will return a parser meta function representing the operator configuration in data, with atom parser function atom and a secondary choised atom if that fails in rest-atom. The returned meta parser function, say ff is typically turned into a parser function for the expression through: +

+

(ff high-level), with high-level, the highes level found in the table. +

+

The generator parser f can then be used to match an expression and outpits a syntactic tree with nodes according to e.g. +

(parse ``1 + -2'' f)
+
+-->
 
 (('xfy ``+'' _ _) (#:number 1) (('yf ``-'' _ _) (#:number 2) 4 0) 2 0)
 
+

That is a binary oparator is of the form, +

+

((type operator-name level _) term-left term-right column line) +

+

And a unary operator is matched by +

+

((type operator-name level _) term column line). +


+
+

+Next: , Previous: , Up: parsing   [Index]

+
-

That is a binary oparator is of the form, - -

((type operator-name level _) term-left term-right column line) - -

And a unary operator is matched by - -

((type operator-name level _) term column line). - + + diff --git a/doc/guile-log/garbage_002dcollect.html b/doc/guile-log/garbage_002dcollect.html index d613769bd1ed83535157959585cc6df72ca634d6..d393ca91e4aafd5d75c19e9879ad1ad85f1e5bce 100644 --- a/doc/guile-log/garbage_002dcollect.html +++ b/doc/guile-log/garbage_002dcollect.html @@ -1,53 +1,78 @@ - + + + + -garbage-collect - Preliminary Manual - - - - - - - +Preliminary Manual: garbage-collect + + + + + + + + + + + + + +a.summary-letter {text-decoration: none} +blockquote.smallquotation {font-size: smaller} +div.display {margin-left: 3.2em} +div.example {margin-left: 3.2em} +div.indentedblock {margin-left: 3.2em} +div.lisp {margin-left: 3.2em} +div.smalldisplay {margin-left: 3.2em} +div.smallexample {margin-left: 3.2em} +div.smallindentedblock {margin-left: 3.2em; font-size: smaller} +div.smalllisp {margin-left: 3.2em} +kbd {font-style:oblique} +pre.display {font-family: inherit} +pre.format {font-family: inherit} +pre.menu-comment {font-family: serif} +pre.menu-preformatted {font-family: serif} +pre.smalldisplay {font-family: inherit; font-size: smaller} +pre.smallexample {font-size: smaller} +pre.smallformat {font-family: inherit; font-size: smaller} +pre.smalllisp {font-size: smaller} +span.nocodebreak {white-space:nowrap} +span.nolinebreak {white-space:nowrap} +span.roman {font-family:serif; font-weight:normal} +span.sansserif {font-family:sans-serif; font-weight:normal} +ul.no-bullet {list-style: none} +--> + + + - -

- + + +

-Next: , -Previous: prolog, -Up: Top -


+Next: , Previous: , Up: Top   [Index]

- +
+

14 Garbage Collection

Guile log sports full garbage collection of logical variables which makes it suitable to run server like prolog code. It is experimental but working. Unfourtunately the bdw-gc that guile uses does not allow this to work effectively and hence you need to download and replace the standard bdw-gc with a modified version of it. You may find it at +

+

https://gitorious.org/bdw-gc-logical-mod +

+

Now you typically build this and make sure to save the old gc.so that guile is using (you can google how to find which shared libraries guile is using) and then clobber the bdw-gc .so file with the newly created one (sic). This is of cause not a simple thing to do, but until we can get some comparable feature in bdw-gc this is what you need to do. Then finally when configureing guile log do something like +

+

./configure --with-logical-gc +

+

And then make, make install and you will run guile-log with garbage collection on. Then on to happy hacking!. +

+

To note is that only variables and cons cells allocated from stacks will support garbage collecting. Knaren style variables is fundamentally broken with respect to this and one need for that style use other techniques like making use of return variables in functions and the small but potent hacks you may find in the kanren sources. Another option is to make use of guile-log’s <call> that will basically only transfer the set of variables in the result essentially skiping all intermediate allocations. +

-

https://gitorious.org/bdw-gc-logical-mod - -

Now you typically build this and make sure to save the old gc.so that guile is using (you can google how to find which shared libraries guile is using) and then clobber the bdw-gc .so file with the newly created one (sic). This is of cause not a simple thing to do, but until we can get some comparable feature in bdw-gc this is what you need to do. Then finally when configureing guile log do something like - -

./configure --with-logical-gc - -

And then make, make install and you will run guile-log with garbage collection on. Then on to happy hacking!. - -

To note is that only variables and cons cells allocated from stacks will support garbage collecting. Knaren style variables is fundamentally broken with respect to this and one need for that style use other techniques like making use of return variables in functions and the small but potent hacks you may find in the kanren sources. Another option is to make use of guile-log's <call> that will basically only transfer the set of variables in the result essentially skiping all intermediate allocations. - + + diff --git a/doc/guile-log/guile_002dlog.html b/doc/guile-log/guile_002dlog.html index 864a1eedb683f5461da2e2e155c52c214b074df2..9719d3e62b0aed2a9e2660782b558af23e56ed0f 100644 --- a/doc/guile-log/guile_002dlog.html +++ b/doc/guile-log/guile_002dlog.html @@ -1,71 +1,91 @@ - + + + + -guile-log - Preliminary Manual - - - - - - - +Preliminary Manual: guile-log + + + + + + + + + + + + + +a.summary-letter {text-decoration: none} +blockquote.smallquotation {font-size: smaller} +div.display {margin-left: 3.2em} +div.example {margin-left: 3.2em} +div.indentedblock {margin-left: 3.2em} +div.lisp {margin-left: 3.2em} +div.smalldisplay {margin-left: 3.2em} +div.smallexample {margin-left: 3.2em} +div.smallindentedblock {margin-left: 3.2em; font-size: smaller} +div.smalllisp {margin-left: 3.2em} +kbd {font-style:oblique} +pre.display {font-family: inherit} +pre.format {font-family: inherit} +pre.menu-comment {font-family: serif} +pre.menu-preformatted {font-family: serif} +pre.smalldisplay {font-family: inherit; font-size: smaller} +pre.smallexample {font-size: smaller} +pre.smallformat {font-family: inherit; font-size: smaller} +pre.smalllisp {font-size: smaller} +span.nocodebreak {white-space:nowrap} +span.nolinebreak {white-space:nowrap} +span.roman {font-family:serif; font-weight:normal} +span.sansserif {font-family:sans-serif; font-weight:normal} +ul.no-bullet {list-style: none} +--> + + + - -

- + + +

-Next: , -Previous: umatch, -Up: Top -


+Next: , Previous: , Up: Top   [Index]

- +
+

2 Guile-log

-

Guile log is a basic framework of macrology that implements functionality that can be compared to both kanren and prolog plus some extra features. The feature set is close to what can be accomplish with plain kanren but more at the speed of prolog. Usually kanren is a more expressive way of implementation and can many times easier be extended with new features, on the other hand, most features in kanren is available in guile-log and performs about 10x faster then scheme kanren. Other possibilities are using the kanren interface ontop of guile-log and then the speed difference is about a factor of 2 slower then guile-log close to the speed that kanren does in compiled chicken. - -

Guile log performs it's actions in a guile-log mode e.g. small scheme like language that behaves in a certain way defining functions for this environment can be done with sugared functions or with a special macro definition. - -

A guile log function is a function where the first argument represent the current state, the second argument the failure thunk and where the third argument represent a continuation lambda. It's possible to write macros that works in guile log mode. - -

A failure thunk is a thunk that is evaluated at failure and usually the stack backtracks in this lambda. The continuation lambda takes a satte and a failure thunk as it's argument which represent the current failure and then execute it's body as the continuation of the algorithm. e.g. - -

guile-log has one aspect that kanren does not have and this is the notion of going up and down a stack at redo and undo. With this we have a notion that is very similar to a dynamic-wind, which can guard constructs. With this it is pretty simple to instrument tracing to not only trace upward but also at the same point track the backtracking. This is not possible in kanren. With this it is possible to keep the number of guarded variables to a minimum something kanren cannot do due to the lack of stack notion. On the other hand it is possible like in the reference implementation of kanren to get away with guarded variables by either using delimited continuations or using special return values. But for some constructs guarded variables is pretty much needed e.g. acumulator like constructs and delimeted continuations. - -

Kanren does one thing pretty well and that is that it can support a notion of tail-call's. We do have options for guile-log to accomplish this as well and hence it is possible to write algorithms in guile-log without risk blowing the stack. - -

To see how the code is designed we can describe, - -

the failure thunk semantic, +

+

Guile log performs it’s actions in a guile-log mode e.g. small scheme like language that behaves in a certain way defining functions for this environment can be done with sugared functions or with a special macro definition. +

+

A guile log function is a function where the first argument represent the current state, the second argument the failure thunk and where the third argument represent a continuation lambda. It’s possible to write macros that works in guile log mode. +

+

A failure thunk is a thunk that is evaluated at failure and usually the stack backtracks in this lambda. The continuation lambda takes a satte and a failure thunk as it’s argument which represent the current failure and then execute it’s body as the continuation of the algorithm. e.g. +

+

guile-log has one aspect that kanren does not have and this is the notion of going up and down a stack at redo and undo. With this we have a notion that is very similar to a dynamic-wind, which can guard constructs. With this it is pretty simple to instrument tracing to not only trace upward but also at the same point track the backtracking. This is not possible in kanren. With this it is possible to keep the number of guarded variables to a minimum something kanren cannot do due to the lack of stack notion. On the other hand it is possible like in the reference implementation of kanren to get away with guarded variables by either using delimited continuations or using special return values. But for some constructs guarded variables is pretty much needed e.g. acumulator like constructs and delimeted continuations. +

+

Kanren does one thing pretty well and that is that it can support a notion of tail-call’s. We do have options for guile-log to accomplish this as well and hence it is possible to write algorithms in guile-log without risk blowing the stack. +

+

To see how the code is designed we can describe, +

+

the failure thunk semantic, (lambda () (unwind) (try-alternative-path)) - -

the continuation lambda (cc) +

+

the continuation lambda (cc) (lambda (state fail) (execute-next-fkn state fail)) - -

To see how they work consider the (<and> (f) (g)), <and> is a directive that represent a sequencing of facts and here the guile-log functions f and g will be tried in sequence e.g. - -

  (<and> (f) (g)):
+

+

To see how they work consider the (<and> (f) (g)), <and> is a directive that represent a sequencing of facts and here the guile-log functions f and g will be tried in sequence e.g. +

+
  (<and> (f) (g)):
      (lambda (state fail cc)
        (f state fail (lambda (state2 fail2) (g state2 fail2 cc))))
 
- -

Likewise an or (e.g. try f and if f fails try g) clause could be defined -

  (<or> (f) (g)):
+

Likewise an or (e.g. try f and if f fails try g) clause could be defined +

  (<or> (f) (g)):
     (lambda (state fail cc)
       (let ((fr (gp-newframe)))
         (f state
@@ -74,415 +94,505 @@ Up: Top
               (g satte fail cc))
             cc)))      
 
- -

Writing these forms in plain scheme is a bit tedious so it is nice to have +

Writing these forms in plain scheme is a bit tedious so it is nice to have macros that does this for us. Note here that Kanren very much the same way (A read and understanding of the Kanren source code and/or Reasoned Schemer is a good background in using this tool) - -

You do find the notion of a cut in prolog and you do have it in guile-log as well. Kanren does not have it explicitly. But basically a cut is maintaining a failure thunk that typically represent backtracking from the function etc. The cut is not a parameter in the functions and hence is a notion that relates to the macrology in the source code, hence typically a guile-log macro looks like - +

+

You do find the notion of a cut in prolog and you do have it in guile-log as well. Kanren does not have it explicitly. But basically a cut is maintaining a failure thunk that typically represent backtracking from the function etc. The cut is not a parameter in the functions and hence is a notion that relates to the macrology in the source code, hence typically a guile-log macro looks like +

(define-guile-log macro
   (syntax-rules ()
     ((_ (cut s p cc) code ...)
       do-something-here)))
 
- -

So we see that guile-macros by convention have that quadruple as a first +

So we see that guile-macros by convention have that quadruple as a first argument. Note the cut parameter, the rest is just the plain old parameters you got in the first three function arguments. - -

The guile-log is simply looking at forms and if it sees a sexp where the car is -a guile-log macro it will insert the (cut s p cc) as a first argument +

+

The guile-log is simply looking at forms and if it sees a sexp where the car is +a guile-log macro it will insert the (cut s p cc) as a first argument and evaluate that macro. Else the sexp is assumed to be a function and guile log will put the p and the cc in front and execute that. e.g. to define or a non guile-log macro you typically use, - -

Kanrens version of or-i and and-i e.g. the interleaving versions of 'or' and 'and', and scale better, the reason is that in guile-log the stack is moved back and forth between states which is unnecesary in kanren where the interpretation of variables is via a state consisting of a list representing a stack or via a functional tree. On the other hand, in guile-log we can make use of dynamic wind constructs which are impossible to get right in kanren. - -

Threading is not supported in the lower levels, e.g. umatch in guile-log and here Kanren is much better off. In principle this is something that can be improved uppon, but we postpone that to later versions of guile-log. - -

guile-log is safe with respect to undo/redo, you can stall everywhere and expect to be able to store the state, and later retrieve it. - -

Functions (f args ...) in guile-log is defines as -

  (define (f s p cc args ...) code ...)
+

+

Kanrens version of or-i and and-i e.g. the interleaving versions of ’or’ and ’and’, and scale better, the reason is that in guile-log the stack is moved back and forth between states which is unnecesary in kanren where the interpretation of variables is via a state consisting of a list representing a stack or via a functional tree. On the other hand, in guile-log we can make use of dynamic wind constructs which are impossible to get right in kanren. +

+

Threading is not supported in the lower levels, e.g. umatch in guile-log and here Kanren is much better off. In principle this is something that can be improved uppon, but we postpone that to later versions of guile-log. +

+

guile-log is safe with respect to undo/redo, you can stall everywhere and expect to be able to store the state, and later retrieve it. +

+

Functions (f args ...) in guile-log is defines as +

  (define (f s p cc args ...) code ...)
 
+

2.1 Basic logic

- -

-G.L. (<and> p1 p2 ...), perform p1, if success then p2 and so on. - -

G.L. (<or> p1 p2 ...), perform p1, if p1 fail then backtrack and try p2 ... - -

G.L. (<and!> p1 p2 ...), same as <and> but yields at most one answer. - -

G.L. (<and!!> p1 p2 ...), the same as (<and> (<and!> p1) (<and!> p2) ...) e.g. at most one answer from p1 and at most one answer from p2 etc. - -

<and!> and <and!!>, are useful when we want to restrict the search space and when a local success correlates to a global one. - -

G.L. (<not> p ...), successes if (<and> p ...) fail and fails otherwise. In either case the form will always backtrack and no variables will be bound inside this form. - -

G.L. (<if> p x), if p is a success then x, p will only success at most one time. - -

G.L. (<if> p x y), if p is success then x, else backtrack and use y, the same condition holds on p as the previous version of if. - -

G.L. (<if-some> p x), the same as (<and> p x). - -

G.L. (<if-some> p x y), logicaly the same as (<or> (<and> p a) (<and> (<not> p) b)). - -

G.L. (<cond> (P X) ...), like the ordinary cond, but using <if> in stead of if - -

G.L. (<or-i> p1 p2 ... pn), if p1 successes and we later backtrack then try p2 etc and so on until pn if pn successes and we later backtrack then p1 is tried again and interleave like that. To note here is that this form uses both bank a and b and in order to function correctly when storing a state both bank a and bank b need to be stored. - -

G.L. (interleave l), the same as <or-i> but with the difference l is a list of lambdas typically made by (</.> ...). - -

G.L. (<or-union> p1 ...), this is like <or-i> but if pk has a success and if, the goal pl, l > k, succeses like in (<and> pk pl) then we will backtrack, this means that duplication of results is in a sense removed. - -

G.L. (interleave-union l), see interleave. - -

G.L. (<and-i> p1 p2 p3 ...), and interleaving! this is an and which will in parctice behave as -

  (<and-i> (<or> A B) (<or> C D))
-  <=>
-  (<or> (<and> A C) (<and> B C) (<and> A C) (<and> B C))
-
-e.g. backtracking is shallow and we will backtrack all the first combinations, then all the second combinations then all the third ones etc. To accomplish this state information needs to be stored hence using this tool can be slow and memory intensive. - -

G.L. (and-interleave l), the same as <and-i> but with the difference l is a list of lambdas typically made by (</.> ...). - -

G.L. (<succeeds> p) will try p and if it succeeds undo any bindings and continue. - -

G.L. (<zip>  (w        g ...) 
+
+
+
+
+
+
+

G.L. (<and> p1 p2 ...), perform p1, if success then p2 and so on. +

+

G.L. (<or> p1 p2 ...), perform p1, if p1 fail then backtrack and try p2 ... +

+

G.L. (<and!> p1 p2 ...), same as <and> but yields at most one answer. +

+

G.L. (<and!!> p1 p2 ...), the same as (<and> (<and!> p1) (<and!> p2) ...) e.g. at most one answer from p1 and at most one answer from p2 etc. +

+

<and!> and <and!!>, are useful when we want to restrict the search space and when a local success correlates to a global one. +

+

G.L. (<not> p ...), successes if (<and> p ...) fail and fails otherwise. In either case the form will always backtrack and no variables will be bound inside this form. +

+ + + + + + + + + + + + + + +

G.L. (<if> p x), if p is a success then x, p will only success at most one time. +

+

G.L. (<if> p x y), if p is success then x, else backtrack and use y, the same condition holds on p as the previous version of if. +

+

G.L. (<if-some> p x), the same as (<and> p x). +

+

G.L. (<if-some> p x y), logicaly the same as (<or> (<and> p a) (<and> (<not> p) b)). +

+

G.L. (<cond> (P X) ...), like the ordinary cond, but using <if> in stead of if +

+

G.L. (<or-i> p1 p2 ... pn), if p1 successes and we later backtrack then try p2 etc and so on until pn if pn successes and we later backtrack then p1 is tried again and interleave like that. To note here is that this form uses both bank a and b and in order to function correctly when storing a state both bank a and bank b need to be stored. +

+

G.L. (interleave l), the same as <or-i> but with the difference l is a list of lambdas typically made by (</.> ...). +

+

G.L. (<or-union> p1 ...), this is like <or-i> but if pk has a success and if, the goal pl, l > k, succeses like in (<and> pk pl) then we will backtrack, this means that duplication of results is in a sense removed. +

+

G.L. (interleave-union l), see interleave. +

+

G.L. (<and-i> p1 p2 p3 ...), and interleaving! this is an and which will in parctice behave as +

  (<and-i> (<or> A B) (<or> C D))
+  <=>
+  (<or> (<and> A C) (<and> B C) (<and> A C) (<and> B C))
+

e.g. backtracking is shallow and we will backtrack all the first combinations, then all the second combinations then all the third ones etc. To accomplish this state information needs to be stored hence using this tool can be slow and memory intensive. +

+

G.L. (and-interleave l), the same as <and-i> but with the difference l is a list of lambdas typically made by (</.> ...). +

+

G.L. (<succeeds> p) will try p and if it succeeds undo any bindings and continue. +

+
G.L. (<zip>  (w        g ...) 
              ((v ...)  h ...) ...)
-
-This is executing n guile-log programs in paralell e.g. when backtracking all +

This is executing n guile-log programs in paralell e.g. when backtracking all of the programs are backtracked in one go. The interface to the outside is via variables w (v ...) etc. (one can either specify a variable or a list of variables. The variables represents the interface for the continuation of the program. So all the programs are executed one by one staring with the first one yielding a construction of what for example w should be bound to, that information is stored and then everything done from the state at the start of the <zip> is unwinded and restored. Then the stored representation of w etc. are at the end of the zip where we have unwinded back to the start the information is unified with the original variables and then the code will continue with the continuation. A backtracking to the zip will backtrack all of the goal sets in paralell again starting with the first and new values for the interfacing variables are constructed. - -

Conside the following definition of a function f, - -

(<define> (f x n)
-  (<or> (<=> x n)
+

+

Conside the following definition of a function f, +

+
(<define> (f x n)
+  (<or> (<=> x n)
         (f x (+ n 1))))
 
- -

this function can be used to illustrate the zip by, - -

(<run> 5 (x y) 
-  (<zip> (x (f x 0)) 
+

this function can be used to illustrate the zip by, +

+
(<run> 5 (x y) 
+  (<zip> (x (f x 0)) 
          (y (f y 1))))
 
-> ((0 1) (1 2) (2 3) (3 4) (4 5))
+> ((0 1) (1 2) (2 3) (3 4) (4 5))
 
- -

G.L. (<call> ((l x) ...) code ...), This will call (<and> code ...) and at success it will store the values x ... and then backtrack and unify the copied x to l. At backtracking the state will be reinstated. Use this when you want to avoid side effets when calling a stub. - -

Example: - -

(<run> 5 (x y) 
-   (<call> ((x y)) (f y 10))
-   (<=> y -1))
-
-=> ((10 -1) (11 -1) (12 -1) (13 -1) (14 -1))
+

G.L. (<call> ((l x) ...) code ...), This will call (<and> code ...) and at success it will store the values x ... and then backtrack and unify the copied x to l. At backtracking the state will be reinstated. Use this when you want to avoid side effets when calling a stub. +

+

Example: +

+
(<run> 5 (x y) 
+   (<call> ((x y)) (f y 10))
+   (<=> y -1))
+
+=> ((10 -1) (11 -1) (12 -1) (13 -1) (14 -1))
 
- -

G.L. (<//> ((fail ((xx x) ... ) code ...) ...) body ...) +

G.L. (<//> ((fail ((xx x) ... ) code ...) ...) body ...) G.L. (<update> (fail vals ...) ...) This is close to functionality to <zip> but somewhat on steroids and a few 4 - 5 times slower. The main usage is when we need to try out two logics in paralell and they are not nessesary in sync. In (fail ((xx x) ...) code ...), (<and> code ...) will be evaluated and any resulting values x will be copied and stored in the introduced variable xx. The failure tag can be used to tell guile-log to only backtrack that part of the arm. This is done via a (<update> (fail vals ...) ... ). Typically the first part of the body is a guard that evaluates if they are on synch and if not, say branch f1, needs to update you can do so by (<update> (f1)) or (<update> (f1 p)) with p a variable containing a failure thunk captured inside the arm. Typically p has before been intrioduced with (letg ((p #f)) co ...) and then p is setted to for example the Current failure thunk P inside the arm. - -

Example: - -

(<run> 1 (x y) 
-   (<//> ((f1  ((xx x)) (f x 1))
+

+

Example: +

+
(<run> 1 (x y) 
+   (<//> ((f1  ((xx x)) (f x 1))
           (f2  ((yy y)) (f y 10)))
-      (if (< (<scm> xx) (<scm> yy))
-          (<update> (f1))
-          <cc>)
-      (<=> (xx yy) (x y))))
+      (if (< (<scm> xx) (<scm> yy))
+          (<update> (f1))
+          <cc>)
+      (<=> (xx yy) (x y))))
 
-=> ((10 10) (11 11) (12 12) (13 13) (14 14))
+=> ((10 10) (11 11) (12 12) (13 13) (14 14))
 
- +

2.2 Probing The Control Variables

- -

It is possible to probe the curretn variables that is transported behind the sceene, use the syntax-parameters S,CC,CUT,P to reach them inside guile-log code. - + + + + +

It is possible to probe the curretn variables that is transported behind the sceene, use the syntax-parameters S,CC,CUT,P to reach them inside guile-log code. +

+

2.3 Guarded variables

- -

This are lower level constructs usable for designers of logical ideoms. Their -purpose is to allow for constructs that need to add variables to store a state + + + + +

This are lower level constructs usable for designers of logical ideoms. Their +purpose is to allow for constructs that need to add variables to store a state across multiple backtrackings to mix well with postpone and undo/redo. - -

G.L. (<let-with-guard> wind guard ((var init) ...) code ...), This construct will bind var ... with init values init ... just as with let. The difference is that we can guard execution of no mutation with e.g. - -

G.L. (guard Lam) e.g. Lam neede to be a guile log closure for -which the code should be safe to undo and redo if not mutated. wind +

+

G.L. (<let-with-guard> wind guard ((var init) ...) code ...), This construct will bind var ... with init values init ... just as with let. The difference is that we can guard execution of no mutation with e.g. +

+

G.L. (guard Lam) e.g. Lam neede to be a guile log closure for +which the code should be safe to undo and redo if not mutated. wind refers to the current wind level and use it in - -

(gp-restore-wind state wind) - -

To restore at the current wind level meaning that any let-with-guard +

+

(gp-restore-wind state wind) +

+

To restore at the current wind level meaning that any let-with-guard construct inside code ... will be restored but the defined var ... will not be restored, if that is wanted then use (- wind 1) instead. - -

G.L. (<let-with-lr-guard> wind lguard rguard ((var init) ...) code ...) +

+

G.L. (<let-with-lr-guard> wind lguard rguard ((var init) ...) code ...) This is very similar to the previous construct but for this ideom we define a lguard and rguard in stead. That stack space between lguard - and rguard is strongly guarded e.g. one can mutate var ... -inside that space. To the right of rguard the variables are guarded if + and rguard is strongly guarded e.g. one can mutate var ... +inside that space. To the right of rguard the variables are guarded if no mutation is done in that space. - -

scm (let-with-guard s wind guard ((var init) ...) code ...) +

+

scm (let-with-guard s wind guard ((var init) ...) code ...) scm (let-with-lr-guard s wind lguard rguard ((var init) ...) code ...) -This is scheme macro that will defined scheme macros lguard and +This is scheme macro that will defined scheme macros lguard and rguard or just a guard. And the code executed inside them e.g. - -

(guard gcode ...) - -

will be protected accordingly the description above for the guile log macrology +

+

(guard gcode ...) +

+

will be protected accordingly the description above for the guile log macrology versions. Finally note that s should be a symbol bounded to the current environment. +

+

2.4 Unify Constructs

- -

-In the forms below remember to use unquote for forms that need to be scheme evaluated inside the patterns. - -

G.L. (let<> ((m pat val) ...) code ...), this will pattern-match val using m = (+ ++ - *) and then pattern-match the next and so on and lastly execute a (<and> code ...). - -

G.L. (<=> X Y), unifies X and Y with occurs check - -

G.L. <==>, the same as <=> but using the - matcher in stead of + meaning that no unifying is used. - -

G.L. <r=>, the same as <=> but using ++ in stead of +. - + + + + + +

In the forms below remember to use unquote for forms that need to be scheme evaluated inside the patterns. +

+

G.L. (let<> ((m pat val) ...) code ...), this will pattern-match val using m = (+ ++ - *) and then pattern-match the next and so on and lastly execute a (<and> code ...). +

+

G.L. (<=> X Y), unifies X and Y with occurs check +

+

G.L. <==>, the same as <=> but using the - matcher in stead of + meaning that no unifying is used. +

+

G.L. <r=>, the same as <=> but using ++ in stead of +. +

+ +

2.5 variable binding

- -

-G.L. (<let> ((V X) ...) code ...), Will introduce bindings V with values X and then evaluate code in guile-log mode with an implicit <and>. - -

G.L. <let*>, relates to <let> as let* relates to let - -

G.L. <letrec>, this th letrec version of <let>. - -

G.L. (<var> (v1 v2 ...) code ...), will make fresh new unify variables v1 v2 ... and use them in a G.L. (<and> code ...) e.g. the same as (<let> ((v1 (gp-var!)) ...) code ...). - -

G.L. (<hvar> (v1 v2 ...) code ...), like <var>, but variable identities is located on the heap instead. - + + + + + + +

G.L. (<let> ((V X) ...) code ...), Will introduce bindings V with values X and then evaluate code in guile-log mode with an implicit <and>. +

+

G.L. <let*>, relates to <let> as let* relates to let +

+

G.L. <letrec>, this th letrec version of <let>. +

+

G.L. (<var> (v1 v2 ...) code ...), will make fresh new unify variables v1 v2 ... and use them in a G.L. (<and> code ...) e.g. the same as (<let> ((v1 (gp-var!)) ...) code ...). +

+

G.L. (<hvar> (v1 v2 ...) code ...), like <var>, but variable identities is located on the heap instead. +

+

2.6 failure and cc

- -

-G.L. <cc>, represent a continuation or success can be used like (<if> P <cc> Y) - -

G.L. <fail>, will issue a failure and start backtracking. - -

G.L. (<fail> p), will use p as a failure backtracking object. - -

G.L. <cut>, will issue a cut e.g. we will stop backtracking from here on used like (<and> P1 <cut> P2) if P2 fails it will typically jump over P1 and back to where the cut point is defined. + + + + + +

G.L. <cc>, represent a continuation or success can be used like (<if> P <cc> Y) +

+

G.L. <fail>, will issue a failure and start backtracking. +

+

G.L. (<fail> p), will use p as a failure backtracking object. +

+

G.L. <cut>, will issue a cut e.g. we will stop backtracking from here on used like (<and> P1 <cut> P2) if P2 fails it will typically jump over P1 and back to where the cut point is defined. G.L. (<cut> code ...), the same as (<and> <cut> code ...) - -

G.L. (<next>), will backtrack to the next clause in a match (TODO: this has not been tested). - -

G.L. (<with-fail> p code ...), this will use p as a failure for G.L. (<and> code ...) - -

G.L. (<with-cut> cut code ...), this will use cut as a cut failure for G.L. (<and> code ...) - -

G.L. (<with-cc> cc code ...), this will use cc as the continuation. - -

G.L. (<with-s> s code ...), this will use s as the state. - -

G.L. (<peek-fail> p code ...) This will bind p to the failure thunk at this instruction. - +

+

G.L. (<next>), will backtrack to the next clause in a match (TODO: this has not been tested). +

+ + + + + +

G.L. (<with-fail> p code ...), this will use p as a failure for G.L. (<and> code ...) +

+

G.L. (<with-cut> cut code ...), this will use cut as a cut failure for G.L. (<and> code ...) +

+

G.L. (<with-cc> cc code ...), this will use cc as the continuation. +

+

G.L. (<with-s> s code ...), this will use s as the state. +

+

G.L. (<peek-fail> p code ...) This will bind p to the failure thunk at this instruction. +

+ +

2.7 defining function and matching

- -

-Scm (<define> (f x ...) code ...), this will define a guile-log function named f with arguments x ... the code will be executed under the G.L environment with an implicit <and> around code ... then f can be used inside G.L. like (<and> (f x y) ...) - -

Scm (<<define>> (f a ...) (p ... code) ...), default #:mode = + - -

Scm (<<define>> (#:mode mode f a ...) (p ... code) ...), - -

This is close to prolog functions. E.g. a ... is the signature, p ... is the pattern that umatches the arguments and if there is a match then code is evaluated in G.L. context. if code failes the next line is tried unless there is a <cut> that forses a return from the function. - -

Scm (<<define->> (f a ...) (p ... code) ...), default #:mode = - e.g. non unifying match. - -

Scm, (<def> (f a ...) (p ... code) ...), - -

Scm, (<def-> (f a ...) (p ... code) ...), - -

This is as with <<define>>,<<define->> but if code fails it will issue a cut and leave the function. - -

Scm (<lambda> (x ...) code ...), this similar like define but an anonymous function. - -

Scm (<<lambda>> (p ... code) ...), this is anonymous <<define> without explisit arguments and mode. - -

Scm (<case-lambda> ((a ..) code ...) ...), th guile-log case-lambda version. - -

Scm (<<case-lambda>> ((p ... code) ...) ...), this is the case-lambda version of <<lambda>>. - -

Scm (</.> code ...) This is (<lambda> () code ...). - -

G.L. (<recur> n ((w v) ...) code ...), this works like the corresponding named let but in guile-log mode but it defines the loop function n to work inside G.L. and the form itself is in G.L. - -

G.L. (<letrec> ((v x) ...) code ...), this will bind v ... with x ... in a letrec manner and then execute code ... with an implicit <and> around it. - -

G.L. (<match> [#:mode +] (pat ... code) ...), this is a small wrapper around umatch the difference is that if works under G.L. and that code is evaluated under G.L. and that backtracking is correctly setup-ed. - -

Scm (<def>      (f [#:mode +] a ..) (p ... code) ...))
-Scm (<<define>> (f [#:mode +] a ..) (p ... code) ...))
-
-This is a sugar for essentially, (<define> (f a ...) (<match> [#:mode +] (a ...) (p ... code) ...)). The difference is that <<define>> will never backtrack to a new match row and <def> will backtrack to the next matcher if the code part fails. - -

G.L. (<funcall> f . l), this is actually funcall with the difference is that it will make sure to lookup f if it is a unify variable pointing to a lambda. - -

G.L. (<apply> f a ... l), this is as with apply, but logic variables will be looked up. - + + + + + + + + + + + + + + + + +

Scm (<define> (f x ...) code ...), this will define a guile-log function named f with arguments x ... the code will be executed under the G.L environment with an implicit <and> around code ... then f can be used inside G.L. like (<and> (f x y) ...) +

+

Scm (<<define>> (f a ...) (p ... code) ...), default #:mode = + +

+

Scm (<<define>> (#:mode mode f a ...) (p ... code) ...), +

+

This is close to prolog functions. E.g. a ... is the signature, p ... is the pattern that umatches the arguments and if there is a match then code is evaluated in G.L. context. if code failes the next line is tried unless there is a <cut> that forses a return from the function. +

+

Scm (<<define->> (f a ...) (p ... code) ...), default #:mode = - e.g. non unifying match. +

+

Scm, (<def> (f a ...) (p ... code) ...), +

+

Scm, (<def-> (f a ...) (p ... code) ...), +

+

This is as with <<define>>,<<define->> but if code fails it will issue a cut and leave the function. +

+

Scm (<lambda> (x ...) code ...), this similar like define but an anonymous function. +

+

Scm (<<lambda>> (p ... code) ...), this is anonymous <<define> without explisit arguments and mode. +

+

Scm (<case-lambda> ((a ..) code ...) ...), th guile-log case-lambda version. +

+

Scm (<<case-lambda>> ((p ... code) ...) ...), this is the case-lambda version of <<lambda>>. +

+

Scm (</.> code ...) This is (<lambda> () code ...). +

+

G.L. (<recur> n ((w v) ...) code ...), this works like the corresponding named let but in guile-log mode but it defines the loop function n to work inside G.L. and the form itself is in G.L. +

+

G.L. (<letrec> ((v x) ...) code ...), this will bind v ... with x ... in a letrec manner and then execute code ... with an implicit <and> around it. +

+ +

G.L. (<match> [#:mode +] (pat ... code) ...), this is a small wrapper around umatch the difference is that if works under G.L. and that code is evaluated under G.L. and that backtracking is correctly setup-ed. +

+
Scm (<def>      (f [#:mode +] a ..) (p ... code) ...))
+Scm (<<define>> (f [#:mode +] a ..) (p ... code) ...))
+

This is a sugar for essentially, (<define> (f a ...) (<match> [#:mode +] (a ...) (p ... code) ...)). The difference is that <<define>> will never backtrack to a new match row and <def> will backtrack to the next matcher if the code part fails. +

+ +

G.L. (<funcall> f . l), this is actually funcall with the difference is that it will make sure to lookup f if it is a unify variable pointing to a lambda. +

+

G.L. (<apply> f a ... l), this is as with apply, but logic variables will be looked up. +

+

2.8 printing information

- -

-Scm (tr x), translate unbound variables with a prefix governed by *gp-var-tr* fluid. - -

Scm (tr pre x), the same as above but using pre as the prefix. - -

G.L. (<pp> x), this will pretty-print x and print it as a list-version of the code - -

(<pp-dyn> redo-print undo-print), when the current unify stack backtracks across the current position in the stack it will do a (<pp> undo-print), it redoes across this dynwind it will pretty-print e.g. (<pp> Redo-print). - -

G.L. (<format> port str arg ...), as with format, but under G.L. - + + + + + + +

Scm (tr x), translate unbound variables with a prefix governed by *gp-var-tr* fluid. +

+

Scm (tr pre x), the same as above but using pre as the prefix. +

+

G.L. (<pp> x), this will pretty-print x and print it as a list-version of the code +

+

(<pp-dyn> redo-print undo-print), when the current unify stack backtracks across the current position in the stack it will do a (<pp> undo-print), it redoes across this dynwind it will pretty-print e.g. (<pp> Redo-print). +

+

G.L. (<format> port str arg ...), as with format, but under G.L. +

+

2.9 evaluate scheme expressions

- -

-G.L. (<code> code ...), will execute (begin code ...) as scheme and then success. - -

G.L. (<tail-code> (p cc) code ...), this will bind the failure thunk p and continuation cc inside code ... which is evaluated under Scm e.g. an implicit begin. It is the scheme code's responsibility to continue using cc or backtrack using p. - -

G.L. (<when> S), the same as (if S <cc>). - + + + + + + + + + + +

G.L. (<code> code ...), will execute (begin code ...) as scheme and then success. +

+

G.L. (<tail-code> (p cc) code ...), this will bind the failure thunk p and continuation cc inside code ... which is evaluated under Scm e.g. an implicit begin. It is the scheme code’s responsibility to continue using cc or backtrack using p. +

+

G.L. (<when> S), the same as (if S <cc>). +

G.L. (if S X)
 G.L. (if S X Y)
-
-S is an ordinary scheme expression and if true will execute X in G.L else Y in G.L. or fail if the scheme expression return #f. - -

Similarly there is (without =>) -

G.L. (when p c ...)
+

S is an ordinary scheme expression and if true will execute X in G.L else Y in G.L. or fail if the scheme expression return #f. +

+

Similarly there is (without =>) +

G.L. (when p c ...)
 G.L. (cond (p a ...) ...)
 G.L. (case a (p a ...) ...)
 
- -

G.L. (<return> code ...), this will do a Scm: (begin code ...) and simply return that form in the guile log pass. - -

G.L. (<ret> val), the same as (<return> (u-scm val)) - -

G.U. (<dynwind> redo-thunk undo-thunk), dynwind that when the unify stack is going in forward direction the redo-thunk is evaluated and else when we backtrack over this barrier the undo-thunk is evaluated. - +

G.L. (<return> code ...), this will do a Scm: (begin code ...) and simply return that form in the guile log pass. +

+

G.L. (<ret> val), the same as (<return> (u-scm val)) +

+

G.U. (<dynwind> redo-thunk undo-thunk), dynwind that when the unify stack is going in forward direction the redo-thunk is evaluated and else when we backtrack over this barrier the undo-thunk is evaluated. +

+

2.10 go from scheme to guile-log

- -

-Scm (<with-guile-log> (p cc) code ...), this will start a guile-log session using failure think p and continuation cc and use p as a cut as well. - -

Scm (<with-guile-log> (cut p cc) code ...), this will start a guile-log session using failure thunk p and continuation cc and use cut as the cut failure thunk. - -

Scm (<ask> P ...), will execute (<and> P ...) and if success return #t else if fail return #f - -

Scm (<eval> (v1 ...) code fini cc), this will bind new variables v1 ... and execute code with failure thunk fini and continuation cc under G.L. - -

Scm (<run> n (v ...) code ...), bind v ... with variables and execute the code and collect the list of list of bindings of v at success if (v ...) = (w) then it will return a list of values. n is the maximum numbers of success results and skipping n results in no limit on the number of successes. - -

Scm (<clear>), cleares the stack back to start, use this when finished with <take>,<run> etc. - -

G.L. (<stall>), this will stall a computation and allow it to continue at the users will and also be able to store the state. - -

Scm (<continue>), this will make it possible to continue a stalled run, but if the run opted out after n successes then must ask for the number of more successes as well by using: - -

Scm (<continue> n), with n the number of more successes to returnif we started with (<run> n () ...). - -

Scm <take>, this is the same as <continue>. - -

Scm (<state-ref>), this returns a value of the current state for which the system can restore later on. - -

Scm (<state-set!> s), restores the state represented by the datadtructure s that was produced by <state-ref>. - + + + + + + + + + + + +

Scm (<with-guile-log> (p cc) code ...), this will start a guile-log session using failure think p and continuation cc and use p as a cut as well. +

+

Scm (<with-guile-log> (cut p cc) code ...), this will start a guile-log session using failure thunk p and continuation cc and use cut as the cut failure thunk. +

+

Scm (<ask> P ...), will execute (<and> P ...) and if success return #t else if fail return #f +

+

Scm (<eval> (v1 ...) code fini cc), this will bind new variables v1 ... and execute code with failure thunk fini and continuation cc under G.L. +

+

Scm (<run> n (v ...) code ...), bind v ... with variables and execute the code and collect the list of list of bindings of v at success if (v ...) = (w) then it will return a list of values. n is the maximum numbers of success results and skipping n results in no limit on the number of successes. +

+

Scm (<clear>), cleares the stack back to start, use this when finished with <take>,<run> etc. +

+

G.L. (<stall>), this will stall a computation and allow it to continue at the users will and also be able to store the state. +

+

Scm (<continue>), this will make it possible to continue a stalled run, but if the run opted out after n successes then must ask for the number of more successes as well by using: +

+

Scm (<continue> n), with n the number of more successes to returnif we started with (<run> n () ...). +

+

Scm <take>, this is the same as <continue>. +

+

Scm (<state-ref>), this returns a value of the current state for which the system can restore later on. +

+

Scm (<state-set!> s), restores the state represented by the datadtructure s that was produced by <state-ref>. +

+

2.11 Using logical variables in scheme mode.

-

When the guile-log system enters scheme mode one may for example need to use state information. But as entering scheme from guile-log the state is implicitly marked for the following macros to work without actually explicitly bound a state variable as may be done as well e.g. - -

- -

(<scm> x) returns essentially a scheme representation of x but where logical variables are included as themselves. - -

<cons>, <car>, <cdr>, used exactly as with corresponding scheme functions. - -

If by some reason one need to do the whole program using (almost) only the state -information, one can do so by setting the variable *kanren-assq* to +

+ + + + + + +

(<scm> x) returns essentially a scheme representation of x but where logical variables are included as themselves. +

+

<cons>, <car>, <cdr>, used exactly as with corresponding scheme functions. +

+

If by some reason one need to do the whole program using (almost) only the state +information, one can do so by setting the variable *kanren-assq* to #t. Doing this will mean that the program almost works as plain kanren. - +

+

2.12 Guile-log macro definitions

- -

-(define-guile-log name . l), this works like define-syntax, but it will mark the symbol as a guile-log macro. - -

(log-code-macro x), marks x as a log-code macro e.g. it will inline it's code into the continuation in an and sequence hence reduce the number of needed closures. - -

Scm (parse<> (cut w fail cc) code), used to continue guile-log macro + + + + + + +

(define-guile-log name . l), this works like define-syntax, but it will mark the symbol as a guile-log macro. +

+

(log-code-macro x), marks x as a log-code macro e.g. it will inline it’s code into the continuation in an and sequence hence reduce the number of needed closures. +

+

Scm (parse<> (cut w fail cc) code), used to continue guile-log macro expansion e.g. we could define <and!!> using -

  (define-guile-log <and!!>
+

  (define-guile-log <and!!>
      (syntax-rules ()
        ((_ meta arg ...)
-        (parse<> meta (<and> (<and!> arg) ...)))))
+        (parse<> meta (<and> (<and!> arg) ...)))))
 
- -

That is a guile-log macro is an ordinary macro but in guile-log expansion it +

That is a guile-log macro is an ordinary macro but in guile-log expansion it will add the first argument a meta to that macro that are then used in an ordinary expansion where we indicate a continue in guile-log mode by using parse<>. - -

<define-guile-log-rule>, this is a fast one-liner version of define-guile-log and throws one into the G.L. context of the producer without explisitly using (cut s p cc). - -

Scm (define-and-log name . l), used in and log context to get the next lines in the <and> into the macro. the match matching signature in the macro is - -

(f (cut s p cc) (f . l) e ...), for a function like signature and - -

(f (cut s p cc) () e ...), for a symbol like signature. - -

An example using this is to for example have constructs that avoids nesting. +

+

<define-guile-log-rule>, this is a fast one-liner version of define-guile-log and throws one into the G.L. context of the producer without explisitly using (cut s p cc). +

+

Scm (define-and-log name . l), used in and log context to get the next lines in the <and> into the macro. the match matching signature in the macro is +

+

(f (cut s p cc) (f . l) e ...), for a function like signature and +

+

(f (cut s p cc) () e ...), for a symbol like signature. +

+

An example using this is to for example have constructs that avoids nesting. For example we can define G.L. (<v> v ...)) through, - -

(define-and-log <v>
+

+
(define-and-log <v>
   (syntax-rules ()
-    ((_ w (<v> v ...) e ...)
-     (<let> w (v ...) e ...))))
+    ((_ w (<v> v ...) e ...)
+     (<let> w (v ...) e ...))))
 
- -

And we would use it as - -

(<define> (f x)
-  (<v> y z)
-  (<=> x (y . z))
+

And we would use it as +

+
(<define> (f x)
+  (<v> y z)
+  (<=> x (y . z))
   (g y z))
 
-

2.13 Controling the kind of variable binding used, kannren assq, or a prolog stack.

-

-(<logical++>),(<logical-->), turn on/off the usage of assq logical variables. Works by introducing a + +

2.13 Controling the kind of variable binding used, kannren assq, or a prolog stack.

-

To make the whole session in kanren assq mode one can set *kanren-assq* to #t. + + + -

Example: -

(<run> 1 (x) (<=> x 1) (<pp> (pk S)))
-;;; ((<gp-stack> 5404676))
+

(<logical++>),(<logical-->), turn on/off the usage of assq logical variables. Works by introducing a +

+

To make the whole session in kanren assq mode one can set *kanren-assq* to #t. +

+

Example: +

(<run> 1 (x) (<=> x 1) (<pp> (pk S)))
+;;; ((<gp-stack> 5404676))
 
-(<run> 1 (x) (<logical++>) (<=> x 1) (<pp> (pk S)))
-;;; ((<gp-stack> 5404676 (<#0 : 1> . 1)))
+(<run> 1 (x) (<logical++>) (<=> x 1) (<pp> (pk S)))
+;;; ((<gp-stack> 5404676 (<#0 : 1> . 1)))
 
-(<run> 1 (x) (<logical++>) (<var> (y) (<=> y 1) (<pp> (pk S))))
-;;; ((<gp-stack> 5404676 (<#0 : 1451764> . 1)))
+(<run> 1 (x) (<logical++>) (<var> (y) (<=> y 1) (<pp> (pk S))))
+;;; ((<gp-stack> 5404676 (<#0 : 1451764> . 1)))
 
- -

The format of the state is for the car to be the stack object and the cdr will +

The format of the state is for the car to be the stack object and the cdr will represent the association list. Here we see how we associated 1 to the guile-variable <#0 : 1>. Also note in the last example how <#0 : 1451764> indicates that it has been allocated on the heap in logical++ mode. - +

+

2.14 Returning multiple values.

- -

(<and> (<values> (v ...) (f args ...)) ...) + +

(<and> (<values> (v ...) (f args ...)) ...) This is a way to define multiple values v ... as a return from f. For this to work we need to add (<cc> x ...) at the logical end of the definition of the functione. - -

Example: -

(define-syntax s-pair!? 
+

+

Example: +

(define-syntax s-pair!? 
   (syntax-rules ()
     ((_ x)   (gp-pair!? (s-lookup x)   S))
     ((_ x S) (gp-pair!? (s-lookup x S) S))))
@@ -492,65 +602,74 @@ This is a way to define multiple values v ... as a return from  s p cc x)
+(define (<pair?> s p cc x)
   (let ((ss (s-pair!? x s)))
     (if ss
         (cc ss p)
         (p))))
 
-(<define> (!car! x)
-  (<pair?> x)
-  (<cc> (<car> x)))
+(<define> (!car! x)
+  (<pair?> x)
+  (<cc> (<car> x)))
 
 and use it as,
 
-(<run> 1 (x y) (<=> x '(1 2)) (values (z) (!car! x)) (<=> y z))
-=> (((1 2) 1))
+(<run> 1 (x y) (<=> x '(1 2)) (values (z) (!car! x)) (<=> y z))
+=> (((1 2) 1))
 
- +

2.15 Acumulators

- -

-These constructs will accumulate all possible values of a construct. - -

G.L. (<fold> kons knil Lam X L), This will initiate an accumulator to knil and then use kons as the acumulating function. The guile log closure Lam is executeded and X will represent the result that will be accumulated. The final result is then added to L. - -

G.L. (<fold-step> kons knil Lam X L), the semantic is similar to <fold>, but the form will at each iteration succeeds with L bound to the current accumulator value. - -

Example: -

(<define> (f x n m) (if (< n m) (<or> (<=> x n) (f x (+ n 1) m))))
-
-(<run> * (l) (<var> (x) (<fold> + 0 (</.> (f x 0 10)) x l)))
-=> (45)
-
-(<run> * (l) (<var> (x) (<fold-step> + 0 (</.> (f x 0 10)) x l)))
-=> (0 1 3 6 10 15 21 28 36 45)
+
+
+
+
+
+

These constructs will accumulate all possible values of a construct. +

+

G.L. (<fold> kons knil Lam X L), This will initiate an accumulator to knil and then use kons as the acumulating function. The guile log closure Lam is executeded and X will represent the result that will be accumulated. The final result is then added to L. +

+

G.L. (<fold-step> kons knil Lam X L), the semantic is similar to <fold>, but the form will at each iteration succeeds with L bound to the current accumulator value. +

+

Example: +

(<define> (f x n m) (if (< n m) (<or> (<=> x n) (f x (+ n 1) m))))
+
+(<run> * (l) (<var> (x) (<fold> + 0 (</.> (f x 0 10)) x l)))
+=> (45)
+
+(<run> * (l) (<var> (x) (<fold-step> + 0 (</.> (f x 0 10)) x l)))
+=> (0 1 3 6 10 15 21 28 36 45)
 
- -

G.L. (<fix-fold> kons knil Lam X Y L), - -

G.L. (<fix-fold-step-> kons knil Lam X Y L), - -

this is as with <fold> etc, but the acumulation is done for each fixed Y. - -

Example: -

(<define> (f x n m) 
-   (if (< n m) (<or> (<=> x n) (f x (+ n 1) m))))
-
-(<run> * (l) 
-  (<var> (x y) 
-    (<fix-fold> cons '() 
-         (</.> (f x 0 5) (f y 0 (<scm> x))) 
+

G.L. (<fix-fold> kons knil Lam X Y L), +

+

G.L. (<fix-fold-step-> kons knil Lam X Y L), +

+

this is as with <fold> etc, but the acumulation is done for each fixed Y. +

+

Example: +

(<define> (f x n m) 
+   (if (< n m) (<or> (<=> x n) (f x (+ n 1) m))))
+
+(<run> * (l) 
+  (<var> (x y) 
+    (<fix-fold> cons '() 
+         (</.> (f x 0 5) (f y 0 (<scm> x))) 
          x y l)))
-=> ((4 3 2 1) (4 3 2) (4 3) (4))
+=> ((4 3 2 1) (4 3 2) (4 3) (4))
 
-(<run> * (l) 
-   (<var> (x y) 
-     (<fix-fold-step> cons '() 
-        (</.> (f x 0 5) (f y 0 (<scm> x))) 
+(<run> * (l) 
+   (<var> (x y) 
+     (<fix-fold-step> cons '() 
+        (</.> (f x 0 5) (f y 0 (<scm> x))) 
         x y l)))
-=> ((1) (2 1) (3 2 1) (4 3 2 1) (2) (3 2) (4 3 2) (3) (4 3) (4))
+=> ((1) (2 1) (3 2 1) (4 3 2 1) (2) (3 2) (4 3 2) (3) (4 3) (4))
 
+
+
+

+Next: , Previous: , Up: Top   [Index]

+
+ - + + diff --git a/doc/guile-log/index.html b/doc/guile-log/index.html index 7ba30924c2508de4524c38f2a1fd80d08ee8340e..7920319b9f3d35b7cca04e1bf51953c6450cdc2b 100644 --- a/doc/guile-log/index.html +++ b/doc/guile-log/index.html @@ -1,60 +1,110 @@ - + + + + -Preliminary Manual - - - - - - - +Preliminary Manual: Top + + + + + + + + + + + + +a.summary-letter {text-decoration: none} +blockquote.smallquotation {font-size: smaller} +div.display {margin-left: 3.2em} +div.example {margin-left: 3.2em} +div.indentedblock {margin-left: 3.2em} +div.lisp {margin-left: 3.2em} +div.smalldisplay {margin-left: 3.2em} +div.smallexample {margin-left: 3.2em} +div.smallindentedblock {margin-left: 3.2em; font-size: smaller} +div.smalllisp {margin-left: 3.2em} +kbd {font-style:oblique} +pre.display {font-family: inherit} +pre.format {font-family: inherit} +pre.menu-comment {font-family: serif} +pre.menu-preformatted {font-family: serif} +pre.smalldisplay {font-family: inherit; font-size: smaller} +pre.smallexample {font-size: smaller} +pre.smallformat {font-family: inherit; font-size: smaller} +pre.smalllisp {font-size: smaller} +span.nocodebreak {white-space:nowrap} +span.nolinebreak {white-space:nowrap} +span.roman {font-family:serif; font-weight:normal} +span.sansserif {font-family:sans-serif; font-weight:normal} +ul.no-bullet {list-style: none} +--> + + + - -

Preliminary Manual

-
+ + +

Preliminary Manual

+ + + +

-Next: , -Up: (dir) -


+Next: , Up: (dir)   [Index]

+
+ +

Guile Log

+ +

Documentation for the Guile-Log Logic Programming Environment for Guile 2.0 v0.4 +

+ + + + + + + + + + + + + + + + + -

Guile Log

-

Documentation for the Guile-Log Logic Programming Environment for Guile 2.0 v0.4 +


+
+

+Next: , Up: (dir)   [Index]

+
+ - - - + + diff --git a/doc/guile-log/kanren.html b/doc/guile-log/kanren.html index 2aba7aaa09fa1f35b9d823ef45b889630c1a04a1..2ea78e7d5e468ec69b0fbd6984e55351f554fbaa 100644 --- a/doc/guile-log/kanren.html +++ b/doc/guile-log/kanren.html @@ -1,170 +1,230 @@ - + + + + -kanren - Preliminary Manual - - - - - - - +Preliminary Manual: kanren + + + + + + + + + + + + + +a.summary-letter {text-decoration: none} +blockquote.smallquotation {font-size: smaller} +div.display {margin-left: 3.2em} +div.example {margin-left: 3.2em} +div.indentedblock {margin-left: 3.2em} +div.lisp {margin-left: 3.2em} +div.smalldisplay {margin-left: 3.2em} +div.smallexample {margin-left: 3.2em} +div.smallindentedblock {margin-left: 3.2em; font-size: smaller} +div.smalllisp {margin-left: 3.2em} +kbd {font-style:oblique} +pre.display {font-family: inherit} +pre.format {font-family: inherit} +pre.menu-comment {font-family: serif} +pre.menu-preformatted {font-family: serif} +pre.smalldisplay {font-family: inherit; font-size: smaller} +pre.smallexample {font-size: smaller} +pre.smallformat {font-family: inherit; font-size: smaller} +pre.smalllisp {font-size: smaller} +span.nocodebreak {white-space:nowrap} +span.nolinebreak {white-space:nowrap} +span.roman {font-family:serif; font-weight:normal} +span.sansserif {font-family:sans-serif; font-weight:normal} +ul.no-bullet {list-style: none} +--> + + + - -
+ + +

-Next: , -Previous: sed/grep, -Up: Top -


+Next: , Previous: , Up: Top   [Index]

- +
+

12 Kanren

-

Almost all of the kanren interface is implemented ontop of guile-log to use it import logic guile-log kanren. One could say that the kanren interface is the functional sister to guile-log which is more a macro framework as such guile-log is about 2x faster the kanren, but kanren has more beutifull semantics. E.g. the kanren operation maps function arguments to functions. The kanren interface is divided into two categories of functionals, facts and relations. One combine facts into relations. The main difference is that fact functions have standardized arguments and relations have customized arguments. Also conversely evaluating the relation will return back a fact. +

+

12.1 The fact building blocks

- -

-succed, This functional item repressents a term that always succeeds. - -

fail,sfail, Both of these will always fail. - -

(all f ...), all will produce a functional item representing success if all f ... will success. - -

(all! f ...), all! will produce only one success where all f ... successes. - -

(all!! f ...), all!! sucesses where all f ... successes only one time. - -

(all-interleave f ...), As with all, this construct sucesses if all of the parts sucesses, but the backtracking is designed so that it backtracks evenly and hence avoids problems due to some of the constructs can backtrack an infinite amount of times berfore the success is found. To note is also that this construct has exponential memory complexity with the depth of the search. - -

(any f ...), this will success if any of f ... sucesses. - -

(any-interleave f ...), as any, but one at a time will be tried cyclically and hence will find a solution in finite time if there exists one, else it could risk getting stuck in an infinite bacltracking sequence. - -

(any-union f ...) This is similar to any-interleave, but it will + + + + + + + + + + + + + + + + + + + + + + + + +

succed, This functional item repressents a term that always succeeds. +

+

fail,sfail, Both of these will always fail. +

+

(all f ...), all will produce a functional item representing success if all f ... will success. +

+

(all! f ...), all! will produce only one success where all f ... successes. +

+

(all!! f ...), all!! sucesses where all f ... successes only one time. +

+

(all-interleave f ...), As with all, this construct sucesses if all of the parts sucesses, but the backtracking is designed so that it backtracks evenly and hence avoids problems due to some of the constructs can backtrack an infinite amount of times berfore the success is found. To note is also that this construct has exponential memory complexity with the depth of the search. +

+

(any f ...), this will success if any of f ... sucesses. +

+

(any-interleave f ...), as any, but one at a time will be tried cyclically and hence will find a solution in finite time if there exists one, else it could risk getting stuck in an infinite bacltracking sequence. +

+

(any-union f ...) This is similar to any-interleave, but it will skipp multiples of similar sucesses e.g. if (all f1 f2) is a success, it will skipp the f1 and continue trying with the f2 which will success. Esentially this capture the case when all f ... bind the same variable to a value and we do not backtrack to the same value multiple times. - -

(if-only pred x), (if-only pred x y), The first form is equivalent to (all (all! pred) x). For the second form if pred successes then the form will fail if x fails. If pred first fails, then y is executed. - -

(if-some p x), (if-some p x y), The first form is equivalent to (all p x) and in the second form y is executed if p fails. - -

(succeeds f ...), is similar to (all f ...) but if this success it will backtrack and undo any bindings and continue. - -

(fails f ...), if (all f ...) fails then this form will backtrack and undo any bindings and continue with a success. - -

(== a b), unifies the terms. - -

(*equal? a b), this will try to unify without any variable binding. - -

(let-lv (id ...) code), this will bind id ... to new fresh variables inside code. - -

(project (var ...) gl), This will take a specification of a functional item represeting a fact, gl and use the lookuped values of var ... inside the gl spec. This logic is captured in a new functinal fact. If the lookup results in a variable an error will be produced. - -

(project/no-check (var ...) gl), As with project, but there is no error reported if the lookup results in a variable. - -

(predicate scheme-expr code), Succeeds if scheme-expr is true. - -

(var? x), true if x is a logical variable. - -

(reify x), will produce a scheme representation of x. - -

_, produces a fress new logical variable in it's place. - +

+

(if-only pred x), (if-only pred x y), The first form is equivalent to (all (all! pred) x). For the second form if pred successes then the form will fail if x fails. If pred first fails, then y is executed. +

+

(if-some p x), (if-some p x y), The first form is equivalent to (all p x) and in the second form y is executed if p fails. +

+

(succeeds f ...), is similar to (all f ...) but if this success it will backtrack and undo any bindings and continue. +

+

(fails f ...), if (all f ...) fails then this form will backtrack and undo any bindings and continue with a success. +

+

(== a b), unifies the terms. +

+

(*equal? a b), this will try to unify without any variable binding. +

+

(let-lv (id ...) code), this will bind id ... to new fresh variables inside code. +

+

(project (var ...) gl), This will take a specification of a functional item represeting a fact, gl and use the lookuped values of var ... inside the gl spec. This logic is captured in a new functinal fact. If the lookup results in a variable an error will be produced. +

+

(project/no-check (var ...) gl), As with project, but there is no error reported if the lookup results in a variable. +

+

(predicate scheme-expr code), Succeeds if scheme-expr is true. +

+

(var? x), true if x is a logical variable. +

+

(reify x), will produce a scheme representation of x. +

+

_, produces a fress new logical variable in it’s place. +

+

12.2 relations

- -

-This is documentation derived from the kanren sources. - -

(relation (VAR ...) (to-show TERM ...) [GL], Defines a relation of arity (length '(TERM ...)) with an optional body GL. VAR ... are logical variables that are local to the relation, i.e., appear in TERM ... or GL. It's better to list as VAR ... only logical variables that appear in TERM .... Variables that appear only in GL should be introduced with exists. That makes their existential quantification clearer. Variables that appear in TERM ... are universally quantified. - -

(relation (head-let TERM ...) [GL]) -A simpler, and more efficient kind of relation. The simplicity comes from a simpler pattern at the head of the relation. The pattern must be linear and shallow with respect to introduced variables. The gl is optional (although omitting it doesn't make much sense in practice) There are two kinds of head-terms. One kind is an identifier. This identifier is taken to be a logical identifier, to be unified with the corresponding actual argument. Each logical identifier must occur exactly once. Another kind of a head-terms is anything else. That anything else may be a constant, a scheme variable, or a complex term that may even include logical variables such as _ – but not logical variables defined in the same head-let pattern. To make the task of distinguishing logical identifiers -from anything else easier, we require that anything else of a sort of a manifest constant be explicitly quoted or quasiquoted. It would be OK to add `, to each 'anything else' term. - -

Examples: - -

(relation-head-let (x y z) (foo x y z)) + + + + + + + + +

This is documentation derived from the kanren sources. +

+

(relation (VAR ...) (to-show TERM ...) [GL], Defines a relation of arity (length '(TERM ...)) with an optional body GL. VAR ... are logical variables that are local to the relation, i.e., appear in TERM ... or GL. It’s better to list as VAR ... only logical variables that appear in TERM .... Variables that appear only in GL should be introduced with exists. That makes their existential quantification clearer. Variables that appear in TERM ... are universally quantified. +

+

(relation (head-let TERM ...) [GL]) +A simpler, and more efficient kind of relation. The simplicity comes from a simpler pattern at the head of the relation. The pattern must be linear and shallow with respect to introduced variables. The gl is optional (although omitting it doesn’t make much sense in practice) There are two kinds of head-terms. One kind is an identifier. This identifier is taken to be a logical identifier, to be unified with the corresponding actual argument. Each logical identifier must occur exactly once. Another kind of a head-terms is anything else. That anything else may be a constant, a scheme variable, or a complex term that may even include logical variables such as _ – but not logical variables defined in the same head-let pattern. To make the task of distinguishing logical identifiers +from anything else easier, we require that anything else of a sort of a manifest constant be explicitly quoted or quasiquoted. It would be OK to add ‘, to each ’anything else’ term. +

+

Examples: +

+

(relation-head-let (x y z) (foo x y z)) Here x y and z are logical variables. - -

(relation-head-let (x y '7) (foo x y)) +

+

(relation-head-let (x y '7) (foo x y)) Here we used a manifest constant that must be quoted - -

(relation-head-let (x y `(1 2 . ,_)) (foo x y)) +

+

(relation-head-let (x y `(1 2 . ,_)) (foo x y)) We used a quasi-quoted constant with an anonymous variable. - -

relation (ANNOT-VAR ...) (to-show TERM ...) [GL] -where ANNOT-VAR is either a simple VAR or (once VAR) where 'once' is a distingushed symbol. The latter form introduces a once-var, aka linear variable. A linear variable appears only once in TERM ... and only at the top level (that is, one and only one TERM in the to-show pattern contains ONCE-VAR, and that term is ONCE-VAR itself). In addition, ONCE-VAR must appear at most once in the body GL. (Of course, then ONCE-VAR could be _, instead.) If these conditions are satisfied, we can replace a logical variable ONCE-VAR with a regular Scheme variable. - -

(fact (VAR ...) TERM ...), this is syntactic sugar for (relation (VAR ...) (to-show TERM ...) succeed). - -

(extend-relation (id ...) rel ...), this relation will simply try each +

+

relation (ANNOT-VAR ...) (to-show TERM ...) [GL] +where ANNOT-VAR is either a simple VAR or (once VAR) where ’once’ is a distingushed symbol. The latter form introduces a once-var, aka linear variable. A linear variable appears only once in TERM ... and only at the top level (that is, one and only one TERM in the to-show pattern contains ONCE-VAR, and that term is ONCE-VAR itself). In addition, ONCE-VAR must appear at most once in the body GL. (Of course, then ONCE-VAR could be _, instead.) If these conditions are satisfied, we can replace a logical variable ONCE-VAR with a regular Scheme variable. +

+

(fact (VAR ...) TERM ...), this is syntactic sugar for (relation (VAR ...) (to-show TERM ...) succeed). +

+

(extend-relation (id ...) rel ...), this relation will simply try each sub relation rel one at a time acording to any calling them with arguments (id ...) which is the arguments of the resulting relation. - -

Example: - +

+

Example: +

(extend-relation (a1 a2)
    (fact () 'sam 'rob)
    (fact () 'roz 'sue)
    (fact () 'rob 'sal))
 
- -

Here a1 and a2 will be tried with one fact after the other until a match is found. At backtracking this process will continue untill another match is found. - -

(extend-relation-with-recur-limit limit (id ...) rel ...), this is the same as the previous term, but the resulting relation cannot be called recursively more then limit times. - -

(lift-to-relations (id ...) (g rel ...)), This will generate a -combination of the relation rel ... according to g and with the argument +

Here a1 and a2 will be tried with one fact after the other until a match is found. At backtracking this process will continue untill another match is found. +

+

(extend-relation-with-recur-limit limit (id ...) rel ...), this is the same as the previous term, but the resulting relation cannot be called recursively more then limit times. +

+

(lift-to-relations (id ...) (g rel ...)), This will generate a +combination of the relation rel ... according to g and with the argument variables id .... E.g. - -

Example: - +

+

Example: +

(lift-to-relations (a1 b1) 
   (any  (fact () 'sam 'rob)
         (fact () 'roz 'sue)
         (fact () 'rob 'sal)))
 
+

Is equivalent to the previous example in the section for extend-relation. +

+

(intersect-relation (id ...) rel ...), This is the same as extend-relation, but it will use all in stead of any. +

-

Is equivalent to the previous example in the section for extend-relation. -

(intersect-relation (id ...) rel ...), This is the same as extend-relation, but it will use all in stead of any. - -

(let-gls (id ...) ((name rel) ...) code), this will create a new realation with arguments id ... and in that create a set af relations names name ... representing rel ... and the names are used in code. +

(let-gls (id ...) ((name rel) ...) code), this will create a new realation with arguments id ... and in that create a set af relations names name ... representing rel ... and the names are used in code. +

+

12.3 Queries

-

-query (redo-k subst id ...) A SE ...) -> result or '(), The low level macro 'query' runs the goal A in the empty initial substitution, and reifies the resulting answer: the substitution and the redo-continuation bound to fresh variables with the names supplied by the user e.g. redo-k and subst. The substitution and the redo continuation can then be used by Scheme expressions SE ... Before running the goal, the macro creates logical variables id ... for use in A and SE ... If the goal fails, '() is returned and SE ... are not evaluated. Note the similarity with shift/reset-based programming where the immediate return signifies "failure" and the invocation of the continuation a "success" Returning '() on failure makes it easy to create the list of answers. - -

(solve n (v ...) g ...), This will create fresh new variables v ... and solve (all g ...). It will output a list of solution which depends on the value of n. If this is equal to * then all solutions will be included. Else if n is a number at must that number of solutions will be publishied in the list. - -

(solution (v ...) g ..., This is the same as (solve 1 (v ...) g ...). - + + + + +

query (redo-k subst id ...) A SE ...) -> result or '(), The low level macro ’query’ runs the goal A in the empty initial substitution, and reifies the resulting answer: the substitution and the redo-continuation bound to fresh variables with the names supplied by the user e.g. redo-k and subst. The substitution and the redo continuation can then be used by Scheme expressions SE ... Before running the goal, the macro creates logical variables id ... for use in A and SE ... If the goal fails, ’() is returned and SE ... are not evaluated. Note the similarity with shift/reset-based programming where the immediate return signifies "failure" and the invocation of the continuation a "success" Returning ’() on failure makes it easy to create the list of answers. +

+

(solve n (v ...) g ...), This will create fresh new variables v ... and solve (all g ...). It will output a list of solution which depends on the value of n. If this is equal to * then all solutions will be included. Else if n is a number at must that number of solutions will be publishied in the list. +

+

(solution (v ...) g ..., This is the same as (solve 1 (v ...) g ...). +

+

12.4 Misc

- -

-(trace-vars title (var ...)), Will print out a trace expression for var .... - -

partially-eval-sgl, not implemented, because guile-log is also directed towards stacks and assq lists and hence usually uses another kind of implementation for the interleaving constructs. - + + + +

(trace-vars title (var ...)), Will print out a trace expression for var .... +

+

partially-eval-sgl, not implemented, because guile-log is also directed towards stacks and assq lists and hence usually uses another kind of implementation for the interleaving constructs. +

+

12.5 Examples

-
Example 1, any-union,
 (let* ((fact1 (fact () 'x1 'y1))
        (fact2 (fact () 'x2 'y2)) 
@@ -180,12 +240,19 @@ variables id .... E.g.
     
     (solve 10 (x y)
            (any-union (R1 x y) (R2 x y))))
-=>    '((x1 y1) (x2 y2) (x3 y3)))
+=>    '((x1 y1) (x2 y2) (x3 y3)))
 
 Note how R1 and R2 first both bind x and y to the same values in their first 
 match and how any-union avoid duplicate the results. This works independent of 
 the orders of fact1 and fact2 etc in the definitions of R1 and R2.
 
+
+
+

+Next: , Previous: , Up: Top   [Index]

+
+ - + + diff --git a/doc/guile-log/parser-combinators.html b/doc/guile-log/parser-combinators.html index 32e49a130866d2762e67eb1fcd1727f27609f278..8b58125cc871e776103a08fe55eadc6d1702b72c 100644 --- a/doc/guile-log/parser-combinators.html +++ b/doc/guile-log/parser-combinators.html @@ -1,114 +1,186 @@ - + + + + -parser combinators - Preliminary Manual - - - - - - - - +Preliminary Manual: parser combinators + + + + + + + + + + + + + +a.summary-letter {text-decoration: none} +blockquote.smallquotation {font-size: smaller} +div.display {margin-left: 3.2em} +div.example {margin-left: 3.2em} +div.indentedblock {margin-left: 3.2em} +div.lisp {margin-left: 3.2em} +div.smalldisplay {margin-left: 3.2em} +div.smallexample {margin-left: 3.2em} +div.smallindentedblock {margin-left: 3.2em; font-size: smaller} +div.smalllisp {margin-left: 3.2em} +kbd {font-style:oblique} +pre.display {font-family: inherit} +pre.format {font-family: inherit} +pre.menu-comment {font-family: serif} +pre.menu-preformatted {font-family: serif} +pre.smalldisplay {font-family: inherit; font-size: smaller} +pre.smallexample {font-size: smaller} +pre.smallformat {font-family: inherit; font-size: smaller} +pre.smalllisp {font-size: smaller} +span.nocodebreak {white-space:nowrap} +span.nolinebreak {white-space:nowrap} +span.roman {font-family:serif; font-weight:normal} +span.sansserif {font-family:sans-serif; font-weight:normal} +ul.no-bullet {list-style: none} +--> + + + - -
+ + +

-Next: , -Previous: stream ideom, -Up: parsing -


+Next: , Previous: , Up: parsing   [Index]

- +
+

10.2 Parser Combinators

-

The combinators are basic elements that you get from the module (logic guile-log parser). To note here is with these we define elements to do parsing in a “functional” way together with som utilities to memoize sections and produce tokens. Tokens are more interned scheme data then the standard way of matching that is lightweight and just represent sequences of the incoming chars. They are also cheap to backtrack over but will put a demand on the supply of prolog variables. - +

+

10.2.1 higher order elements,

- -

In the arguments to the combinators below a string will be automatically converted to (f-tag "string"). - -

(f-and f ...), higher order function, matches if all f ... matches and returns the values from the last one. Similarly and! only successes ones and for and!! all f ... only sucesses once. - -

(f-or f ...), higher order funciton, matches if at least one of f ... matches, similarly f-or! matches only once. - -

(f-seq f ...), higher order function. Matches if f ... macthes in sequence. Similarly f-seq! only matches once and for f-seq!! each f only matches once. - -

(f-not f), higher order function. matches one char if not f maches. Similarly f-not! stores and returns the matched character in the match standard way of storing data and f-not-pr prints the character on standard output. - -

(f-not* f), this will not consume any characters and fail if f is true. - -

(f* f), higher order function, matches f 0 or more times. - -

(f+ f), higher order function, matches f 1 or more times. - -

(fn f n m), matches f n to m times - +

In the arguments to the combinators below a string will be automatically converted to (f-tag "string"). +

+ + + +

(f-and f ...), higher order function, matches if all f ... matches and returns the values from the last one. Similarly and! only successes ones and for and!! all f ... only sucesses once. +

+ + +

(f-or f ...), higher order funciton, matches if at least one of f ... matches, similarly f-or! matches only once. +

+ + + +

(f-seq f ...), higher order function. Matches if f ... macthes in sequence. Similarly f-seq! only matches once and for f-seq!! each f only matches once. +

+ + + + +

(f-not f), higher order function. matches one char if not f maches. Similarly f-not! stores and returns the matched character in the match standard way of storing data and f-not-pr prints the character on standard output. +

+

(f-not* f), this will not consume any characters and fail if f is true. +

+ +

(f* f), higher order function, matches f 0 or more times. +

+ +

(f+ f), higher order function, matches f 1 or more times. +

+ +

(fn f n m), matches f n to m times +

+

10.2.2 Basic parser functions

- -

(f-tag str), produces a matcher of the tag str. f-tag! stores that match the standard way and f-tag-pr prints the match on standard output. - -

(f-reg char-regexp), produces a matcher that will macth one char according to char-regexp. Similarly we have f-reg! to store the standard way and - -

f-true, f-false macthers that represt a successful match and a failed match. These are mute constructs and does not consume any data. - -

f-eof, matches end of file. + + + + +

(f-tag str), produces a matcher of the tag str. f-tag! stores that match the standard way and f-tag-pr prints the match on standard output. +

+ + + +

(f-reg char-regexp), produces a matcher that will macth one char according to char-regexp. Similarly we have f-reg! to store the standard way and +

+ + +

f-true, f-false macthers that represt a successful match and a failed match. These are mute constructs and does not consume any data. +

+ + + + +

f-eof, matches end of file. f-nl, do not use newlines with e.g. f-reg, it will not work use this in stead to match a newline. There is also f-nl! and f-nl-pr versions. - -

tok-ws*, tok-ws+, this is an non token generator token e.g. it returns the input state of the out stream. But it does tokenizing by issuing a freeze so it memoizes and will not reparse whitespace. the * version is for 0 or more whitespaces and + for one or more whitespaces. A whitespace is here defined as 'space' 'tab' and 'newline'. - +

+ + +

tok-ws*, tok-ws+, this is an non token generator token e.g. it returns the input state of the out stream. But it does tokenizing by issuing a freeze so it memoizes and will not reparse whitespace. the * version is for 0 or more whitespaces and + for one or more whitespaces. A whitespace is here defined as ’space’ ’tab’ and ’newline’. +

+

10.2.3 constructor combinators,

- -

The argument to these functions will auto output keyword arguments e.g. it does an automatic (f-out #:keyword) in the place. - -

-(f-cons f1 f2), as (f-seq f1 f2), but the output is consed. - -

(f-list f ...), as (f-seq f ...), but the outut is combined in a list. - -

(f-cons* f ...), similarly as f-list above. - -

(f-out tag), will produce a matcher that conses tag +

The argument to these functions will auto output keyword arguments e.g. it does an automatic (f-out #:keyword) in the place. +

+ + + + + + + + + +

(f-cons f1 f2), as (f-seq f1 f2), but the output is consed. +

+

(f-list f ...), as (f-seq f ...), but the outut is combined in a list. +

+

(f-cons* f ...), similarly as f-list above. +

+

(f-out tag), will produce a matcher that conses tag to the output at the end of a matching. - -

(ff* f), as (f* f), but makes a list of the output. - -

(ff* f tag), as aboove but prepends the list with tag. - -

(ff+ f), (ff+ f tag), as for ff* above but matches one or more elements. - -

(ff? f), Matches one or if zero matches outputs #f. +

+

(ff* f), as (f* f), but makes a list of the output. +

+

(ff* f tag), as aboove but prepends the list with tag. +

+

(ff+ f), (ff+ f tag), as for ff* above but matches one or more elements. +

+

(ff? f), Matches one or if zero matches outputs #f. (ff? f default), Matches one or if zero matches outputs default. +

+

10.2.4 utilities

- -

(p-freeze tok f mk) This will freeze the interpretation of the comming characters according to the parser function f as token tok. Using backtracking, one can get into the unfourtunate stage of reparsing things over and over again. WIth p-freeze we will memoize the reseult and the second time we try to parse the token at the same position we will just use the memoized data. this is how we tokenize and gives the guile-log parsing system a slower tokenizer on one hand, then traditional tokenizers, but on the other hand allows far more advanced tokens to be builed e.g. tokenize a parenthesied expression in C. mk is a function whos purpose is to construct that value that should be memoized it has the signature - -

(mk s in-value out-value), where s is state value neede to tarnslate any prolog variables, in-value is the value that get's into the resulting parser function, and out-value is the value out of the parser function f above. typical uses are (define (mk s cin cout) cout). - -

(mk-token f), this is the lower level tokenizer that just produces a string token out of the all the matched characters by the parser function f. - -

(Ds f), will delay the evaluation of the parser matcher f. This function is needed in recursive definitions in order to avoid infinite recursion. - -

(parse f) + +

(p-freeze tok f mk) This will freeze the interpretation of the comming characters according to the parser function f as token tok. Using backtracking, one can get into the unfourtunate stage of reparsing things over and over again. WIth p-freeze we will memoize the reseult and the second time we try to parse the token at the same position we will just use the memoized data. this is how we tokenize and gives the guile-log parsing system a slower tokenizer on one hand, then traditional tokenizers, but on the other hand allows far more advanced tokens to be builed e.g. tokenize a parenthesied expression in C. mk is a function whos purpose is to construct that value that should be memoized it has the signature +

+

(mk s in-value out-value), where s is state value neede to tarnslate any prolog variables, in-value is the value that get’s into the resulting parser function, and out-value is the value out of the parser function f above. typical uses are (define (mk s cin cout) cout). +

+ +

(mk-token f), this is the lower level tokenizer that just produces a string token out of the all the matched characters by the parser function f. +

+ +

(Ds f), will delay the evaluation of the parser matcher f. This function is needed in recursive definitions in order to avoid infinite recursion. +

+ +

(parse f) (parse string f) -The first version will read from standard input and produce an output as +The first version will read from standard input and produce an output as returned by the parser function f. We may also in the second version use a string as input to the parser as per convinience. +

+
+
+

+Next: , Previous: , Up: parsing   [Index]

+
+ - + + diff --git a/doc/guile-log/parsing.html b/doc/guile-log/parsing.html index e9754025bd17ec9edb01ed5e3167c5612c8c632f..9c885aaaa445ebad3bf51aaf8de728d35b8cc60b 100644 --- a/doc/guile-log/parsing.html +++ b/doc/guile-log/parsing.html @@ -1,72 +1,104 @@ - + + + + -parsing - Preliminary Manual - - - - - - - +Preliminary Manual: parsing + + + + + + + + + + + + + +a.summary-letter {text-decoration: none} +blockquote.smallquotation {font-size: smaller} +div.display {margin-left: 3.2em} +div.example {margin-left: 3.2em} +div.indentedblock {margin-left: 3.2em} +div.lisp {margin-left: 3.2em} +div.smalldisplay {margin-left: 3.2em} +div.smallexample {margin-left: 3.2em} +div.smallindentedblock {margin-left: 3.2em; font-size: smaller} +div.smalllisp {margin-left: 3.2em} +kbd {font-style:oblique} +pre.display {font-family: inherit} +pre.format {font-family: inherit} +pre.menu-comment {font-family: serif} +pre.menu-preformatted {font-family: serif} +pre.smalldisplay {font-family: inherit; font-size: smaller} +pre.smallexample {font-size: smaller} +pre.smallformat {font-family: inherit; font-size: smaller} +pre.smalllisp {font-size: smaller} +span.nocodebreak {white-space:nowrap} +span.nolinebreak {white-space:nowrap} +span.roman {font-family:serif; font-weight:normal} +span.sansserif {font-family:sans-serif; font-weight:normal} +ul.no-bullet {list-style: none} +--> + + + - -
+ + +

-Next: , -Previous: attributes, -Up: Top -


+Next: , Previous: , Up: Top   [Index]

- +
+

10 Parsing

- -

Prolog has historically been used for setting up parsers for various languages and has an extensible expression parser where one congigure the operator handling. We continue in this tradition to produce elements to do backtracking enabled parsing for guile. With this, one can explore the new interesting constructs in guile-log to enable new features with respect to parsing. - -

Generally in guile-log a parser is a function that follows a certain call semantics. It is a guile log function e.g. it takes the standard arguments S P CC. But ontop of this it takes X XL N M e.g. current char on line (X), current line in stream of lines (XL), current line column (N) and current line number (M). Typically in code these elements are hidden in return values as calling signatures and hence the resulting code is less littered with standard ideoms and tons of variables. This design allows the programmer to easier spot errors and also produce fewer of them and we belive that it is a boon for productivity when writing parsers. Ontop of this semantics an extra output stream field in both imputt and output may be supplied e.g. the tool needed to produce a syntax tree. Code look typically like this, when using this tool to produce a parser function - -

(<p-lambda> (c)
+

Prolog has historically been used for setting up parsers for various languages and has an extensible expression parser where one congigure the operator handling. We continue in this tradition to produce elements to do backtracking enabled parsing for guile. With this, one can explore the new interesting constructs in guile-log to enable new features with respect to parsing. +

+

Generally in guile-log a parser is a function that follows a certain call semantics. It is a guile log function e.g. it takes the standard arguments S P CC. But ontop of this it takes X XL N M e.g. current char on line (X), current line in stream of lines (XL), current line column (N) and current line number (M). Typically in code these elements are hidden in return values as calling signatures and hence the resulting code is less littered with standard ideoms and tons of variables. This design allows the programmer to easier spot errors and also produce fewer of them and we belive that it is a boon for productivity when writing parsers. Ontop of this semantics an extra output stream field in both imputt and output may be supplied e.g. the tool needed to produce a syntax tree. Code look typically like this, when using this tool to produce a parser function +

+
(<p-lambda> (c)
   (.. (c) (ws c))                                    ;; Match whitespace
-  (<let> ((n N) (m M))                               ;; store M and N
+  (<let> ((n N) (m M))                               ;; store M and N
     (.. (c) (exponent c))                            ;; The actual number
     (.. (q) (ws c))                                  ;; Match whitespace
-    (<p-cc> `(#:number ,(string->number c) ,n ,m)))) ;; Ret value
-
- -

We see that we use <p-lambda> in stead of <lambda>. '..' is a special <values> form that has the effect to rebind X,XL,N,M to the new returned values. We also see the technique to bind e.g. N,M to different values. this code would look like this if we did use pure guile-log. - -

(<lambda> (x xl n m c)
-  (<values> (x xl nn mm c) (ws x xl n m c))
-  (<values> (x xl n m c) (exponent x xl nn mm c))
-  (<values> (x xl n m q) (ws x xl n m c))
-  (<cc> x xl n m `(#:number ,(string->number c) ,nn ,mm))))
+    (<p-cc> `(#:number ,(string->number c) ,n ,m)))) ;; Ret value
 
-Not nice on the eye's right. Anyway a bonus point is that we have a framework to create stream like translaters like parsing this through a little macrology and hence it is a 'notime' thingie to change the call idioms. This is the power of guile in action. Ontop of this we build parser combinators which is a functional kanren influenced way of combining parser functions. If we have parser functions f,g we would like to combine them into new parser functions, there are typical ideoms suitable for all translators of sequences e.g. combinators that can be employed e.g. (f-and f g) that successes if both does and outputs the last translation into the value stream. Se the combinators subsection to find out more. +

We see that we use <p-lambda> in stead of <lambda>. ’..’ is a special <values> form that has the effect to rebind X,XL,N,M to the new returned values. We also see the technique to bind e.g. N,M to different values. this code would look like this if we did use pure guile-log. +

+
(<lambda> (x xl n m c)
+  (<values> (x xl nn mm c) (ws x xl n m c))
+  (<values> (x xl n m c) (exponent x xl nn mm c))
+  (<values> (x xl n m q) (ws x xl n m c))
+  (<cc> x xl n m `(#:number ,(string->number c) ,nn ,mm))))
+

Not nice on the eye’s right. Anyway a bonus point is that we have a framework to create stream like translaters like parsing this through a little macrology and hence it is a ’notime’ thingie to change the call idioms. This is the power of guile in action. Ontop of this we build parser combinators which is a functional kanren influenced way of combining parser functions. If we have parser functions f,g we would like to combine them into new parser functions, there are typical ideoms suitable for all translators of sequences e.g. combinators that can be employed e.g. (f-and f g) that successes if both does and outputs the last translation into the value stream. Se the combinators subsection to find out more. +

+

The parsing lib is structured in subnodes according to, +

+ + + + + + -

The parsing lib is structured in subnodes according to, +


+
+

+Next: , Previous: , Up: Top   [Index]

+
- - + + diff --git a/doc/guile-log/postpone.html b/doc/guile-log/postpone.html index 979edbdb9bfe28c1351d3590e5695f3692e4db51..168abead2ca7a5c40295b2674d7541a487e77d40 100644 --- a/doc/guile-log/postpone.html +++ b/doc/guile-log/postpone.html @@ -1,52 +1,83 @@ - + + + + -postpone - Preliminary Manual - - - - - - - +Preliminary Manual: postpone + + + + + + + + + + + + + +a.summary-letter {text-decoration: none} +blockquote.smallquotation {font-size: smaller} +div.display {margin-left: 3.2em} +div.example {margin-left: 3.2em} +div.indentedblock {margin-left: 3.2em} +div.lisp {margin-left: 3.2em} +div.smalldisplay {margin-left: 3.2em} +div.smallexample {margin-left: 3.2em} +div.smallindentedblock {margin-left: 3.2em; font-size: smaller} +div.smalllisp {margin-left: 3.2em} +kbd {font-style:oblique} +pre.display {font-family: inherit} +pre.format {font-family: inherit} +pre.menu-comment {font-family: serif} +pre.menu-preformatted {font-family: serif} +pre.smalldisplay {font-family: inherit; font-size: smaller} +pre.smallexample {font-size: smaller} +pre.smallformat {font-family: inherit; font-size: smaller} +pre.smalllisp {font-size: smaller} +span.nocodebreak {white-space:nowrap} +span.nolinebreak {white-space:nowrap} +span.roman {font-family:serif; font-weight:normal} +span.sansserif {font-family:sans-serif; font-weight:normal} +ul.no-bullet {list-style: none} +--> + + + - -
+ + +

-Next: , -Previous: acumulators/generators, -Up: Top -


+Next: , Previous: , Up: Top   [Index]

- +
+

4 Postpone, a framework for postponing guile-log evaluations.

- -

This code is available from (logic guile-log postpone) You may have noticed that guile log is a framework to do tree searches to meet a certain criteria and during the path in the tree create data structures that are able to undo and also redo it's state. Most people when approaching this will sooner or later be bitten by the NP hardness of many interesting problems. The solution might then be to try intelligent guesses in which branch the gold is hiding. What one would like to do is try a set of branches, freeze the different states and at that point create some sort of index that represent the likelihood of the gold lying buried beneath. Then an overall global decision can be taken and only the most promising paths will be further examined. It is for this use case the following system is constructed. Postpone mix well with the rest of prolog, but especially the <zip>, forms might behave unexpectedly due to teh postpone mechansim interfering with the synch and produce bad result. - +

This code is available from (logic guile-log postpone) You may have noticed that guile log is a framework to do tree searches to meet a certain criteria and during the path in the tree create data structures that are able to undo and also redo it’s state. Most people when approaching this will sooner or later be bitten by the NP hardness of many interesting problems. The solution might then be to try intelligent guesses in which branch the gold is hiding. What one would like to do is try a set of branches, freeze the different states and at that point create some sort of index that represent the likelihood of the gold lying buried beneath. Then an overall global decision can be taken and only the most promising paths will be further examined. It is for this use case the following system is constructed. Postpone mix well with the rest of prolog, but especially the <zip>, forms might behave unexpectedly due to teh postpone mechansim interfering with the synch and produce bad result. +

+

4.1 Api.

+ + -

G.L. (postpone val power)
 G.L. (postpone-frame limit fact maxsize)
-
-To be able to postpone we must have a baseline from which we will base our restarts e.g. postpone-frame. The postpone command will basically evaluate val and postpone if it's larger then a certain limit that is governed by an initial value limit and fact - a factor that adds to the limit each postpone turn. The power is the sorting index used to manage a list of possible restarts for and this list is sorted so that we at restarts will try to use maxsize first elements of the list. The list is never larger then 10 * maxsize. +

To be able to postpone we must have a baseline from which we will base our restarts e.g. postpone-frame. The postpone command will basically evaluate val and postpone if it’s larger then a certain limit that is governed by an initial value limit and fact - a factor that adds to the limit each postpone turn. The power is the sorting index used to manage a list of possible restarts for and this list is sorted so that we at restarts will try to use maxsize first elements of the list. The list is never larger then 10 * maxsize. +

+

Make sure to use positive values for the power, value. If all postponing functions leave a negative value, then postpone-frame will fail. This is useful in tabling where this teqnicque is used to produce all possible solutions (recursive application as well) for a given input until a fixpoint with no more new solutions are reached. +

+
+
+

+Next: , Previous: , Up: Top   [Index]

+
-

Make sure to use positive values for the power, value. If all postponing functions leave a negative value, then postpone-frame will fail. This is useful in tabling where this teqnicque is used to produce all possible solutions (recursive application as well) for a given input until a fixpoint with no more new solutions are reached. - + + diff --git a/doc/guile-log/prolog.html b/doc/guile-log/prolog.html index 8c53da6afe3da191a0fa24c4abd5ae151c07d99e..574eadf0c8ece1a3bed05a22dff3ea8243da5dc7 100644 --- a/doc/guile-log/prolog.html +++ b/doc/guile-log/prolog.html @@ -1,56 +1,97 @@ - + + + + -prolog - Preliminary Manual - - - - - - - +Preliminary Manual: prolog + + + + + + + + + + + + + +a.summary-letter {text-decoration: none} +blockquote.smallquotation {font-size: smaller} +div.display {margin-left: 3.2em} +div.example {margin-left: 3.2em} +div.indentedblock {margin-left: 3.2em} +div.lisp {margin-left: 3.2em} +div.smalldisplay {margin-left: 3.2em} +div.smallexample {margin-left: 3.2em} +div.smallindentedblock {margin-left: 3.2em; font-size: smaller} +div.smalllisp {margin-left: 3.2em} +kbd {font-style:oblique} +pre.display {font-family: inherit} +pre.format {font-family: inherit} +pre.menu-comment {font-family: serif} +pre.menu-preformatted {font-family: serif} +pre.smalldisplay {font-family: inherit; font-size: smaller} +pre.smallexample {font-size: smaller} +pre.smallformat {font-family: inherit; font-size: smaller} +pre.smalllisp {font-size: smaller} +span.nocodebreak {white-space:nowrap} +span.nolinebreak {white-space:nowrap} +span.roman {font-family:serif; font-weight:normal} +span.sansserif {font-family:sans-serif; font-weight:normal} +ul.no-bullet {list-style: none} +--> + + + - -

+ + +

-Next: , -Previous: kanren, -Up: Top -


+Next: , Previous: , Up: Top   [Index]

- +
+

13 Prolog

-

Guile log also sports an iso-prolog interface as a logic programming interface besides kanren. The interface is pretty complete at this point appart a few points that have not yet been resolved but sure it is currently alpha software and help is very very much appriciated. With this most programs written in iso prolog should probably work. The intention is to enhance this interface so that the bulk of already written prolog programs should be able to run on guile. We will also add the fetures unique to guile-log and hence enhance the prolog experience. Featurewise guile-log prolog is taking over many properties of scheme like closures, continuations, delimeted continuations, the interleaving constructs of kanren and a delicate system to treat dynamic objects like dynamic functions, dynamic hashes and a library to tell how you want the dynamism to work at a fine grained level. +

+ + + + + + + + + + + + + + +
+
+

+Next: , Previous: , Up: Top   [Index]

+
+ - - - + + diff --git a/doc/guile-log/sed_002fgrep.html b/doc/guile-log/sed_002fgrep.html index e92c11cb182442912a80ba2d6a2a823cb3eed988..744a7b7723d7c5f6a76ad0d912b7495d819f10ca 100644 --- a/doc/guile-log/sed_002fgrep.html +++ b/doc/guile-log/sed_002fgrep.html @@ -1,88 +1,109 @@ - + + + + -sed/grep - Preliminary Manual - - - - - - - +Preliminary Manual: sed/grep + + + + + + + + + + + + + +a.summary-letter {text-decoration: none} +blockquote.smallquotation {font-size: smaller} +div.display {margin-left: 3.2em} +div.example {margin-left: 3.2em} +div.indentedblock {margin-left: 3.2em} +div.lisp {margin-left: 3.2em} +div.smalldisplay {margin-left: 3.2em} +div.smallexample {margin-left: 3.2em} +div.smallindentedblock {margin-left: 3.2em; font-size: smaller} +div.smalllisp {margin-left: 3.2em} +kbd {font-style:oblique} +pre.display {font-family: inherit} +pre.format {font-family: inherit} +pre.menu-comment {font-family: serif} +pre.menu-preformatted {font-family: serif} +pre.smalldisplay {font-family: inherit; font-size: smaller} +pre.smallexample {font-size: smaller} +pre.smallformat {font-family: inherit; font-size: smaller} +pre.smalllisp {font-size: smaller} +span.nocodebreak {white-space:nowrap} +span.nolinebreak {white-space:nowrap} +span.roman {font-family:serif; font-weight:normal} +span.sansserif {font-family:sans-serif; font-weight:normal} +ul.no-bullet {list-style: none} +--> + + + - -
- + + +

-Next: , -Previous: parsing, -Up: Top -


+Next: , Previous: , Up: Top   [Index]

- +
+

11 Sed/grep overview

-

To overengineer and test out the framework a simple grep and sed utility has been designed. It knows about scheme and can locate and translate scheme files as well as having traditional grep/sed funcitonality. The main interface is in the module (logic guile-log grep). - +

+

11.1 Api

-

(grep match code #:key (a 0) (b 0) (c 0)), this will evaluate code in a separate thread and capture standard output and only print what the parser function match matches. a,b,c defines an interval [min(-b,-c),max(a,c)] around the matched line which is printed. - -

(sed match code), will print everything but if match matches, it's output will be printed instead by the matcher, e.g. use the pr versions of the parser combinators for printing matches. - -

(par-grep match code #:key (str q-false) (com q-false) (a 0) (b 0) (c 0)), This is a grep funciton that knows about scheme, it works as before but will print the sexp or part of sexp that is matching. The extra fields are, str, the matcher used inside strings, com, the matcher used in comments, and d prints the lines containing the d level enclosing sexp. - -

(par-sed match code #:key (str q-false) (com q-false)), This is a sed utility that knows about scheme. - +

+

(sed match code), will print everything but if match matches, it’s output will be printed instead by the matcher, e.g. use the pr versions of the parser combinators for printing matches. +

+

(par-grep match code #:key (str q-false) (com q-false) (a 0) (b 0) (c 0)), This is a grep funciton that knows about scheme, it works as before but will print the sexp or part of sexp that is matching. The extra fields are, str, the matcher used inside strings, com, the matcher used in comments, and d prints the lines containing the d level enclosing sexp. +

+

(par-sed match code #:key (str q-false) (com q-false)), This is a sed utility that knows about scheme. +

+

11.2 The scheme matcher.

- -

In order to translate scheme code we have a nice little monster framework to to the grunt work. You may use it by importing (logic guile-log parsing sch-match). +

In order to translate scheme code we have a nice little monster framework to to the grunt work. You may use it by importing (logic guile-log parsing sch-match). To use this one need to know about how syntax-parse works. We only support a subset of the syntax-parse interface, namlely the directives ~and ~or ~not ~var _) added to this we make use of ice-9 match notation for symbols. - -

To define a match abstraction use, - -

(define-match-class [nm | (nm . args)] (pattern pat l ...) ...), -just use this as with define-syntax-class, but with the exception that you will build and match according to some whitespace rules stated below. - -

(define-splicing-match-class [nm | (nm . args)] (pattern pat l ...) ...), +

+

To define a match abstraction use, +

+

(define-match-class [nm | (nm . args)] (pattern pat l ...) ...), +just use this as with define-syntax-class, but with the exception that you will build and match according to some whitespace rules stated below. +

+

(define-splicing-match-class [nm | (nm . args)] (pattern pat l ...) ...), This works just as with define-splicing-syntax-class in syntax-parse, but again with some extra twarts. - -

The actual matchers are, - -

(scm-sed (pat res ...) ...), this works just as with syntax-parse, but with the extra build-rules. - -

(scm-match pat), use this as a matcher in par-grep, but with the syntax-parse pattern interface to define a match. - +

+

The actual matchers are, +

+

(scm-sed (pat res ...) ...), this works just as with syntax-parse, but with the extra build-rules. +

+

(scm-match pat), use this as a matcher in par-grep, but with the syntax-parse pattern interface to define a match. +

+

11.3 Building the result.

-

The philosophy is to treat the sed translation as a special syntax transform. A variable x in the pattern will produce three sub matches, x.l,x.it.x.r. e.g. left whitespace, sexp, right whitespace. By matching #(l it r) l will be left whitespace, it the sexp and r the right whitespace, and this is how you define the output as well in order to surround an element with whitespace. - +

+

11.4 Example

-

This is an example how one may define a sed translator that swaps the meaning of variable and value in a let form and preserving whitespace as much as possible. - +

(define-match-class swap
   (pattern #(l (x y) r) 
      #:with tr #'#(l (x.l y.it x.r y.l x.it y.r) r)))
 
 (define-match-class (tr-it oldval newval)
   (pattern #(l ,oldval r)
-     #:with tr #`#(l #,(datum->syntax #'a newval) r)))
+     #:with tr #`#(l #,(datum->syntax #'a newval) r)))
 
 (define (test f)
   (par-sed (scm-sed (#(l ((~var let (tr-it 'let 'tel))
@@ -91,6 +112,13 @@ This works just as with define-splicing-syntax-class in syntax-pars
 		     #'#(l (let.tr #(a (bind.tr ...) b) body ...) r)))
       (f)))
 
+
+
+

+Next: , Previous: , Up: Top   [Index]

+
+ - + + diff --git a/doc/guile-log/stream-ideom.html b/doc/guile-log/stream-ideom.html index 3588ee8658d7a702d444e0e94794d8102857097d..607e5ba9999e98b6ef7085584312500c78613636 100644 --- a/doc/guile-log/stream-ideom.html +++ b/doc/guile-log/stream-ideom.html @@ -1,64 +1,90 @@ - + + + + -stream ideom - Preliminary Manual - - - - - - - +Preliminary Manual: stream ideom + + + + + + + + + + + + + +a.summary-letter {text-decoration: none} +blockquote.smallquotation {font-size: smaller} +div.display {margin-left: 3.2em} +div.example {margin-left: 3.2em} +div.indentedblock {margin-left: 3.2em} +div.lisp {margin-left: 3.2em} +div.smalldisplay {margin-left: 3.2em} +div.smallexample {margin-left: 3.2em} +div.smallindentedblock {margin-left: 3.2em; font-size: smaller} +div.smalllisp {margin-left: 3.2em} +kbd {font-style:oblique} +pre.display {font-family: inherit} +pre.format {font-family: inherit} +pre.menu-comment {font-family: serif} +pre.menu-preformatted {font-family: serif} +pre.smalldisplay {font-family: inherit; font-size: smaller} +pre.smallexample {font-size: smaller} +pre.smallformat {font-family: inherit; font-size: smaller} +pre.smalllisp {font-size: smaller} +span.nocodebreak {white-space:nowrap} +span.nolinebreak {white-space:nowrap} +span.roman {font-family:serif; font-weight:normal} +span.sansserif {font-family:sans-serif; font-weight:normal} +ul.no-bullet {list-style: none} +--> + + + - -
+ + +

-Next: , -Up: parsing -


+Next: , Up: parsing   [Index]

- +
+

10.1 Stream ideom api

- -

There is a little framework in guile-log imported with (logic guile-log) that enables the setup of syntactic sugar for streams. The api is - -

SCM: (define-guile-log-parser-tool (lam (X ...)) def oo xx cc) - -

lam will be the name of the new lambda object that can be used to produce a matcher. X ... will be the name of the syntax parameters and also define the standard positions for them in call and return. def is the corresponding define. To do an actual match in guile-log with parser function call one need to use oo and when one issues a whole new expression we use xx. To return values from the matcher we use cc. The use of oo is twofold. First -G.L (oo (v ...) (f a ..)), does a call in nontail possition. + +

There is a little framework in guile-log imported with (logic guile-log) that enables the setup of syntactic sugar for streams. The api is +

+

SCM: (define-guile-log-parser-tool (lam (X ...)) def oo xx cc) +

+

lam will be the name of the new lambda object that can be used to produce a matcher. X ... will be the name of the syntax parameters and also define the standard positions for them in call and return. def is the corresponding define. To do an actual match in guile-log with parser function call one need to use oo and when one issues a whole new expression we use xx. To return values from the matcher we use cc. The use of oo is twofold. First +G.L (oo (v ...) (f a ..)), does a call in nontail possition. G.L (oo (f a ..)), does a call in tail position. - -

xx is used to capture the return of a subexpression like in the example below. It cannot be used to call parser funcitons. - +

+

xx is used to capture the return of a subexpression like in the example below. It cannot be used to call parser funcitons. +

+

10.1.1 Example

- -

The parsing framwork is using - -

(define-guile-log-parser-tool (<p-lambda> (X XL N M)) <p-define> .. xx <p-cc>)
+

The parsing framwork is using +

+
(define-guile-log-parser-tool (<p-lambda> (X XL N M)) <p-define> .. xx <p-cc>)
 
- -

An example to use xx is, -

(<p-define> (f c1)
-  (xx (c2) (<or> (.. (g c1)) (.. (h c1))))
-  (<p-cc> `(g-or-h ,c2)))
+

An example to use xx is, +

(<p-define> (f c1)
+  (xx (c2) (<or> (.. (g c1)) (.. (h c1))))
+  (<p-cc> `(g-or-h ,c2)))
 
+

in practice one keeps the numbers of needed uses of all of the above framework by using functional combinators of matchers. But it is practical to just use this framework to e.g. define a c-parser. +

+ -

in practice one keeps the numbers of needed uses of all of the above framework by using functional combinators of matchers. But it is practical to just use this framework to e.g. define a c-parser. - + + diff --git a/doc/guile-log/umatch.html b/doc/guile-log/umatch.html index 0b6b7a7728da8a8439890a6a2e1039389bf7227e..d26c8c98a3a060f4936ed199523d390f49d450ba 100644 --- a/doc/guile-log/umatch.html +++ b/doc/guile-log/umatch.html @@ -1,51 +1,74 @@ - + + + + -umatch - Preliminary Manual - - - - - - - +Preliminary Manual: umatch + + + + + + + + + + + + + +a.summary-letter {text-decoration: none} +blockquote.smallquotation {font-size: smaller} +div.display {margin-left: 3.2em} +div.example {margin-left: 3.2em} +div.indentedblock {margin-left: 3.2em} +div.lisp {margin-left: 3.2em} +div.smalldisplay {margin-left: 3.2em} +div.smallexample {margin-left: 3.2em} +div.smallindentedblock {margin-left: 3.2em; font-size: smaller} +div.smalllisp {margin-left: 3.2em} +kbd {font-style:oblique} +pre.display {font-family: inherit} +pre.format {font-family: inherit} +pre.menu-comment {font-family: serif} +pre.menu-preformatted {font-family: serif} +pre.smalldisplay {font-family: inherit; font-size: smaller} +pre.smallexample {font-size: smaller} +pre.smallformat {font-family: inherit; font-size: smaller} +pre.smalllisp {font-size: smaller} +span.nocodebreak {white-space:nowrap} +span.nolinebreak {white-space:nowrap} +span.roman {font-family:serif; font-weight:normal} +span.sansserif {font-family:sans-serif; font-weight:normal} +ul.no-bullet {list-style: none} +--> + + + - -

+ + +

-Next: , -Previous: Top, -Up: Top -


+Next: , Previous: , Up: Top   [Index]

- +
+

1 Overview

- -

umatch in (logic guile-log umatch) represent the lower level routines +

umatch in (logic guile-log umatch) represent the lower level routines implemented in C code and loaded by that module. A matcher targeted to be used in code handling the unify variables is defined here as well. - +

+

1.1 umatch

+ -

-umatch is a matcher that derives from (ice-9 match) with some extra features that relates to unifying variables. The usage is - -

  (umatch [#:status s] [#:mode *] [#:status #f] [#:tag w] [#:name "anon"] [#:raw #f] (m ...) 
+

umatch is a matcher that derives from (ice-9 match) with some extra features that relates to unifying variables. The usage is +

+
  (umatch [#:status s] [#:mode *] [#:status #f] [#:tag w] [#:name "anon"] [#:raw #f] (m ...) 
      (pat ... code) 
      ...)
    
@@ -56,267 +79,320 @@ umatch is a matcher that derives from (ice-9 match) with some extra features tha
    form ice-9/match plus ',' and the following symbols should not be used in 
    fuctional position: 
 
-      or not cond ... ___ ,@ *** <> arguments $   
-
-',' can be used to quote a variable from the outside of the match - -

(set! s) will define a setter s that can be used in e.g. (<and> (s 1) ...), for <and> refere to guile-log. - -

(get! g) will define a getter g used with an argument representing the current state like e.g. (g S), with S beeing define in the guile-log section. - -

[#:mode +] is used to set the kind of matcher that is initially valid it can be + or not cond ... ___ ,@ *** <> arguments $ +

’,’ can be used to quote a variable from the outside of the match +

+

(set! s) will define a setter s that can be used in e.g. (<and> (s 1) ...), for <and> refere to guile-log. +

+

(get! g) will define a getter g used with an argument representing the current state like e.g. (g S), with S beeing define in the guile-log section. +

+

[#:mode +] is used to set the kind of matcher that is initially valid it can be either of + ++ - * (see below for an explanation of these) - -

[#:tag w], that tag that related to backtracking to the next matcher. e.g. - +

+

[#:tag w], that tag that related to backtracking to the next matcher. e.g. +

  (umatch #:tag next ('(1 2 3))
       ((x y z) (if (number? x) (next) x))
       ((x . l) l))
-  => '(2 3)
+  => '(2 3)
 
- -

[#:name "anon"], this is used when outputting error messages - -

[#:raw #f], do not use this, this + #:mode + is the same as #:mode ++ - -

[#:status #f], This is where the state variable should be it must be a variable +

[#:name "anon"], this is used when outputting error messages +

+

[#:raw #f], do not use this, this + #:mode + is the same as #:mode ++ +

+

[#:status #f], This is where the state variable should be it must be a variable which contains the current state at the entering of the matcher. This syntax symbol is resetted with new state at unifications and similar constructs which may enter new information onto implicit stack or explicit state info. - -

(m ...), is a sequence of elements to be matched in parallel - -

(pat ... code), if pat is a pattern to use to match a m the last form is the code to execute if all patterns matches. - +

+

(m ...), is a sequence of elements to be matched in parallel +

+

(pat ... code), if pat is a pattern to use to match a m the last form is the code to execute if all patterns matches. +

+

1.2 Directives

-

The following feature is added to the ice-9 matchers -

    -
  • (+ p ...) will match (p ...) with the framework + -
  • (+ + p) will match p with the framework + -
+

    +
  • (+ p ...) will match (p ...) with the framework + +
  • (+ + p) will match p with the framework + +
-

The frameworks are, -

  (*  (car    cdr    pair?     null?       equal?        id)))))
+

The frameworks are, +

  (*  (car    cdr    pair?     null?       equal?        id)))))
   (+  (gp-car gp-cdr gp-pair!? gp-null!?   gp-unify!     gp-lookup))
   (++ (gp-car gp-cdr gp-pair!? gp-null!?   gp-unify-raw! gp-lookup))
   (-  (gp-car gp-cdr gp-pair?  gp-null?    gp-m-unify!   gp-lookup))
 
+

Toe explain more, +

    +
  • * : the usual list framework -

    Toe explain more, -

      -
    • * : the usual list framework - -
    • + : (match (+) (1 v) (w 2)) matches and v=2,w=1 +
    • + : (match (+) (1 v) (w 2)) matches and v=2,w=1 with a recurrence check e.g. if any self referenceing will appera in the matcher then the match fails. This is the safe way to do a unifying match. -
    • ++ : (match (++) (1 v) (w 2)) matches and v=2,w=1 without +
    • ++ : (match (++) (1 v) (w 2)) matches and v=2,w=1 without a recurrence check. Do this with care cause cyclisity is unsupportand and can lead to a blowup of the stacks. -
    • - : (match (-) (1 (v = 2)) ((w = 1) 2)) matches unify -variable v = 2 at the start e.g. unify variable is looked up but never bounded. -
    +
  • - : (match (-) (1 (v = 2)) ((w = 1) 2)) matches unify +variable v = 2 at the start e.g. unify variable is looked up but never bounded. +
-

Also unquote directive is used in the matcher to signal an evaluation e.g. in -

  (umatch (x) 
+

Also unquote directive is used in the matcher to signal an evaluation e.g. in +

  (umatch (x) 
     ((a ,(+ z w)) a)) 
      (+ z w)))
-
-(+ z w) will be first evaluated and then used in matching. - +

(+ z w) will be first evaluated and then used in matching. +

+

1.3 low level api

-

in (logic guile-log umatch) a large set of unify constructs are loaded from a library defined in C, this api are, - +

+

1.4 stack banks

- -

The work is done with state objects containing appropriate stacks, rewind information and the assoq list of bindings. You will have the notion of a current 'gp' state that is a fluid representing the current stack in use. Also there is a *current-state* fluid that holds the current assoq binding list/tree. You can create new stacks. The setup can be thread safe in the meaning that if you try to set a logic variable that is not associated to the supplied stack then a binding will be done by logically consing it to a datastructure that has the same functional behavior as an assoq list on the supplied state data and returned. This means that a large class (but certainly not all) of interop issues between multiple threads is solved. A state or stack datastructure will hold information on what thread-id it belongs and also have a unique id. The stack consists of actualy 4 stacks, one control stack (nc) one datastack (ns) and a stack of allocated cons cells (ncs) and one that holds the equivalent of fluids and guards. The control stack will contain unwind information, dynwinds and binding information. The cons stack is not used currently, it can be used to implement closure objects that is created from the stack in stead of the heap, we currently do not use this becuase other overhead is more significant currently e.g. the guile call overhead to C-funcitons. The dynstack is specaial in that its data is recreated at each wind. It represent the expensive winding that essentially originates from the guards and from the equivalent of fluids. Note that multiple reinstation of the other stacks are really cheap in that it does no consing, by allowing e.g. gp-fluid-set! we must pay with copying the stack at each wind, now by separating the small dynstack from the rest we get an important optimization. - -

*gp*, fluid that holds the current gp-stack + + + +

The work is done with state objects containing appropriate stacks, rewind information and the assoq list of bindings. You will have the notion of a current ’gp’ state that is a fluid representing the current stack in use. Also there is a *current-state* fluid that holds the current assoq binding list/tree. You can create new stacks. The setup can be thread safe in the meaning that if you try to set a logic variable that is not associated to the supplied stack then a binding will be done by logically consing it to a datastructure that has the same functional behavior as an assoq list on the supplied state data and returned. This means that a large class (but certainly not all) of interop issues between multiple threads is solved. A state or stack datastructure will hold information on what thread-id it belongs and also have a unique id. The stack consists of actualy 4 stacks, one control stack (nc) one datastack (ns) and a stack of allocated cons cells (ncs) and one that holds the equivalent of fluids and guards. The control stack will contain unwind information, dynwinds and binding information. The cons stack is not used currently, it can be used to implement closure objects that is created from the stack in stead of the heap, we currently do not use this becuase other overhead is more significant currently e.g. the guile call overhead to C-funcitons. The dynstack is specaial in that its data is recreated at each wind. It represent the expensive winding that essentially originates from the guards and from the equivalent of fluids. Note that multiple reinstation of the other stacks are really cheap in that it does no consing, by allowing e.g. gp-fluid-set! we must pay with copying the stack at each wind, now by separating the small dynstack from the rest we get an important optimization. +

+

*gp*, fluid that holds the current gp-stack *current-stack*, fluid that holds the current assoq (gp-make-stack id thread-id nc ns ncs) Allocate a new state datastructure with identity number id, thread identity number thread-id and the sizes of the different stacks. Also it will be stupped so it can be used to unwind to e.g. w can reset the stack to the initial state calling gp-unwind with it. - -

(gp-clear state), Reset the state to it's initial setup. - +

+

(gp-clear state), Reset the state to it’s initial setup. +

+

1.5 Redo safe variables and redo safe parameters.

+ + + -

-A redo safe variable is a ordinary scheme variable object or fluid object that has the property that its state will be intelligently stored and retrieved under various premisses. Essentially if there is no mutattion further down the stack we can use the guard version. Else between lguard and rguard the variable is guaranteed to have restorage property independent of mutation or not. - -

(gp-undo-safe-variable-guard var kind s +

A redo safe variable is a ordinary scheme variable object or fluid object that has the property that its state will be intelligently stored and retrieved under various premisses. Essentially if there is no mutattion further down the stack we can use the guard version. Else between lguard and rguard the variable is guaranteed to have restorage property independent of mutation or not. +

+

(gp-undo-safe-variable-guard var kind s (gp-undo-safe-variable-lguard var kind s (gp-undo-safe-variable-rguard var kind s - -

var is a guile variable or fluid. We have a control parameter kind which must not be a GP variable. and s containes the guile-log assoq state. - -

At rewind in context K, the rules for restoring the state is as follows -

    -
  • kind = #t, restore the state. -
  • kind = #f, do not restore. -
  • K = #t, restore the state. -
  • K = #f, do not restore. -
  • kind, number and K, number Then we will restore the state if K <= kind. -
  • else do not restore the state. -
- +

+

var is a guile variable or fluid. We have a control parameter kind which must not be a GP variable. and s containes the guile-log assoq state. +

+

At rewind in context K, the rules for restoring the state is as follows +

    +
  • kind = #t, restore the state. +
  • kind = #f, do not restore. +
  • K = #t, restore the state. +
  • K = #f, do not restore. +
  • kind, number and K, number Then we will restore the state if K <= kind. +
  • else do not restore the state. +
+ + +

1.6 Managing stack frames

- -

-Stack has a stack pointers to undo stacks a data stack and a cons stack and dynstack, by walking up and down these stacks we can recreate a state. The most lightweight way of winding is to use gp-newframe and gp-unwind where you can only go to a previous stack point stored by gp-newframe and doing that the system forgets everything. This is fast and with no memory overhead. The other mode of operation using gp-store-state,gp-restore-state and gp-restore-wind will go the full way and keep everything in memory until you drop and references to the returned state information and the gc can kick in at recollect the data. gp-store-state will make a state data structure suitable to be for this mode of operation and gp-restore-state will restore the infromation either backward or forward in time. Then the setup will be precisely as when the store operation was issued. To note here is that sometimes you would like to use the store and restore operation in a mode that follows a calculation like with the interleaving constructs for this operation it is very nifty to have global variables like if they lived on the heap to implement the logic. The downside is that with heap objects you typically cannot restore a state if you would like to do that. Guile log has a nifty framework to define variables that behaves just like these heap variables but with the difference that they are automagicaly restored when the user issues the gp-restore-state. In order for this to work we use gp-restore-wind internally when we store and restore information as we follow an algorithmic calculation path. - -

(gp-newframe s), returns the current frame incorporated in a state variable state of the stack in order to be able to backtrack. - -

(gp-unwind s), backtrack to state represented by s that should have been returned by (gp-newframe s) e.g. a state data structure. - -

The next two command is mirroring the two commands above. But for these we don't impose the restriction to only go back in time, we can freely restore a state. Memory wise and performance this is heavier. But to note is that we do tree compression e.g. we try to reuse as much data as possible. - -

(gp-store-state s) -> state, Gives a state that can be used to restore a state, this makes the unify stack act well together with call/cc constructions or using continuation closures e.g. it is possible to do continuations with these prolog stacks. Note that this is a very effective storage mechanism, basically the continuation is stored in a tree like structure. - -

(gp-restore-state state), Restore a state that is saved by gp-store-state - -

(gp-restore-wind state wind), the same as above, but they will not change the dynamic globals e.g. guarded variables to the old state depending an the algorithm described in teh beginning of this section. - + + + + + + +

Stack has a stack pointers to undo stacks a data stack and a cons stack and dynstack, by walking up and down these stacks we can recreate a state. The most lightweight way of winding is to use gp-newframe and gp-unwind where you can only go to a previous stack point stored by gp-newframe and doing that the system forgets everything. This is fast and with no memory overhead. The other mode of operation using gp-store-state,gp-restore-state and gp-restore-wind will go the full way and keep everything in memory until you drop and references to the returned state information and the gc can kick in at recollect the data. gp-store-state will make a state data structure suitable to be for this mode of operation and gp-restore-state will restore the infromation either backward or forward in time. Then the setup will be precisely as when the store operation was issued. To note here is that sometimes you would like to use the store and restore operation in a mode that follows a calculation like with the interleaving constructs for this operation it is very nifty to have global variables like if they lived on the heap to implement the logic. The downside is that with heap objects you typically cannot restore a state if you would like to do that. Guile log has a nifty framework to define variables that behaves just like these heap variables but with the difference that they are automagicaly restored when the user issues the gp-restore-state. In order for this to work we use gp-restore-wind internally when we store and restore information as we follow an algorithmic calculation path. +

+

(gp-newframe s), returns the current frame incorporated in a state variable state of the stack in order to be able to backtrack. +

+

(gp-unwind s), backtrack to state represented by s that should have been returned by (gp-newframe s) e.g. a state data structure. +

+

The next two command is mirroring the two commands above. But for these we don’t impose the restriction to only go back in time, we can freely restore a state. Memory wise and performance this is heavier. But to note is that we do tree compression e.g. we try to reuse as much data as possible. +

+

(gp-store-state s) -> state, Gives a state that can be used to restore a state, this makes the unify stack act well together with call/cc constructions or using continuation closures e.g. it is possible to do continuations with these prolog stacks. Note that this is a very effective storage mechanism, basically the continuation is stored in a tree like structure. +

+

(gp-restore-state state), Restore a state that is saved by gp-store-state +

+

(gp-restore-wind state wind), the same as above, but they will not change the dynamic globals e.g. guarded variables to the old state depending an the algorithm described in teh beginning of this section. +

+

1.7 The gp fluid

- -

For a guile variable or more prefereble (it is thread safe) for a fluid we can model it as a guile fluid but living on the guile-log stacks in stead. For this to work just use variable-ref, variable-set!, fluid-ref, fluid-set! and - -

(gp-fluid-set var val) -This will bind var to val for the rest of the guile log stacks, e.g. similar to guile's with-fluids. - + +

For a guile variable or more prefereble (it is thread safe) for a fluid we can model it as a guile fluid but living on the guile-log stacks in stead. For this to work just use variable-ref, variable-set!, fluid-ref, fluid-set! and +

+

(gp-fluid-set var val) +This will bind var to val for the rest of the guile log stacks, e.g. similar to guile’s with-fluids. +

+

1.8 The guile log variables

- -

-(gp-var!), generate a new unify variable. E.g. -

  scheme(guile-user)> (define a (gp-var!))
-  scheme(guile-user)> (define b (gp-var!))
-  scheme(guile-user)> a
-  $7 = <#0>
-  scheme(guile-user)> b
-  $8 = <#1>
-  scheme(guile-user)> (gp-unify! a b)
+
+
+
+
+
+
+
+
+

(gp-var!), generate a new unify variable. E.g. +

  scheme(guile-user)> (define a (gp-var!))
+  scheme(guile-user)> (define b (gp-var!))
+  scheme(guile-user)> a
+  $7 = <#0>
+  scheme(guile-user)> b
+  $8 = <#1>
+  scheme(guile-user)> (gp-unify! a b)
   $9 = #t
-  scheme(guile-user)> a
-  $10 = <#1>
-  scheme  (guile-user)> b
-  $11 = <#1>
+  scheme(guile-user)> a
+  $10 = <#1>
+  scheme  (guile-user)> b
+  $11 = <#1>
 
 If executed under logical kanren assq feature then the variable is created on the heap, else it is created on the stack.
 
- -

(gp->scm x s), Take a unify variable and a state and turn it into a +

(gp->scm x s), Take a unify variable and a state and turn it into a list representation, variables is transfered as is. - -

  scheme(guile-user)> (u-set! a '(1 2))
-  scheme(guile-user)> a
-  $17 = <#gp (1 2)>
-  scheme(guile-user)> (gp->scm a)
+

+
  scheme(guile-user)> (u-set! a '(1 2))
+  scheme(guile-user)> a
+  $17 = <#gp (1 2)>
+  scheme(guile-user)> (gp->scm a)
   $18 = (1 2)
 
- -

(gp-budy x), it is possible to pair variable if you do -

  (let ((x (gp-var!))
+

(gp-budy x), it is possible to pair variable if you do +

  (let ((x (gp-var!))
         (y (gp-var!)))
     ...)
-
-Then inside ... y = (gp-budy x). +

Then inside ... y = (gp-budy x). +

-

(gp-var? x s), #t if x is a not bounded unify variable. +

(gp-var? x s), #t if x is a not bounded unify variable. s is the current state. +

-

(gp-lookup x s) If x is a unify variable it tries to find the element it points at using state information in s. If it is a unify variable that is returned, if it's a scheme object that is returned If it's a unify cons, that is returned. - -

(gp-var-number x), the variable number identifying a gp variable. - -

(gp-set! v a s) -> s, set looked up unify variable v to a. +

(gp-lookup x s) If x is a unify variable it tries to find the element it points at using state information in s. If it is a unify variable that is returned, if it’s a scheme object that is returned If it’s a unify cons, that is returned. +

+

(gp-var-number x), the variable number identifying a gp variable. +

+

(gp-set! v a s) -> s, set looked up unify variable v to a. using state s e.g. v is looked up until the last variable pointing to a scheme variable. It may change the state and a new state is returned. - +

+

1.9 guile log pairs

- -

-(gp-cons! x y), makes a unify cons variable out of x and y. To note here is that these conses are faster to allocate and they work well with rebounding later on and backtracks correctly. - -

(gp-pair? x s) -> s, checks to see if x is a pair or a unify pair + + + + + +

(gp-cons! x y), makes a unify cons variable out of x and y. To note here is that these conses are faster to allocate and they work well with rebounding later on and backtracks correctly. +

+

(gp-pair? x s) -> s, checks to see if x is a pair or a unify pair not a variable is will retrun false- Here the returned state is always the same as the input. x is assumed to have been looked up. - -

(gp-car x), takes the car of a unify pair or ordinary pair. x is +

+

(gp-car x), takes the car of a unify pair or ordinary pair. x is assumed to have been looked up. +

+

(gp-cdr x), takes the cdr of a unify pair or a ordinary pair x is assumed to have been looked up. +

-

(gp-cdr x), takes the cdr of a unify pair or a ordinary pair x is assumed to have been looked up. - +

1.10 unifying

+ + + -

-(gp-unify! x y s) -> s or #f, s if x and y -unifies with a recurrence check e.g. loop detection. #f if they do not +

(gp-unify! x y s) -> s or #f, s if x and y +unifies with a recurrence check e.g. loop detection. #f if they do not unify (note that although this is false variables could have been unified so #f is usually followed by a (gp-unwind Frame)) e.g. -

  (let ((Fr (gp-newframe)))
+

  (let ((Fr (gp-newframe)))
      (if (gp-unify! x y)
           #t
          (begin (gp-unwind Fr) #f)))
-
- -

(gp-unify-raw! x y s) -> s or #f, the same as gp-unify! but now loop detection e.g. we can end up in an infinite c-recursive loop and the stack will eventually be consumed and an error reported. +

-

(gp-m-unify! x y s) -> s or #f, the same as gp-unify! but now variables are not bounded, if x is a variable then y must be the same variable and vice verse in order to unify. +

(gp-unify-raw! x y s) -> s or #f, the same as gp-unify! but now loop detection e.g. we can end up in an infinite c-recursive loop and the stack will eventually be consumed and an error reported. +

+

(gp-m-unify! x y s) -> s or #f, the same as gp-unify! but now variables are not bounded, if x is a variable then y must be the same variable and vice verse in order to unify. +

+ +

1.11 guile log fluids guile log dynwinds

- -

-Fluids functions does not change the stack parameters it is a buggy interface because the kind of stack sign should be in the state parameter that should be used as well as input. - -

(gp-make-var),(gp-make-var init) makes guile log variable on the heap and an optional init value, init. - -

(gp-var-set! v x) set! a guile-log variable without backtracking !danger! do not use this anywhere else then a before a first gp-var-set have + + + + + + + + +

Fluids functions does not change the stack parameters it is a buggy interface because the kind of stack sign should be in the state parameter that should be used as well as input. +

+

(gp-make-var),(gp-make-var init) makes guile log variable on the heap and an optional init value, init. +

+

(gp-var-set! v x) set! a guile-log variable without backtracking !danger! do not use this anywhere else then a before a first gp-var-set have been issued on the variable. - -

(gp-var-set v x) set a guile-log variable with backtracking the guile +

+

(gp-var-set v x) set a guile-log variable with backtracking the guile stack is forced to be used to handle the backtracking. - -

(gp-var-ref v) reference a guile-log var. - -

(gp-dynwind Redo Do Undo) a similar tool as the dynwind construction but this one follows the current bank stack and not the call stack. Again - -

These two should only be used by experts. +

+

(gp-var-ref v) reference a guile-log var. +

+

(gp-dynwind Redo Do Undo) a similar tool as the dynwind construction but this one follows the current bank stack and not the call stack. Again +

+

These two should only be used by experts. (push-setup thunk), this will push a thunk on the push stack, a setup is code that is run after the winding has ben done, typically this is used inside a dynwind. +

+

(que-setup thunk), this will que thunk on the setup que that is executed after the winding of the stack have been done. +

+

N.B. the setup stack is executed before the setup que. +

-

(que-setup thunk), this will que thunk on the setup que that is executed after the winding of the stack have been done. -

N.B. the setup stack is executed before the setup que. +

1.12 Kanren logical variables support

- -

-In kanren the interpretation of a variable is goverend in a state that behaves -as an assq list. To find a value of a binding that list are searched for a -binding. now this datastructure need not be a assq list, only sematically -behave like it and that it need to be functional. The benifit is mainly that + + + + +

In kanren the interpretation of a variable is goverend in a state that behaves +as an assq list. To find a value of a binding that list are searched for a +binding. now this datastructure need not be a assq list, only sematically +behave like it and that it need to be functional. The benifit is mainly that multiprocessor support is trivial by having such a feature. The intention is to - execute the usage seamlessly in the background but uit can be beneficial to + execute the usage seamlessly in the background but uit can be beneficial to force the usage of them and therefore there is a public interface with primitives. - -

SCM (use-logical) +

+

SCM (use-logical) SCM (leave-logical) -To mark that the engine enters a region where it uses kanren logical structure +To mark that the engine enters a region where it uses kanren logical structure excecute the use-logical function, and to leave use the other form. -These codes will add guards on the stack as well in order for it to work +These codes will add guards on the stack as well in order for it to work seamlessly with regards to backtracking and state restorage. - -

(gp-stack-set! x v s) -> s, forces the usage of the stack as +

+

(gp-stack-set! x v s) -> s, forces the usage of the stack as a method of doing an undoable set. - +

+

1.13 spurious commands

+ + + + -

-(gp-print x) debug tool, prints out information of the internal representation of x. +

(gp-print x) debug tool, prints out information of the internal representation of x. +

+

(gp-printer port x), the printer used to print unify variables +

-

(gp-printer port x), the printer used to print unify variables +

(gp-copy x) Makes a copy of x, but copy the references to variables and not the variables them self +

+

(gp-get-stack), a debug tool. Yields the control stack containing undo information. +

-

(gp-copy x) Makes a copy of x, but copy the references to variables and not the variables them self -

(gp-get-stack), a debug tool. Yields the control stack containing undo information. +


+
+

+Next: , Previous: , Up: Top   [Index]

+
+ - + + diff --git a/logic/guile-log/guile-prolog/canon.scm b/logic/guile-log/guile-prolog/canon.scm index fb80582590aa1f673c1b066575f1a743fa9bfa5b..b7b87c7f7c95fa1a5d7063dd1312e7d1d879d2a6 100644 --- a/logic/guile-log/guile-prolog/canon.scm +++ b/logic/guile-log/guile-prolog/canon.scm @@ -74,7 +74,11 @@ fstart(X,Z,H) :- make_vhash(W), f(X,Z,H,W),!. ( (recursive_canonize x z) ( ((m (make-hash-table))) - (rec-action00 ( (x) ( (hashq-set! m ( x) #t))) x) + ((with-atomic-frec ( (x) + (rec-action00 + ( (x) ( (hashq-set! m ( x) #t))) + x))) + x) (fstart x z m))) ( (canonize f . x) diff --git a/logic/guile-log/guile-prolog/interpreter.scm b/logic/guile-log/guile-prolog/interpreter.scm index 6dfc691b354ad6a53d19a95097679530cf6825d9..b4a7412a798815cd75b25785338fb3da17963ac5 100644 --- a/logic/guile-log/guile-prolog/interpreter.scm +++ b/logic/guile-log/guile-prolog/interpreter.scm @@ -450,10 +450,13 @@ solve(X) :- X. (define recurs-map (make-fluid '())) ( (rec_analyze x) ( (fluid-set! recurs-map (make-hash-table))) - (rec-action - ( (x) - ( (hashq-set! (fluid-ref recurs-map) - ( x) #t))) + ((with-atomic-frec + ( (x) + (rec-action + ( (x) + ( (hashq-set! (fluid-ref recurs-map) + ( x) #t))) + x))) x)) ( (vtosym-guard x s) @@ -475,7 +478,9 @@ solve(X) :- X. (<=> y '*)))) x)) -(define vtosym4 (rec-once-0 vtosym_ vtosym-guard doit-at-rec)) +(define vtosym4 + (with-atomic-rec + (rec-00 vtosym_ vtosym-guard doit-at-rec))) diff --git a/logic/guile-log/memoize.scm b/logic/guile-log/memoize.scm index 16718d101211ea0ca5988a7fdf8b6cfd6ab4b460..60c2725213fe184456bc1b9ec422e76242eac19a 100644 --- a/logic/guile-log/memoize.scm +++ b/logic/guile-log/memoize.scm @@ -13,12 +13,12 @@ #:use-module (logic guile-log prolog closed) #:use-module (logic guile-log prolog namespace) #:use-module (logic guile-log guile-prolog closure) - #:export (memo rec tabling memo-rec memo-ref rec-ref table-ref + #:export (memo rec rec-00 tabling memo-rec memo-ref rec-ref table-ref rec-once memos recs rec= rec== rec-action with-rec-unifyer rec-unifyer rec-0 rec-once-0 rec-lam rec-action00 rec-lam-once rec-lam-0 rec-lam-once-0 gp-cp-rec gp->scm-rec canon-it-rec with-nonrec-unifyer nonrec-unifyer - recursive with-canon with-atomic-rec )) + recursive with-canon with-atomic-rec with-atomic-frec)) #| Memoizing can speed up function evaluation by memoizing the input and output. @@ -425,15 +425,25 @@ Also it is possible to solve inifinite recursion. (define-syntax-rule (with-atomic-rec code) (let ((f code)) - ( (x y) + ( x ( ((h (fluid-ref recs)) (p P)) ( (lambda () (fluid-set! recs h) (p)) - (f x y) + ( f x) ( (vhash-truncate! h) (fluid-set! recs h))))))) +(define-syntax-rule (with-atomic-frec f) + ( x + ( ((h (fluid-ref recs)) + (p P)) + ( (lambda () (fluid-set! recs h) (p)) + ( f x) + ( + (vhash-truncate! h) + (fluid-set! recs h)))))) + (define rec= (with-atomic-rec (rec-00 rec=* unify-guard doit-id))) (define rec== (with-atomic-rec (rec-00 rec==* unify-guard doit-id))) diff --git a/logic/guile-log/prolog/io.scm b/logic/guile-log/prolog/io.scm index 233a5aee64f53160fa7c7012018827d0d6fe55d2..d8e4f9448abbc812660a353c6e881a297e65fb1b 100644 --- a/logic/guile-log/prolog/io.scm +++ b/logic/guile-log/prolog/io.scm @@ -691,7 +691,7 @@ (else (format #f "~a" a))))))) - ( rec-action00 s action x) + ( (with-atomic-frec ( (x) (rec-action00 action x))) s x) (lp x)) (define write_term