Skip to content

Commit

Permalink
Merge pull request #570 from okp4/fix/variable-resolution
Browse files Browse the repository at this point in the history
Fix/incorrect variable resolution
  • Loading branch information
ccamel authored Feb 23, 2024
2 parents 9fd5264 + d06a731 commit 0dd8526
Show file tree
Hide file tree
Showing 18 changed files with 317 additions and 205 deletions.
65 changes: 1 addition & 64 deletions x/logic/keeper/interpreter.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,8 @@ package keeper
import (
"context"
"math"
"strings"

"github.com/ichiban/prolog"
"github.com/ichiban/prolog/engine"
"github.com/samber/lo"

errorsmod "cosmossdk.io/errors"
Expand Down Expand Up @@ -73,41 +71,7 @@ func (k Keeper) execute(ctx context.Context, program, query string) (*types.Quer

// queryInterpreter executes the given query on the given interpreter and returns the answer.
func (k Keeper) queryInterpreter(ctx context.Context, i *prolog.Interpreter, query string, limit sdkmath.Uint) (*types.Answer, error) {
p := engine.NewParser(&i.VM, strings.NewReader(query))
t, err := p.Term()
if err != nil {
return nil, err
}

var env *engine.Env
count := sdkmath.ZeroUint()
envs := make([]*engine.Env, 0, limit.Uint64())
_, callErr := engine.Call(&i.VM, t, func(env *engine.Env) *engine.Promise {
if count.LT(limit) {
envs = append(envs, env)
}
count = count.Incr()
return engine.Bool(count.GT(limit))
}, env).Force(ctx)

answerErr := lo.IfF(callErr != nil, func() string {
return callErr.Error()
}).Else("")
success := len(envs) > 0
hasMore := count.GT(limit)
vars := parsedVarsToVars(p.Vars)
results, err := envsToResults(envs, p.Vars, i)
if err != nil {
return nil, err
}

return &types.Answer{
Success: success,
Error: answerErr,
HasMore: hasMore,
Variables: vars,
Results: results,
}, nil
return util.QueryInterpreter(ctx, i, query, limit)
}

// newInterpreter creates a new interpreter properly configured.
Expand Down Expand Up @@ -193,30 +157,3 @@ func nonNilNorZeroOrDefaultUint64(v *sdkmath.Uint, defaultValue uint64) uint64 {

return v.Uint64()
}

func parsedVarsToVars(vars []engine.ParsedVariable) []string {
return lo.Map(vars, func(v engine.ParsedVariable, _ int) string {
return v.Name.String()
})
}

func envsToResults(envs []*engine.Env, vars []engine.ParsedVariable, i *prolog.Interpreter) ([]types.Result, error) {
results := make([]types.Result, 0, len(envs))
for _, rEnv := range envs {
substitutions := make([]types.Substitution, 0, len(vars))
for _, v := range vars {
var expression prolog.TermString
err := expression.Scan(&i.VM, v.Variable, rEnv)
if err != nil {
return nil, err
}
substitution := types.Substitution{
Variable: v.Name.String(),
Expression: string(expression),
}
substitutions = append(substitutions, substitution)
}
results = append(results, types.Result{Substitutions: substitutions})
}
return results, nil
}
6 changes: 3 additions & 3 deletions x/logic/predicate/address.go
Original file line number Diff line number Diff line change
Expand Up @@ -35,15 +35,15 @@ import (
// [base64]: https://fr.wikipedia.org/wiki/Base64
func Bech32Address(_ *engine.VM, address, bech32 engine.Term, cont engine.Cont, env *engine.Env) *engine.Promise {
forwardConverter := func(value []engine.Term, _ engine.Term, env *engine.Env) ([]engine.Term, error) {
hrpTerm, dataTerm, err := prolog.AssertPair(env, value[0])
hrpTerm, dataTerm, err := prolog.AssertPair(value[0], env)
if err != nil {
return nil, err
}
data, err := prolog.ByteListTermToBytes(dataTerm, env)
if err != nil {
return nil, err
}
hrp, err := prolog.AssertAtom(env, hrpTerm)
hrp, err := prolog.AssertAtom(hrpTerm, env)
if err != nil {
return nil, err
}
Expand All @@ -56,7 +56,7 @@ func Bech32Address(_ *engine.VM, address, bech32 engine.Term, cont engine.Cont,
return []engine.Term{engine.NewAtom(b)}, nil
}
backwardConverter := func(value []engine.Term, _ engine.Term, env *engine.Env) ([]engine.Term, error) {
b, err := prolog.AssertAtom(env, value[0])
b, err := prolog.AssertAtom(value[0], env)
if err != nil {
return nil, err
}
Expand Down
6 changes: 6 additions & 0 deletions x/logic/predicate/address_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,12 @@ func TestBech32(t *testing.T) {
}},
wantSuccess: true,
},
{
program: `okp4_addr(Addr) :- bech32_address(-('okp4', _), Addr).`,
query: `okp4_addr('okp41p8u47en82gmzfm259y6z93r9qe63l25dfwwng6').`,
wantResult: []testutil.TermResults{{}},
wantSuccess: true,
},
{
query: `bech32_address(Address, 'okp415wn30a9z4uc692s0kkx5fp5d4qfr3ac7sj9dqn').`,
wantResult: []testutil.TermResults{{
Expand Down
4 changes: 2 additions & 2 deletions x/logic/predicate/crypto.go
Original file line number Diff line number Diff line change
Expand Up @@ -167,7 +167,7 @@ func xVerify(key, data, sig, options engine.Term, defaultAlgo util.KeyAlg,
if err != nil {
return engine.Error(err)
}
typeAtom, err := prolog.AssertAtom(env, typeTerm)
typeAtom, err := prolog.AssertAtom(typeTerm, env)
if err != nil {
return engine.Error(err)
}
Expand Down Expand Up @@ -211,7 +211,7 @@ func termToBytes(term, options, defaultEncoding engine.Term, env *engine.Env) ([
if err != nil {
return nil, err
}
encodingAtom, err := prolog.AssertAtom(env, encodingTerm)
encodingAtom, err := prolog.AssertAtom(encodingTerm, env)
if err != nil {
return nil, err
}
Expand Down
2 changes: 1 addition & 1 deletion x/logic/predicate/did.go
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,7 @@ func DIDComponents(vm *engine.VM, did, components engine.Term, cont engine.Cont,
switch segment := env.Resolve(t2.Arg(i)).(type) {
case engine.Variable:
default:
atom, err := prolog.AssertAtom(env, segment)
atom, err := prolog.AssertAtom(segment, env)
if err != nil {
return engine.Error(err)
}
Expand Down
5 changes: 5 additions & 0 deletions x/logic/predicate/did_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,11 @@ func TestDID(t *testing.T) {
query: `did_components('did:example:123456',did_components(X,Y,_,_,_)).`,
wantResult: []testutil.TermResults{{"X": "example", "Y": "'123456'"}},
},
{
program: `is_did_key(DID) :- did_components(DID, Components), Components = did_components('key',_,_,_,_).`,
query: `is_did_key('did:key:123456').`,
wantResult: []testutil.TermResults{{}},
},
{
query: `did_components('did:example:123456',did_components(X,Y,Z,_,_)).`,
wantResult: []testutil.TermResults{{"X": "example", "Y": "'123456'", "Z": "_1"}},
Expand Down
4 changes: 2 additions & 2 deletions x/logic/predicate/file.go
Original file line number Diff line number Diff line change
Expand Up @@ -150,11 +150,11 @@ func Open(vm *engine.VM, sourceSink, mode, stream, options engine.Term, k engine
s := engine.NewInputTextStream(f)

if prolog.IsGround(options, env) {
_, err = prolog.AssertList(env, options)
_, err = prolog.AssertList(options, env)
switch {
case err != nil:
return engine.Error(err)
case !prolog.IsEmptyList(options):
case !prolog.IsEmptyList(options, env):
return engine.Error(engine.DomainError(prolog.ValidEmptyList(), options, env))
}
}
Expand Down
2 changes: 1 addition & 1 deletion x/logic/predicate/string.go
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,7 @@ func ReadString(vm *engine.VM, stream, length, result engine.Term, cont engine.C
func StringBytes(
_ *engine.VM, str, bts, encodingTerm engine.Term, cont engine.Cont, env *engine.Env,
) *engine.Promise {
encoding, err := prolog.AssertAtom(env, encodingTerm)
encoding, err := prolog.AssertAtom(encodingTerm, env)
if err != nil {
return engine.Error(err)
}
Expand Down
4 changes: 2 additions & 2 deletions x/logic/predicate/uri.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,11 +31,11 @@ import (
//
// [RFC 3986]: https://datatracker.ietf.org/doc/html/rfc3986#section-2.1
func URIEncoded(_ *engine.VM, component, decoded, encoded engine.Term, cont engine.Cont, env *engine.Env) *engine.Promise {
_, err := prolog.AssertIsGround(env, component)
_, err := prolog.AssertIsGround(component, env)
if err != nil {
return engine.Error(err)
}
uriComponent, err := prolog.AssertURIComponent(env, component)
uriComponent, err := prolog.AssertURIComponent(component, env)
if err != nil {
return engine.Error(err)
}
Expand Down
Loading

0 comments on commit 0dd8526

Please sign in to comment.