Fix VM memory allocation optimizations by reducing what we allocate on the heap
This commit is contained in:
@@ -25,7 +25,7 @@ func (ao *Array) PopLeft() Object {
|
||||
ao.Elements = ao.Elements[1:]
|
||||
return e
|
||||
}
|
||||
return &Null{}
|
||||
return Null{}
|
||||
}
|
||||
|
||||
func (ao *Array) PopRight() Object {
|
||||
@@ -34,7 +34,7 @@ func (ao *Array) PopRight() Object {
|
||||
ao.Elements = ao.Elements[:(len(ao.Elements) - 1)]
|
||||
return e
|
||||
}
|
||||
return &Null{}
|
||||
return Null{}
|
||||
}
|
||||
|
||||
func (ao *Array) Prepend(obj Object) {
|
||||
@@ -89,7 +89,7 @@ func (ao *Array) Mul(other Object) (Object, error) {
|
||||
}
|
||||
|
||||
var elements []Object
|
||||
N := int(other.(*Integer).Value)
|
||||
N := int(other.(Integer).Value)
|
||||
for i := 0; i < N; i++ {
|
||||
elements = append(elements, ao.Elements...)
|
||||
}
|
||||
@@ -102,10 +102,10 @@ func (ao *Array) Get(index Object) (Object, error) {
|
||||
return nil, fmt.Errorf("invalid type for array index, expected Integer got %s", index.Type())
|
||||
}
|
||||
|
||||
i := index.(*Integer).Value
|
||||
i := index.(Integer).Value
|
||||
N := int64(len(ao.Elements))
|
||||
if i < 0 || i >= N {
|
||||
return &Null{}, nil
|
||||
return Null{}, nil
|
||||
}
|
||||
|
||||
return ao.Elements[i], nil
|
||||
@@ -116,7 +116,7 @@ func (ao *Array) Set(index, other Object) error {
|
||||
return fmt.Errorf("invalid type for array index, expected Integer got %s", index.Type())
|
||||
}
|
||||
|
||||
i := index.(*Integer).Value
|
||||
i := index.(Integer).Value
|
||||
N := int64(len(ao.Elements))
|
||||
if i < 0 || i >= N {
|
||||
return fmt.Errorf("index out of bounds %d with array length %d", i, N)
|
||||
|
||||
@@ -8,53 +8,53 @@ type Boolean struct {
|
||||
Value bool
|
||||
}
|
||||
|
||||
func (b *Boolean) Bool() bool {
|
||||
func (b Boolean) Bool() bool {
|
||||
return b.Value
|
||||
}
|
||||
|
||||
func (b *Boolean) Type() Type {
|
||||
func (b Boolean) Type() Type {
|
||||
return BooleanType
|
||||
}
|
||||
|
||||
func (b *Boolean) Inspect() string {
|
||||
func (b Boolean) Inspect() string {
|
||||
return fmt.Sprintf("%t", b.Value)
|
||||
}
|
||||
|
||||
func (b *Boolean) Clone() Object {
|
||||
return &Boolean{Value: b.Value}
|
||||
func (b Boolean) Clone() Object {
|
||||
return Boolean{Value: b.Value}
|
||||
}
|
||||
|
||||
func (b *Boolean) String() string {
|
||||
func (b Boolean) String() string {
|
||||
return b.Inspect()
|
||||
}
|
||||
|
||||
func (b *Boolean) Int() int {
|
||||
func (b Boolean) Int() int {
|
||||
if b.Value {
|
||||
return 1
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
func (b *Boolean) LogicalAnd(other Object) (Object, error) {
|
||||
func (b Boolean) LogicalAnd(other Object) (Object, error) {
|
||||
if !AssertTypes(other, BooleanType, IntegerType) {
|
||||
return nil, NewBinaryOpError(b, other, "&&")
|
||||
}
|
||||
return &Boolean{b.Value && other.Bool()}, nil
|
||||
return Boolean{b.Value && other.Bool()}, nil
|
||||
}
|
||||
|
||||
func (b *Boolean) LogicalOr(other Object) (Object, error) {
|
||||
func (b Boolean) LogicalOr(other Object) (Object, error) {
|
||||
if !AssertTypes(other, BooleanType, IntegerType) {
|
||||
return nil, NewBinaryOpError(b, other, "||")
|
||||
}
|
||||
return &Boolean{b.Value || other.Bool()}, nil
|
||||
return Boolean{b.Value || other.Bool()}, nil
|
||||
}
|
||||
|
||||
func (b *Boolean) LogicalNot() Object {
|
||||
return &Boolean{!b.Value}
|
||||
func (b Boolean) LogicalNot() Object {
|
||||
return Boolean{!b.Value}
|
||||
}
|
||||
|
||||
func (b *Boolean) Compare(other Object) int {
|
||||
if obj, ok := other.(*Boolean); ok {
|
||||
func (b Boolean) Compare(other Object) int {
|
||||
if obj, ok := other.(Boolean); ok {
|
||||
return b.Int() - obj.Int()
|
||||
}
|
||||
return 1
|
||||
|
||||
@@ -39,7 +39,7 @@ func (e *Environment) ExportedHash() *Hash {
|
||||
pairs := make(map[HashKey]HashPair)
|
||||
for k, v := range e.store {
|
||||
if unicode.IsUpper(rune(k[0])) {
|
||||
s := &String{Value: k}
|
||||
s := String{Value: k}
|
||||
pairs[s.HashKey()] = HashPair{Key: s, Value: v}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,22 +6,22 @@ type Error struct {
|
||||
Message string
|
||||
}
|
||||
|
||||
func (e *Error) Bool() bool {
|
||||
func (e Error) Bool() bool {
|
||||
return false
|
||||
}
|
||||
|
||||
func (e *Error) Type() Type {
|
||||
func (e Error) Type() Type {
|
||||
return ErrorType
|
||||
}
|
||||
|
||||
func (e *Error) Inspect() string {
|
||||
func (e Error) Inspect() string {
|
||||
return "Error: " + e.Message
|
||||
}
|
||||
|
||||
func (e *Error) Clone() Object {
|
||||
return &Error{Message: e.Message}
|
||||
func (e Error) Clone() Object {
|
||||
return Error{Message: e.Message}
|
||||
}
|
||||
|
||||
func (e *Error) String() string {
|
||||
func (e Error) String() string {
|
||||
return e.Message
|
||||
}
|
||||
|
||||
@@ -12,15 +12,15 @@ type Function struct {
|
||||
Env *Environment
|
||||
}
|
||||
|
||||
func (f *Function) Bool() bool {
|
||||
func (f Function) Bool() bool {
|
||||
return false
|
||||
}
|
||||
|
||||
func (f *Function) Type() Type {
|
||||
func (f Function) Type() Type {
|
||||
return FunctionType
|
||||
}
|
||||
|
||||
func (f *Function) Inspect() string {
|
||||
func (f Function) Inspect() string {
|
||||
var out bytes.Buffer
|
||||
|
||||
params := []string{}
|
||||
@@ -38,7 +38,7 @@ func (f *Function) Inspect() string {
|
||||
return out.String()
|
||||
}
|
||||
|
||||
func (f *Function) String() string {
|
||||
func (f Function) String() string {
|
||||
return f.Inspect()
|
||||
}
|
||||
|
||||
@@ -46,18 +46,18 @@ type ReturnValue struct {
|
||||
Value Object
|
||||
}
|
||||
|
||||
func (rv *ReturnValue) Bool() bool {
|
||||
func (rv ReturnValue) Bool() bool {
|
||||
return true
|
||||
}
|
||||
|
||||
func (rv *ReturnValue) Type() Type {
|
||||
func (rv ReturnValue) Type() Type {
|
||||
return ReturnType
|
||||
}
|
||||
|
||||
func (rv *ReturnValue) Inspect() string {
|
||||
func (rv ReturnValue) Inspect() string {
|
||||
return rv.Value.Inspect()
|
||||
}
|
||||
|
||||
func (rv *ReturnValue) String() string {
|
||||
func (rv ReturnValue) String() string {
|
||||
return rv.Inspect()
|
||||
}
|
||||
|
||||
@@ -12,7 +12,7 @@ type HashKey struct {
|
||||
Value uint64
|
||||
}
|
||||
|
||||
func (b *Boolean) HashKey() HashKey {
|
||||
func (b Boolean) HashKey() HashKey {
|
||||
var value uint64
|
||||
|
||||
if b.Value {
|
||||
@@ -24,11 +24,11 @@ func (b *Boolean) HashKey() HashKey {
|
||||
return HashKey{Type: b.Type(), Value: value}
|
||||
}
|
||||
|
||||
func (i *Integer) HashKey() HashKey {
|
||||
func (i Integer) HashKey() HashKey {
|
||||
return HashKey{Type: i.Type(), Value: uint64(i.Value)}
|
||||
}
|
||||
|
||||
func (s *String) HashKey() HashKey {
|
||||
func (s String) HashKey() HashKey {
|
||||
h := fnv.New64a()
|
||||
h.Write([]byte(s.Value))
|
||||
|
||||
@@ -98,7 +98,7 @@ func (h *Hash) Get(index Object) (Object, error) {
|
||||
|
||||
pair, found := h.Pairs[key.HashKey()]
|
||||
if !found {
|
||||
return &Null{}, nil
|
||||
return Null{}, nil
|
||||
}
|
||||
|
||||
return pair.Value, nil
|
||||
|
||||
@@ -6,44 +6,44 @@ type Integer struct {
|
||||
Value int64
|
||||
}
|
||||
|
||||
func (i *Integer) Bool() bool {
|
||||
func (i Integer) Bool() bool {
|
||||
return i.Value != 0
|
||||
}
|
||||
|
||||
func (i *Integer) Type() Type {
|
||||
func (i Integer) Type() Type {
|
||||
return IntegerType
|
||||
}
|
||||
|
||||
func (i *Integer) Inspect() string {
|
||||
func (i Integer) Inspect() string {
|
||||
return fmt.Sprintf("%d", i.Value)
|
||||
}
|
||||
|
||||
func (i *Integer) Clone() Object {
|
||||
return &Integer{Value: i.Value}
|
||||
func (i Integer) Clone() Object {
|
||||
return Integer{Value: i.Value}
|
||||
}
|
||||
|
||||
func (i *Integer) String() string {
|
||||
func (i Integer) String() string {
|
||||
return i.Inspect()
|
||||
}
|
||||
|
||||
func (i *Integer) Add(other Object) (Object, error) {
|
||||
func (i Integer) Add(other Object) (Object, error) {
|
||||
if !AssertTypes(other, IntegerType) {
|
||||
return nil, NewBinaryOpError(i, other, "+")
|
||||
}
|
||||
return &Integer{i.Value + other.(*Integer).Value}, nil
|
||||
return Integer{i.Value + other.(Integer).Value}, nil
|
||||
}
|
||||
|
||||
func (i *Integer) Sub(other Object) (Object, error) {
|
||||
func (i Integer) Sub(other Object) (Object, error) {
|
||||
if !AssertTypes(other, IntegerType) {
|
||||
return nil, NewBinaryOpError(i, other, "-")
|
||||
}
|
||||
return &Integer{i.Value - other.(*Integer).Value}, nil
|
||||
return Integer{i.Value - other.(Integer).Value}, nil
|
||||
}
|
||||
|
||||
func (i *Integer) Mul(other Object) (Object, error) {
|
||||
func (i Integer) Mul(other Object) (Object, error) {
|
||||
switch other.Type() {
|
||||
case IntegerType:
|
||||
return &Integer{i.Value * other.(*Integer).Value}, nil
|
||||
return Integer{i.Value * other.(Integer).Value}, nil
|
||||
case StringType:
|
||||
return other.(Mul).Mul(i)
|
||||
case ArrayType:
|
||||
@@ -53,69 +53,69 @@ func (i *Integer) Mul(other Object) (Object, error) {
|
||||
}
|
||||
}
|
||||
|
||||
func (i *Integer) Div(other Object) (Object, error) {
|
||||
func (i Integer) Div(other Object) (Object, error) {
|
||||
if !AssertTypes(other, IntegerType) {
|
||||
return nil, NewBinaryOpError(i, other, "/")
|
||||
}
|
||||
return &Integer{i.Value / other.(*Integer).Value}, nil
|
||||
return Integer{i.Value / other.(Integer).Value}, nil
|
||||
}
|
||||
|
||||
func (i *Integer) Mod(other Object) (Object, error) {
|
||||
func (i Integer) Mod(other Object) (Object, error) {
|
||||
if !AssertTypes(other, IntegerType) {
|
||||
return nil, NewBinaryOpError(i, other, "%")
|
||||
}
|
||||
return &Integer{i.Value % other.(*Integer).Value}, nil
|
||||
return Integer{i.Value % other.(Integer).Value}, nil
|
||||
}
|
||||
|
||||
func (i *Integer) BitwiseOr(other Object) (Object, error) {
|
||||
func (i Integer) BitwiseOr(other Object) (Object, error) {
|
||||
if !AssertTypes(other, IntegerType) {
|
||||
return nil, NewBinaryOpError(i, other, "|")
|
||||
}
|
||||
return &Integer{i.Value | other.(*Integer).Value}, nil
|
||||
return Integer{i.Value | other.(Integer).Value}, nil
|
||||
}
|
||||
|
||||
func (i *Integer) BitwiseXor(other Object) (Object, error) {
|
||||
func (i Integer) BitwiseXor(other Object) (Object, error) {
|
||||
if !AssertTypes(other, IntegerType) {
|
||||
return nil, NewBinaryOpError(i, other, "^")
|
||||
}
|
||||
return &Integer{i.Value ^ other.(*Integer).Value}, nil
|
||||
return Integer{i.Value ^ other.(Integer).Value}, nil
|
||||
}
|
||||
|
||||
func (i *Integer) BitwiseAnd(other Object) (Object, error) {
|
||||
func (i Integer) BitwiseAnd(other Object) (Object, error) {
|
||||
if !AssertTypes(other, IntegerType) {
|
||||
return nil, NewBinaryOpError(i, other, "&")
|
||||
return nil, NewBinaryOpError(i, other, "")
|
||||
}
|
||||
return &Integer{i.Value & other.(*Integer).Value}, nil
|
||||
return Integer{i.Value & other.(Integer).Value}, nil
|
||||
}
|
||||
|
||||
func (i *Integer) BitwiseNot() Object {
|
||||
return &Integer{^i.Value}
|
||||
func (i Integer) BitwiseNot() Object {
|
||||
return Integer{^i.Value}
|
||||
}
|
||||
|
||||
func (i *Integer) LeftShift(other Object) (Object, error) {
|
||||
func (i Integer) LeftShift(other Object) (Object, error) {
|
||||
if !AssertTypes(other, IntegerType) {
|
||||
return nil, NewBinaryOpError(i, other, "<<")
|
||||
}
|
||||
return &Integer{i.Value << other.(*Integer).Value}, nil
|
||||
return Integer{i.Value << other.(Integer).Value}, nil
|
||||
}
|
||||
|
||||
func (i *Integer) RightShift(other Object) (Object, error) {
|
||||
func (i Integer) RightShift(other Object) (Object, error) {
|
||||
if !AssertTypes(other, IntegerType) {
|
||||
return nil, NewBinaryOpError(i, other, ">>")
|
||||
}
|
||||
return &Integer{i.Value >> other.(*Integer).Value}, nil
|
||||
return Integer{i.Value >> other.(Integer).Value}, nil
|
||||
}
|
||||
|
||||
func (i *Integer) LogicalNot() Object {
|
||||
return &Boolean{!i.Bool()}
|
||||
func (i Integer) LogicalNot() Object {
|
||||
return Boolean{!i.Bool()}
|
||||
}
|
||||
|
||||
func (i *Integer) Negate() Object {
|
||||
return &Integer{-i.Value}
|
||||
func (i Integer) Negate() Object {
|
||||
return Integer{-i.Value}
|
||||
}
|
||||
|
||||
func (i *Integer) Compare(other Object) int {
|
||||
if obj, ok := other.(*Integer); ok {
|
||||
func (i Integer) Compare(other Object) int {
|
||||
if obj, ok := other.(Integer); ok {
|
||||
switch {
|
||||
case i.Value < obj.Value:
|
||||
return -1
|
||||
|
||||
@@ -24,7 +24,7 @@ func (m Module) Inspect() string {
|
||||
return fmt.Sprintf("<module '%s'>", m.Name)
|
||||
}
|
||||
|
||||
func (m *Module) Get(index Object) (Object, error) {
|
||||
func (m Module) Get(index Object) (Object, error) {
|
||||
key, ok := index.(Hashable)
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("invalid module attribute %s", index.Type())
|
||||
@@ -32,7 +32,7 @@ func (m *Module) Get(index Object) (Object, error) {
|
||||
|
||||
attr, found := m.Attrs.(*Hash).Pairs[key.HashKey()]
|
||||
if !found {
|
||||
return &Null{}, nil
|
||||
return Null{}, nil
|
||||
}
|
||||
|
||||
return attr.Value, nil
|
||||
|
||||
@@ -2,28 +2,28 @@ package object
|
||||
|
||||
type Null struct{}
|
||||
|
||||
func (n *Null) Bool() bool {
|
||||
func (n Null) Bool() bool {
|
||||
return false
|
||||
}
|
||||
|
||||
func (n *Null) Type() Type {
|
||||
func (n Null) Type() Type {
|
||||
return NullType
|
||||
}
|
||||
|
||||
func (n *Null) Inspect() string {
|
||||
func (n Null) Inspect() string {
|
||||
return "null"
|
||||
}
|
||||
|
||||
func (n *Null) String() string {
|
||||
func (n Null) String() string {
|
||||
return n.Inspect()
|
||||
}
|
||||
|
||||
func (n *Null) LogicalNot() Object {
|
||||
return &Boolean{!n.Bool()}
|
||||
func (n Null) LogicalNot() Object {
|
||||
return Boolean{!n.Bool()}
|
||||
}
|
||||
|
||||
func (n *Null) Compare(other Object) int {
|
||||
if _, ok := other.(*Null); ok {
|
||||
func (n Null) Compare(other Object) int {
|
||||
if _, ok := other.(Null); ok {
|
||||
return 0
|
||||
}
|
||||
return 1
|
||||
|
||||
@@ -3,10 +3,10 @@ package object
|
||||
import "testing"
|
||||
|
||||
func TestStringHashKey(t *testing.T) {
|
||||
hello1 := &String{Value: "Hello World"}
|
||||
hello2 := &String{Value: "Hello World"}
|
||||
diff1 := &String{Value: "My name is johnny"}
|
||||
diff2 := &String{Value: "My name is johnny"}
|
||||
hello1 := String{Value: "Hello World"}
|
||||
hello2 := String{Value: "Hello World"}
|
||||
diff1 := String{Value: "My name is johnny"}
|
||||
diff2 := String{Value: "My name is johnny"}
|
||||
|
||||
if hello1.HashKey() != hello2.HashKey() {
|
||||
t.Errorf("string with same content have different hash keys")
|
||||
|
||||
@@ -10,59 +10,59 @@ type String struct {
|
||||
Value string
|
||||
}
|
||||
|
||||
func (s *String) Len() int {
|
||||
func (s String) Len() int {
|
||||
return utf8.RuneCountInString(s.Value)
|
||||
}
|
||||
|
||||
func (s *String) Bool() bool {
|
||||
func (s String) Bool() bool {
|
||||
return s.Value != ""
|
||||
}
|
||||
|
||||
func (s *String) Type() Type {
|
||||
func (s String) Type() Type {
|
||||
return StringType
|
||||
}
|
||||
|
||||
func (s *String) Inspect() string {
|
||||
func (s String) Inspect() string {
|
||||
return fmt.Sprintf("%#v", s.Value)
|
||||
}
|
||||
|
||||
func (s *String) Clone() Object {
|
||||
return &String{Value: s.Value}
|
||||
func (s String) Clone() Object {
|
||||
return String{Value: s.Value}
|
||||
}
|
||||
|
||||
func (s *String) String() string {
|
||||
func (s String) String() string {
|
||||
return s.Value
|
||||
}
|
||||
|
||||
func (s *String) Add(other Object) (Object, error) {
|
||||
func (s String) Add(other Object) (Object, error) {
|
||||
if !AssertTypes(other, StringType) {
|
||||
return nil, NewBinaryOpError(s, other, "+")
|
||||
}
|
||||
return &String{s.Value + other.(*String).Value}, nil
|
||||
return String{s.Value + other.(String).Value}, nil
|
||||
}
|
||||
|
||||
func (s *String) Mul(other Object) (Object, error) {
|
||||
func (s String) Mul(other Object) (Object, error) {
|
||||
if !AssertTypes(other, IntegerType) {
|
||||
return nil, NewBinaryOpError(s, other, "*")
|
||||
}
|
||||
return &String{strings.Repeat(s.Value, int(other.(*Integer).Value))}, nil
|
||||
return String{strings.Repeat(s.Value, int(other.(Integer).Value))}, nil
|
||||
}
|
||||
|
||||
func (s *String) Get(index Object) (Object, error) {
|
||||
func (s String) Get(index Object) (Object, error) {
|
||||
if !AssertTypes(index, IntegerType) {
|
||||
return nil, fmt.Errorf("invalid type for string index, expected Integer got %s", index.Type())
|
||||
}
|
||||
|
||||
i := int(index.(*Integer).Value)
|
||||
i := int(index.(Integer).Value)
|
||||
if i < 0 || i >= len(s.Value) {
|
||||
return &String{}, nil
|
||||
return String{}, nil
|
||||
}
|
||||
|
||||
return &String{string(s.Value[i])}, nil
|
||||
return String{string(s.Value[i])}, nil
|
||||
}
|
||||
|
||||
func (s *String) Compare(other Object) int {
|
||||
if obj, ok := other.(*String); ok {
|
||||
func (s String) Compare(other Object) int {
|
||||
if obj, ok := other.(String); ok {
|
||||
switch {
|
||||
case s.Value < obj.Value:
|
||||
return -1
|
||||
|
||||
Reference in New Issue
Block a user