Skip to content

Commit

Permalink
add interop example, Subquery type, update trealla
Browse files Browse the repository at this point in the history
  • Loading branch information
guregu committed Oct 24, 2022
1 parent 7deaa28 commit 32a07d8
Show file tree
Hide file tree
Showing 4 changed files with 65 additions and 5 deletions.
8 changes: 6 additions & 2 deletions trealla/interop.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,11 @@ import (
// - Return a call/1 compound to call a different goal instead.
// - Return a 'fail' atom to fail instead.
// - Return a 'true' atom to succeed without unifying anything.
type Predicate func(pl Prolog, subquery int32, goal Term) Term
type Predicate func(pl Prolog, subquery Subquery, goal Term) Term

// Subquery is an opaque value representing an in-flight query.
// It is unique as long as the query is alive, but may be re-used later on.
type Subquery int32

func (pl *prolog) exports() map[string]wasmer.IntoExtern {
return map[string]wasmer.IntoExtern{
Expand Down Expand Up @@ -97,7 +101,7 @@ func hostCall(env any, args []wasmer.Value) ([]wasmer.Value, error) {
}

locked := &lockedProlog{prolog: pl}
continuation := proc(locked, subquery, goal)
continuation := proc(locked, Subquery(subquery), goal)
locked.kill()
expr, err := marshal(continuation)
if err != nil {
Expand Down
58 changes: 57 additions & 1 deletion trealla/interop_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,9 @@ package trealla

import (
"context"
"encoding/base32"
"errors"
"fmt"
"log"
"reflect"
"testing"
Expand All @@ -15,7 +17,7 @@ func TestInterop(t *testing.T) {
}

ctx := context.Background()
pl.Register(ctx, "interop_test", 1, func(pl Prolog, _ int32, goal Term) Term {
pl.Register(ctx, "interop_test", 1, func(pl Prolog, _ Subquery, goal Term) Term {
want := Atom("interop_test").Of(Variable{Name: "A"})
if !reflect.DeepEqual(want, goal) {
t.Error("bad goal. want:", want, "got:", goal)
Expand Down Expand Up @@ -83,3 +85,57 @@ func TestInterop(t *testing.T) {
})
}
}

func ExampleProlog_Register() {
ctx := context.Background()
pl, err := New()
if err != nil {
panic(err)
}

// Let's add a base32 encoding predicate.
// To keep it brief, this only handles one mode.
// base32(+Input, -Output) is det.
pl.Register(ctx, "base32", 2, func(_ Prolog, _ Subquery, goal0 Term) Term {
// goal is the goal called by Prolog, such as: base32("hello", X).
// Guaranteed to match up with the registered arity and name.
goal := goal0.(Compound)

// Check the Input argument's type, must be string.
input, ok := goal.Args[0].(string)
if !ok {
// throw(error(type_error(list, X), base32/2)).
return Atom("throw").Of(Atom("error").Of(
Atom("type_error").Of("list", goal.Args[0]),
Atom("/").Of(Atom("base32"), 2),
))
}

// Check Output type, must be string or var.
switch goal.Args[1].(type) {
case string: // ok
case Variable: // ok
default:
// throw(error(type_error(list, X), base32/2)).
return Atom("throw").Of(Atom("error").Of(
Atom("type_error").Of("list", goal.Args[0]),
Atom("/").Of(Atom("base32"), 2),
))
}

// Do the encoding actual work.
output := base32.StdEncoding.EncodeToString([]byte(input))

// Return a goal that Trealla will unify with its input:
// base32(Input, "output_goes_here").
return Atom("base32").Of(input, output)
})

// Try it out.
answer, err := pl.QueryOnce(ctx, `base32("hello", Encoded).`)
if err != nil {
panic(err)
}
fmt.Println(answer.Solution["Encoded"])
// Output: NBSWY3DP
}
4 changes: 2 additions & 2 deletions trealla/library.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ func (pl *prolog) loadBuiltins() error {
return nil
}

func http_consult_1(_ Prolog, _ int32, goal Term) Term {
func http_consult_1(_ Prolog, _ Subquery, goal Term) Term {
cmp, ok := goal.(Compound)
if !ok {
return typeError("compound", goal, piTerm("http_consult", 1))
Expand Down Expand Up @@ -83,7 +83,7 @@ func http_consult_1(_ Prolog, _ int32, goal Term) Term {
return Atom("call").Of(Atom(":").Of(Atom(href.String()), Atom("$load_chars").Of(buf.String())))
}

func crypto_data_hash_3(pl Prolog, _ int32, goal Term) Term {
func crypto_data_hash_3(pl Prolog, _ Subquery, goal Term) Term {
cmp, ok := goal.(Compound)
if !ok {
return typeError("compound", goal, piTerm("crypto_data_hash", 3))
Expand Down
Binary file modified trealla/libtpl.wasm
Binary file not shown.

0 comments on commit 32a07d8

Please sign in to comment.