From 9116a8955255f6f6d0d340001c61a97d449e79b5 Mon Sep 17 00:00:00 2001 From: dzikoysk Date: Thu, 31 Dec 2020 02:19:27 +0100 Subject: [PATCH] GH-556 Support reassignation of parametrized types --- examples/lang/generics.panda | 38 +++--- .../language/architecture/type/PandaType.java | 9 +- .../architecture/type/PandaTypeMetadata.java | 6 + .../language/architecture/type/Type.java | 2 + .../language/architecture/type/TypeFrame.java | 21 +++- .../language/architecture/type/TypeScope.java | 66 ++--------- .../type/{ => generator}/ClassGenerator.java | 15 ++- .../type/generator/ConstructorGenerator.java | 2 +- .../type/generator/MethodGenerator.java | 2 +- .../type/member/AbstractMember.java | 7 +- .../member/AbstractParametrizedMember.java | 6 +- .../type/member/MemberInvoker.java | 4 +- .../type/member/constructor/BaseCall.java | 29 ++++- .../member/constructor/ConstructorFrame.java | 20 ---- .../member/constructor/ConstructorScope.java | 109 +++++++++++++++++- .../member/constructor/PandaConstructor.java | 21 +++- .../member/constructor/TypeConstructor.java | 2 + .../type/member/method/MethodScope.java | 38 ++---- .../type/member/method/PandaMethod.java | 14 +-- .../type/signature/AdjustedExpression.java | 20 ++-- .../interpreter/logging/ErrorFormatter.java | 2 +- .../parser/PandaParserFailure.java | 2 +- .../ConstructorExpressionSubparser.java | 26 ++++- .../DeclarationExpressionSubparser.java | 15 ++- .../subparsers/FieldExpression.java | 2 +- .../variable/VariableDataInitializer.java | 9 +- .../resource/syntax/type/BaseCallParser.java | 9 +- .../syntax/type/ConstructorParser.java | 19 ++- .../resource/syntax/type/TypeParser.java | 13 +-- .../panda/shell/repl/ReplCreator.java | 14 +-- 30 files changed, 338 insertions(+), 204 deletions(-) rename panda-framework/src/main/java/org/panda_lang/language/architecture/type/{ => generator}/ClassGenerator.java (92%) delete mode 100644 panda-framework/src/main/java/org/panda_lang/language/architecture/type/member/constructor/ConstructorFrame.java diff --git a/examples/lang/generics.panda b/examples/lang/generics.panda index c30640432..edbb8d681 100644 --- a/examples/lang/generics.panda +++ b/examples/lang/generics.panda @@ -1,9 +1,30 @@ module lang -require java:collections +main { + /* Parametrized instance */ + Foo parametrizedType = new Foo('test') + + /* Parametrized return type */ + String parametrizedValue = parametrizedType.getValue() + // Int invalidValue = genericType.getValue() /* Should not compile */ + + /* Parametrized arguments */ + parametrizedType.setValue(parametrizedValue) + // genericType.setValue(10) /* Should not compile */ -type Foo { + /* Parametrized reassignation */ + Foo sameParametrizedType = parametrizedType + Foo lowerParametrizedType = sameParametrizedType + Bar lowerBaseType = sameParametrizedType +} + +type Foo : Bar { + constructor (V barValue) { + base(barValue) + } +} +type Bar { internal mut V value constructor (V value) { @@ -17,17 +38,4 @@ type Foo { shared getValue () -> V { return value } - -} - -main { - Foo genericType = new Foo('test') - - /* Generic return type */ - String value = genericType.getValue() - // Int invalidValue = genericType.getValue() /* Should not compile */ - - /* Generic parameter */ - genericType.setValue(value) - // genericType.setValue(10) /* Should not compile */ } \ No newline at end of file diff --git a/panda-framework/src/main/java/org/panda_lang/language/architecture/type/PandaType.java b/panda-framework/src/main/java/org/panda_lang/language/architecture/type/PandaType.java index 930994834..4b4b078e7 100644 --- a/panda-framework/src/main/java/org/panda_lang/language/architecture/type/PandaType.java +++ b/panda-framework/src/main/java/org/panda_lang/language/architecture/type/PandaType.java @@ -53,6 +53,7 @@ public class PandaType extends AbstractMetadata implements Type { protected final Module module; protected final String kind; protected final State state; + protected final Option typeScope; protected final Completable> associated; protected final List bases = new ArrayList<>(); protected final Map> autocasts = new HashMap<>(); @@ -70,8 +71,9 @@ public PandaType(PandaTypeMetadata metadata) { this.kind = ValidationUtils.notNull(metadata.kind, "The kind of type is not defined"); this.state = ValidationUtils.notNull(metadata.state, "State of type is missing"); this.associated = ValidationUtils.notNull(metadata.associatedType, "Associated type is missing"); - + this.typeScope = Option.of(metadata.typeScope); ValidationUtils.notNull(metadata.bases, "Bases are not defined").forEach(this::addBase); + this.reference = new Reference(this); } @@ -245,6 +247,11 @@ public Completable> getAssociated() { return associated; } + @Override + public Option getTypeScope() { + return typeScope; + } + @Override public Option getTypeLoader() { return Option.of(typeLoader); diff --git a/panda-framework/src/main/java/org/panda_lang/language/architecture/type/PandaTypeMetadata.java b/panda-framework/src/main/java/org/panda_lang/language/architecture/type/PandaTypeMetadata.java index a6d953428..175f8b4d2 100644 --- a/panda-framework/src/main/java/org/panda_lang/language/architecture/type/PandaTypeMetadata.java +++ b/panda-framework/src/main/java/org/panda_lang/language/architecture/type/PandaTypeMetadata.java @@ -32,6 +32,7 @@ public class PandaTypeMetadata, TY protected Signature signature; protected Module module; protected Location location; + protected TypeScope typeScope; protected Completable> associatedType; protected List bases = new ArrayList<>(); protected String kind = Kind.TYPE; @@ -56,6 +57,11 @@ public BUILDER module(Module module) { return getThis(); } + public BUILDER typeScope(TypeScope typeScope) { + this.typeScope = typeScope; + return getThis(); + } + public BUILDER location(Location location) { this.location = location; return getThis(); diff --git a/panda-framework/src/main/java/org/panda_lang/language/architecture/type/Type.java b/panda-framework/src/main/java/org/panda_lang/language/architecture/type/Type.java index 3d83e8786..8234d36b0 100644 --- a/panda-framework/src/main/java/org/panda_lang/language/architecture/type/Type.java +++ b/panda-framework/src/main/java/org/panda_lang/language/architecture/type/Type.java @@ -155,6 +155,8 @@ default boolean is(String name) { */ Completable> getAssociated(); + Option getTypeScope(); + /** * Get state of type * diff --git a/panda-framework/src/main/java/org/panda_lang/language/architecture/type/TypeFrame.java b/panda-framework/src/main/java/org/panda_lang/language/architecture/type/TypeFrame.java index 12c3bf223..9eecb1801 100644 --- a/panda-framework/src/main/java/org/panda_lang/language/architecture/type/TypeFrame.java +++ b/panda-framework/src/main/java/org/panda_lang/language/architecture/type/TypeFrame.java @@ -27,13 +27,26 @@ public final class TypeFrame extends AbstractFrame { protected final int id; protected final Process process; - protected final Object[] baseArguments; - public TypeFrame(Process process, TypeScope scope, Object[] baseArguments) { - super(scope, scope.getType().getFields().getDeclaredProperties().size()); + protected TypeInstance typeInstance; + protected Object[] baseArguments; + + public TypeFrame(Process process, TypeScope scope) { + super(scope, scope.getReference().fetchType().getFields().getProperties().size()); this.id = ID.getAndIncrement(); this.process = process; + } + + public void setTypeInstance(TypeInstance typeInstance) { + this.typeInstance = typeInstance; + } + + public TypeInstance getTypeInstance() { + return typeInstance; + } + + public void setBaseArguments(Object[] baseArguments) { this.baseArguments = baseArguments; } @@ -51,7 +64,7 @@ public int getId() { @Override public String toString() { - return framedScope.getType().getSimpleName() + "#" + String.format("%06X", id & 0xFFFFF); + return framedScope.getReference().getSimpleName() + "#" + String.format("%06X", id & 0xFFFFF); } } diff --git a/panda-framework/src/main/java/org/panda_lang/language/architecture/type/TypeScope.java b/panda-framework/src/main/java/org/panda_lang/language/architecture/type/TypeScope.java index 629e378a8..cfd3769fa 100644 --- a/panda-framework/src/main/java/org/panda_lang/language/architecture/type/TypeScope.java +++ b/panda-framework/src/main/java/org/panda_lang/language/architecture/type/TypeScope.java @@ -17,82 +17,30 @@ package org.panda_lang.language.architecture.type; import org.jetbrains.annotations.Nullable; -import org.panda_lang.language.PandaFrameworkException; -import org.panda_lang.language.architecture.expression.Expression; import org.panda_lang.language.architecture.statement.AbstractFramedScope; import org.panda_lang.language.architecture.type.member.constructor.TypeConstructor; -import org.panda_lang.language.architecture.type.member.field.TypeField; -import org.panda_lang.language.architecture.type.member.parameter.ParameterUtils; -import org.panda_lang.language.architecture.type.member.parameter.PropertyParameter; import org.panda_lang.language.interpreter.source.Location; -import org.panda_lang.language.runtime.PandaRuntimeException; import org.panda_lang.language.runtime.ProcessStack; -import org.panda_lang.utilities.commons.ArrayUtils; -import org.panda_lang.utilities.commons.function.Option; - -import java.lang.reflect.Constructor; -import java.lang.reflect.InvocationTargetException; -import java.util.Arrays; -import java.util.List; public final class TypeScope extends AbstractFramedScope { - private final Type type; + private final Reference reference; - public TypeScope(Location location, Type type) { + public TypeScope(Location location, Reference reference) { super(location); - this.type = type; - } - - public TypeInstance createInstance(ProcessStack stack, @Nullable Object instance, TypeConstructor constructor, List parameters, Object[] arguments) throws Exception { - Object[] baseArguments = constructor.getBaseCall() - .flatMap(call -> Option.attempt(Exception.class, () -> call.evaluate(stack, instance))) - .orElseGet(() -> new Object[0]); - - TypeFrame typeFrame = new TypeFrame(stack.getProcess(), this, baseArguments); - TypeInstance typeInstance; - - try { - Constructor nativeConstructor = getConstructor(parameters); - typeInstance = nativeConstructor.newInstance(ArrayUtils.merge(typeFrame, arguments, Object[]::new)); - } catch (InvocationTargetException targetException) { - throw new PandaRuntimeException(targetException.getTargetException().getMessage(), targetException.getTargetException()); - } - - for (TypeField field : type.getFields().getDeclaredProperties()) { - if (!field.hasDefaultValue()) { - continue; - } - - if (field.isStatic()) { - field.fetchStaticValue(); // just init - continue; - } - - Expression expression = field.getDefaultValue(); - typeInstance.__panda__get_frame().set(field.getPointer(), expression.evaluate(stack, typeInstance)); - } - - return typeInstance; + this.reference = reference; } - @SuppressWarnings("unchecked") - private Constructor getConstructor(List parameters) { - Class[] parameterTypes = ArrayUtils.merge(TypeFrame.class, ParameterUtils.parametersToClasses(parameters), Class[]::new); - - try { - return (Constructor) type.getAssociated().get().getConstructor(parameterTypes); - } catch (NoSuchMethodException e) { - throw new PandaFrameworkException("Associated class does not implement " + Arrays.toString(parameterTypes) + " constructor"); - } + public TypeFrame revive(ProcessStack stack, @Nullable Object instance, TypeConstructor constructor, Object[] arguments) throws Exception { + return new TypeFrame(stack.getProcess(), this); } public Location getLocation() { return location; } - public Type getType() { - return type; + public Reference getReference() { + return reference; } } diff --git a/panda-framework/src/main/java/org/panda_lang/language/architecture/type/ClassGenerator.java b/panda-framework/src/main/java/org/panda_lang/language/architecture/type/generator/ClassGenerator.java similarity index 92% rename from panda-framework/src/main/java/org/panda_lang/language/architecture/type/ClassGenerator.java rename to panda-framework/src/main/java/org/panda_lang/language/architecture/type/generator/ClassGenerator.java index 65683b59f..5175f544e 100644 --- a/panda-framework/src/main/java/org/panda_lang/language/architecture/type/ClassGenerator.java +++ b/panda-framework/src/main/java/org/panda_lang/language/architecture/type/generator/ClassGenerator.java @@ -1,4 +1,4 @@ -package org.panda_lang.language.architecture.type; +package org.panda_lang.language.architecture.type.generator; import javassist.CannotCompileException; import javassist.ClassPool; @@ -9,6 +9,11 @@ import javassist.Modifier; import javassist.NotFoundException; import org.panda_lang.language.architecture.dynamic.Frame; +import org.panda_lang.language.architecture.type.Kind; +import org.panda_lang.language.architecture.type.State; +import org.panda_lang.language.architecture.type.Type; +import org.panda_lang.language.architecture.type.TypeFrame; +import org.panda_lang.language.architecture.type.TypeInstance; import org.panda_lang.language.architecture.type.member.constructor.TypeConstructor; import org.panda_lang.language.architecture.type.member.method.TypeMethod; import org.panda_lang.language.architecture.type.member.parameter.ParameterUtils; @@ -53,12 +58,16 @@ public CtClass allocate(Type type) { public void generate(Type type) throws CannotCompileException, NotFoundException { CtClass javaType = generatedClasses.get(type); + // supertype if (!javaType.isInterface() && type.getSuperclass().isDefined()) { javaType.setSuperclass(getCtClass(type.getSuperclass().get().fetchType())); } + boolean hasGeneratedSuperclass = ArrayUtils.contains(javaType.getSuperclass().getInterfaces(), CT_TYPE_INSTANCE_CLASS); + boolean generateFields = !hasGeneratedSuperclass && !javaType.isInterface(); + // interfaces for (TypedSignature baseSignature : type.getBases()) { @@ -71,7 +80,7 @@ public void generate(Type type) throws CannotCompileException, NotFoundException // fields - if (!javaType.isInterface()) { + if (generateFields) { CtField frameField = new CtField(CT_TYPE_FRAME_CLASS, "__panda__frame", javaType); javaType.addField(frameField); } @@ -81,7 +90,7 @@ public void generate(Type type) throws CannotCompileException, NotFoundException { javaType.addInterface(CT_TYPE_INSTANCE_CLASS); - if (!javaType.isInterface()) { + if (generateFields) { CtMethod getter = new CtMethod(CT_TYPE_FRAME_CLASS, "__panda__get_frame", new CtClass[0], javaType); getter.setBody("{ return $0.__panda__frame; }"); javaType.addMethod(getter); diff --git a/panda-framework/src/main/java/org/panda_lang/language/architecture/type/generator/ConstructorGenerator.java b/panda-framework/src/main/java/org/panda_lang/language/architecture/type/generator/ConstructorGenerator.java index f2aef7b37..00516fbbd 100644 --- a/panda-framework/src/main/java/org/panda_lang/language/architecture/type/generator/ConstructorGenerator.java +++ b/panda-framework/src/main/java/org/panda_lang/language/architecture/type/generator/ConstructorGenerator.java @@ -49,7 +49,7 @@ protected TypeConstructor generate(TypeLoader typeLoader) { .parameters(typeParameters) .type(type) .returnType(type.getSignature()) - .callback((pandaConstructor, frame, instance, arguments) -> constructor.newInstance(arguments)) + .invoker((pandaConstructor, frame, instance, arguments) -> constructor.newInstance(arguments)) .build(); } diff --git a/panda-framework/src/main/java/org/panda_lang/language/architecture/type/generator/MethodGenerator.java b/panda-framework/src/main/java/org/panda_lang/language/architecture/type/generator/MethodGenerator.java index a5e14ef81..f24bff14b 100644 --- a/panda-framework/src/main/java/org/panda_lang/language/architecture/type/generator/MethodGenerator.java +++ b/panda-framework/src/main/java/org/panda_lang/language/architecture/type/generator/MethodGenerator.java @@ -54,7 +54,7 @@ protected TypeMethod generate(TypeLoader typeLoader) { // TODO: Generate bytecode method.setAccessible(true); - MemberInvoker methodBody = (typeMethod, stack, instance, arguments) -> { + MemberInvoker methodBody = (typeMethod, stack, instance, arguments) -> { int amountOfArgs = arguments.length; int parameterCount = method.getParameterCount(); Object varargs = null; diff --git a/panda-framework/src/main/java/org/panda_lang/language/architecture/type/member/AbstractMember.java b/panda-framework/src/main/java/org/panda_lang/language/architecture/type/member/AbstractMember.java index 8340ef29d..53230a955 100644 --- a/panda-framework/src/main/java/org/panda_lang/language/architecture/type/member/AbstractMember.java +++ b/panda-framework/src/main/java/org/panda_lang/language/architecture/type/member/AbstractMember.java @@ -22,6 +22,7 @@ import org.panda_lang.language.architecture.type.signature.Signature; import org.panda_lang.language.interpreter.source.Localizable; import org.panda_lang.language.interpreter.source.Location; +import org.panda_lang.utilities.commons.ObjectUtils; import java.util.Collections; import java.util.List; @@ -59,7 +60,7 @@ public abstract static class PandaParametrizedExecutableBuilder callback; + protected MemberInvoker invoker; protected Visibility visibility = Visibility.OPEN; protected List parameters = Collections.emptyList(); protected boolean isNative; @@ -99,8 +100,8 @@ public T isNative(boolean isNative) { return returnThis(); } - public T callback(MemberInvoker callback) { - this.callback = callback; + public T invoker(MemberInvoker invoker) { + this.invoker = ObjectUtils.cast(invoker); return returnThis(); } diff --git a/panda-framework/src/main/java/org/panda_lang/language/architecture/type/member/AbstractParametrizedMember.java b/panda-framework/src/main/java/org/panda_lang/language/architecture/type/member/AbstractParametrizedMember.java index 2acf27637..a02fde37c 100644 --- a/panda-framework/src/main/java/org/panda_lang/language/architecture/type/member/AbstractParametrizedMember.java +++ b/panda-framework/src/main/java/org/panda_lang/language/architecture/type/member/AbstractParametrizedMember.java @@ -12,19 +12,19 @@ public abstract class AbstractParametrizedMember extends AbstractMember implements ParametrizedMember { private final List parameters; - private final MemberInvoker callback; + private final MemberInvoker invoker; protected AbstractParametrizedMember(PandaParametrizedExecutableBuilder builder) { super(builder); this.parameters = builder.parameters; - this.callback = builder.callback; + this.invoker = builder.invoker; } @Override @SuppressWarnings("unchecked") public Object invoke(ProcessStack stack, Object instance, Object... arguments) throws Exception { - return callback.invoke((E) this, stack, instance, arguments); + return invoker.invoke((E) this, stack, instance, arguments); } @Override diff --git a/panda-framework/src/main/java/org/panda_lang/language/architecture/type/member/MemberInvoker.java b/panda-framework/src/main/java/org/panda_lang/language/architecture/type/member/MemberInvoker.java index 376075485..80a1c7fcd 100644 --- a/panda-framework/src/main/java/org/panda_lang/language/architecture/type/member/MemberInvoker.java +++ b/panda-framework/src/main/java/org/panda_lang/language/architecture/type/member/MemberInvoker.java @@ -19,8 +19,8 @@ import org.jetbrains.annotations.Nullable; import org.panda_lang.language.runtime.ProcessStack; -public interface MemberInvoker { +public interface MemberInvoker { - Object invoke(E property, ProcessStack stack, @Nullable T instance, Object[] arguments) throws Exception; + R invoke(E property, ProcessStack stack, @Nullable T instance, Object[] arguments) throws Exception; } diff --git a/panda-framework/src/main/java/org/panda_lang/language/architecture/type/member/constructor/BaseCall.java b/panda-framework/src/main/java/org/panda_lang/language/architecture/type/member/constructor/BaseCall.java index a8519130b..518466449 100644 --- a/panda-framework/src/main/java/org/panda_lang/language/architecture/type/member/constructor/BaseCall.java +++ b/panda-framework/src/main/java/org/panda_lang/language/architecture/type/member/constructor/BaseCall.java @@ -17,24 +17,43 @@ package org.panda_lang.language.architecture.type.member.constructor; import org.jetbrains.annotations.Nullable; +import org.panda_lang.language.architecture.dynamic.AbstractExecutableStatement; import org.panda_lang.language.architecture.expression.Expression; import org.panda_lang.language.architecture.expression.ExpressionEvaluator; import org.panda_lang.language.architecture.expression.ExpressionUtils; -import org.panda_lang.language.architecture.statement.AbstractStatement; +import org.panda_lang.language.architecture.type.TypeInstance; +import org.panda_lang.language.architecture.type.member.constructor.ConstructorScope.ConstructorFrame; import org.panda_lang.language.interpreter.source.Location; import org.panda_lang.language.runtime.ProcessStack; +import org.panda_lang.utilities.commons.function.Option; import java.util.List; -public final class BaseCall extends AbstractStatement implements ExpressionEvaluator { +public final class BaseCall extends AbstractExecutableStatement implements ExpressionEvaluator { + private final TypeConstructor baseConstructor; private final List arguments; - public BaseCall(Location location, List arguments) { + public BaseCall(Location location, TypeConstructor baseConstructor, List arguments) { super(location); + this.baseConstructor = baseConstructor; this.arguments = arguments; } + @Override + public @Nullable Object execute(ProcessStack stack, Object instance) throws Exception { + Option constructorScope = baseConstructor.getConstructorScope(); + + if (constructorScope.isEmpty()) { + return instance; + } + + ConstructorFrame constructorFrame = (ConstructorFrame) instance; + TypeInstance typeInstance = constructorFrame.getTypeFrame().getTypeInstance(); + + return constructorScope.get().invoke(baseConstructor, stack, typeInstance, typeInstance.__panda__get_frame().getBaseArguments()); + } + @Override public Object[] evaluate(ProcessStack stack, @Nullable Object instance) throws Exception { return ExpressionUtils.evaluate(stack, instance, arguments); @@ -44,4 +63,8 @@ public List getArguments() { return arguments; } + public TypeConstructor getBaseConstructor() { + return baseConstructor; + } + } diff --git a/panda-framework/src/main/java/org/panda_lang/language/architecture/type/member/constructor/ConstructorFrame.java b/panda-framework/src/main/java/org/panda_lang/language/architecture/type/member/constructor/ConstructorFrame.java deleted file mode 100644 index 934b24625..000000000 --- a/panda-framework/src/main/java/org/panda_lang/language/architecture/type/member/constructor/ConstructorFrame.java +++ /dev/null @@ -1,20 +0,0 @@ -package org.panda_lang.language.architecture.type.member.constructor; - -import org.panda_lang.language.architecture.type.member.MemberFrameImpl; -import org.panda_lang.language.architecture.type.TypeInstance; -import org.panda_lang.language.architecture.type.member.parameter.ParameterUtils; -import org.panda_lang.language.runtime.ProcessStack; - -public final class ConstructorFrame extends MemberFrameImpl { - - public ConstructorFrame(ConstructorScope scope, TypeInstance instance) { - super(scope, instance.__panda__get_frame()); - } - - public TypeInstance initialize(ProcessStack stack, TypeInstance typeInstance, Object[] parameters) throws Exception { - ParameterUtils.assignValues(this, parameters); - stack.callFrame(typeInstance, this); - return typeInstance; - } - -} diff --git a/panda-framework/src/main/java/org/panda_lang/language/architecture/type/member/constructor/ConstructorScope.java b/panda-framework/src/main/java/org/panda_lang/language/architecture/type/member/constructor/ConstructorScope.java index 1eb368c6a..15245e45a 100644 --- a/panda-framework/src/main/java/org/panda_lang/language/architecture/type/member/constructor/ConstructorScope.java +++ b/panda-framework/src/main/java/org/panda_lang/language/architecture/type/member/constructor/ConstructorScope.java @@ -16,26 +16,108 @@ package org.panda_lang.language.architecture.type.member.constructor; +import org.jetbrains.annotations.Nullable; +import org.panda_lang.language.PandaFrameworkException; +import org.panda_lang.language.architecture.dynamic.Frameable; +import org.panda_lang.language.architecture.expression.Expression; +import org.panda_lang.language.architecture.statement.AbstractPropertyFramedScope; +import org.panda_lang.language.architecture.type.Type; +import org.panda_lang.language.architecture.type.TypeFrame; import org.panda_lang.language.architecture.type.TypeInstance; +import org.panda_lang.language.architecture.type.member.MemberFrameImpl; +import org.panda_lang.language.architecture.type.member.MemberInvoker; +import org.panda_lang.language.architecture.type.member.field.TypeField; +import org.panda_lang.language.architecture.type.member.parameter.ParameterUtils; import org.panda_lang.language.architecture.type.member.parameter.PropertyParameter; import org.panda_lang.language.interpreter.source.Localizable; -import org.panda_lang.utilities.commons.function.Option; -import org.panda_lang.language.interpreter.source.Location; import org.panda_lang.language.runtime.ProcessStack; -import org.panda_lang.language.architecture.statement.AbstractPropertyFramedScope; +import org.panda_lang.language.runtime.Result; +import org.panda_lang.language.runtime.Status; +import org.panda_lang.utilities.commons.ArrayUtils; +import org.panda_lang.utilities.commons.UnsafeUtils; import org.panda_lang.utilities.commons.collection.Lists; +import org.panda_lang.utilities.commons.function.Option; +import java.lang.reflect.Constructor; +import java.lang.reflect.InvocationTargetException; +import java.util.Arrays; import java.util.List; +import java.util.Objects; -public final class ConstructorScope extends AbstractPropertyFramedScope { +public final class ConstructorScope extends AbstractPropertyFramedScope implements MemberInvoker { + + private static final Object[] EMPTY = new Object[0]; public ConstructorScope(Localizable localizable, List parameters) { super(localizable, parameters); } @Override - public ConstructorFrame revive(ProcessStack stack, Object instance) { - return new ConstructorFrame(this, (TypeInstance) instance); + public ConstructorFrame revive(ProcessStack stack, Object typeInstance) { + return new ConstructorFrame(this, (TypeFrame) typeInstance); + } + + @Override + public Object invoke(TypeConstructor constructor, ProcessStack stack, @Nullable Frameable frameable, Object[] arguments) throws Exception { + TypeFrame typeFrame = (TypeFrame) Objects.requireNonNull(frameable).__panda__to_frame(); + + ConstructorFrame constructorFrame = revive(stack, typeFrame); + ParameterUtils.assignValues(constructorFrame, arguments); + + constructor.getBaseCall() + .map(call -> { + try { + return (Object[]) stack.callCustomFrame(frameable, typeFrame, () -> { + return stack.callCustomFrame(typeFrame, constructorFrame, () -> { + return new Result<>(Status.RETURN, call.evaluate(stack, constructorFrame)); + }); + }).getResult(); + } catch (Exception exception) { + return UnsafeUtils.throwException(exception); + } + }) + .orElse(EMPTY) + .peek(typeFrame::setBaseArguments); + + TypeInstance typeInstance; + + try { + Constructor nativeConstructor = getConstructor(constructor.getType(), constructor.getParameters()); + typeInstance = nativeConstructor.newInstance(ArrayUtils.merge(typeFrame, arguments, Object[]::new)); + } catch (InvocationTargetException targetException) { + return UnsafeUtils.throwException(targetException.getTargetException()); + } + + typeFrame.setTypeInstance(typeInstance); + + for (TypeField field : constructor.getType().getFields().getDeclaredProperties()) { + if (!field.hasDefaultValue()) { + continue; + } + + if (field.isStatic()) { + field.fetchStaticValue(); // just init + continue; + } + + Expression expression = field.getDefaultValue(); + typeInstance.__panda__get_frame().set(field.getPointer(), expression.evaluate(stack, typeInstance)); + } + + stack.callFrame(typeFrame, constructorFrame); + + return typeInstance; + } + + @SuppressWarnings("unchecked") + private Constructor getConstructor(Type type, List parameters) { + Class[] parameterTypes = ArrayUtils.merge(TypeFrame.class, ParameterUtils.parametersToClasses(parameters), Class[]::new); + + try { + return (Constructor) type.getAssociated().get().getConstructor(parameterTypes); + } catch (NoSuchMethodException e) { + throw new PandaFrameworkException("Associated class does not implement " + Arrays.toString(parameterTypes) + " constructor"); + } } public Option getBaseCall() { @@ -49,4 +131,19 @@ public List getParameters() { return parameters; } + public static final class ConstructorFrame extends MemberFrameImpl { + + private final TypeFrame typeFrame; + + public ConstructorFrame(ConstructorScope scope, TypeFrame frame) { + super(scope, frame); + this.typeFrame = frame; + } + + public TypeFrame getTypeFrame() { + return typeFrame; + } + + } + } diff --git a/panda-framework/src/main/java/org/panda_lang/language/architecture/type/member/constructor/PandaConstructor.java b/panda-framework/src/main/java/org/panda_lang/language/architecture/type/member/constructor/PandaConstructor.java index eaae72522..fc72d57ec 100644 --- a/panda-framework/src/main/java/org/panda_lang/language/architecture/type/member/constructor/PandaConstructor.java +++ b/panda-framework/src/main/java/org/panda_lang/language/architecture/type/member/constructor/PandaConstructor.java @@ -26,11 +26,13 @@ public final class PandaConstructor extends AbstractParametrizedMember implements TypeConstructor { + private final @Nullable ConstructorScope constructorScope; private final @Nullable Lazy> baseCallArgumentsSupplier; private PandaConstructor(PandaConstructorBuilder builder) { super(builder); - this.baseCallArgumentsSupplier = builder.baseCallArgumentsSupplier; + this.constructorScope = builder.constructorScope; + this.baseCallArgumentsSupplier = builder.baseCallSupplier; } @Override @@ -38,6 +40,11 @@ public Option getBaseCall() { return Option.of(baseCallArgumentsSupplier).flatMap(Supplier::get); } + @Override + public Option getConstructorScope() { + return Option.of(constructorScope); + } + @Override public String toString() { return getType().getName() + "(" + ParameterUtils.toString(getParameters()) + ")"; @@ -49,12 +56,18 @@ public static PandaConstructorBuilder builder() { public static final class PandaConstructorBuilder extends PandaParametrizedExecutableBuilder { - private Lazy> baseCallArgumentsSupplier; + private ConstructorScope constructorScope; + private Lazy> baseCallSupplier; private PandaConstructorBuilder() { } - public PandaConstructorBuilder baseCall(Supplier> baseCallArgumentsSupplier) { - this.baseCallArgumentsSupplier = new Lazy<>(baseCallArgumentsSupplier); + public PandaConstructorBuilder scope(ConstructorScope scope) { + this.constructorScope = scope; + return this; + } + + public PandaConstructorBuilder baseCall(Supplier> baseCallSupplier) { + this.baseCallSupplier = new Lazy<>(baseCallSupplier); return this; } diff --git a/panda-framework/src/main/java/org/panda_lang/language/architecture/type/member/constructor/TypeConstructor.java b/panda-framework/src/main/java/org/panda_lang/language/architecture/type/member/constructor/TypeConstructor.java index 769c7c2c2..da04dd258 100644 --- a/panda-framework/src/main/java/org/panda_lang/language/architecture/type/member/constructor/TypeConstructor.java +++ b/panda-framework/src/main/java/org/panda_lang/language/architecture/type/member/constructor/TypeConstructor.java @@ -32,4 +32,6 @@ public interface TypeConstructor extends ParametrizedMember { */ Option getBaseCall(); + Option getConstructorScope(); + } diff --git a/panda-framework/src/main/java/org/panda_lang/language/architecture/type/member/method/MethodScope.java b/panda-framework/src/main/java/org/panda_lang/language/architecture/type/member/method/MethodScope.java index 04490fcfb..18cd39b68 100644 --- a/panda-framework/src/main/java/org/panda_lang/language/architecture/type/member/method/MethodScope.java +++ b/panda-framework/src/main/java/org/panda_lang/language/architecture/type/member/method/MethodScope.java @@ -30,7 +30,7 @@ import java.util.List; -public final class MethodScope extends AbstractPropertyFramedScope { +public final class MethodScope extends AbstractPropertyFramedScope implements MemberInvoker { public MethodScope(Localizable localizable, List parameters) { super(localizable, parameters); @@ -41,37 +41,23 @@ public MethodFrame revive(ProcessStack stack, Object instance) { return new MethodFrame(this, (Frame) instance); } - public PandaMethodCallback toCallback() { - return new PandaMethodCallback(this); - } - - public static final class MethodFrame extends MemberFrameImpl { + @Override + public @Nullable Object invoke(TypeMethod method, ProcessStack stack, @Nullable Frameable instance, Object[] arguments) throws Exception { + MethodFrame scopeInstance = revive(stack, instance != null ? instance.__panda__to_frame() : null); + ParameterUtils.assignValues(scopeInstance, arguments); + Result result = stack.callFrame(scopeInstance, scopeInstance); - public MethodFrame(MethodScope method, Frame instance) { - super(method, instance); + if (result == null) { + return null; } + return result.getResult(); } - public static final class PandaMethodCallback implements MemberInvoker { - - private final MethodScope scope; - - public PandaMethodCallback(MethodScope scope) { - this.scope = scope; - } - - @Override - public @Nullable Object invoke(TypeMethod method, ProcessStack stack, @Nullable Frameable instance, Object[] arguments) throws Exception { - MethodFrame scopeInstance = scope.revive(stack, instance != null ? instance.__panda__to_frame() : null); - ParameterUtils.assignValues(scopeInstance, arguments); - Result result = stack.callFrame(scopeInstance, scopeInstance); - - if (result == null) { - return null; - } + public static final class MethodFrame extends MemberFrameImpl { - return result.getResult(); + public MethodFrame(MethodScope method, Frame instance) { + super(method, instance); } } diff --git a/panda-framework/src/main/java/org/panda_lang/language/architecture/type/member/method/PandaMethod.java b/panda-framework/src/main/java/org/panda_lang/language/architecture/type/member/method/PandaMethod.java index 4644876d1..6f9ced594 100644 --- a/panda-framework/src/main/java/org/panda_lang/language/architecture/type/member/method/PandaMethod.java +++ b/panda-framework/src/main/java/org/panda_lang/language/architecture/type/member/method/PandaMethod.java @@ -24,7 +24,7 @@ public final class PandaMethod extends AbstractParametrizedMember implements TypeMethod { - private final MemberInvoker methodBody; + private final MemberInvoker methodBody; private final boolean isAbstract; private final boolean isStatic; private final boolean isNative; @@ -39,8 +39,8 @@ protected PandaMethod(PandaMethodBuilder builder) { } @Override - public Object invoke(ProcessStack stack, Object instance, Object... parameters) throws Exception { - return methodBody.invoke(this, stack, instance, parameters); + public Object invoke(ProcessStack stack, Object instance, Object... arguments) throws Exception { + return methodBody.invoke(this, stack, instance, arguments); } @Override @@ -69,7 +69,7 @@ public static PandaMethodBuilder builder() { public static final class PandaMethodBuilder extends PandaParametrizedExecutableBuilder { - protected MemberInvoker body; + protected MemberInvoker body; protected boolean isAbstract; protected boolean isStatic; protected boolean isNative; @@ -77,11 +77,11 @@ public static final class PandaMethodBuilder extends PandaParametrizedExecutable private PandaMethodBuilder() { } public PandaMethodBuilder body(MethodScope scope) { - return customBody(ObjectUtils.cast(scope.toCallback())); + return customBody(scope); } - public PandaMethodBuilder customBody(MemberInvoker callback) { - this.body = callback; + public PandaMethodBuilder customBody(MemberInvoker invoker) { + this.body = ObjectUtils.cast(invoker); return this; } diff --git a/panda-framework/src/main/java/org/panda_lang/language/architecture/type/signature/AdjustedExpression.java b/panda-framework/src/main/java/org/panda_lang/language/architecture/type/signature/AdjustedExpression.java index 2cfe9caf0..fe1b69358 100644 --- a/panda-framework/src/main/java/org/panda_lang/language/architecture/type/signature/AdjustedExpression.java +++ b/panda-framework/src/main/java/org/panda_lang/language/architecture/type/signature/AdjustedExpression.java @@ -16,10 +16,10 @@ package org.panda_lang.language.architecture.type.signature; -import org.jetbrains.annotations.Nullable; import org.panda_lang.language.architecture.expression.Expression; import org.panda_lang.language.architecture.expression.ExpressionUtils; import org.panda_lang.language.architecture.expression.ExpressionValueType; +import org.panda_lang.language.architecture.type.member.MemberInvoker; import org.panda_lang.language.architecture.type.member.ParametrizedMember; import org.panda_lang.language.runtime.ProcessStack; @@ -28,30 +28,34 @@ public final class AdjustedExpression implements Expression { private final ParametrizedMember member; - private final Expression instanceExpression; + private final MemberInvoker instanceInvoker; private final List arguments; private final Signature returnType; - public AdjustedExpression(@Nullable Expression instance, ParametrizedMember member, List arguments) { + public AdjustedExpression(MemberInvoker instanceInvoker, Signature instanceSignature, ParametrizedMember member, List arguments) { this.member = member; - this.instanceExpression = instance; + this.instanceInvoker = instanceInvoker; this.arguments = arguments; - if (instanceExpression == null) { + if (instanceSignature == null) { this.returnType = member.getReturnType(); } else { - this.returnType = member.getReturnType().apply(instanceExpression); + this.returnType = member.getReturnType().apply(instanceSignature); } } + public AdjustedExpression(Expression instance, ParametrizedMember member, List arguments) { + this((property, stack, currentInstance, args) -> instance.evaluate(stack, currentInstance), instance.getSignature(), member, arguments); + } + @Override @SuppressWarnings("unchecked") public Object evaluate(ProcessStack stack, Object instance) throws Exception { Object[] values = ExpressionUtils.evaluate(stack, instance, arguments); - if (instanceExpression != null) { - instance = instanceExpression.evaluate(stack, instance); + if (instanceInvoker != null) { + instance = instanceInvoker.invoke(member, stack, instance, values); } return member.invoke(stack, instance, values); diff --git a/panda-framework/src/main/java/org/panda_lang/language/interpreter/logging/ErrorFormatter.java b/panda-framework/src/main/java/org/panda_lang/language/interpreter/logging/ErrorFormatter.java index 50363039b..928ef54b2 100644 --- a/panda-framework/src/main/java/org/panda_lang/language/interpreter/logging/ErrorFormatter.java +++ b/panda-framework/src/main/java/org/panda_lang/language/interpreter/logging/ErrorFormatter.java @@ -98,7 +98,7 @@ else if (throwable instanceof PandaProcessFailure) { logger.error(""); logger.error("Stack:"); - for (int index = 0; index < 3 && index < stackTrace.length; index++) { + for (int index = 0; index < 5 && index < stackTrace.length; index++) { StackTraceElement stackTraceElement = stackTrace[index]; logger.error(" at " + stackTraceElement.toString()); } diff --git a/panda-framework/src/main/java/org/panda_lang/language/interpreter/parser/PandaParserFailure.java b/panda-framework/src/main/java/org/panda_lang/language/interpreter/parser/PandaParserFailure.java index 78a0ade68..4de59f4cd 100644 --- a/panda-framework/src/main/java/org/panda_lang/language/interpreter/parser/PandaParserFailure.java +++ b/panda-framework/src/main/java/org/panda_lang/language/interpreter/parser/PandaParserFailure.java @@ -30,7 +30,7 @@ public PandaParserFailure(Contextual contextual, Location location, String me } public PandaParserFailure(Contextual contextual, Location location, String message, @Nullable String note) { - this(contextual, contextual.toContext().getSource().getLine(location.getLine()), message, note); + this(contextual, contextual.toContext().getScriptSource().getLine(location.getLine()), message, note); } public PandaParserFailure(Contextual contextual, String message) { diff --git a/panda/src/main/java/org/panda_lang/panda/language/resource/syntax/expressions/subparsers/ConstructorExpressionSubparser.java b/panda/src/main/java/org/panda_lang/panda/language/resource/syntax/expressions/subparsers/ConstructorExpressionSubparser.java index 421b6090a..c1814ba69 100644 --- a/panda/src/main/java/org/panda_lang/panda/language/resource/syntax/expressions/subparsers/ConstructorExpressionSubparser.java +++ b/panda/src/main/java/org/panda_lang/panda/language/resource/syntax/expressions/subparsers/ConstructorExpressionSubparser.java @@ -21,6 +21,9 @@ import org.panda_lang.language.architecture.type.State; import org.panda_lang.language.architecture.type.Type; import org.panda_lang.language.architecture.type.VisibilityComparator; +import org.panda_lang.language.architecture.type.member.MemberInvoker; +import org.panda_lang.language.architecture.type.member.ParametrizedMember; +import org.panda_lang.language.architecture.type.member.constructor.TypeConstructor; import org.panda_lang.language.architecture.type.signature.AdjustedExpression; import org.panda_lang.language.architecture.type.signature.Signature; import org.panda_lang.language.interpreter.parser.Context; @@ -37,6 +40,8 @@ import org.panda_lang.language.resource.syntax.auxiliary.Section; import org.panda_lang.language.resource.syntax.keyword.Keywords; import org.panda_lang.language.resource.syntax.separator.Separators; +import org.panda_lang.language.runtime.PandaRuntimeException; +import org.panda_lang.language.runtime.ProcessStack; import org.panda_lang.panda.language.interpreter.parser.PandaSourceReader; import org.panda_lang.panda.language.resource.syntax.type.SignatureParser; import org.panda_lang.utilities.commons.function.Option; @@ -127,10 +132,25 @@ private static final class ConstructorWorker extends AbstractExpressionSubparser Snippet argsSource = next.toToken(Section.class).getContent(); List arguments = ARGUMENT_PARSER.parse(context, argsSource); + Option typeConstructor = type.getConstructors().getConstructor(arguments); - return type.getConstructors().getConstructor(arguments) - .map(constructor -> ExpressionResult.of(new AdjustedExpression(null, constructor, arguments))) - .orElseGet(() -> ExpressionResult.error(type.getSimpleName() + " does not have constructor with the required parameters: " + arguments, next)); + if (typeConstructor.isEmpty()) { + return ExpressionResult.error(type.getSimpleName() + " does not have constructor with the required parameters: " + arguments, next); + } + + //noinspection Convert2Lambda + return ExpressionResult.of(new AdjustedExpression(new MemberInvoker() { + @Override + public Object invoke(ParametrizedMember property, ProcessStack stack, @Nullable Object instance, Object[] args) { + return type.getTypeScope().map(scope -> { + try { + return scope.revive(stack, instance, typeConstructor.get(), args); + } catch (Exception exception) { + throw new PandaRuntimeException("Cannot create scope instance", exception); + } + }).getOrNull(); + } + }, signature, typeConstructor.get(), arguments)); } } diff --git a/panda/src/main/java/org/panda_lang/panda/language/resource/syntax/expressions/subparsers/DeclarationExpressionSubparser.java b/panda/src/main/java/org/panda_lang/panda/language/resource/syntax/expressions/subparsers/DeclarationExpressionSubparser.java index b1e4a2f8b..567859828 100644 --- a/panda/src/main/java/org/panda_lang/panda/language/resource/syntax/expressions/subparsers/DeclarationExpressionSubparser.java +++ b/panda/src/main/java/org/panda_lang/panda/language/resource/syntax/expressions/subparsers/DeclarationExpressionSubparser.java @@ -5,7 +5,9 @@ import org.panda_lang.language.architecture.statement.Variable; import org.panda_lang.language.architecture.statement.VariableAccessor; import org.panda_lang.language.architecture.statement.VariableData; +import org.panda_lang.language.architecture.type.signature.Signature; import org.panda_lang.language.interpreter.parser.Context; +import org.panda_lang.language.interpreter.parser.PandaParserFailure; import org.panda_lang.language.interpreter.parser.expression.ExpressionContext; import org.panda_lang.language.interpreter.parser.expression.ExpressionResult; import org.panda_lang.language.interpreter.parser.expression.ExpressionSubparser; @@ -17,6 +19,7 @@ import org.panda_lang.language.resource.syntax.keyword.Keywords; import org.panda_lang.panda.language.interpreter.parser.PandaSourceReader; import org.panda_lang.panda.language.resource.syntax.scope.variable.VariableDataInitializer; +import org.panda_lang.panda.language.resource.syntax.type.SignatureParser; import org.panda_lang.panda.language.resource.syntax.type.SignatureSource; import org.panda_lang.utilities.commons.function.Option; @@ -44,6 +47,8 @@ public String name() { private static final class Worker extends AbstractExpressionSubparserWorker implements ExpressionSubparserWorker { + private static final SignatureParser SIGNATURE_PARSER = new SignatureParser(); + @Override public @Nullable ExpressionResult next(ExpressionContext expressionContext, TokenInfo token) { if (token.getType() != TokenTypes.UNKNOWN && token.getType() != TokenTypes.KEYWORD) { @@ -73,12 +78,20 @@ private static final class Worker extends AbstractExpressionSubparserWorker impl return null; } + Signature signature; + + try { + signature = SIGNATURE_PARSER.parse(expressionContext, signatureSource.get(), false, null); + } catch (PandaParserFailure failure) { + return ExpressionResult.error(failure.getMessage(), failure.getIndicatedSource().getSource()); + } + expressionContext.getSynchronizedSource().next(stream.getReadLength() - 1); Context context = expressionContext.toContext(); Scope scope = context.getScope(); VariableDataInitializer dataInitializer = new VariableDataInitializer(context, scope); - VariableData variableData = dataInitializer.createVariableData(signatureSource.get(), name.get(), mutable, nillable); + VariableData variableData = dataInitializer.createVariableData(signature, name.get(), mutable, nillable); Variable variable = scope.createVariable(variableData); return ExpressionResult.of(new VariableExpression(new VariableAccessor(variable))); diff --git a/panda/src/main/java/org/panda_lang/panda/language/resource/syntax/expressions/subparsers/FieldExpression.java b/panda/src/main/java/org/panda_lang/panda/language/resource/syntax/expressions/subparsers/FieldExpression.java index 900fcdc37..4ac5f9ff5 100644 --- a/panda/src/main/java/org/panda_lang/panda/language/resource/syntax/expressions/subparsers/FieldExpression.java +++ b/panda/src/main/java/org/panda_lang/panda/language/resource/syntax/expressions/subparsers/FieldExpression.java @@ -53,7 +53,7 @@ public Object evaluate(ProcessStack stack, Object instance) throws Exception { Object value = accessor.getValue(stack, instance); - if (value == null) { + if (value == null && !field.isNillable()) { throw new PandaRuntimeException("Field " + field + " has not been initialized"); } diff --git a/panda/src/main/java/org/panda_lang/panda/language/resource/syntax/scope/variable/VariableDataInitializer.java b/panda/src/main/java/org/panda_lang/panda/language/resource/syntax/scope/variable/VariableDataInitializer.java index 8a5d3ec41..cc6350668 100644 --- a/panda/src/main/java/org/panda_lang/panda/language/resource/syntax/scope/variable/VariableDataInitializer.java +++ b/panda/src/main/java/org/panda_lang/panda/language/resource/syntax/scope/variable/VariableDataInitializer.java @@ -56,7 +56,13 @@ public VariableData createVariableData(Snippetable declaration, boolean mutable, return createVariableData(signatures.get(0), name, mutable, nillable); } + public VariableData createVariableData(SignatureSource signatureSource, Snippetable name, boolean mutable, boolean nillable) { + Signature signature = SIGNATURE_PARSER.parse(context, signatureSource, false, null); + return createVariableData(signature, name, mutable, nillable); + } + + public VariableData createVariableData(Signature signature, Snippetable name, boolean mutable, boolean nillable) { Snippet nameSource = name.toSnippet(); if (nameSource.size() > 1) { @@ -70,8 +76,7 @@ public VariableData createVariableData(SignatureSource signatureSource, Snippeta } // TODO: parent signature - Signature signature = SIGNATURE_PARSER.parse(context, signatureSource, false, null); - VisibilityComparator.requireAccess(signature.toTyped().fetchType(), context, signatureSource.getName()); + VisibilityComparator.requireAccess(signature.toTyped().fetchType(), context, nameSource); return new PandaVariableData(signature, nameSource.asSource(), mutable, nillable); } diff --git a/panda/src/main/java/org/panda_lang/panda/language/resource/syntax/type/BaseCallParser.java b/panda/src/main/java/org/panda_lang/panda/language/resource/syntax/type/BaseCallParser.java index 0053c606e..9c70f5c35 100644 --- a/panda/src/main/java/org/panda_lang/panda/language/resource/syntax/type/BaseCallParser.java +++ b/panda/src/main/java/org/panda_lang/panda/language/resource/syntax/type/BaseCallParser.java @@ -22,6 +22,7 @@ import org.panda_lang.language.architecture.type.TypeContext; import org.panda_lang.language.architecture.type.member.constructor.BaseCall; import org.panda_lang.language.architecture.type.member.constructor.ConstructorScope; +import org.panda_lang.language.architecture.type.member.constructor.TypeConstructor; import org.panda_lang.language.interpreter.parser.Context; import org.panda_lang.language.interpreter.parser.ContextParser; import org.panda_lang.language.interpreter.parser.PandaParserFailure; @@ -81,13 +82,15 @@ public Option> parse(Context contex } List expressions = ARGUMENTS_PARSER.parse(context, arguments.get()); - BaseCall baseCall = new BaseCall(context.toLocation(), expressions); - parent.addStatement(baseCall); + Option constructor = type.getSuperclass().get().fetchType().getConstructors().getConstructor(expressions); - type.getSuperclass().get().fetchType().getConstructors().getConstructor(expressions).onEmpty(() -> { + constructor.onEmpty(() -> { throw new PandaParserFailure(context, context.getSource(), "Base type does not contain constructor with the given parameters"); }); + BaseCall baseCall = new BaseCall(context.toLocation(), constructor.get(), expressions); + parent.addStatement(baseCall); + return Option.ofCompleted(baseCall); } diff --git a/panda/src/main/java/org/panda_lang/panda/language/resource/syntax/type/ConstructorParser.java b/panda/src/main/java/org/panda_lang/panda/language/resource/syntax/type/ConstructorParser.java index 79ce1c3d5..371736527 100644 --- a/panda/src/main/java/org/panda_lang/panda/language/resource/syntax/type/ConstructorParser.java +++ b/panda/src/main/java/org/panda_lang/panda/language/resource/syntax/type/ConstructorParser.java @@ -16,10 +16,9 @@ package org.panda_lang.panda.language.resource.syntax.type; +import org.panda_lang.language.architecture.type.Type; import org.panda_lang.language.architecture.type.TypeContext; -import org.panda_lang.language.architecture.type.TypeInstance; import org.panda_lang.language.architecture.type.TypeScope; -import org.panda_lang.language.architecture.type.member.constructor.ConstructorFrame; import org.panda_lang.language.architecture.type.member.constructor.ConstructorScope; import org.panda_lang.language.architecture.type.member.constructor.PandaConstructor; import org.panda_lang.language.architecture.type.member.constructor.TypeConstructor; @@ -86,28 +85,26 @@ public Option> parse(Context parameters = PARAMETER_PARSER.parse(context, parametersSource.get()); ConstructorScope constructorScope = new ConstructorScope(sourceReader.toLocation(), parameters); TypeScope typeScope = context.getSubject().getScope(); + Type type = typeScope.getReference().fetchType(); TypeConstructor constructor = PandaConstructor.builder() - .type(typeScope.getType()) - .returnType(typeScope.getType().getSignature()) + .type(type) + .returnType(type.getSignature()) .location(context.getSource()) .parameters(parameters) .baseCall(constructorScope::getBaseCall) - .callback((typeConstructor, stack, instance, arguments) -> { - TypeInstance typeInstance = typeScope.createInstance(stack, instance, typeConstructor, parameters, arguments); - ConstructorFrame constructorInstance = constructorScope.revive(stack, typeInstance); - return constructorInstance.initialize(stack, typeInstance, arguments); - }) + .scope(constructorScope) + .invoker(constructorScope) .build(); - typeScope.getType().getConstructors().declare(constructor); + type.getConstructors().declare(constructor); context.getStageService().delegate("parse constructor body", Phases.CONTENT, Layer.NEXT_DEFAULT, bodyPhase -> { scopeParser.parse(context, constructorScope, body.get()); }); context.getStageService().delegate("verify base call", Phases.VERIFY, Layer.NEXT_DEFAULT, verifyPhase -> { - typeScope.getType().getSuperclass() + type.getSuperclass() .filterNot(superclass -> superclass.fetchType().is("panda::Object")) .filterNot(superclass -> superclass.fetchType().getConstructors().getConstructor(Collections.emptyList()).isDefined()) .filterNot(superclass -> constructorScope.getBaseCall().isDefined()) diff --git a/panda/src/main/java/org/panda_lang/panda/language/resource/syntax/type/TypeParser.java b/panda/src/main/java/org/panda_lang/panda/language/resource/syntax/type/TypeParser.java index ccd3f1e8a..a5afe676e 100644 --- a/panda/src/main/java/org/panda_lang/panda/language/resource/syntax/type/TypeParser.java +++ b/panda/src/main/java/org/panda_lang/panda/language/resource/syntax/type/TypeParser.java @@ -19,7 +19,6 @@ import javassist.CannotCompileException; import javassist.NotFoundException; import org.panda_lang.language.architecture.module.Module; -import org.panda_lang.language.architecture.type.ClassGenerator; import org.panda_lang.language.architecture.type.PandaType; import org.panda_lang.language.architecture.type.Reference; import org.panda_lang.language.architecture.type.State; @@ -27,6 +26,7 @@ import org.panda_lang.language.architecture.type.TypeContext; import org.panda_lang.language.architecture.type.TypeScope; import org.panda_lang.language.architecture.type.Visibility; +import org.panda_lang.language.architecture.type.generator.ClassGenerator; import org.panda_lang.language.architecture.type.member.constructor.PandaConstructor; import org.panda_lang.language.architecture.type.member.field.TypeField; import org.panda_lang.language.architecture.type.member.method.TypeMethod; @@ -57,7 +57,6 @@ import org.panda_lang.utilities.commons.function.PandaStream; import java.util.ArrayList; -import java.util.Collections; import java.util.List; import java.util.stream.Collectors; @@ -148,12 +147,14 @@ public Option> parse(Context context) { Signature signature = SIGNATURE_PARSER.parse(context, signatureSource.get(), true, null); Completable> associatedType = new Completable<>(); + TypeScope scope = new TypeScope(reference.getLocation(), reference); Type type = PandaType.builder() .module(module) .name(reference.getSimpleName()) .signature(signature) .associatedType(associatedType) + .typeScope(scope) .kind(kind.get().getValue()) .state(State.of(kind.get().getValue())) .location(context.getSource().getLocation()) @@ -162,7 +163,6 @@ public Option> parse(Context context) { futureType.complete(type); TYPE_GENERATOR.allocate(type); - TypeScope scope = new TypeScope(reference.getLocation(), type); Context typeContext = context.forkCreator() .withSubject(new TypeContext(type, scope)) @@ -199,14 +199,11 @@ public Option> parse(Context context) { type.getConstructors().declare(PandaConstructor.builder() .type(type) - .callback((typeConstructor, frame, instance, arguments) -> { - return scope.createInstance(frame, instance, typeConstructor, Collections.emptyList(), arguments); - }) + .invoker((constructor, frame, instance, args) -> scope.revive(frame, instance, constructor, args)) .location(type.getLocation()) + .returnType(type.getSignature()) .build()); } - - }); stageService.delegate("verify " + type.getName() + "type properties", Phases.VERIFY, Layer.NEXT_DEFAULT, verifyPhase -> { diff --git a/panda/src/main/java/org/panda_lang/panda/shell/repl/ReplCreator.java b/panda/src/main/java/org/panda_lang/panda/shell/repl/ReplCreator.java index bd83c3de7..bb11833ae 100644 --- a/panda/src/main/java/org/panda_lang/panda/shell/repl/ReplCreator.java +++ b/panda/src/main/java/org/panda_lang/panda/shell/repl/ReplCreator.java @@ -19,7 +19,6 @@ import org.jetbrains.annotations.Nullable; import org.panda_lang.language.architecture.module.PandaModule; import org.panda_lang.language.architecture.statement.PandaVariableData; -import org.panda_lang.language.architecture.type.ClassGenerator; import org.panda_lang.language.architecture.type.Kind; import org.panda_lang.language.architecture.type.PandaType; import org.panda_lang.language.architecture.type.Reference; @@ -28,6 +27,7 @@ import org.panda_lang.language.architecture.type.TypeContext; import org.panda_lang.language.architecture.type.TypeScope; import org.panda_lang.language.architecture.type.Visibility; +import org.panda_lang.language.architecture.type.generator.ClassGenerator; import org.panda_lang.language.architecture.type.member.constructor.PandaConstructor; import org.panda_lang.language.architecture.type.member.method.PandaMethod; import org.panda_lang.language.architecture.type.signature.Relation; @@ -45,7 +45,6 @@ import org.panda_lang.utilities.commons.function.Completable; import org.panda_lang.utilities.commons.function.ThrowingFunction; -import java.util.Arrays; import java.util.Collections; import java.util.function.Supplier; @@ -81,12 +80,13 @@ public final class ReplCreator { ClassGenerator classGenerator = new ClassGenerator(); classGenerator.allocate(type); - this.typeScope = new TypeScope(PandaLocation.unknownLocation("repl"), type); + this.typeScope = new TypeScope(PandaLocation.unknownLocation("repl"), reference); type.getConstructors().declare(PandaConstructor.builder() .type(type) - .callback((typeConstructor, frame, instance, arguments) -> typeScope.createInstance(frame, instance, typeConstructor, Arrays.asList(), arguments)) + .invoker((typeConstructor, frame, instance, arguments) -> typeScope.revive(frame, instance, typeConstructor, arguments)) .location(type.getLocation()) + .returnType(type.getSignature()) .build()); try { @@ -113,10 +113,10 @@ public final class ReplCreator { public Repl create() throws Exception { this.processSupplier = () -> new PandaProcess(context.getApplication(), replScope); - Type type = typeScope.getType(); + Type type = typeScope.getReference().fetchType(); this.instanceSupplier = stack -> { - return typeScope.createInstance(stack, typeScope, type.getConstructors().getConstructor(Collections.emptyList()).getOrNull(), Collections.emptyList(), new Object[0]); + return typeScope.revive(stack, typeScope, type.getConstructors().getConstructor(Collections.emptyList()).getOrNull(), new Object[0]); }; return new Repl(this); @@ -129,7 +129,7 @@ public Repl create() throws Exception { * @return the REPL creator instance */ public ReplCreator define(PandaMethod method) { - typeScope.getType().getMethods().declare(method); + typeScope.getReference().fetchType().getMethods().declare(method); return this; }