Repository: d5/tengo (go)

Issue:
How to solve precision problem in tengo?
Hi,  thanks for such a great project!

How to solve precision problem in tengo?
```go
json := import("json")
fmt := import("fmt")


base_info := bytes(`{
        "1":7075984636689534001,
        "2":7075984636689534002
}`)
m := json.decode(base_info)
fmt.println(m[1])
```

result: 7075984636689534000



Pull request:
fix: solve precision problem when decode bigint in json
Fixes #379 
slightly modify json.decode to solve precision problem when decode bigint in json

Patch:
diff --git a/stdlib/json/decode.go b/stdlib/json/decode.go
index 6d468ef..37432d4 100644
--- a/stdlib/json/decode.go
+++ b/stdlib/json/decode.go
@@ -62,9 +62,12 @@ func (d *decodeState) scanNext() {
 
 // scanWhile processes bytes in d.data[d.off:] until it
 // receives a scan code not equal to op.
-func (d *decodeState) scanWhile(op int) {
+func (d *decodeState) scanWhile(op int) (isFloat bool) {
 	s, data, i := &d.scan, d.data, d.off
 	for i < len(data) {
+		if data[i] == '.' {
+			isFloat = true
+		}
 		newOp := s.step(s, data[i])
 		i++
 		if newOp != op {
@@ -76,6 +79,7 @@ func (d *decodeState) scanWhile(op int) {
 
 	d.off = len(data) + 1 // mark processed EOF with len+1
 	d.opcode = d.scan.eof()
+	return
 }
 
 func (d *decodeState) value() (tengo.Object, error) {
@@ -185,7 +189,7 @@ func (d *decodeState) object() (tengo.Object, error) {
 func (d *decodeState) literal() (tengo.Object, error) {
 	// All bytes inside literal return scanContinue op code.
 	start := d.readIndex()
-	d.scanWhile(scanContinue)
+	isFloat := d.scanWhile(scanContinue)
 
 	item := d.data[start:d.readIndex()]
 
@@ -210,8 +214,12 @@ func (d *decodeState) literal() (tengo.Object, error) {
 		if c != '-' && (c < '0' || c > '9') {
 			panic(phasePanicMsg)
 		}
-		n, _ := strconv.ParseFloat(string(item), 10)
-		return &tengo.Float{Value: n}, nil
+		if isFloat {
+			n, _ := strconv.ParseFloat(string(item), 10)
+			return &tengo.Float{Value: n}, nil
+		}
+		n, _ := strconv.ParseInt(string(item), 10, 64)
+		return &tengo.Int{Value: n}, nil
 	}
 }
 


Test patch:
diff --git a/stdlib/json/json_test.go b/stdlib/json/json_test.go
index 5abfdec..b12bd64 100644
--- a/stdlib/json/json_test.go
+++ b/stdlib/json/json_test.go
@@ -57,6 +57,8 @@ func TestJSON(t *testing.T) {
 		"arr": ARR{1, 2, 3, "four"}})
 	testJSONEncodeDecode(t, MAP{"a": 0, "b": "bee",
 		"arr": ARR{1, 2, 3, MAP{"a": false, "b": 109.4}}})
+
+	testJSONEncodeDecode(t, MAP{"id1": 7075984636689534001, "id2": 7075984636689534002})
 }
 
 func TestDecode(t *testing.T) {
diff --git a/stdlib/json_test.go b/stdlib/json_test.go
index adf7037..ac8dcf1 100644
--- a/stdlib/json_test.go
+++ b/stdlib/json_test.go
@@ -48,13 +48,13 @@ func TestJSON(t *testing.T) {
 		expect([]byte("[[\"bar\",1],[\"bar\",1]]"))
 
 	module(t, "json").call("decode", `5`).
-		expect(5.0)
+		expect(5)
 	module(t, "json").call("decode", `"foo"`).
 		expect("foo")
 	module(t, "json").call("decode", `[1,2,3,"bar"]`).
-		expect(ARR{1.0, 2.0, 3.0, "bar"})
+		expect(ARR{1, 2, 3, "bar"})
 	module(t, "json").call("decode", `{"foo":5}`).
-		expect(MAP{"foo": 5.0})
+		expect(MAP{"foo": 5})
 	module(t, "json").call("decode", `{"foo":2.5}`).
 		expect(MAP{"foo": 2.5})
 	module(t, "json").call("decode", `{"foo":true}`).
@@ -62,7 +62,7 @@ func TestJSON(t *testing.T) {
 	module(t, "json").call("decode", `{"foo":"bar"}`).
 		expect(MAP{"foo": "bar"})
 	module(t, "json").call("decode", `{"foo":[1,2,3,"bar"]}`).
-		expect(MAP{"foo": ARR{1.0, 2.0, 3.0, "bar"}})
+		expect(MAP{"foo": ARR{1, 2, 3, "bar"}})
 
 	module(t, "json").
 		call("indent", []byte("{\"foo\":[\"bar\",1,1.8,56,true]}"), "", "  ").