Skip to content

Commit

Permalink
bigint
Browse files Browse the repository at this point in the history
  • Loading branch information
r3v4s committed Dec 7, 2023
1 parent a4c7b86 commit f763389
Show file tree
Hide file tree
Showing 6 changed files with 109 additions and 5 deletions.
6 changes: 6 additions & 0 deletions examples/gno.land/p/demo/ufmt/ufmt.gno
Original file line number Diff line number Diff line change
Expand Up @@ -64,12 +64,18 @@ func Sprintf(format string, args ...interface{}) string {
switch v := arg.(type) {
case int:
buf += strconv.Itoa(v)
case int32:
buf += strconv.Itoa(int(v))
case int64:
buf += strconv.Itoa(int(v))
case uint:
buf += strconv.FormatUint(uint64(v), 10)
case uint32:
buf += strconv.FormatUint(uint64(v), 10)
case uint64:
buf += strconv.FormatUint(v, 10)
case bigint:
buf += string(v)
default:
buf += "(unhandled)"
}
Expand Down
13 changes: 13 additions & 0 deletions gno.land/pkg/sdk/vm/convert.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package vm
import (
"encoding/base64"
"fmt"
"math/big"
"strconv"

gno "github.com/gnolang/gno/gnovm/pkg/gnolang"
Expand Down Expand Up @@ -153,6 +154,18 @@ func convertArgToGno(arg string, argT gno.Type) (tv gno.TypedValue) {
}
tv.SetUint64(u64)
return
case gno.BigintType:
if arg[0] == '+' {
panic("numbers cannot start with +")
}
bi, ok := big.NewInt(0).SetString(arg, 10)
if !ok {
panic(fmt.Sprintf(
"error parsing bigint %v", arg))
}

tv.SetBigInt(bi)
return
default:
panic(fmt.Sprintf("unexpected primitive type %s", bt.String()))
}
Expand Down
9 changes: 7 additions & 2 deletions gnovm/pkg/gnolang/gonative.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package gnolang

import (
"fmt"
"math/big"
"reflect"
)

Expand Down Expand Up @@ -508,7 +509,9 @@ func go2GnoValueUpdate(alloc *Allocator, rlm *Realm, lvl int, tv *TypedValue, rv
tv.SetFloat64(rv.Float())
}
case BigintKind:
panic("not yet implemented")
if lvl != 0 {
tv.SetBigInt(rv.Interface().(*big.Int))
}
case BigdecKind:
panic("not yet implemented")
case ArrayKind:
Expand Down Expand Up @@ -828,7 +831,7 @@ func gno2GoType(t Type) reflect.Type {
case Float64Type:
return reflect.TypeOf(float64(0))
case BigintType, UntypedBigintType:
panic("not yet implemented")
return reflect.TypeOf(big.NewInt(0))
case BigdecType, UntypedBigdecType:
panic("not yet implemented")
default:
Expand Down Expand Up @@ -1113,6 +1116,8 @@ func gno2GoValue(tv *TypedValue, rv reflect.Value) (ret reflect.Value) {
rv.SetFloat(float64(tv.GetFloat32()))
case Float64Type:
rv.SetFloat(tv.GetFloat64())
case BigintType, UntypedBigintType:
rv.Set(reflect.ValueOf(tv.GetBigInt()))
default:
panic(fmt.Sprintf(
"unexpected type %s",
Expand Down
6 changes: 3 additions & 3 deletions gnovm/pkg/gnolang/op_binary.go
Original file line number Diff line number Diff line change
Expand Up @@ -1109,9 +1109,9 @@ func shlAssign(lv, rv *TypedValue) {
case Uint64Type:
lv.SetUint64(lv.GetUint64() << rv.GetUint())
case BigintType, UntypedBigintType:
lb := lv.GetBigInt()
lb = big.NewInt(0).Lsh(lb, rv.GetUint())
lv.V = BigintValue{V: lb}
z := big.NewInt(0)
z.Lsh(lv.GetBigInt(), rv.GetUint())
lv.V = BigintValue{V: z}
default:
panic(fmt.Sprintf(
"operators << and <<= not defined for %s",
Expand Down
16 changes: 16 additions & 0 deletions gnovm/pkg/gnolang/values.go
Original file line number Diff line number Diff line change
Expand Up @@ -996,6 +996,7 @@ func (tv TypedValue) Copy(alloc *Allocator) (cp TypedValue) {
case BigintValue:
cp.T = tv.T
cp.V = cv.Copy(alloc)
cp.N = tv.N
case *ArrayValue:
cp.T = tv.T
cp.V = cv.Copy(alloc)
Expand Down Expand Up @@ -1432,6 +1433,17 @@ func (tv *TypedValue) GetFloat64() float64 {
return *(*float64)(unsafe.Pointer(&tv.N))
}

func (tv *TypedValue) SetBigInt(bi *big.Int) {
if debug {
if tv.T.Kind() != BigintKind || isNative(tv.T) {
panic(fmt.Sprintf(
"TypedValue.SetBigInt() on type %s",
tv.T.String()))
}
}
tv.V = BigintValue{bi}
}

func (tv *TypedValue) GetBigInt() *big.Int {
if debug {
if tv.T != nil && tv.T.Kind() != BigintKind {
Expand Down Expand Up @@ -2439,6 +2451,10 @@ func defaultValue(alloc *Allocator, t Type) Value {
)
}
default:
switch t.Kind() {
case BigintKind:
return BigintValue{V: big.NewInt(0)}
}
return nil
}
}
Expand Down
64 changes: 64 additions & 0 deletions gnovm/pkg/gnolang/values_conversions.go
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,9 @@ GNO_CASE:
x := uint64(tv.GetInt())
tv.T = t
tv.SetUint64(x)
case BigintKind:
tv.V = BigintValue{V: big.NewInt(tv.GetInt64())}
tv.T = t
case Float32Kind:
x := float32(tv.GetInt()) // XXX determinism?
tv.T = t
Expand Down Expand Up @@ -307,6 +310,9 @@ GNO_CASE:
x := uint64(tv.GetInt32())
tv.T = t
tv.SetUint64(x)
case BigintKind:
tv.V = BigintValue{V: big.NewInt(tv.GetInt64())}
tv.T = t
case Float32Kind:
x := float32(tv.GetInt32()) // XXX determinism?
tv.T = t
Expand Down Expand Up @@ -366,6 +372,9 @@ GNO_CASE:
x := uint64(tv.GetInt64())
tv.T = t
tv.SetUint64(x)
case BigintKind:
tv.V = BigintValue{V: big.NewInt(tv.GetInt64())}
tv.T = t
case Float32Kind:
x := float32(tv.GetInt64()) // XXX determinism?
tv.T = t
Expand Down Expand Up @@ -425,6 +434,9 @@ GNO_CASE:
x := uint64(tv.GetUint())
tv.T = t
tv.SetUint64(x)
case BigintKind:
tv.V = BigintValue{V: big.NewInt(tv.GetInt64())}
tv.T = t
case Float32Kind:
x := float32(tv.GetUint()) // XXX determinism?
tv.T = t
Expand Down Expand Up @@ -661,6 +673,9 @@ GNO_CASE:
x := tv.GetUint64()
tv.T = t
tv.SetUint64(x)
case BigintKind:
tv.V = BigintValue{V: big.NewInt(tv.GetInt64())}
tv.T = t
case Float32Kind:
x := float32(tv.GetUint64()) // XXX determinism?
tv.T = t
Expand All @@ -678,6 +693,41 @@ GNO_CASE:
"cannot convert %s to %s",
tvk.String(), k.String()))
}
case BigintKind:
switch k {
case IntKind, Int8Kind, Int16Kind, Int32Kind, UintKind, Uint8Kind, Uint16Kind, Uint32Kind:
panic(fmt.Sprintf(
"cannot convert %s to %s",
tvk.String(), k.String()))
case Int64Kind:
x := tv.GetBigInt()
if x.IsInt64() {
tv.T = t
tv.SetInt64(x.Int64())
} else {
panic(fmt.Sprintf(
"cannot convert %s to %s",
tvk.String(), k.String()))
}
case Uint64Kind:
x := tv.GetBigInt()
if x.IsUint64() {
tv.T = t
tv.SetUint64(x.Uint64())
} else {
panic(fmt.Sprintf(
"cannot convert %s to %s",
tvk.String(), k.String()))
}
case StringKind:
tv.T = t
tv.SetString(StringValue(tv.GetBigInt().String()))
default:
panic(fmt.Sprintf(
"cannot convert %s to %s",
tvk.String(), k.String()))

}
case Float32Kind:
switch k {
case IntKind:
Expand Down Expand Up @@ -809,6 +859,20 @@ GNO_CASE:
"cannot convert %s to %s",
tvk.String(), t.String()))
}
case PrimitiveType:
switch k {
case BigintKind:
bi := new(big.Int)
bi, ok := bi.SetString(tv.GetString(), 10)
if !ok {
panic(fmt.Sprintf(
"cannot convert %s to %s",
tvk.String(), k.String(),
))
}
tv.V = BigintValue{V: bi}
tv.T = t
}
default:
panic(fmt.Sprintf(
"cannot convert %s to %s",
Expand Down

0 comments on commit f763389

Please sign in to comment.