Skip to content

Commit

Permalink
Merge pull request #319 from okp4/feat/source_files_predicate
Browse files Browse the repository at this point in the history
🧠 Logic: 🗂️ source_files/1 predicate
  • Loading branch information
ccamel committed Mar 21, 2023
2 parents a58991c + 67f4889 commit edf5b8a
Show file tree
Hide file tree
Showing 11 changed files with 90 additions and 22 deletions.
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package interpreter
package bootstrap

import _ "embed"

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -253,3 +253,5 @@
maplist(Cont_7, [E1|E1s], [E2|E2s], [E3|E3s], [E4|E4s], [E5|E5s], [E6|E6s], [E7|E7s]) :-
call(Cont_7, E1, E2, E3, E4, E5, E6, E7),
maplist(Cont_7, E1s, E2s, E3s, E4s, E5s, E6s, E7s).

source_files(Files) :- bagof(File, source_file(File), Files).
3 changes: 2 additions & 1 deletion x/logic/keeper/interpreter.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import (
sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/ichiban/prolog"
"github.com/okp4/okp4d/x/logic/interpreter"
"github.com/okp4/okp4d/x/logic/interpreter/bootstrap"
"github.com/okp4/okp4d/x/logic/types"
"github.com/okp4/okp4d/x/logic/util"
)
Expand Down Expand Up @@ -97,7 +98,7 @@ func (k Keeper) newInterpreter(ctx goctx.Context) (*prolog.Interpreter, error) {
interpreted, err := interpreter.New(
ctx,
util.NonZeroOrDefault(interpreterParams.GetRegisteredPredicates(), interpreter.RegistryNames),
util.NonZeroOrDefault(interpreterParams.GetBootstrap(), interpreter.Bootstrap()),
util.NonZeroOrDefault(interpreterParams.GetBootstrap(), bootstrap.Bootstrap()),
sdkctx.GasMeter(),
k.fsProvider(ctx),
)
Expand Down
2 changes: 1 addition & 1 deletion x/logic/predicate/address_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -117,7 +117,7 @@ func TestBech32(t *testing.T) {
ctx := sdk.NewContext(stateStore, tmproto.Header{}, false, log.NewNopLogger())

Convey("and a vm", func() {
interpreter := testutil.NewInterpreterMust(ctx)
interpreter := testutil.NewLightInterpreterMust(ctx)
interpreter.Register2(engine.NewAtom("bech32_address"), Bech32Address)

err := interpreter.Compile(ctx, tc.program)
Expand Down
2 changes: 1 addition & 1 deletion x/logic/predicate/bank_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -454,7 +454,7 @@ func TestBank(t *testing.T) {
Return(tc.balances)

Convey("and a vm", func() {
interpreter := testutil.NewInterpreterMust(ctx)
interpreter := testutil.NewLightInterpreterMust(ctx)
interpreter.Register2(engine.NewAtom("bank_balances"), BankBalances)
interpreter.Register2(engine.NewAtom("bank_spendable_balances"), BankSpendableBalances)
interpreter.Register2(engine.NewAtom("bank_locked_balances"), BankLockedBalances)
Expand Down
2 changes: 1 addition & 1 deletion x/logic/predicate/block_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ func TestBlock(t *testing.T) {
ctx := sdk.NewContext(stateStore, tc.header, false, log.NewNopLogger())

Convey("and a vm", func() {
interpreter := testutil.NewInterpreterMust(ctx)
interpreter := testutil.NewLightInterpreterMust(ctx)
interpreter.Register1(engine.NewAtom("block_height"), BlockHeight)
interpreter.Register1(engine.NewAtom("block_time"), BlockTime)
testutil.CompileMust(ctx, interpreter, fmt.Sprintf("test :- %s.", tc.implication))
Expand Down
2 changes: 1 addition & 1 deletion x/logic/predicate/chain_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ func TestChainID(t *testing.T) {
ctx := sdk.NewContext(stateStore, tc.header, false, log.NewNopLogger())

Convey("and an interpreter", func() {
interpreter := testutil.NewInterpreterMust(ctx)
interpreter := testutil.NewLightInterpreterMust(ctx)
interpreter.Register1(engine.NewAtom("chain_id"), ChainID)
testutil.CompileMust(ctx, interpreter, fmt.Sprintf("test :- %s.", tc.implication))

Expand Down
2 changes: 1 addition & 1 deletion x/logic/predicate/crypto_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -117,7 +117,7 @@ H == [2252,222,43,46,219,165,107,244,8,96,31,183,33,254,155,92,51,141,16,238,66,
ctx := sdk.NewContext(stateStore, tmproto.Header{}, false, log.NewNopLogger())

Convey("and a vm", func() {
interpreter := testutil.NewInterpreterMust(ctx)
interpreter := testutil.NewLightInterpreterMust(ctx)
interpreter.Register2(engine.NewAtom("sha_hash"), SHAHash)
interpreter.Register2(engine.NewAtom("hex_bytes"), HexBytes)

Expand Down
2 changes: 1 addition & 1 deletion x/logic/predicate/did_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,7 @@ func TestDID(t *testing.T) {
ctx := sdk.NewContext(stateStore, tmproto.Header{}, false, log.NewNopLogger())

Convey("and a vm", func() {
interpreter := testutil.NewInterpreterMust(ctx)
interpreter := testutil.NewLightInterpreterMust(ctx)
interpreter.Register2(engine.NewAtom("did_components"), DIDComponents)

err := interpreter.Compile(ctx, tc.program)
Expand Down
54 changes: 50 additions & 4 deletions x/logic/predicate/file_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,12 @@ import (
"testing"
"time"

goctx "context"

"github.com/cosmos/cosmos-sdk/store"
sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/golang/mock/gomock"
"github.com/ichiban/prolog"
"github.com/ichiban/prolog/engine"
"github.com/okp4/okp4d/x/logic/fs"
"github.com/okp4/okp4d/x/logic/testutil"
Expand All @@ -26,47 +29,90 @@ func TestSourceFile(t *testing.T) {
defer ctrl.Finish()

cases := []struct {
interpreter func(ctx goctx.Context) (i *prolog.Interpreter)
query string
wantResult []types.TermResults
wantError error
wantSuccess bool
}{
{
interpreter: testutil.NewLightInterpreterMust,
query: "source_file(file).",
wantSuccess: false,
},
{
interpreter: testutil.NewLightInterpreterMust,
query: "consult(file1), consult(file2), source_file(file1).",
wantResult: []types.TermResults{{}},
wantSuccess: true,
},
{
interpreter: testutil.NewLightInterpreterMust,
query: "consult(file1), consult(file2), consult(file3), source_file(file2).",
wantResult: []types.TermResults{{}},
wantSuccess: true,
},
{
interpreter: testutil.NewLightInterpreterMust,
query: "consult(file1), consult(file2), source_file(file3).",
wantSuccess: false,
},
{
interpreter: testutil.NewLightInterpreterMust,
query: "source_file(X).",
wantSuccess: false,
},
{
interpreter: testutil.NewLightInterpreterMust,
query: "consult(file1), consult(file2), source_file(X).",
wantResult: []types.TermResults{{"X": "file1"}, {"X": "file2"}},
wantSuccess: true,
},
{
interpreter: testutil.NewLightInterpreterMust,
query: "consult(file2), consult(file3), consult(file1), source_file(X).",
wantResult: []types.TermResults{{"X": "file1"}, {"X": "file2"}, {"X": "file3"}},
wantSuccess: true,
},
{
query: "source_file(foo(bar)).",
wantResult: []types.TermResults{},
wantError: fmt.Errorf("source_file/1: cannot unify file with *engine.compound"),
interpreter: testutil.NewLightInterpreterMust,
query: "source_file(foo(bar)).",
wantResult: []types.TermResults{},
wantError: fmt.Errorf("source_file/1: cannot unify file with *engine.compound"),
},

{
interpreter: testutil.NewComprehensiveInterpreterMust,
query: "source_files([file]).",
wantSuccess: false,
},
{
interpreter: testutil.NewComprehensiveInterpreterMust,
query: "consult(file1), consult(file2), source_files([file1, file2]).",
wantResult: []types.TermResults{{}},
wantSuccess: true,
},
{
interpreter: testutil.NewComprehensiveInterpreterMust,
query: "consult(file1), consult(file2), source_files([file1, file2, file3]).",
wantSuccess: false,
},
{
interpreter: testutil.NewComprehensiveInterpreterMust,
query: "source_files(X).",
wantSuccess: false,
},
{
interpreter: testutil.NewComprehensiveInterpreterMust,
query: "consult(file2), consult(file1), source_files(X).",
wantResult: []types.TermResults{{"X": "[file1,file2]"}},
wantSuccess: true,
},
{
interpreter: testutil.NewComprehensiveInterpreterMust,
query: "consult(file2), consult(file1), source_files([file1, X]).",
wantResult: []types.TermResults{{"X": "file2"}},
wantSuccess: true,
},
}

Expand All @@ -87,7 +133,7 @@ func TestSourceFile(t *testing.T) {
ctx := sdk.NewContext(stateStore, tmproto.Header{}, false, log.NewNopLogger())

Convey("and a vm", func() {
interpreter := testutil.NewInterpreterMust(ctx)
interpreter := tc.interpreter(ctx)
interpreter.FS = mockedFS
interpreter.Register1(engine.NewAtom("source_file"), SourceFile)

Expand Down
39 changes: 29 additions & 10 deletions x/logic/testutil/logic.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,18 +7,19 @@ import (

"github.com/ichiban/prolog"
"github.com/ichiban/prolog/engine"
"github.com/okp4/okp4d/x/logic/interpreter/bootstrap"
)

// NewInterpreterMust returns a new Interpreter with the given context or panics if it fails.
// NewLightInterpreterMust returns a new Interpreter with the given context or panics if it fails.
// The Interpreter is configured with minimal settings to support testing.
func NewInterpreterMust(ctx context.Context) (interpreter *prolog.Interpreter) {
interpreter = &prolog.Interpreter{}
interpreter.Register3(engine.NewAtom("op"), engine.Op)
interpreter.Register3(engine.NewAtom("compare"), engine.Compare)
interpreter.Register2(engine.NewAtom("="), engine.Unify)
interpreter.Register1(engine.NewAtom("consult"), engine.Consult)
func NewLightInterpreterMust(ctx context.Context) (i *prolog.Interpreter) {
i = &prolog.Interpreter{}
i.Register3(engine.NewAtom("op"), engine.Op)
i.Register3(engine.NewAtom("compare"), engine.Compare)
i.Register2(engine.NewAtom("="), engine.Unify)
i.Register1(engine.NewAtom("consult"), engine.Consult)

err := interpreter.Compile(ctx, `
err := i.Compile(ctx, `
:-(op(1200, xfx, ':-')).
:-(op(1000, xfy, ',')).
:-(op(700, xfx, [==, \==, @<, @=<, @>, @>=])).
Expand All @@ -35,10 +36,28 @@ func NewInterpreterMust(ctx context.Context) (interpreter *prolog.Interpreter) {
return
}

// NewComprehensiveInterpreterMust returns a new Interpreter with the given context or panics if it fails.
// The Interpreter is configured with the full boostrap but with a minimal set of predicates.
func NewComprehensiveInterpreterMust(ctx context.Context) (i *prolog.Interpreter) {
i = &prolog.Interpreter{}
i.Register3(engine.NewAtom("op"), engine.Op)
i.Register3(engine.NewAtom("compare"), engine.Compare)
i.Register2(engine.NewAtom("="), engine.Unify)
i.Register1(engine.NewAtom("consult"), engine.Consult)
i.Register3(engine.NewAtom("bagof"), engine.BagOf)

err := i.Compile(ctx, bootstrap.Bootstrap())
if err != nil {
panic(err)
}

return
}

// CompileMust compiles the given source code and panics if it fails.
// This is a convenience function for testing.
func CompileMust(ctx context.Context, interpreter *prolog.Interpreter, s string, args ...interface{}) {
err := interpreter.Compile(ctx, s, args...)
func CompileMust(ctx context.Context, i *prolog.Interpreter, s string, args ...interface{}) {
err := i.Compile(ctx, s, args...)
if err != nil {
panic(err)
}
Expand Down

0 comments on commit edf5b8a

Please sign in to comment.