refactor objects
This commit is contained in:
@@ -14,8 +14,8 @@ func HashOf(args ...object.Object) object.Object {
|
|||||||
return newError(err.Error())
|
return newError(err.Error())
|
||||||
}
|
}
|
||||||
|
|
||||||
if hash, ok := args[0].(object.Hashable); ok {
|
if hash, ok := args[0].(object.Hasher); ok {
|
||||||
return object.Integer{Value: int64(hash.HashKey().Value)}
|
return object.Integer{Value: int64(hash.Hash().Value)}
|
||||||
}
|
}
|
||||||
|
|
||||||
return newError("TypeError: hash() expected argument #1 to be hashable")
|
return newError("TypeError: hash() expected argument #1 to be hashable")
|
||||||
|
|||||||
@@ -61,8 +61,8 @@ func Eval(node ast.Node, env *object.Environment) object.Object {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if ident, ok := node.Left.(*ast.Identifier); ok {
|
if ident, ok := node.Left.(*ast.Identifier); ok {
|
||||||
if immutable, ok := value.(object.Immutable); ok {
|
if obj, ok := value.(object.Copyable); ok {
|
||||||
env.Set(ident.Value, immutable.Clone())
|
env.Set(ident.Value, obj.Copy())
|
||||||
} else {
|
} else {
|
||||||
env.Set(ident.Value, value)
|
env.Set(ident.Value, value)
|
||||||
}
|
}
|
||||||
@@ -105,8 +105,8 @@ func Eval(node ast.Node, env *object.Environment) object.Object {
|
|||||||
if isError(key) {
|
if isError(key) {
|
||||||
return key
|
return key
|
||||||
}
|
}
|
||||||
if hashKey, ok := key.(object.Hashable); ok {
|
if hashKey, ok := key.(object.Hasher); ok {
|
||||||
hashed := hashKey.HashKey()
|
hashed := hashKey.Hash()
|
||||||
hash.Pairs[hashed] = object.HashPair{Key: key, Value: value}
|
hash.Pairs[hashed] = object.HashPair{Key: key, Value: value}
|
||||||
} else {
|
} else {
|
||||||
return newError("cannot index hash with %T", key)
|
return newError("cannot index hash with %T", key)
|
||||||
@@ -630,12 +630,12 @@ func evalStringIndexExpression(str, index object.Object) object.Object {
|
|||||||
func evalHashIndexExpression(hash, index object.Object) object.Object {
|
func evalHashIndexExpression(hash, index object.Object) object.Object {
|
||||||
hashObject := hash.(*object.Hash)
|
hashObject := hash.(*object.Hash)
|
||||||
|
|
||||||
key, ok := index.(object.Hashable)
|
key, ok := index.(object.Hasher)
|
||||||
if !ok {
|
if !ok {
|
||||||
return newError("unusable as hash key: %s", index.Type())
|
return newError("unusable as hash key: %s", index.Type())
|
||||||
}
|
}
|
||||||
|
|
||||||
pair, ok := hashObject.Pairs[key.HashKey()]
|
pair, ok := hashObject.Pairs[key.Hash()]
|
||||||
if !ok {
|
if !ok {
|
||||||
return NULL
|
return NULL
|
||||||
}
|
}
|
||||||
@@ -664,7 +664,7 @@ func evalHashLiteral(node *ast.HashLiteral, env *object.Environment) object.Obje
|
|||||||
return key
|
return key
|
||||||
}
|
}
|
||||||
|
|
||||||
hashKey, ok := key.(object.Hashable)
|
hashKey, ok := key.(object.Hasher)
|
||||||
if !ok {
|
if !ok {
|
||||||
return newError("unusable as hash key: %s", key.Type())
|
return newError("unusable as hash key: %s", key.Type())
|
||||||
}
|
}
|
||||||
@@ -674,7 +674,7 @@ func evalHashLiteral(node *ast.HashLiteral, env *object.Environment) object.Obje
|
|||||||
return value
|
return value
|
||||||
}
|
}
|
||||||
|
|
||||||
hashed := hashKey.HashKey()
|
hashed := hashKey.Hash()
|
||||||
pairs[hashed] = object.HashPair{
|
pairs[hashed] = object.HashPair{
|
||||||
Key: key,
|
Key: key,
|
||||||
Value: value,
|
Value: value,
|
||||||
|
|||||||
@@ -640,12 +640,12 @@ func TestHashLiterals(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
expected := map[object.HashKey]int64{
|
expected := map[object.HashKey]int64{
|
||||||
(object.String{Value: "one"}).HashKey(): 1,
|
(object.String{Value: "one"}).Hash(): 1,
|
||||||
(object.String{Value: "two"}).HashKey(): 2,
|
(object.String{Value: "two"}).Hash(): 2,
|
||||||
(object.String{Value: "three"}).HashKey(): 3,
|
(object.String{Value: "three"}).Hash(): 3,
|
||||||
(object.Integer{Value: 4}).HashKey(): 4,
|
(object.Integer{Value: 4}).Hash(): 4,
|
||||||
TRUE.HashKey(): 5,
|
TRUE.Hash(): 5,
|
||||||
FALSE.HashKey(): 6,
|
FALSE.Hash(): 6,
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(result.Pairs) != len(expected) {
|
if len(result.Pairs) != len(expected) {
|
||||||
@@ -671,8 +671,8 @@ func TestHashMerging(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
expected := map[object.HashKey]int64{
|
expected := map[object.HashKey]int64{
|
||||||
(object.String{Value: "a"}).HashKey(): 1,
|
(object.String{Value: "a"}).Hash(): 1,
|
||||||
(object.String{Value: "b"}).HashKey(): 2,
|
(object.String{Value: "b"}).Hash(): 2,
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(result.Pairs) != len(expected) {
|
if len(result.Pairs) != len(expected) {
|
||||||
|
|||||||
@@ -32,10 +32,24 @@ func (b Boolean) Inspect() string {
|
|||||||
return fmt.Sprintf("%t", b.Value)
|
return fmt.Sprintf("%t", b.Value)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (b Boolean) Clone() Object {
|
// Copy implements the Copyable interface
|
||||||
|
func (b Boolean) Copy() Object {
|
||||||
return Boolean{Value: b.Value}
|
return Boolean{Value: b.Value}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Hash implements the Hasher interface
|
||||||
|
func (b Boolean) Hash() HashKey {
|
||||||
|
var value uint64
|
||||||
|
|
||||||
|
if b.Value {
|
||||||
|
value = 1
|
||||||
|
} else {
|
||||||
|
value = 0
|
||||||
|
}
|
||||||
|
|
||||||
|
return HashKey{Type: b.Type(), Value: value}
|
||||||
|
}
|
||||||
|
|
||||||
func (b Boolean) String() string {
|
func (b Boolean) String() string {
|
||||||
return b.Inspect()
|
return b.Inspect()
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,24 +4,31 @@ import "unicode"
|
|||||||
|
|
||||||
func NewEnclosedEnvironment(outer *Environment) *Environment {
|
func NewEnclosedEnvironment(outer *Environment) *Environment {
|
||||||
env := NewEnvironment()
|
env := NewEnvironment()
|
||||||
env.outer = outer
|
env.parent = outer
|
||||||
return env
|
return env
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewEnvironment() *Environment {
|
func NewEnvironment() *Environment {
|
||||||
s := make(map[string]Object)
|
s := make(map[string]Object)
|
||||||
return &Environment{store: s, outer: nil}
|
return &Environment{store: s, parent: nil}
|
||||||
}
|
}
|
||||||
|
|
||||||
type Environment struct {
|
type Environment struct {
|
||||||
store map[string]Object
|
store map[string]Object
|
||||||
outer *Environment
|
parent *Environment
|
||||||
|
}
|
||||||
|
|
||||||
|
// New creates a new copy of the environment with the current environment as parent
|
||||||
|
func (e *Environment) New() *Environment {
|
||||||
|
env := NewEnvironment()
|
||||||
|
env.parent = e
|
||||||
|
return env
|
||||||
}
|
}
|
||||||
|
|
||||||
func (e *Environment) Get(name string) (Object, bool) {
|
func (e *Environment) Get(name string) (Object, bool) {
|
||||||
obj, ok := e.store[name]
|
obj, ok := e.store[name]
|
||||||
if !ok && e.outer != nil {
|
if !ok && e.parent != nil {
|
||||||
obj, ok = e.outer.Get(name)
|
obj, ok = e.parent.Get(name)
|
||||||
}
|
}
|
||||||
return obj, ok
|
return obj, ok
|
||||||
}
|
}
|
||||||
@@ -40,7 +47,7 @@ func (e *Environment) ExportedHash() *Hash {
|
|||||||
for k, v := range e.store {
|
for k, v := range e.store {
|
||||||
if unicode.IsUpper(rune(k[0])) {
|
if unicode.IsUpper(rune(k[0])) {
|
||||||
s := String{Value: k}
|
s := String{Value: k}
|
||||||
pairs[s.HashKey()] = HashPair{Key: s, Value: v}
|
pairs[s.Hash()] = HashPair{Key: s, Value: v}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return &Hash{Pairs: pairs}
|
return &Hash{Pairs: pairs}
|
||||||
|
|||||||
@@ -18,7 +18,8 @@ func (e Error) Inspect() string {
|
|||||||
return "Error: " + e.Message
|
return "Error: " + e.Message
|
||||||
}
|
}
|
||||||
|
|
||||||
func (e Error) Clone() Object {
|
// Copy implements the Copyable interface
|
||||||
|
func (e Error) Copy() Object {
|
||||||
return Error{Message: e.Message}
|
return Error{Message: e.Message}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -3,7 +3,6 @@ package object
|
|||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"fmt"
|
"fmt"
|
||||||
"hash/fnv"
|
|
||||||
"strings"
|
"strings"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -12,29 +11,6 @@ type HashKey struct {
|
|||||||
Value uint64
|
Value uint64
|
||||||
}
|
}
|
||||||
|
|
||||||
func (b Boolean) HashKey() HashKey {
|
|
||||||
var value uint64
|
|
||||||
|
|
||||||
if b.Value {
|
|
||||||
value = 1
|
|
||||||
} else {
|
|
||||||
value = 0
|
|
||||||
}
|
|
||||||
|
|
||||||
return HashKey{Type: b.Type(), Value: value}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (i Integer) HashKey() HashKey {
|
|
||||||
return HashKey{Type: i.Type(), Value: uint64(i.Value)}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s String) HashKey() HashKey {
|
|
||||||
h := fnv.New64a()
|
|
||||||
h.Write([]byte(s.Value))
|
|
||||||
|
|
||||||
return HashKey{Type: s.Type(), Value: h.Sum64()}
|
|
||||||
}
|
|
||||||
|
|
||||||
type HashPair struct {
|
type HashPair struct {
|
||||||
Key Object
|
Key Object
|
||||||
Value Object
|
Value Object
|
||||||
@@ -91,12 +67,12 @@ func (h *Hash) Add(other Object) (Object, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (h *Hash) Get(index Object) (Object, error) {
|
func (h *Hash) Get(index Object) (Object, error) {
|
||||||
key, ok := index.(Hashable)
|
key, ok := index.(Hasher)
|
||||||
if !ok {
|
if !ok {
|
||||||
return nil, fmt.Errorf("invalid hash key %s", index.Type())
|
return nil, fmt.Errorf("invalid hash key %s", index.Type())
|
||||||
}
|
}
|
||||||
|
|
||||||
pair, found := h.Pairs[key.HashKey()]
|
pair, found := h.Pairs[key.Hash()]
|
||||||
if !found {
|
if !found {
|
||||||
return Null{}, nil
|
return Null{}, nil
|
||||||
}
|
}
|
||||||
@@ -105,12 +81,12 @@ func (h *Hash) Get(index Object) (Object, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (h *Hash) Set(index, other Object) error {
|
func (h *Hash) Set(index, other Object) error {
|
||||||
key, ok := index.(Hashable)
|
key, ok := index.(Hasher)
|
||||||
if !ok {
|
if !ok {
|
||||||
return fmt.Errorf("invalid hash key %s", index.Type())
|
return fmt.Errorf("invalid hash key %s", index.Type())
|
||||||
}
|
}
|
||||||
|
|
||||||
h.Pairs[key.HashKey()] = HashPair{Key: index, Value: other}
|
h.Pairs[key.Hash()] = HashPair{Key: index, Value: other}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
@@ -122,8 +98,8 @@ func (h *Hash) Compare(other Object) int {
|
|||||||
}
|
}
|
||||||
for _, pair := range h.Pairs {
|
for _, pair := range h.Pairs {
|
||||||
left := pair.Value
|
left := pair.Value
|
||||||
hashed := left.(Hashable)
|
hashed := left.(Hasher)
|
||||||
right, ok := obj.Pairs[hashed.HashKey()]
|
right, ok := obj.Pairs[hashed.Hash()]
|
||||||
if !ok {
|
if !ok {
|
||||||
return -1
|
return -1
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -18,10 +18,15 @@ func (i Integer) Inspect() string {
|
|||||||
return fmt.Sprintf("%d", i.Value)
|
return fmt.Sprintf("%d", i.Value)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (i Integer) Clone() Object {
|
func (i Integer) Copy() Object {
|
||||||
return Integer{Value: i.Value}
|
return Integer{Value: i.Value}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Hash implements the Hasher interface
|
||||||
|
func (i Integer) Hash() HashKey {
|
||||||
|
return HashKey{Type: i.Type(), Value: uint64(i.Value)}
|
||||||
|
}
|
||||||
|
|
||||||
func (i Integer) String() string {
|
func (i Integer) String() string {
|
||||||
return i.Inspect()
|
return i.Inspect()
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -25,12 +25,12 @@ func (m Module) Inspect() string {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (m Module) Get(index Object) (Object, error) {
|
func (m Module) Get(index Object) (Object, error) {
|
||||||
key, ok := index.(Hashable)
|
key, ok := index.(Hasher)
|
||||||
if !ok {
|
if !ok {
|
||||||
return nil, fmt.Errorf("invalid module attribute %s", index.Type())
|
return nil, fmt.Errorf("invalid module attribute %s", index.Type())
|
||||||
}
|
}
|
||||||
|
|
||||||
attr, found := m.Attrs.(*Hash).Pairs[key.HashKey()]
|
attr, found := m.Attrs.(*Hash).Pairs[key.Hash()]
|
||||||
if !found {
|
if !found {
|
||||||
return Null{}, nil
|
return Null{}, nil
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -54,17 +54,14 @@ func (t Type) String() string {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Comparable is the interface for comparing two Object and their underlying
|
// Comparable is the interface for objects to implement suitable comparisons
|
||||||
// values. It is the responsibility of the caller (left) to check for types.
|
|
||||||
// Returns `true` iif the types and values are identical, `false` otherwise.
|
|
||||||
type Comparable interface {
|
type Comparable interface {
|
||||||
Compare(other Object) int
|
Compare(other Object) int
|
||||||
}
|
}
|
||||||
|
|
||||||
// Immutable is the interface for all immutable objects which must implement
|
// Copyable is the interface for creating copies of objects
|
||||||
// the Clone() method used by binding names to values.
|
type Copyable interface {
|
||||||
type Immutable interface {
|
Copy() Object
|
||||||
Clone() Object
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Object represents a value and implementations are expected to implement
|
// Object represents a value and implementations are expected to implement
|
||||||
@@ -76,10 +73,9 @@ type Object interface {
|
|||||||
Inspect() string
|
Inspect() string
|
||||||
}
|
}
|
||||||
|
|
||||||
// Hashable is the interface for all hashable objects which must implement
|
// Hasher is the interface for objects to provide suitable hash keys
|
||||||
// the HashKey() method which returns a HashKey result.
|
type Hasher interface {
|
||||||
type Hashable interface {
|
Hash() HashKey
|
||||||
HashKey() HashKey
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// BuiltinFunction represents the builtin function type
|
// BuiltinFunction represents the builtin function type
|
||||||
|
|||||||
@@ -8,15 +8,15 @@ func TestStringHashKey(t *testing.T) {
|
|||||||
diff1 := String{Value: "My name is johnny"}
|
diff1 := String{Value: "My name is johnny"}
|
||||||
diff2 := String{Value: "My name is johnny"}
|
diff2 := String{Value: "My name is johnny"}
|
||||||
|
|
||||||
if hello1.HashKey() != hello2.HashKey() {
|
if hello1.Hash() != hello2.Hash() {
|
||||||
t.Errorf("string with same content have different hash keys")
|
t.Errorf("string with same content have different hash keys")
|
||||||
}
|
}
|
||||||
|
|
||||||
if diff1.HashKey() != diff2.HashKey() {
|
if diff1.Hash() != diff2.Hash() {
|
||||||
t.Errorf("string with same content have different hash keys")
|
t.Errorf("string with same content have different hash keys")
|
||||||
}
|
}
|
||||||
|
|
||||||
if hello1.HashKey() == diff1.HashKey() {
|
if hello1.Hash() == diff1.Hash() {
|
||||||
t.Errorf("string with different content have same hash keys")
|
t.Errorf("string with different content have same hash keys")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ package object
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"hash/fnv"
|
||||||
"strings"
|
"strings"
|
||||||
"unicode/utf8"
|
"unicode/utf8"
|
||||||
)
|
)
|
||||||
@@ -26,10 +27,18 @@ func (s String) Inspect() string {
|
|||||||
return fmt.Sprintf("%#v", s.Value)
|
return fmt.Sprintf("%#v", s.Value)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s String) Clone() Object {
|
func (s String) Copy() Object {
|
||||||
return String{Value: s.Value}
|
return String{Value: s.Value}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Hash implements the Hasher interface
|
||||||
|
func (s String) Hash() HashKey {
|
||||||
|
h := fnv.New64a()
|
||||||
|
h.Write([]byte(s.Value))
|
||||||
|
|
||||||
|
return HashKey{Type: s.Type(), Value: h.Sum64()}
|
||||||
|
}
|
||||||
|
|
||||||
func (s String) String() string {
|
func (s String) String() string {
|
||||||
return s.Value
|
return s.Value
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -102,7 +102,7 @@ func (s *VMState) ExportedHash() *object.Hash {
|
|||||||
if symbol.Scope == compiler.GlobalScope {
|
if symbol.Scope == compiler.GlobalScope {
|
||||||
obj := s.Globals[symbol.Index]
|
obj := s.Globals[symbol.Index]
|
||||||
s := object.String{Value: name}
|
s := object.String{Value: name}
|
||||||
pairs[s.HashKey()] = object.HashPair{Key: s, Value: obj}
|
pairs[s.Hash()] = object.HashPair{Key: s, Value: obj}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -210,8 +210,8 @@ func (vm *VM) executeSetGlobal() error {
|
|||||||
globalIndex := vm.currentFrame().ReadUint16()
|
globalIndex := vm.currentFrame().ReadUint16()
|
||||||
|
|
||||||
ref := vm.pop()
|
ref := vm.pop()
|
||||||
if immutable, ok := ref.(object.Immutable); ok {
|
if obj, ok := ref.(object.Copyable); ok {
|
||||||
vm.state.Globals[globalIndex] = immutable.Clone()
|
vm.state.Globals[globalIndex] = obj.Copy()
|
||||||
} else {
|
} else {
|
||||||
vm.state.Globals[globalIndex] = ref
|
vm.state.Globals[globalIndex] = ref
|
||||||
}
|
}
|
||||||
@@ -223,8 +223,8 @@ func (vm *VM) executeSetLocal() error {
|
|||||||
localIndex := vm.currentFrame().ReadUint8()
|
localIndex := vm.currentFrame().ReadUint8()
|
||||||
|
|
||||||
ref := vm.pop()
|
ref := vm.pop()
|
||||||
if immutable, ok := ref.(object.Immutable); ok {
|
if obj, ok := ref.(object.Copyable); ok {
|
||||||
vm.stack[vm.currentFrame().basePointer+int(localIndex)] = immutable.Clone()
|
vm.stack[vm.currentFrame().basePointer+int(localIndex)] = obj.Copy()
|
||||||
} else {
|
} else {
|
||||||
vm.stack[vm.currentFrame().basePointer+int(localIndex)] = ref
|
vm.stack[vm.currentFrame().basePointer+int(localIndex)] = ref
|
||||||
}
|
}
|
||||||
@@ -241,12 +241,12 @@ func (vm *VM) buildHash(startIndex, endIndex int) (object.Object, error) {
|
|||||||
|
|
||||||
pair := object.HashPair{Key: key, Value: value}
|
pair := object.HashPair{Key: key, Value: value}
|
||||||
|
|
||||||
hashKey, ok := key.(object.Hashable)
|
hashKey, ok := key.(object.Hasher)
|
||||||
if !ok {
|
if !ok {
|
||||||
return nil, fmt.Errorf("unusable as hash key: %s", key.Type())
|
return nil, fmt.Errorf("unusable as hash key: %s", key.Type())
|
||||||
}
|
}
|
||||||
|
|
||||||
hashedPairs[hashKey.HashKey()] = pair
|
hashedPairs[hashKey.Hash()] = pair
|
||||||
}
|
}
|
||||||
|
|
||||||
return &object.Hash{Pairs: hashedPairs}, nil
|
return &object.Hash{Pairs: hashedPairs}, nil
|
||||||
|
|||||||
@@ -379,15 +379,15 @@ func TestHashLiterals(t *testing.T) {
|
|||||||
{
|
{
|
||||||
"{1: 2, 2: 3}",
|
"{1: 2, 2: 3}",
|
||||||
map[object.HashKey]int64{
|
map[object.HashKey]int64{
|
||||||
(object.Integer{Value: 1}).HashKey(): 2,
|
(object.Integer{Value: 1}).Hash(): 2,
|
||||||
(object.Integer{Value: 2}).HashKey(): 3,
|
(object.Integer{Value: 2}).Hash(): 3,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"{1 + 1: 2 * 2, 3 + 3: 4 * 4}",
|
"{1 + 1: 2 * 2, 3 + 3: 4 * 4}",
|
||||||
map[object.HashKey]int64{
|
map[object.HashKey]int64{
|
||||||
(object.Integer{Value: 2}).HashKey(): 4,
|
(object.Integer{Value: 2}).Hash(): 4,
|
||||||
(object.Integer{Value: 6}).HashKey(): 16,
|
(object.Integer{Value: 6}).Hash(): 16,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
@@ -400,14 +400,14 @@ func TestHashMerging(t *testing.T) {
|
|||||||
{
|
{
|
||||||
`{} + {"a": 1}`,
|
`{} + {"a": 1}`,
|
||||||
map[object.HashKey]int64{
|
map[object.HashKey]int64{
|
||||||
(object.String{Value: "a"}).HashKey(): 1,
|
(object.String{Value: "a"}).Hash(): 1,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
`{"a": 1} + {"b": 2}`,
|
`{"a": 1} + {"b": 2}`,
|
||||||
map[object.HashKey]int64{
|
map[object.HashKey]int64{
|
||||||
(object.String{Value: "a"}).HashKey(): 1,
|
(object.String{Value: "a"}).Hash(): 1,
|
||||||
(object.String{Value: "b"}).HashKey(): 2,
|
(object.String{Value: "b"}).Hash(): 2,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,15 +6,14 @@ import (
|
|||||||
"flag"
|
"flag"
|
||||||
"fmt"
|
"fmt"
|
||||||
"log"
|
"log"
|
||||||
|
"monkey/internal/compiler"
|
||||||
|
"monkey/internal/object"
|
||||||
|
"monkey/internal/parser"
|
||||||
|
"monkey/internal/vm"
|
||||||
"os"
|
"os"
|
||||||
"runtime"
|
"runtime"
|
||||||
"runtime/pprof"
|
"runtime/pprof"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"git.mills.io/prologic/monkey-lang/internal/compiler"
|
|
||||||
"git.mills.io/prologic/monkey-lang/internal/object"
|
|
||||||
"git.mills.io/prologic/monkey-lang/internal/parser"
|
|
||||||
"git.mills.io/prologic/monkey-lang/internal/vm"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
const defaultCode = `
|
const defaultCode = `
|
||||||
|
|||||||
Reference in New Issue
Block a user