clone
Some checks failed
Build / build (push) Failing after 1m45s
Test / build (push) Failing after 12m0s

This commit is contained in:
Chuck Smith
2024-03-15 15:35:45 -04:00
parent 2988719c9c
commit 80f1a2d78c
6 changed files with 59 additions and 6 deletions

View File

@@ -70,7 +70,12 @@ func Eval(node ast.Node, env *object.Environment) object.Object {
if isError(val) { if isError(val) {
return val return val
} }
if mutable, ok := val.(object.Mutable); ok {
env.Set(node.Name.Value, mutable.Clone())
} else {
env.Set(node.Name.Value, val) env.Set(node.Name.Value, val)
}
case *ast.Identifier: case *ast.Identifier:
return evalIdentifier(node, env) return evalIdentifier(node, env)

View File

@@ -251,6 +251,7 @@ func TestAssignmentStatements(t *testing.T) {
{"let a = 0; a = 5; let b = 0; b = a; b;", 5}, {"let a = 0; a = 5; let b = 0; b = a; b;", 5},
{"let a = 0; a = 5; let b = 0; b = a; let c = 0; c = a + b + 5;", 15}, {"let a = 0; a = 5; let b = 0; b = a; let c = 0; c = a + b + 5;", 15},
{"let a = 0; a = 5; let b = 0; b = a; let c = 0; c = a + b + 5; c;", 15}, {"let a = 0; a = 5; let b = 0; b = a; let c = 0; c = a + b + 5; c;", 15},
{"let a = 5; let b = a; a = 0; b;", 5},
} }
for _, tt := range tests { for _, tt := range tests {
@@ -474,6 +475,7 @@ func TestArrayIndexExpressions(t *testing.T) {
} }
for _, tt := range tests { for _, tt := range tests {
t.Log(tt.input)
evaluated := testEval(tt.input) evaluated := testEval(tt.input)
integer, ok := tt.expected.(int) integer, ok := tt.expected.(int)

18
examples/ fibi.monkey Normal file
View File

@@ -0,0 +1,18 @@
let fib = fn(n) {
if (n < 3) {
return 1
}
let a = 1
let b = 1
let c = 0
let i = 0
while (i < n - 2) {
c = a + b
b = a
a = c
i = i + 1
}
return a
}
print(fib(35))

View File

@@ -1,2 +0,0 @@
let a = 0;
let a = a + 1;

View File

@@ -29,6 +29,7 @@ const (
// Mutable is the interface for all mutable objects which must implement // Mutable is the interface for all mutable objects which must implement
// the Set() method which rebinds its internal value for assignment statements // the Set() method which rebinds its internal value for assignment statements
type Mutable interface { type Mutable interface {
Clone() Object
Set(obj Object) Set(obj Object)
} }
@@ -56,6 +57,9 @@ func (i *Integer) Inspect() string {
func (i *Integer) Set(obj Object) { func (i *Integer) Set(obj Object) {
i.Value = obj.(*Integer).Value i.Value = obj.(*Integer).Value
} }
func (i *Integer) Clone() Object {
return &Integer{Value: i.Value}
}
type Boolean struct { type Boolean struct {
Value bool Value bool
@@ -67,8 +71,11 @@ func (b *Boolean) Type() ObjectType {
func (b *Boolean) Inspect() string { func (b *Boolean) Inspect() string {
return fmt.Sprintf("%t", b.Value) return fmt.Sprintf("%t", b.Value)
} }
func (i *Boolean) Set(obj Object) { func (b *Boolean) Set(obj Object) {
i.Value = obj.(*Boolean).Value b.Value = obj.(*Boolean).Value
}
func (b *Boolean) Clone() Object {
return &Boolean{Value: b.Value}
} }
type Null struct{} type Null struct{}
@@ -105,6 +112,9 @@ func (e *Error) Inspect() string {
func (e *Error) Set(obj Object) { func (e *Error) Set(obj Object) {
e.Message = obj.(*Error).Message e.Message = obj.(*Error).Message
} }
func (e *Error) Clone() Object {
return &Error{Message: e.Message}
}
type Function struct { type Function struct {
Parameters []*ast.Identifier Parameters []*ast.Identifier
@@ -147,6 +157,9 @@ func (s *String) Inspect() string {
func (s *String) Set(obj Object) { func (s *String) Set(obj Object) {
s.Value = obj.(*String).Value s.Value = obj.(*String).Value
} }
func (s *String) Clone() Object {
return &String{Value: s.Value}
}
type BuiltinFunction func(args ...Object) Object type BuiltinFunction func(args ...Object) Object
@@ -185,6 +198,11 @@ func (ao *Array) Inspect() string {
func (ao *Array) Set(obj Object) { func (ao *Array) Set(obj Object) {
ao.Elements = obj.(*Array).Elements ao.Elements = obj.(*Array).Elements
} }
func (ao *Array) Clone() Object {
elements := make([]Object, len(ao.Elements))
copy(elements, ao.Elements)
return &Array{Elements: elements}
}
type HashKey struct { type HashKey struct {
Type ObjectType Type ObjectType
@@ -247,6 +265,13 @@ func (h *Hash) Inspect() string {
func (h *Hash) Set(obj Object) { func (h *Hash) Set(obj Object) {
h.Pairs = obj.(*Hash).Pairs h.Pairs = obj.(*Hash).Pairs
} }
func (h *Hash) Clone() Object {
pairs := make(map[HashKey]HashPair)
for k, v := range h.Pairs {
pairs[k] = v
}
return &Hash{Pairs: pairs}
}
func (cf *CompiledFunction) Type() ObjectType { func (cf *CompiledFunction) Type() ObjectType {
return COMPILED_FUNCTION_OBJ return COMPILED_FUNCTION_OBJ

View File

@@ -156,7 +156,12 @@ func (vm *VM) Run() error {
globalIndex := code.ReadUint16(ins[ip+1:]) globalIndex := code.ReadUint16(ins[ip+1:])
vm.currentFrame().ip += 2 vm.currentFrame().ip += 2
vm.globals[globalIndex] = vm.pop() ref := vm.pop()
if mutable, ok := ref.(object.Mutable); ok {
vm.globals[globalIndex] = mutable.Clone()
} else {
vm.globals[globalIndex] = ref
}
case code.OpAssign: case code.OpAssign:
ident := vm.pop() ident := vm.pop()