separate number into float and integer
This commit is contained in:
parent
10f55313b0
commit
daab50d54c
22 changed files with 848 additions and 428 deletions
|
|
@ -3,7 +3,7 @@ package core
|
|||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"math"
|
||||
"math/big"
|
||||
"reflect"
|
||||
"strconv"
|
||||
)
|
||||
|
|
@ -13,7 +13,8 @@ type ValueType int
|
|||
const (
|
||||
NilValueType ValueType = iota
|
||||
BoolValueType
|
||||
NumberValueType
|
||||
FloatValueType
|
||||
IntegerValueType
|
||||
StringValueType
|
||||
ListValueType
|
||||
ObjectValueType
|
||||
|
|
@ -30,8 +31,10 @@ func (v ValueType) String() string {
|
|||
return "bool"
|
||||
case ObjectValueType:
|
||||
return "object"
|
||||
case NumberValueType:
|
||||
return "number"
|
||||
case FloatValueType:
|
||||
return "float"
|
||||
case IntegerValueType:
|
||||
return "int"
|
||||
case StringValueType:
|
||||
return "string"
|
||||
case ListValueType:
|
||||
|
|
@ -57,11 +60,15 @@ func GoToValue(gov interface{}) Value {
|
|||
v,
|
||||
}
|
||||
case int:
|
||||
return &NumberValue{
|
||||
float64(v),
|
||||
return &IntegerValue{
|
||||
new(big.Int).SetInt64(int64(v)),
|
||||
}
|
||||
case *big.Int:
|
||||
return &IntegerValue{
|
||||
v,
|
||||
}
|
||||
case float64:
|
||||
return &NumberValue{
|
||||
return &FloatValue{
|
||||
v,
|
||||
}
|
||||
case string:
|
||||
|
|
@ -259,40 +266,71 @@ func (v *ObjectValue) Clone() Value {
|
|||
}
|
||||
}
|
||||
|
||||
// NumberValue Integer or floating-point values
|
||||
type NumberValue struct {
|
||||
// FloatValue floating-point values
|
||||
type FloatValue struct {
|
||||
Number float64
|
||||
}
|
||||
|
||||
const NumberSize int = 64
|
||||
const FloatSize int = 64
|
||||
|
||||
func (v *NumberValue) Type() ValueType {
|
||||
return NumberValueType
|
||||
func (v *FloatValue) Type() ValueType {
|
||||
return FloatValueType
|
||||
}
|
||||
|
||||
func (v *NumberValue) String() string {
|
||||
return strconv.FormatFloat(v.Number, 'g', -1, NumberSize)
|
||||
func (v *FloatValue) String() string {
|
||||
return strconv.FormatFloat(v.Number, 'g', -1, FloatSize)
|
||||
}
|
||||
|
||||
func (v *NumberValue) DebugString() string {
|
||||
func (v *FloatValue) DebugString() string {
|
||||
return v.String()
|
||||
}
|
||||
|
||||
func (v *NumberValue) Equals(other Value) bool {
|
||||
return other.Type() == NumberValueType && other.(*NumberValue).Number == v.Number
|
||||
func (v *FloatValue) Equals(other Value) bool {
|
||||
return other.Type() == FloatValueType && other.(*FloatValue).Number == v.Number
|
||||
}
|
||||
|
||||
func (v *NumberValue) Get(_ string) (Value, error) {
|
||||
func (v *FloatValue) Get(_ string) (Value, error) {
|
||||
// TODO maybe add standard functions for number values?
|
||||
return nil, errors.New("numbers have no properties")
|
||||
}
|
||||
|
||||
func (v *NumberValue) Clone() Value {
|
||||
return &NumberValue{
|
||||
func (v *FloatValue) Clone() Value {
|
||||
return &FloatValue{
|
||||
v.Number,
|
||||
}
|
||||
}
|
||||
|
||||
// IntegerValue whole number/integer values
|
||||
type IntegerValue struct {
|
||||
Number *big.Int
|
||||
}
|
||||
|
||||
func (v *IntegerValue) Type() ValueType {
|
||||
return IntegerValueType
|
||||
}
|
||||
|
||||
func (v *IntegerValue) String() string {
|
||||
return v.Number.String()
|
||||
}
|
||||
|
||||
func (v *IntegerValue) DebugString() string {
|
||||
return v.String()
|
||||
}
|
||||
|
||||
func (v *IntegerValue) Equals(other Value) bool {
|
||||
return other.Type() == IntegerValueType && other.(*IntegerValue).Number.Cmp(v.Number) == 0
|
||||
}
|
||||
|
||||
func (v *IntegerValue) Get(_ string) (Value, error) {
|
||||
return nil, errors.New("numbers have no properties")
|
||||
}
|
||||
|
||||
func (v *IntegerValue) Clone() Value {
|
||||
return &IntegerValue{
|
||||
new(big.Int).Set(v.Number),
|
||||
}
|
||||
}
|
||||
|
||||
type StringValue struct {
|
||||
Text string
|
||||
}
|
||||
|
|
@ -348,7 +386,7 @@ var StringPrototype = map[string]*BuiltinFunctionValue{
|
|||
Name: "length",
|
||||
Signature: &FunctionSignature{
|
||||
[]TypeSignature{},
|
||||
&NumberSignature{},
|
||||
&IntegerSignature{},
|
||||
},
|
||||
F: func(vm *VM, this Value, _ []Value) (Value, error) {
|
||||
return GoToValue(len(this.(*StringValue).Text)), nil
|
||||
|
|
@ -357,11 +395,11 @@ var StringPrototype = map[string]*BuiltinFunctionValue{
|
|||
"at": {
|
||||
Name: "at",
|
||||
Signature: &FunctionSignature{
|
||||
[]TypeSignature{&NumberSignature{}},
|
||||
[]TypeSignature{&IntegerSignature{}},
|
||||
&StringSignature{},
|
||||
},
|
||||
F: func(vm *VM, this Value, args []Value) (Value, error) {
|
||||
i := int(math.Floor(args[0].(*NumberValue).Number))
|
||||
i := int(args[0].(*IntegerValue).Number.Int64())
|
||||
|
||||
if i < 0 || i >= len(this.(*StringValue).Text) {
|
||||
return nil, errors.New("index is out of range")
|
||||
|
|
@ -450,13 +488,13 @@ var ListPrototype = map[string]*BuiltinFunctionValue{
|
|||
"at",
|
||||
&FunctionSignature{
|
||||
[]TypeSignature{
|
||||
&NumberSignature{},
|
||||
&IntegerSignature{},
|
||||
},
|
||||
&InnerSignature{},
|
||||
},
|
||||
func(_ *VM, this Value, p []Value) (Value, error) {
|
||||
items := this.(*ListValue).Items
|
||||
index := int(p[0].(*NumberValue).Number)
|
||||
index := int(p[0].(*IntegerValue).Number.Int64())
|
||||
|
||||
if index >= len(items) {
|
||||
return nil, errors.New(fmt.Sprintf("list index %x out of range", index))
|
||||
|
|
@ -471,13 +509,13 @@ var ListPrototype = map[string]*BuiltinFunctionValue{
|
|||
"put",
|
||||
&FunctionSignature{
|
||||
[]TypeSignature{
|
||||
&NumberSignature{}, &InnerSignature{},
|
||||
&FloatSignature{}, &InnerSignature{},
|
||||
},
|
||||
&NilSignature{},
|
||||
},
|
||||
func(_ *VM, this Value, args []Value) (Value, error) {
|
||||
l := this.(*ListValue)
|
||||
i := int(args[0].(*NumberValue).Number)
|
||||
i := int(args[0].(*FloatValue).Number)
|
||||
v := args[1]
|
||||
|
||||
// bounds check
|
||||
|
|
@ -496,7 +534,7 @@ var ListPrototype = map[string]*BuiltinFunctionValue{
|
|||
"length",
|
||||
&FunctionSignature{
|
||||
[]TypeSignature{},
|
||||
&NumberSignature{},
|
||||
&IntegerSignature{},
|
||||
},
|
||||
func(_ *VM, this Value, _ []Value) (Value, error) {
|
||||
return GoToValue(len(this.(*ListValue).Items)), nil
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue