From 7cb1074a3d80c553c24b7367583e109bfbca248b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bastian=20M=C3=BCller?= Date: Fri, 22 Sep 2023 10:24:02 -0700 Subject: [PATCH] add support for injecting types into the environment --- runtime/environment.go | 21 +++++++--- runtime/predeclaredvalues_test.go | 65 +++++++++++++++++++++++++++++-- 2 files changed, 77 insertions(+), 9 deletions(-) diff --git a/runtime/environment.go b/runtime/environment.go index 32a5f8b024..91011df111 100644 --- a/runtime/environment.go +++ b/runtime/environment.go @@ -38,7 +38,8 @@ import ( type Environment interface { ArgumentDecoder - Declare(valueDeclaration stdlib.StandardLibraryValue) + DeclareValue(valueDeclaration stdlib.StandardLibraryValue) + DeclareType(typeDeclaration stdlib.StandardLibraryType) Configure( runtimeInterface Interface, codesAndPrograms CodesAndPrograms, @@ -78,8 +79,9 @@ type interpreterEnvironmentReconfigured struct { type interpreterEnvironment struct { interpreterEnvironmentReconfigured - baseActivation *interpreter.VariableActivation + baseTypeActivation *sema.VariableActivation baseValueActivation *sema.VariableActivation + baseActivation *interpreter.VariableActivation InterpreterConfig *interpreter.Config CheckerConfig *sema.Config deployedContractConstructorInvocation *stdlib.DeployedContractConstructorInvocation @@ -108,12 +110,14 @@ var _ common.MemoryGauge = &interpreterEnvironment{} func newInterpreterEnvironment(config Config) *interpreterEnvironment { baseValueActivation := sema.NewVariableActivation(sema.BaseValueActivation) + baseTypeActivation := sema.NewVariableActivation(sema.BaseTypeActivation) baseActivation := activations.NewActivation[*interpreter.Variable](nil, interpreter.BaseActivation) env := &interpreterEnvironment{ config: config, - baseActivation: baseActivation, baseValueActivation: baseValueActivation, + baseTypeActivation: baseTypeActivation, + baseActivation: baseActivation, stackDepthLimiter: newStackDepthLimiter(config.StackDepthLimit), } env.InterpreterConfig = env.newInterpreterConfig() @@ -158,6 +162,7 @@ func (e *interpreterEnvironment) newCheckerConfig() *sema.Config { return &sema.Config{ AccessCheckMode: sema.AccessCheckModeStrict, BaseValueActivation: e.baseValueActivation, + BaseTypeActivation: e.baseTypeActivation, ValidTopLevelDeclarationsHandler: validTopLevelDeclarations, LocationHandler: e.newLocationHandler(), ImportHandler: e.resolveImport, @@ -171,7 +176,7 @@ func (e *interpreterEnvironment) newCheckerConfig() *sema.Config { func NewBaseInterpreterEnvironment(config Config) *interpreterEnvironment { env := newInterpreterEnvironment(config) for _, valueDeclaration := range stdlib.DefaultStandardLibraryValues(env) { - env.Declare(valueDeclaration) + env.DeclareValue(valueDeclaration) } return env } @@ -179,7 +184,7 @@ func NewBaseInterpreterEnvironment(config Config) *interpreterEnvironment { func NewScriptInterpreterEnvironment(config Config) Environment { env := newInterpreterEnvironment(config) for _, valueDeclaration := range stdlib.DefaultScriptStandardLibraryValues(env) { - env.Declare(valueDeclaration) + env.DeclareValue(valueDeclaration) } return env } @@ -198,11 +203,15 @@ func (e *interpreterEnvironment) Configure( e.stackDepthLimiter.depth = 0 } -func (e *interpreterEnvironment) Declare(valueDeclaration stdlib.StandardLibraryValue) { +func (e *interpreterEnvironment) DeclareValue(valueDeclaration stdlib.StandardLibraryValue) { e.baseValueActivation.DeclareValue(valueDeclaration) interpreter.Declare(e.baseActivation, valueDeclaration) } +func (e *interpreterEnvironment) DeclareType(typeDeclaration stdlib.StandardLibraryType) { + e.baseTypeActivation.DeclareType(typeDeclaration) +} + func (e *interpreterEnvironment) NewAuthAccountValue(address interpreter.AddressValue) interpreter.Value { return stdlib.NewAuthAccountValue(e, e, address) } diff --git a/runtime/predeclaredvalues_test.go b/runtime/predeclaredvalues_test.go index 069838164b..fee5147550 100644 --- a/runtime/predeclaredvalues_test.go +++ b/runtime/predeclaredvalues_test.go @@ -39,7 +39,7 @@ func TestRuntimePredeclaredValues(t *testing.T) { valueDeclaration := stdlib.StandardLibraryValue{ Name: "foo", Type: sema.IntType, - Kind: common.DeclarationKindFunction, + Kind: common.DeclarationKindConstant, Value: interpreter.NewUnmeteredIntValueFromInt64(2), } @@ -91,7 +91,7 @@ func TestRuntimePredeclaredValues(t *testing.T) { // Run transaction transactionEnvironment := NewBaseInterpreterEnvironment(Config{}) - transactionEnvironment.Declare(valueDeclaration) + transactionEnvironment.DeclareValue(valueDeclaration) err := runtime.ExecuteTransaction( Script{ @@ -108,7 +108,7 @@ func TestRuntimePredeclaredValues(t *testing.T) { // Run script scriptEnvironment := NewScriptInterpreterEnvironment(Config{}) - scriptEnvironment.Declare(valueDeclaration) + scriptEnvironment.DeclareValue(valueDeclaration) result, err := runtime.ExecuteScript( Script{ @@ -127,3 +127,62 @@ func TestRuntimePredeclaredValues(t *testing.T) { result, ) } + +func TestRuntimePredeclaredTypes(t *testing.T) { + + t.Parallel() + + xType := sema.IntType + + valueDeclaration := stdlib.StandardLibraryValue{ + Name: "x", + Type: xType, + Kind: common.DeclarationKindConstant, + Value: interpreter.NewUnmeteredIntValueFromInt64(2), + } + + typeDeclaration := stdlib.StandardLibraryType{ + Name: "X", + Type: xType, + Kind: common.DeclarationKindType, + } + + script := []byte(` + pub fun main(): X { + return x + } + `) + + runtime := newTestInterpreterRuntime() + + runtimeInterface := &testRuntimeInterface{ + storage: newTestLedger(nil, nil), + getSigningAccounts: func() ([]Address, error) { + return []Address{common.MustBytesToAddress([]byte{0x1})}, nil + }, + resolveLocation: singleIdentifierLocationResolver(t), + } + + // Run script + + scriptEnvironment := NewScriptInterpreterEnvironment(Config{}) + scriptEnvironment.DeclareValue(valueDeclaration) + scriptEnvironment.DeclareType(typeDeclaration) + + result, err := runtime.ExecuteScript( + Script{ + Source: script, + }, + Context{ + Interface: runtimeInterface, + Location: common.ScriptLocation{}, + Environment: scriptEnvironment, + }, + ) + require.NoError(t, err) + + require.Equal(t, + cadence.Int{Value: big.NewInt(2)}, + result, + ) +}