diff --git a/examples/tests/current_test.panda b/examples/tests/current_test.panda index 74a08d1e1..aaad28687 100644 --- a/examples/tests/current_test.panda +++ b/examples/tests/current_test.panda @@ -94,12 +94,7 @@ main { break // or just stop } - // create TestArray instance and - TestArray testArray = new TestArray(7); - testArray.modify(test) - - // print array and some logical expressions - log "Content of " + "array " + testArray.array.asString() + // logical expressions log "OR v AND: " + (false || false) + ", " + false || true, true && false, true && true log "Compare: " + 1 > 2, 1 > 2, 1 < 2, 2 < 1 log "Random", (false || false) + ", " + false || true, true && false, true && true, (false || false) + ", " + false || true, true && false, true && true @@ -114,6 +109,7 @@ main { log creaseValue // create instance of class imported from another file + // should use generated default constructor Required required = new Required() required.hello() @@ -276,37 +272,6 @@ internal type Test { } -// array test -internal type TestArray { - - // shared array - shared Array array - - // create TestArray and define array size - constructor (Int size) { - this.array = new Array(size) - } - - // modify some values in array - shared modify (Test test) { - // this.getArray()[Test.INDEX] = "Hello Array" - // array[6] = String.valueOf(this) - - // log "Value at array[test.index]: " + this.getArray()[test.INDEX] - varargs(array) - } - - shared varargs (String varargs) { - log varargs - } - - // get array - internal getArray() -> Array { - return array - } - -} - internal type CustomThread : Thread { constructor () { diff --git a/examples/tests/current_test_required.panda b/examples/tests/current_test_required.panda index 03a0b4398..a40c26afa 100644 --- a/examples/tests/current_test_required.panda +++ b/examples/tests/current_test_required.panda @@ -6,6 +6,8 @@ export org.panda_lang.utilities.commons.StringUtils // shared class to test visibility access shared type Required { + // should generate default empty constructor + shared hello() { log "Required print" diff --git a/panda-framework/src/main/java/org/panda_lang/language/architecture/Environment.java b/panda-framework/src/main/java/org/panda_lang/language/architecture/Environment.java index 212543c47..e940f2a91 100644 --- a/panda-framework/src/main/java/org/panda_lang/language/architecture/Environment.java +++ b/panda-framework/src/main/java/org/panda_lang/language/architecture/Environment.java @@ -19,6 +19,7 @@ import org.panda_lang.language.FrameworkController; import org.panda_lang.language.architecture.module.ModulePath; import org.panda_lang.language.architecture.module.TypeLoader; +import org.panda_lang.language.architecture.type.generator.TypeGenerator; import org.panda_lang.language.interpreter.Interpreter; import org.panda_lang.language.interpreter.logging.LoggerHolder; import org.panda_lang.language.interpreter.source.SourceService; @@ -51,6 +52,13 @@ public interface Environment extends LoggerHolder { */ TypeLoader getTypeLoader(); + /** + * Get default type generator + * + * @return the type generator + */ + TypeGenerator getTypeGenerator(); + /** * Get sources used by this environment * diff --git a/panda-framework/src/main/java/org/panda_lang/language/architecture/expression/ExpressionUtils.java b/panda-framework/src/main/java/org/panda_lang/language/architecture/expression/ExpressionUtils.java index c0eb97a0c..0374171c7 100644 --- a/panda-framework/src/main/java/org/panda_lang/language/architecture/expression/ExpressionUtils.java +++ b/panda-framework/src/main/java/org/panda_lang/language/architecture/expression/ExpressionUtils.java @@ -80,7 +80,7 @@ public static Result equalize(Expression expression, Signatu return Result.ok(expression); } - if (expression.getSignature().isAssignableFrom(expected)) { + if (expected.isAssignableFrom(expression.getSignature())) { return Result.ok(expression); } 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 2f292e4ae..d882047dc 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 @@ -44,7 +44,6 @@ import java.util.HashMap; import java.util.List; import java.util.Map; -import java.util.Map.Entry; import java.util.Objects; public class PandaType extends AbstractMetadata implements Type { @@ -118,6 +117,7 @@ public void addBase(TypedSignature baseSignature) { } bases.add(baseSignature); + autocasts.put(baseSignature.fetchType(), (originalType, object, resultType) -> object); } @Override @@ -142,10 +142,7 @@ public boolean equals(@Nullable Object to) { @Override public boolean isAssignableFrom(Type from) { - return this.equals(from) - || from.getBases().stream().anyMatch(base -> isAssignableFrom(base.fetchType())) - || from.getAutocasts().stream().anyMatch(this::isAssignableFrom) - || from.getAutocast(this).isPresent(); + return this.equals(from) || from.getAutocast(this).isDefined(); } @Override @@ -173,14 +170,26 @@ else if (TypeField.class.isAssignableFrom(propertyType)) { @Override public Option> getAutocast(Type to) { - return PandaStream.of(autocasts.entrySet()) - .find(autocastEntry -> to.isAssignableFrom(autocastEntry.getKey())) - .map(Entry::getValue); + Autocast autocast = autocasts.get(to); + + if (autocast != null) { + return Option.of(autocast); + } + + for (TypedSignature base : bases) { + Option> baseAutocast = base.fetchType().getAutocast(to); + + if (baseAutocast != null) { + return baseAutocast; + } + } + + return Option.none(); } @Override - public Collection getAutocasts() { - return autocasts.keySet(); + public Map> getAutocasts() { + return autocasts; } @Override @@ -205,7 +214,8 @@ public Collection getBases() { @Override public Option getSuperclass() { - return PandaStream.of(getBases()).find(base -> Kind.isClass(base.fetchType())); + return PandaStream.of(getBases()) + .find(base -> Kind.isClass(base.fetchType())); } @Override 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 55cd01040..7e52d8a70 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 @@ -30,6 +30,7 @@ import org.panda_lang.utilities.commons.function.Option; import java.util.Collection; +import java.util.Map; /** * Extensible owner of properties @@ -124,14 +125,14 @@ default boolean is(String name) { * @param to the type to search for * @return the autocast */ - Option> getAutocast(Type to); + Option> getAutocast(Type to); /** * Get all of the supported autocasts * * @return collection of autocasts */ - Collection getAutocasts(); + Map> getAutocasts(); /** * Get supertypes of type diff --git a/panda-framework/src/main/java/org/panda_lang/language/architecture/type/generator/TypeGenerator.java b/panda-framework/src/main/java/org/panda_lang/language/architecture/type/generator/TypeGenerator.java index 854c942c4..52cc31f04 100644 --- a/panda-framework/src/main/java/org/panda_lang/language/architecture/type/generator/TypeGenerator.java +++ b/panda-framework/src/main/java/org/panda_lang/language/architecture/type/generator/TypeGenerator.java @@ -44,7 +44,7 @@ public final class TypeGenerator { - protected final Map initializedTypes = new HashMap<>(); + protected final Map, Type> initializedTypes = new HashMap<>(); protected final FrameworkController frameworkController; public TypeGenerator(FrameworkController frameworkController) { @@ -52,9 +52,7 @@ public TypeGenerator(FrameworkController frameworkController) { } public Reference generate(Module module, String name, Class javaType) { - String identifier = getId(module, name); - - return Option.of(initializedTypes.get(identifier)) + return Option.of(initializedTypes.get(javaType)) .map(Reference::new) .orElse(() -> module.get(name)) .orElseGet(() -> { @@ -85,6 +83,11 @@ public Reference generate(Module module, String name, Class javaType) { type.addBase(typeLoader.load(findOrGenerate(typeLoader, module, javaInterface)).getSignature()); } + if (!javaType.equals(Object.class) && type.getBases().isEmpty()) { + // type.addAutocast(typeLoader.requireType("panda::Object"), (originalType, object, resultType) -> object); + type.addBase(typeLoader.requireType("panda::Object").getSignature()); + } + if (!Modifier.isPublic(javaType.getModifiers())) { return; } @@ -100,7 +103,7 @@ public Reference generate(Module module, String name, Class javaType) { for (Constructor constructor : ReflectionUtils.getByModifier(javaType.getDeclaredConstructors(), Modifier.PUBLIC)) { ConstructorGenerator generator = new ConstructorGenerator(this, initializedType, constructor); - initializedType.getConstructors().declare(name, () -> generator.generate(typeLoader)); + initializedType.getConstructors().declare(constructor.toString(), () -> generator.generate(typeLoader)); } for (Method method : ReflectionUtils.getByModifier(javaType.getDeclaredMethods(), Modifier.PUBLIC)) { @@ -109,7 +112,7 @@ public Reference generate(Module module, String name, Class javaType) { } }); - initializedTypes.put(identifier, type); + initializedTypes.put(javaType, type); completableType.complete(type); return new Reference(type); @@ -127,7 +130,7 @@ protected Type findOrGenerate(TypeLoader typeLoader, Module module, Class jav return typeValue.get(); } - Type type = initializedTypes.get(getId(module, javaType.getSimpleName())); + Type type = initializedTypes.get(javaType); if (type != null) { return type; @@ -136,12 +139,4 @@ protected Type findOrGenerate(TypeLoader typeLoader, Module module, Class jav return generate(module, javaType.getSimpleName(), javaType).fetchType(); } - protected void disposeCache() { - initializedTypes.clear(); - } - - private String getId(Module module, String name) { - return module.getName() + "::" + name; - } - } diff --git a/panda-framework/src/main/java/org/panda_lang/language/architecture/type/signature/SignatureMatcher.java b/panda-framework/src/main/java/org/panda_lang/language/architecture/type/signature/SignatureMatcher.java index 25450c05f..db7f2bab9 100644 --- a/panda-framework/src/main/java/org/panda_lang/language/architecture/type/signature/SignatureMatcher.java +++ b/panda-framework/src/main/java/org/panda_lang/language/architecture/type/signature/SignatureMatcher.java @@ -52,44 +52,15 @@ public Option> match(Collection collection, Signature } // map arguments into parameters - int[] target = new int[requiredTypes.length]; - int index = 0, required = 0, varArgs = 0; + int index = 0, required = 0; // loop as long parameters and types are available for (; (index < parameters.length) && (required < requiredTypes.length); index++) { PropertyParameter parameter = parameters[index]; - //if (!parameter.isVarargs()) { - target[required] = index; - - if (!parameter.getSignature().isAssignableFrom(requiredTypes[required++])) { - return null; - } - - continue; - //} - - /* - // varargs parameter has to be array - Type type = ((ArrayType) parameter.getType()).getArrayType(); - varArgs++; - - // read vararg - while (required < requiredTypes.length) { - Signature nextType = requiredTypes[required]; - - if (!type.isAssignableFrom(nextType)) { - // array was directly passed to the varargs - if (nextType.isAssignableFrom(parameter.getType())) { - target[required++] = index; - } - - break; - } - - target[required++] = index; + if (!parameter.getSignature().isAssignableFrom(requiredTypes[required++])) { + return null; } - */ } // return if does not match @@ -103,54 +74,6 @@ public Option> match(Collection collection, Signature } return new Adjustment<>(executable, arguments); - - /* - // return result without varargs mappings - if (varArgs == 0) { - return new Adjustment<>(executable, arguments); - } - - @SuppressWarnings("unchecked") - List[] mapped = new List[parameters.length]; - - // group arguments - for (int targetIndex = 0; targetIndex < target.length; ) { - int targetParameter = target[targetIndex]; - List section = mapped[targetParameter]; - - if (section == null) { - section = (mapped[targetParameter] = new ArrayList<>(arguments.length - parameters.length - varArgs + 1)); - } - - section.add(arguments[targetIndex]); - targetIndex++; - } - - Expression[] fixedArguments = new Expression[mapped.length]; - - // map arguments - for (int argumentIndex = 0; argumentIndex < mapped.length; argumentIndex++) { - List expressions = mapped[argumentIndex]; - - if (expressions.size() == 1) { - fixedArguments[argumentIndex] = expressions.get(0); - continue; - } - - Expression[] expressionsArray = expressions.toArray(new Expression[0]); - - // generate varargs array expression - fixedArguments[argumentIndex] = new AbstractDynamicExpression(((ArrayType) parameters[argumentIndex].getType()).getArrayType()) { - @Override - @SuppressWarnings("unchecked") - public Object evaluate(ProcessStack stack, Object instance) throws Exception { - return ExpressionUtils.evaluate(stack, instance, expressionsArray); - } - }.toExpression(); - } - - return new Adjustment<>(executable, fixedArguments); - */ } } diff --git a/panda-framework/src/main/java/org/panda_lang/language/resource/syntax/keyword/Keywords.java b/panda-framework/src/main/java/org/panda_lang/language/resource/syntax/keyword/Keywords.java index 549202d20..8aec4db32 100644 --- a/panda-framework/src/main/java/org/panda_lang/language/resource/syntax/keyword/Keywords.java +++ b/panda-framework/src/main/java/org/panda_lang/language/resource/syntax/keyword/Keywords.java @@ -46,8 +46,6 @@ public final class Keywords { public static final Keyword ELSE = add(VALUES, new Keyword("else")); - public static final Keyword ELSE_IF = add(VALUES, new Keyword("else if")); - public static final Keyword EXPORT = add(VALUES, new Keyword("export")); public static final Keyword FOREACH = add(VALUES, new Keyword("foreach")); diff --git a/panda/src/main/java/org/panda_lang/panda/language/architecture/PandaEnvironment.java b/panda/src/main/java/org/panda_lang/panda/language/architecture/PandaEnvironment.java index eb3aa212b..b14e886ad 100644 --- a/panda/src/main/java/org/panda_lang/panda/language/architecture/PandaEnvironment.java +++ b/panda/src/main/java/org/panda_lang/panda/language/architecture/PandaEnvironment.java @@ -49,8 +49,8 @@ public PandaEnvironment(FrameworkController controller, File workingDirectory) { this.workingDirectory = workingDirectory; this.sources = new PandaSourceService(); this.modulePath = new PandaModulePath(sources); - this.typeGenerator = new TypeGenerator(controller); this.typeLoader = new PandaTypeLoader(modulePath); + this.typeGenerator = new TypeGenerator(controller); this.interpreter = new PandaInterpreter(this); this.resources = new Lazy<>(() -> { @@ -82,6 +82,11 @@ public ModulePath getModulePath() { return modulePath; } + @Override + public TypeGenerator getTypeGenerator() { + return typeGenerator; + } + @Override public TypeLoader getTypeLoader() { return typeLoader; diff --git a/panda/src/main/java/org/panda_lang/panda/language/resource/ResourcesLoader.java b/panda/src/main/java/org/panda_lang/panda/language/resource/ResourcesLoader.java index aca348e3f..63d131a02 100644 --- a/panda/src/main/java/org/panda_lang/panda/language/resource/ResourcesLoader.java +++ b/panda/src/main/java/org/panda_lang/panda/language/resource/ResourcesLoader.java @@ -57,6 +57,7 @@ private void loadClass(ModulePath modulePath, TypeGenerator typeGenerator, TypeL ClassUtils.forName(packageName + name) .map(type -> typeGenerator.generate(module, name, type)) .peek(module::add) + .peek(reference -> typeLoader.load(reference.fetchType())) .orThrow(() -> { throw new PandaFrameworkException("Cannot find class " + name + " in " + packageName); }); diff --git a/panda/src/main/java/org/panda_lang/panda/language/resource/internal/PandaModules.java b/panda/src/main/java/org/panda_lang/panda/language/resource/internal/PandaModules.java index 84a06e8ea..b0c96b10b 100644 --- a/panda/src/main/java/org/panda_lang/panda/language/resource/internal/PandaModules.java +++ b/panda/src/main/java/org/panda_lang/panda/language/resource/internal/PandaModules.java @@ -23,15 +23,13 @@ public final class PandaModules { - private static final Object[] MODULES = { - new JavaModule(), - new JavaExtensionModule(), - new JavaUtilsModule(), - new JavaCollectionsModule() - }; - public static Object[] getMappings() { - return MODULES; + return new Object[] { + new JavaModule(), + new JavaExtensionModule(), + new JavaUtilsModule(), + new JavaCollectionsModule() + }; } } diff --git a/panda/src/main/java/org/panda_lang/panda/language/resource/syntax/head/ConveyanceUtils.java b/panda/src/main/java/org/panda_lang/panda/language/resource/syntax/head/ConveyanceUtils.java index 631daf1c2..5601ac176 100644 --- a/panda/src/main/java/org/panda_lang/panda/language/resource/syntax/head/ConveyanceUtils.java +++ b/panda/src/main/java/org/panda_lang/panda/language/resource/syntax/head/ConveyanceUtils.java @@ -18,7 +18,6 @@ import org.panda_lang.language.architecture.module.Module; import org.panda_lang.language.architecture.type.Type; -import org.panda_lang.language.architecture.type.generator.TypeGenerator; import org.panda_lang.language.interpreter.parser.Context; import org.panda_lang.language.interpreter.parser.PandaParserFailure; import org.panda_lang.language.interpreter.token.Snippet; @@ -35,8 +34,8 @@ protected static Type fetchType(Context context, Snippet javaTypeSource) { throw new PandaParserFailure(context, javaTypeSource, "Undefined script module"); }); - TypeGenerator typeGenerator = new TypeGenerator(context.getEnvironment().getController()); - return context.getTypeLoader().load(typeGenerator.generate(module, importedClass.getSimpleName(), importedClass).fetchType()); + Type type = context.getEnvironment().getTypeGenerator().generate(module, importedClass.getSimpleName(), importedClass).fetchType(); + return context.getTypeLoader().load(type); } catch (ClassNotFoundException e) { throw new PandaParserFailure(context, javaTypeSource, "Class " + javaTypeSource.asSource() + " does not exist"); } diff --git a/panda/src/main/java/org/panda_lang/panda/language/resource/syntax/scope/block/TryCatchParser.java b/panda/src/main/java/org/panda_lang/panda/language/resource/syntax/scope/block/TryCatchParser.java index ed1ec7fa5..8ead6db74 100644 --- a/panda/src/main/java/org/panda_lang/panda/language/resource/syntax/scope/block/TryCatchParser.java +++ b/panda/src/main/java/org/panda_lang/panda/language/resource/syntax/scope/block/TryCatchParser.java @@ -82,7 +82,7 @@ public Option> parse(Context context) { Variable variable = catchBlock.createVariable(variableData); SCOPE_PARSER.parse(context, catchBlock, catchBody.get()); - if (variableData.getKnownType().isAssignableFrom(context.getTypeLoader().requireType("panda::Throwable"))) { + if (context.getTypeLoader().requireType("java::Throwable").isAssignableFrom(variableData.getKnownType())) { //noinspection unchecked tryCatch.addHandler((Class) variable.getKnownType().getType().getAssociated().get(), variable, catchBlock); } diff --git a/panda/src/main/java/org/panda_lang/panda/language/resource/syntax/scope/block/conditional/ConditionalParser.java b/panda/src/main/java/org/panda_lang/panda/language/resource/syntax/scope/block/conditional/ConditionalParser.java index cbec4772d..17751c6e6 100644 --- a/panda/src/main/java/org/panda_lang/panda/language/resource/syntax/scope/block/conditional/ConditionalParser.java +++ b/panda/src/main/java/org/panda_lang/panda/language/resource/syntax/scope/block/conditional/ConditionalParser.java @@ -22,6 +22,7 @@ import org.panda_lang.language.architecture.statement.Statement; import org.panda_lang.language.interpreter.parser.Context; import org.panda_lang.language.interpreter.parser.PandaParserFailure; +import org.panda_lang.language.interpreter.token.Snippet; import org.panda_lang.language.resource.syntax.keyword.Keyword; import org.panda_lang.panda.language.interpreter.parser.PandaSourceReader; import org.panda_lang.panda.language.interpreter.parser.ScopeParser; @@ -30,20 +31,28 @@ final class ConditionalParser { - Option parse(ScopeParser scopeParser, Context context, Keyword keyword, boolean hasExpression) { + Option parse(ScopeParser scopeParser, Context context, boolean hasExpression, Keyword... keywords) { PandaSourceReader sourceReader = new PandaSourceReader(context.getStream()); - if (sourceReader.read(keyword).isEmpty()) { - return Option.none(); + for (Keyword keyword : keywords) { + if (sourceReader.read(keyword).isEmpty()) { + return Option.none(); + } } Expression condition = hasExpression ? context.getExpressionParser().parse(context, context.getStream()).getExpression() : new PandaExpression(context.getTypeLoader().requireType("panda::Bool").getSignature(), true); + Option body = sourceReader.readBody(); + + if (body.isEmpty()) { + throw new PandaParserFailure(context, "Missing condition body"); + } + ConditionalBlock conditionalBlock = new ConditionalBlock(context.getScope(), context, condition); context.getScope().addStatement(conditionalBlock); - scopeParser.parse(context, conditionalBlock, sourceReader.readBody().get()); + scopeParser.parse(context, conditionalBlock, body.get()); return Option.of(conditionalBlock); } diff --git a/panda/src/main/java/org/panda_lang/panda/language/resource/syntax/scope/block/conditional/ElseIfParser.java b/panda/src/main/java/org/panda_lang/panda/language/resource/syntax/scope/block/conditional/ElseIfParser.java index 091fbe4e2..acc7071d7 100644 --- a/panda/src/main/java/org/panda_lang/panda/language/resource/syntax/scope/block/conditional/ElseIfParser.java +++ b/panda/src/main/java/org/panda_lang/panda/language/resource/syntax/scope/block/conditional/ElseIfParser.java @@ -17,7 +17,7 @@ public String name() { @Override public Option> parse(Context context) { - return CONDITIONAL_PARSER.parse(SCOPE_PARSER, context, Keywords.ELSE_IF, true) + return CONDITIONAL_PARSER.parse(SCOPE_PARSER, context, true, Keywords.ELSE, Keywords.IF) .peek(conditionalBlock -> CONDITIONAL_PARSER.linkBlocks(context, conditionalBlock)) .map(Completable::completed); } diff --git a/panda/src/main/java/org/panda_lang/panda/language/resource/syntax/scope/block/conditional/ElseParser.java b/panda/src/main/java/org/panda_lang/panda/language/resource/syntax/scope/block/conditional/ElseParser.java index d6c841f01..a17b81436 100644 --- a/panda/src/main/java/org/panda_lang/panda/language/resource/syntax/scope/block/conditional/ElseParser.java +++ b/panda/src/main/java/org/panda_lang/panda/language/resource/syntax/scope/block/conditional/ElseParser.java @@ -17,7 +17,7 @@ public String name() { @Override public Option> parse(Context context) { - return CONDITIONAL_PARSER.parse(SCOPE_PARSER, context, Keywords.ELSE, false) + return CONDITIONAL_PARSER.parse(SCOPE_PARSER, context, false, Keywords.ELSE) .peek(conditionalBlock -> CONDITIONAL_PARSER.linkBlocks(context, conditionalBlock)) .map(Completable::completed); } diff --git a/panda/src/main/java/org/panda_lang/panda/language/resource/syntax/scope/block/conditional/IfParser.java b/panda/src/main/java/org/panda_lang/panda/language/resource/syntax/scope/block/conditional/IfParser.java index 7653bdfd1..c9c54e186 100644 --- a/panda/src/main/java/org/panda_lang/panda/language/resource/syntax/scope/block/conditional/IfParser.java +++ b/panda/src/main/java/org/panda_lang/panda/language/resource/syntax/scope/block/conditional/IfParser.java @@ -18,7 +18,7 @@ public String name() { @Override public Option> parse(Context context) { return CONDITIONAL_PARSER - .parse(SCOPE_PARSER, context, Keywords.IF, true) + .parse(SCOPE_PARSER, context, true, Keywords.IF) .map(Completable::completed); } diff --git a/panda/src/main/java/org/panda_lang/panda/language/resource/syntax/scope/block/looping/ForEachParser.java b/panda/src/main/java/org/panda_lang/panda/language/resource/syntax/scope/block/looping/ForEachParser.java index 357916eca..00a8794ba 100644 --- a/panda/src/main/java/org/panda_lang/panda/language/resource/syntax/scope/block/looping/ForEachParser.java +++ b/panda/src/main/java/org/panda_lang/panda/language/resource/syntax/scope/block/looping/ForEachParser.java @@ -62,7 +62,7 @@ public Option> parse(Context context) { Expression iterableExpression = context.getExpressionParser().parse(context, elements[1]).getExpression(); - if (!iterableExpression.getKnownType().isAssignableFrom(context.getTypeLoader().requireType("panda::Iterable"))) { + if (!context.getTypeLoader().requireType("panda::Iterable").isAssignableFrom(iterableExpression.getKnownType())) { throw new PandaParserException("ForEach requires Iterable value"); } 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 dd8e1f198..2eb695187 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 @@ -179,10 +179,48 @@ public Option> parse(Context context) { stageService.delegate("parse " + type.getName() + " type body", Phases.DEFAULT, Layer.NEXT_DEFAULT, bodyPhase -> { typePoolParser.parse(typeContext, new PandaSourceStream(body)); futureType.complete(type); + + stageService.delegate("check default constructor", Phases.DEFAULT, Layer.NEXT_DEFAULT, nextPhase -> { + if (type.getConstructors().getDeclaredProperties().isEmpty()) { + type.getSuperclass().toStream() + .flatMapStream(superSignature -> superSignature.fetchType().getConstructors().getProperties().stream()) + .find(constructor -> constructor.getParameters().length > 0) + .peek(constructorWithParameters -> { + throw new PandaParserFailure(context, constructorWithParameters.getLocation(), + "Type " + type + " does not implement any constructor from the base type " + constructorWithParameters.getType(), + "Some of the overridden types may contain custom constructors. To properly initialize object, you have to call one of them." + ); + }); + + type.getConstructors().declare(PandaConstructor.builder() + .type(type) + .callback((typeConstructor, frame, instance, arguments) -> { + return scope.createInstance(frame, instance, typeConstructor, Collections.emptyList(), arguments); + }) + .location(type.getLocation()) + .build()); + } + }); }); stageService.delegate("verify " + type.getName() + "type properties", Phases.VERIFY, Layer.NEXT_DEFAULT, verifyPhase -> { - verifyProperties(typeContext); + for (TypedSignature base : type.getBases()) { + State.requireInheritance(context, base.fetchType(), context.getSource()); + } + + if (type.getState() != State.ABSTRACT) { + PandaStream.of(type.getBases()) + .map(TypedSignature::fetchType) + .flatMapStream(base -> base.getMethods().getProperties().stream()) + .filter(TypeMethod::isAbstract) + .filter(method -> !type.getMethods().getMethod(method.getSimpleName(), method.getParameterSignatures()).isDefined()) + .forEach(method -> { + throw new PandaParserFailure(context, type.getLocation(), + "Missing implementation of &1" + method + "&r in &1" + type + "&r", + "You have to override all non-default methods declared by " + type + " abstract type" + ); + }); + } }); stageService.delegate("generate type class", Phases.INITIALIZE, Layer.NEXT_DEFAULT, initializePhase -> { @@ -206,47 +244,5 @@ public Option> parse(Context context) { return Option.of(futureType); } - - private void verifyProperties(Context context) { - Type type = context.getSubject().getType(); - - for (TypedSignature base : type.getBases()) { - State.requireInheritance(context, base.fetchType(), context.getSource()); - } - - if (type.getState() != State.ABSTRACT) { - PandaStream.of(type.getBases()) - .map(TypedSignature::fetchType) - .flatMapStream(base -> base.getMethods().getProperties().stream()) - .filter(TypeMethod::isAbstract) - .filter(method -> !type.getMethods().getMethod(method.getSimpleName(), method.getParameterSignatures()).isDefined()) - .forEach(method -> { - throw new PandaParserFailure(context, type.getLocation(), - "Missing implementation of &1" + method + "&r in &1" + type + "&r", - "You have to override all non-default methods declared by " + type + " abstract type" - ); - }); - } - - if (type.getConstructors().getDeclaredProperties().isEmpty()) { - type.getSuperclass().toStream() - .flatMapStream(superSignature -> superSignature.fetchType().getConstructors().getProperties().stream()) - .find(constructor -> constructor.getParameters().length > 0) - .peek(constructorWithParameters -> { - throw new PandaParserFailure(context, constructorWithParameters.getLocation(), - "Type " + type + " does not implement any constructor from the base type " + constructorWithParameters.getType(), - "Some of the overridden types may contain custom constructors. To properly initialize object, you have to call one of them." - ); - }); - - type.getConstructors().declare(PandaConstructor.builder() - .type(type) - .callback((typeConstructor, frame, instance, arguments) -> { - return context.getSubject().getScope().createInstance(frame, instance, typeConstructor, Collections.emptyList(), arguments); - }) - .location(type.getLocation()) - .build()); - } - } }