From 18aa1dc570ad603c905fa4cb67c60b5bae8b6e44 Mon Sep 17 00:00:00 2001 From: Stepan Koltsov Date: Fri, 8 Jun 2012 04:19:24 +0400 Subject: [PATCH] script parameter closure --- .../jet/codegen/ExpressionCodegen.java | 36 ++++++++++++------- .../jetbrains/jet/codegen/ScriptCodegen.java | 18 ++++++++++ .../codegen/script/parameterClosure.ktscript | 7 ++++ .../jetbrains/jet/codegen/ScriptGenTest.java | 4 +++ 4 files changed, 52 insertions(+), 13 deletions(-) create mode 100644 compiler/testData/codegen/script/parameterClosure.ktscript diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/ExpressionCodegen.java b/compiler/backend/src/org/jetbrains/jet/codegen/ExpressionCodegen.java index df3170b9f40..a12e9ba97e5 100644 --- a/compiler/backend/src/org/jetbrains/jet/codegen/ExpressionCodegen.java +++ b/compiler/backend/src/org/jetbrains/jet/codegen/ExpressionCodegen.java @@ -1126,23 +1126,33 @@ public class ExpressionCodegen extends JetVisitor { } StackValue value = context.lookupInContext(descriptor, v, StackValue.local(0, TYPE_OBJECT)); - if (value == null) { - throw new UnsupportedOperationException("don't know how to generate reference " + descriptor); + if (value != null) { + + if (value instanceof StackValue.Composed) { + StackValue.Composed composed = (StackValue.Composed) value; + composed.prefix.put(TYPE_OBJECT, v); + value = composed.suffix; + } + + if (value instanceof StackValue.FieldForSharedVar) { + StackValue.FieldForSharedVar fieldForSharedVar = (StackValue.FieldForSharedVar) value; + Type sharedType = StackValue.sharedTypeForType(value.type); + v.visitFieldInsn(Opcodes.GETFIELD, fieldForSharedVar.owner.getInternalName(), fieldForSharedVar.name, sharedType.getDescriptor()); + } + + return value; } - if(value instanceof StackValue.Composed) { - StackValue.Composed composed = (StackValue.Composed) value; - composed.prefix.put(TYPE_OBJECT, v); - value = composed.suffix; + if (descriptor instanceof ValueParameterDescriptor && descriptor.getContainingDeclaration() instanceof ScriptDescriptor) { + ScriptDescriptor scriptDescriptor = (ScriptDescriptor) descriptor.getContainingDeclaration(); + JvmClassName scriptClassName = state.getInjector().getClosureAnnotator().classNameForScriptDescriptor(scriptDescriptor); + ValueParameterDescriptor valueParameterDescriptor = (ValueParameterDescriptor) descriptor; + generateThisOrOuter(state.getInjector().getClosureAnnotator().classDescriptorForScrpitDescriptor(scriptDescriptor)); + Type fieldType = typeMapper.mapType(valueParameterDescriptor.getType(), MapTypeMode.VALUE); + return StackValue.field(fieldType, scriptClassName, valueParameterDescriptor.getName().getIdentifier(), false); } - if(value instanceof StackValue.FieldForSharedVar) { - StackValue.FieldForSharedVar fieldForSharedVar = (StackValue.FieldForSharedVar) value; - Type sharedType = StackValue.sharedTypeForType(value.type); - v.visitFieldInsn(Opcodes.GETFIELD, fieldForSharedVar.owner.getInternalName(), fieldForSharedVar.name, sharedType.getDescriptor()); - } - - return value; + throw new UnsupportedOperationException("don't know how to generate reference " + descriptor); } private StackValue stackValueForLocal(DeclarationDescriptor descriptor, int index) { diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/ScriptCodegen.java b/compiler/backend/src/org/jetbrains/jet/codegen/ScriptCodegen.java index b3e7be4e382..7e770c23d6b 100644 --- a/compiler/backend/src/org/jetbrains/jet/codegen/ScriptCodegen.java +++ b/compiler/backend/src/org/jetbrains/jet/codegen/ScriptCodegen.java @@ -109,6 +109,7 @@ public class ScriptCodegen { new String[0]); genMembers(scriptDeclaration, context, classBuilder); + genFieldsForParameters(scriptDescriptor, classBuilder); genConstructor(scriptDeclaration, scriptDescriptor, classDescriptorForScript, classBuilder, context.intoFunction(scriptDescriptor.getScriptCodeDescriptor())); classBuilder.done(); @@ -159,6 +160,15 @@ public class ScriptCodegen { bindingContext, jetTypeMapper); + int offset = 1; + for (ValueParameterDescriptor parameter : scriptDescriptor.getValueParameters()) { + Type parameterType = jetTypeMapper.mapType(parameter.getType(), MapTypeMode.VALUE); + instructionAdapter.load(0, className.getAsmType()); + instructionAdapter.load(offset, parameterType); + offset += parameterType.getSize(); + instructionAdapter.putfield(className.getInternalName(), parameter.getName().getIdentifier(), parameterType.getDescriptor()); + } + StackValue stackValue = new ExpressionCodegen(mv, frameMap, Type.VOID_TYPE, context, state).gen(scriptDeclaration.getBlockExpression()); if (stackValue.type != Type.VOID_TYPE) { stackValue.put(stackValue.type, instructionAdapter); @@ -170,6 +180,14 @@ public class ScriptCodegen { mv.visitEnd(); } + private void genFieldsForParameters(@NotNull ScriptDescriptor script, @NotNull ClassBuilder classBuilder) { + for (ValueParameterDescriptor parameter : script.getValueParameters()) { + Type parameterType = jetTypeMapper.mapType(parameter.getType(), MapTypeMode.VALUE); + int access = Opcodes.ACC_PRIVATE | Opcodes.ACC_FINAL; + classBuilder.newField(null, access, parameter.getName().getIdentifier(), parameterType.getDescriptor(), null, null); + } + } + private void genMembers(@NotNull JetScript scriptDeclaration, @NotNull CodegenContext context, @NotNull ClassBuilder classBuilder) { for (JetDeclaration decl : scriptDeclaration.getDeclarations()) { memberCodegen.generateFunctionOrProperty((JetTypeParameterListOwner) decl, context, classBuilder); diff --git a/compiler/testData/codegen/script/parameterClosure.ktscript b/compiler/testData/codegen/script/parameterClosure.ktscript new file mode 100644 index 00000000000..896e82c2a4a --- /dev/null +++ b/compiler/testData/codegen/script/parameterClosure.ktscript @@ -0,0 +1,7 @@ +// param: x: jet.Int: 10 + +fun addX(y: Int) = x + y + +addX(3) + +// expected: rv: 13 diff --git a/compiler/tests/org/jetbrains/jet/codegen/ScriptGenTest.java b/compiler/tests/org/jetbrains/jet/codegen/ScriptGenTest.java index b69fe2199cf..70a2b8f5954 100644 --- a/compiler/tests/org/jetbrains/jet/codegen/ScriptGenTest.java +++ b/compiler/tests/org/jetbrains/jet/codegen/ScriptGenTest.java @@ -78,4 +78,8 @@ public class ScriptGenTest extends CodegenTestCase { blackBoxFile("script/parameterArray.ktscript"); } + public void testScriptParameterClosure() { + blackBoxFile("script/parameterClosure.ktscript"); + } + }