diff --git a/bbq/compiler/compiler.go b/bbq/compiler/compiler.go index ea35ffc26..9360f4d46 100644 --- a/bbq/compiler/compiler.go +++ b/bbq/compiler/compiler.go @@ -411,11 +411,7 @@ func (c *Compiler) exportConstants() []*bbq.Constant { } func (c *Compiler) exportTypes() [][]byte { - types := make([][]byte, len(c.staticTypes)) - for index, typeBytes := range c.staticTypes { - types[index] = typeBytes - } - return types + return c.staticTypes } func (c *Compiler) exportImports() []*bbq.Import { @@ -645,8 +641,15 @@ func (c *Compiler) VisitSwapStatement(_ *ast.SwapStatement) (_ struct{}) { func (c *Compiler) VisitExpressionStatement(statement *ast.ExpressionStatement) (_ struct{}) { c.compileExpression(statement.Expression) - // Drop the expression evaluation result - c.emit(opcode.Drop) + + switch statement.Expression.(type) { + case *ast.DestroyExpression: + // Do nothing. Destroy operation will not produce any result. + default: + // Otherwise, drop the expression evaluation result. + c.emit(opcode.Drop) + } + return } @@ -748,11 +751,11 @@ func (c *Compiler) VisitInvocationExpression(expression *ast.InvocationExpressio switch invokedExpr := expression.InvokedExpression.(type) { case *ast.IdentifierExpression: - typ := c.Elaboration.IdentifierInInvocationType(invokedExpr) - invocationType := typ.(*sema.FunctionType) - if invocationType.IsConstructor { - // TODO: - } + // TODO: Does constructors need any special handling? + //typ := c.Elaboration.IdentifierInInvocationType(invokedExpr) + //invocationType := typ.(*sema.FunctionType) + //if invocationType.IsConstructor { + //} // Load arguments c.loadArguments(expression) diff --git a/bbq/vm/test/ft_test.go b/bbq/vm/test/ft_test.go index 9598bba5e..920d925d0 100644 --- a/bbq/vm/test/ft_test.go +++ b/bbq/vm/test/ft_test.go @@ -140,7 +140,7 @@ func TestFTTransfer(t *testing.T) { mintTxArgs := []vm.Value{ vm.AddressValue(senderAddress), - vm.IntValue{total}, + vm.NewIntValue(total), } mintTxAuthorizer := vm.NewAuthAccountReferenceValue(vmConfig, contractsAddress) @@ -158,7 +158,7 @@ func TestFTTransfer(t *testing.T) { transferAmount := int64(1) tokenTransferTxArgs := []vm.Value{ - vm.IntValue{transferAmount}, + vm.NewIntValue(transferAmount), vm.AddressValue(receiverAddress), } @@ -183,9 +183,9 @@ func TestFTTransfer(t *testing.T) { require.Equal(t, 0, validationScriptVM.StackSize()) if address == senderAddress { - assert.Equal(t, vm.IntValue{total - transferAmount}, result) + assert.Equal(t, vm.NewIntValue(total-transferAmount), result) } else { - assert.Equal(t, vm.IntValue{transferAmount}, result) + assert.Equal(t, vm.NewIntValue(transferAmount), result) } } } @@ -292,7 +292,7 @@ func BenchmarkFTTransfer(b *testing.B) { mintTxArgs := []vm.Value{ vm.AddressValue(senderAddress), - vm.IntValue{total}, + vm.NewIntValue(total), } mintTxAuthorizer := vm.NewAuthAccountReferenceValue(vmConfig, contractsAddress) @@ -305,7 +305,7 @@ func BenchmarkFTTransfer(b *testing.B) { transferAmount := int64(1) tokenTransferTxArgs := []vm.Value{ - vm.IntValue{transferAmount}, + vm.NewIntValue(transferAmount), vm.AddressValue(receiverAddress), } diff --git a/bbq/vm/test/vm_bench_test.go b/bbq/vm/test/vm_bench_test.go index 0cdcdf6b6..7711d4121 100644 --- a/bbq/vm/test/vm_bench_test.go +++ b/bbq/vm/test/vm_bench_test.go @@ -35,13 +35,13 @@ func BenchmarkRecursionFib(b *testing.B) { b.ReportAllocs() b.ResetTimer() - expected := vm.IntValue{SmallInt: 377} + expected := vm.NewIntValue(377) for i := 0; i < b.N; i++ { result, err := vmInstance.Invoke( "fib", - vm.IntValue{SmallInt: 14}, + vm.NewIntValue(14), ) require.NoError(b, err) require.Equal(b, expected, result) @@ -64,7 +64,7 @@ func BenchmarkImperativeFib(b *testing.B) { b.ReportAllocs() b.ResetTimer() - var value vm.Value = vm.IntValue{SmallInt: 14} + var value vm.Value = vm.NewIntValue(14) for i := 0; i < b.N; i++ { _, err := vmInstance.Invoke("fib", value) @@ -97,7 +97,7 @@ func BenchmarkNewStruct(b *testing.B) { `) require.NoError(b, err) - value := vm.IntValue{SmallInt: 1} + value := vm.NewIntValue(1) b.ReportAllocs() b.ResetTimer() @@ -140,7 +140,7 @@ func BenchmarkNewResource(b *testing.B) { b.ReportAllocs() b.ResetTimer() - value := vm.IntValue{SmallInt: 9} + value := vm.NewIntValue(9) scriptLocation := runtime_utils.NewScriptLocationGenerator() @@ -162,7 +162,7 @@ func BenchmarkNewStructRaw(b *testing.B) { Storage: storage, } - fieldValue := vm.IntValue{SmallInt: 7} + fieldValue := vm.NewIntValue(7) b.ReportAllocs() b.ResetTimer() @@ -239,7 +239,7 @@ func BenchmarkContractImport(b *testing.B) { b.ResetTimer() b.ReportAllocs() - value := vm.IntValue{SmallInt: 7} + value := vm.NewIntValue(7) for i := 0; i < b.N; i++ { checker, err := ParseAndCheckWithOptions(b, ` @@ -367,7 +367,7 @@ func BenchmarkMethodCall(b *testing.B) { vmInstance = vm.NewVM(scriptLocation(), program, vmConfig) - value := vm.IntValue{SmallInt: 10} + value := vm.NewIntValue(10) b.ResetTimer() b.ReportAllocs() @@ -461,7 +461,7 @@ func BenchmarkMethodCall(b *testing.B) { vmInstance = vm.NewVM(scriptLocation(), program, vmConfig) - value := vm.IntValue{SmallInt: 10} + value := vm.NewIntValue(10) b.ResetTimer() b.ReportAllocs() diff --git a/bbq/vm/test/vm_test.go b/bbq/vm/test/vm_test.go index 45adbee04..34567862a 100644 --- a/bbq/vm/test/vm_test.go +++ b/bbq/vm/test/vm_test.go @@ -68,10 +68,10 @@ func TestRecursionFib(t *testing.T) { result, err := vmInstance.Invoke( "fib", - vm.IntValue{SmallInt: 7}, + vm.NewIntValue(7), ) require.NoError(t, err) - require.Equal(t, vm.IntValue{SmallInt: 13}, result) + require.Equal(t, vm.NewIntValue(13), result) require.Equal(t, 0, vmInstance.StackSize()) } @@ -106,10 +106,10 @@ func TestImperativeFib(t *testing.T) { result, err := vmInstance.Invoke( "fib", - vm.IntValue{SmallInt: 7}, + vm.NewIntValue(7), ) require.NoError(t, err) - require.Equal(t, vm.IntValue{SmallInt: 13}, result) + require.Equal(t, vm.NewIntValue(13), result) require.Equal(t, 0, vmInstance.StackSize()) } @@ -140,7 +140,7 @@ func TestBreak(t *testing.T) { result, err := vmInstance.Invoke("test") require.NoError(t, err) - require.Equal(t, vm.IntValue{SmallInt: 4}, result) + require.Equal(t, vm.NewIntValue(4), result) require.Equal(t, 0, vmInstance.StackSize()) } @@ -172,7 +172,7 @@ func TestContinue(t *testing.T) { result, err := vmInstance.Invoke("test") require.NoError(t, err) - require.Equal(t, vm.IntValue{SmallInt: 3}, result) + require.Equal(t, vm.NewIntValue(3), result) require.Equal(t, 0, vmInstance.StackSize()) } @@ -201,7 +201,7 @@ func TestNilCoalesce(t *testing.T) { result, err := vmInstance.Invoke("test") require.NoError(t, err) - require.Equal(t, vm.IntValue{SmallInt: 2}, result) + require.Equal(t, vm.NewIntValue(2), result) require.Equal(t, 0, vmInstance.StackSize()) }) @@ -226,7 +226,7 @@ func TestNilCoalesce(t *testing.T) { result, err := vmInstance.Invoke("test") require.NoError(t, err) - require.Equal(t, vm.IntValue{SmallInt: 3}, result) + require.Equal(t, vm.NewIntValue(3), result) require.Equal(t, 0, vmInstance.StackSize()) }) } @@ -263,7 +263,7 @@ func TestNewStruct(t *testing.T) { vmConfig := &vm.Config{} vmInstance := vm.NewVM(scriptLocation(), program, vmConfig) - result, err := vmInstance.Invoke("test", vm.IntValue{SmallInt: 10}) + result, err := vmInstance.Invoke("test", vm.NewIntValue(10)) require.NoError(t, err) require.Equal(t, 0, vmInstance.StackSize()) @@ -274,7 +274,7 @@ func TestNewStruct(t *testing.T) { require.Equal(t, "Foo", compositeType.QualifiedIdentifier) require.Equal( t, - vm.IntValue{SmallInt: 12}, + vm.NewIntValue(12), structValue.GetMember(vmConfig, "id"), ) } @@ -313,7 +313,7 @@ func TestStructMethodCall(t *testing.T) { require.NoError(t, err) require.Equal(t, 0, vmInstance.StackSize()) - require.Equal(t, vm.StringValue{Str: []byte("Hello from Foo!")}, result) + require.Equal(t, vm.NewStringValue("Hello from Foo!"), result) } func TestImport(t *testing.T) { @@ -388,7 +388,7 @@ func TestImport(t *testing.T) { require.NoError(t, err) require.Equal(t, 0, vmInstance.StackSize()) - require.Equal(t, vm.StringValue{Str: []byte("global function of the imported program")}, result) + require.Equal(t, vm.NewStringValue("global function of the imported program"), result) } func TestContractImport(t *testing.T) { @@ -478,7 +478,7 @@ func TestContractImport(t *testing.T) { require.NoError(t, err) require.Equal(t, 0, vmInstance.StackSize()) - require.Equal(t, vm.StringValue{Str: []byte("global function of the imported program")}, result) + require.Equal(t, vm.NewStringValue("global function of the imported program"), result) }) t.Run("contract function", func(t *testing.T) { @@ -553,7 +553,7 @@ func TestContractImport(t *testing.T) { require.NoError(t, err) require.Equal(t, 0, vmInstance.StackSize()) - require.Equal(t, vm.StringValue{Str: []byte("contract function of the imported program")}, result) + require.Equal(t, vm.NewStringValue("contract function of the imported program"), result) }) t.Run("nested imports", func(t *testing.T) { @@ -726,7 +726,7 @@ func TestContractImport(t *testing.T) { require.NoError(t, err) require.Equal(t, 0, vmInstance.StackSize()) - require.Equal(t, vm.StringValue{Str: []byte("Hello from Foo!")}, result) + require.Equal(t, vm.NewStringValue("Hello from Foo!"), result) }) t.Run("contract interface", func(t *testing.T) { @@ -897,7 +897,7 @@ func TestContractImport(t *testing.T) { require.NoError(t, err) require.Equal(t, 0, vmInstance.StackSize()) - require.Equal(t, vm.StringValue{Str: []byte("Successfully withdrew")}, result) + require.Equal(t, vm.NewStringValue("Successfully withdrew"), result) }) } @@ -927,7 +927,7 @@ func TestInitializeContract(t *testing.T) { require.NoError(t, err) fieldValue := contractValue.GetMember(vmConfig, "status") - assert.Equal(t, vm.StringValue{Str: []byte("PENDING")}, fieldValue) + assert.Equal(t, vm.NewStringValue("PENDING"), fieldValue) } func TestContractAccessDuringInit(t *testing.T) { @@ -964,7 +964,7 @@ func TestContractAccessDuringInit(t *testing.T) { require.NoError(t, err) fieldValue := contractValue.GetMember(vmConfig, "status") - assert.Equal(t, vm.StringValue{Str: []byte("PENDING")}, fieldValue) + assert.Equal(t, vm.NewStringValue("PENDING"), fieldValue) }) t.Run("using self", func(t *testing.T) { @@ -997,7 +997,7 @@ func TestContractAccessDuringInit(t *testing.T) { require.NoError(t, err) fieldValue := contractValue.GetMember(vmConfig, "status") - assert.Equal(t, vm.StringValue{Str: []byte("PENDING")}, fieldValue) + assert.Equal(t, vm.NewStringValue("PENDING"), fieldValue) }) } @@ -1032,7 +1032,7 @@ func TestFunctionOrder(t *testing.T) { require.NoError(t, err) require.Equal(t, 0, vmInstance.StackSize()) - require.Equal(t, vm.IntValue{SmallInt: 5}, result) + require.Equal(t, vm.NewIntValue(5), result) }) t.Run("nested", func(t *testing.T) { @@ -1162,7 +1162,7 @@ func TestContractField(t *testing.T) { require.NoError(t, err) require.Equal(t, 0, vmInstance.StackSize()) - require.Equal(t, vm.StringValue{Str: []byte("PENDING")}, result) + require.Equal(t, vm.NewStringValue("PENDING"), result) }) t.Run("set", func(t *testing.T) { @@ -1233,10 +1233,10 @@ func TestContractField(t *testing.T) { require.NoError(t, err) require.Equal(t, 0, vmInstance.StackSize()) - require.Equal(t, vm.StringValue{Str: []byte("UPDATED")}, result) + require.Equal(t, vm.NewStringValue("UPDATED"), result) fieldValue := importedContractValue.GetMember(vmConfig, "status") - assert.Equal(t, vm.StringValue{Str: []byte("UPDATED")}, fieldValue) + assert.Equal(t, vm.NewStringValue("UPDATED"), fieldValue) }) } @@ -1310,7 +1310,7 @@ func TestNativeFunctions(t *testing.T) { require.NoError(t, err) require.Equal(t, 0, vmInstance.StackSize()) - require.Equal(t, vm.StringValue{Str: []byte("Hello, World!")}, result) + require.Equal(t, vm.NewStringValue("Hello, World!"), result) }) } @@ -1359,14 +1359,14 @@ func TestTransaction(t *testing.T) { require.NoError(t, err) // Once 'prepare' is called, 'a' is initialized to "Hello!" - assert.Equal(t, vm.StringValue{Str: []byte("Hello!")}, compositeValue.GetMember(vmConfig, "a")) + assert.Equal(t, vm.NewStringValue("Hello!"), compositeValue.GetMember(vmConfig, "a")) // Invoke 'execute' _, err = vmInstance.Invoke(commons.TransactionExecuteFunctionName, transaction) require.NoError(t, err) // Once 'execute' is called, 'a' is initialized to "Hello, again!" - assert.Equal(t, vm.StringValue{Str: []byte("Hello again!")}, compositeValue.GetMember(vmConfig, "a")) + assert.Equal(t, vm.NewStringValue("Hello again!"), compositeValue.GetMember(vmConfig, "a")) }) t.Run("with params", func(t *testing.T) { @@ -1415,14 +1415,14 @@ func TestTransaction(t *testing.T) { require.NoError(t, err) // Once 'prepare' is called, 'a' is initialized to "Hello!" - assert.Equal(t, vm.StringValue{Str: []byte("Hello!")}, compositeValue.GetMember(vmConfig, "a")) + assert.Equal(t, vm.NewStringValue("Hello!"), compositeValue.GetMember(vmConfig, "a")) // Invoke 'execute' _, err = vmInstance.Invoke(commons.TransactionExecuteFunctionName, transaction) require.NoError(t, err) // Once 'execute' is called, 'a' is initialized to "Hello, again!" - assert.Equal(t, vm.StringValue{Str: []byte("Hello again!")}, compositeValue.GetMember(vmConfig, "a")) + assert.Equal(t, vm.NewStringValue("Hello again!"), compositeValue.GetMember(vmConfig, "a")) }) } @@ -1519,7 +1519,7 @@ func TestInterfaceMethodCall(t *testing.T) { require.NoError(t, err) require.Equal(t, 0, vmInstance.StackSize()) - require.Equal(t, vm.StringValue{Str: []byte("Hello from Foo!")}, result) + require.Equal(t, vm.NewStringValue("Hello from Foo!"), result) } func TestArrayLiteral(t *testing.T) { @@ -1549,8 +1549,8 @@ func TestArrayLiteral(t *testing.T) { require.IsType(t, &vm.ArrayValue{}, result) array := result.(*vm.ArrayValue) assert.Equal(t, 2, array.Count()) - assert.Equal(t, vm.IntValue{SmallInt: 2}, array.Get(vmConfig, 0)) - assert.Equal(t, vm.IntValue{SmallInt: 5}, array.Get(vmConfig, 1)) + assert.Equal(t, vm.NewIntValue(2), array.Get(vmConfig, 0)) + assert.Equal(t, vm.NewIntValue(5), array.Get(vmConfig, 1)) }) t.Run("array get", func(t *testing.T) { @@ -1573,7 +1573,7 @@ func TestArrayLiteral(t *testing.T) { result, err := vmInstance.Invoke("test") require.NoError(t, err) require.Equal(t, 0, vmInstance.StackSize()) - assert.Equal(t, vm.IntValue{SmallInt: 5}, result) + assert.Equal(t, vm.NewIntValue(5), result) }) t.Run("array set", func(t *testing.T) { @@ -1601,9 +1601,9 @@ func TestArrayLiteral(t *testing.T) { require.IsType(t, &vm.ArrayValue{}, result) array := result.(*vm.ArrayValue) assert.Equal(t, 3, array.Count()) - assert.Equal(t, vm.IntValue{SmallInt: 2}, array.Get(vmConfig, 0)) - assert.Equal(t, vm.IntValue{SmallInt: 5}, array.Get(vmConfig, 1)) - assert.Equal(t, vm.IntValue{SmallInt: 8}, array.Get(vmConfig, 2)) + assert.Equal(t, vm.NewIntValue(2), array.Get(vmConfig, 0)) + assert.Equal(t, vm.NewIntValue(5), array.Get(vmConfig, 1)) + assert.Equal(t, vm.NewIntValue(8), array.Get(vmConfig, 2)) }) } @@ -1646,6 +1646,87 @@ func TestReference(t *testing.T) { require.NoError(t, err) require.Equal(t, 0, vmInstance.StackSize()) - require.Equal(t, vm.StringValue{Str: []byte("Hello from Foo!")}, result) + require.Equal(t, vm.NewStringValue("Hello from Foo!"), result) }) } + +func TestResource(t *testing.T) { + + t.Parallel() + + t.Run("new", func(t *testing.T) { + t.Parallel() + + checker, err := ParseAndCheck(t, ` + resource Foo { + var id : Int + + init(_ id: Int) { + self.id = id + } + } + + fun test(): @Foo { + var i = 0 + var r <- create Foo(5) + return <- r + } + `) + require.NoError(t, err) + + comp := compiler.NewCompiler(checker.Program, checker.Elaboration) + program := comp.Compile() + + vmConfig := &vm.Config{} + vmInstance := vm.NewVM(scriptLocation(), program, vmConfig) + + result, err := vmInstance.Invoke("test") + require.NoError(t, err) + require.Equal(t, 0, vmInstance.StackSize()) + + require.IsType(t, &vm.CompositeValue{}, result) + structValue := result.(*vm.CompositeValue) + compositeType := structValue.CompositeType + + require.Equal(t, "Foo", compositeType.QualifiedIdentifier) + require.Equal( + t, + vm.NewIntValue(5), + structValue.GetMember(vmConfig, "id"), + ) + }) + + t.Run("destroy", func(t *testing.T) { + t.Parallel() + + checker, err := ParseAndCheck(t, ` + resource Foo { + var id : Int + + init(_ id: Int) { + self.id = id + } + } + + fun test() { + var i = 0 + var r <- create Foo(5) + destroy r + } + `) + require.NoError(t, err) + + comp := compiler.NewCompiler(checker.Program, checker.Elaboration) + program := comp.Compile() + + printProgram("", program) + + vmConfig := &vm.Config{} + vmInstance := vm.NewVM(scriptLocation(), program, vmConfig) + + _, err = vmInstance.Invoke("test") + require.NoError(t, err) + require.Equal(t, 0, vmInstance.StackSize()) + }) + +} diff --git a/bbq/vm/value_array.go b/bbq/vm/value_array.go index 708ea3317..b2e777e0d 100644 --- a/bbq/vm/value_array.go +++ b/bbq/vm/value_array.go @@ -185,15 +185,7 @@ func (v *ArrayValue) Transfer(config *Config, address atree.Address, remove bool element := interpreter.MustConvertStoredValue(config.MemoryGauge, value) - // TODO: converted value is unused - vmElement := InterpreterValueToVMValue(config.Storage, element) - vmElement = vmElement.Transfer( - config, - address, - remove, - nil, - ) - + // TODO: Transfer before returning. return element, nil }, ) diff --git a/bbq/vm/value_capability.go b/bbq/vm/value_capability.go index 0931fe4eb..485a9f672 100644 --- a/bbq/vm/value_capability.go +++ b/bbq/vm/value_capability.go @@ -177,6 +177,8 @@ func getCheckedCapabilityController( if wantedBorrowType == nil { wantedBorrowType = capabilityBorrowType } else { + //wantedBorrowType = inter.SubstituteMappedEntitlements(wantedBorrowType).(*sema.ReferenceType) + if !canBorrow(wantedBorrowType, capabilityBorrowType) { return nil, nil } diff --git a/bbq/vm/value_conversions.go b/bbq/vm/value_conversions.go index 69123b727..48f4bf1d8 100644 --- a/bbq/vm/value_conversions.go +++ b/bbq/vm/value_conversions.go @@ -36,7 +36,7 @@ func InterpreterValueToVMValue(storage interpreter.Storage, value interpreter.Va case interpreter.IntValue: return IntValue{value.BigInt.Int64()} case *interpreter.StringValue: - return StringValue{Str: []byte(value.Str)} + return NewStringValue(value.Str) case *interpreter.CompositeValue: return newCompositeValueFromOrderedMap( value.AtreeMap(), @@ -57,13 +57,9 @@ func InterpreterValueToVMValue(storage interpreter.Storage, value interpreter.Va return AddressValue(value) case *interpreter.SimpleCompositeValue: fields := make(map[string]Value) - var fieldNames []string - - for name, field := range value.Fields { + for name, field := range value.Fields { //nolint:maprange fields[name] = InterpreterValueToVMValue(storage, field) - fieldNames = append(fieldNames, name) } - return NewSimpleCompositeValue( common.CompositeKindStructure, value.TypeID, @@ -153,7 +149,8 @@ func VMValueToInterpreterValue(config *Config, value Value) interpreter.Value { fields := make(map[string]interpreter.Value) var fieldNames []string - for name, field := range value.fields { + // TODO: Fields names order matters. However, this is temporary. So ignore for now. + for name, field := range value.fields { //nolint:maprange fields[name] = VMValueToInterpreterValue(config, field) fieldNames = append(fieldNames, name) } @@ -161,7 +158,7 @@ func VMValueToInterpreterValue(config *Config, value Value) interpreter.Value { return interpreter.NewSimpleCompositeValue( nil, value.typeID, - nil, + value.staticType, fieldNames, fields, nil, diff --git a/bbq/vm/value_dictionary.go b/bbq/vm/value_dictionary.go index c03308c3b..86f9739e0 100644 --- a/bbq/vm/value_dictionary.go +++ b/bbq/vm/value_dictionary.go @@ -252,15 +252,9 @@ func (v *DictionaryValue) Transfer( } key := interpreter.MustConvertStoredValue(config.MemoryGauge, atreeValue) - // TODO: converted value is unused - vmKey := InterpreterValueToVMValue(config.Storage, key) - vmKey = vmKey.Transfer(config, address, remove, nil) - value := interpreter.MustConvertStoredValue(config.MemoryGauge, atreeValue) - // TODO: converted value is unused - vmValue := InterpreterValueToVMValue(config.Storage, value) - vmValue = vmValue.Transfer(config, address, remove, nil) + // TODO: Transfer both key and value before returning. return key, value, nil }, ) diff --git a/bbq/vm/value_string.go b/bbq/vm/value_string.go index 34617cbf4..e5211915b 100644 --- a/bbq/vm/value_string.go +++ b/bbq/vm/value_string.go @@ -34,6 +34,18 @@ type StringValue struct { var _ Value = StringValue{} +func NewStringValue(str string) StringValue { + return StringValue{ + Str: []byte(str), + } +} + +func NewStringValueFromBytes(bytes []byte) StringValue { + return StringValue{ + Str: bytes, + } +} + func (StringValue) isValue() {} func (StringValue) StaticType(common.MemoryGauge) StaticType { @@ -65,9 +77,7 @@ func init() { var sb strings.Builder sb.Write(first.Str) sb.Write(second.Str) - return StringValue{ - []byte(sb.String()), - } + return NewStringValue(sb.String()) }, }) } diff --git a/bbq/vm/vm.go b/bbq/vm/vm.go index bf6b3fa44..06df2d4fb 100644 --- a/bbq/vm/vm.go +++ b/bbq/vm/vm.go @@ -140,9 +140,8 @@ func (vm *VM) replaceTop(value Value) { func (vm *VM) pushCallFrame(functionValue FunctionValue, arguments []Value) { locals := make([]Value, functionValue.Function.LocalCount) - for i, argument := range arguments { - locals[i] = argument - } + + copy(locals, arguments) callFrame := &callFrame{ parent: vm.callFrame, @@ -415,6 +414,8 @@ func opInvokeDynamic(vm *VM) { typeArg := vm.loadType() typeArguments = append(typeArguments, typeArg) } + // TODO: Just to make the linter happy + _ = typeArguments switch typedReceiver := receiver.(type) { case *StorageReferenceValue: @@ -517,7 +518,7 @@ func opTransfer(vm *VM) { } func opDestroy(vm *VM) { - value := vm.peek().(*CompositeValue) + value := vm.pop().(*CompositeValue) value.Destroy(vm.config) } @@ -699,7 +700,7 @@ func (vm *VM) initializeConstant(index uint16) (value Value) { smallInt, _, _ := leb128.ReadInt64(constant.Data) value = IntValue{SmallInt: smallInt} case constantkind.String: - value = StringValue{Str: constant.Data} + value = NewStringValueFromBytes(constant.Data) default: // TODO: panic(errors.NewUnexpectedError("unsupported constant kind '%s'", constant.Kind.String()))