Skip to content

Commit

Permalink
feat(logic): json_prolog/2 handle integer number
Browse files Browse the repository at this point in the history
  • Loading branch information
bdeneux committed Apr 26, 2023
1 parent 310459a commit a60f332
Show file tree
Hide file tree
Showing 2 changed files with 39 additions and 1 deletion.
18 changes: 17 additions & 1 deletion x/logic/predicate/json.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,9 @@ import (
"encoding/json"
"fmt"
"sort"
"strings"

"cosmossdk.io/math"
"github.com/ichiban/prolog/engine"
"github.com/okp4/okp4d/x/logic/util"
"github.com/samber/lo"
Expand Down Expand Up @@ -39,7 +41,12 @@ func JsonProlog(vm *engine.VM, j, term engine.Term, cont engine.Cont, env *engin

func jsonStringToTerms(j string) (engine.Term, error) {
var values any
json.Unmarshal([]byte(j), &values)
decoder := json.NewDecoder(strings.NewReader(j))
decoder.UseNumber() // unmarshal a number into an interface{} as a Number instead of as a float64

if err := decoder.Decode(&values); err != nil {
return nil, err
}

return jsonToTerms(values)
}
Expand All @@ -48,6 +55,15 @@ func jsonToTerms(value any) (engine.Term, error) {
switch v := value.(type) {
case string:
return util.StringToTerm(v), nil
case json.Number:
r, ok := math.NewIntFromString(string(v))
if !ok {
return nil, fmt.Errorf("could not convert number '%s' into integer term, decimal number is not handled yet", v)
}
if !r.IsInt64() {
return nil, fmt.Errorf("could not convert number '%s' into integer term, overflow", v)
}
return engine.Integer(r.Int64()), nil
case map[string]any:
keys := lo.Keys(v)
sort.Strings(keys)
Expand Down
22 changes: 22 additions & 0 deletions x/logic/predicate/json_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,28 @@ func TestJsonProlog(t *testing.T) {
}},
wantSuccess: true,
},
// ** JSON -> Prolog **
// Number
{
description: "convert json number into prolog",
query: `json_prolog('10', Term).`,
wantResult: []types.TermResults{{
"Term": "10",
}},
wantSuccess: true,
},
{
description: "convert large json number into prolog",
query: `json_prolog('100000000000000000000', Term).`,
wantSuccess: false,
wantError: fmt.Errorf("json_prolog/2: could not convert number '100000000000000000000' into integer term, overflow"),
},
{
description: "decimal number not compatible yet",
query: `json_prolog('10.4', Term).`,
wantSuccess: false,
wantError: fmt.Errorf("json_prolog/2: could not convert number '10.4' into integer term, decimal number is not handled yet"),
},
}
for nc, tc := range cases {
Convey(fmt.Sprintf("Given the query #%d: %s", nc, tc.query), func() {
Expand Down

0 comments on commit a60f332

Please sign in to comment.