diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..938d216 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,30 @@ +#Dont use maven directly, because all maven dependencies downloaded during build time won't be in the image +FROM openjdk:8-jdk + +RUN apt-get update && apt-get install -y \ + maven \ + llvm \ + graphviz \ + build-essential \ + && rm -rf /var/lib/apt/lists/* + + +WORKDIR /moco + +COPY pom.xml /moco/pom.xml +#COPY settings-maven.xml /maven + +#Download everything +#... except surefire :-( +RUN mvn dependency:resolve +RUN mvn dependency:resolve-plugins +RUN mvn antlr4:antlr4 +RUN mvn test --fail-never + +#Add sources last, because they are changed often +COPY src /moco/src + +#RUN mvn package + +ENTRYPOINT mvn +CMD package \ No newline at end of file diff --git a/LICENSE_HEADER b/LICENSE_HEADER new file mode 100644 index 0000000..9000271 --- /dev/null +++ b/LICENSE_HEADER @@ -0,0 +1,36 @@ +moco, the Monty Compiler +Copyright (c) 2013-2014, Monty's Coconut, All rights reserved. + +This file is part of moco, the Monty Compiler. + +moco is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public +License as published by the Free Software Foundation; either +version 3.0 of the License, or (at your option) any later version. + +moco is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +Linking this program and/or its accompanying libraries statically or +dynamically with other modules is making a combined work based on this +program. Thus, the terms and conditions of the GNU General Public License +cover the whole combination. + +As a special exception, the copyright holders of moco give +you permission to link this programm and/or its accompanying libraries +with independent modules to produce an executable, regardless of the +license terms of these independent modules, and to copy and distribute the +resulting executable under terms of your choice, provided that you also meet, +for each linked independent module, the terms and conditions of the +license of that module. + +An independent module is a module which is not +derived from or based on this program and/or its accompanying libraries. +If you modify this library, you may extend this exception to your version of +the program or library, but you are not obliged to do so. If you do not wish +to do so, delete this exception statement from your version. + +You should have received a copy of the GNU General Public +License along with this library. \ No newline at end of file diff --git a/README.md b/README.md index be23a23..71d7a70 100644 --- a/README.md +++ b/README.md @@ -18,13 +18,13 @@ Installing Dependencies Linux (Ubuntu) -------------- -Install [LLVM](http://llvm.org/) and a JRE 7. +Install [LLVM](http://llvm.org/) and a JRE 8. sudo apt-get install llvm sudo apt-get install default-jre If you want to build `moco` yourself you'll need to install the following -dependencies and a JDK 7. +dependencies and a JDK 8. sudo apt-get install git sudo apt-get install maven @@ -37,7 +37,7 @@ You can also install Graphviz to generate class diagrams. This is optional. Mac OS X -------- -> **Note:** Please make sure you have [homebrew](http://brew.sh/) and a JRE 7 +> **Note:** Please make sure you have [homebrew](http://brew.sh/) and a JRE 8 installed. Install [LLVM](http://llvm.org/) using homebrew: @@ -45,7 +45,7 @@ Install [LLVM](http://llvm.org/) using homebrew: brew install llvm If you want to build `moco` yourself you'll need to install the following -dependencies and a JDK 7. +dependencies and a JDK 8. brew install git brew install maven @@ -61,28 +61,7 @@ You can also install Graphviz to generate class diagrams. This is optional. Windows ------- -To use [LLVM](http://llvm.org/) you'll need to download and install the -following executables. In addition you'll need to download and extract the -`llvm-3.4-tools-windows.7z` archive into the `bin\` directory of your LLVM -installation. To run the executable .jar file you'll also need a JRE 7. - - -- http://www.microsoft.com/de-DE/download/details.aspx?id=40784 (the **x86 and - the x64** version) -- http://llvm.org/releases/3.4/LLVM-3.4-win32.exe -- https://github.com/CRogers/LLVM-Windows-Binaries/releases/download/v3.4/llvm-3.4-tools-windows.7z - -If you want to build `moco` yourself you'll need to install the following -dependencies and a JDK 7. These examples use the -[chocolatey](https://chocolatey.org/) package manager. - - choco install maven - choco install java.jdk - choco install git.commandline - -You can also install Graphviz to generate class diagrams. This is optional. - - choco install graphviz +Currently Windows is not supported. Building ======== diff --git a/pom.xml b/pom.xml index 194196b..d24dbb1 100644 --- a/pom.xml +++ b/pom.xml @@ -1,4 +1,44 @@ + @@ -115,9 +155,9 @@ ${project.basedir}/src/main/resources/moco-code-conv.xml true - 1.7 - 1.7 - 1.7 + 1.8 + 1.8 + 1.8 LF UTF-8 @@ -135,8 +175,8 @@ maven-compiler-plugin 3.1 - 1.7 - 1.7 + 1.8 + 1.8 @@ -192,7 +232,36 @@ - + + com.mycila + license-maven-plugin + 2.6 + +
${basedir}/LICENSE_HEADER
+ + SLASHSTAR_STYLE + SLASHSTAR_STYLE + + + **/README + **/COPYING + **/COPYING_EXCEPTION + **/COPYING_HEADER + **/LICENSE_HEADER + src/test/resources/** + src/site/** + src/main/resources/** + +
+ + + compile + + check + + + +
@@ -313,5 +382,6 @@ 1.3 test +
diff --git a/src/main/antlr4/de/uni/bremen/monty/moco/antlr/Monty.g4 b/src/main/antlr4/de/uni/bremen/monty/moco/antlr/Monty.g4 index dac3e3a..0b14486 100644 --- a/src/main/antlr4/de/uni/bremen/monty/moco/antlr/Monty.g4 +++ b/src/main/antlr4/de/uni/bremen/monty/moco/antlr/Monty.g4 @@ -1,4 +1,43 @@ -grammar Monty; +/* + * moco, the Monty Compiler + * Copyright (c) 2013-2014, Monty's Coconut, All rights reserved. + * + * This file is part of moco, the Monty Compiler. + * + * moco is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation; either + * version 3.0 of the License, or (at your option) any later version. + * + * moco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * Linking this program and/or its accompanying libraries statically or + * dynamically with other modules is making a combined work based on this + * program. Thus, the terms and conditions of the GNU General Public License + * cover the whole combination. + * + * As a special exception, the copyright holders of moco give + * you permission to link this programm and/or its accompanying libraries + * with independent modules to produce an executable, regardless of the + * license terms of these independent modules, and to copy and distribute the + * resulting executable under terms of your choice, provided that you also meet, + * for each linked independent module, the terms and conditions of the + * license of that module. + * + * An independent module is a module which is not + * derived from or based on this program and/or its accompanying libraries. + * If you modify this library, you may extend this exception to your version of + * the program or library, but you are not obliged to do so. If you do not wish + * to do so, delete this exception statement from your version. + * + * You should have received a copy of the GNU General Public + * License along with this library. + */ + + grammar Monty; import lex; @@ -33,7 +72,7 @@ independentDeclaration ; classDeclaration - : nativeAnnotation? AbstractKeyword? 'class' type ('inherits' typeList)? + : nativeAnnotation? AbstractKeyword? 'class' typeDef ('inherits' typeList)? ':' EndOfLine Indent (memberDeclaration+ | 'pass' EndOfLine) @@ -41,7 +80,7 @@ classDeclaration ; caseClassDeclaration - : 'case' 'class' type '(' (parameterListWithoutDefaults)? ')' ('inherits' typeList)? + : 'case' 'class' typeDef '(' (parameterListWithoutDefaults)? ')' ('inherits' typeList)? (':' EndOfLine Indent (memberDeclaration+ | 'pass' EndOfLine) @@ -76,6 +115,18 @@ arrow : '->' ; +typeDef + : ClassIdentifier ('<' typeDefList '>')? + ; + +typeDefList + : boundedType (',' boundedType)* + ; + +boundedType + : ClassIdentifier (typeBound)? ('<' typeList '>')? + ; + type : ClassIdentifier ('<' typeList '>')? | '(' (type (',' type)+)? ')' @@ -83,6 +134,10 @@ type | '(' type arrow type ')' ; +typeBound + : 'inherits' type + ; + typeList : type (',' type)* ; @@ -213,7 +268,7 @@ expression | left=expression andOperator right=expression | left=expression orOperator right=expression | expr=expression asOperator type - | expr=expression isOperator ClassIdentifier + | expr=expression isOperator type | listComprehension ; diff --git a/src/main/antlr4/imports/lex.g4 b/src/main/antlr4/imports/lex.g4 index 9531b81..30c749f 100644 --- a/src/main/antlr4/imports/lex.g4 +++ b/src/main/antlr4/imports/lex.g4 @@ -1,4 +1,43 @@ -lexer grammar lex; +/* + * moco, the Monty Compiler + * Copyright (c) 2013-2014, Monty's Coconut, All rights reserved. + * + * This file is part of moco, the Monty Compiler. + * + * moco is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation; either + * version 3.0 of the License, or (at your option) any later version. + * + * moco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * Linking this program and/or its accompanying libraries statically or + * dynamically with other modules is making a combined work based on this + * program. Thus, the terms and conditions of the GNU General Public License + * cover the whole combination. + * + * As a special exception, the copyright holders of moco give + * you permission to link this programm and/or its accompanying libraries + * with independent modules to produce an executable, regardless of the + * license terms of these independent modules, and to copy and distribute the + * resulting executable under terms of your choice, provided that you also meet, + * for each linked independent module, the terms and conditions of the + * license of that module. + * + * An independent module is a module which is not + * derived from or based on this program and/or its accompanying libraries. + * If you modify this library, you may extend this exception to your version of + * the program or library, but you are not obliged to do so. If you do not wish + * to do so, delete this exception statement from your version. + * + * You should have received a copy of the GNU General Public + * License along with this library. + */ + + lexer grammar lex; @lexer::header { import java.util.Stack; diff --git a/src/main/java/de/uni/bremen/monty/moco/Main.java b/src/main/java/de/uni/bremen/monty/moco/Main.java index 16c4a82..3262e86 100644 --- a/src/main/java/de/uni/bremen/monty/moco/Main.java +++ b/src/main/java/de/uni/bremen/monty/moco/Main.java @@ -40,8 +40,10 @@ import de.uni.bremen.monty.moco.antlr.MontyParser; import de.uni.bremen.monty.moco.ast.AntlrAdapter; +import de.uni.bremen.monty.moco.ast.CoreClasses; import de.uni.bremen.monty.moco.ast.Package; import de.uni.bremen.monty.moco.ast.PackageBuilder; +import de.uni.bremen.monty.moco.ast.types.ConcreteType; import de.uni.bremen.monty.moco.util.*; import de.uni.bremen.monty.moco.visitor.*; @@ -116,7 +118,7 @@ private static boolean visitVisitors(Package ast, boolean stopOnFirstError, Stri CodeGenerationVisitor cgv = new CodeGenerationVisitor(); BaseVisitor[] visitors = new BaseVisitor[] { new SetParentVisitor(), new DeclarationVisitor(), new ResolveVisitor(), - new TypeCheckVisitor(), new ControlFlowVisitor(), cgv }; + new VMTResolveVisitor(), new TypeCheckVisitor(), new ControlFlowVisitor(), cgv }; boolean everyThingIsAwesome = true; @@ -137,6 +139,18 @@ private static boolean visitVisitors(Package ast, boolean stopOnFirstError, Stri } } + if(everyThingIsAwesome) { + try { + cgv.visitAllClasses(); + } catch (RuntimeException exception) { + cgv.logError(exception); + everyThingIsAwesome = false; + } + if (cgv.foundError()) { + everyThingIsAwesome = false; + } + } + cgv.writeLLVMCode(output); return everyThingIsAwesome; } @@ -205,7 +219,7 @@ private static File buildExecutable(String outputFileName, String inputFileName, return outputFile; } - private static void runExecutable(File executable) throws IOException, InterruptedException { + private static int runExecutable(File executable) throws IOException, InterruptedException { ProcessBuilder processBuilder = new ProcessBuilder(executable.getAbsolutePath()); String readFromFile = System.getProperty("testrun.readFromFile"); @@ -215,15 +229,25 @@ private static void runExecutable(File executable) throws IOException, Interrupt processBuilder.redirectInput(ProcessBuilder.Redirect.INHERIT); } Process process = processBuilder.start(); + int statusCode = process.waitFor(); System.err.print(IOUtils.toString(process.getErrorStream())); System.out.print(IOUtils.toString(process.getInputStream())); + return statusCode; } - public static void main(String[] args) throws IOException, InterruptedException { + public static void main(String[] args) throws IOException, InterruptedException { + int statusCode = mainWithStatusCode(args); + System.exit(statusCode); + } + + public static int mainWithStatusCode(String[] args) throws IOException, InterruptedException { + CoreClasses.reset(); + ConcreteType.reset(); + Namespace ns = parseArgs(args); if (ns == null) { - return; + return 1; } String inputFileName = ns.get("file"); @@ -236,7 +260,7 @@ public static void main(String[] args) throws IOException, InterruptedException if (debugParseTree) { debugParseTree(inputFileName); - return; + return 0; } StringWriter writer = new StringWriter(); @@ -245,21 +269,22 @@ public static void main(String[] args) throws IOException, InterruptedException Package ast = buildPackage(inputFileName); if (!visitVisitors(ast, stopOnFirstError, writer.getBuffer())) { - return; + return 1; } if (printAST) { (new PrintVisitor()).visitDoubleDispatched(ast); } + String llvmCode = writer.toString(); if (emitAssembly) { - writeAssembly(outputFileName, inputFileName, writer.toString()); - return; + writeAssembly(outputFileName, inputFileName, llvmCode); } - File executable = buildExecutable(outputFileName, inputFileName, compileOnly, writer.toString()); + File executable = buildExecutable(outputFileName, inputFileName, compileOnly, llvmCode); if (!compileOnly) { - runExecutable(executable); + return runExecutable(executable); } + return 0; } } diff --git a/src/main/java/de/uni/bremen/monty/moco/ast/ASTBuilder.java b/src/main/java/de/uni/bremen/monty/moco/ast/ASTBuilder.java index 98ab0d5..2e3ab25 100644 --- a/src/main/java/de/uni/bremen/monty/moco/ast/ASTBuilder.java +++ b/src/main/java/de/uni/bremen/monty/moco/ast/ASTBuilder.java @@ -41,11 +41,13 @@ import de.uni.bremen.monty.moco.antlr.MontyBaseVisitor; import de.uni.bremen.monty.moco.antlr.MontyParser; import de.uni.bremen.monty.moco.antlr.MontyParser.*; +import de.uni.bremen.monty.moco.antlr.MontyParser.TypeContext; import de.uni.bremen.monty.moco.ast.declaration.*; import de.uni.bremen.monty.moco.ast.declaration.FunctionDeclaration.DeclarationType; import de.uni.bremen.monty.moco.ast.expression.*; import de.uni.bremen.monty.moco.ast.expression.literal.*; import de.uni.bremen.monty.moco.ast.statement.*; +import de.uni.bremen.monty.moco.ast.types.*; import de.uni.bremen.monty.moco.util.*; import org.antlr.v4.runtime.Token; import org.antlr.v4.runtime.misc.NotNull; @@ -54,6 +56,8 @@ import java.util.*; +import static de.uni.bremen.monty.moco.ast.types.TypeContext.EMPTY; + public class ASTBuilder extends MontyBaseVisitor { private final String fileName; private Stack currentBlocks; @@ -230,7 +234,7 @@ public ASTNode visitFunctionCall(FunctionCallContext ctx) { return new WrappedFunctionCall(position(ctx.getStart()), func); } - private void buildDefaultFunctions(boolean isFunction, List defaultParameter, + private void buildDefaultFunctions(List defaultParameter, List allVariableDeclarations, List params, List defaultExpression, List defaultVariableDeclaration, Identifier identifier, Token token, TypeContext typeContext, DeclarationType declarationTypeCopy, @@ -267,11 +271,9 @@ private void buildDefaultFunctions(boolean isFunction, List params = parameterListToVarDeclList(parameterListContext); - ResolvableIdentifier typeIdent = null; - if (typeContext != null) { - typeIdent = convertResolvableIdentifier(typeContext); - tupleDeclarationFactory.checkTupleType(typeIdent); - } + ResolvableIdentifier typeIdent = convertTypeContext(typeContext); FunctionDeclaration procDecl = new FunctionDeclaration(position(token), identifier, new Block(position(token)), params, @@ -361,14 +366,8 @@ public ASTNode visitFunctionDeclaration(FunctionDeclarationContext ctx) { currentGeneratorReturnType.push(null); boolean isNativeFunction = ctx.nativeAnnotation() != null; FunctionDeclaration proc = - buildFunctions( - ctx.type() != null, - ctx.parameterList(), - ctx.getStart(), - ctx.type(), - ctx.statementBlock(), - new Identifier(getText(ctx.Identifier())), - isNativeFunction); + buildFunctions(ctx.parameterList(), ctx.getStart(), ctx.type(), ctx.statementBlock(), new Identifier( + getText(ctx.Identifier())), isNativeFunction); // if the function does not have any return type, we have to add a return statement if (ctx.type() == null) { List list = proc.getBody().getStatements(); @@ -470,13 +469,13 @@ public ASTNode visitClassDeclaration(ClassDeclarationContext ctx) { // if there is an 'abstract' keyword, the class is abstract return createClass( position(ctx.getStart()), - ctx.type(), + ctx.typeDef(), ctx.typeList(), ctx.getTokens(MontyParser.AbstractKeyword).size() > 0, ctx.memberDeclaration()); } - protected ClassDeclaration createClass(Position pos, TypeContext className, TypeListContext inheritsFrom, + protected ClassDeclaration createClass(Position pos, TypeDefContext className, TypeListContext inheritsFrom, boolean isAbstract, List members) { List superClasses = new ArrayList<>(); if (inheritsFrom != null) { @@ -487,16 +486,16 @@ protected ClassDeclaration createClass(Position pos, TypeContext className, Type } } - ArrayList genericTypes = new ArrayList<>(); + ArrayList genericTypes = new ArrayList<>(); ClassDeclaration cl = new ClassDeclaration(pos, convertResolvableIdentifier(className), superClasses, new Block(pos), isAbstract, genericTypes); - TypeContext type = className; - if (type.typeList() != null) { - for (TypeContext typeContext1 : type.typeList().type()) { - genericTypes.add(new AbstractGenericType(cl, position(typeContext1.getStart()), - convertResolvableIdentifier(typeContext1))); + TypeDefContext type = className; + if (type.typeDefList() != null) { + for (BoundedTypeContext boundedTypeContext : type.typeDefList().boundedType()) { + genericTypes.add(new TypeParameterDeclaration(position(boundedTypeContext.getStart()), + convertResolvableIdentifier(boundedTypeContext), getTypeBound(boundedTypeContext))); } } @@ -536,10 +535,23 @@ protected ClassDeclaration createClass(Position pos, TypeContext className, Type return cl; } + private ResolvableIdentifier convertResolvableIdentifier(BoundedTypeContext boundedTypeContext) { + return new ResolvableIdentifier(boundedTypeContext.ClassIdentifier().toString()); + } + + private ResolvableIdentifier convertResolvableIdentifier(TypeDefContext className) { + return new ResolvableIdentifier(className.ClassIdentifier().toString()); + } + + private Optional getTypeBound(BoundedTypeContext typeContext) { + TypeBoundContext typeBoundContext = typeContext. + typeBound(); + return Optional.ofNullable(typeBoundContext).map( t -> convertResolvableIdentifier(t.type())); + } + @Override public ASTNode visitAbstractMethodDeclaration(AbstractMethodDeclarationContext ctx) { return buildAbstractMethod( - true, ctx.parameterList(), ctx.getStart(), ctx.type(), @@ -644,7 +656,7 @@ private ASTNode createForLoop(Position pos, ResolvableIdentifier indexVar, Expre // ## MONTY: ## Int i := (_i as Just).getValue() ResolvableIdentifier iteratorType = - new ResolvableIdentifier("Just", Arrays.asList((ResolvableIdentifier) null)); + new ResolvableIdentifier("Just", Collections.singletonList(new ResolvableIdentifier("Type"))); Expression getValueExpr = new MemberAccess(pos, new CastExpression(pos, new VariableAccess(pos, maybeIdent), iteratorType, callGetNext), new FunctionCall(pos, new ResolvableIdentifier("getValue"), @@ -906,7 +918,9 @@ public ASTNode visitLiteral(LiteralContext ctx) { for (ExpressionContext eContext : ctx.arrayLiteral().expression()) { elements.add((Expression) visit(eContext)); } - return new ArrayLiteral(position(ctx.getStart()), elements); + ArrayLiteral arrayLiteral = new ArrayLiteral(position(ctx.getStart()), elements); + ResolvableIdentifier top = new ResolvableIdentifier("Object"); //This should be infered or the Bottom Type + return new FunctionCall(position(ctx.getStart()), new ResolvableIdentifier("Array", Arrays.asList(top)), Arrays.asList(arrayLiteral)); } else if (ctx.rangeLiteral() != null) { ArrayList parameters = new ArrayList<>(); for (ExpressionContext eContext : ctx.rangeLiteral().expression()) { @@ -1019,7 +1033,7 @@ private CastExpression visitCastExpression(ExpressionContext ctx) { } private IsExpression visitIsExpression(ExpressionContext ctx) { - ResolvableIdentifier type = new ResolvableIdentifier(getText(ctx.ClassIdentifier())); + ResolvableIdentifier type = convertResolvableIdentifier(ctx.type()); tupleDeclarationFactory.checkTupleType(type); return new IsExpression(position(ctx.getStart()), (Expression) visit(ctx.expr), type); } @@ -1299,7 +1313,7 @@ protected ConditionalStatement ifNotAlreadyMatched(Position pos, ResolvableIdent @Override public ASTNode visitCaseClassDeclaration(CaseClassDeclarationContext ctx) { Position pos = position(ctx.getStart()); - ClassDeclaration classDecl = createClass(pos, ctx.type(), ctx.typeList(), false, ctx.memberDeclaration()); + ClassDeclaration classDecl = createClass(pos, ctx.typeDef(), ctx.typeList(), false, ctx.memberDeclaration()); List parameterList = createParameterListWithoutDefaults(ctx.parameterListWithoutDefaults()); @@ -1324,10 +1338,13 @@ public ASTNode visitCaseClassDeclaration(CaseClassDeclarationContext ctx) { DeclarationType.INITIALIZER, null); classDecl.getBlock().addDeclaration(caseInit); classDecl.getBlock().addDeclaration(createCaseEqMethod(pos, parameterList, classDecl)); - currentBlocks.peek().addDeclaration(classDecl); + if(classDecl.getTypeParameterDeclarations().isEmpty()){ + currentBlocks.peek().addDeclaration(classDecl); - // create the decompose function - return createDecomposerFunction(pos, parameterList, classDecl); + // create the decompose function + return createDecomposerFunction(pos, parameterList, classDecl); + } + return classDecl; } protected FunctionDeclaration createDecomposerFunction(Position pos, List parameterList, @@ -1396,7 +1413,7 @@ protected FunctionDeclaration createCaseEqMethod(Position pos, List T getParentNodeByType(Class type) { ASTNode n = getParentNode(); while ((!type.isInstance(n)) && (n != null)) { n = n.getParentNode(); } - return n; + return (T) n; } /** Set parent node. diff --git a/src/main/java/de/uni/bremen/monty/moco/ast/ClassScope.java b/src/main/java/de/uni/bremen/monty/moco/ast/ClassScope.java index 330107b..26fb875 100644 --- a/src/main/java/de/uni/bremen/monty/moco/ast/ClassScope.java +++ b/src/main/java/de/uni/bremen/monty/moco/ast/ClassScope.java @@ -39,9 +39,18 @@ package de.uni.bremen.monty.moco.ast; import de.uni.bremen.monty.moco.ast.declaration.*; +import de.uni.bremen.monty.moco.ast.types.FunctionType; +import de.uni.bremen.monty.moco.ast.types.TypeContext; +import de.uni.bremen.monty.moco.ast.types.TypeFactory; import de.uni.bremen.monty.moco.exception.*; +import de.uni.bremen.monty.moco.util.JavaUtil; +import de.uni.bremen.monty.moco.visitor.VisitOnceVisitor; + +import java.util.Collections; import java.util.List; import java.util.ArrayList; +import java.util.Optional; +import java.util.stream.Collectors; /** A scope in which identifier are associated with declarations. *

@@ -64,6 +73,7 @@ * Note: only single inheritance so far. */ public class ClassScope extends Scope { + private final TypeContext context; /** The parent class in inheritance hierachy. */ private List parentClassesScopes; @@ -71,8 +81,9 @@ public class ClassScope extends Scope { * * @param parent * the parent scope in nesting hierachy */ - public ClassScope(Scope parent) { + public ClassScope(Scope parent, TypeContext context) { super(parent); + this.context = context; this.parentClassesScopes = new ArrayList<>(); } @@ -85,23 +96,23 @@ public void addParentClassScope(ClassScope scope) { * @param identifier * the identifier * @return the declaration or null if nothing is found */ - protected Declaration resolveMember(ResolvableIdentifier identifier) { + protected Optional resolveMember(ResolvableIdentifier identifier) { Declaration declaration = members.get(identifier); if (declaration != null) { - return declaration; + return Optional.of(declaration); } for (ClassScope scope : parentClassesScopes) { try { - declaration = scope.resolveMember(identifier); + Optional parentDecl = scope.resolveMember(identifier); + if(parentDecl.isPresent()){ + return parentDecl; + } } catch (StackOverflowError soe) { throw new CyclicDependencyException("Cyclic dependency detected: " + identifier.getSymbol()); } - if (declaration != null) { - return declaration; - } } - return null; + return Optional.empty(); } /** Resolve an identifier for list of overloaded functions in inherited scope. @@ -109,18 +120,21 @@ protected Declaration resolveMember(ResolvableIdentifier identifier) { * @param identifier * the identifier to resolve * @return the list of function declarations */ - protected List resolveFunctionMember(ResolvableIdentifier identifier) { - List result = new ArrayList<>(); + protected List resolveFunctionMember(ResolvableIdentifier identifier, VisitOnceVisitor visitor) { + List result = new ArrayList<>(); if (functions.containsKey(identifier)) { - result.addAll(functions.get(identifier)); + result.addAll(getResolvedFunctions(identifier,visitor)); } if (members.containsKey(identifier)) { - result.add(members.get(identifier)); + Declaration declaration = members.get(identifier); + if(isFunctionVariable(declaration)) { + result.add(TypeFactory.createFunction((VariableDeclaration) declaration)); + } } for (ClassScope scope : parentClassesScopes) { - result.addAll(scope.resolveFunctionMember(identifier)); + result.addAll(scope.resolveFunctionMember(identifier,visitor)); } return result; } @@ -133,13 +147,8 @@ protected List resolveFunctionMember(ResolvableIdentifier identifie * the identifier to resolve * @return the declaration or null if nothing is found */ @Override - public Declaration resolve(ResolvableIdentifier identifier) { - Declaration declaration = resolveMember(identifier); - - if (declaration != null) { - return declaration; - } - return super.resolve(identifier); + public Optional _resolve(ResolvableIdentifier identifier) { + return JavaUtil.or(resolveMember(identifier), () -> super._resolve(identifier)); } /** Resolve an identifier for list of overloaded functions. @@ -150,18 +159,35 @@ public Declaration resolve(ResolvableIdentifier identifier) { * the identifier to resolve * @return the list of function declarations */ @Override - public List resolveFunction(ResolvableIdentifier identifier) { - List result = new ArrayList<>(); - result.addAll(resolveFunctionMember(identifier)); + public Optional> _resolveFunction(ResolvableIdentifier identifier, VisitOnceVisitor visitor) { + List result = new ArrayList<>(); + result.addAll(resolveFunctionMember(identifier,visitor)); if (parent != null) { - try { - result.addAll(parent.resolveFunction(identifier)); - } catch (UnknownIdentifierException e) { - } + result.addAll(parent._resolveFunction(identifier, visitor).orElse(Collections.emptyList())); } if (result.isEmpty()) { - throw new UnknownIdentifierException(identifier); + return Optional.empty(); } - return result; + return Optional.of(result); + } + + @Override + protected List getResolvedFunctions(ResolvableIdentifier identifier, VisitOnceVisitor visitor) { + return functions.get(identifier).stream().map(f -> { + visitor.visitDoubleDispatched(f); + return TypeFactory.from(f, context); + }).collect(Collectors.toList()); + } + + public ClassScope extend(TypeContext context) { + ClassScope classScope = new ClassScope(parent, this.context.extend(context)); + classScope.parentClassesScopes = this.parentClassesScopes; + classScope.members = this.members; + classScope.functions = this.functions; + return classScope; + } + + public TypeContext getContext() { + return context; } } diff --git a/src/main/java/de/uni/bremen/monty/moco/ast/CoreClasses.java b/src/main/java/de/uni/bremen/monty/moco/ast/CoreClasses.java index dcc2f26..1a1e67b 100644 --- a/src/main/java/de/uni/bremen/monty/moco/ast/CoreClasses.java +++ b/src/main/java/de/uni/bremen/monty/moco/ast/CoreClasses.java @@ -47,16 +47,24 @@ public class CoreClasses { - private static Map coreClasses = new HashMap(); + public static final String OBJECT_SYMBOL = "Object"; + public static final String VOID_SYMBOL = "__void"; + + private static Map coreClasses; static { + reset(); + } + + public static void reset() { + coreClasses = new HashMap<>(); // TODO find name for void that is not a valid identifier String[] classNames = - new String[] { "Object", "Char", "String", "Int", "Float", "Bool", "Array", "__void", "Function" }; + new String[] { "Object", "Char", "String", "Int", "Float", "Bool", "NativeArray", VOID_SYMBOL, "Function" }; for (String name : classNames) { CoreClasses.setCoreClass(name, new ClassDeclaration(new Position("Dummy_" + name, 0, 0), new Identifier( - name), Collections. emptyList(), new Block( - new Position("Dummy_" + name, 1, 0)))); + name), Collections.emptyList(), new Block( + new Position("Dummy_" + name, 1, 0)), true)); } } @@ -65,7 +73,7 @@ public static void setCoreClass(String name, ClassDeclaration classDeclaration) } public static ClassDeclaration objectType() { - return coreClasses.get("Object"); + return coreClasses.get(OBJECT_SYMBOL); } public static ClassDeclaration charType() { @@ -89,7 +97,7 @@ public static ClassDeclaration boolType() { } public static ClassDeclaration arrayType() { - return coreClasses.get("Array"); + return coreClasses.get("NativeArray"); } public static ClassDeclaration functionType() { @@ -97,6 +105,6 @@ public static ClassDeclaration functionType() { } public static ClassDeclaration voidType() { - return coreClasses.get("__void"); + return coreClasses.get(VOID_SYMBOL); } } diff --git a/src/main/java/de/uni/bremen/monty/moco/ast/ResolvableIdentifier.java b/src/main/java/de/uni/bremen/monty/moco/ast/ResolvableIdentifier.java index 7bdc34c..6f979b6 100644 --- a/src/main/java/de/uni/bremen/monty/moco/ast/ResolvableIdentifier.java +++ b/src/main/java/de/uni/bremen/monty/moco/ast/ResolvableIdentifier.java @@ -99,6 +99,7 @@ public String toString() { for (ResolvableIdentifier generic : getGenericTypes()) { generics += generic != null ? generic.toString() + ", " : "?, "; } + generics = generics.substring(0, generics.length()-2); generics += ">"; } return getSymbol() + generics; diff --git a/src/main/java/de/uni/bremen/monty/moco/ast/Scope.java b/src/main/java/de/uni/bremen/monty/moco/ast/Scope.java index d3bf962..74da6e5 100644 --- a/src/main/java/de/uni/bremen/monty/moco/ast/Scope.java +++ b/src/main/java/de/uni/bremen/monty/moco/ast/Scope.java @@ -39,15 +39,15 @@ package de.uni.bremen.monty.moco.ast; import de.uni.bremen.monty.moco.ast.declaration.*; +import de.uni.bremen.monty.moco.ast.types.*; import de.uni.bremen.monty.moco.exception.InvalidExpressionException; import de.uni.bremen.monty.moco.exception.RedeclarationException; import de.uni.bremen.monty.moco.exception.UnknownIdentifierException; import de.uni.bremen.monty.moco.exception.UnknownTypeException; +import de.uni.bremen.monty.moco.visitor.VisitOnceVisitor; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; +import java.util.*; +import java.util.stream.Collectors; /** A scope in which an identifier is associated with a declaration. *

@@ -103,15 +103,19 @@ public Scope getParentScope() { * the identifier to resolve * @return the declaration */ public Declaration resolve(ResolvableIdentifier identifier) { + return _resolve(identifier).orElseThrow(() -> new UnknownIdentifierException(identifier)); + } + + protected Optional _resolve(ResolvableIdentifier identifier) { Declaration declaration = members.get(identifier); if (declaration != null) { - return declaration; + return Optional.of(declaration); } if (functions.containsKey(identifier)) { List functionDeclarations = functions.get(identifier); if (functionDeclarations.size() == 1) { - return functionDeclarations.get(0).getWrapperFunctionObjectDeclaration(); + return Optional.ofNullable(functionDeclarations.get(0).getWrapperFunctionObjectDeclaration()); } else if (functionDeclarations.size() > 1) { throw new InvalidExpressionException(null, "Accessing the identifier '" + identifier.getSymbol() + "' without a cast is ambiguous, since there are " + functionDeclarations.size() @@ -119,10 +123,10 @@ public Declaration resolve(ResolvableIdentifier identifier) { } } if (parent != null) { - return parent.resolve(identifier); + return parent._resolve(identifier); } - throw new UnknownIdentifierException(identifier); + return Optional.empty(); } /** Resolve an identifier for a type declaration. @@ -130,16 +134,9 @@ public Declaration resolve(ResolvableIdentifier identifier) { * @param identifier * the identifier to resolve * @return the declaration */ - public TypeDeclaration resolveType(ResolvableIdentifier identifier) { - try { - Declaration declaration = resolve(identifier); - if (declaration instanceof TypeDeclaration) { - return resolveGenericClass((TypeDeclaration) declaration, identifier); - } - throw new UnknownTypeException(identifier); - } catch (UnknownIdentifierException e) { - throw new UnknownTypeException(identifier); - } + public Type resolveType(ResolvableIdentifier identifier, VisitOnceVisitor visitor) { + Optional maybeType = tryToResolveType(identifier, visitor); + return maybeType.map(t -> t.extend(getContext())).orElseThrow(() -> new UnknownTypeException(identifier)); } /** Tries to resolve an identifier for a type declaration. @@ -147,13 +144,22 @@ public TypeDeclaration resolveType(ResolvableIdentifier identifier) { * @param identifier * the identifier to resolve * @return the declaration or null */ - public TypeDeclaration tryToResolveType(ResolvableIdentifier identifier) { + public Optional tryToResolveType(ResolvableIdentifier identifier, VisitOnceVisitor visitor) { try { - return resolveType(identifier); - } catch (UnknownTypeException e) { - return null; + return _resolve(identifier).flatMap((declaration) -> { + if (declaration instanceof TypeDeclaration) { + List resolvedGenericTypes = resolveGenericIdentifier(identifier, visitor); + visitor.visitDoubleDispatched(declaration); + if (declaration instanceof ClassDeclaration) { + TypeContext context = TypeContext.from((ClassDeclaration) declaration, resolvedGenericTypes); + return Optional.of(TypeFactory.from((ClassDeclaration) declaration, context)); + } + return Optional.of(new TypeVariable((TypeParameterDeclaration) declaration)); + } + return Optional.empty(); + }); } catch (InvalidExpressionException e) { - return null; + return Optional.empty(); } } @@ -162,25 +168,49 @@ public TypeDeclaration tryToResolveType(ResolvableIdentifier identifier) { * @param identifier * the identifier to resolve * @return the list of function declarations */ - public List resolveFunction(ResolvableIdentifier identifier) { - List result = new ArrayList(); + public List resolveFunction(ResolvableIdentifier identifier, VisitOnceVisitor visitor) { + return _resolveFunction(identifier, visitor).orElseThrow(() -> new UnknownIdentifierException(identifier)); + } + public Optional> _resolveFunction(ResolvableIdentifier identifier, VisitOnceVisitor visitor) { + List result = new ArrayList<>(); if (functions.containsKey(identifier)) { - result.addAll(functions.get(identifier)); + List functionDeclarations = getResolvedFunctions(identifier, visitor); + result.addAll(functionDeclarations); } if (members.containsKey(identifier)) { - result.add(members.get(identifier)); + Declaration declaration = members.get(identifier); + if(isFunctionVariable(declaration)) { + result.add(TypeFactory.createFunction((VariableDeclaration) declaration)); + } } if (parent != null) { - try { - result.addAll(parent.resolveFunction(identifier)); - } catch (UnknownIdentifierException e) { - } + result.addAll(parent._resolveFunction(identifier, visitor).orElse(Collections.emptyList())); } if (result.isEmpty()) { - throw new UnknownIdentifierException(identifier); + return Optional.empty(); + } + return Optional.of(result); + } + + public boolean isFunctionVariable(Declaration declaration) { + return declaration instanceof VariableDeclaration && ((VariableDeclaration) declaration).getType().isAssignableFrom(Types.functionType()); + } + + protected List getResolvedFunctions(ResolvableIdentifier identifier, VisitOnceVisitor visitor) { + return functions.get(identifier).stream().map((declaration) -> { + visitor.visitDoubleDispatched(declaration); + return TypeFactory.from(declaration, TypeContext.EMPTY); + }).collect(Collectors.toList()); + } + + private List resolveGenericIdentifier(ResolvableIdentifier identifier, VisitOnceVisitor visitor) { + ArrayList genericIdentifier = new ArrayList<>(); + for (ResolvableIdentifier resolvableIdentifier : identifier.getGenericTypes()) { + Type typeInfo = resolveType(resolvableIdentifier,visitor); + genericIdentifier.add(typeInfo); } - return result; + return genericIdentifier; } /** Associate an identifier with a declaration. @@ -228,29 +258,14 @@ public void define(Declaration declaration) throws RedeclarationException { * the declaration * @throws RedeclarationException * if this is invalid overloading */ - public void define(Identifier identifier, FunctionDeclaration declaration) throws RedeclarationException { + private void define(Identifier identifier, FunctionDeclaration declaration) throws RedeclarationException { if (!functions.containsKey(identifier)) { functions.put(identifier, new ArrayList()); } functions.get(identifier).add(declaration); } - private TypeDeclaration resolveGenericClass(TypeDeclaration originalType, ResolvableIdentifier genericIdentifier) { - List genericTypes = genericIdentifier.getGenericTypes(); - if (!genericTypes.isEmpty() && originalType instanceof ClassDeclaration) { - ClassDeclaration originalClass = (ClassDeclaration) originalType; - ArrayList concreteGenerics = new ArrayList<>(); - for (ResolvableIdentifier genericType : genericTypes) { - TypeDeclaration decl = resolveType(genericType); - decl = resolveGenericClass(decl, genericType); - - if (decl instanceof AbstractGenericType) { - return originalType; - } - concreteGenerics.add((ClassDeclaration) decl); - } - return originalClass.getVariation(genericIdentifier, concreteGenerics); - } - return originalType; + public TypeContext getContext() { + return TypeContext.EMPTY; } } diff --git a/src/main/java/de/uni/bremen/monty/moco/ast/declaration/AbstractGenericType.java b/src/main/java/de/uni/bremen/monty/moco/ast/declaration/AbstractGenericType.java deleted file mode 100644 index 142ca8a..0000000 --- a/src/main/java/de/uni/bremen/monty/moco/ast/declaration/AbstractGenericType.java +++ /dev/null @@ -1,44 +0,0 @@ -package de.uni.bremen.monty.moco.ast.declaration; - -import de.uni.bremen.monty.moco.ast.ASTNode; -import de.uni.bremen.monty.moco.ast.Identifier; -import de.uni.bremen.monty.moco.ast.Position; -import de.uni.bremen.monty.moco.visitor.BaseVisitor; - -public class AbstractGenericType extends TypeDeclaration { - - private ClassDeclaration definedIn; - - /** Constructor. - * - * @param definedIn - * @param position - * Position of this node - * @param identifier - * the identifier */ - public AbstractGenericType(ClassDeclaration definedIn, Position position, Identifier identifier) { - super(position, identifier); - this.definedIn = definedIn; - } - - @Override - public void visit(BaseVisitor visitor) { - visitor.visit(this); - } - - @Override - public void visitChildren(BaseVisitor visitor) { - - } - - public ClassDeclaration getDefinedIn() { - return definedIn; - } - - public boolean equals(Object other) { - if (other instanceof AbstractGenericType) { - return ((AbstractGenericType) other).getIdentifier().equals(getIdentifier()); - } - return false; - } -} diff --git a/src/main/java/de/uni/bremen/monty/moco/ast/declaration/ClassDeclaration.java b/src/main/java/de/uni/bremen/monty/moco/ast/declaration/ClassDeclaration.java index 1c1c310..cdec023 100644 --- a/src/main/java/de/uni/bremen/monty/moco/ast/declaration/ClassDeclaration.java +++ b/src/main/java/de/uni/bremen/monty/moco/ast/declaration/ClassDeclaration.java @@ -38,10 +38,8 @@ */ package de.uni.bremen.monty.moco.ast.declaration; -import de.uni.bremen.monty.moco.ast.Block; -import de.uni.bremen.monty.moco.ast.Identifier; -import de.uni.bremen.monty.moco.ast.Position; -import de.uni.bremen.monty.moco.ast.ResolvableIdentifier; +import de.uni.bremen.monty.moco.ast.*; +import de.uni.bremen.monty.moco.ast.types.PartialAppliedTypeInfo; import de.uni.bremen.monty.moco.visitor.BaseVisitor; import java.util.ArrayList; @@ -53,13 +51,15 @@ * A ClassDeclaration has a list of superclasses and a list of nested declarations. It can be used as a type. */ public class ClassDeclaration extends TypeDeclaration { - private final List abstractGenericTypes; + private final List typeParameterDeclarations; /** Identifier of superclasses. */ private final List superClassIdentifiers; /** Superclasses. */ - private final List superClassDeclarations = new ArrayList<>(); + private final List superClassDeclarations = new ArrayList<>(); + + private final boolean dummy; /** The generated default initializer to be called from every user defined initializer. */ private FunctionDeclaration defaultInitializer; @@ -67,8 +67,6 @@ public class ClassDeclaration extends TypeDeclaration { /** Block with assignments **/ private Block block; - private final List variations; - /** The virtal method table for this class */ private List virtualMethodTable = new ArrayList<>(); @@ -77,7 +75,7 @@ public class ClassDeclaration extends TypeDeclaration { /** The last index for the attributes of this class. This counter starts at `1` as index 0 is reserved for a pointer * to the vmt. */ - private int lastAttributeIndex = 1; + private int lastAttributeIndex = -1; private boolean abstractClass = false; @@ -98,21 +96,31 @@ public ClassDeclaration(Position position, Identifier identifier, List superClasses, + Block block, boolean dummy) { + super(position, identifier); + this.block = block; + this.superClassIdentifiers = superClasses; + this.typeParameterDeclarations = Collections.emptyList(); + this.dummy = dummy; } public ClassDeclaration(Position position, Identifier identifier, List superClassIdentifiers, - Block block, boolean isAbstract, List abstractGenericTypes) { + Block block, boolean isAbstract, List typeParameterDeclarations) { super(position, identifier); this.superClassIdentifiers = superClassIdentifiers; this.block = block; - this.abstractGenericTypes = abstractGenericTypes; - this.variations = new ArrayList<>(abstractGenericTypes.size()); + this.typeParameterDeclarations = typeParameterDeclarations; this.abstractClass = isAbstract; + this.dummy = false; } /** Get the list of declarations and assignments. + * * * @return the block with declarations and assignments */ public Block getBlock() { @@ -134,22 +142,10 @@ public List getSuperClassIdentifiers() { /** Get the list of direct superclasses this class inherits from. * * @return the superclasses */ - public List getSuperClassDeclarations() { + public List getSuperClassDeclarations() { return superClassDeclarations; } - /** Get a list of all the declarations of superclasses and this one. */ - public List getSuperClassDeclarationsRecursive() { - List allSuperClassDeclarations = new ArrayList<>(); - for (TypeDeclaration superClass : superClassDeclarations) { - if (superClass instanceof ClassDeclaration) { - allSuperClassDeclarations.addAll(((ClassDeclaration) superClass).getSuperClassDeclarationsRecursive()); - } - } - allSuperClassDeclarations.add(this); - return allSuperClassDeclarations; - } - /** set the last attribute index. * * @param lastAttributeIndex @@ -187,8 +183,8 @@ public void setDefaultInitializer(FunctionDeclaration defaultInitializer) { this.defaultInitializer = defaultInitializer; } - public List getAbstractGenericTypes() { - return abstractGenericTypes; + public List getTypeParameterDeclarations() { + return typeParameterDeclarations; } /** {@inheritDoc} */ @@ -200,49 +196,10 @@ public void visit(BaseVisitor visitor) { /** {@inheritDoc} */ @Override public void visitChildren(BaseVisitor visitor) { - for (AbstractGenericType abstractGenericType : abstractGenericTypes) { - visitor.visitDoubleDispatched(abstractGenericType); - } - for (ClassDeclarationVariation variation : variations) { - visitor.visitDoubleDispatched(variation); - } + typeParameterDeclarations.forEach(visitor::visitDoubleDispatched); visitor.visitDoubleDispatched(block); } - /** {@inheritDoc} */ - @Override - public boolean matchesType(TypeDeclaration other) { - if (super.matchesType(other)) { - return true; - } - if (other instanceof ClassDeclaration) { - for (TypeDeclaration parentClass : superClassDeclarations) { - if (parentClass.matchesType(other)) { - return true; - } - } - } - return false; - } - - public void addVariation(ClassDeclarationVariation variation) { - variations.add(variation); - } - - public List getVariations() { - return variations; - } - - public TypeDeclaration getVariation(ResolvableIdentifier genericIdentifier, - ArrayList concreteGenerics) { - for (ClassDeclarationVariation variation : getVariations()) { - if (variation.getConcreteGenericTypes().equals(concreteGenerics)) { - return variation; - } - } - return new ClassDeclarationVariation(this, genericIdentifier, concreteGenerics); - } - public List getMethods() { ArrayList methods = new ArrayList<>(); for (Declaration decl : getBlock().getDeclarations()) { @@ -272,4 +229,23 @@ public boolean isGenerator() { public void setGenerator(boolean gen) { _isGenerator = gen; } + + public ClassScope getScope() { + return (ClassScope) super.getScope(); + } + + public String toString(){ + Object abstractGenericTypes = getTypeParameterDeclarations().isEmpty() ? "" : getTypeParameterDeclarations(); + String symbol; + if(isFunctionWrapper()) { + symbol = getWrappedFunction().getIdentifier().toString(); + } else { + symbol = getIdentifier().getSymbol(); + } + return symbol + abstractGenericTypes; + } + + public boolean isDummy() { + return dummy; + } } diff --git a/src/main/java/de/uni/bremen/monty/moco/ast/declaration/ClassDeclarationVariation.java b/src/main/java/de/uni/bremen/monty/moco/ast/declaration/ClassDeclarationVariation.java deleted file mode 100644 index cb9f37d..0000000 --- a/src/main/java/de/uni/bremen/monty/moco/ast/declaration/ClassDeclarationVariation.java +++ /dev/null @@ -1,291 +0,0 @@ -package de.uni.bremen.monty.moco.ast.declaration; - -import de.uni.bremen.monty.moco.ast.Block; -import de.uni.bremen.monty.moco.ast.ClassScope; -import de.uni.bremen.monty.moco.ast.ResolvableIdentifier; -import de.uni.bremen.monty.moco.ast.statement.Statement; - -import java.util.ArrayList; -import java.util.Collection; -import java.util.List; - -public class ClassDeclarationVariation extends ClassDeclaration { - - private List concreteGenericTypes; - - private final ClassDeclaration baseClass; - - public ClassDeclarationVariation(ClassDeclaration classDecl, ResolvableIdentifier identifier, - List concreteGenericTypes) { - super(classDecl.getPosition(), identifier, classDecl.getSuperClassIdentifiers(), new Block( - classDecl.getBlock().getPosition()), classDecl.isAbstract(), classDecl.getAbstractGenericTypes()); - this.baseClass = classDecl; - this.concreteGenericTypes = concreteGenericTypes; - setParentNode(classDecl.getParentNode()); - ClassScope classScope = new ClassScope(classDecl.getScope().getParentScope()); - setScope(classScope); - classDecl.addVariation(this); - - addSuperClassDeclarations(classDecl); - - Collection functionDeclarations = mapFunctions(classDecl.getVirtualMethodTable()); - getVirtualMethodTable().addAll(functionDeclarations); - mapBlock(classDecl.getBlock()); - getBlock().setParentNode(this); - FunctionDeclaration defaultInitializer = mapFunction(classDecl.getDefaultInitializer()); - setDefaultInitializer(defaultInitializer); - for (Declaration functionDeclaration : getBlock().getDeclarations()) { - if (!(functionDeclaration instanceof FunctionDeclaration) - || !((FunctionDeclaration) functionDeclaration).isDefaultInitializer()) { - classScope.define(functionDeclaration); - } - } - classScope.define(defaultInitializer); - } - - /** The parent (super) class declarations should also be referenced in the ClassDeclarationVariation and not only in - * the ClassDeclaration, since they can be used interchangeably - * - * @param classDecl */ - private void addSuperClassDeclarations(ClassDeclaration classDecl) { - List ownParents = getSuperClassDeclarations(); - for (TypeDeclaration parent : classDecl.getSuperClassDeclarations()) { - // if the parent class is a concrete generic class, we can add it - if (parent instanceof ClassDeclarationVariation) { - ownParents.add(parent); - } else if (parent instanceof ClassDeclaration) { - // if the parent class has no unresolved abstract generic types, we can add it as well - if (((ClassDeclaration) parent).getAbstractGenericTypes().isEmpty()) { - ownParents.add(parent); - ((ClassScope) getScope()).addParentClassScope((ClassScope) parent.getScope()); - } - // if there are unresolved type parameters, we have to resolve them using our own - else { - TypeDeclaration newParent = mapAbstractGenericSuperClass((ClassDeclaration) parent); - ownParents.add(newParent); - ((ClassScope) getScope()).addParentClassScope((ClassScope) newParent.getScope()); - } - } - // if the parent is neither one of the above, something is terribly going wrong... - else { - throw new RuntimeException("Was ist hier los?!?"); - } - } - } - - /** converts a parent ClassDeclaration with abstractGenericTypes into a ClassDeclarationVariation with - * concreteGenericTypes - * - * @return */ - private TypeDeclaration mapAbstractGenericSuperClass(ClassDeclaration parent) { - List placeholders = parent.getAbstractGenericTypes(); - List ownPlaceholders = baseClass.getAbstractGenericTypes(); - ArrayList concreteTypes = new ArrayList<>(placeholders.size()); - ArrayList concreteIdentifiers = new ArrayList<>(placeholders.size()); - - for (AbstractGenericType placeholder : placeholders) { - int index = ownPlaceholders.indexOf(placeholder); - concreteTypes.add(concreteGenericTypes.get(index)); - concreteIdentifiers.add(ResolvableIdentifier.convert(concreteGenericTypes.get(index).getIdentifier())); - } - - return parent.getVariation( - new ResolvableIdentifier(parent.getIdentifier().getSymbol(), concreteIdentifiers), - concreteTypes); - } - - private void mapBlock(Block block) { - for (Statement statement : block.getStatements()) { - getBlock().addStatement(statement); - } - for (Declaration declaration : block.getDeclarations()) { - - if (declaration instanceof FunctionDeclaration) { - declaration = mapFunction((FunctionDeclaration) declaration); - } else if (declaration instanceof VariableDeclaration) { - declaration = mapDeclaration((VariableDeclaration) declaration); - } - getBlock().addDeclaration(declaration); - } - } - - private Collection mapFunctions(List originalVirtualMethods) { - ArrayList functionDeclarations = new ArrayList<>(); - for (FunctionDeclaration functionDeclaration : originalVirtualMethods) { - functionDeclarations.add(mapFunction(functionDeclaration)); - } - return functionDeclarations; - } - - private FunctionDeclaration mapFunction(FunctionDeclaration functionDeclaration) { - FunctionDeclaration funDecl; - // important for generic inheritance - - if (!functionDeclaration.getDefiningClass().getAbstractGenericTypes().isEmpty()) { - ClassDeclarationVariation parent = findCorrectSuperClass(functionDeclaration); - parent = parent != null ? parent : this; - if (functionDeclaration.isFunction()) { - TypeDeclaration returnType = mapGenericType((functionDeclaration).getReturnType()); - funDecl = new ConcreteProcDecl(parent, functionDeclaration, returnType); - } else { - funDecl = new ConcreteProcDecl(parent, functionDeclaration); - } - funDecl.getParameters().addAll(mapParameter(functionDeclaration.getParameters(), funDecl)); - funDecl.setParentNode(this); - funDecl.setScope(functionDeclaration.getScope()); - return funDecl; - } - return functionDeclaration; - } - - /** inherited methods in the VMT should get the correct ClassDeclarationVariation reference. If this does not happen, - * inheritance does not work for ``Gen2 ----|> Gen1`` but only for ``NotGen ----|> Gen`` - * - * @param funDecl - * @return */ - private ClassDeclarationVariation findCorrectSuperClass(FunctionDeclaration funDecl) { - ClassDeclaration classDecl = funDecl.getDefiningClass(); - for (TypeDeclaration parent : getSuperClassDeclarations()) { - if (parent instanceof ClassDeclarationVariation) { - int index = classDecl.getVariations().indexOf(parent); - if (index >= 0) { - return classDecl.getVariations().get(index); - } - } - } - return null; - } - - private TypeDeclaration mapGenericType(TypeDeclaration type) { - if (type instanceof AbstractGenericType) { - return mapAbstractToConcrete((AbstractGenericType) type); - } else if ((type instanceof ClassDeclaration) - && (!((ClassDeclaration) type).getAbstractGenericTypes().isEmpty())) { - return mapAbstractGenericToConcrete((ClassDeclaration) type); - } else { - return type; - } - } - - public TypeDeclaration mapAbstractGenericToConcrete(ClassDeclaration type) { - ArrayList concreteTypes = new ArrayList<>(type.getAbstractGenericTypes().size()); - ArrayList concreteIdentifiers = new ArrayList<>(type.getAbstractGenericTypes().size()); - for (AbstractGenericType abs : type.getAbstractGenericTypes()) { - TypeDeclaration con = mapGenericType(abs); - concreteTypes.add((ClassDeclaration) con); - concreteIdentifiers.add(ResolvableIdentifier.convert(con.getIdentifier())); - } - TypeDeclaration result = - type.getVariation( - new ResolvableIdentifier(type.getIdentifier().getSymbol(), concreteIdentifiers), - concreteTypes); - return result; - } - - public ClassDeclaration mapAbstractToConcrete(AbstractGenericType type) { - int index = getAbstractGenericTypes().indexOf(type); - if (index >= 0) { - return concreteGenericTypes.get(index); - } else { - throw new RuntimeException("is this really an Error?"); - } - } - - public List getConcreteGenericTypes() { - return concreteGenericTypes; - } - - private List mapParameter(List parameter, FunctionDeclaration decl) { - ArrayList params = new ArrayList<>(); - for (VariableDeclaration variableDeclaration : parameter) { - VariableDeclaration var; - TypeDeclaration abstractType = variableDeclaration.getType(); - if (abstractType instanceof AbstractGenericType) { - ClassDeclaration type = mapAbstractToConcrete((AbstractGenericType) abstractType); - var = - new VariableDeclaration(variableDeclaration.getPosition(), variableDeclaration.getIdentifier(), - type, variableDeclaration.getDeclarationType()); - var.setParentNode(decl); - var.setScope(getScope()); - } else { - var = variableDeclaration; - } - params.add(var); - } - return params; - } - - private Declaration mapDeclaration(VariableDeclaration declaration) { - VariableDeclaration variableDeclaration = - new VariableDeclaration(declaration.getPosition(), declaration.getIdentifier(), - mapGenericType(declaration.getType()), declaration.getDeclarationType()); - variableDeclaration.setParentNode(this); - variableDeclaration.setScope(getScope()); - variableDeclaration.setAttributeIndex(declaration.getAttributeIndex()); - return variableDeclaration; - } - - @Override - public List getVariations() { - return baseClass.getVariations(); - } - - @Override - public TypeDeclaration getVariation(ResolvableIdentifier genericIdentifier, - ArrayList concreteGenerics) { - return baseClass.getVariation(genericIdentifier, concreteGenerics); - } - - @Override - public void addVariation(ClassDeclarationVariation variation) { - baseClass.addVariation(variation); - } - - /** this method checks whether the type parameters match exactly - * - * @param other - * @return true if all params have the same type */ - protected boolean doTypeParamsMatch(TypeDeclaration other) { - if (other instanceof ClassDeclarationVariation) { - List otherGenerics = ((ClassDeclarationVariation) other).getConcreteGenericTypes(); - List ownGenerics = getConcreteGenericTypes(); - if (otherGenerics.size() == ownGenerics.size()) { - for (int i = 0; i < ownGenerics.size(); i++) { - // invariant behavior for generic classes - if (!ownGenerics.get(i).matchesTypeExactly(otherGenerics.get(i))) { - return false; - } - } - return true; - } - } - return false; - } - - @Override - public int getTypeDist(TypeDeclaration other, int dist) { - if (doTypeParamsMatch(other)) { // currently we only support invariance - return super.getTypeDist(other, dist); - } else { // but if the other one does not have any type parameters, super types of it could do so... - if (other instanceof ClassDeclaration) { - List superTypes = ((ClassDeclaration) other).getSuperClassDeclarations(); - int minScore = Integer.MAX_VALUE; - for (TypeDeclaration superType : superTypes) { - int score = getTypeDist(superType); - if (score < minScore) { - minScore = score; - } - } - if ((dist < Integer.MAX_VALUE) && (minScore < Integer.MAX_VALUE)) { - return dist + minScore; - } - } - } - return Integer.MAX_VALUE; - } - - public ClassDeclaration getBaseClass() { - return baseClass; - } - -} diff --git a/src/main/java/de/uni/bremen/monty/moco/ast/declaration/ConcreteProcDecl.java b/src/main/java/de/uni/bremen/monty/moco/ast/declaration/ConcreteProcDecl.java deleted file mode 100644 index 1dd15cb..0000000 --- a/src/main/java/de/uni/bremen/monty/moco/ast/declaration/ConcreteProcDecl.java +++ /dev/null @@ -1,33 +0,0 @@ -package de.uni.bremen.monty.moco.ast.declaration; - -import java.util.ArrayList; - -public class ConcreteProcDecl extends FunctionDeclaration { - private final ClassDeclarationVariation variation; - - public ConcreteProcDecl(ClassDeclarationVariation variation, FunctionDeclaration abstractDecl) { - super(abstractDecl.getPosition(), abstractDecl.getIdentifier(), abstractDecl.getBody(), - new ArrayList(), abstractDecl.getDeclarationType(), - abstractDecl.getReturnTypeIdentifier(), abstractDecl.isAbstract()); - this.variation = variation; - setParentNode(variation); - setVMTIndex(abstractDecl.getVMTIndex()); - } - - public ConcreteProcDecl(ClassDeclarationVariation variation, FunctionDeclaration abstractDecl, - TypeDeclaration returnType) { - super(abstractDecl.getPosition(), abstractDecl.getIdentifier(), abstractDecl.getBody(), - new ArrayList(), abstractDecl.getDeclarationType(), returnType, - abstractDecl.isAbstract()); - this.variation = variation; - setParentNode(variation); - setVMTIndex(abstractDecl.getVMTIndex()); - setScope(abstractDecl.getScope()); - } - - @Override - public ClassDeclarationVariation getDefiningClass() { - return variation; - } - -} diff --git a/src/main/java/de/uni/bremen/monty/moco/ast/declaration/Declaration.java b/src/main/java/de/uni/bremen/monty/moco/ast/declaration/Declaration.java index cbeda87..e3c95f7 100644 --- a/src/main/java/de/uni/bremen/monty/moco/ast/declaration/Declaration.java +++ b/src/main/java/de/uni/bremen/monty/moco/ast/declaration/Declaration.java @@ -42,6 +42,8 @@ import de.uni.bremen.monty.moco.ast.BasicASTNode; import de.uni.bremen.monty.moco.ast.Identifier; import de.uni.bremen.monty.moco.ast.Position; +import org.apache.commons.lang3.builder.EqualsBuilder; +import org.apache.commons.lang3.builder.HashCodeBuilder; /** The baseclass of every declaration. *

@@ -75,4 +77,24 @@ public void setAccessModifier(AccessModifier access) { public Identifier getIdentifier() { return identifier; } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + + if (o == null || getClass() != o.getClass()) return false; + + Declaration that = (Declaration) o; + + return new EqualsBuilder() + .append(identifier, that.identifier) + .isEquals(); + } + + @Override + public int hashCode() { + return new HashCodeBuilder(17, 37) + .append(identifier) + .toHashCode(); + } } diff --git a/src/main/java/de/uni/bremen/monty/moco/ast/declaration/FunctionDeclaration.java b/src/main/java/de/uni/bremen/monty/moco/ast/declaration/FunctionDeclaration.java index 6474a64..04ac63d 100644 --- a/src/main/java/de/uni/bremen/monty/moco/ast/declaration/FunctionDeclaration.java +++ b/src/main/java/de/uni/bremen/monty/moco/ast/declaration/FunctionDeclaration.java @@ -41,11 +41,12 @@ import de.uni.bremen.monty.moco.ast.*; import de.uni.bremen.monty.moco.ast.expression.Expression; import de.uni.bremen.monty.moco.ast.expression.FunctionCall; -import de.uni.bremen.monty.moco.ast.expression.WrappedFunctionCall; import de.uni.bremen.monty.moco.ast.statement.Assignment; import de.uni.bremen.monty.moco.ast.statement.ReturnStatement; import de.uni.bremen.monty.moco.ast.statement.Statement; +import de.uni.bremen.monty.moco.ast.types.*; import de.uni.bremen.monty.moco.visitor.BaseVisitor; +import de.uni.bremen.monty.moco.visitor.VisitOnceVisitor; import java.util.*; @@ -57,9 +58,9 @@ public enum DeclarationType { INITIALIZER, DEFAULT_INITIALIZER, METHOD, UNBOUND } - ClassDeclaration wrapperClass = null; - VariableDeclaration wrapperFunctionObjectDeclaration = null; - Assignment wrapperFunctionAssignment = null; + private ClassDeclaration wrapperClass = null; + private VariableDeclaration wrapperFunctionObjectDeclaration = null; + private Assignment wrapperFunctionAssignment = null; /** The declarations and statements within this declaration. */ private final Block body; @@ -74,7 +75,7 @@ public enum DeclarationType { /** The return returnType. */ private ResolvableIdentifier returnTypeIdentifier; - private TypeDeclaration returnType; + private Type returnType; private final boolean abstractMethod; @@ -118,36 +119,12 @@ public FunctionDeclaration(Position position, Identifier identifier, Block body, public FunctionDeclaration(Position position, Identifier identifier, Block body, List parameters) { - this(position, identifier, body, parameters, DeclarationType.UNBOUND, (ResolvableIdentifier) null); + this(position, identifier, body, parameters, DeclarationType.UNBOUND, null); returnTypeMustBeInferred = true; } public FunctionDeclaration(Position position, Identifier identifier, Block body, - List parameters, ResolvableIdentifier returnTypeIdentifier) { - this(position, identifier, body, parameters, DeclarationType.UNBOUND, returnTypeIdentifier); - } - - /** Constructor - * - * @param position - * * Position of this node - * @param identifier - * the identifier - * @param body - * the body of this function - * @param parameters - * the parameters of this function - * @param returnType - * the return returnType */ - public FunctionDeclaration(Position position, Identifier identifier, Block body, - List parameters, ClassDeclaration returnType) { - this(position, identifier, body, parameters, - returnType != null ? ResolvableIdentifier.convert(returnType.getIdentifier()) : null); - this.returnType = returnType; - } - - public FunctionDeclaration(Position position, Identifier identifier, Block body, - List parameters, DeclarationType declarationType, TypeDeclaration returnType, + List parameters, DeclarationType declarationType, Type returnType, boolean isAbstract) { this(position, identifier, body, parameters, declarationType, returnType != null ? ResolvableIdentifier.convert(returnType.getIdentifier()) : null, isAbstract); @@ -158,15 +135,18 @@ public FunctionDeclaration(Position position, Identifier identifier, Block body, * * @return the return returnType */ public ResolvableIdentifier getReturnTypeIdentifier() { + if (returnTypeIdentifier == null && !returnTypeMustBeInferred) { + return ResolvableIdentifier.convert(Types.voidType().getIdentifier()); + } return returnTypeIdentifier; } /** get the returnType. * * @return the returnType */ - public TypeDeclaration getReturnType() { - if (returnType == null) { - return CoreClasses.voidType(); + public Type getReturnType() { + if (returnType == null && !returnTypeMustBeInferred) { + return Types.voidType(); } return returnType; } @@ -174,7 +154,7 @@ public TypeDeclaration getReturnType() { /** set the returnType * * @param returnType */ - public void setReturnType(TypeDeclaration returnType) { + public void setReturnType(Type returnType) { if (this.returnType != null) return; this.returnType = returnType; } @@ -227,7 +207,7 @@ public boolean isUnbound() { public ClassDeclaration getDefiningClass() { if (isMethod() || isInitializer()) { - return (ClassDeclaration) getParentNodeByType(ClassDeclaration.class); + return getParentNodeByType(ClassDeclaration.class); } return null; } @@ -254,64 +234,46 @@ public void visitChildren(BaseVisitor visitor) { for (VariableDeclaration variableDeclaration : parameters) { visitor.visitDoubleDispatched(variableDeclaration); } +// if(wrapperFunctionObjectDeclaration != null){ +// visitor.visitDoubleDispatched(wrapperFunctionAssignment); +// } visitor.visitDoubleDispatched(body); } /** @return true if the procedure has no return type */ public boolean isProcedure() { - return returnTypeIdentifier == null; + return returnTypeIdentifier == null + || new ResolvableIdentifier(CoreClasses.VOID_SYMBOL).equals(returnTypeIdentifier); } /** @return true if the function has a return type */ public boolean isFunction() { - return returnTypeIdentifier != null; - } - - /** Check equality of two types taking into account the AST object hierachy. - *

- * - * @param other - * the other TypeDeclaration to check against - * @return if equal */ - @Override - public boolean matchesType(TypeDeclaration other) { - if (!super.matchesType(other)) { - return false; - } - if (!(other instanceof FunctionDeclaration)) { - return false; - } - List otherParameter = ((FunctionDeclaration) other).getParameters(); - if (parameters.size() != otherParameter.size()) { - return false; - } - for (int i = 0; i < parameters.size(); i++) { - if (!parameters.get(i).getType().matchesType(otherParameter.get(i).getType())) { - return false; - } - } - FunctionDeclaration proc = ((FunctionDeclaration) other); - - return !((proc.getReturnType() != null) && (proc.getReturnType() != CoreClasses.voidType())) - || returnType.matchesType(proc.getReturnType()); + return !isProcedure(); } - public boolean overridesFunction(FunctionDeclaration other) { + public boolean overridesFunction(FunctionType other) { +// ClassDeclaration thisClass = this.getParentNodeByType(ClassDeclaration.class); // List +// ClassDeclaration otherClass = other.getParentNodeByType(ClassDeclaration.class); // Collection +// if(thisClass.isAssignableFrom(otherClass)){ +// throw new RuntimeException("this Function must be invoked from the super class"); +// } +// if(thisClass.getSuperClassDeclarations()) if (!other.getIdentifier().getSymbol().equals(getIdentifier().getSymbol())) { return false; } - List otherParameter = other.getParameters(); + List otherParameter = other.getParameterTypes(); if (parameters.size() != otherParameter.size()) { return false; } for (int i = 0; i < parameters.size(); i++) { - if (!parameters.get(i).getType().matchesTypeExactly(otherParameter.get(i).getType())) { + Type type = otherParameter.get(i); + if (!parameters.get(i).getType().matchesTypeExactly(type)) { return false; } } - return !((other.getReturnType() != null) && (other.getReturnType() != CoreClasses.voidType())) - || returnType.matchesType(other.getReturnType()); + return !((other.getReturnType() != null) && (!other.getReturnType().isVoid())) + || returnType.isAssignableFrom(other.getReturnType()); } public boolean isAbstract() { @@ -346,18 +308,19 @@ public boolean isReturnTypeToBeInferred() { return returnTypeMustBeInferred; } - public void setInferredReturnType(TypeDeclaration type) { + public void setInferredReturnType(Type type, VisitOnceVisitor visitor) { returnType = type; returnTypeIdentifier = ResolvableIdentifier.convert(type.getIdentifier()); ResolvableIdentifier retIdent = returnTypeIdentifier; FunctionDeclaration applyMethod = wrapperClass.getMethods().get(0); - if (CoreClasses.voidType().equals(type)) { + if (type.isVoid()) { returnTypeIdentifier = null; retIdent = new ResolvableIdentifier("Tuple0"); applyMethod.setReturnTypeIdentifier(retIdent); - applyMethod.setReturnType(getScope().resolveType(retIdent)); + Type tuple0Type = getScope().resolveType(retIdent, visitor); + applyMethod.setReturnType(tuple0Type); splitReturnStatement(false); applyMethod.splitReturnStatement(true); @@ -373,7 +336,7 @@ public void setInferredReturnType(TypeDeclaration type) { genericWrapper.getGenericTypes().add(retIdent); } - protected void splitReturnStatement(boolean tupleInsteadOfVoid) { + protected ReturnStatement splitReturnStatement(boolean tupleInsteadOfVoid) { ReturnStatement oldRet = (ReturnStatement) getBody().getStatements().get(getBody().getStatements().size() - 1); // create a new return statement @@ -405,6 +368,7 @@ protected void splitReturnStatement(boolean tupleInsteadOfVoid) { throw new RuntimeException("invalid AST!"); } getBody().addStatement(newRet); + return newRet; } public String toString() { diff --git a/src/main/java/de/uni/bremen/monty/moco/ast/declaration/GeneratorFunctionDeclaration.java b/src/main/java/de/uni/bremen/monty/moco/ast/declaration/GeneratorFunctionDeclaration.java index f2bb383..01c70fb 100644 --- a/src/main/java/de/uni/bremen/monty/moco/ast/declaration/GeneratorFunctionDeclaration.java +++ b/src/main/java/de/uni/bremen/monty/moco/ast/declaration/GeneratorFunctionDeclaration.java @@ -1,3 +1,41 @@ +/* + * moco, the Monty Compiler + * Copyright (c) 2013-2014, Monty's Coconut, All rights reserved. + * + * This file is part of moco, the Monty Compiler. + * + * moco is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation; either + * version 3.0 of the License, or (at your option) any later version. + * + * moco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * Linking this program and/or its accompanying libraries statically or + * dynamically with other modules is making a combined work based on this + * program. Thus, the terms and conditions of the GNU General Public License + * cover the whole combination. + * + * As a special exception, the copyright holders of moco give + * you permission to link this programm and/or its accompanying libraries + * with independent modules to produce an executable, regardless of the + * license terms of these independent modules, and to copy and distribute the + * resulting executable under terms of your choice, provided that you also meet, + * for each linked independent module, the terms and conditions of the + * license of that module. + * + * An independent module is a module which is not + * derived from or based on this program and/or its accompanying libraries. + * If you modify this library, you may extend this exception to your version of + * the program or library, but you are not obliged to do so. If you do not wish + * to do so, delete this exception statement from your version. + * + * You should have received a copy of the GNU General Public + * License along with this library. + */ package de.uni.bremen.monty.moco.ast.declaration; import de.uni.bremen.monty.moco.ast.Block; diff --git a/src/main/java/de/uni/bremen/monty/moco/ast/declaration/TypeDeclaration.java b/src/main/java/de/uni/bremen/monty/moco/ast/declaration/TypeDeclaration.java index 8219ddf..d3c768e 100644 --- a/src/main/java/de/uni/bremen/monty/moco/ast/declaration/TypeDeclaration.java +++ b/src/main/java/de/uni/bremen/monty/moco/ast/declaration/TypeDeclaration.java @@ -54,53 +54,4 @@ public abstract class TypeDeclaration extends Declaration { public TypeDeclaration(Position position, Identifier identifier) { super(position, identifier); } - - /** Check equality of two types taking into account the AST object hierachy. - *

- * - * @param other - * the other TypeDeclaration to check against - * @return if equal */ - public boolean matchesType(TypeDeclaration other) { - return matchesTypeExactly(other); - } - - public boolean matchesTypeExactly(TypeDeclaration other) { - return getIdentifier().equals(other.getIdentifier()); - } - - /** Calculates the distance of this and other in the inheritance graph. Only calculates positive distances, i.e. if - * this is a parameter and other is an argument, other must be equal to or a subtype of this. otherwise the result - * will be Integer.MAX_VALUE. - * - * @param other - * @return a distance 0 <= dist <= Integer.MAX_VALUE */ - public int getTypeDist(TypeDeclaration other) { - return getTypeDist(other, 0); - } - - /** a helper method for "public int getTypeDist(TypeDeclaration other)" - * - * @param other - * @param dist - * @return */ - protected int getTypeDist(TypeDeclaration other, int dist) { - if (dist == Integer.MAX_VALUE) { - return dist; - } - if (matchesTypeExactly(other)) { - return dist; - } else if ((other instanceof ClassDeclaration) - && (!((ClassDeclaration) other).getSuperClassDeclarations().isEmpty())) { - int parentDist = Integer.MAX_VALUE; - for (TypeDeclaration superClass : ((ClassDeclaration) other).getSuperClassDeclarations()) { - int superDist = getTypeDist(superClass, dist + 1); - if (superDist < parentDist) { - parentDist = superDist; - } - } - return parentDist; - } - return Integer.MAX_VALUE; - } } diff --git a/src/main/java/de/uni/bremen/monty/moco/ast/declaration/TypeParameterDeclaration.java b/src/main/java/de/uni/bremen/monty/moco/ast/declaration/TypeParameterDeclaration.java new file mode 100644 index 0000000..ab3e389 --- /dev/null +++ b/src/main/java/de/uni/bremen/monty/moco/ast/declaration/TypeParameterDeclaration.java @@ -0,0 +1,89 @@ +/* + * moco, the Monty Compiler + * Copyright (c) 2013-2014, Monty's Coconut, All rights reserved. + * + * This file is part of moco, the Monty Compiler. + * + * moco is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation; either + * version 3.0 of the License, or (at your option) any later version. + * + * moco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * Linking this program and/or its accompanying libraries statically or + * dynamically with other modules is making a combined work based on this + * program. Thus, the terms and conditions of the GNU General Public License + * cover the whole combination. + * + * As a special exception, the copyright holders of moco give + * you permission to link this programm and/or its accompanying libraries + * with independent modules to produce an executable, regardless of the + * license terms of these independent modules, and to copy and distribute the + * resulting executable under terms of your choice, provided that you also meet, + * for each linked independent module, the terms and conditions of the + * license of that module. + * + * An independent module is a module which is not + * derived from or based on this program and/or its accompanying libraries. + * If you modify this library, you may extend this exception to your version of + * the program or library, but you are not obliged to do so. If you do not wish + * to do so, delete this exception statement from your version. + * + * You should have received a copy of the GNU General Public + * License along with this library. + */ +package de.uni.bremen.monty.moco.ast.declaration; + +import de.uni.bremen.monty.moco.ast.*; +import de.uni.bremen.monty.moco.ast.types.Type; +import de.uni.bremen.monty.moco.visitor.BaseVisitor; + +import java.util.Optional; + + +public class TypeParameterDeclaration extends TypeDeclaration { + + private Type upperTypeBound; + private final ResolvableIdentifier upperTypeBoundIdentifier; + + public TypeParameterDeclaration(Position position, Identifier identifier, Optional typeBound) { + super(position, identifier); + this.upperTypeBoundIdentifier = typeBound.orElse(new ResolvableIdentifier(CoreClasses.OBJECT_SYMBOL)); + } + + @Override + public void visit(BaseVisitor visitor) { + visitor.visit(this); + } + + @Override + public void visitChildren(BaseVisitor visitor) {} + + public boolean equals(Object other) { + if (other instanceof TypeParameterDeclaration) { + return ((TypeParameterDeclaration) other).getIdentifier().equals(getIdentifier()); + } + return false; + } + + public Type getUpperTypeBound() { + return upperTypeBound; + } + + @Override + public String toString() { + return getIdentifier().getSymbol(); + } + + public ResolvableIdentifier getUpperTypeBoundIdentifier() { + return upperTypeBoundIdentifier; + } + + public void setUpperTypeBound(Type upperTypeBound) { + this.upperTypeBound = upperTypeBound; + } +} diff --git a/src/main/java/de/uni/bremen/monty/moco/ast/declaration/VariableDeclaration.java b/src/main/java/de/uni/bremen/monty/moco/ast/declaration/VariableDeclaration.java index 4e6153c..e80bd90 100644 --- a/src/main/java/de/uni/bremen/monty/moco/ast/declaration/VariableDeclaration.java +++ b/src/main/java/de/uni/bremen/monty/moco/ast/declaration/VariableDeclaration.java @@ -42,6 +42,7 @@ import de.uni.bremen.monty.moco.ast.Position; import de.uni.bremen.monty.moco.ast.ResolvableIdentifier; import de.uni.bremen.monty.moco.ast.expression.Expression; +import de.uni.bremen.monty.moco.ast.types.Type; import de.uni.bremen.monty.moco.visitor.BaseVisitor; public class VariableDeclaration extends Declaration { @@ -50,8 +51,8 @@ public enum DeclarationType { } private ResolvableIdentifier typeIdentifier; - private TypeDeclaration type; - private DeclarationType declarationType; + private Type type; + private final DeclarationType declarationType; private boolean isGlobal; private Expression inferTypeFrom = null; @@ -60,11 +61,13 @@ public enum DeclarationType { public VariableDeclaration(Position position, Identifier identifier, ResolvableIdentifier typeIdentifier, DeclarationType declarationType) { - this(position, identifier, typeIdentifier); + super(position, identifier); + this.typeIdentifier = typeIdentifier; this.declarationType = declarationType; + attributeIndex = -1; } - public VariableDeclaration(Position position, Identifier identifier, TypeDeclaration type, + public VariableDeclaration(Position position, Identifier identifier, Type type, DeclarationType declarationType) { super(position, identifier); this.declarationType = declarationType; @@ -84,11 +87,6 @@ public VariableDeclaration(Position position, Identifier identifier, Expression this.inferTypeFrom = inferTypeFrom; } - /** set the declaration type */ - public void setDeclarationType(DeclarationType type) { - this.declarationType = type; - } - /** get the declaration type * * @return the declaration type */ @@ -118,14 +116,14 @@ public ResolvableIdentifier getTypeIdentifier() { /** get the type. * * @return the type */ - public TypeDeclaration getType() { + public Type getType() { return type; } /** set the type * * @param type */ - public void setType(TypeDeclaration type) { + public void setType(Type type) { if (this.type != null) return; this.type = type; } diff --git a/src/main/java/de/uni/bremen/monty/moco/ast/expression/CastExpression.java b/src/main/java/de/uni/bremen/monty/moco/ast/expression/CastExpression.java index 9ff757a..9a9c411 100644 --- a/src/main/java/de/uni/bremen/monty/moco/ast/expression/CastExpression.java +++ b/src/main/java/de/uni/bremen/monty/moco/ast/expression/CastExpression.java @@ -39,7 +39,9 @@ package de.uni.bremen.monty.moco.ast.expression; import de.uni.bremen.monty.moco.ast.*; +import de.uni.bremen.monty.moco.ast.types.Type; import de.uni.bremen.monty.moco.visitor.BaseVisitor; +import de.uni.bremen.monty.moco.visitor.ResolveVisitor; public class CastExpression extends Expression { @@ -93,31 +95,18 @@ public Expression getExpression() { return expression; } - public boolean typeParameterMustBeInferred() { - return inferTypeParameterFrom != null; - } - - public void inferTypeParameter() { - if (inferTypeParameterFrom.getType().getIdentifier() instanceof ResolvableIdentifier) { - ResolvableIdentifier otherIdent = (ResolvableIdentifier) inferTypeParameterFrom.getType().getIdentifier(); - int max = Math.min(otherIdent.getGenericTypes().size(), castIdentifier.getGenericTypes().size()); - for (int i = 0; i < max; i++) { - castIdentifier.getGenericTypes().set(i, otherIdent.getGenericTypes().get(i)); - } - } + public Type inferType(ResolveVisitor visitor) { + if (inferTypeParameterFrom != null) { + Scope inferScope = inferTypeParameterFrom.getType().getScope(); + return inferScope.resolveType(castIdentifier, visitor); + } else if(inferTypeFrom != null) { + visitor.visitDoubleDispatched(inferTypeFrom); + return inferTypeFrom.getType(); + } else throw new RuntimeException("Type doesn't need to be infered"); } public boolean typeMustBeInferred() { - return inferTypeFrom != null; - } - - public Expression getExpressionToInferFrom() { - return inferTypeFrom; - } - - public void inferType() { - setType(inferTypeFrom.getType()); - castIdentifier = ResolvableIdentifier.convert(getType().getIdentifier()); + return inferTypeFrom != null || inferTypeParameterFrom != null; } @Override diff --git a/src/main/java/de/uni/bremen/monty/moco/ast/expression/Expression.java b/src/main/java/de/uni/bremen/monty/moco/ast/expression/Expression.java index e5d8c92..dc09fa8 100644 --- a/src/main/java/de/uni/bremen/monty/moco/ast/expression/Expression.java +++ b/src/main/java/de/uni/bremen/monty/moco/ast/expression/Expression.java @@ -39,7 +39,7 @@ package de.uni.bremen.monty.moco.ast.expression; import de.uni.bremen.monty.moco.ast.*; -import de.uni.bremen.monty.moco.ast.declaration.TypeDeclaration; +import de.uni.bremen.monty.moco.ast.types.Type; /** The base class for every expression. *

@@ -47,7 +47,7 @@ public abstract class Expression extends BasicASTNode { /** The type. */ - private TypeDeclaration type; + private Type type; /** Constructor. * @@ -61,14 +61,14 @@ public Expression(Position position) { * * @param type * the new type */ - public void setType(TypeDeclaration type) { + public void setType(Type type) { this.type = type; } /** Get the type. * * @return the type */ - public TypeDeclaration getType() { + public Type getType() { return type; } } diff --git a/src/main/java/de/uni/bremen/monty/moco/ast/expression/FunctionCall.java b/src/main/java/de/uni/bremen/monty/moco/ast/expression/FunctionCall.java index e752b1a..6d3d479 100644 --- a/src/main/java/de/uni/bremen/monty/moco/ast/expression/FunctionCall.java +++ b/src/main/java/de/uni/bremen/monty/moco/ast/expression/FunctionCall.java @@ -40,8 +40,8 @@ import de.uni.bremen.monty.moco.ast.Position; import de.uni.bremen.monty.moco.ast.ResolvableIdentifier; -import de.uni.bremen.monty.moco.ast.declaration.FunctionDeclaration; import de.uni.bremen.monty.moco.ast.statement.Statement; +import de.uni.bremen.monty.moco.ast.types.FunctionType; import de.uni.bremen.monty.moco.visitor.BaseVisitor; import java.util.List; @@ -49,7 +49,7 @@ public class FunctionCall extends Expression implements Statement { private final ResolvableIdentifier identifier; protected final List arguments; - private FunctionDeclaration declaration; + private FunctionType declaration; public FunctionCall(Position position, ResolvableIdentifier identifier, List arguments) { super(position); @@ -86,13 +86,13 @@ public void visitChildren(BaseVisitor visitor) { } /** @return the declaration */ - public FunctionDeclaration getDeclaration() { + public FunctionType getDeclaration() { return declaration; } /** @param declaration * the declaration to set */ - public void setDeclaration(FunctionDeclaration declaration) { + public void setDeclaration(FunctionType declaration) { this.declaration = declaration; } } diff --git a/src/main/java/de/uni/bremen/monty/moco/ast/expression/IsExpression.java b/src/main/java/de/uni/bremen/monty/moco/ast/expression/IsExpression.java index 472dc26..bffff47 100644 --- a/src/main/java/de/uni/bremen/monty/moco/ast/expression/IsExpression.java +++ b/src/main/java/de/uni/bremen/monty/moco/ast/expression/IsExpression.java @@ -39,14 +39,14 @@ package de.uni.bremen.monty.moco.ast.expression; import de.uni.bremen.monty.moco.ast.*; -import de.uni.bremen.monty.moco.ast.declaration.*; +import de.uni.bremen.monty.moco.ast.types.Type; import de.uni.bremen.monty.moco.visitor.BaseVisitor; public class IsExpression extends Expression { private Expression expression; private ResolvableIdentifier isIdentifier; - private TypeDeclaration toType; + private Type toType; private Expression inferTypeFrom; public IsExpression(Position position, Expression expression, ResolvableIdentifier isIdentifier) { @@ -69,11 +69,11 @@ public Expression getExpression() { return expression; } - public void setToType(TypeDeclaration toType) { + public void setToType(Type toType) { this.toType = toType; } - public TypeDeclaration getToType() { + public Type getToType() { return toType; } diff --git a/src/main/java/de/uni/bremen/monty/moco/ast/expression/ParentExpression.java b/src/main/java/de/uni/bremen/monty/moco/ast/expression/ParentExpression.java index 4cb5c22..32c9e32 100644 --- a/src/main/java/de/uni/bremen/monty/moco/ast/expression/ParentExpression.java +++ b/src/main/java/de/uni/bremen/monty/moco/ast/expression/ParentExpression.java @@ -39,13 +39,13 @@ package de.uni.bremen.monty.moco.ast.expression; import de.uni.bremen.monty.moco.ast.*; -import de.uni.bremen.monty.moco.ast.declaration.*; +import de.uni.bremen.monty.moco.ast.types.PartialAppliedTypeInfo; import de.uni.bremen.monty.moco.visitor.BaseVisitor; public class ParentExpression extends Expression { private ResolvableIdentifier parentIdentifier; - private ClassDeclaration selfType; + private PartialAppliedTypeInfo selfType; public ParentExpression(Position position, ResolvableIdentifier parentIdentifier) { super(position); @@ -56,11 +56,11 @@ public ResolvableIdentifier getParentIdentifier() { return parentIdentifier; } - public ClassDeclaration getSelfType() { + public PartialAppliedTypeInfo getSelfType() { return selfType; } - public void setSelfType(ClassDeclaration selfType) { + public void setSelfType(PartialAppliedTypeInfo selfType) { this.selfType = selfType; } diff --git a/src/main/java/de/uni/bremen/monty/moco/ast/expression/WrappedFunctionCall.java b/src/main/java/de/uni/bremen/monty/moco/ast/expression/WrappedFunctionCall.java index 4bb2ccc..940107b 100644 --- a/src/main/java/de/uni/bremen/monty/moco/ast/expression/WrappedFunctionCall.java +++ b/src/main/java/de/uni/bremen/monty/moco/ast/expression/WrappedFunctionCall.java @@ -40,7 +40,7 @@ import de.uni.bremen.monty.moco.ast.Position; import de.uni.bremen.monty.moco.ast.Scope; -import de.uni.bremen.monty.moco.ast.declaration.TypeDeclaration; +import de.uni.bremen.monty.moco.ast.types.Type; import de.uni.bremen.monty.moco.ast.statement.Statement; import de.uni.bremen.monty.moco.visitor.BaseVisitor; @@ -88,7 +88,7 @@ public void setMemberAccess(MemberAccess memberAccess) { } @Override - public TypeDeclaration getType() { + public Type getType() { if (functionCall != null) { return functionCall.getType(); } diff --git a/src/main/java/de/uni/bremen/monty/moco/ast/expression/literal/TupleLiteral.java b/src/main/java/de/uni/bremen/monty/moco/ast/expression/literal/TupleLiteral.java index 1a0f7e6..0b498da 100644 --- a/src/main/java/de/uni/bremen/monty/moco/ast/expression/literal/TupleLiteral.java +++ b/src/main/java/de/uni/bremen/monty/moco/ast/expression/literal/TupleLiteral.java @@ -59,11 +59,7 @@ public TupleLiteral(Position position, List entries) { public void setConcreteTupleType() { for (Expression entry : arguments) { - if (entry.getType() instanceof ClassDeclaration) { - getIdentifier().getGenericTypes().add(ResolvableIdentifier.convert(entry.getType().getIdentifier())); - } else { - throw new RuntimeException("TYPE:: " + entry.getType()); - } + getIdentifier().getGenericTypes().add(ResolvableIdentifier.convert(entry.getType().getIdentifier())); } } } diff --git a/src/main/java/de/uni/bremen/monty/moco/ast/statement/ReturnStatement.java b/src/main/java/de/uni/bremen/monty/moco/ast/statement/ReturnStatement.java index 8ae4025..9071504 100644 --- a/src/main/java/de/uni/bremen/monty/moco/ast/statement/ReturnStatement.java +++ b/src/main/java/de/uni/bremen/monty/moco/ast/statement/ReturnStatement.java @@ -43,7 +43,7 @@ import de.uni.bremen.monty.moco.visitor.BaseVisitor; public class ReturnStatement extends BasicASTNode implements Statement { - private Expression parameter; + private final Expression parameter; /** Constructor. * diff --git a/src/main/java/de/uni/bremen/monty/moco/ast/types/ConcreteFunctionType.java b/src/main/java/de/uni/bremen/monty/moco/ast/types/ConcreteFunctionType.java new file mode 100644 index 0000000..28e8790 --- /dev/null +++ b/src/main/java/de/uni/bremen/monty/moco/ast/types/ConcreteFunctionType.java @@ -0,0 +1,66 @@ +/* + * moco, the Monty Compiler + * Copyright (c) 2013-2014, Monty's Coconut, All rights reserved. + * + * This file is part of moco, the Monty Compiler. + * + * moco is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation; either + * version 3.0 of the License, or (at your option) any later version. + * + * moco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * Linking this program and/or its accompanying libraries statically or + * dynamically with other modules is making a combined work based on this + * program. Thus, the terms and conditions of the GNU General Public License + * cover the whole combination. + * + * As a special exception, the copyright holders of moco give + * you permission to link this programm and/or its accompanying libraries + * with independent modules to produce an executable, regardless of the + * license terms of these independent modules, and to copy and distribute the + * resulting executable under terms of your choice, provided that you also meet, + * for each linked independent module, the terms and conditions of the + * license of that module. + * + * An independent module is a module which is not + * derived from or based on this program and/or its accompanying libraries. + * If you modify this library, you may extend this exception to your version of + * the program or library, but you are not obliged to do so. If you do not wish + * to do so, delete this exception statement from your version. + * + * You should have received a copy of the GNU General Public + * License along with this library. + */ +package de.uni.bremen.monty.moco.ast.types; + +import de.uni.bremen.monty.moco.ast.declaration.FunctionDeclaration; + +import java.util.List; + +public interface ConcreteFunctionType extends FunctionType { + + @Override + public ConcreteType getReturnType(); + + public List getParameter(); + + @Override + public ConcreteType getWrapperClass(); + + @Override + public ConcreteVariableType getWrapperFunctionObjectDeclaration(); + + @Override + public List getClosureVariables(); + + @Override + public ConcreteType getDefiningClass(); + + @Override + public FunctionType extend(TypeContext context); +} diff --git a/src/main/java/de/uni/bremen/monty/moco/ast/types/ConcreteFunctionTypeDecl.java b/src/main/java/de/uni/bremen/monty/moco/ast/types/ConcreteFunctionTypeDecl.java new file mode 100644 index 0000000..a7a38e7 --- /dev/null +++ b/src/main/java/de/uni/bremen/monty/moco/ast/types/ConcreteFunctionTypeDecl.java @@ -0,0 +1,84 @@ +/* + * moco, the Monty Compiler + * Copyright (c) 2013-2014, Monty's Coconut, All rights reserved. + * + * This file is part of moco, the Monty Compiler. + * + * moco is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation; either + * version 3.0 of the License, or (at your option) any later version. + * + * moco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * Linking this program and/or its accompanying libraries statically or + * dynamically with other modules is making a combined work based on this + * program. Thus, the terms and conditions of the GNU General Public License + * cover the whole combination. + * + * As a special exception, the copyright holders of moco give + * you permission to link this programm and/or its accompanying libraries + * with independent modules to produce an executable, regardless of the + * license terms of these independent modules, and to copy and distribute the + * resulting executable under terms of your choice, provided that you also meet, + * for each linked independent module, the terms and conditions of the + * license of that module. + * + * An independent module is a module which is not + * derived from or based on this program and/or its accompanying libraries. + * If you modify this library, you may extend this exception to your version of + * the program or library, but you are not obliged to do so. If you do not wish + * to do so, delete this exception statement from your version. + * + * You should have received a copy of the GNU General Public + * License along with this library. + */ +package de.uni.bremen.monty.moco.ast.types; + +import de.uni.bremen.monty.moco.ast.declaration.FunctionDeclaration; + +import java.util.List; + +public class ConcreteFunctionTypeDecl extends FunctionTypeDecl implements ConcreteFunctionType { + ConcreteFunctionTypeDecl(FunctionDeclaration declaration, TypeContext context, List parameter, ConcreteType returnType, ConcreteType definingClass, ConcreteType wrapperClass, ConcreteVariableType wrapperFunctionObjects, List closureVariables) { + super(declaration, context, parameter, returnType, definingClass, wrapperClass, wrapperFunctionObjects, closureVariables); + } + + @Override + public ConcreteType getReturnType() { + return (ConcreteType) super.getReturnType(); + } + + @Override + public List getParameter() { + return (List) super.getParameter(); + } + + @Override + public ConcreteType getWrapperClass() { + return (ConcreteType) super.getWrapperClass(); + } + + @Override + public ConcreteVariableType getWrapperFunctionObjectDeclaration() { + return (ConcreteVariableType) super.getWrapperFunctionObjectDeclaration(); + } + + @Override + public List getClosureVariables() { + return (List) super.getClosureVariables(); + } + + @Override + public ConcreteType getDefiningClass() { + return (ConcreteType) super.getDefiningClass(); + } + + @Override + public FunctionType extend(TypeContext context) { + return new ConcreteFunctionTypeDecl(declaration, this.context.extend(context), getParameter(), getReturnType(), getDefiningClass(), getWrapperClass(), getWrapperFunctionObjectDeclaration(), getClosureVariables()); + } +} diff --git a/src/main/java/de/uni/bremen/monty/moco/ast/types/ConcreteGeneratorFunctionType.java b/src/main/java/de/uni/bremen/monty/moco/ast/types/ConcreteGeneratorFunctionType.java new file mode 100644 index 0000000..e2146c2 --- /dev/null +++ b/src/main/java/de/uni/bremen/monty/moco/ast/types/ConcreteGeneratorFunctionType.java @@ -0,0 +1,65 @@ +/* + * moco, the Monty Compiler + * Copyright (c) 2013-2014, Monty's Coconut, All rights reserved. + * + * This file is part of moco, the Monty Compiler. + * + * moco is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation; either + * version 3.0 of the License, or (at your option) any later version. + * + * moco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * Linking this program and/or its accompanying libraries statically or + * dynamically with other modules is making a combined work based on this + * program. Thus, the terms and conditions of the GNU General Public License + * cover the whole combination. + * + * As a special exception, the copyright holders of moco give + * you permission to link this programm and/or its accompanying libraries + * with independent modules to produce an executable, regardless of the + * license terms of these independent modules, and to copy and distribute the + * resulting executable under terms of your choice, provided that you also meet, + * for each linked independent module, the terms and conditions of the + * license of that module. + * + * An independent module is a module which is not + * derived from or based on this program and/or its accompanying libraries. + * If you modify this library, you may extend this exception to your version of + * the program or library, but you are not obliged to do so. If you do not wish + * to do so, delete this exception statement from your version. + * + * You should have received a copy of the GNU General Public + * License along with this library. + */ +package de.uni.bremen.monty.moco.ast.types; + +import de.uni.bremen.monty.moco.ast.declaration.GeneratorFunctionDeclaration; +import de.uni.bremen.monty.moco.ast.statement.YieldStatement; + +import java.util.List; +import java.util.stream.Collectors; + +public class ConcreteGeneratorFunctionType extends ConcreteFunctionTypeDecl implements GeneratorFunctionType { + ConcreteGeneratorFunctionType(GeneratorFunctionDeclaration declaration, TypeContext context, List parameter, ConcreteType returnType, ConcreteType definingClass, ConcreteType wrapperClass, ConcreteVariableType wrapperFunctionObjects, List closureVariables) { + super(declaration, context, parameter, returnType, definingClass, wrapperClass, wrapperFunctionObjects, closureVariables); + } + + private GeneratorFunctionDeclaration getDeclaration(){ + return (GeneratorFunctionDeclaration) super.declaration; + } + + @Override + public List getYieldStatements() { + return getDeclaration().getYieldStatements(); + } + + @Override + public List getVariableDeclarations() { + return getDeclaration().getVariableDeclarations().stream().map(d -> (ConcreteVariableType) TypeFactory.from(d, context)).collect(Collectors.toList()); + } +} diff --git a/src/main/java/de/uni/bremen/monty/moco/ast/types/ConcreteType.java b/src/main/java/de/uni/bremen/monty/moco/ast/types/ConcreteType.java new file mode 100644 index 0000000..b101b19 --- /dev/null +++ b/src/main/java/de/uni/bremen/monty/moco/ast/types/ConcreteType.java @@ -0,0 +1,171 @@ +/* + * moco, the Monty Compiler + * Copyright (c) 2013-2014, Monty's Coconut, All rights reserved. + * + * This file is part of moco, the Monty Compiler. + * + * moco is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation; either + * version 3.0 of the License, or (at your option) any later version. + * + * moco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * Linking this program and/or its accompanying libraries statically or + * dynamically with other modules is making a combined work based on this + * program. Thus, the terms and conditions of the GNU General Public License + * cover the whole combination. + * + * As a special exception, the copyright holders of moco give + * you permission to link this programm and/or its accompanying libraries + * with independent modules to produce an executable, regardless of the + * license terms of these independent modules, and to copy and distribute the + * resulting executable under terms of your choice, provided that you also meet, + * for each linked independent module, the terms and conditions of the + * license of that module. + * + * An independent module is a module which is not + * derived from or based on this program and/or its accompanying libraries. + * If you modify this library, you may extend this exception to your version of + * the program or library, but you are not obliged to do so. If you do not wish + * to do so, delete this exception statement from your version. + * + * You should have received a copy of the GNU General Public + * License along with this library. + */ +package de.uni.bremen.monty.moco.ast.types; + +import de.uni.bremen.monty.moco.ast.ASTNode; +import de.uni.bremen.monty.moco.ast.Identifier; +import de.uni.bremen.monty.moco.ast.declaration.*; +import de.uni.bremen.monty.moco.util.AllIterator; +import org.apache.commons.lang3.builder.EqualsBuilder; +import org.apache.commons.lang3.builder.HashCodeBuilder; + +import java.util.*; + +public class ConcreteType extends PartialAppliedTypeInfo { + + private static Set allTypes = new HashSet<>(); + private final List concreteTypeParamters; + + ConcreteType(ClassDeclaration declaration, List concreteTypeParamters, TypeContext context) { + super(declaration,concreteTypeParamters, context); + this.concreteTypeParamters = concreteTypeParamters; + if(declaration.getTypeParameterDeclarations().size() != concreteTypeParamters.size()){ + throw new RuntimeException("abstract and concrete Types does not match"); + } + if(!declaration.isDummy()) { + allTypes.add(this); + } + } + + public List getSuperClassDeclarationsRecursive() { + List allSuperClassDeclarations = new ArrayList<>(); + for (PartialAppliedTypeInfo superClass : declaration.getSuperClassDeclarations()) { + ConcreteType concreteType = (ConcreteType) superClass.extend(context); + Collection superClassDeclarationsRecursive = concreteType.getSuperClassDeclarationsRecursive(); + allSuperClassDeclarations.addAll(superClassDeclarationsRecursive); + } + allSuperClassDeclarations.add(this); + return allSuperClassDeclarations; + } + + @Override + public Identifier getIdentifier() { + return declaration.getIdentifier(); + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + + if (o == null || getClass() != o.getClass()) return false; + + ConcreteType that = (ConcreteType) o; + + return new EqualsBuilder() + .append(declaration, that.declaration) + .append(concreteTypeParamters, that.concreteTypeParamters) + .isEquals(); + } + + @Override + public int hashCode() { + return new HashCodeBuilder(17, 37) + .append(declaration.getIdentifier()) + .append(1) + .append(concreteTypeParamters) + .toHashCode(); + } + + public List getVirtualMethods() { + List functions = new ArrayList<>(); + for (FunctionDeclaration functionDeclaration : declaration.getVirtualMethodTable()) { + functions.add(TypeFactory.makeConcrete(functionDeclaration, context)); + } + return functions; + } + + public ConcreteFunctionType getWrappedFunction() { + return TypeFactory.makeConcrete(declaration.getWrappedFunction(), context); + } + + public List getVariables() { + ArrayList result = new ArrayList<>(); + for (Declaration decl : declaration.getBlock().getDeclarations()) { + if (decl instanceof VariableDeclaration) { + result.add(TypeFactory.makeConcrete((VariableDeclaration) decl,context)); + } + } + return result; + } + + public boolean isGenerator() { + return declaration.isGenerator(); + } + + public ModuleDeclaration getModuleDeclaration() { + return declaration.getParentNodeByType(ModuleDeclaration.class); + } + + public List getConcreteGenericTypes() { + return concreteTypeParamters; + } + + public List getMethods() { + List functions = new ArrayList<>(); + + for (FunctionDeclaration declaration : declaration.getMethods()) { + functions.add(TypeFactory.makeConcrete(declaration, context)); + } + return functions; + } + + public static Iterable getAllTypes() { + return () -> new AllIterator(allTypes); + } + + public ASTNode getBlock() { + return declaration.getBlock(); + } + + public boolean hasWrappedFunction() { + return declaration.getWrappedFunction() != null; + } + + public static void reset() { + allTypes.clear(); + } + + public boolean isFunctionWrapper() { + return declaration.isFunctionWrapper(); + } + + public ConcreteFunctionType getDefaultInitializer() { + return (ConcreteFunctionType) super.getDefaultInitializer(); + } +} diff --git a/src/main/java/de/uni/bremen/monty/moco/ast/types/ConcreteVariableType.java b/src/main/java/de/uni/bremen/monty/moco/ast/types/ConcreteVariableType.java new file mode 100644 index 0000000..19404dd --- /dev/null +++ b/src/main/java/de/uni/bremen/monty/moco/ast/types/ConcreteVariableType.java @@ -0,0 +1,63 @@ +/* + * moco, the Monty Compiler + * Copyright (c) 2013-2014, Monty's Coconut, All rights reserved. + * + * This file is part of moco, the Monty Compiler. + * + * moco is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation; either + * version 3.0 of the License, or (at your option) any later version. + * + * moco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * Linking this program and/or its accompanying libraries statically or + * dynamically with other modules is making a combined work based on this + * program. Thus, the terms and conditions of the GNU General Public License + * cover the whole combination. + * + * As a special exception, the copyright holders of moco give + * you permission to link this programm and/or its accompanying libraries + * with independent modules to produce an executable, regardless of the + * license terms of these independent modules, and to copy and distribute the + * resulting executable under terms of your choice, provided that you also meet, + * for each linked independent module, the terms and conditions of the + * license of that module. + * + * An independent module is a module which is not + * derived from or based on this program and/or its accompanying libraries. + * If you modify this library, you may extend this exception to your version of + * the program or library, but you are not obliged to do so. If you do not wish + * to do so, delete this exception statement from your version. + * + * You should have received a copy of the GNU General Public + * License along with this library. + */ +package de.uni.bremen.monty.moco.ast.types; + +import de.uni.bremen.monty.moco.ast.declaration.VariableDeclaration; + +public class ConcreteVariableType extends VariableType { + private final TypeContext context; + + ConcreteVariableType(VariableDeclaration declaration, ConcreteType returnType, TypeContext context) { + super(declaration, returnType); + this.context = context; + } + + @Override + public ConcreteType getType() { + return (ConcreteType) super.getType(); + } + + public TypeContext getContext() { + return context; + } + + public VariableDeclaration getDeclaration() { + return declaration; + } +} diff --git a/src/main/java/de/uni/bremen/monty/moco/ast/types/FunctionType.java b/src/main/java/de/uni/bremen/monty/moco/ast/types/FunctionType.java new file mode 100644 index 0000000..c7159f0 --- /dev/null +++ b/src/main/java/de/uni/bremen/monty/moco/ast/types/FunctionType.java @@ -0,0 +1,84 @@ +/* + * moco, the Monty Compiler + * Copyright (c) 2013-2014, Monty's Coconut, All rights reserved. + * + * This file is part of moco, the Monty Compiler. + * + * moco is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation; either + * version 3.0 of the License, or (at your option) any later version. + * + * moco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * Linking this program and/or its accompanying libraries statically or + * dynamically with other modules is making a combined work based on this + * program. Thus, the terms and conditions of the GNU General Public License + * cover the whole combination. + * + * As a special exception, the copyright holders of moco give + * you permission to link this programm and/or its accompanying libraries + * with independent modules to produce an executable, regardless of the + * license terms of these independent modules, and to copy and distribute the + * resulting executable under terms of your choice, provided that you also meet, + * for each linked independent module, the terms and conditions of the + * license of that module. + * + * An independent module is a module which is not + * derived from or based on this program and/or its accompanying libraries. + * If you modify this library, you may extend this exception to your version of + * the program or library, but you are not obliged to do so. If you do not wish + * to do so, delete this exception statement from your version. + * + * You should have received a copy of the GNU General Public + * License along with this library. + */ +package de.uni.bremen.monty.moco.ast.types; + +import de.uni.bremen.monty.moco.ast.ASTNode; +import de.uni.bremen.monty.moco.ast.Identifier; +import de.uni.bremen.monty.moco.ast.declaration.FunctionDeclaration; + +import java.util.List; + +public interface FunctionType extends MemberType { + int getVMTIndex(); + + Identifier getIdentifier(); + + PartialAppliedTypeInfo getDefiningClass(); + + Type getReturnType(); + + boolean isFunction(); + + List getParameterTypes(); + + @Override + ASTNode getASTNode(); + + TypeContext getContext(); + + boolean isMethod(); + + boolean isInitializer(); + + boolean isClosure(); + + PartialAppliedTypeInfo getWrapperClass(); + + boolean isDefaultInitializer(); + + VariableType getWrapperFunctionObjectDeclaration(); + + List getClosureVariables(); + + FunctionDeclaration.DeclarationType getDeclarationType(); + + FunctionType extend(TypeContext context); + + String toString(); +} diff --git a/src/main/java/de/uni/bremen/monty/moco/ast/types/FunctionTypeDecl.java b/src/main/java/de/uni/bremen/monty/moco/ast/types/FunctionTypeDecl.java new file mode 100644 index 0000000..94341bc --- /dev/null +++ b/src/main/java/de/uni/bremen/monty/moco/ast/types/FunctionTypeDecl.java @@ -0,0 +1,164 @@ +/* + * moco, the Monty Compiler + * Copyright (c) 2013-2014, Monty's Coconut, All rights reserved. + * + * This file is part of moco, the Monty Compiler. + * + * moco is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation; either + * version 3.0 of the License, or (at your option) any later version. + * + * moco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * Linking this program and/or its accompanying libraries statically or + * dynamically with other modules is making a combined work based on this + * program. Thus, the terms and conditions of the GNU General Public License + * cover the whole combination. + * + * As a special exception, the copyright holders of moco give + * you permission to link this programm and/or its accompanying libraries + * with independent modules to produce an executable, regardless of the + * license terms of these independent modules, and to copy and distribute the + * resulting executable under terms of your choice, provided that you also meet, + * for each linked independent module, the terms and conditions of the + * license of that module. + * + * An independent module is a module which is not + * derived from or based on this program and/or its accompanying libraries. + * If you modify this library, you may extend this exception to your version of + * the program or library, but you are not obliged to do so. If you do not wish + * to do so, delete this exception statement from your version. + * + * You should have received a copy of the GNU General Public + * License along with this library. + */ +package de.uni.bremen.monty.moco.ast.types; + +import de.uni.bremen.monty.moco.ast.ASTNode; +import de.uni.bremen.monty.moco.ast.Identifier; +import de.uni.bremen.monty.moco.ast.declaration.FunctionDeclaration; + +import java.util.List; +import java.util.stream.Collectors; + +public class FunctionTypeDecl implements FunctionType { + protected final FunctionDeclaration declaration; + protected final TypeContext context; + protected final Type returnType; + protected final PartialAppliedTypeInfo definingClass; + protected final List parameter; + protected final PartialAppliedTypeInfo wrapperClass; + protected final VariableType wrapperFunctionObjects; + protected final List closureVariables; + + FunctionTypeDecl(FunctionDeclaration declaration, TypeContext context, List parameter, Type returnType, PartialAppliedTypeInfo definingClass, PartialAppliedTypeInfo wrapperClass, VariableType wrapperFunctionObjects, List closureVariables) { + this.declaration = declaration; + this.context = context; + this.parameter = parameter; + this.returnType = returnType; + this.definingClass = definingClass; + this.wrapperClass = wrapperClass; + this.wrapperFunctionObjects = wrapperFunctionObjects; + this.closureVariables = closureVariables; + } + + @Override + public int getVMTIndex() { + return declaration.getVMTIndex(); + } + + @Override + public Identifier getIdentifier() { + return declaration.getIdentifier(); + } + + @Override + public PartialAppliedTypeInfo getDefiningClass() { + return definingClass; + } + + @Override + public Type getReturnType() { + if(declaration.isReturnTypeToBeInferred()){ + return declaration.getReturnType().extend(context); + } + return returnType; + } + + @Override + public boolean isFunction() { + return declaration.isFunction(); + } + + public List getParameterTypes() { + return parameter.stream().map(VariableType::getType).collect(Collectors.toList()); + } + + public List getParameter() { + return parameter; + } + + @Override + public ASTNode getASTNode() { + return declaration; + } + + @Override + public TypeContext getContext() { + return context; + } + + @Override + public boolean isMethod() { + return declaration.isMethod(); + } + + @Override + public boolean isInitializer() { + return declaration.isInitializer(); + } + + @Override + public boolean isClosure() { + return declaration.isClosure(); + } + + @Override + public PartialAppliedTypeInfo getWrapperClass() { + return wrapperClass; + } + + @Override + public boolean isDefaultInitializer() { + return declaration.isDefaultInitializer(); + } + + @Override + public VariableType getWrapperFunctionObjectDeclaration() { + return wrapperFunctionObjects; + } + + @Override + public List getClosureVariables() { + return closureVariables; + } + + @Override + public FunctionDeclaration.DeclarationType getDeclarationType() { + return declaration.getDeclarationType(); + } + + @Override + public FunctionType extend(TypeContext context) { + return TypeFactory.from(declaration, this.context.extend(context)); + } + + @Override + public String toString() { + return declaration.toString(); + } +} diff --git a/src/main/java/de/uni/bremen/monty/moco/ast/types/FunctionTypeVariable.java b/src/main/java/de/uni/bremen/monty/moco/ast/types/FunctionTypeVariable.java new file mode 100644 index 0000000..983ef59 --- /dev/null +++ b/src/main/java/de/uni/bremen/monty/moco/ast/types/FunctionTypeVariable.java @@ -0,0 +1,169 @@ +/* + * moco, the Monty Compiler + * Copyright (c) 2013-2014, Monty's Coconut, All rights reserved. + * + * This file is part of moco, the Monty Compiler. + * + * moco is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation; either + * version 3.0 of the License, or (at your option) any later version. + * + * moco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * Linking this program and/or its accompanying libraries statically or + * dynamically with other modules is making a combined work based on this + * program. Thus, the terms and conditions of the GNU General Public License + * cover the whole combination. + * + * As a special exception, the copyright holders of moco give + * you permission to link this programm and/or its accompanying libraries + * with independent modules to produce an executable, regardless of the + * license terms of these independent modules, and to copy and distribute the + * resulting executable under terms of your choice, provided that you also meet, + * for each linked independent module, the terms and conditions of the + * license of that module. + * + * An independent module is a module which is not + * derived from or based on this program and/or its accompanying libraries. + * If you modify this library, you may extend this exception to your version of + * the program or library, but you are not obliged to do so. If you do not wish + * to do so, delete this exception statement from your version. + * + * You should have received a copy of the GNU General Public + * License along with this library. + */ +package de.uni.bremen.monty.moco.ast.types; + +import de.uni.bremen.monty.moco.ast.ASTNode; +import de.uni.bremen.monty.moco.ast.Identifier; +import de.uni.bremen.monty.moco.ast.declaration.FunctionDeclaration; +import de.uni.bremen.monty.moco.ast.declaration.VariableDeclaration; + +import java.util.Collections; +import java.util.List; + +public class FunctionTypeVariable implements ConcreteFunctionType { + private final List paramTypes; + private final ConcreteType returnType; + private VariableDeclaration declaration; + + FunctionTypeVariable(VariableDeclaration declaration) { + this.declaration = declaration; + if(!declaration.getType().isFunction()){ + throw new RuntimeException("Function Variable has to be a Function"); + } + List functionTypes = ((ConcreteType) declaration.getType()).getConcreteGenericTypes(); + + ConcreteType paramType = functionTypes.get(0); + if (paramType.isTuple()) { + paramTypes = paramType.getConcreteGenericTypes(); + } else { + paramTypes = Collections.singletonList(paramType); + } + + returnType = functionTypes.get(1); + + if(!(returnType instanceof ConcreteType && paramTypes.stream().allMatch( s -> s instanceof ConcreteType) )) { + throw new RuntimeException("Only concrete Function Variables are allowed"); + } + } + + @Override + public int getVMTIndex() { + throw new UnsupportedOperationException(); + } + + @Override + public Identifier getIdentifier() { + return declaration.getIdentifier(); + } + + @Override + public ConcreteType getDefiningClass() { + throw new UnsupportedOperationException(); + } + + @Override + public ConcreteType getReturnType() { + return returnType; + } + + @Override + public List getParameter() { + throw new UnsupportedOperationException(); + } + + @Override + public boolean isFunction() { + throw new UnsupportedOperationException(); + } + + @Override + public List getParameterTypes() { + return paramTypes; + } + + @Override + public ASTNode getASTNode() { + throw new UnsupportedOperationException(); + } + + @Override + public TypeContext getContext() { + throw new UnsupportedOperationException(); + } + + @Override + public boolean isMethod() { + throw new UnsupportedOperationException(); + } + + @Override + public boolean isInitializer() { + throw new UnsupportedOperationException(); + } + + @Override + public boolean isClosure() { + throw new UnsupportedOperationException(); + } + + @Override + public ConcreteType getWrapperClass() { + throw new UnsupportedOperationException(); + } + + @Override + public boolean isDefaultInitializer() { + throw new UnsupportedOperationException(); + } + + @Override + public ConcreteVariableType getWrapperFunctionObjectDeclaration() { + throw new UnsupportedOperationException(); + } + + @Override + public List getClosureVariables() { + throw new UnsupportedOperationException(); + } + + @Override + public FunctionDeclaration.DeclarationType getDeclarationType() { + throw new UnsupportedOperationException(); + } + + @Override + public FunctionType extend(TypeContext context) { + throw new UnsupportedOperationException(); + } + + @Override + public String toString() { + throw new UnsupportedOperationException(); + } +} diff --git a/src/main/java/de/uni/bremen/monty/moco/ast/types/GeneratorFunctionType.java b/src/main/java/de/uni/bremen/monty/moco/ast/types/GeneratorFunctionType.java new file mode 100644 index 0000000..24b9dc8 --- /dev/null +++ b/src/main/java/de/uni/bremen/monty/moco/ast/types/GeneratorFunctionType.java @@ -0,0 +1,49 @@ +/* + * moco, the Monty Compiler + * Copyright (c) 2013-2014, Monty's Coconut, All rights reserved. + * + * This file is part of moco, the Monty Compiler. + * + * moco is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation; either + * version 3.0 of the License, or (at your option) any later version. + * + * moco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * Linking this program and/or its accompanying libraries statically or + * dynamically with other modules is making a combined work based on this + * program. Thus, the terms and conditions of the GNU General Public License + * cover the whole combination. + * + * As a special exception, the copyright holders of moco give + * you permission to link this programm and/or its accompanying libraries + * with independent modules to produce an executable, regardless of the + * license terms of these independent modules, and to copy and distribute the + * resulting executable under terms of your choice, provided that you also meet, + * for each linked independent module, the terms and conditions of the + * license of that module. + * + * An independent module is a module which is not + * derived from or based on this program and/or its accompanying libraries. + * If you modify this library, you may extend this exception to your version of + * the program or library, but you are not obliged to do so. If you do not wish + * to do so, delete this exception statement from your version. + * + * You should have received a copy of the GNU General Public + * License along with this library. + */ +package de.uni.bremen.monty.moco.ast.types; + +import de.uni.bremen.monty.moco.ast.statement.YieldStatement; + +import java.util.List; + +public interface GeneratorFunctionType { + List getYieldStatements(); + + List getVariableDeclarations(); +} diff --git a/src/main/java/de/uni/bremen/monty/moco/ast/types/GeneratorFunctionTypeImpl.java b/src/main/java/de/uni/bremen/monty/moco/ast/types/GeneratorFunctionTypeImpl.java new file mode 100644 index 0000000..005edf5 --- /dev/null +++ b/src/main/java/de/uni/bremen/monty/moco/ast/types/GeneratorFunctionTypeImpl.java @@ -0,0 +1,66 @@ +/* + * moco, the Monty Compiler + * Copyright (c) 2013-2014, Monty's Coconut, All rights reserved. + * + * This file is part of moco, the Monty Compiler. + * + * moco is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation; either + * version 3.0 of the License, or (at your option) any later version. + * + * moco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * Linking this program and/or its accompanying libraries statically or + * dynamically with other modules is making a combined work based on this + * program. Thus, the terms and conditions of the GNU General Public License + * cover the whole combination. + * + * As a special exception, the copyright holders of moco give + * you permission to link this programm and/or its accompanying libraries + * with independent modules to produce an executable, regardless of the + * license terms of these independent modules, and to copy and distribute the + * resulting executable under terms of your choice, provided that you also meet, + * for each linked independent module, the terms and conditions of the + * license of that module. + * + * An independent module is a module which is not + * derived from or based on this program and/or its accompanying libraries. + * If you modify this library, you may extend this exception to your version of + * the program or library, but you are not obliged to do so. If you do not wish + * to do so, delete this exception statement from your version. + * + * You should have received a copy of the GNU General Public + * License along with this library. + */ +package de.uni.bremen.monty.moco.ast.types; + +import de.uni.bremen.monty.moco.ast.declaration.GeneratorFunctionDeclaration; +import de.uni.bremen.monty.moco.ast.statement.YieldStatement; + +import java.util.List; +import java.util.stream.Collectors; + +public class GeneratorFunctionTypeImpl extends FunctionTypeDecl implements GeneratorFunctionType { + + GeneratorFunctionTypeImpl(GeneratorFunctionDeclaration declaration, TypeContext context, List parameter, Type returnType, PartialAppliedTypeInfo definingClass, PartialAppliedTypeInfo wrapperClass, VariableType wrapperFunctionObjects, List closureVariables) { + super(declaration, context, parameter, returnType, definingClass, wrapperClass, wrapperFunctionObjects, closureVariables); + } + + private GeneratorFunctionDeclaration getDeclaration(){ + return (GeneratorFunctionDeclaration) super.declaration; + } + + @Override + public List getYieldStatements() { + return getDeclaration().getYieldStatements(); + } + + @Override + public List getVariableDeclarations() { + return getDeclaration().getVariableDeclarations().stream().map(d -> TypeFactory.from(d, context)).collect(Collectors.toList()); + } +} diff --git a/src/main/java/de/uni/bremen/monty/moco/ast/types/MemberType.java b/src/main/java/de/uni/bremen/monty/moco/ast/types/MemberType.java new file mode 100644 index 0000000..978d819 --- /dev/null +++ b/src/main/java/de/uni/bremen/monty/moco/ast/types/MemberType.java @@ -0,0 +1,45 @@ +/* + * moco, the Monty Compiler + * Copyright (c) 2013-2014, Monty's Coconut, All rights reserved. + * + * This file is part of moco, the Monty Compiler. + * + * moco is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation; either + * version 3.0 of the License, or (at your option) any later version. + * + * moco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * Linking this program and/or its accompanying libraries statically or + * dynamically with other modules is making a combined work based on this + * program. Thus, the terms and conditions of the GNU General Public License + * cover the whole combination. + * + * As a special exception, the copyright holders of moco give + * you permission to link this programm and/or its accompanying libraries + * with independent modules to produce an executable, regardless of the + * license terms of these independent modules, and to copy and distribute the + * resulting executable under terms of your choice, provided that you also meet, + * for each linked independent module, the terms and conditions of the + * license of that module. + * + * An independent module is a module which is not + * derived from or based on this program and/or its accompanying libraries. + * If you modify this library, you may extend this exception to your version of + * the program or library, but you are not obliged to do so. If you do not wish + * to do so, delete this exception statement from your version. + * + * You should have received a copy of the GNU General Public + * License along with this library. + */ +package de.uni.bremen.monty.moco.ast.types; + +import de.uni.bremen.monty.moco.ast.ASTNode; + +public interface MemberType { + ASTNode getASTNode(); +} diff --git a/src/main/java/de/uni/bremen/monty/moco/ast/types/PartialAppliedTypeInfo.java b/src/main/java/de/uni/bremen/monty/moco/ast/types/PartialAppliedTypeInfo.java new file mode 100644 index 0000000..780c404 --- /dev/null +++ b/src/main/java/de/uni/bremen/monty/moco/ast/types/PartialAppliedTypeInfo.java @@ -0,0 +1,220 @@ +/* + * moco, the Monty Compiler + * Copyright (c) 2013-2014, Monty's Coconut, All rights reserved. + * + * This file is part of moco, the Monty Compiler. + * + * moco is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation; either + * version 3.0 of the License, or (at your option) any later version. + * + * moco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * Linking this program and/or its accompanying libraries statically or + * dynamically with other modules is making a combined work based on this + * program. Thus, the terms and conditions of the GNU General Public License + * cover the whole combination. + * + * As a special exception, the copyright holders of moco give + * you permission to link this programm and/or its accompanying libraries + * with independent modules to produce an executable, regardless of the + * license terms of these independent modules, and to copy and distribute the + * resulting executable under terms of your choice, provided that you also meet, + * for each linked independent module, the terms and conditions of the + * license of that module. + * + * An independent module is a module which is not + * derived from or based on this program and/or its accompanying libraries. + * If you modify this library, you may extend this exception to your version of + * the program or library, but you are not obliged to do so. If you do not wish + * to do so, delete this exception statement from your version. + * + * You should have received a copy of the GNU General Public + * License along with this library. + */ +package de.uni.bremen.monty.moco.ast.types; + +import de.uni.bremen.monty.moco.ast.ClassScope; +import de.uni.bremen.monty.moco.ast.Identifier; +import de.uni.bremen.monty.moco.ast.ResolvableIdentifier; +import de.uni.bremen.monty.moco.ast.declaration.ClassDeclaration; +import de.uni.bremen.monty.moco.ast.declaration.FunctionDeclaration; +import de.uni.bremen.monty.moco.visitor.VisitOnceVisitor; + +import java.util.ArrayList; +import java.util.List; +import java.util.stream.Collectors; + +public class PartialAppliedTypeInfo extends Type { + + protected final ClassDeclaration declaration; + private final List partialAppliedTypes; + protected final TypeContext context; + + PartialAppliedTypeInfo(ClassDeclaration declaration, List partialAppliedTypes, TypeContext context) { + this.declaration = declaration; + this.partialAppliedTypes = partialAppliedTypes; + this.context = TypeContext.from(declaration, partialAppliedTypes).extend(context); + } + + @Override + public boolean matchesTypeExactly(Type type) { + if(type instanceof PartialAppliedTypeInfo){ + PartialAppliedTypeInfo other = (PartialAppliedTypeInfo) type; + if (other.declaration.equals(this.declaration)) { + for (int i = 0; i < partialAppliedTypes.size(); i++) { + Type partialAppliedType = partialAppliedTypes.get(i); + Type typeVariable = other.partialAppliedTypes.get(i); + if(typeVariable instanceof TypeVariable){ + continue; + } + if(!partialAppliedType.matchesTypeExactly(typeVariable)){ + return false; + } + } + return true; + } else if (matchesVoidAndTuple0(this, other) || matchesVoidAndTuple0(other, this)) { + return true; + } + } +// else { +//// context.makeConcrete() +//// TypeVariable typeVariable = (TypeVariable) type; +//// typeVariable.turnConcrete(this) +//// turnConcrete(typeVariable) +// return false; +// } + return false; + } + + private static boolean matchesVoidAndTuple0(PartialAppliedTypeInfo type, PartialAppliedTypeInfo other) { + return type.isVoid() && other.isTuple(0); + } + + @Override + public Identifier getIdentifier() { + return declaration.getIdentifier(); + } + + public ClassScope getScope() { + return declaration.getScope().extend(context); + } + + public int getLastAttributeIndex() { + return declaration.getLastAttributeIndex(); + } + + public List getVirtualMethodTable() { + return declaration.getVirtualMethodTable(); + } + + public List getSuperClassDeclarations() { + return declaration.getSuperClassDeclarations(); + } + + @Override + public boolean isAssignableFrom(Type other) { + if (matchesTypeExactly(other)) { + return true; + } + if ((other instanceof PartialAppliedTypeInfo)) { + PartialAppliedTypeInfo otherType = (PartialAppliedTypeInfo) other; + boolean superMatch = declaration.getSuperClassDeclarations().stream().anyMatch(e -> e.declaration == otherType.declaration); + return superMatch; + } + return false; + } + + @Override + protected boolean matchesDeclaration(ClassDeclaration declaration) { + return this.declaration.equals(declaration); + } + + public TypeContext getContext() { + return context; + } + +// ConcreteTypeInfo turnConcrete(TypeContext context) { +// ArrayList concreteTypeParamters = new ArrayList<>(); +// for (Type partialAppliedType : partialAppliedTypes) { +// concreteTypeParamters.add(context.makeConcrete(partialAppliedType)); +// } +// return new ConcreteTypeInfo(declaration, concreteTypeParamters); +// } + + public Type extend(TypeContext context) { + return TypeFactory.from(declaration, this.context.extend(context)); + } + + public String toString() { + Object genericTypes = partialAppliedTypes.isEmpty() ? "" : partialAppliedTypes; + return getIdentifier().getSymbol() + genericTypes; + } + + public boolean isTuple(int n) { + return isTuple() && partialAppliedTypes.size() == n; + } + + public boolean isTuple() { + String strIdent = getIdentifier().getSymbol(); + if (strIdent.startsWith("Tuple")) { + int n; + try { + n = Integer.parseInt(strIdent.substring(5)); + } catch (Exception e) { + return false; + } + if (partialAppliedTypes.size() == n) { + return true; + } + } + return false; + } + + @Override + public boolean isFunction() { + return isAssignableFrom(Types.functionType()); + } + + public List getPartialAppliedTypes() { + return partialAppliedTypes; + } + + public boolean isAbstract() { + return declaration.isAbstract(); + } + + public FunctionType getDefaultInitializer() { + return TypeFactory.from(declaration.getDefaultInitializer(), context); + } + + public List getInitializers(VisitOnceVisitor visitor) { + List functions = new ArrayList<>(); + + // iterate through the declarations of the given class + for (FunctionDeclaration declaration : declaration.getMethods()) { + // find a matching declaration + if ("initializer".equals(declaration.getIdentifier().getSymbol())) { + // and verify that it is a function... + // without any return type + if (!(declaration.isFunction())) { + visitor.visitDoubleDispatched(declaration); + functions.add(TypeFactory.from(declaration, context)); + } + } + } + return functions; + } + + public void visit(VisitOnceVisitor visitor) { + visitor.visitDoubleDispatched(declaration); + } + + public ResolvableIdentifier getResolvableIdentifier() { + return new ResolvableIdentifier(declaration.getIdentifier().getSymbol(), partialAppliedTypes.stream().map(r -> r.getResolvableIdentifier()).collect(Collectors.toList())); + } +} diff --git a/src/main/java/de/uni/bremen/monty/moco/ast/types/Type.java b/src/main/java/de/uni/bremen/monty/moco/ast/types/Type.java new file mode 100644 index 0000000..c0dab5e --- /dev/null +++ b/src/main/java/de/uni/bremen/monty/moco/ast/types/Type.java @@ -0,0 +1,124 @@ +/* + * moco, the Monty Compiler + * Copyright (c) 2013-2014, Monty's Coconut, All rights reserved. + * + * This file is part of moco, the Monty Compiler. + * + * moco is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation; either + * version 3.0 of the License, or (at your option) any later version. + * + * moco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * Linking this program and/or its accompanying libraries statically or + * dynamically with other modules is making a combined work based on this + * program. Thus, the terms and conditions of the GNU General Public License + * cover the whole combination. + * + * As a special exception, the copyright holders of moco give + * you permission to link this programm and/or its accompanying libraries + * with independent modules to produce an executable, regardless of the + * license terms of these independent modules, and to copy and distribute the + * resulting executable under terms of your choice, provided that you also meet, + * for each linked independent module, the terms and conditions of the + * license of that module. + * + * An independent module is a module which is not + * derived from or based on this program and/or its accompanying libraries. + * If you modify this library, you may extend this exception to your version of + * the program or library, but you are not obliged to do so. If you do not wish + * to do so, delete this exception statement from your version. + * + * You should have received a copy of the GNU General Public + * License along with this library. + */ +package de.uni.bremen.monty.moco.ast.types; + +import de.uni.bremen.monty.moco.ast.CoreClasses; +import de.uni.bremen.monty.moco.ast.Identifier; +import de.uni.bremen.monty.moco.ast.ResolvableIdentifier; +import de.uni.bremen.monty.moco.ast.Scope; +import de.uni.bremen.monty.moco.ast.declaration.ClassDeclaration; + +/** + * Is a Class or a TypeVariable or something between. + * Not FunctionDecl or Mudule + */ +public abstract class Type { + + public abstract boolean isAssignableFrom(Type other); + + public boolean isVoid() { + return this.matchesDeclaration(CoreClasses.voidType()); + } + + protected abstract boolean matchesDeclaration(ClassDeclaration declaration); + + public abstract boolean matchesTypeExactly(Type type); + + public abstract Identifier getIdentifier(); + + /** Calculates the distance of this and other in the inheritance graph. Only calculates positive distances, i.e. if + * this is a parameter and other is an argument, other must be equal to or a subtype of this. otherwise the result + * will be Integer.MAX_VALUE. + * + * @param other + * @return a distance 0 <= dist <= Integer.MAX_VALUE */ + public int getTypeDist(Type other) { + return getTypeDist(other, 0); + } + + /** a helper method for "public int getTypeDist(TypeDeclaration other)" + * + * @param other + * @param dist + * @return */ + protected int getTypeDist(Type other, int dist) { + if (dist == Integer.MAX_VALUE) { + return dist; + } + if (matchesTypeExactly(other)) { + return dist; + } else if ((other instanceof PartialAppliedTypeInfo) + && (!((PartialAppliedTypeInfo) other).getSuperClassDeclarations().isEmpty())) { + int parentDist = Integer.MAX_VALUE; + for (Type superClass : ((PartialAppliedTypeInfo) other).getSuperClassDeclarations()) { + int superDist = getTypeDist(superClass, dist + 1); + if (superDist < parentDist) { + parentDist = superDist; + } + } + return parentDist; + } else if (other instanceof TypeVariable) { + return getTypeDist(((TypeVariable) other).getUpperTypeBound()); + } + return Integer.MAX_VALUE; + } + + @Override + public boolean equals(Object o) { + throw new UnsupportedOperationException(); + } + + @Override + public int hashCode() { + throw new UnsupportedOperationException(); + } + + public abstract Scope getScope(); + + public abstract Type extend(TypeContext context); +// abstract ConcreteTypeInfo turnConcrete(TypeContext context); + + public abstract boolean isTuple(int n); + + public abstract boolean isTuple(); + + public abstract boolean isFunction(); + + public abstract ResolvableIdentifier getResolvableIdentifier(); +} diff --git a/src/main/java/de/uni/bremen/monty/moco/ast/types/TypeContext.java b/src/main/java/de/uni/bremen/monty/moco/ast/types/TypeContext.java new file mode 100644 index 0000000..e7bc271 --- /dev/null +++ b/src/main/java/de/uni/bremen/monty/moco/ast/types/TypeContext.java @@ -0,0 +1,86 @@ +/* + * moco, the Monty Compiler + * Copyright (c) 2013-2014, Monty's Coconut, All rights reserved. + * + * This file is part of moco, the Monty Compiler. + * + * moco is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation; either + * version 3.0 of the License, or (at your option) any later version. + * + * moco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * Linking this program and/or its accompanying libraries statically or + * dynamically with other modules is making a combined work based on this + * program. Thus, the terms and conditions of the GNU General Public License + * cover the whole combination. + * + * As a special exception, the copyright holders of moco give + * you permission to link this programm and/or its accompanying libraries + * with independent modules to produce an executable, regardless of the + * license terms of these independent modules, and to copy and distribute the + * resulting executable under terms of your choice, provided that you also meet, + * for each linked independent module, the terms and conditions of the + * license of that module. + * + * An independent module is a module which is not + * derived from or based on this program and/or its accompanying libraries. + * If you modify this library, you may extend this exception to your version of + * the program or library, but you are not obliged to do so. If you do not wish + * to do so, delete this exception statement from your version. + * + * You should have received a copy of the GNU General Public + * License along with this library. + */ +package de.uni.bremen.monty.moco.ast.types; + +import de.uni.bremen.monty.moco.ast.declaration.TypeParameterDeclaration; +import de.uni.bremen.monty.moco.ast.declaration.ClassDeclaration; +import de.uni.bremen.monty.moco.exception.InvalidTypeException; + +import java.util.List; + +public abstract class TypeContext { + public static TypeContext EMPTY = new TypeContext() { + @Override + public TypeContext extend(TypeContext context) { + return context; + } + + @Override + public Type resolve(Type type) { + return type; + } + + @Override + public Type resolve(TypeParameterDeclaration typeVariable) { + return new TypeVariable(typeVariable); + } + + @Override + protected Type tryToResolve(TypeParameterDeclaration typeVariable) { + return null; + } + }; + + public abstract TypeContext extend(TypeContext context); + public abstract Type resolve(Type type); + public abstract Type resolve(TypeParameterDeclaration typeVariable); + protected abstract Type tryToResolve(TypeParameterDeclaration typeVariable); + + public ConcreteType makeConcrete(Type type) { + return (ConcreteType) resolve(type); + } + + public static TypeContext from(ClassDeclaration declaration, List partialAppliedTypes) { + int declsize = declaration.getTypeParameterDeclarations().size(); + if(declsize != partialAppliedTypes.size()){ + throw new InvalidTypeException(String.format("The class %s has %d Typeparameters but only %d were provided", declaration.getIdentifier(), declsize, partialAppliedTypes.size())); + } + return new TypeContextImpl(declaration, partialAppliedTypes); + } +} diff --git a/src/main/java/de/uni/bremen/monty/moco/ast/types/TypeContextImpl.java b/src/main/java/de/uni/bremen/monty/moco/ast/types/TypeContextImpl.java new file mode 100644 index 0000000..107abce --- /dev/null +++ b/src/main/java/de/uni/bremen/monty/moco/ast/types/TypeContextImpl.java @@ -0,0 +1,160 @@ +/* + * moco, the Monty Compiler + * Copyright (c) 2013-2014, Monty's Coconut, All rights reserved. + * + * This file is part of moco, the Monty Compiler. + * + * moco is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation; either + * version 3.0 of the License, or (at your option) any later version. + * + * moco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * Linking this program and/or its accompanying libraries statically or + * dynamically with other modules is making a combined work based on this + * program. Thus, the terms and conditions of the GNU General Public License + * cover the whole combination. + * + * As a special exception, the copyright holders of moco give + * you permission to link this programm and/or its accompanying libraries + * with independent modules to produce an executable, regardless of the + * license terms of these independent modules, and to copy and distribute the + * resulting executable under terms of your choice, provided that you also meet, + * for each linked independent module, the terms and conditions of the + * license of that module. + * + * An independent module is a module which is not + * derived from or based on this program and/or its accompanying libraries. + * If you modify this library, you may extend this exception to your version of + * the program or library, but you are not obliged to do so. If you do not wish + * to do so, delete this exception statement from your version. + * + * You should have received a copy of the GNU General Public + * License along with this library. + */ +package de.uni.bremen.monty.moco.ast.types; + +import de.uni.bremen.monty.moco.ast.CoreClasses; +import de.uni.bremen.monty.moco.ast.declaration.TypeParameterDeclaration; +import de.uni.bremen.monty.moco.ast.declaration.ClassDeclaration; + +import java.util.*; +import java.util.stream.Collectors; + + +public class TypeContextImpl extends TypeContext { + + private ClassDeclaration declaration; + private final List appliedTypes; + private final TypeContext parent; + + protected TypeContextImpl(ClassDeclaration declaration, List appliedTypes) { + this.declaration = declaration; + this.appliedTypes = appliedTypes; + parent = EMPTY; + } + + protected TypeContextImpl(ClassDeclaration declaration, List appliedTypes, TypeContext parent) { + this.declaration = declaration; + this.appliedTypes = appliedTypes; + this.parent = parent; + } + + private List superContext() { + return declaration.getSuperClassDeclarations().stream().map( s -> s.context).collect(Collectors.toList()); + } + + @Override + public TypeContext extend(TypeContext context) { + return new TypeContextImpl(declaration, appliedTypes, context); + } + + @Override + public Type resolve(Type type) { + if(type instanceof TypeVariable) { + return resolve(((TypeVariable) type).declaration); + } else { + return type.extend(this); + } + } + + @Override + public Type resolve(TypeParameterDeclaration typeVariable) { + Type type = tryToResolve(typeVariable); + if(type == null){ + return new TypeVariable(typeVariable); + } + return type; + } + + @Override + protected Type tryToResolve(TypeParameterDeclaration typeVariable) { + Type type = resolveOwnTypes(typeVariable); + if (type != null) { + return type; + } + type = resolveClassParentTypes(typeVariable); + if (type != null) return type; + + type = resolveParentTypes(typeVariable); + if (type != null) return type; + + return null; + } + + private Type resolveFunctionTypes(TypeContext typeContext, TypeParameterDeclaration typeVariable) { + if(typeContext instanceof TypeContextImpl && ((TypeContextImpl) typeContext).declaration.equals(CoreClasses.functionType())){ + Type tuple = ((TypeContextImpl) typeContext).appliedTypes.get(0); + if (tuple instanceof PartialAppliedTypeInfo){ + PartialAppliedTypeInfo concreteTuple = (ConcreteType) tuple; + return concreteTuple.context.tryToResolve(typeVariable); + } + } + return null; + } + + private Type resolveParentTypes(TypeParameterDeclaration typeVariable) { + return parent.tryToResolve(typeVariable); + } + + private Type resolveClassParentTypes(TypeParameterDeclaration typeVariable) { + Type type; + for (TypeContext typeContext : superContext()) { + type = typeContext.tryToResolve(typeVariable); + if(type != null) { + return type; + } + type = resolveFunctionTypes(typeContext, typeVariable); + if (type != null) { + return type; + } + } + return null; + } + + private Type resolveOwnTypes(TypeParameterDeclaration typeVariable) { + Type type = mappings().get(typeVariable); + if(type instanceof TypeVariable) { + Type otherType = tryToResolve(((TypeVariable) type).declaration); + return otherType != null ? otherType : type; + } + return type; + } + + private HashMap mappings() { + HashMap map = new HashMap<>(); + List typeParameterDeclarations = declaration.getTypeParameterDeclarations(); + for (int i = 0; i < typeParameterDeclarations.size(); i++) { + TypeParameterDeclaration key = typeParameterDeclarations.get(i); + Type value = appliedTypes.get(i); + if (!(value instanceof TypeVariable && ((TypeVariable) value).declaration.equals(key))) { + map.put(key, value); + } + } + return map; + } +} diff --git a/src/main/java/de/uni/bremen/monty/moco/ast/types/TypeFactory.java b/src/main/java/de/uni/bremen/monty/moco/ast/types/TypeFactory.java new file mode 100644 index 0000000..3210f8f --- /dev/null +++ b/src/main/java/de/uni/bremen/monty/moco/ast/types/TypeFactory.java @@ -0,0 +1,130 @@ +/* + * moco, the Monty Compiler + * Copyright (c) 2013-2014, Monty's Coconut, All rights reserved. + * + * This file is part of moco, the Monty Compiler. + * + * moco is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation; either + * version 3.0 of the License, or (at your option) any later version. + * + * moco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * Linking this program and/or its accompanying libraries statically or + * dynamically with other modules is making a combined work based on this + * program. Thus, the terms and conditions of the GNU General Public License + * cover the whole combination. + * + * As a special exception, the copyright holders of moco give + * you permission to link this programm and/or its accompanying libraries + * with independent modules to produce an executable, regardless of the + * license terms of these independent modules, and to copy and distribute the + * resulting executable under terms of your choice, provided that you also meet, + * for each linked independent module, the terms and conditions of the + * license of that module. + * + * An independent module is a module which is not + * derived from or based on this program and/or its accompanying libraries. + * If you modify this library, you may extend this exception to your version of + * the program or library, but you are not obliged to do so. If you do not wish + * to do so, delete this exception statement from your version. + * + * You should have received a copy of the GNU General Public + * License along with this library. + */ +package de.uni.bremen.monty.moco.ast.types; + +import de.uni.bremen.monty.moco.ast.declaration.*; + +import java.util.ArrayList; +import java.util.List; +import java.util.stream.Collectors; + +public class TypeFactory { + + public static PartialAppliedTypeInfo from(ClassDeclaration declaration, TypeContext context){ + List types = new ArrayList<>(); + boolean concrete = true; + for (TypeParameterDeclaration typeParameterDeclaration : declaration.getTypeParameterDeclarations()) { + Type type = context.resolve(typeParameterDeclaration); + types.add(type); + if(!(type instanceof ConcreteType)) { + concrete = false; + } + } + if(concrete){ + return new ConcreteType(declaration, (List) types, context); + } + return new PartialAppliedTypeInfo(declaration, types, context); + } + + public static VariableType from(VariableDeclaration declaration, TypeContext context) { + Type type = declaration.getType(); + Type returnType = context.resolve(type); + if (returnType instanceof ConcreteType) { + return new ConcreteVariableType(declaration, (ConcreteType) returnType, context); + } + return new VariableType(declaration, returnType); + } + + public static FunctionType from(FunctionDeclaration declaration, TypeContext context){ + Type type = declaration.getReturnType(); + Type returnType = context.resolve(type); + + List parameter = declaration.getParameters().stream().map(p -> from(p, context)).collect(Collectors.toList()); + List closureVariables = declaration.getClosureVariables().stream().map(d -> from(d, context)).collect(Collectors.toList()); + PartialAppliedTypeInfo wrapperClass; + VariableType wrapperObject; + PartialAppliedTypeInfo definingClass; + boolean isUnbound = declaration.getDeclarationType() == FunctionDeclaration.DeclarationType.UNBOUND; + if(isUnbound){ + definingClass = null; + } else { + definingClass = from(declaration.getDefiningClass(), context); + } + if (declaration.getWrapperClass() != null) { + wrapperClass = from(declaration.getWrapperClass(), context); + wrapperObject = TypeFactory.from(declaration.getWrapperFunctionObjectDeclaration(), context); + } else { + wrapperClass = null; + wrapperObject = null; + } + + if((!declaration.isReturnTypeToBeInferred() || declaration.getReturnType()!=null) && returnType instanceof ConcreteType && parameter.stream().allMatch(t -> t instanceof ConcreteVariableType) && (isUnbound || definingClass instanceof ConcreteType)) { + if(declaration instanceof GeneratorFunctionDeclaration){ + return new ConcreteGeneratorFunctionType((GeneratorFunctionDeclaration) declaration, context, (List) parameter, (ConcreteType)returnType,(ConcreteType) definingClass, (ConcreteType) wrapperClass, (ConcreteVariableType) wrapperObject, (List) closureVariables); + } + return new ConcreteFunctionTypeDecl(declaration, context, (List) parameter, (ConcreteType)returnType, (ConcreteType) definingClass, (ConcreteType) wrapperClass, (ConcreteVariableType) wrapperObject, (List) closureVariables); + } + if(declaration instanceof GeneratorFunctionDeclaration){ + return new GeneratorFunctionTypeImpl((GeneratorFunctionDeclaration) declaration, context, parameter, returnType, definingClass, wrapperClass, wrapperObject, closureVariables); + } + return new FunctionTypeDecl(declaration, context, parameter, returnType, definingClass, wrapperClass, wrapperObject, closureVariables); + } + + public static ConcreteType makeConcrete(ClassDeclaration declaration, TypeContext context) { + return (ConcreteType) from(declaration, context); + } + + public static ConcreteFunctionType makeConcrete(FunctionDeclaration declaration, TypeContext context) { + FunctionType from = from(declaration, context); + return (ConcreteFunctionType) from; + } + + public static ConcreteFunctionType makeConcrete(FunctionType declaration, TypeContext context) { + FunctionType extend = declaration.extend(context); + return (ConcreteFunctionType) extend; + } + + public static ConcreteVariableType makeConcrete(VariableDeclaration declaration, TypeContext context) { + return (ConcreteVariableType) from(declaration, context); + } + + public static FunctionType createFunction(VariableDeclaration declaration) { + return new FunctionTypeVariable(declaration); + } +} diff --git a/src/main/java/de/uni/bremen/monty/moco/ast/types/TypeVariable.java b/src/main/java/de/uni/bremen/monty/moco/ast/types/TypeVariable.java new file mode 100644 index 0000000..2833621 --- /dev/null +++ b/src/main/java/de/uni/bremen/monty/moco/ast/types/TypeVariable.java @@ -0,0 +1,135 @@ +/* + * moco, the Monty Compiler + * Copyright (c) 2013-2014, Monty's Coconut, All rights reserved. + * + * This file is part of moco, the Monty Compiler. + * + * moco is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation; either + * version 3.0 of the License, or (at your option) any later version. + * + * moco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * Linking this program and/or its accompanying libraries statically or + * dynamically with other modules is making a combined work based on this + * program. Thus, the terms and conditions of the GNU General Public License + * cover the whole combination. + * + * As a special exception, the copyright holders of moco give + * you permission to link this programm and/or its accompanying libraries + * with independent modules to produce an executable, regardless of the + * license terms of these independent modules, and to copy and distribute the + * resulting executable under terms of your choice, provided that you also meet, + * for each linked independent module, the terms and conditions of the + * license of that module. + * + * An independent module is a module which is not + * derived from or based on this program and/or its accompanying libraries. + * If you modify this library, you may extend this exception to your version of + * the program or library, but you are not obliged to do so. If you do not wish + * to do so, delete this exception statement from your version. + * + * You should have received a copy of the GNU General Public + * License along with this library. + */ +package de.uni.bremen.monty.moco.ast.types; + +import de.uni.bremen.monty.moco.ast.Identifier; +import de.uni.bremen.monty.moco.ast.ResolvableIdentifier; +import de.uni.bremen.monty.moco.ast.Scope; +import de.uni.bremen.monty.moco.ast.declaration.TypeParameterDeclaration; +import de.uni.bremen.monty.moco.ast.declaration.ClassDeclaration; + +public class TypeVariable extends Type { + + TypeParameterDeclaration declaration; + + public TypeVariable(TypeParameterDeclaration declaration) { + this.declaration = declaration; + } + + @Override + public boolean isAssignableFrom(Type other) { + if(other instanceof TypeVariable){ + return this.declaration.equals(((TypeVariable) other).declaration); + } + return declaration.getUpperTypeBound().isAssignableFrom(other); + } + + @Override + protected boolean matchesDeclaration(ClassDeclaration declaration) { + return false; + } + + @Override + public boolean matchesTypeExactly(Type type) { + if (type instanceof TypeVariable) { + if (((TypeVariable) type).declaration.equals(declaration)) { + return true; + } + } + return false; + } + + @Override + public Identifier getIdentifier() { + return declaration.getIdentifier(); + } + + @Override + public Scope getScope() { + return declaration.getUpperTypeBound().getScope(); + } + + public Type extend(TypeContext context) { + return context.resolve(this); + } + + @Override + public boolean isTuple(int n) { + return false; + } + + @Override + public boolean isTuple() { + return false; + } + + @Override + public boolean isFunction() { + return false; + } + + public Type getUpperTypeBound() { + return declaration.getUpperTypeBound(); + } + + @Override + public int getTypeDist(Type other) { + if(other instanceof TypeVariable){ + if(this.declaration == ((TypeVariable) other).declaration){ + return 0; + } + return Integer.MAX_VALUE; + } + throw new RuntimeException(); + } + + @Override + protected int getTypeDist(Type other, int dist) { + throw new RuntimeException(); + } + + @Override + public String toString() { + return declaration.getIdentifier().getSymbol(); + } + + public ResolvableIdentifier getResolvableIdentifier() { + return new ResolvableIdentifier(declaration.getIdentifier().getSymbol()); + } +} diff --git a/src/main/java/de/uni/bremen/monty/moco/ast/types/Types.java b/src/main/java/de/uni/bremen/monty/moco/ast/types/Types.java new file mode 100644 index 0000000..e0cd5b6 --- /dev/null +++ b/src/main/java/de/uni/bremen/monty/moco/ast/types/Types.java @@ -0,0 +1,89 @@ +/* + * moco, the Monty Compiler + * Copyright (c) 2013-2014, Monty's Coconut, All rights reserved. + * + * This file is part of moco, the Monty Compiler. + * + * moco is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation; either + * version 3.0 of the License, or (at your option) any later version. + * + * moco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * Linking this program and/or its accompanying libraries statically or + * dynamically with other modules is making a combined work based on this + * program. Thus, the terms and conditions of the GNU General Public License + * cover the whole combination. + * + * As a special exception, the copyright holders of moco give + * you permission to link this programm and/or its accompanying libraries + * with independent modules to produce an executable, regardless of the + * license terms of these independent modules, and to copy and distribute the + * resulting executable under terms of your choice, provided that you also meet, + * for each linked independent module, the terms and conditions of the + * license of that module. + * + * An independent module is a module which is not + * derived from or based on this program and/or its accompanying libraries. + * If you modify this library, you may extend this exception to your version of + * the program or library, but you are not obliged to do so. If you do not wish + * to do so, delete this exception statement from your version. + * + * You should have received a copy of the GNU General Public + * License along with this library. + */ +package de.uni.bremen.monty.moco.ast.types; + +import de.uni.bremen.monty.moco.ast.CoreClasses; +import de.uni.bremen.monty.moco.ast.declaration.ClassDeclaration; + +import java.util.Collections; + +public class Types { + + public static PartialAppliedTypeInfo functionType() { + return TypeFactory.from(CoreClasses.functionType(), TypeContext.EMPTY); + }; + + public static ConcreteType create(ClassDeclaration declaration) { + return new ConcreteType(declaration, Collections.emptyList(), TypeContext.EMPTY); + } + + public static ConcreteType intType() { + ClassDeclaration declaration = CoreClasses.intType(); + return create(declaration); + } + + public static ConcreteType boolType() { + return create(CoreClasses.boolType()); + } + + public static ConcreteType floatType() { + return create(CoreClasses.floatType()); + } + + public static ConcreteType charType() { + return create(CoreClasses.charType()); + } + + public static ConcreteType stringType() { + return create(CoreClasses.stringType()); + } + + public static ConcreteType arrayType() { + return create(CoreClasses.arrayType()); + } + + public static ConcreteType objectType() { + return create(CoreClasses.objectType()); + } + + public static ConcreteType voidType() { + return create(CoreClasses.voidType()); + } + +} diff --git a/src/main/java/de/uni/bremen/monty/moco/ast/types/VariableType.java b/src/main/java/de/uni/bremen/monty/moco/ast/types/VariableType.java new file mode 100644 index 0000000..dbcfb1f --- /dev/null +++ b/src/main/java/de/uni/bremen/monty/moco/ast/types/VariableType.java @@ -0,0 +1,75 @@ +/* + * moco, the Monty Compiler + * Copyright (c) 2013-2014, Monty's Coconut, All rights reserved. + * + * This file is part of moco, the Monty Compiler. + * + * moco is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation; either + * version 3.0 of the License, or (at your option) any later version. + * + * moco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * Linking this program and/or its accompanying libraries statically or + * dynamically with other modules is making a combined work based on this + * program. Thus, the terms and conditions of the GNU General Public License + * cover the whole combination. + * + * As a special exception, the copyright holders of moco give + * you permission to link this programm and/or its accompanying libraries + * with independent modules to produce an executable, regardless of the + * license terms of these independent modules, and to copy and distribute the + * resulting executable under terms of your choice, provided that you also meet, + * for each linked independent module, the terms and conditions of the + * license of that module. + * + * An independent module is a module which is not + * derived from or based on this program and/or its accompanying libraries. + * If you modify this library, you may extend this exception to your version of + * the program or library, but you are not obliged to do so. If you do not wish + * to do so, delete this exception statement from your version. + * + * You should have received a copy of the GNU General Public + * License along with this library. + */ +package de.uni.bremen.monty.moco.ast.types; + +import de.uni.bremen.monty.moco.ast.ASTNode; +import de.uni.bremen.monty.moco.ast.Identifier; +import de.uni.bremen.monty.moco.ast.ResolvableIdentifier; +import de.uni.bremen.monty.moco.ast.declaration.VariableDeclaration; + +public class VariableType implements MemberType { + protected final VariableDeclaration declaration; + private final Type returnType; + + VariableType(VariableDeclaration declaration, Type returnType) { + this.declaration = declaration; + this.returnType = returnType; + } + + public Identifier getIdentifier() { + return declaration.getIdentifier(); + } + + public Type getType() { + return returnType; + } + + @Override + public ASTNode getASTNode() { + return declaration; + } + + public void setAttributeIndex(int attributeIndex) { + this.declaration.setAttributeIndex(attributeIndex); + } + + public ResolvableIdentifier getTypeIdentifier() { + return declaration.getTypeIdentifier(); + } +} diff --git a/src/main/java/de/uni/bremen/monty/moco/codegeneration/CodeGenerator.java b/src/main/java/de/uni/bremen/monty/moco/codegeneration/CodeGenerator.java index a381f65..3336929 100644 --- a/src/main/java/de/uni/bremen/monty/moco/codegeneration/CodeGenerator.java +++ b/src/main/java/de/uni/bremen/monty/moco/codegeneration/CodeGenerator.java @@ -39,10 +39,10 @@ package de.uni.bremen.monty.moco.codegeneration; import de.uni.bremen.monty.moco.ast.ASTNode; -import de.uni.bremen.monty.moco.ast.CoreClasses; import de.uni.bremen.monty.moco.ast.declaration.*; import de.uni.bremen.monty.moco.ast.expression.VariableAccess; import de.uni.bremen.monty.moco.ast.expression.literal.StringLiteral; +import de.uni.bremen.monty.moco.ast.types.*; import de.uni.bremen.monty.moco.codegeneration.context.CodeContext; import de.uni.bremen.monty.moco.codegeneration.context.CodeContext.LLVMFunctionAttribute; import de.uni.bremen.monty.moco.codegeneration.context.CodeContext.Linkage; @@ -53,7 +53,6 @@ import de.uni.bremen.monty.moco.codegeneration.types.*; import de.uni.bremen.monty.moco.codegeneration.voodoo.BlackMagic; -import java.lang.reflect.Type; import java.util.*; import static de.uni.bremen.monty.moco.codegeneration.types.LLVMTypeFactory.*; @@ -126,7 +125,7 @@ public LLVMIdentifier resolveIfNeeded(CodeContext c, LLV } private List> resolveArgumentsIfNeeded(CodeContext c, - List> arguments, List parameters) { + List> arguments, List parameters) { List> resolvedArguments = new ArrayList<>(arguments.size()); for (int i = 0; i < arguments.size(); i++) { LLVMIdentifier resolvedArgument = resolveIfNeeded(c, (LLVMIdentifier) arguments.get(i)); @@ -140,18 +139,18 @@ private List> unboxArgumentsIfNeeded(CodeCont List> arguments) { List> unboxedArguments = new ArrayList<>(arguments.size()); for (LLVMIdentifier llvmIdentifier : arguments) { - if (llvmIdentifier.getType().equals(mapToLLVMType(CoreClasses.intType()))) { + if (llvmIdentifier.getType().equals(mapToLLVMType(Types.intType()))) { unboxedArguments.add(unboxType(c, (LLVMIdentifier) llvmIdentifier, int64())); - } else if (llvmIdentifier.getType().equals(mapToLLVMType(CoreClasses.boolType()))) { + } else if (llvmIdentifier.getType().equals(mapToLLVMType(Types.boolType()))) { unboxedArguments.add(unboxType(c, (LLVMIdentifier) llvmIdentifier, int1())); - } else if (llvmIdentifier.getType().equals(mapToLLVMType(CoreClasses.floatType()))) { + } else if (llvmIdentifier.getType().equals(mapToLLVMType(Types.floatType()))) { unboxedArguments.add(unboxType(c, (LLVMIdentifier) llvmIdentifier, double64())); - } else if (llvmIdentifier.getType().equals(mapToLLVMType(CoreClasses.charType()))) { + } else if (llvmIdentifier.getType().equals(mapToLLVMType(Types.charType()))) { unboxedArguments.add(unboxType(c, (LLVMIdentifier) llvmIdentifier, int8())); - } else if (llvmIdentifier.getType().equals(mapToLLVMType(CoreClasses.stringType()))) { + } else if (llvmIdentifier.getType().equals(mapToLLVMType(Types.stringType()))) { unboxedArguments.add(unboxType(c, (LLVMIdentifier) llvmIdentifier, pointer(int8()))); - } else if (llvmIdentifier.getType().equals(mapToLLVMType(CoreClasses.arrayType()))) { - LLVMType llvmType = mapToLLVMType((TypeDeclaration) CoreClasses.objectType()); + } else if (llvmIdentifier.getType().equals(mapToLLVMType(Types.arrayType()))) { + LLVMType llvmType = mapToLLVMType(Types.objectType()); LLVMType array = pointer(struct(Arrays.asList(int64(), array(llvmType, 0)))); unboxedArguments.add(unboxType(c, (LLVMIdentifier) llvmIdentifier, array)); } else { @@ -173,7 +172,7 @@ private LLVMIdentifier> addStringToDataField(CodeContext } private LLVMIdentifier> getVMTPointer(CodeContext c, - LLVMIdentifier> selfReference, ClassDeclaration classDeclaration) { + LLVMIdentifier> selfReference, ConcreteType classDeclaration) { String s = nameMangler.mangleClass(classDeclaration); LLVMPointer vmtType = pointer((LLVMType) struct(s + "_vmt_type")); LLVMIdentifier> vmtPointer = llvmIdentifierFactory.newLocal(vmtType, true); @@ -186,15 +185,15 @@ private LLVMIdentifier> getVMTPointer(CodeContext c, } private LLVMIdentifier> getFunctionPointer(CodeContext c, - LLVMIdentifier> selfReference, FunctionDeclaration declaration) { + LLVMIdentifier> selfReference, ConcreteFunctionType declaration) { LLVMIdentifier> vmtPointer = getVMTPointer( c, selfReference, - (ClassDeclaration) mapAbstractGenericToConcreteIfApplicable(declaration.getDefiningClass())); + declaration.getDefiningClass()); - LLVMPointer functionType = mapToLLVMType(declaration); - LLVMIdentifier> functionPointer = llvmIdentifierFactory.newLocal(functionType); + LLVMPointer ConcreteFunctionType = mapToLLVMType(declaration); + LLVMIdentifier> functionPointer = llvmIdentifierFactory.newLocal(ConcreteFunctionType); c.getelementptr( functionPointer, resolveIfNeeded(c, vmtPointer), @@ -203,7 +202,7 @@ private LLVMIdentifier> getFunctionPointer(CodeCon return functionPointer; } - public void buildConstructor(CodeContext c, ClassDeclaration classDeclaration) { + public void buildConstructor(CodeContext c, ConcreteType classDeclaration) { List> llvmParameter = new ArrayList<>(); String mangledClass = nameMangler.mangleClass(classDeclaration); String constructorName = mangledClass + "_constructor"; @@ -222,7 +221,7 @@ public void buildConstructor(CodeContext c, ClassDeclaration classDeclaration) { returnValue(c, (LLVMIdentifier) selfReference, classDeclaration); } - public LLVMIdentifier callConstructor(CodeContext c, ClassDeclaration classDeclaration) { + public LLVMIdentifier callConstructor(CodeContext c, ConcreteType classDeclaration) { LLVMIdentifier result = llvmIdentifierFactory.newLocal(mapToLLVMType(classDeclaration), false); LLVMIdentifier signature = llvmIdentifierFactory.newGlobal( @@ -251,14 +250,14 @@ public String getLabelPrefix(ASTNode node) { return node2label.get(node); } - public LLVMIdentifier declareGlobalVariable(CodeContext c, String name, TypeDeclaration type) { + public LLVMIdentifier declareGlobalVariable(CodeContext c, String name, ConcreteType type) { LLVMType llvmType = mapToLLVMType(type); LLVMIdentifier variable = llvmIdentifierFactory.newGlobal(name, llvmType); c.global(Linkage.priv, variable, false); return variable; } - public LLVMIdentifier declareLocalVariable(CodeContext c, String name, TypeDeclaration type) { + public LLVMIdentifier declareLocalVariable(CodeContext c, String name, ConcreteType type) { LLVMType llvmType = mapToLLVMType(type); LLVMIdentifier variable = llvmIdentifierFactory.newLocal(name, llvmType, true); @@ -266,13 +265,13 @@ public LLVMIdentifier declareLocalVariable(CodeContext c, String name, return variable; } - public LLVMIdentifier resolveLocalVarName(String name, TypeDeclaration type, + public LLVMIdentifier resolveLocalVarName(String name, ConcreteType type, boolean resolvable) { T llvmType = mapToLLVMType(type); return llvmIdentifierFactory.newLocal(name, llvmType, resolvable); } - public LLVMIdentifier resolveGlobalVarName(String name, TypeDeclaration type) { + public LLVMIdentifier resolveGlobalVarName(String name, ConcreteType type) { T llvmType = mapToLLVMType(type); return llvmIdentifierFactory.newGlobal(name, llvmType); } @@ -289,7 +288,7 @@ public void addMain(CodeContext active) { active.label("entry"); } - public void addFunction(CodeContext c, TypeDeclaration returnType, + public void addFunction(CodeContext c, ConcreteType returnType, List> llvmParameter, String name) { LLVMType llvmReturnType = mapToLLVMType(returnType); c.define( @@ -298,7 +297,7 @@ public void addFunction(CodeContext c, TypeDeclaration returnType, c.label("entry"); } - public void addNativeFunction(CodeContext c, TypeDeclaration returnType, + public void addNativeFunction(CodeContext c, ConcreteType returnType, List> llvmParameter, String name) { addFunction(c, returnType, llvmParameter, name); @@ -316,7 +315,7 @@ public void addNativeFunction(CodeContext c, TypeDeclaration returnType, returnValue( c, (LLVMIdentifier) (LLVMIdentifier) llvmIdentifierFactory.voidId(), - CoreClasses.voidType()); + Types.voidType()); } } @@ -324,7 +323,7 @@ public void returnMain(CodeContext c) { c.ret(llvmIdentifierFactory.constant(int32(), 0)); } - public void returnValue(CodeContext c, LLVMIdentifier returnValue, TypeDeclaration expectedType) { + public void returnValue(CodeContext c, LLVMIdentifier returnValue, ConcreteType expectedType) { LLVMIdentifier resolved = resolveIfNeeded(c, returnValue); LLVMIdentifier casted = castIfNeeded(c, resolved, mapToLLVMType(expectedType)); c.ret(casted); @@ -387,7 +386,7 @@ public LLVMIdentifier accessMember(CodeContext c, LLVMIdentifier accessMember(CodeContext c, LLVMIdentifier> pointer, - int attributeOffset, TypeDeclaration type, boolean load) { + int attributeOffset, ConcreteType type, boolean load) { LLVMIdentifier result = llvmIdentifierFactory.newLocal(mapToLLVMType(type), load); c.getelementptr( @@ -398,8 +397,8 @@ public LLVMIdentifier accessMember(CodeContext c, LLVMIdentifier accessClosureContextMember(CodeContext c, ClassDeclaration closureClass, - VariableDeclaration varDecl, VariableAccess varAccess, TypeDeclaration variableType, + public LLVMIdentifier accessClosureContextMember(CodeContext c, ConcreteType closureClass, + VariableDeclaration varDecl, VariableAccess varAccess, ConcreteType variableType, LLVMIdentifier> context) { LLVMType contextType = LLVMTypeFactory.struct(nameMangler.mangleClass(closureClass) + "_closure_context"); @@ -415,15 +414,15 @@ public LLVMIdentifier accessClosureContextMember(CodeContext c, ClassD return result; } - public LLVMIdentifier accessClosureContextMember(CodeContext c, ClassDeclaration closureClass, - VariableDeclaration varDecl, VariableAccess varAccess, TypeDeclaration variableType) { + public LLVMIdentifier accessClosureContextMember(CodeContext c, ConcreteType closureClass, + VariableDeclaration varDecl, VariableAccess varAccess, ConcreteType variableType) { LLVMIdentifier> self = resolveLocalVarName("..ctx..", closureClass, false); return accessClosureContextMember(c, closureClass, varDecl, varAccess, variableType, self); } - public LLVMIdentifier accessContextMember(CodeContext c, ClassDeclaration generatorClass, - VariableDeclaration varDecl, VariableAccess varAccess, TypeDeclaration variableType) { + public LLVMIdentifier accessContextMember(CodeContext c, ConcreteType generatorClass, + VariableDeclaration varDecl, VariableAccess varAccess, ConcreteType variableType) { LLVMType contextType = LLVMTypeFactory.struct(nameMangler.mangleClass(generatorClass) + "_context"); @@ -446,8 +445,8 @@ public LLVMIdentifier accessContextMember(CodeContext c, ClassDeclarat } public LLVMIdentifier accessGeneratorJumpPointer(CodeContext c, - LLVMIdentifier> pointer, ClassDeclaration generatorClass, int attributeOffset, - boolean load) { + LLVMIdentifier> pointer, ConcreteType generatorClass, int attributeOffset, + boolean load) { LLVMType contextType = LLVMTypeFactory.struct(nameMangler.mangleClass(generatorClass) + "_context"); LLVMType jumpPrtType = LLVMTypeFactory.pointer(LLVMTypeFactory.int8()); @@ -464,13 +463,22 @@ public LLVMIdentifier accessGeneratorJumpPointer(CodeContext c, return pointervar; } - public T mapToLLVMType(TypeDeclaration type) { + public T mapToLLVMType(ConcreteVariableType type) { + return typeConverter.mapToLLVMType(type.getType()); + } + + + public LLVMPointer mapToLLVMType(ConcreteFunctionType type) { + return typeConverter.mapToLLVMType(type); + } + + public T mapToLLVMType(ConcreteType type) { return typeConverter.mapToLLVMType(type); } public LLVMIdentifier> castClass(CodeContext c, - LLVMIdentifier> pointer, ClassDeclaration sourceType, ClassDeclaration resultType, - String labelPrefix) { + LLVMIdentifier> pointer, ConcreteType sourceType, ConcreteType resultType, + String labelPrefix) { String successLabel = labelPrefix + ".success"; String failureLabel = labelPrefix + ".failure"; @@ -487,14 +495,14 @@ public LLVMIdentifier> castClass(CodeContext c, } public LLVMIdentifier> castClassUnchecked(CodeContext c, - LLVMIdentifier> pointer, ClassDeclaration sourceType, ClassDeclaration resultType) { + LLVMIdentifier> pointer, ConcreteType resultType) { pointer = resolveIfNeeded(c, pointer); - return castIfNeeded(c, pointer, (LLVMPointer) mapToLLVMType(resultType)); + return castIfNeeded(c, pointer, mapToLLVMType(resultType)); } public LLVMIdentifier isClass(CodeContext c, LLVMIdentifier> pointer, - ClassDeclaration sourceType, ClassDeclaration resultType) { + ConcreteType sourceType, ConcreteType resultType) { pointer = resolveIfNeeded(c, pointer); LLVMIdentifier> vmt = getVMTPointer(c, pointer, sourceType); @@ -534,8 +542,8 @@ public void checkArrayBounds(CodeContext c, LLVMIdentifier) (LLVMIdentifier) boundsCheckSignature, array, index); } - public LLVMIdentifier call(CodeContext c, String functionName, TypeDeclaration returnType, - List> arguments, List parameters) { + public LLVMIdentifier call(CodeContext c, String functionName, ConcreteType returnType, + List> arguments, List parameters) { LLVMType llvmReturnType = mapToLLVMType(returnType); LLVMIdentifier functionSignature = llvmIdentifierFactory.newGlobal(functionName, llvmReturnType); List> resolvedArguments = resolveArgumentsIfNeeded(c, arguments, parameters); @@ -546,25 +554,25 @@ public LLVMIdentifier call(CodeContext c, String functionName, TypeDeclaratio } public void callVoid(CodeContext c, String functionName, List> arguments, - List parameters) { + List parameters) { List> resolvedArguments = resolveArgumentsIfNeeded(c, arguments, parameters); c.callVoid(llvmIdentifierFactory.newGlobal(functionName, (LLVMType) voidType()), resolvedArguments); } - public LLVMIdentifier callMethod(CodeContext c, FunctionDeclaration declaration, - List> arguments, List parameters) { + public LLVMIdentifier callMethod(CodeContext c, ConcreteFunctionType declaration, + List> arguments, List parameters) { List> resolvedArguments = resolveArgumentsIfNeeded(c, arguments, parameters); LLVMIdentifier> functionPointer = getFunctionPointer(c, (LLVMIdentifier>) resolvedArguments.get(0), declaration); return c.call( (LLVMIdentifier) resolveIfNeeded(c, functionPointer), - llvmIdentifierFactory.newLocal(mapToLLVMType(declaration.getReturnType()), false), + llvmIdentifierFactory.newLocal(mapToLLVMType((ConcreteType) declaration.getReturnType()), false), resolvedArguments); } - public void callVoidMethod(CodeContext c, FunctionDeclaration declaration, List> arguments, - List parameters) { + public void callVoidMethod(CodeContext c, ConcreteFunctionType declaration, List> arguments, + List parameters) { List> resolvedArguments = resolveArgumentsIfNeeded(c, arguments, parameters); LLVMIdentifier> functionPointer = @@ -598,7 +606,7 @@ public LLVMIdentifier loadChar(Character value) { public LLVMIdentifier> buildArray(CodeContext c, List> elements) { - LLVMType elementType = mapToLLVMType((TypeDeclaration) CoreClasses.objectType()); + LLVMType elementType = mapToLLVMType(Types.objectType()); LLVMType lengthFieldType = int64(); LLVMArrayType rawArrayType = array(elementType, 0); LLVMStructType arrayStructType = struct(Arrays.asList(lengthFieldType, rawArrayType)); @@ -635,9 +643,9 @@ public LLVMIdentifier> buildArray(CodeContext c, Lis return arrayPointerVar; } - public LLVMIdentifier boxType(CodeContext c, LLVMIdentifier toBox, TypeDeclaration type) { + public LLVMIdentifier boxType(CodeContext c, LLVMIdentifier toBox, ConcreteType type) { - LLVMIdentifier boxedValue = callConstructor(c, (ClassDeclaration) type); + LLVMIdentifier boxedValue = callConstructor(c, type); LLVMIdentifier boxedValueField = llvmIdentifierFactory.newLocal(toBox.getType()); c.getelementptr( boxedValueField, @@ -664,20 +672,4 @@ public LLVMIdentifier unboxType(CodeContext c, LLVMIdent c.load(sourcePointer, targetPointer); return targetPointer; } - - public void pushClassDeclarationVariation(ClassDeclarationVariation var) { - typeConverter.pushClassDeclarationVariation(var); - } - - public ClassDeclarationVariation getCurrentClassDeclarationVariation() { - return typeConverter.getCurrentClassDeclarationVariation(); - } - - public void popClassDeclarationVariation() { - typeConverter.popClassDeclarationVariation(); - } - - public TypeDeclaration mapAbstractGenericToConcreteIfApplicable(ClassDeclaration classDecl) { - return typeConverter.mapAbstractGenericToConcreteIfApplicable(classDecl); - } } diff --git a/src/main/java/de/uni/bremen/monty/moco/codegeneration/NameMangler.java b/src/main/java/de/uni/bremen/monty/moco/codegeneration/NameMangler.java index 4827917..4def702 100644 --- a/src/main/java/de/uni/bremen/monty/moco/codegeneration/NameMangler.java +++ b/src/main/java/de/uni/bremen/monty/moco/codegeneration/NameMangler.java @@ -44,7 +44,7 @@ import de.uni.bremen.monty.moco.ast.declaration.*; import de.uni.bremen.monty.moco.ast.statement.ConditionalStatement; import de.uni.bremen.monty.moco.ast.statement.WhileLoop; -import de.uni.bremen.monty.moco.codegeneration.types.TypeConverter; +import de.uni.bremen.monty.moco.ast.types.*; enum Mangled { MODULE("M."), CLASS(".C."), FUNC(".F."), PROC(".P."), BLOCK(".B."), VAR(".V."), TYPE("$"), IF("IF."), ELSE("ELSE."), WHILE( @@ -84,42 +84,29 @@ public String toString() { * * mangled : packet_module(_class)?((_block|_proc|_func)*(_proc|_func|_var))?; * */ public class NameMangler { - TypeConverter typeConverter; - private String mangleFunctionDeclaration(FunctionDeclaration node, String midTerm) { + private String mangleFunctionDeclaration(ConcreteFunctionType node, String midTerm) { String parameter = ""; - for (final VariableDeclaration variableDeclaration : node.getParameters()) { - if (escapeForLLVM(variableDeclaration.getIdentifier()).equals("self")) { - } else { - TypeDeclaration type = variableDeclaration.getType(); - ClassDeclaration classDeclaration = getConcreteClass(node, type); - parameter += Mangled.TYPE + mangleClass(classDeclaration); + for (final ConcreteVariableType variableDeclaration : node.getParameter()) { + if (!escapeForLLVM(variableDeclaration.getIdentifier()).equals("self")) { + parameter += Mangled.TYPE + mangleClass(variableDeclaration.getType()); } } String base; - if (node.getDefiningClass() != null) { - base = - mangleClass((ClassDeclaration) typeConverter.mapAbstractGenericToConcreteIfApplicable(node.getDefiningClass())); + if (node.getDeclarationType() == FunctionDeclaration.DeclarationType.UNBOUND) { + base = mangleBlock(node.getASTNode(), node.getContext()); } else { - base = mangleBlock(node); + base = mangleClass(node.getDefiningClass()); } return base + midTerm + parameter; } - private ClassDeclaration getConcreteClass(ASTNode node, TypeDeclaration type) { - if (type instanceof AbstractGenericType) { - ClassDeclarationVariation variation = typeConverter.getCurrentClassDeclarationVariation(); - type = variation.mapAbstractToConcrete((AbstractGenericType) type); - } - return (ClassDeclaration) type; - } - - public String mangleFunction(FunctionDeclaration node) { + public String mangleFunction(ConcreteFunctionType node) { if (node.isFunction()) { String funcName = Mangled.FUNC + escapeForLLVM(node.getIdentifier()); - funcName += Mangled.TYPE + mangleClass(getConcreteClass(node, node.getReturnType())); + funcName += Mangled.TYPE + mangleClass(node.getReturnType()); return mangleFunctionDeclaration(node, funcName); @@ -130,39 +117,40 @@ public String mangleFunction(FunctionDeclaration node) { } } - public String mangleVariable(VariableDeclaration node) { - String base = mangleBlock(node); + public String mangleVariable(ConcreteVariableType node) { + String base = mangleBlock(node.getASTNode(), node.getContext()); String var = Mangled.VAR + escapeForLLVM(node.getIdentifier()) + Mangled.TYPE - + mangleClass(getConcreteClass(node, node.getType())); + + mangleClass(node.getType()); return base + var; } - private String mangleBlock(ASTNode node) { + private String mangleBlock(ASTNode node, TypeContext context) { ASTNode parent = node.getParentNode(); if (parent instanceof ModuleDeclaration) { return mangleModule((ModuleDeclaration) parent); } else if (parent instanceof ClassDeclaration) { - return mangleClass((ClassDeclaration) parent); + ClassDeclaration clazz = (ClassDeclaration) parent; + return mangleClass(TypeFactory.makeConcrete(clazz,context)); } else if (parent instanceof FunctionDeclaration) { - return mangleFunction((FunctionDeclaration) parent); + return mangleFunction(TypeFactory.makeConcrete((FunctionDeclaration) parent, context)); } else if (parent instanceof ConditionalStatement || parent instanceof WhileLoop) { - return Mangled.BLOCK + Integer.toHexString(System.identityHashCode(parent)) + mangleBlock(parent); + return Mangled.BLOCK + Integer.toHexString(System.identityHashCode(parent)) + mangleBlock(parent, context); } else { - return mangleBlock(parent); + return mangleBlock(parent, context); } } - public String mangleClass(ClassDeclaration node) { - ModuleDeclaration module = (ModuleDeclaration) node.getParentNodeByType(ModuleDeclaration.class); + public String mangleClass(ConcreteType type){ + ModuleDeclaration module = type.getModuleDeclaration(); String base = mangleModule(module); - String className = Mangled.CLASS + escapeForLLVM(node.getIdentifier()); - if (node instanceof ClassDeclarationVariation) { + String className = Mangled.CLASS + escapeForLLVM(type.getIdentifier()); + if (!type.getConcreteGenericTypes().isEmpty()) { className += Mangled.TYPE; - for (ClassDeclaration concreteGenericType : ((ClassDeclarationVariation) node).getConcreteGenericTypes()) { + for (ConcreteType concreteGenericType : type.getConcreteGenericTypes()) { className += Mangled.TYPE + mangleClass(concreteGenericType); } } @@ -192,8 +180,4 @@ private String escapeForLLVM(Identifier identifier) { string = string.replaceAll("%", "_rem"); return string; } - - public void setTypeConverter(TypeConverter converter) { - typeConverter = converter; - } } diff --git a/src/main/java/de/uni/bremen/monty/moco/codegeneration/context/Operations.java b/src/main/java/de/uni/bremen/monty/moco/codegeneration/context/Operations.java index 870f942..360f66b 100644 --- a/src/main/java/de/uni/bremen/monty/moco/codegeneration/context/Operations.java +++ b/src/main/java/de/uni/bremen/monty/moco/codegeneration/context/Operations.java @@ -39,8 +39,7 @@ package de.uni.bremen.monty.moco.codegeneration.context; -import de.uni.bremen.monty.moco.ast.CoreClasses; -import de.uni.bremen.monty.moco.ast.declaration.TypeDeclaration; +import de.uni.bremen.monty.moco.ast.types.Types; import de.uni.bremen.monty.moco.codegeneration.Native; import de.uni.bremen.monty.moco.codegeneration.CodeGenerator; import de.uni.bremen.monty.moco.codegeneration.context.CodeContext.FcmpOperand; @@ -150,7 +149,7 @@ public LLVMIdentifier readln(CodeContext c) { return codeGenerator.boxType( c, (LLVMIdentifier) (LLVMIdentifier) resultPointer, - CoreClasses.stringType()); + Types.stringType()); } @Native("M.System.F.read$M.String.C.String$M.Int.C.Int") @@ -164,7 +163,7 @@ public LLVMIdentifier read(CodeContext c, LLVMIdentifier num return codeGenerator.boxType( c, (LLVMIdentifier) (LLVMIdentifier) resultPointer, - CoreClasses.stringType()); + Types.stringType()); } @Native("M.Object.C.Object.F._eq_$M.Bool.C.Bool$M.Object.C.Object") @@ -333,7 +332,7 @@ public LLVMIdentifier srem(CodeContext c, LLVMIdentifier arg1, return c.binaryOperation("srem", arg1, arg2, llvmIdentifierFactory.newLocal(arg1.getType(), false)); } - @Native("M.Array.C.Array.F.length$M.Int.C.Int") + @Native("M.Array.C.NativeArray.F.length$M.Int.C.Int") public LLVMIdentifier arrayLength(CodeContext c, LLVMIdentifier arrayPointer) { LLVMIdentifier> arrayStructPointer = (LLVMIdentifier>) (LLVMIdentifier) arrayPointer; @@ -347,7 +346,7 @@ public LLVMIdentifier arrayLength(CodeContext c, LLVMIdentifier arrayAccess(CodeContext c, LLVMIdentifier arrayPointer, LLVMIdentifier index) { LLVMIdentifier> arrayStructPointer = @@ -355,7 +354,7 @@ public LLVMIdentifier arrayAccess(CodeContext c, LLVMIdentifier result = - llvmIdentifierFactory.newLocal(codeGenerator.mapToLLVMType(CoreClasses.objectType())); + llvmIdentifierFactory.newLocal(codeGenerator.mapToLLVMType(Types.objectType())); c.getelementptr( result, arrayStructPointer, @@ -365,7 +364,7 @@ public LLVMIdentifier arrayAccess(CodeContext c, LLVMIdentifier arrayPointer, LLVMIdentifier index, LLVMIdentifier value) { @@ -374,7 +373,7 @@ public void arraySet(CodeContext c, LLVMIdentifier arrayPointer, LL codeGenerator.checkArrayBounds(c, arrayStructPointer, index); - LLVMType elementType = codeGenerator.mapToLLVMType((TypeDeclaration) CoreClasses.objectType()); + LLVMType elementType = codeGenerator.mapToLLVMType(Types.objectType()); LLVMIdentifier> element = llvmIdentifierFactory.newLocal(pointer(elementType)); c.getelementptr( diff --git a/src/main/java/de/uni/bremen/monty/moco/codegeneration/types/TypeConverter.java b/src/main/java/de/uni/bremen/monty/moco/codegeneration/types/TypeConverter.java index 3210728..3f0edce 100644 --- a/src/main/java/de/uni/bremen/monty/moco/codegeneration/types/TypeConverter.java +++ b/src/main/java/de/uni/bremen/monty/moco/codegeneration/types/TypeConverter.java @@ -39,8 +39,8 @@ package de.uni.bremen.monty.moco.codegeneration.types; -import de.uni.bremen.monty.moco.ast.CoreClasses; import de.uni.bremen.monty.moco.ast.declaration.*; +import de.uni.bremen.monty.moco.ast.types.*; import de.uni.bremen.monty.moco.codegeneration.NameMangler; import de.uni.bremen.monty.moco.codegeneration.context.CodeContext; import de.uni.bremen.monty.moco.codegeneration.context.CodeContext.Linkage; @@ -52,11 +52,10 @@ import static de.uni.bremen.monty.moco.codegeneration.types.LLVMTypeFactory.*; public class TypeConverter { - private Map typeMap = new HashMap<>(); + private Map typeMap = new HashMap<>(); private LLVMIdentifierFactory llvmIdentifierFactory; private CodeContext constantContext; private NameMangler nameMangler; - private Stack currentClassDeclVar = new Stack<>(); public TypeConverter(LLVMIdentifierFactory llvmIdentifierFactory, CodeContext constantContext, NameMangler nameMangler) { @@ -67,15 +66,15 @@ public TypeConverter(LLVMIdentifierFactory llvmIdentifierFactory, CodeContext co } private void initPreDefinedTypes() { - typeMap.put(CoreClasses.voidType(), voidType()); + typeMap.put(Types.voidType(), voidType()); } - private LLVMPointer convertType(FunctionDeclaration type) { + private LLVMPointer convertType(ConcreteFunctionType type) { List parameter = new ArrayList<>(); if (type.getDeclarationType().equals(FunctionDeclaration.DeclarationType.METHOD)) { - parameter.add(mapToLLVMType(mapAbstractGenericToConcreteIfApplicable(type.getDefiningClass()))); + parameter.add(mapToLLVMType(type.getDefiningClass())); } - for (VariableDeclaration varDecl : type.getParameters()) { + for (ConcreteVariableType varDecl : type.getParameter()) { parameter.add(mapToLLVMType(varDecl.getType())); } if (type.isFunction()) { @@ -84,26 +83,12 @@ private LLVMPointer convertType(FunctionDeclaration type) { return pointer(function(voidType(), parameter)); } - private LLVMPointer convertType(ClassDeclaration type) { - return pointer(struct(nameMangler.mangleClass(type))); + private T convertType(ConcreteType type) { + return (T)pointer(struct(nameMangler.mangleClass(type))); } - private T convertType(TypeDeclaration type) { - if (type instanceof FunctionDeclaration) { - LLVMPointer llvmFunctionTypeLLVMPointer = convertType((FunctionDeclaration) type); - return (T) llvmFunctionTypeLLVMPointer; - } - return (T) convertType((ClassDeclaration) type); - } - - private void addType(TypeDeclaration typeDecl) { - if (typeDecl instanceof ClassDeclaration) { - addClass((ClassDeclaration) typeDecl); - } - } - - private void addClass(ClassDeclaration classDecl) { - String mangledNodeName = nameMangler.mangleClass(classDecl); + private void addType(ConcreteType concreteType) { + String mangledNodeName = nameMangler.mangleClass(concreteType); LLVMStructType llvmClassType = struct(mangledNodeName); List llvmClassTypeDeclarations = new ArrayList<>(); @@ -112,72 +97,72 @@ private void addClass(ClassDeclaration classDecl) { llvmClassTypeDeclarations.add(pointer(llvmVMTType)); LLVMIdentifier llvmVMTDataIdentifier = - llvmIdentifierFactory.newGlobal(mangledNodeName + "_vmt_data", (LLVMType) llvmVMTType); + llvmIdentifierFactory.newGlobal(mangledNodeName + "_vmt_data", llvmVMTType); List> llvmVMTDataInitializer = new ArrayList<>(); - List recursiveSuperClassDeclarations = classDecl.getSuperClassDeclarationsRecursive(); + List recursiveSuperClassDeclarations = concreteType.getSuperClassDeclarationsRecursive(); LLVMArrayType llvmCTDataType = array(pointer(int8()), recursiveSuperClassDeclarations.size() + 1); LLVMIdentifier llvmCTDataIdentifier = - llvmIdentifierFactory.newGlobal(mangledNodeName + "_ct_data", (LLVMType) llvmCTDataType); + llvmIdentifierFactory.newGlobal(mangledNodeName + "_ct_data", llvmCTDataType); List> llvmCTDataInitializer = new ArrayList<>(); llvmVMTTypeDeclarations.add(pointer(llvmCTDataType)); llvmVMTDataInitializer.add((LLVMIdentifier) (LLVMIdentifier) llvmIdentifierFactory.pointerTo(llvmCTDataIdentifier)); - for (ClassDeclaration classDeclaration : recursiveSuperClassDeclarations) { + for (ConcreteType classDeclaration : recursiveSuperClassDeclarations) { // Ensure that addType() was called for this classDeclaration so that a VMT/CT was generated. mapToLLVMType(classDeclaration); String mangledClass = nameMangler.mangleClass(classDeclaration); LLVMIdentifier vmtDataIdent = - llvmIdentifierFactory.newGlobal(mangledClass + "_vmt_data", (LLVMType) pointer(struct(mangledClass + llvmIdentifierFactory.newGlobal(mangledClass + "_vmt_data", pointer(struct(mangledClass + "_vmt_type"))); llvmCTDataInitializer.add(llvmIdentifierFactory.bitcast(vmtDataIdent, pointer(int8()))); } llvmCTDataInitializer.add((LLVMIdentifier) (LLVMIdentifier) llvmIdentifierFactory.constantNull(pointer(int8()))); - if (classDecl == CoreClasses.intType()) { + if (concreteType.equals(Types.intType())) { llvmClassTypeDeclarations.add(LLVMTypeFactory.int64()); - } else if (classDecl == CoreClasses.boolType()) { + } else if (concreteType.equals(Types.boolType())) { llvmClassTypeDeclarations.add(LLVMTypeFactory.int1()); - } else if (classDecl == CoreClasses.floatType()) { + } else if (concreteType.equals(Types.floatType())) { llvmClassTypeDeclarations.add(LLVMTypeFactory.double64()); - } else if (classDecl == CoreClasses.charType()) { + } else if (concreteType.equals(Types.charType())) { llvmClassTypeDeclarations.add(LLVMTypeFactory.int8()); - } else if (classDecl == CoreClasses.stringType()) { + } else if (concreteType.equals(Types.stringType())) { llvmClassTypeDeclarations.add(LLVMTypeFactory.pointer(LLVMTypeFactory.int8())); - } else if (classDecl == CoreClasses.arrayType()) { - LLVMType llvmType = mapToLLVMType((TypeDeclaration) CoreClasses.objectType()); + } else if (concreteType.equals(Types.arrayType())) { + LLVMType llvmType = mapToLLVMType(Types.objectType()); LLVMType array = struct(Arrays.asList(LLVMTypeFactory.int64(), LLVMTypeFactory.array(llvmType, 0))); llvmClassTypeDeclarations.add(LLVMTypeFactory.pointer(array)); } - for (ClassDeclaration classDeclaration : recursiveSuperClassDeclarations) { - for (Declaration decl : classDeclaration.getBlock().getDeclarations()) { - if (decl instanceof VariableDeclaration) { - llvmClassTypeDeclarations.add(mapToLLVMType(((VariableDeclaration) decl).getType())); - } + for (ConcreteType classDeclaration : recursiveSuperClassDeclarations) { + for (ConcreteVariableType decl : classDeclaration.getVariables()) { + llvmClassTypeDeclarations.add(mapToLLVMType(decl.getType())); } } // generator functions - if (classDecl.isGenerator()) { + if (concreteType.isGenerator()) { // create the structure - LLVMType contextStruct = addGeneratorContext(classDecl, mangledNodeName); + LLVMType contextStruct = addGeneratorContext(concreteType, mangledNodeName); // add context struct as the last index to the class declaration llvmClassTypeDeclarations.add(contextStruct); } // closures - FunctionDeclaration wrappedFunction = classDecl.getWrappedFunction(); - if ((wrappedFunction != null) && (wrappedFunction.isClosure())) { - // create the structure - LLVMType closureContextStruct = - addClosureContext(classDecl, wrappedFunction.getClosureVariables(), mangledNodeName); - // add context struct as the last index to the class declaration - llvmClassTypeDeclarations.add(closureContextStruct); - } - - for (FunctionDeclaration function : classDecl.getVirtualMethodTable()) { + if (concreteType.hasWrappedFunction()) { + ConcreteFunctionType wrappedFunction = concreteType.getWrappedFunction(); + if (wrappedFunction.isClosure()) { + // create the structure + LLVMType closureContextStruct = + addClosureContext(concreteType, wrappedFunction.getClosureVariables(), mangledNodeName); + // add context struct as the last index to the class declaration + llvmClassTypeDeclarations.add(closureContextStruct); + } + } + + for (ConcreteFunctionType function : concreteType.getVirtualMethods()) { if (!function.isInitializer()) { LLVMType signature = mapToLLVMType(function); llvmVMTTypeDeclarations.add(signature); @@ -200,8 +185,8 @@ private void addClass(ClassDeclaration classDecl) { llvmIdentifierFactory.constant(llvmVMTType, llvmVMTDataInitializer)); } - protected LLVMType addClosureContext(ClassDeclaration classDecl, Collection variables, - String mangledNodeName) { + protected LLVMType addClosureContext(ConcreteType classDecl, Collection variables, + String mangledNodeName) { // declaration types inside the struct List llvmStructTypeDeclarations = new ArrayList<>(); @@ -209,7 +194,7 @@ protected LLVMType addClosureContext(ClassDeclaration classDecl, Collection mapToLLVMType(ClassDeclaration type) { - return (LLVMPointer) mapToLLVMType((TypeDeclaration) type); - } - - public LLVMPointer mapToLLVMType(FunctionDeclaration type) { - return (LLVMPointer) mapToLLVMType((TypeDeclaration) type); + public LLVMPointer mapToLLVMType(ConcreteFunctionType type) { + return convertType(type); } - public T mapToLLVMType(TypeDeclaration type) { - if (type instanceof AbstractGenericType) { - ClassDeclaration concreteType = - getCurrentClassDeclarationVariation().mapAbstractToConcrete((AbstractGenericType) type); - T t = (T) mapToLLVMType(concreteType); - return t; - } - + public T mapToLLVMType(ConcreteType type) { T llvmType = (T) typeMap.get(type); if (llvmType == null) { llvmType = convertType(type); @@ -270,28 +245,4 @@ public T mapToLLVMType(TypeDeclaration type) { } return llvmType; } - - public void pushClassDeclarationVariation(ClassDeclarationVariation var) { - currentClassDeclVar.push(var); - } - - public ClassDeclarationVariation getCurrentClassDeclarationVariation() { - if (currentClassDeclVar.isEmpty()) { - return null; - } - return currentClassDeclVar.peek(); - } - - public void popClassDeclarationVariation() { - if (!currentClassDeclVar.isEmpty()) { - currentClassDeclVar.pop(); - } - } - - public TypeDeclaration mapAbstractGenericToConcreteIfApplicable(ClassDeclaration type) { - if ((type.getAbstractGenericTypes().isEmpty()) || (type instanceof ClassDeclarationVariation)) { - return type; - } - return getCurrentClassDeclarationVariation().mapAbstractGenericToConcrete(type); - } } diff --git a/src/main/java/de/uni/bremen/monty/moco/exception/InvalidTypeException.java b/src/main/java/de/uni/bremen/monty/moco/exception/InvalidTypeException.java new file mode 100644 index 0000000..46b5bdd --- /dev/null +++ b/src/main/java/de/uni/bremen/monty/moco/exception/InvalidTypeException.java @@ -0,0 +1,51 @@ +/* + * moco, the Monty Compiler + * Copyright (c) 2013-2014, Monty's Coconut, All rights reserved. + * + * This file is part of moco, the Monty Compiler. + * + * moco is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation; either + * version 3.0 of the License, or (at your option) any later version. + * + * moco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * Linking this program and/or its accompanying libraries statically or + * dynamically with other modules is making a combined work based on this + * program. Thus, the terms and conditions of the GNU General Public License + * cover the whole combination. + * + * As a special exception, the copyright holders of moco give + * you permission to link this programm and/or its accompanying libraries + * with independent modules to produce an executable, regardless of the + * license terms of these independent modules, and to copy and distribute the + * resulting executable under terms of your choice, provided that you also meet, + * for each linked independent module, the terms and conditions of the + * license of that module. + * + * An independent module is a module which is not + * derived from or based on this program and/or its accompanying libraries. + * If you modify this library, you may extend this exception to your version of + * the program or library, but you are not obliged to do so. If you do not wish + * to do so, delete this exception statement from your version. + * + * You should have received a copy of the GNU General Public + * License along with this library. + */ +package de.uni.bremen.monty.moco.exception; + +import de.uni.bremen.monty.moco.ast.ASTNode; + +public class InvalidTypeException extends MontyBaseException { + public InvalidTypeException(String message) { + super(message); + } + + public InvalidTypeException(ASTNode node, String message) { + super(node, message); + } +} diff --git a/src/main/java/de/uni/bremen/monty/moco/exception/MontyBaseException.java b/src/main/java/de/uni/bremen/monty/moco/exception/MontyBaseException.java index e7b89ad..12c6c41 100644 --- a/src/main/java/de/uni/bremen/monty/moco/exception/MontyBaseException.java +++ b/src/main/java/de/uni/bremen/monty/moco/exception/MontyBaseException.java @@ -56,4 +56,8 @@ public MontyBaseException(ASTNode node, String message) { public ASTNode getNode() { return node; } + + public void setNode(ASTNode node) { + this.node = node; + } } diff --git a/src/main/java/de/uni/bremen/monty/moco/util/AllIterator.java b/src/main/java/de/uni/bremen/monty/moco/util/AllIterator.java new file mode 100644 index 0000000..5b0a1a6 --- /dev/null +++ b/src/main/java/de/uni/bremen/monty/moco/util/AllIterator.java @@ -0,0 +1,91 @@ +/* + * moco, the Monty Compiler + * Copyright (c) 2013-2014, Monty's Coconut, All rights reserved. + * + * This file is part of moco, the Monty Compiler. + * + * moco is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation; either + * version 3.0 of the License, or (at your option) any later version. + * + * moco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * Linking this program and/or its accompanying libraries statically or + * dynamically with other modules is making a combined work based on this + * program. Thus, the terms and conditions of the GNU General Public License + * cover the whole combination. + * + * As a special exception, the copyright holders of moco give + * you permission to link this programm and/or its accompanying libraries + * with independent modules to produce an executable, regardless of the + * license terms of these independent modules, and to copy and distribute the + * resulting executable under terms of your choice, provided that you also meet, + * for each linked independent module, the terms and conditions of the + * license of that module. + * + * An independent module is a module which is not + * derived from or based on this program and/or its accompanying libraries. + * If you modify this library, you may extend this exception to your version of + * the program or library, but you are not obliged to do so. If you do not wish + * to do so, delete this exception statement from your version. + * + * You should have received a copy of the GNU General Public + * License along with this library. + */ +package de.uni.bremen.monty.moco.util; + + +import java.util.HashSet; +import java.util.Iterator; +import java.util.Set; + +/** + * iterates over the given Set. If Elements are added during the iteration they will be processed too. + * The default iterator of a Set would throw a ConcurrentModificationException in that case. + * + * This is not Thread safe! + */ +public class AllIterator implements Iterator { + + private final Set visited = new HashSet<>(); + private final Set original; + private Iterator iterator; + + public AllIterator(Set allTypes) { + original = allTypes; + iterator = copy(original).iterator(); + } + + @Override + public boolean hasNext() { + boolean hasNext = iterator.hasNext(); + if (!hasNext) { + Set copy = copy(original); + copy.removeAll(visited); + if (copy.isEmpty()) { + return false; + } else { + iterator = copy.iterator(); + return true; + } + } + return true; + } + + @Override + public T next() { + T ele = iterator.next(); + visited.add(ele); + return ele; + } + + private Set copy(Set from) { + HashSet newSet = new HashSet<>(from.size()); + newSet.addAll(from); + return newSet; + } +} diff --git a/src/main/java/de/uni/bremen/monty/moco/util/FunctionWrapperFactory.java b/src/main/java/de/uni/bremen/monty/moco/util/FunctionWrapperFactory.java index c9827a8..8cb273f 100644 --- a/src/main/java/de/uni/bremen/monty/moco/util/FunctionWrapperFactory.java +++ b/src/main/java/de/uni/bremen/monty/moco/util/FunctionWrapperFactory.java @@ -38,10 +38,7 @@ */ package de.uni.bremen.monty.moco.util; -import de.uni.bremen.monty.moco.ast.Block; -import de.uni.bremen.monty.moco.ast.Identifier; -import de.uni.bremen.monty.moco.ast.Position; -import de.uni.bremen.monty.moco.ast.ResolvableIdentifier; +import de.uni.bremen.monty.moco.ast.*; import de.uni.bremen.monty.moco.ast.declaration.ClassDeclaration; import de.uni.bremen.monty.moco.ast.declaration.FunctionDeclaration; import de.uni.bremen.monty.moco.ast.declaration.VariableDeclaration; @@ -51,6 +48,8 @@ import de.uni.bremen.monty.moco.ast.statement.Assignment; import de.uni.bremen.monty.moco.ast.statement.ReturnStatement; import de.uni.bremen.monty.moco.ast.statement.UnpackAssignment; +import de.uni.bremen.monty.moco.ast.types.TypeContext; +import de.uni.bremen.monty.moco.ast.types.TypeFactory; import java.util.ArrayList; import java.util.List; @@ -77,7 +76,7 @@ public static void generateWrapperClass(FunctionDeclaration function, TupleDecla // create a variable and store an instance of the wrapper in it VariableDeclaration functionObjectDeclaration = - new VariableDeclaration(pos, varIdentifier, wrapperClass, VariableDeclaration.DeclarationType.VARIABLE); + new VariableDeclaration(pos, varIdentifier, TypeFactory.from(wrapperClass, TypeContext.EMPTY), VariableDeclaration.DeclarationType.VARIABLE); Assignment functionObjectAssignment = new Assignment(pos, new VariableAccess(pos, ResolvableIdentifier.convert(functionObjectDeclaration.getIdentifier())), new FunctionCall(pos, @@ -131,7 +130,7 @@ else if (function.getParameters().size() == 1) { } // either return the real return value (if function has a return value or if the return type must be inferred) - if ((function.isFunction()) || (function.isReturnTypeToBeInferred())) { + if (function.isReturnTypeToBeInferred() || function.isFunction()) { body.addStatement(new ReturnStatement(pos, new FunctionCall(pos, ResolvableIdentifier.convert(function.getIdentifier()), localVariables))); } @@ -146,7 +145,7 @@ else if (function.getParameters().size() == 1) { // the return type of the method is either the return type of the original function, // or empty tuple if it was a procedure. ResolvableIdentifier returnTypeIdentifier = - function.getReturnTypeIdentifier() != null ? function.getReturnTypeIdentifier() : tupleFactory.getTupleIdentifier(new ArrayList()); + function.isFunction() ? function.getReturnTypeIdentifier() : tupleFactory.getTupleIdentifier(new ArrayList()); // create a list containing the only parameter of the method List methodParams = new ArrayList<>(1); @@ -156,7 +155,7 @@ else if (function.getParameters().size() == 1) { // compose the actual method FunctionDeclaration applyMethod = new FunctionDeclaration(pos, new Identifier("_apply_"), body, methodParams, - FunctionDeclaration.DeclarationType.METHOD, returnTypeIdentifier, false); + FunctionDeclaration.DeclarationType.METHOD, returnTypeIdentifier, false); return applyMethod; } } diff --git a/src/main/java/de/uni/bremen/monty/moco/util/JavaUtil.java b/src/main/java/de/uni/bremen/monty/moco/util/JavaUtil.java new file mode 100644 index 0000000..ab1e893 --- /dev/null +++ b/src/main/java/de/uni/bremen/monty/moco/util/JavaUtil.java @@ -0,0 +1,56 @@ +/* + * moco, the Monty Compiler + * Copyright (c) 2013-2014, Monty's Coconut, All rights reserved. + * + * This file is part of moco, the Monty Compiler. + * + * moco is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation; either + * version 3.0 of the License, or (at your option) any later version. + * + * moco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * Linking this program and/or its accompanying libraries statically or + * dynamically with other modules is making a combined work based on this + * program. Thus, the terms and conditions of the GNU General Public License + * cover the whole combination. + * + * As a special exception, the copyright holders of moco give + * you permission to link this programm and/or its accompanying libraries + * with independent modules to produce an executable, regardless of the + * license terms of these independent modules, and to copy and distribute the + * resulting executable under terms of your choice, provided that you also meet, + * for each linked independent module, the terms and conditions of the + * license of that module. + * + * An independent module is a module which is not + * derived from or based on this program and/or its accompanying libraries. + * If you modify this library, you may extend this exception to your version of + * the program or library, but you are not obliged to do so. If you do not wish + * to do so, delete this exception statement from your version. + * + * You should have received a copy of the GNU General Public + * License along with this library. + */ +package de.uni.bremen.monty.moco.util; + +import com.sun.org.apache.xpath.internal.operations.Bool; + +import java.util.Objects; +import java.util.Optional; +import java.util.function.Supplier; + +public class JavaUtil { + public static Optional or(Optional self, Supplier> supplier) { + Objects.requireNonNull(supplier); + if (self.isPresent()) { + return self; + } else { + return Objects.requireNonNull(supplier.get()); + } + } +} diff --git a/src/main/java/de/uni/bremen/monty/moco/util/OverloadCandidate.java b/src/main/java/de/uni/bremen/monty/moco/util/OverloadCandidate.java index 74fcdd3..8e984cf 100644 --- a/src/main/java/de/uni/bremen/monty/moco/util/OverloadCandidate.java +++ b/src/main/java/de/uni/bremen/monty/moco/util/OverloadCandidate.java @@ -38,13 +38,13 @@ */ package de.uni.bremen.monty.moco.util; -import de.uni.bremen.monty.moco.ast.declaration.Declaration; +import de.uni.bremen.monty.moco.ast.types.MemberType; -public class OverloadCandidate { - private Declaration declaration; +public class OverloadCandidate { + private T declaration; private int score; - public OverloadCandidate(Declaration declaration, int score) { + public OverloadCandidate(T declaration, int score) { this.declaration = declaration; this.score = score; } @@ -57,7 +57,7 @@ public void setScore(int score) { this.score = score; } - public Declaration getDeclaration() { + public T getDeclaration() { return declaration; } } diff --git a/src/main/java/de/uni/bremen/monty/moco/util/TupleDeclarationFactory.java b/src/main/java/de/uni/bremen/monty/moco/util/TupleDeclarationFactory.java index 0d3b9ed..2f473bd 100644 --- a/src/main/java/de/uni/bremen/monty/moco/util/TupleDeclarationFactory.java +++ b/src/main/java/de/uni/bremen/monty/moco/util/TupleDeclarationFactory.java @@ -48,6 +48,8 @@ import de.uni.bremen.monty.moco.ast.expression.VariableAccess; import de.uni.bremen.monty.moco.ast.statement.Assignment; import de.uni.bremen.monty.moco.ast.statement.ReturnStatement; +import de.uni.bremen.monty.moco.ast.types.Type; +import de.uni.bremen.monty.moco.ast.types.TypeVariable; import java.util.*; @@ -93,19 +95,19 @@ protected ClassDeclaration createTupleType(int n) { ClassDeclaration tupleType = new ClassDeclaration(new Position(), new Identifier("Tuple" + n), new ArrayList(), new Block(new Position()), false, - new ArrayList()); + new ArrayList()); // generate the initializer FunctionDeclaration initializer = new FunctionDeclaration(new Position(), new Identifier("initializer"), new Block(new Position()), new ArrayList(), FunctionDeclaration.DeclarationType.INITIALIZER, - (TypeDeclaration) null, false); + (Type) null, false); // process the generic type parameters for (int i = 0; i < n; i++) { // add the type parameter to the class - AbstractGenericType t = new AbstractGenericType(tupleType, new Position(), new Identifier("T" + i)); - tupleType.getAbstractGenericTypes().add(t); + TypeParameterDeclaration t = new TypeParameterDeclaration(new Position(), new Identifier("T" + i), Optional.empty()); + tupleType.getTypeParameterDeclarations().add(t); // add an attribute with that type to the class addTupleAttribute(tupleType, i, t); @@ -121,17 +123,17 @@ protected ClassDeclaration createTupleType(int n) { return tupleType; } - protected void addTupleAttribute(ClassDeclaration tupleType, int i, AbstractGenericType t) { + protected void addTupleAttribute(ClassDeclaration tupleType, int i, TypeParameterDeclaration t) { VariableDeclaration attr = - new VariableDeclaration(new Position(), new Identifier("_" + (i + 1)), t, + new VariableDeclaration(new Position(), new Identifier("_" + (i + 1)), new TypeVariable(t), VariableDeclaration.DeclarationType.ATTRIBUTE); tupleType.getBlock().addDeclaration(attr); } - protected void addTupleInitializerParameter(FunctionDeclaration initializer, int i, AbstractGenericType t) { + protected void addTupleInitializerParameter(FunctionDeclaration initializer, int i, TypeParameterDeclaration t) { // add a parameter with that type to the initializer parameter list VariableDeclaration param = - new VariableDeclaration(new Position(), new Identifier("p" + (i + 1)), t, + new VariableDeclaration(new Position(), new Identifier("p" + (i + 1)), new TypeVariable(t), VariableDeclaration.DeclarationType.PARAMETER); initializer.getParameters().add(param); @@ -150,22 +152,4 @@ public Collection generateNecessaryTupleTypes() { } return tupleClasses; } - - public static boolean isTuple(ClassDeclaration type) { - String strIdent = type.getIdentifier().getSymbol(); - if (strIdent.startsWith("Tuple")) { - int n; - try { - n = Integer.parseInt(strIdent.substring(5)); - } catch (Exception e) { - return false; - } - if (type instanceof ClassDeclarationVariation) { - if (((ClassDeclarationVariation) type).getConcreteGenericTypes().size() == n) { - return true; - } - } - } - return false; - } } diff --git a/src/main/java/de/uni/bremen/monty/moco/visitor/BaseVisitor.java b/src/main/java/de/uni/bremen/monty/moco/visitor/BaseVisitor.java index 95c5a7c..03285ca 100644 --- a/src/main/java/de/uni/bremen/monty/moco/visitor/BaseVisitor.java +++ b/src/main/java/de/uni/bremen/monty/moco/visitor/BaseVisitor.java @@ -71,13 +71,22 @@ public void visitDoubleDispatched(ASTNode node) { onEnterEachNode(node); node.visit(this); onExitEachNode(node); - } catch (RuntimeException exception) { - errorCounter += 1; - if (stopOnFirstError) { - throw exception; - } else { - logError(exception); + } catch (MontyBaseException e) { + if (e.getNode() == null) { + e.setNode(node); } + handleError(e); + } catch (RuntimeException exception) { + handleError(exception); + } + } + + private void handleError(RuntimeException exception) { + errorCounter += 1; + if (stopOnFirstError) { + throw exception; + } else { + logError(exception); } } @@ -88,10 +97,14 @@ public void visitDoubleDispatched(ASTNode node) { public String getNodeInformation(ASTNode node) { if (node == null) { return "null"; - } else if (node.getPosition() != null) { - return String.format("%s at %s", node.toString(), node.getPosition().toString()); } - return node.toString(); + String nodeS = node.toString(); + String nodeClass = node.getClass().getSimpleName(); + String nodeString = nodeS.equals(nodeClass) ? nodeClass : nodeS + ":" + nodeClass; + if (node.getPosition() != null) { + return String.format("%s at %s", nodeString, node.getPosition().toString()); + } + return nodeString; } /** Log an exception. @@ -139,11 +152,11 @@ public void visit(ClassDeclaration node) { onExitChildrenEachNode(node); } - /** Visitor method to visit a AbstractGenericType. + /** Visitor method to visit a TypeParameterDeclaration. * * @param node * the node to visit */ - public void visit(AbstractGenericType node) { + public void visit(TypeParameterDeclaration node) { onEnterChildrenEachNode(node); node.visitChildren(this); onExitChildrenEachNode(node); diff --git a/src/main/java/de/uni/bremen/monty/moco/visitor/CodeGenerationVisitor.java b/src/main/java/de/uni/bremen/monty/moco/visitor/CodeGenerationVisitor.java index 76a6d52..fc75142 100644 --- a/src/main/java/de/uni/bremen/monty/moco/visitor/CodeGenerationVisitor.java +++ b/src/main/java/de/uni/bremen/monty/moco/visitor/CodeGenerationVisitor.java @@ -44,6 +44,7 @@ import de.uni.bremen.monty.moco.ast.expression.*; import de.uni.bremen.monty.moco.ast.expression.literal.*; import de.uni.bremen.monty.moco.ast.statement.*; +import de.uni.bremen.monty.moco.ast.types.*; import de.uni.bremen.monty.moco.codegeneration.CodeGenerator; import de.uni.bremen.monty.moco.codegeneration.NameMangler; import de.uni.bremen.monty.moco.codegeneration.context.CodeContext; @@ -52,11 +53,7 @@ import de.uni.bremen.monty.moco.codegeneration.identifier.LLVMIdentifierFactory; import de.uni.bremen.monty.moco.codegeneration.types.*; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collections; -import java.util.List; -import java.util.Stack; +import java.util.*; import static de.uni.bremen.monty.moco.codegeneration.types.LLVMTypeFactory.pointer; @@ -77,6 +74,8 @@ public class CodeGenerationVisitor extends BaseVisitor { private final CodeGenerator codeGenerator; private final NameMangler nameMangler; + private TypeContext currentContext = TypeContext.EMPTY; + /** Each Expression pushes it's evaluated value onto the Stack. The value is represented by a LLVMIdentifier where * the evaluated value is stored at runtime. * @@ -94,7 +93,6 @@ public class CodeGenerationVisitor extends BaseVisitor { public CodeGenerationVisitor() { nameMangler = new NameMangler(); TypeConverter typeConverter = new TypeConverter(llvmIdentifierFactory, contextUtils.constant(), nameMangler); - nameMangler.setTypeConverter(typeConverter); this.codeGenerator = new CodeGenerator(typeConverter, llvmIdentifierFactory, nameMangler); } @@ -113,26 +111,24 @@ private void closeFunctionContext() { llvmIdentifierFactory.closeScope(); } - private List> buildLLVMParameter(FunctionDeclaration node) { + private List> buildLLVMParameter(ConcreteFunctionType node) { List> llvmParameter = new ArrayList<>(); if (node.isMethod() || node.isInitializer()) { - ClassDeclaration typeDeclaration = - (ClassDeclaration) codeGenerator.mapAbstractGenericToConcreteIfApplicable(node.getDefiningClass()); - LLVMType selfType = codeGenerator.mapToLLVMType(typeDeclaration); + LLVMType selfType = codeGenerator.mapToLLVMType(node.getDefiningClass()); LLVMIdentifier selfReference = llvmIdentifierFactory.newLocal("self", selfType, false); llvmParameter.add(selfReference); } if (node.isClosure()) { - ClassDeclaration typeDeclaration = node.getWrapperClass(); + ConcreteType typeDeclaration = node.getWrapperClass(); LLVMType contextType = codeGenerator.mapToLLVMType(typeDeclaration); LLVMIdentifier ctxReference = llvmIdentifierFactory.newLocal("..ctx..", contextType, false); llvmParameter.add(ctxReference); } - for (VariableDeclaration param : node.getParameters()) { - LLVMType llvmType = codeGenerator.mapToLLVMType(param.getType()); + for (ConcreteVariableType param : node.getParameter()) { + LLVMType llvmType = codeGenerator.mapToLLVMType(param); llvmType = llvmType instanceof LLVMStructType ? pointer(llvmType) : llvmType; boolean resolvable = llvmType instanceof LLVMStructType; LLVMIdentifier e = @@ -143,18 +139,18 @@ private List> buildLLVMParameter(FunctionDecl return llvmParameter; } - private void addFunction(FunctionDeclaration node, TypeDeclaration returnType) { + private void addFunction(ConcreteFunctionType node, ConcreteType returnType) { List> llvmParameter = buildLLVMParameter(node); String name = nameMangler.mangleFunction(node); codeGenerator.addFunction(contextUtils.active(), returnType, llvmParameter, name); - if (node instanceof GeneratorFunctionDeclaration) { - addGeneratorJumpHeader((GeneratorFunctionDeclaration) node); + if (node instanceof GeneratorFunctionType) { + addGeneratorJumpHeader((ConcreteGeneratorFunctionType) node); } } - private void addGeneratorJumpHeader(GeneratorFunctionDeclaration node) { - TypeDeclaration selfType = useClassVariationIfApplicable(node.getDefiningClass()); + private void addGeneratorJumpHeader(ConcreteGeneratorFunctionType node) { + ConcreteType selfType = node.getDefiningClass(); LLVMIdentifier> self = codeGenerator.resolveLocalVarName("self", selfType, false); LLVMIdentifier pointervar = @@ -176,15 +172,14 @@ private void addGeneratorJumpHeader(GeneratorFunctionDeclaration node) { contextUtils.active().label("startGenerator"); } - private void setGeneratorLabel(ClassDeclaration classDecl, String label) { - TypeDeclaration selfType = useClassVariationIfApplicable(classDecl); - LLVMIdentifier> self = codeGenerator.resolveLocalVarName("self", selfType, false); + private void setGeneratorLabel(ConcreteType classDecl, String label) { + LLVMIdentifier> self = codeGenerator.resolveLocalVarName("self", classDecl, false); LLVMIdentifier pointervar = codeGenerator.accessGeneratorJumpPointer(contextUtils.active(), self, classDecl, 0, true); // used as // lvalue - FunctionDeclaration inFunction = null; - for (FunctionDeclaration fun : classDecl.getMethods()) { + ConcreteFunctionType inFunction = null; + for (ConcreteFunctionType fun : classDecl.getMethods()) { if (fun.getIdentifier().getSymbol().equals("getNext")) { inFunction = fun; break; @@ -197,7 +192,7 @@ private void setGeneratorLabel(ClassDeclaration classDecl, String label) { + llvmIdentifierFactory.pointerTo(pointervar)); } - private void addNativeFunction(FunctionDeclaration node, TypeDeclaration returnType) { + private void addNativeFunction(ConcreteFunctionType node, ConcreteType returnType) { List> llvmParameter = buildLLVMParameter(node); String name = nameMangler.mangleFunction(node); codeGenerator.addNativeFunction(contextUtils.active(), returnType, llvmParameter, name); @@ -253,10 +248,10 @@ protected void initializeClosureWrapper(Assignment node, LLVMIdentifier sourc LLVMIdentifier closureTarget = codeGenerator.accessClosureContextMember( contextUtils.active(), - functionWrapper, + (TypeFactory.makeConcrete(functionWrapper, currentContext)), localVar, lvalue, - var.getType(), + currentContext.makeConcrete(var.getType()), (LLVMIdentifier>) source); if (var.getIdentifier().getSymbol().equals("self")) { @@ -270,6 +265,7 @@ protected void initializeClosureWrapper(Assignment node, LLVMIdentifier sourc varAccess.setType(var.getType()); varAccess.setDeclaration(var); varAccess.setParentNode(node.getParentNode()); + varAccess.setScope(node.getScope()); visit(varAccess); } LLVMIdentifier closureSource = stack.pop(); @@ -280,44 +276,39 @@ protected void initializeClosureWrapper(Assignment node, LLVMIdentifier sourc @Override public void visit(ClassDeclaration node) { - if (node instanceof ClassDeclarationVariation) { - codeGenerator.pushClassDeclarationVariation((ClassDeclarationVariation) node); - } - onEnterChildrenEachNode(node); - if (node.getAbstractGenericTypes().isEmpty() || node instanceof ClassDeclarationVariation) { - if (node != CoreClasses.voidType()) { - openNewFunctionScope(); - codeGenerator.buildConstructor(contextUtils.active(), node); - closeFunctionContext(); - } - visitDoubleDispatched(node.getBlock()); - } else { - for (ClassDeclarationVariation variation : node.getVariations()) { - visit(variation); - } - } - onExitChildrenEachNode(node); - if (node instanceof ClassDeclarationVariation) { - codeGenerator.popClassDeclarationVariation(); + //Do nothing + } + + public void visitAllClasses() { + for (ConcreteType variation : ConcreteType.getAllTypes()) { + currentContext = variation.getContext(); + if (!variation.equals(Types.voidType())) { + openNewFunctionScope(); + codeGenerator.buildConstructor(contextUtils.active(), variation); + closeFunctionContext(); + } + visitDoubleDispatched(variation.getBlock()); } } @Override public void visit(VariableDeclaration node) { + ConcreteVariableType variableType = TypeFactory.makeConcrete(node, currentContext); super.visit(node); if (!node.isAttribute()) { + ConcreteType type = currentContext.makeConcrete(node.getType()); if (node.getIsGlobal()) { codeGenerator.declareGlobalVariable( contextUtils.constant(), - nameMangler.mangleVariable(node), - node.getType()); + nameMangler.mangleVariable(variableType), + type); } else if (!(node.getParentNodeByType(FunctionDeclaration.class) instanceof GeneratorFunctionDeclaration)) { // only do sth. if the enclosing function is not a generator function. // if it is, the declaration is already made somewhere else... codeGenerator.declareLocalVariable( contextUtils.active(), - nameMangler.mangleVariable(node), - node.getType()); + nameMangler.mangleVariable(variableType), + type); } } } @@ -328,37 +319,36 @@ public void visit(VariableAccess node) { VariableDeclaration varDeclaration = (VariableDeclaration) node.getDeclaration(); - TypeDeclaration type = node.getType(); - if (type instanceof ClassDeclaration) { - type = codeGenerator.mapAbstractGenericToConcreteIfApplicable((ClassDeclaration) type); - } + ConcreteVariableType variableType = TypeFactory.makeConcrete(varDeclaration, currentContext.extend(node.getScope().getContext())); + + ConcreteType type = currentContext.makeConcrete(node.getType()); FunctionDeclaration functionParent = - (FunctionDeclaration) varDeclaration.getParentNodeByType(FunctionDeclaration.class); + varDeclaration.getParentNodeByType(FunctionDeclaration.class); GeneratorFunctionDeclaration generatorParent = null; if (functionParent instanceof GeneratorFunctionDeclaration) { generatorParent = - (GeneratorFunctionDeclaration) varDeclaration.getParentNodeByType(GeneratorFunctionDeclaration.class); + varDeclaration.getParentNodeByType(GeneratorFunctionDeclaration.class); } LLVMIdentifier llvmIdentifier; if (varDeclaration.getIsGlobal()) { - llvmIdentifier = codeGenerator.resolveGlobalVarName(nameMangler.mangleVariable(varDeclaration), type); + llvmIdentifier = codeGenerator.resolveGlobalVarName(nameMangler.mangleVariable(variableType), type); } else if (generatorParent != null) { llvmIdentifier = codeGenerator.accessContextMember( contextUtils.active(), - (ClassDeclaration) useClassVariationIfApplicable(generatorParent.getDefiningClass()), + TypeFactory.makeConcrete(generatorParent.getDefiningClass(), currentContext), varDeclaration, node, type); } else if (node.isClosureVariable()) { ClassDeclaration containingClass = - ((FunctionDeclaration) node.getParentNodeByType(FunctionDeclaration.class)).getWrapperClass(); + node.getParentNodeByType(FunctionDeclaration.class).getWrapperClass(); llvmIdentifier = codeGenerator.accessClosureContextMember( contextUtils.active(), - containingClass, + (TypeFactory.makeConcrete(containingClass, currentContext)), varDeclaration, node, type); @@ -374,30 +364,18 @@ public void visit(VariableAccess node) { } else { llvmIdentifier = codeGenerator.resolveLocalVarName( - nameMangler.mangleVariable(varDeclaration), + nameMangler.mangleVariable(variableType), type, !varDeclaration.isParameter()); } stack.push(llvmIdentifier); } - /** this method finds out whether the given class is a generic class. If yes, it is replaced by its equivalent - * ClassDeclarationVariation. - * - * @param type - * @return */ - private TypeDeclaration useClassVariationIfApplicable(TypeDeclaration type) { - if ((!(type instanceof ClassDeclarationVariation)) && (type instanceof ClassDeclaration) - && (!((ClassDeclaration) type).getAbstractGenericTypes().isEmpty())) { - return codeGenerator.mapAbstractGenericToConcreteIfApplicable((ClassDeclaration) type); - } - return type; - } - @SuppressWarnings("unchecked") @Override public void visit(SelfExpression node) { - TypeDeclaration type = useClassVariationIfApplicable(node.getType()); + Type type = node.getType(); + ConcreteType concreteType = currentContext.makeConcrete(type); // if 'self' is used inside a closure, we can not use the usual 'self' if (node.isInClosure()) { FunctionDeclaration funDecl = (FunctionDeclaration) node.getParentNodeByType(FunctionDeclaration.class); @@ -406,26 +384,30 @@ public void visit(SelfExpression node) { stack.push(codeGenerator.accessClosureContextMember( contextUtils.active(), - containingClass, - funDecl.getClosureVariable(new VariableDeclaration(new Position(), new Identifier("self"), type, + (TypeFactory.makeConcrete(containingClass, currentContext)), + funDecl.getClosureVariable(new VariableDeclaration(new Position(), new Identifier("self"), concreteType, VariableDeclaration.DeclarationType.VARIABLE)), lvalue, - type)); + concreteType)); } else { - stack.push(codeGenerator.resolveLocalVarName("self", type, false)); + LLVMIdentifier self = codeGenerator.resolveLocalVarName("self", concreteType, false); + stack.push(self); } } @SuppressWarnings("unchecked") @Override public void visit(ParentExpression node) { - LLVMIdentifier self = codeGenerator.resolveLocalVarName("self", node.getSelfType(), false); + ConcreteType selfType = currentContext.makeConcrete(node.getSelfType()); + ConcreteType resultType = currentContext.makeConcrete(node.getType()); + + LLVMIdentifier self = codeGenerator.resolveLocalVarName("self", selfType, false); LLVMIdentifier result = codeGenerator.castClass( contextUtils.active(), (LLVMIdentifier>) self, - node.getSelfType(), - (ClassDeclaration) node.getType(), + selfType, + resultType, codeGenerator.createLabelPrefix("cast", node)); stack.push((LLVMIdentifier) result); } @@ -436,20 +418,21 @@ public void visit(CastExpression node) { super.visit(node); LLVMIdentifier object = stack.pop(); LLVMIdentifier result; + ConcreteType resultType = currentContext.makeConcrete(node.getType()); + ConcreteType sourceType = currentContext.makeConcrete(node.getExpression().getType()); if (node.isUnchecked()) { result = codeGenerator.castClassUnchecked( contextUtils.active(), (LLVMIdentifier>) object, - (ClassDeclaration) node.getExpression().getType(), - (ClassDeclaration) node.getType()); + resultType); } else { result = codeGenerator.castClass( contextUtils.active(), (LLVMIdentifier>) object, - (ClassDeclaration) node.getExpression().getType(), - (ClassDeclaration) node.getType(), + sourceType, + resultType, codeGenerator.createLabelPrefix("cast", node)); } stack.push((LLVMIdentifier) result); @@ -460,14 +443,16 @@ public void visit(CastExpression node) { public void visit(IsExpression node) { super.visit(node); LLVMIdentifier object = stack.pop(); + ConcreteType resultType = currentContext.makeConcrete(node.getToType()); + ConcreteType sourceType = currentContext.makeConcrete(node.getExpression().getType()); LLVMIdentifier result = codeGenerator.isClass( contextUtils.active(), (LLVMIdentifier>) object, - (ClassDeclaration) node.getExpression().getType(), - (ClassDeclaration) node.getToType()); + sourceType, + resultType); LLVMIdentifier boxedResult = - codeGenerator.boxType(contextUtils.active(), (LLVMIdentifier) result, CoreClasses.boolType()); + codeGenerator.boxType(contextUtils.active(), (LLVMIdentifier) result, Types.boolType()); stack.push(boxedResult); } @@ -481,7 +466,9 @@ public void visit(MemberAccess node) { @Override public void visit(ZeroExpression node) { super.visit(node); - stack.push(llvmIdentifierFactory.constantNull((LLVMPointer) codeGenerator.mapToLLVMType(node.getType()))); + ConcreteType type = currentContext.makeConcrete(node.getType()); + LLVMPointer llvmType = codeGenerator.mapToLLVMType(type); + stack.push(llvmIdentifierFactory.constantNull(llvmType)); } @SuppressWarnings("unchecked") @@ -492,7 +479,7 @@ public void visit(StringLiteral node) { codeGenerator.addConstantString(contextUtils.constant(), node.getValue()); // Boxing CodeContext c = contextUtils.active(); - LLVMIdentifier box = codeGenerator.boxType(c, (LLVMIdentifier) addr, node.getType()); + LLVMIdentifier box = codeGenerator.boxType(c, (LLVMIdentifier) addr, (ConcreteType) node.getType()); stack.push(box); } @@ -503,7 +490,7 @@ public void visit(CharacterLiteral node) { LLVMIdentifier addr = codeGenerator.loadChar(node.getValue()); // Boxing CodeContext c = contextUtils.active(); - LLVMIdentifier box = codeGenerator.boxType(c, (LLVMIdentifier) addr, node.getType()); + LLVMIdentifier box = codeGenerator.boxType(c, (LLVMIdentifier) addr, (ConcreteType) node.getType()); stack.push(box); } @@ -515,7 +502,7 @@ public void visit(IntegerLiteral node) { LLVMIdentifier addr = codeGenerator.loadInt(node.getValue()); // Boxing CodeContext c = contextUtils.active(); - LLVMIdentifier box = codeGenerator.boxType(c, (LLVMIdentifier) addr, node.getType()); + LLVMIdentifier box = codeGenerator.boxType(c, (LLVMIdentifier) addr, (ConcreteType) node.getType()); stack.push(box); } @@ -527,7 +514,7 @@ public void visit(BooleanLiteral node) { LLVMIdentifier addr = codeGenerator.loadBool(node.getValue()); // Boxing CodeContext c = contextUtils.active(); - LLVMIdentifier box = codeGenerator.boxType(c, (LLVMIdentifier) addr, node.getType()); + LLVMIdentifier box = codeGenerator.boxType(c, (LLVMIdentifier) addr, (ConcreteType) node.getType()); stack.push(box); } @@ -539,7 +526,7 @@ public void visit(FloatLiteral node) { LLVMIdentifier addr = codeGenerator.loadFloat(node.getValue()); // Boxing CodeContext c = contextUtils.active(); - LLVMIdentifier box = codeGenerator.boxType(c, (LLVMIdentifier) addr, node.getType()); + LLVMIdentifier box = codeGenerator.boxType(c, (LLVMIdentifier) addr, (ConcreteType) node.getType()); stack.push(box); } @@ -557,7 +544,7 @@ public void visit(ArrayLiteral node) { // Boxing CodeContext c = contextUtils.active(); - LLVMIdentifier box = codeGenerator.boxType(c, (LLVMIdentifier) array, node.getType()); + LLVMIdentifier box = codeGenerator.boxType(c, (LLVMIdentifier) array, currentContext.makeConcrete(node.getType())); stack.push(box); } @@ -604,9 +591,9 @@ public void visit(ConditionalExpression node) { public void visit(FunctionCall node) { super.visit(node); - List expectedParameters = new ArrayList<>(); - for (VariableDeclaration varDeclaration : node.getDeclaration().getParameters()) { - expectedParameters.add(varDeclaration.getType()); + List expectedParameters = new ArrayList<>(); + for (Type paramType : node.getDeclaration().getParameterTypes()) { + expectedParameters.add(currentContext.makeConcrete(paramType)); } List> arguments = new ArrayList<>(node.getArguments().size()); for (int i = 0; i < node.getArguments().size(); i++) { @@ -614,19 +601,19 @@ public void visit(FunctionCall node) { } Collections.reverse(arguments); - FunctionDeclaration declaration = node.getDeclaration(); + ConcreteFunctionType declaration = TypeFactory.makeConcrete(node.getDeclaration(),currentContext); - ClassDeclaration definingClass = - (ClassDeclaration) useClassVariationIfApplicable(declaration.getDefiningClass()); + Type definingClass = declaration.getDefiningClass(); - List treatSpecial = + ConcreteType concreteType = definingClass == null ? null : currentContext.makeConcrete(definingClass); + List treatSpecial = Arrays.asList( - CoreClasses.intType(), - CoreClasses.boolType(), - CoreClasses.floatType(), - CoreClasses.charType(), - CoreClasses.stringType(), - CoreClasses.arrayType()); + Types.intType(), + Types.boolType(), + Types.floatType(), + Types.charType(), + Types.stringType(), + Types.arrayType()); if (declaration.isInitializer() && treatSpecial.contains(definingClass)) { // Instead of calling the initializer of this boxed type with a boxed value as arguments just push the // argument on the stack and return. @@ -635,7 +622,7 @@ public void visit(FunctionCall node) { } if (declaration.isMethod() || declaration.isInitializer()) { - expectedParameters.add(0, definingClass); + expectedParameters.add(0, concreteType); if (declaration.isMethod()) { arguments.add(0, stack.pop()); } else if (declaration.isInitializer()) { @@ -649,13 +636,13 @@ public void visit(FunctionCall node) { arguments.add(0, stack.pop()); } else { LLVMIdentifier selfReference = - codeGenerator.callConstructor(contextUtils.active(), definingClass); + codeGenerator.callConstructor(contextUtils.active(), concreteType); if (!declaration.isDefaultInitializer()) { codeGenerator.callVoid( contextUtils.active(), - nameMangler.mangleFunction(definingClass.getDefaultInitializer()), - Arrays.> asList(selfReference), - Arrays. asList(definingClass)); + nameMangler.mangleFunction(declaration.getDefiningClass().getDefaultInitializer()), + Arrays.asList(selfReference), + Arrays.asList(concreteType)); } arguments.add(0, selfReference); } @@ -664,21 +651,21 @@ Arrays.> asList(selfReference), if (declaration.isClosure()) { // the 'self' of a function wrapper implementation is passed as a context to the actual function - TypeDeclaration ctxType = useClassVariationIfApplicable(declaration.getWrapperClass()); + ConcreteType wrapperClass = declaration.getWrapperClass(); LLVMIdentifier> ctx; // if we're inside the wrapper class' _apply_ method, use "self" as the function's context - if (declaration.getWrapperClass() == node.getParentNodeByType(ClassDeclaration.class)) { - ctx = codeGenerator.resolveLocalVarName("self", ctxType, false); + if (wrapperClass.isAssignableFrom(TypeFactory.from(node.getParentNodeByType(ClassDeclaration.class), wrapperClass.getContext()))) { + ctx = codeGenerator.resolveLocalVarName("self", wrapperClass, false); } else { // if not, use the respective wrapper object ctx = codeGenerator.resolveLocalVarName( nameMangler.mangleVariable(declaration.getWrapperFunctionObjectDeclaration()), - ctxType, + wrapperClass, true); } - expectedParameters.add(0, ctxType); + expectedParameters.add(0, wrapperClass); arguments.add(0, ctx); } @@ -686,7 +673,7 @@ Arrays.> asList(selfReference), if (declaration.isFunction()) { stack.push((LLVMIdentifier) codeGenerator.callMethod( contextUtils.active(), - declaration, + declaration, arguments, expectedParameters)); } else { @@ -697,7 +684,7 @@ Arrays.> asList(selfReference), stack.push((LLVMIdentifier) codeGenerator.call( contextUtils.active(), nameMangler.mangleFunction(declaration), - node.getType(), + currentContext.makeConcrete(node.getType()), arguments, expectedParameters)); } else { @@ -715,20 +702,18 @@ Arrays.> asList(selfReference), @Override public void visit(FunctionDeclaration node) { - TypeDeclaration returnType = node.getReturnType(); - if (returnType instanceof ClassDeclaration) { - codeGenerator.mapAbstractGenericToConcreteIfApplicable((ClassDeclaration) returnType); - } + ConcreteType returnType = currentContext.makeConcrete(node.getReturnType()); + ConcreteFunctionType functionType = TypeFactory.makeConcrete(node, currentContext); if (node.isAbstract()) { openNewFunctionScope(); - if ((returnType == null) || (returnType == CoreClasses.voidType())) { - addFunction(node, CoreClasses.voidType()); + if ((returnType == null) || (returnType.isVoid())) { + addFunction(functionType, Types.voidType()); codeGenerator.returnValue( contextUtils.active(), (LLVMIdentifier) (LLVMIdentifier) llvmIdentifierFactory.voidId(), - CoreClasses.voidType()); + Types.voidType()); } else { - addFunction(node, returnType); + addFunction(functionType, returnType); codeGenerator.returnValue( contextUtils.active(), (LLVMIdentifier) (LLVMIdentifier) llvmIdentifierFactory.constantNull((LLVMPointer) codeGenerator.mapToLLVMType(returnType)), @@ -739,28 +724,28 @@ public void visit(FunctionDeclaration node) { if (node.isFunction()) { openNewFunctionScope(); if (node.isNative()) { - addNativeFunction(node, returnType); + addNativeFunction(functionType, returnType); } else { - addFunction(node, returnType); + addFunction(functionType, returnType); visitDoubleDispatched(node.getBody()); } closeFunctionContext(); } else { openNewFunctionScope(); if (node.isNative() && !node.isInitializer()) { - addNativeFunction(node, returnType); + addNativeFunction(functionType, returnType); } else { - addFunction(node, returnType); + addFunction(functionType, returnType); visitDoubleDispatched(node.getBody()); if (node.isInitializer()) { if (node.getDefiningClass().isGenerator()) { - setGeneratorLabel(node.getDefiningClass(), "startGenerator"); + setGeneratorLabel((TypeFactory.makeConcrete(node.getDefiningClass(), currentContext)) , "startGenerator"); } codeGenerator.returnValue( contextUtils.active(), (LLVMIdentifier) (LLVMIdentifier) llvmIdentifierFactory.voidId(), - CoreClasses.voidType()); + Types.voidType()); } } closeFunctionContext(); @@ -773,24 +758,22 @@ public void visit(ReturnStatement node) { super.visit(node); // if we have a yield statement here, we have to set the generator jump destination to this label if (node instanceof YieldStatement) { - setGeneratorLabel((ClassDeclaration) node.getParentNodeByType(ClassDeclaration.class), "yield" + ClassDeclaration parentClass = node.getParentNodeByType(ClassDeclaration.class); + setGeneratorLabel((TypeFactory.makeConcrete(parentClass, currentContext)), "yield" + ((YieldStatement) node).getYieldStatementIndex()); } if (node.getParameter() != null) { ASTNode parent = node.getParentNodeByType(FunctionDeclaration.class); - LLVMIdentifier returnValue = stack.pop(); - TypeDeclaration returnType = ((FunctionDeclaration) parent).getReturnType(); - if (returnType instanceof ClassDeclaration) { - returnType = codeGenerator.mapAbstractGenericToConcreteIfApplicable((ClassDeclaration) returnType); - } + ConcreteType returnType = currentContext.makeConcrete(((FunctionDeclaration) parent).getReturnType()); + LLVMIdentifier returnValue = stack.pop(); codeGenerator.returnValue(contextUtils.active(), returnValue, returnType); } else { codeGenerator.returnValue( contextUtils.active(), (LLVMIdentifier) (LLVMIdentifier) llvmIdentifierFactory.voidId(), - CoreClasses.voidType()); + Types.voidType()); } // if we have a yield statement here, we have to add a label to jump to if (node instanceof YieldStatement) { diff --git a/src/main/java/de/uni/bremen/monty/moco/visitor/DeclarationVisitor.java b/src/main/java/de/uni/bremen/monty/moco/visitor/DeclarationVisitor.java index 2e7936f..fb6792c 100644 --- a/src/main/java/de/uni/bremen/monty/moco/visitor/DeclarationVisitor.java +++ b/src/main/java/de/uni/bremen/monty/moco/visitor/DeclarationVisitor.java @@ -49,12 +49,11 @@ import de.uni.bremen.monty.moco.ast.expression.MemberAccess; import de.uni.bremen.monty.moco.ast.expression.SelfExpression; import de.uni.bremen.monty.moco.ast.statement.Statement; +import de.uni.bremen.monty.moco.ast.types.TypeContext; +import de.uni.bremen.monty.moco.ast.types.Type; import de.uni.bremen.monty.moco.exception.InvalidPlaceToDeclareException; -import sun.reflect.generics.tree.ReturnType; import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; /** This visitor must traverse the entire AST, set up scopes and define declarations. *

@@ -94,10 +93,10 @@ public void visit(ClassDeclaration node) { Block classBlock = node.getBlock(); currentScope.define(node); - currentScope = new ClassScope(currentScope); + currentScope = new ClassScope(currentScope, TypeContext.EMPTY); - for (AbstractGenericType abstractGenericType : node.getAbstractGenericTypes()) { - currentScope.define(abstractGenericType); + for (TypeParameterDeclaration typeParameterDeclaration : node.getTypeParameterDeclarations()) { + currentScope.define(typeParameterDeclaration); } if (node != CoreClasses.voidType()) { @@ -147,7 +146,7 @@ public void visit(Block node) { boolean backToParentScope = false; if (node.getParentNode() instanceof ClassDeclaration) { - currentScope = new ClassScope(currentScope); + currentScope = new ClassScope(currentScope, TypeContext.EMPTY); backToParentScope = true; } else if (!(node.getParentNode() instanceof ModuleDeclaration)) { currentScope = new Scope(currentScope); @@ -171,7 +170,7 @@ private FunctionDeclaration buildDefaultInitializer(ClassDeclaration node) { FunctionDeclaration initializer = new FunctionDeclaration(node.getPosition(), new Identifier(node.getIdentifier().getSymbol() + "_definit"), new Block(node.getPosition()), new ArrayList(), - FunctionDeclaration.DeclarationType.DEFAULT_INITIALIZER, (TypeDeclaration) null, false); + FunctionDeclaration.DeclarationType.DEFAULT_INITIALIZER, (Type) null, false); initializer.setParentNode(node.getBlock()); Block initializerBlock = initializer.getBody(); initializerBlock.setParentNode(initializer); diff --git a/src/main/java/de/uni/bremen/monty/moco/visitor/PrintVisitor.java b/src/main/java/de/uni/bremen/monty/moco/visitor/PrintVisitor.java index 844d265..0c032fc 100644 --- a/src/main/java/de/uni/bremen/monty/moco/visitor/PrintVisitor.java +++ b/src/main/java/de/uni/bremen/monty/moco/visitor/PrintVisitor.java @@ -47,6 +47,7 @@ import de.uni.bremen.monty.moco.ast.expression.literal.IntegerLiteral; import de.uni.bremen.monty.moco.ast.expression.literal.StringLiteral; import de.uni.bremen.monty.moco.ast.statement.Assignment; +import de.uni.bremen.monty.moco.ast.types.Type; /** This visitor traverses the AST and prints useful information to stdout. */ public class PrintVisitor extends BaseVisitor { @@ -75,8 +76,8 @@ public void visit(VariableDeclaration node) { public void visit(FunctionCall node) { printIndent("Symbol: " + node.getIdentifier()); String parameters = ""; - for (VariableDeclaration parameter : node.getDeclaration().getParameters()) { - parameters += parameter.getTypeIdentifier() + " " + parameter.getIdentifier() + ", "; + for (Type parameter : node.getDeclaration().getParameterTypes()) { + parameters += parameter.getIdentifier() + ", "; } printIndent("Parameters: (" + parameters + ")"); } diff --git a/src/main/java/de/uni/bremen/monty/moco/visitor/ResolveVisitor.java b/src/main/java/de/uni/bremen/monty/moco/visitor/ResolveVisitor.java index 882c847..eb2559d 100644 --- a/src/main/java/de/uni/bremen/monty/moco/visitor/ResolveVisitor.java +++ b/src/main/java/de/uni/bremen/monty/moco/visitor/ResolveVisitor.java @@ -46,12 +46,16 @@ import de.uni.bremen.monty.moco.ast.statement.Statement; import de.uni.bremen.monty.moco.ast.statement.UnpackAssignment; import de.uni.bremen.monty.moco.ast.statement.YieldStatement; +import de.uni.bremen.monty.moco.ast.types.*; import de.uni.bremen.monty.moco.exception.*; import de.uni.bremen.monty.moco.util.OverloadCandidate; -import de.uni.bremen.monty.moco.util.TupleDeclarationFactory; import java.util.ArrayList; +import java.util.Collections; import java.util.List; +import java.util.Optional; +import java.util.stream.Collectors; +import java.util.Arrays; /** This visitor must traverse the entire AST and resolve variables and types. */ public class ResolveVisitor extends VisitOnceVisitor { @@ -69,60 +73,22 @@ public ResolveVisitor() { /** {@inheritDoc} */ @Override public void visit(ClassDeclaration node) { - ClassScope scope = (ClassScope) node.getScope(); - List superClasses = node.getSuperClassDeclarations(); + ClassScope scope = node.getScope(); + List superClasses = node.getSuperClassDeclarations(); for (ResolvableIdentifier identifier : node.getSuperClassIdentifiers()) { - TypeDeclaration type = scope.resolveType(identifier); + PartialAppliedTypeInfo type = (PartialAppliedTypeInfo) scope.resolveType(identifier, this); superClasses.add(type); - if (type instanceof ClassDeclaration) { - scope.addParentClassScope((ClassScope) type.getScope()); - } + scope.addParentClassScope(type.getScope()); } super.visit(node); - - setVMT(node, superClasses); } - private void setVMT(ClassDeclaration node, List superClasses) { - int attributeIndex = 1; - List virtualMethodTable = node.getVirtualMethodTable(); - // This can only deal with single inheritance! - if (!superClasses.isEmpty()) { - TypeDeclaration type = superClasses.get(0); - if (type instanceof ClassDeclaration) { - ClassDeclaration clazz = (ClassDeclaration) type; - attributeIndex = clazz.getLastAttributeIndex(); - virtualMethodTable.addAll(clazz.getVirtualMethodTable()); - } - } - - // Make room for the ctable pointer - int vmtIndex = virtualMethodTable.size() + 1; - - for (Declaration decl : node.getBlock().getDeclarations()) { - if (decl instanceof VariableDeclaration) { - VariableDeclaration varDecl = (VariableDeclaration) decl; - varDecl.setAttributeIndex(attributeIndex++); - } else if (decl instanceof FunctionDeclaration) { - FunctionDeclaration procDecl = (FunctionDeclaration) decl; - if (!procDecl.isInitializer()) { - boolean foundEntry = false; - for (int i = 0; !foundEntry && i < virtualMethodTable.size(); i++) { - FunctionDeclaration vmtEntry = virtualMethodTable.get(i); - if (procDecl.overridesFunction(vmtEntry)) { - virtualMethodTable.set(i, procDecl); - procDecl.setVMTIndex(vmtEntry.getVMTIndex()); - foundEntry = true; - } - } - if (!foundEntry) { - virtualMethodTable.add(procDecl); - procDecl.setVMTIndex(vmtIndex++); - } - } - } - } - node.setLastAttributeIndex(attributeIndex); + /** {@inheritDoc} */ + @Override + public void visit(TypeParameterDeclaration node) { + ResolvableIdentifier upperTypeBound = node.getUpperTypeBoundIdentifier(); + Type type = node.getScope().resolveType(upperTypeBound, this); + node.setUpperTypeBound(type); } /** {@inheritDoc} */ @@ -130,15 +96,17 @@ private void setVMT(ClassDeclaration node, List superClasses) { public void visit(VariableDeclaration node) { super.visit(node); Scope scope = node.getScope(); - TypeDeclaration type; - if (node.typeMustBeInferred()) { - Expression inferred = node.getExpressionToInferType(); - visitDoubleDispatched(inferred); - type = inferred.getType(); - } else { - type = scope.resolveType(node.getTypeIdentifier()); + if(node.getType()== null) { + Type type; + if (node.typeMustBeInferred()) { + Expression inferred = node.getExpressionToInferType(); + visitDoubleDispatched(inferred); + type = inferred.getType(); + } else { + type = scope.resolveType(node.getTypeIdentifier(), this); + } + node.setType(type); } - node.setType(type); // variable declarations in a generator must be registered ASTNode generatorFun = node.getParentNodeByType(FunctionDeclaration.class); @@ -156,6 +124,7 @@ public void visit(VariableAccess node) { Scope scope = node.getScope(); // if the variable access is casted into something else, right away... if (node.getParentNode() instanceof CastExpression) { + visitDoubleDispatched(node.getParentNode()); declaration = overloadResolutionForVariableAccess(node); } if (declaration == null) { @@ -169,7 +138,7 @@ public void visit(VariableAccess node) { resolveClosureVariables(node, variable); visitDoubleDispatched(variable); - node.setType(variable.getType()); + node.setType(variable.getType().extend(scope.getContext())); if (!(scope instanceof ClassScope) && findEnclosingClass(node) == CoreClasses.voidType()) { if (node.getDeclaration() == null || node.getDeclaration().getPosition().getLineNumber() > node.getPosition().getLineNumber()) { @@ -214,38 +183,36 @@ protected void resolveClosureVariablesForSelf(SelfExpression self) { * @return */ protected Declaration overloadResolutionForVariableAccess(VariableAccess node) { CastExpression cast = (CastExpression) node.getParentNode(); - // if the cast type is inferred, we can not resolve this one - if (cast.getCastIdentifier() == null) { - return null; - } + Type castedTo = cast.getType(); - TypeDeclaration castedTo = cast.getScope().resolveType(cast.getCastIdentifier()); - Declaration declaration = null; - if (castedTo.matchesType(CoreClasses.functionType())) { + if(castedTo.isFunction()){ + if(!(castedTo instanceof ConcreteType)){ + throw new RuntimeException(); + } + ConcreteType functionType = (ConcreteType) castedTo; + ConcreteType param = functionType.getConcreteGenericTypes().get(0); - ClassDeclaration paramType = ((ClassDeclarationVariation) castedTo).getConcreteGenericTypes().get(0); - List params = new ArrayList<>(); - if (TupleDeclarationFactory.isTuple(paramType)) { - params.addAll(((ClassDeclarationVariation) paramType).getConcreteGenericTypes()); + List params; + if(param.isTuple()){ + params = param.getConcreteGenericTypes(); } else { - params.add(paramType); - } - declaration = overloadResolution(params, node.getScope().resolveFunction(node.getIdentifier())); - if (declaration instanceof FunctionDeclaration) { - declaration = ((FunctionDeclaration) declaration).getWrapperFunctionObjectDeclaration(); - } - if (declaration == null) { - throw new UnknownIdentifierException(node, ResolvableIdentifier.convert(node.getIdentifier())); + params = Collections.singletonList(param); } + + List availableFunctions = node.getScope().resolveFunction(node.getIdentifier(), this); + + FunctionType result = overloadResolution(params, availableFunctions); + ConcreteVariableType variableType = (ConcreteVariableType) result.getWrapperFunctionObjectDeclaration(); + return variableType.getDeclaration(); } - return declaration; + return null; } /** {@inheritDoc} */ @Override public void visit(SelfExpression node) { super.visit(node); - node.setType(findEnclosingClass(node)); + node.setType(TypeFactory.from(findEnclosingClass(node), TypeContext.EMPTY)); resolveClosureVariablesForSelf(node); } @@ -253,22 +220,22 @@ public void visit(SelfExpression node) { @Override public void visit(ParentExpression node) { super.visit(node); - node.setType(node.getScope().resolveType(node.getParentIdentifier())); - node.setSelfType(findEnclosingClass(node)); + ResolvableIdentifier parentIdentifier = node.getParentIdentifier(); + node.setType(node.getScope().resolveType(parentIdentifier, this)); + node.setSelfType(TypeFactory.from(findEnclosingClass(node), TypeContext.EMPTY)); } /** {@inheritDoc} */ @Override public void visit(CastExpression node) { - if (node.typeParameterMustBeInferred()) { - node.inferTypeParameter(); - } + Type type; if (node.typeMustBeInferred()) { - visitDoubleDispatched(node.getExpressionToInferFrom()); - node.inferType(); + type = node.inferType(this); + } else { + type = node.getScope().resolveType(node.getCastIdentifier(), this); } + node.setType(type); super.visit(node); - node.setType(node.getScope().resolveType(node.getCastIdentifier())); } /** {@inheritDoc} */ @@ -279,23 +246,23 @@ public void visit(IsExpression node) { visitDoubleDispatched(node.getExpressionToInferFrom()); node.inferType(); } else { - node.setToType(node.getScope().resolveType(node.getIsIdentifier())); + node.setToType(node.getScope().resolveType(node.getIsIdentifier(), this)); } - node.setType(CoreClasses.boolType()); + node.setType(Types.boolType()); } /** {@inheritDoc} */ @Override public void visit(MemberAccess node) { - visitDoubleDispatched(node.getLeft()); - TypeDeclaration leftType = node.getLeft().getType(); + Expression leftExpr = node.getLeft(); + Expression rightExpr = node.getRight(); + visitDoubleDispatched(leftExpr); + Type leftType = leftExpr.getType(); - if (leftType instanceof ClassDeclaration) { - node.getRight().setScope(leftType.getScope()); - } - visitDoubleDispatched(node.getRight()); + rightExpr.setScope(leftType.getScope()); + visitDoubleDispatched(rightExpr); - TypeDeclaration type = node.getRight().getType(); + Type type = rightExpr.getType(); node.setType(type); } @@ -310,50 +277,69 @@ public void visit(ConditionalExpression node) { @Override public void visit(ZeroExpression node) { Scope scope = node.getScope(); - node.setType(scope.resolveType(node.getIdentifier())); + node.setType(scope.resolveType(node.getIdentifier(), this)); super.visit(node); } /** {@inheritDoc} */ @Override public void visit(IntegerLiteral node) { - node.setType(CoreClasses.intType()); + node.setType(Types.intType()); super.visit(node); } /** {@inheritDoc} */ @Override public void visit(FloatLiteral node) { - node.setType(CoreClasses.floatType()); + node.setType(Types.floatType()); super.visit(node); } /** {@inheritDoc} */ @Override public void visit(CharacterLiteral node) { - node.setType(CoreClasses.charType()); + node.setType(Types.charType()); super.visit(node); } /** {@inheritDoc} */ @Override public void visit(StringLiteral node) { - node.setType(CoreClasses.stringType()); + node.setType(Types.stringType()); super.visit(node); } /** {@inheritDoc} */ @Override public void visit(BooleanLiteral node) { - node.setType(CoreClasses.boolType()); + node.setType(Types.boolType()); super.visit(node); } /** {@inheritDoc} */ @Override public void visit(ArrayLiteral node) { - node.setType(CoreClasses.arrayType()); super.visit(node); + Type genericType; + if(node.getEntries().isEmpty()){ + Type arrayType = Types.objectType(); //Should be the Bottom type + genericType = arrayType; + } else { + Type firstType = node.getEntries().get(0).getType(); + for (Expression expression : node.getEntries()) { + if (!expression.getType().matchesTypeExactly(firstType)) { + throw new RuntimeException("All Types of an Array must be the same"); + } + } + genericType = firstType; + } + ResolvableIdentifier genericTypeIdentifier = ((ConcreteType)genericType).getResolvableIdentifier(); + ConcreteType arrayType = (ConcreteType) node.getScope().resolveType(new ResolvableIdentifier("Array", Arrays.asList(genericTypeIdentifier)), this); + FunctionCall parentNode = (FunctionCall) node.getParentNode(); + parentNode.setType(arrayType); + parentNode.getIdentifier().getGenericTypes().set(0,genericTypeIdentifier); + node.setType(Types.arrayType()); + } /** {@inheritDoc} */ @@ -380,14 +366,14 @@ public void visit(FunctionDeclaration node) { super.visit(node); Statement returnStatement = node.getBody().getStatements().get(node.getBody().getStatements().size() - 1); if (returnStatement instanceof ReturnStatement) { - node.setInferredReturnType(((ReturnStatement) returnStatement).getParameter().getType()); + node.setInferredReturnType(((ReturnStatement) returnStatement).getParameter().getType(), this); } else { throw new MontyBaseException(node, "can not infer return type!"); } } else { if (node.isFunction()) { Scope scope = node.getScope(); - TypeDeclaration returnType = scope.resolveType(node.getReturnTypeIdentifier()); + Type returnType = scope.resolveType(node.getReturnTypeIdentifier(), this); node.setReturnType(returnType); } else { if (node.isMethod() && node.getIdentifier().getSymbol().equals("initializer")) { @@ -408,63 +394,83 @@ public void visit(FunctionCall node) { } Scope scope = node.getScope(); - Declaration declaration = null; - - declaration = scope.tryToResolveType(node.getIdentifier()); + Optional maybeTypeDeclaration = scope.tryToResolveType(node.getIdentifier(), this); // constructor call - if (declaration instanceof ClassDeclaration) { - ClassDeclaration classDecl = (ClassDeclaration) declaration; + if (maybeTypeDeclaration.isPresent()) { + Type declaration = maybeTypeDeclaration.get(); + if(!(declaration instanceof PartialAppliedTypeInfo)){ + throw new InvalidExpressionException(node, "Type Variables can't be instantiated"); + } + PartialAppliedTypeInfo classDecl = (PartialAppliedTypeInfo) declaration; ResolvableIdentifier identifier = node.getIdentifier(); if (classDecl.isAbstract()) { throw new InvalidExpressionException(node, "The abstract class '" + identifier.toString() + "' must not be instantiated"); } - node.setType(classDecl); - FunctionDeclaration initializer = (FunctionDeclaration) findMatchingInitializer(node, classDecl); + if(node.getType() == null) { + node.setType(classDecl); + } + FunctionType initializer = findMatchingInitializer(node, classDecl); initializer = (initializer != null) ? initializer : classDecl.getDefaultInitializer(); node.setDeclaration(initializer); } else { - List argTypes = new ArrayList<>(node.getArguments().size()); + List argTypes = new ArrayList<>(node.getArguments().size()); for (Expression exp : node.getArguments()) { argTypes.add(exp.getType()); } - Declaration callableDeclaration = overloadResolution(argTypes, scope.resolveFunction(node.getIdentifier())); + List alternatives = scope.resolveFunction(node.getIdentifier(), this); + FunctionType callableDeclaration = overloadResolution(argTypes, alternatives); // if the parameter is just one tuple, we might have to unpack it - if ((callableDeclaration == null) && (argTypes.size() == 1) - && (argTypes.get(0).getIdentifier().getSymbol().startsWith("Tuple"))) { - List argCls = ((ClassDeclarationVariation) argTypes.get(0)).getConcreteGenericTypes(); - argTypes = new ArrayList<>(argCls.size()); - for (ClassDeclaration cls : argCls) { - argTypes.add(cls); + if (callableDeclaration == null) { + if ((argTypes.size() == 1) + && (argTypes.get(0).getIdentifier().getSymbol().startsWith("Tuple"))) { + List argCls = ((ConcreteType)argTypes.get(0)).getConcreteGenericTypes(); + argTypes = new ArrayList<>(argCls.size()); + for (ConcreteType cls : argCls) { + argTypes.add(cls); + } + callableDeclaration = overloadResolution(argTypes, alternatives); + } else { + throw new TypeMismatchException(node, String.format("Could not find matching Function for Identifier \"%s\" with arguments: \"%s\"", node.getIdentifier(), argsAsString(argTypes))); } - callableDeclaration = overloadResolution(argTypes, scope.resolveFunction(node.getIdentifier())); } - if (callableDeclaration instanceof FunctionDeclaration) { - FunctionDeclaration function = (FunctionDeclaration) callableDeclaration; - node.setDeclaration(function); - if (function.isFunction()) { - visitDoubleDispatched(function); - - node.setType(function.getReturnType()); + if (callableDeclaration instanceof FunctionTypeDecl) { + FunctionType functionType = callableDeclaration.extend(scope.getContext()); + node.setDeclaration(functionType); + if (functionType.isFunction()) { + node.setType(functionType.getReturnType()); } else { - node.setType(CoreClasses.voidType()); + node.setType(Types.voidType()); } - } else if (callableDeclaration instanceof VariableDeclaration) { - callVariable(node, callableDeclaration); + } + else if (callableDeclaration instanceof FunctionTypeVariable) { + callVariable(node, (FunctionTypeVariable) callableDeclaration); } else { - throw new TypeMismatchException(node, "Arguments of function call do not match declaration."); + List argsAsString = argsAsString(argTypes); + List> possibleParametersAsString = alternatives.stream().filter(FunctionDeclaration.class::isInstance) + .map(FunctionDeclaration.class::cast).map((functionDeclaration) -> functionDeclaration.getParameters().stream().map(s -> s.getType().getIdentifier().toString()).collect(Collectors.toList())).collect(Collectors.toList()); + throw new TypeMismatchException(node, String.format("Arguments \"%s\" of function call \"%s\" do not match declaration.\nPossible parameters are: \"%s\"", argsAsString, node.getIdentifier(), possibleParametersAsString)); } } } + public List argsAsString(List argTypes) { + return argTypes.stream().map(t -> { + if(t instanceof ConcreteType && ((ConcreteType)t).isFunctionWrapper()){ + return (((ConcreteType)t).getWrappedFunction().getIdentifier()); + } + return t.getIdentifier(); + }).collect(Collectors.toList()); + } + /** this method does the wrapping logic for function objects * * @param node * @param callableDeclaration */ - protected void callVariable(FunctionCall node, Declaration callableDeclaration) { + protected void callVariable(FunctionCall node, FunctionTypeVariable callableDeclaration) { VariableAccess varAccess = new VariableAccess(node.getPosition(), ResolvableIdentifier.convert(callableDeclaration.getIdentifier())); @@ -519,28 +525,14 @@ private ClassDeclaration findEnclosingClass(ASTNode node) { * @param classDeclaration * the class declaration searched for a matching initializer. * @return the matching initializer if one is found for the given function call or null otherwise */ - private Declaration findMatchingInitializer(FunctionCall node, ClassDeclaration classDeclaration) { - - List functions = new ArrayList<>(); - - // iterate through the declarations of the given class - for (Declaration declaration : classDeclaration.getBlock().getDeclarations()) { - // find a matching declaration - if ("initializer".equals(declaration.getIdentifier().getSymbol())) { - // and verify that it is a function... - if (declaration instanceof FunctionDeclaration) { - // without any return type - if (!(((FunctionDeclaration) declaration).isFunction())) { - functions.add(declaration); - } - } - } - } + private FunctionType findMatchingInitializer(FunctionCall node, PartialAppliedTypeInfo classDeclaration) { + + List functions = classDeclaration.getInitializers(this); if (functions.isEmpty()) { return null; } else { - List argTypes = new ArrayList<>(node.getArguments().size()); + List argTypes = new ArrayList<>(node.getArguments().size()); for (Expression exp : node.getArguments()) { argTypes.add(exp.getType()); } @@ -548,27 +540,51 @@ private Declaration findMatchingInitializer(FunctionCall node, ClassDeclaration } } +// /** this one performs the best-fit algorithm, described in the language specification +// * +// * @param arguments +// * @param variables +// * @return */ +// public Declaration overloadResolution(List arguments, List variables) { +// List candidates = new ArrayList<>(); +// for (FunctionType declaration : variables) { +// if (declaration instanceof FunctionDeclaration) { +// handleOverloadedFunction(arguments, declaration, candidates); +// } else if (declaration instanceof VariableDeclaration) { +// handleOverloadedVariable(arguments, declaration, candidates); +// } else { +// throw new RuntimeException("Invalid declaration type for overload resolution: '" +// + declaration.getIdentifier() + "'!"); +// } +// } +// return overloadResolution_(candidates); +// } + /** this one performs the best-fit algorithm, described in the language specification * * @param arguments * @param functions * @return */ - public Declaration overloadResolution(List arguments, List functions) { - List candidates = new ArrayList<>(); - for (Declaration declaration : functions) { - if (declaration instanceof FunctionDeclaration) { - handleOverloadedFunction(arguments, declaration, candidates); - } else if (declaration instanceof VariableDeclaration) { - handleOverloadedVariable(arguments, declaration, candidates); + public FunctionType overloadResolution(List arguments, List functions) { + List> candidates = new ArrayList<>(); + for (FunctionType declaration : functions) { + if (declaration instanceof FunctionTypeDecl) { + handleOverloadedFunction(arguments, (FunctionTypeDecl) declaration, candidates); + } else if (declaration instanceof FunctionTypeVariable) { + handleOverloadedVariable(arguments, (FunctionTypeVariable) declaration, candidates); } else { throw new RuntimeException("Invalid declaration type for overload resolution: '" + declaration.getIdentifier() + "'!"); } } - Declaration result = null; + return overloadResolution_(candidates); + } + + private T overloadResolution_(List> candidates) { + T result = null; // find out the minimum type distance int minScore = Integer.MAX_VALUE; - for (OverloadCandidate candidate : candidates) { + for (OverloadCandidate candidate : candidates) { if (candidate.getScore() < minScore) { minScore = candidate.getScore(); result = candidate.getDeclaration(); @@ -577,41 +593,21 @@ public Declaration overloadResolution(List arguments, List, but not - * ClassDeclarationVariations themself. - * - * @param type - * @return */ - protected ClassDeclarationVariation getClassDeclarationVariationFromTypeDecl(TypeDeclaration type) { - if (type instanceof ClassDeclarationVariation) { - return (ClassDeclarationVariation) type; - } else if (type instanceof ClassDeclaration) { - List superClasses = ((ClassDeclaration) type).getSuperClassDeclarations(); - for (TypeDeclaration decl : superClasses) { - ClassDeclarationVariation result = getClassDeclarationVariationFromTypeDecl(decl); - if (result != null) { - return result; - } - } - } - return null; - } - /** adds 'declaration' to 'candidates' if the signature of it matches 'arguments' * * @param arguments * @param declaration * @param candidates */ - protected void handleOverloadedFunction(List arguments, Declaration declaration, - List candidates) { - FunctionDeclaration funDecl = (FunctionDeclaration) declaration; - if (funDecl.getParameters().size() == arguments.size()) { + protected void handleOverloadedFunction(List arguments, FunctionTypeDecl declaration, + List> candidates) { + if (declaration.getParameter().size() == arguments.size()) { int score = 0; int argIndex = 0; - for (VariableDeclaration param : funDecl.getParameters()) { - visitDoubleDispatched(param); - int typeDist = param.getType().getTypeDist(arguments.get(argIndex)); + for (VariableType param : declaration.getParameter()) { + int typeDist = param. + getType(). + getTypeDist(arguments. + get(argIndex)); if ((typeDist < Integer.MAX_VALUE) && (score < Integer.MAX_VALUE)) { score += typeDist; argIndex++; @@ -621,13 +617,13 @@ protected void handleOverloadedFunction(List arguments, Declara } } if (score != Integer.MAX_VALUE) { - candidates.add(new OverloadCandidate(declaration, score)); + candidates.add(new OverloadCandidate<>(declaration, score)); } // special case for functions without parameters - } else if ((arguments.size() == 0) && (funDecl.getParameters().size() == 1) - && (funDecl.getParameters().get(0).getType() != null) - && (funDecl.getParameters().get(0).getType().getIdentifier().getSymbol().equals("Tuple0"))) { - candidates.add(new OverloadCandidate(declaration, 0)); + } else if ((arguments.size() == 0) && (declaration.getParameter().size() == 1) + && (declaration.getParameter().get(0).getType() != null) + && (declaration.getParameter().get(0).getType().getIdentifier().getSymbol().equals("Tuple0"))) { + candidates.add(new OverloadCandidate<>(declaration, 0)); } } @@ -636,43 +632,31 @@ protected void handleOverloadedFunction(List arguments, Declara * @param arguments * @param declaration * @param candidates */ - protected void handleOverloadedVariable(List arguments, Declaration declaration, - List candidates) { - ClassDeclarationVariation typedecl = - getClassDeclarationVariationFromTypeDecl(((VariableDeclaration) declaration).getType()); - if (typedecl != null) { - if (typedecl.getConcreteGenericTypes().size() == 2) { - ClassDeclaration concreteParamType = typedecl.getConcreteGenericTypes().get(0); - List paramTypes; - if (TupleDeclarationFactory.isTuple(concreteParamType)) { - paramTypes = ((ClassDeclarationVariation) concreteParamType).getConcreteGenericTypes(); + protected void handleOverloadedVariable(List arguments, FunctionTypeVariable declaration, + List> candidates) { + List paramTypes = declaration.getParameterTypes(); + + if (declaration.getParameterTypes().size() == arguments.size()) { + int score = 0; + int argIndex = 0; + for (Type genericType : paramTypes) { + int typeDist = genericType.getTypeDist(arguments.get(argIndex)); + if ((typeDist < Integer.MAX_VALUE) && (score < Integer.MAX_VALUE)) { + score += typeDist; + argIndex++; } else { - paramTypes = new ArrayList<>(1); - paramTypes.add(concreteParamType); - } - if (paramTypes.size() == arguments.size()) { - int score = 0; - int argIndex = 0; - for (ClassDeclaration genericType : paramTypes) { - int typeDist = genericType.getTypeDist(arguments.get(argIndex)); - if ((typeDist < Integer.MAX_VALUE) && (score < Integer.MAX_VALUE)) { - score += typeDist; - argIndex++; - } else { - score = Integer.MAX_VALUE; - break; - } - } - if (score != Integer.MAX_VALUE) { - candidates.add(new OverloadCandidate(declaration, score)); - } - } - // special case for functions without parameters - else if ((arguments.size() == 0) && (paramTypes.size() == 1) - && (paramTypes.get(0).getIdentifier().getSymbol().equals("Tuple0"))) { - candidates.add(new OverloadCandidate(declaration, 0)); + score = Integer.MAX_VALUE; + break; } } + if (score != Integer.MAX_VALUE) { + candidates.add(new OverloadCandidate(declaration, score)); + } + } + // special case for functions without parameters + else if ((arguments.size() == 0) && (paramTypes.size() == 1) + && (paramTypes.get(0).getIdentifier().getSymbol().equals("Tuple0"))) { + candidates.add(new OverloadCandidate(declaration, 0)); } } @@ -682,7 +666,7 @@ public void visit(ReturnStatement node) { super.visit(node); if (node instanceof YieldStatement) { - FunctionDeclaration parentNode = (FunctionDeclaration) node.getParentNodeByType(FunctionDeclaration.class); + FunctionDeclaration parentNode = node.getParentNodeByType(FunctionDeclaration.class); if (parentNode instanceof GeneratorFunctionDeclaration) { ((GeneratorFunctionDeclaration) parentNode).addYieldStatement((YieldStatement) node); } diff --git a/src/main/java/de/uni/bremen/monty/moco/visitor/TypeCheckVisitor.java b/src/main/java/de/uni/bremen/monty/moco/visitor/TypeCheckVisitor.java index 52c7f42..592ab65 100644 --- a/src/main/java/de/uni/bremen/monty/moco/visitor/TypeCheckVisitor.java +++ b/src/main/java/de/uni/bremen/monty/moco/visitor/TypeCheckVisitor.java @@ -39,14 +39,15 @@ package de.uni.bremen.monty.moco.visitor; import de.uni.bremen.monty.moco.ast.ASTNode; -import de.uni.bremen.monty.moco.ast.Block; -import de.uni.bremen.monty.moco.ast.CoreClasses; import de.uni.bremen.monty.moco.ast.declaration.*; import de.uni.bremen.monty.moco.ast.expression.*; import de.uni.bremen.monty.moco.ast.expression.literal.ArrayLiteral; import de.uni.bremen.monty.moco.ast.statement.Assignment; import de.uni.bremen.monty.moco.ast.statement.ConditionalStatement; import de.uni.bremen.monty.moco.ast.statement.ReturnStatement; +import de.uni.bremen.monty.moco.ast.types.FunctionType; +import de.uni.bremen.monty.moco.ast.types.Type; +import de.uni.bremen.monty.moco.ast.types.Types; import de.uni.bremen.monty.moco.exception.InvalidExpressionException; import de.uni.bremen.monty.moco.exception.InvalidPlaceToDeclareException; import de.uni.bremen.monty.moco.exception.TypeMismatchException; @@ -61,13 +62,6 @@ public class TypeCheckVisitor extends BaseVisitor { /** {@inheritDoc} */ @Override public void visit(ClassDeclaration node) { - // go through all direct parent classes (indirect classes are not considered, though) - for (TypeDeclaration type : node.getSuperClassDeclarations()) { - if (!(type instanceof ClassDeclaration)) { - throw new TypeMismatchException(node, String.format("Declaration of superclass is not a class.")); - } - } - if (!node.isAbstract()) { // go through all methods and ensure that there remains no abstract one // (i.e. all abstract ones are overridden) @@ -109,7 +103,7 @@ public void visit(VariableAccess node) { @Override public void visit(SelfExpression node) { super.visit(node); - if (node.getType() == CoreClasses.voidType()) { + if (node.getType().isVoid()) { throw new TypeMismatchException(node, "No enclosing class found."); } } @@ -118,7 +112,7 @@ public void visit(SelfExpression node) { @Override public void visit(ParentExpression node) { super.visit(node); - if (node.getSelfType() == CoreClasses.voidType()) { + if (node.getSelfType().equals(Types.voidType())) { throw new TypeMismatchException(node, "No enclosing class found."); } if (!node.getSelfType().getSuperClassDeclarations().contains(node.getType())) { @@ -130,11 +124,8 @@ public void visit(ParentExpression node) { @Override public void visit(CastExpression node) { super.visit(node); - TypeDeclaration expressionType = node.getExpression().getType(); - if (!(expressionType instanceof ClassDeclaration)) { - throw new TypeMismatchException(node, "It is not possible to cast something different than a class."); - } - if (!(node.getType().matchesType(expressionType) || expressionType.matchesType(node.getType()))) { + Type expressionType = node.getExpression().getType(); + if (!(node.getType().isAssignableFrom(expressionType) || expressionType.isAssignableFrom(node.getType()))) { throw new TypeMismatchException(node, "Impossible cast"); } } @@ -143,19 +134,13 @@ public void visit(CastExpression node) { @Override public void visit(IsExpression node) { super.visit(node); - if (!(node.getExpression().getType() instanceof ClassDeclaration)) { - throw new TypeMismatchException(node, - "It is not possible to check something different than an instance of a class."); - } } /** {@inheritDoc} */ @Override public void visit(MemberAccess node) { super.visit(node); - if (!(node.getLeft().getType() instanceof ClassDeclaration)) { - throw new TypeMismatchException(node, "Left part is not an instance of a class declaration."); - } else if (node.getLeft() instanceof VariableAccess) { + if (node.getLeft() instanceof VariableAccess) { VariableAccess varAcc = (VariableAccess) node.getLeft(); if (varAcc.getDeclaration() instanceof ClassDeclaration) { throw new TypeMismatchException(node, String.format( @@ -174,11 +159,11 @@ public void visit(MemberAccess node) { @Override public void visit(Assignment node) { super.visit(node); - if (!node.getRight().getType().matchesType(node.getLeft().getType())) { + if (!node.getRight().getType().isAssignableFrom(node.getLeft().getType())) { throw new TypeMismatchException(node, String.format( "%s does not match %s", - node.getRight().getType().getIdentifier().getSymbol(), - node.getLeft().getType().getIdentifier().getSymbol())); + node.getRight().getType(), + node.getLeft().getType())); } if (node.getLeft() instanceof VariableAccess) { ((VariableAccess) node.getLeft()).setLValue(); @@ -196,12 +181,12 @@ public void visit(Assignment node) { @Override public void visit(ConditionalExpression node) { super.visit(node); - if (!node.getThenExpression().getType().matchesType(node.getElseExpression().getType())) { + if (!node.getThenExpression().getType().isAssignableFrom(node.getElseExpression().getType())) { throw new TypeMismatchException(node, String.format( "%s does not match %s", node.getThenExpression().getType().getIdentifier().getSymbol(), node.getElseExpression().getType().getIdentifier().getSymbol())); - } else if (!node.getCondition().getType().matchesType(CoreClasses.boolType())) { + } else if (!node.getCondition().getType().isAssignableFrom(Types.boolType())) { throw new TypeMismatchException(node, String.format( "%s is not a bool type.", node.getThenExpression().getType().getIdentifier().getSymbol())); @@ -213,7 +198,7 @@ public void visit(ConditionalExpression node) { public void visit(ArrayLiteral node) { super.visit(node); for (Expression entry : node.getEntries()) { - if (!entry.getType().matchesType(CoreClasses.objectType())) { + if (!entry.getType().isAssignableFrom(Types.objectType())) { throw new TypeMismatchException(node, "Array entries must be Objects"); } } @@ -223,7 +208,7 @@ public void visit(ArrayLiteral node) { @Override public void visit(ConditionalStatement node) { super.visit(node); - if (!node.getCondition().getType().matchesType(CoreClasses.boolType())) { + if (!node.getCondition().getType().isAssignableFrom(Types.boolType())) { throw new TypeMismatchException(node, String.format("%s is not a bool type.", node.getCondition().getType())); } @@ -233,11 +218,6 @@ public void visit(ConditionalStatement node) { @Override public void visit(FunctionDeclaration node) { super.visit(node); - if (node.isFunction()) { - if (!(node.getReturnType() instanceof ClassDeclaration || node.getReturnType() instanceof AbstractGenericType)) { - throw new TypeMismatchException(node, "Must return a class type."); - } - } if (node.isAbstract()) { ASTNode parent = node.getParentNode(); while (!(parent instanceof ClassDeclaration)) { @@ -245,7 +225,7 @@ public void visit(FunctionDeclaration node) { } if (!((ClassDeclaration) parent).isAbstract()) { throw new InvalidPlaceToDeclareException(node, "Abstract method '" + node.getIdentifier() - + "' declared in non-abstract class '" + ((ClassDeclaration) parent).getIdentifier() + "'!"); + + "' declared in non-abstract class '" + ((ClassDeclaration) parent).getIdentifier() + "'!"); } } } @@ -254,42 +234,36 @@ public void visit(FunctionDeclaration node) { @Override public void visit(FunctionCall node) { super.visit(node); - FunctionDeclaration function = node.getDeclaration(); + FunctionType function = node.getDeclaration(); if (function.isFunction()) { if (function.isInitializer()) { throw new TypeMismatchException(node, "Initializer may not have a return type."); } - if (!node.getType().matchesType(function.getReturnType())) { + if (!node.getType().isAssignableFrom(function.getReturnType().extend(node.getScope().getContext()))) { throw new TypeMismatchException(node, "Returntype of function call does not match declaration."); } } else { - if (!function.isInitializer() && node.getType() != CoreClasses.voidType()) { + if (!function.isInitializer() && !node.getType().isVoid()) { throw new TypeMismatchException(node, "Procedures must not return anything."); } } - boolean callMatchesDeclaration = callMatchesDeclaration(node, function); - - if (!callMatchesDeclaration) { - throw new TypeMismatchException(node, "Arguments of function call do not match declaration."); - } + assertCallMatchesDeclaration(node,function); } - private boolean callMatchesDeclaration(FunctionCall node, FunctionDeclaration function) { + private void assertCallMatchesDeclaration(FunctionCall node, FunctionType function) { boolean callMatchesDeclaration = true; List callParams = node.getArguments(); - List declParams = function.getParameters(); + List declParams = function.getParameterTypes(); if (callParams.size() == declParams.size()) { for (int i = 0; i < callParams.size(); i++) { Expression callParam = callParams.get(i); - VariableDeclaration declParam = declParams.get(i); + Type declType = declParams.get(i); + Type callParamType = callParam.getType(); - TypeDeclaration declType = declParam.getType(); - TypeDeclaration callParamType = callParam.getType(); - - if (!callParamType.matchesType(declType)) { + if (!callParamType.isAssignableFrom(declType)) { callMatchesDeclaration = false; break; } @@ -297,22 +271,24 @@ private boolean callMatchesDeclaration(FunctionCall node, FunctionDeclaration fu } else { callMatchesDeclaration = false; } - return callMatchesDeclaration; + if(!callMatchesDeclaration){ + throw new TypeMismatchException(node, "Arguments of function call do not match declaration."); + } } /** {@inheritDoc} */ @Override public void visit(ReturnStatement node) { super.visit(node); - FunctionDeclaration proc = ((FunctionDeclaration) node.getParentNodeByType(FunctionDeclaration.class)); + FunctionDeclaration proc = node.getParentNodeByType(FunctionDeclaration.class); if (proc.isFunction()) { - if (!(node.getParameter().getType().matchesType(proc.getReturnType()))) { + if (!(node.getParameter().getType().isAssignableFrom(proc.getReturnType()))) { throw new TypeMismatchException(node, String.format( "Expected to return %s, but was %s", proc.getReturnType().getIdentifier(), node.getParameter().getType().getIdentifier())); } - } else if (node.getParameter() != null) { + } else if (node.getParameter() != null && !node.getParameter().getType().isTuple(0)) { throw new TypeMismatchException(node, "Expected to return void."); } } diff --git a/src/main/java/de/uni/bremen/monty/moco/visitor/VMTResolveVisitor.java b/src/main/java/de/uni/bremen/monty/moco/visitor/VMTResolveVisitor.java new file mode 100644 index 0000000..2fada89 --- /dev/null +++ b/src/main/java/de/uni/bremen/monty/moco/visitor/VMTResolveVisitor.java @@ -0,0 +1,113 @@ +/* + * moco, the Monty Compiler + * Copyright (c) 2013-2014, Monty's Coconut, All rights reserved. + * + * This file is part of moco, the Monty Compiler. + * + * moco is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation; either + * version 3.0 of the License, or (at your option) any later version. + * + * moco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * Linking this program and/or its accompanying libraries statically or + * dynamically with other modules is making a combined work based on this + * program. Thus, the terms and conditions of the GNU General Public License + * cover the whole combination. + * + * As a special exception, the copyright holders of moco give + * you permission to link this programm and/or its accompanying libraries + * with independent modules to produce an executable, regardless of the + * license terms of these independent modules, and to copy and distribute the + * resulting executable under terms of your choice, provided that you also meet, + * for each linked independent module, the terms and conditions of the + * license of that module. + * + * An independent module is a module which is not + * derived from or based on this program and/or its accompanying libraries. + * If you modify this library, you may extend this exception to your version of + * the program or library, but you are not obliged to do so. If you do not wish + * to do so, delete this exception statement from your version. + * + * You should have received a copy of the GNU General Public + * License along with this library. + */ +package de.uni.bremen.monty.moco.visitor; + +import de.uni.bremen.monty.moco.ast.ClassScope; +import de.uni.bremen.monty.moco.ast.ResolvableIdentifier; +import de.uni.bremen.monty.moco.ast.declaration.ClassDeclaration; +import de.uni.bremen.monty.moco.ast.declaration.Declaration; +import de.uni.bremen.monty.moco.ast.declaration.FunctionDeclaration; +import de.uni.bremen.monty.moco.ast.declaration.VariableDeclaration; +import de.uni.bremen.monty.moco.ast.types.FunctionType; +import de.uni.bremen.monty.moco.ast.types.PartialAppliedTypeInfo; +import de.uni.bremen.monty.moco.ast.types.TypeContext; +import de.uni.bremen.monty.moco.ast.types.TypeFactory; + +import java.util.List; + +public class VMTResolveVisitor extends VisitOnceVisitor { + + @Override + protected int bit() { + return 2; + } + + /** {@inheritDoc} */ + @Override + public void visit(ClassDeclaration node) { + super.visit(node); + setVMT(node, node.getSuperClassDeclarations()); + } + + private void setVMT(ClassDeclaration node, List superClasses) { + int attributeIndex = 1; + List virtualMethodTable = node.getVirtualMethodTable(); + // This can only deal with single inheritance! + if (!superClasses.isEmpty()) { + PartialAppliedTypeInfo type = superClasses.get(0); + type.visit(this); + if(type.getLastAttributeIndex() == -1) { + throw new RuntimeException("Not initilized"); + } + attributeIndex = type.getLastAttributeIndex(); + virtualMethodTable.addAll(type.getVirtualMethodTable()); + } + + // Make room for the ctable pointer + int vmtIndex = virtualMethodTable.size() + 1; + + for (Declaration decl : node.getBlock().getDeclarations()) { + if (decl instanceof VariableDeclaration) { + VariableDeclaration varDecl = (VariableDeclaration) decl; + varDecl.setAttributeIndex(attributeIndex++); + } else if (decl instanceof FunctionDeclaration) { + FunctionDeclaration procDecl = (FunctionDeclaration) decl; + if (!procDecl.isInitializer()) { + boolean foundEntry = false; + for (int i = 0; !foundEntry && i < virtualMethodTable.size(); i++) { + FunctionDeclaration vmtEntry = virtualMethodTable.get(i); + visitDoubleDispatched(vmtEntry); + TypeContext context = TypeFactory.from(procDecl.getDefiningClass(), TypeContext.EMPTY).getContext(); //TODO try with Empty + FunctionType vmtFunction = TypeFactory.from(vmtEntry, context); + if (procDecl.overridesFunction(vmtFunction)) { + virtualMethodTable.set(i, procDecl); + procDecl.setVMTIndex(vmtEntry.getVMTIndex()); + foundEntry = true; + } + } + if (!foundEntry) { + virtualMethodTable.add(procDecl); + procDecl.setVMTIndex(vmtIndex++); + } + } + } + } + node.setLastAttributeIndex(attributeIndex); + } +} diff --git a/src/main/resources/corelib/Array.monty b/src/main/resources/corelib/Array.monty index f763d6b..ca2c8df 100644 --- a/src/main/resources/corelib/Array.monty +++ b/src/main/resources/corelib/Array.monty @@ -1,12 +1,30 @@ -@native class Array: - + @native initializer(Array a): - pass +@native class NativeArray: + + @native initializer(NativeArray a): + pass - + @native Int length(): - pass + + @native Int length(): + pass - + @native Object get(Int index): - pass + + @native Object get(Int index): + pass - + @native set(Int index, Object element): - pass + + @native set(Int index, Object element): + pass + +class Array: + - NativeArray underlying + + + initializer(Array copy): + self.underlying := copy.underlying + + + initializer(NativeArray underlying): + self.underlying := underlying + + + Int length(): + return self.underlying.length() + + + Type get(Int index): + return self.underlying.get(index) as Type + + + set(Int index, Type element): + self.underlying.set(index,element) \ No newline at end of file diff --git a/src/test/java/de/uni/bremen/monty/moco/CompileFilesBaseTest.java b/src/test/java/de/uni/bremen/monty/moco/CompileFilesBaseTest.java index 4ad9399..17db387 100644 --- a/src/test/java/de/uni/bremen/monty/moco/CompileFilesBaseTest.java +++ b/src/test/java/de/uni/bremen/monty/moco/CompileFilesBaseTest.java @@ -38,17 +38,22 @@ */ package de.uni.bremen.monty.moco; -import de.uni.bremen.monty.moco.util.MultiOutputStream; import org.apache.commons.io.FileUtils; +import org.apache.commons.lang3.StringUtils; +import java.io.ByteArrayOutputStream; import java.io.File; -import java.io.FilenameFilter; -import java.net.URI; +import java.io.IOException; +import java.io.PrintStream; import java.net.URISyntaxException; - import java.util.Arrays; import java.util.Collection; +import static de.uni.bremen.monty.moco.IntegrationTestUtils.*; +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.is; +import static org.hamcrest.Matchers.isEmptyString; + public class CompileFilesBaseTest { protected File file; protected String fileName; @@ -93,4 +98,29 @@ protected static File getLastModifiedMontyFile(String folderPath) throws URISynt return latestModifiedMontyProgram; } + protected void runTest() throws IOException, InterruptedException { + final PrintStream bufferOut = System.out; + final PrintStream bufferErr = System.err; + final ByteArrayOutputStream outStream = setStdout(); + final ByteArrayOutputStream errorStream = setStdErr(file); + + if (inputFileExists(file)) { + System.setProperty("testrun.readFromFile", changeFileExtension(file, ".input")); + } + int statusCode = Main.mainWithStatusCode(new String[]{"-e", "-S", file.getAbsolutePath()}); + + if (outputFileExists(file)) { + assertThat(getOutput(errorStream), is(isEmptyString())); + assertThat(statusCode, is(0)); + assertThat(getOutput(outStream), is(expectedResultFromFile(file))); + } else { + // chop the last char to not contain /n in the string + assertThat(StringUtils.chop(getOutput(errorStream)), is(expectedErrorFromFile(file))); + assertThat(getOutput(outStream), is(isEmptyString())); + } + System.clearProperty("testrun.readFromFile"); + System.setOut(bufferOut); + System.setErr(bufferErr); + } + } diff --git a/src/test/java/de/uni/bremen/monty/moco/CompileLatestTestProgramsTest.java b/src/test/java/de/uni/bremen/monty/moco/CompileLatestTestProgramsTest.java index 87537d2..69a1daf 100644 --- a/src/test/java/de/uni/bremen/monty/moco/CompileLatestTestProgramsTest.java +++ b/src/test/java/de/uni/bremen/monty/moco/CompileLatestTestProgramsTest.java @@ -44,18 +44,11 @@ import org.junit.runner.RunWith; import org.junit.runners.Parameterized; -import java.io.ByteArrayOutputStream; import java.io.File; import java.io.IOException; -import java.io.InputStream; -import java.io.PrintStream; import java.util.Arrays; import java.util.Collection; -import static de.uni.bremen.monty.moco.IntegrationTestUtils.*; -import static org.hamcrest.MatcherAssert.assertThat; -import static org.hamcrest.Matchers.is; -import static org.hamcrest.Matchers.isEmptyString; import static org.junit.runners.Parameterized.Parameters; @Ignore @@ -75,25 +68,6 @@ public static Collection data() throws Exception { @Test public void compileProgramTest() throws IOException, InterruptedException { - final PrintStream bufferOut = System.out; - final PrintStream bufferErr = System.err; - final ByteArrayOutputStream outStream = setStdout(); - final ByteArrayOutputStream errorStream = setStdErr(file); - - if (inputFileExists(file)) { - System.setProperty("testrun.readFromFile", changeFileExtension(file, ".input")); - } - Main.main(new String[] { "-e", file.getAbsolutePath() }); - - if (outputFileExists(file)) { - assertThat(getOutput(errorStream), is(isEmptyString())); - assertThat(getOutput(outStream), is(expectedResultFromFile(file))); - } else { - assertThat(getOutput(errorStream), is(expectedErrorFromFile(file))); - assertThat(getOutput(outStream), is(isEmptyString())); - } - System.clearProperty("testrun.readFromFile"); - System.setOut(bufferOut); - System.setErr(bufferErr); + runTest(); } } diff --git a/src/test/java/de/uni/bremen/monty/moco/CompileTestProgramsTest.java b/src/test/java/de/uni/bremen/monty/moco/CompileTestProgramsTest.java index 17b542d..31affb2 100644 --- a/src/test/java/de/uni/bremen/monty/moco/CompileTestProgramsTest.java +++ b/src/test/java/de/uni/bremen/monty/moco/CompileTestProgramsTest.java @@ -38,22 +38,15 @@ */ package de.uni.bremen.monty.moco; -import static de.uni.bremen.monty.moco.IntegrationTestUtils.*; -import java.io.ByteArrayOutputStream; -import java.io.File; -import java.io.IOException; -import java.io.InputStream; -import java.io.PrintStream; -import java.util.Collection; -import org.apache.commons.lang3.StringUtils; -import static org.hamcrest.MatcherAssert.assertThat; -import static org.hamcrest.Matchers.is; -import static org.hamcrest.Matchers.isEmptyString; import org.junit.Test; import org.junit.runner.RunWith; import org.junit.runners.Parameterized; import org.junit.runners.Parameterized.Parameters; +import java.io.File; +import java.io.IOException; +import java.util.Collection; + @RunWith(Parameterized.class) public class CompileTestProgramsTest extends CompileFilesBaseTest { @@ -70,27 +63,7 @@ public static Collection data() throws Exception { @Test public void compileProgramTest() throws IOException, InterruptedException { - final PrintStream bufferOut = System.out; - final PrintStream bufferErr = System.err; - final ByteArrayOutputStream outStream = setStdout(); - final ByteArrayOutputStream errorStream = setStdErr(file); - - if (inputFileExists(file)) { - System.setProperty("testrun.readFromFile", changeFileExtension(file, ".input")); - } - Main.main(new String[] { "-e", file.getAbsolutePath() }); - - if (outputFileExists(file)) { - assertThat(getOutput(errorStream), is(isEmptyString())); - assertThat(getOutput(outStream), is(expectedResultFromFile(file))); - } else { - // chop the last char to not contain /n in the string - assertThat(StringUtils.chop(getOutput(errorStream)), is(expectedErrorFromFile(file))); - assertThat(getOutput(outStream), is(isEmptyString())); - } - System.clearProperty("testrun.readFromFile"); - System.setOut(bufferOut); - System.setErr(bufferErr); + runTest(); } } diff --git a/src/test/resources/testPrograms/array/ArrayEmptyInit.monty b/src/test/resources/testPrograms/array/ArrayEmptyInit.monty index d072792..f4ac616 100644 --- a/src/test/resources/testPrograms/array/ArrayEmptyInit.monty +++ b/src/test/resources/testPrograms/array/ArrayEmptyInit.monty @@ -4,4 +4,4 @@ // // Expected output: -Array a := [] +Array a := [] diff --git a/src/test/resources/testPrograms/array/ArrayEmptyLength.monty b/src/test/resources/testPrograms/array/ArrayEmptyLength.monty index 1d70fd3..008a0a2 100644 --- a/src/test/resources/testPrograms/array/ArrayEmptyLength.monty +++ b/src/test/resources/testPrograms/array/ArrayEmptyLength.monty @@ -4,5 +4,5 @@ // // Expected output: 0 -Array a := [] +Array a := [] print(a.length()) diff --git a/src/test/resources/testPrograms/array/ArrayEmptyRead.error b/src/test/resources/testPrograms/array/ArrayEmptyRead.error index e69de29..81ec0ac 100644 --- a/src/test/resources/testPrograms/array/ArrayEmptyRead.error +++ b/src/test/resources/testPrograms/array/ArrayEmptyRead.error @@ -0,0 +1 @@ +ResolveVisitor caught error in FunctionCall at file: ArrayEmptyRead.monty, line: 8, char: 0: Could not find matching Function for Identifier "print" with arguments: "[Object]" \ No newline at end of file diff --git a/src/test/resources/testPrograms/array/ArrayEmptyRead.monty b/src/test/resources/testPrograms/array/ArrayEmptyRead.monty index 92d0f10..07994ab 100644 --- a/src/test/resources/testPrograms/array/ArrayEmptyRead.monty +++ b/src/test/resources/testPrograms/array/ArrayEmptyRead.monty @@ -4,5 +4,5 @@ // // Expected error -Array a := [] -print(a.get(0) as Int) +Array a := [] +print(a.get(0)) diff --git a/src/test/resources/testPrograms/array/ArrayEmptyWrite.monty b/src/test/resources/testPrograms/array/ArrayEmptyWrite.monty index 4d40979..28b74e8 100644 --- a/src/test/resources/testPrograms/array/ArrayEmptyWrite.monty +++ b/src/test/resources/testPrograms/array/ArrayEmptyWrite.monty @@ -4,5 +4,5 @@ // // Expected error -Array a := [] +Array a := [] a.set(0, 0) diff --git a/src/test/resources/testPrograms/array/ArrayInGeneric.monty b/src/test/resources/testPrograms/array/ArrayInGeneric.monty new file mode 100644 index 0000000..fb2fbc4 --- /dev/null +++ b/src/test/resources/testPrograms/array/ArrayInGeneric.monty @@ -0,0 +1,3 @@ +case class Wrapper(Array content) + +println(Wrapper([1.1,1.2,1.3]).content.get(1)) \ No newline at end of file diff --git a/src/test/resources/testPrograms/array/ArrayInGeneric.output b/src/test/resources/testPrograms/array/ArrayInGeneric.output new file mode 100644 index 0000000..5625e59 --- /dev/null +++ b/src/test/resources/testPrograms/array/ArrayInGeneric.output @@ -0,0 +1 @@ +1.2 diff --git a/src/test/resources/testPrograms/array/ArrayMany.monty b/src/test/resources/testPrograms/array/ArrayMany.monty index e4e47a4..6fca42a 100644 --- a/src/test/resources/testPrograms/array/ArrayMany.monty +++ b/src/test/resources/testPrograms/array/ArrayMany.monty @@ -4,22 +4,22 @@ // // Expected output: 101112131415202122232425 -Array a := [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15] -print(a.get(10) as Int) -print(a.get(11) as Int) -print(a.get(12) as Int) -print(a.get(13) as Int) -print(a.get(14) as Int) -print(a.get(15) as Int) +Array a := [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15] +print(a.get(10)) +print(a.get(11)) +print(a.get(12)) +print(a.get(13)) +print(a.get(14)) +print(a.get(15)) a.set(10, 20) a.set(11, 21) a.set(12, 22) a.set(13, 23) a.set(14, 24) a.set(15, 25) -print(a.get(10) as Int) -print(a.get(11) as Int) -print(a.get(12) as Int) -print(a.get(13) as Int) -print(a.get(14) as Int) -print(a.get(15) as Int) +print(a.get(10)) +print(a.get(11)) +print(a.get(12)) +print(a.get(13)) +print(a.get(14)) +print(a.get(15)) diff --git a/src/test/resources/testPrograms/array/ArrayManyLength.monty b/src/test/resources/testPrograms/array/ArrayManyLength.monty index 8c8a7cf..2b973d0 100644 --- a/src/test/resources/testPrograms/array/ArrayManyLength.monty +++ b/src/test/resources/testPrograms/array/ArrayManyLength.monty @@ -4,5 +4,5 @@ // // Expected output: 16 -Array a := [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15] +Array a := [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15] print(a.length()) diff --git a/src/test/resources/testPrograms/array/ArrayOne.monty b/src/test/resources/testPrograms/array/ArrayOne.monty index a8fe0f0..26ec64c 100644 --- a/src/test/resources/testPrograms/array/ArrayOne.monty +++ b/src/test/resources/testPrograms/array/ArrayOne.monty @@ -4,7 +4,7 @@ // // Expected output: 010 -Array a := [0] -print(a.get(0) as Int) +Array a := [0] +print(a.get(0)) a.set(0, 10) -print(a.get(0) as Int) +print(a.get(0)) diff --git a/src/test/resources/testPrograms/array/ArrayOneLength.monty b/src/test/resources/testPrograms/array/ArrayOneLength.monty index 8e27a43..d1aa4b9 100644 --- a/src/test/resources/testPrograms/array/ArrayOneLength.monty +++ b/src/test/resources/testPrograms/array/ArrayOneLength.monty @@ -4,5 +4,5 @@ // // Expected output: 1 -Array a := [0] +Array a := [0] print(a.length()) diff --git a/src/test/resources/testPrograms/array/ArrayOutOfBounds1.monty b/src/test/resources/testPrograms/array/ArrayOutOfBounds1.monty index 846f44e..a4efefa 100644 --- a/src/test/resources/testPrograms/array/ArrayOutOfBounds1.monty +++ b/src/test/resources/testPrograms/array/ArrayOutOfBounds1.monty @@ -4,5 +4,5 @@ // // Expected error -Array a := [0, 1] +Array a := [0, 1] print(a.get(-1) as Int) diff --git a/src/test/resources/testPrograms/array/ArrayOutOfBounds2.monty b/src/test/resources/testPrograms/array/ArrayOutOfBounds2.monty index 2a6da46..fa1894c 100644 --- a/src/test/resources/testPrograms/array/ArrayOutOfBounds2.monty +++ b/src/test/resources/testPrograms/array/ArrayOutOfBounds2.monty @@ -4,5 +4,5 @@ // // Expected error -Array a := [0, 1] +Array a := [0, 1] a.set(-1, 42) diff --git a/src/test/resources/testPrograms/array/ArrayOutOfBounds3.monty b/src/test/resources/testPrograms/array/ArrayOutOfBounds3.monty index e801ab5..e649eaf 100644 --- a/src/test/resources/testPrograms/array/ArrayOutOfBounds3.monty +++ b/src/test/resources/testPrograms/array/ArrayOutOfBounds3.monty @@ -4,5 +4,6 @@ // // Expected error -Array a := [0, 1] -print(a.get(42) as Int) +Array a := [0, 1] +print(a.get(42)) + diff --git a/src/test/resources/testPrograms/array/ArrayOutOfBounds4.monty b/src/test/resources/testPrograms/array/ArrayOutOfBounds4.monty index 2f56517..8ea255c 100644 --- a/src/test/resources/testPrograms/array/ArrayOutOfBounds4.monty +++ b/src/test/resources/testPrograms/array/ArrayOutOfBounds4.monty @@ -4,5 +4,5 @@ // // Expected error -Array a := [0, 1] +Array a := [0, 1] a.set(42, 42) diff --git a/src/test/resources/testPrograms/array/ArrayTwo.monty b/src/test/resources/testPrograms/array/ArrayTwo.monty index bbe28aa..30117bf 100644 --- a/src/test/resources/testPrograms/array/ArrayTwo.monty +++ b/src/test/resources/testPrograms/array/ArrayTwo.monty @@ -4,10 +4,10 @@ // // Expected output: 011011 -Array a := [0, 1] -print(a.get(0) as Int) -print(a.get(1) as Int) +Array a := [0, 1] +print(a.get(0)) +print(a.get(1)) a.set(0, 10) a.set(1, 11) -print(a.get(0) as Int) -print(a.get(1) as Int) +print(a.get(0)) +print(a.get(1)) diff --git a/src/test/resources/testPrograms/array/ArrayTwoLength.monty b/src/test/resources/testPrograms/array/ArrayTwoLength.monty index 572250f..cc83ef1 100644 --- a/src/test/resources/testPrograms/array/ArrayTwoLength.monty +++ b/src/test/resources/testPrograms/array/ArrayTwoLength.monty @@ -4,5 +4,5 @@ // // Expected output: 2 -Array a := [0, 1] +Array a := [0, 1] print(a.length()) diff --git a/src/test/resources/testPrograms/array/GenericArray.monty b/src/test/resources/testPrograms/array/GenericArray.monty new file mode 100644 index 0000000..d402562 --- /dev/null +++ b/src/test/resources/testPrograms/array/GenericArray.monty @@ -0,0 +1,4 @@ +case class Wrapper(Content content) + +Array> a := [Wrapper(4)] +println(a.get(0).content) \ No newline at end of file diff --git a/src/test/resources/testPrograms/array/GenericArray.output b/src/test/resources/testPrograms/array/GenericArray.output new file mode 100644 index 0000000..b8626c4 --- /dev/null +++ b/src/test/resources/testPrograms/array/GenericArray.output @@ -0,0 +1 @@ +4 diff --git a/src/test/resources/testPrograms/array/StringArray.monty b/src/test/resources/testPrograms/array/StringArray.monty new file mode 100644 index 0000000..1a1d6c1 --- /dev/null +++ b/src/test/resources/testPrograms/array/StringArray.monty @@ -0,0 +1,13 @@ +Array hw := ["Hallo ", "World"] +Array em := Array(["!"]) + +println(hw.length()) +println(em.length()) + +hw.set(1, "Welt") +String world := hw.get(1) +String e := em.get(0) + +print(hw.get(0)) +print(world) +println(e) \ No newline at end of file diff --git a/src/test/resources/testPrograms/array/StringArray.output b/src/test/resources/testPrograms/array/StringArray.output new file mode 100644 index 0000000..f6d9365 --- /dev/null +++ b/src/test/resources/testPrograms/array/StringArray.output @@ -0,0 +1,3 @@ +2 +1 +Hallo Welt! diff --git a/src/test/resources/testPrograms/classes/constructor/ArrayConstructor.monty b/src/test/resources/testPrograms/classes/constructor/ArrayConstructor.monty index 6066e7c..84b976a 100644 --- a/src/test/resources/testPrograms/classes/constructor/ArrayConstructor.monty +++ b/src/test/resources/testPrograms/classes/constructor/ArrayConstructor.monty @@ -4,5 +4,6 @@ // // Expected output: 0 -Array a := Array([0]) +Array a := Array([0]) print(a.get(0) as Int) + diff --git a/src/test/resources/testPrograms/generics/DependentTypes.monty b/src/test/resources/testPrograms/generics/DependentTypes.monty new file mode 100644 index 0000000..b5d2d85 --- /dev/null +++ b/src/test/resources/testPrograms/generics/DependentTypes.monty @@ -0,0 +1,14 @@ +class Aa: + sayHello(): + println("Hello") + +class Bb inherits Aa: + sayWorld(): + println("World") + +case class Foo(Tt t, Ss s) + +Foo foo := Foo(Bb(),Aa()) +foo.s.sayHello() +foo.t.sayHello() +foo.t.sayWorld() diff --git a/src/test/resources/testPrograms/generics/DependentTypes.output b/src/test/resources/testPrograms/generics/DependentTypes.output new file mode 100644 index 0000000..0092eb7 --- /dev/null +++ b/src/test/resources/testPrograms/generics/DependentTypes.output @@ -0,0 +1,3 @@ +Hello +Hello +World diff --git a/src/test/resources/testPrograms/generics/GenericOperatorOverloading.monty b/src/test/resources/testPrograms/generics/GenericOperatorOverloading.monty new file mode 100644 index 0000000..8fb07bd --- /dev/null +++ b/src/test/resources/testPrograms/generics/GenericOperatorOverloading.monty @@ -0,0 +1,15 @@ +abstract class Number: + abstract Number _add_(Number a) + abstract print() + +case class Integer(Int v) inherits Number: + Number _add_(Number a): + return Integer((a as Integer).v + self.v) + print(): + println(self.v) + +case class Adder(Nn n1, Nn n2): + Number add(): + return self.n1 + self.n2 + +Adder(Integer(1), Integer(2)).add().print() \ No newline at end of file diff --git a/src/test/resources/testPrograms/generics/GenericOperatorOverloading.output b/src/test/resources/testPrograms/generics/GenericOperatorOverloading.output new file mode 100644 index 0000000..00750ed --- /dev/null +++ b/src/test/resources/testPrograms/generics/GenericOperatorOverloading.output @@ -0,0 +1 @@ +3 diff --git a/src/test/resources/testPrograms/generics/GenericSelfParameter.monty b/src/test/resources/testPrograms/generics/GenericSelfParameter.monty new file mode 100644 index 0000000..38c6a58 --- /dev/null +++ b/src/test/resources/testPrograms/generics/GenericSelfParameter.monty @@ -0,0 +1,21 @@ +class Ab: + - Ba b + + initializer(Ba v): + self.b := v + + + Ba getB(): + return self.b + + + Ab getSelf(): + return self + + + setSelfContent(Ab ab): + self.b := ab.getB() + + +Ab x := Ab("Monty!") +x := x.getSelf() +println(x.getB()) + +x.setSelfContent(Ab("Monty!!")) +println(x.getB()) \ No newline at end of file diff --git a/src/test/resources/testPrograms/generics/GenericSelfParameter.output b/src/test/resources/testPrograms/generics/GenericSelfParameter.output new file mode 100644 index 0000000..6b0e4ff --- /dev/null +++ b/src/test/resources/testPrograms/generics/GenericSelfParameter.output @@ -0,0 +1,2 @@ +Monty! +Monty!! diff --git a/src/test/resources/testPrograms/generics/UpperTypeBound.monty b/src/test/resources/testPrograms/generics/UpperTypeBound.monty new file mode 100644 index 0000000..303ef03 --- /dev/null +++ b/src/test/resources/testPrograms/generics/UpperTypeBound.monty @@ -0,0 +1,13 @@ +abstract class Writeable: + + abstract write() + +case class StringWriter(String s) inherits Writeable: + + write(): + println(self.s) + +case class Writers(Wr w): + + write(): + self.w.write() + +StringWriter("Hallo").write() +Writers(StringWriter("World!")).write() \ No newline at end of file diff --git a/src/test/resources/testPrograms/generics/UpperTypeBound.output b/src/test/resources/testPrograms/generics/UpperTypeBound.output new file mode 100644 index 0000000..b80069a --- /dev/null +++ b/src/test/resources/testPrograms/generics/UpperTypeBound.output @@ -0,0 +1,2 @@ +Hallo +World! diff --git a/src/test/resources/testPrograms/generics/genericContainsGeneric.monty b/src/test/resources/testPrograms/generics/genericContainsGeneric.monty index 46019ca..9383b56 100644 --- a/src/test/resources/testPrograms/generics/genericContainsGeneric.monty +++ b/src/test/resources/testPrograms/generics/genericContainsGeneric.monty @@ -10,12 +10,12 @@ // --------------------- // -class Wrapper: - Par value - initializer(Par p): +class Wrapper: + Pas value + initializer(Pas p): self.value := p - Par getValue(): + Pas getValue(): return self.value diff --git a/src/test/resources/testPrograms/inheritance/InheritanceCycle1.error b/src/test/resources/testPrograms/inheritance/InheritanceCycle1.error index 4ac4201..9f9c9f6 100644 --- a/src/test/resources/testPrograms/inheritance/InheritanceCycle1.error +++ b/src/test/resources/testPrograms/inheritance/InheritanceCycle1.error @@ -1 +1 @@ -ResolveVisitor caught error in null: Cyclic dependency detected: ClassA_definit \ No newline at end of file +ResolveVisitor caught error in FunctionCall at file: InheritanceCycle1.monty, line: 7, char: 0: Identifier is not defined: ClassB_definit \ No newline at end of file diff --git a/src/test/resources/testPrograms/inheritance/InheritanceCycle2.error b/src/test/resources/testPrograms/inheritance/InheritanceCycle2.error index ab4135e..9c24195 100644 --- a/src/test/resources/testPrograms/inheritance/InheritanceCycle2.error +++ b/src/test/resources/testPrograms/inheritance/InheritanceCycle2.error @@ -1 +1 @@ -ResolveVisitor caught error in null: Cyclic dependency detected: ClassD_definit \ No newline at end of file +ResolveVisitor caught error in FunctionCall at file: InheritanceCycle2.monty, line: 7, char: 0: Identifier is not defined: ClassE_definit \ No newline at end of file diff --git a/src/test/resources/testPrograms/inheritance/as/ArrayAsObject1.monty b/src/test/resources/testPrograms/inheritance/as/ArrayAsObject1.monty index aededb6..3766060 100644 --- a/src/test/resources/testPrograms/inheritance/as/ArrayAsObject1.monty +++ b/src/test/resources/testPrograms/inheritance/as/ArrayAsObject1.monty @@ -6,5 +6,5 @@ Object a := [1, 0] -print((a as Array).get(0) as Int) -print((a as Array).get(1) as Int) +print((a as Array).get(0) as Int) +print((a as Array).get(1) as Int) diff --git a/src/test/resources/testPrograms/inheritance/as/ArrayAsObject2.monty b/src/test/resources/testPrograms/inheritance/as/ArrayAsObject2.monty index 5b4ab49..2109200 100644 --- a/src/test/resources/testPrograms/inheritance/as/ArrayAsObject2.monty +++ b/src/test/resources/testPrograms/inheritance/as/ArrayAsObject2.monty @@ -6,5 +6,5 @@ Object a := [1, 0] as Object -print((a as Array).get(0) as Int) -print((a as Array).get(1) as Int) +print((a as Array).get(0) as Int) +print((a as Array).get(1) as Int) diff --git a/src/test/resources/testPrograms/inheritance/is/ArrayIsObject.monty b/src/test/resources/testPrograms/inheritance/is/ArrayIsObject.monty index 5a699c0..2621a3f 100644 --- a/src/test/resources/testPrograms/inheritance/is/ArrayIsObject.monty +++ b/src/test/resources/testPrograms/inheritance/is/ArrayIsObject.monty @@ -6,7 +6,7 @@ Object a := [42] -if a is Array: +if a is Array: print("Ok(Array)") else: print("Nope(Array)") diff --git a/src/test/resources/testPrograms/negativ/IdentifierNotDefined.error b/src/test/resources/testPrograms/negativ/IdentifierNotDefined.error index 3f092fe..49be44f 100644 --- a/src/test/resources/testPrograms/negativ/IdentifierNotDefined.error +++ b/src/test/resources/testPrograms/negativ/IdentifierNotDefined.error @@ -1 +1 @@ -ResolveVisitor caught error in null: Identifier is not defined: x \ No newline at end of file +ResolveVisitor caught error in VariableAccess at file: IdentifierNotDefined.monty, line: 7, char: 6: Identifier is not defined: x \ No newline at end of file diff --git a/src/test/resources/testPrograms/negativ/assignment/Assignment1.error b/src/test/resources/testPrograms/negativ/assignment/Assignment1.error new file mode 100644 index 0000000..3d481cd --- /dev/null +++ b/src/test/resources/testPrograms/negativ/assignment/Assignment1.error @@ -0,0 +1 @@ +TypeCheckVisitor caught error in Assignment at file: Assignment1.monty, line: 2, char: 0: Int does not match Bool \ No newline at end of file diff --git a/src/test/resources/testPrograms/negativ/assignment/Assignment1.monty b/src/test/resources/testPrograms/negativ/assignment/Assignment1.monty new file mode 100644 index 0000000..7e2a17a --- /dev/null +++ b/src/test/resources/testPrograms/negativ/assignment/Assignment1.monty @@ -0,0 +1,4 @@ +Int a := 5 +Bool b := a + +println(b) \ No newline at end of file diff --git a/src/test/resources/testPrograms/negativ/callable/neg_Function1.error b/src/test/resources/testPrograms/negativ/callable/neg_Function1.error index 7c3e9bd..4e8ab2f 100644 --- a/src/test/resources/testPrograms/negativ/callable/neg_Function1.error +++ b/src/test/resources/testPrograms/negativ/callable/neg_Function1.error @@ -1 +1 @@ -ResolveVisitor caught error in FunctionCall at file: neg_Function1.monty, line: 10, char: 0: Arguments of function call do not match declaration. \ No newline at end of file +ResolveVisitor caught error in FunctionCall at file: neg_Function1.monty, line: 10, char: 0: Could not find matching Function for Identifier "square" with arguments: "[square]" \ No newline at end of file diff --git a/src/test/resources/testPrograms/negativ/callable/neg_Function1.monty b/src/test/resources/testPrograms/negativ/callable/neg_Function1.monty index 77528c5..72e320d 100644 --- a/src/test/resources/testPrograms/negativ/callable/neg_Function1.monty +++ b/src/test/resources/testPrograms/negativ/callable/neg_Function1.monty @@ -7,4 +7,5 @@ Int square(Int value): return value * value -square(square) \ No newline at end of file +square(square) + diff --git a/src/test/resources/testPrograms/negativ/callable/neg_Function2.error b/src/test/resources/testPrograms/negativ/callable/neg_Function2.error index 4ab72c2..70ea054 100644 --- a/src/test/resources/testPrograms/negativ/callable/neg_Function2.error +++ b/src/test/resources/testPrograms/negativ/callable/neg_Function2.error @@ -1 +1 @@ -ResolveVisitor caught error in null: Type is not defined: Boolean \ No newline at end of file +ResolveVisitor caught error in square:ClassDeclaration at file: neg_Function2.monty, line: 7, char: 0: Type is not defined: Boolean \ No newline at end of file diff --git a/src/test/resources/testPrograms/negativ/callable/neg_Procedure2.error b/src/test/resources/testPrograms/negativ/callable/neg_Procedure2.error index 672c96e..9be1a76 100644 --- a/src/test/resources/testPrograms/negativ/callable/neg_Procedure2.error +++ b/src/test/resources/testPrograms/negativ/callable/neg_Procedure2.error @@ -1 +1 @@ -ResolveVisitor caught error in FunctionCall at file: neg_Procedure2.monty, line: 13, char: 0: Arguments of function call do not match declaration. \ No newline at end of file +ResolveVisitor caught error in FunctionCall at file: neg_Procedure2.monty, line: 13, char: 0: Could not find matching Function for Identifier "print" with arguments: "[__void]" \ No newline at end of file diff --git a/src/test/resources/testPrograms/negativ/classes/AbstractMethodInClass.error b/src/test/resources/testPrograms/negativ/classes/AbstractMethodInClass.error index 7246052..a9d6bf3 100644 --- a/src/test/resources/testPrograms/negativ/classes/AbstractMethodInClass.error +++ b/src/test/resources/testPrograms/negativ/classes/AbstractMethodInClass.error @@ -1 +1 @@ -TypeCheckVisitor caught error in ClassDeclaration at file: AbstractMethodInClass.monty, line: 1, char: 0: The non-abstract class 'Logger' contains an abstract method 'log'! \ No newline at end of file +TypeCheckVisitor caught error in Logger:ClassDeclaration at file: AbstractMethodInClass.monty, line: 1, char: 0: The non-abstract class 'Logger' contains an abstract method 'log'! \ No newline at end of file diff --git a/src/test/resources/testPrograms/negativ/classes/AbstractMethodInheritedInClass.error b/src/test/resources/testPrograms/negativ/classes/AbstractMethodInheritedInClass.error index bf094aa..9e98c5f 100644 --- a/src/test/resources/testPrograms/negativ/classes/AbstractMethodInheritedInClass.error +++ b/src/test/resources/testPrograms/negativ/classes/AbstractMethodInheritedInClass.error @@ -1 +1 @@ -TypeCheckVisitor caught error in ClassDeclaration at file: AbstractMethodInheritedInClass.monty, line: 4, char: 0: The non-abstract class 'StdOutLogger' inherits an abstract method 'log', which has not been implemented! \ No newline at end of file +TypeCheckVisitor caught error in StdOutLogger:ClassDeclaration at file: AbstractMethodInheritedInClass.monty, line: 4, char: 0: The non-abstract class 'StdOutLogger' inherits an abstract method 'log', which has not been implemented! \ No newline at end of file diff --git a/src/test/resources/testPrograms/negativ/functionObject/funAsObj.error b/src/test/resources/testPrograms/negativ/functionObject/funAsObj.error new file mode 100644 index 0000000..c88cf2b --- /dev/null +++ b/src/test/resources/testPrograms/negativ/functionObject/funAsObj.error @@ -0,0 +1 @@ +ResolveVisitor caught error in FunctionCall at file: funAsObj.monty, line: 6, char: 8: Could not find matching Function for Identifier "sq" with arguments: "[Int]" \ No newline at end of file diff --git a/src/test/resources/testPrograms/negativ/functionObject/funAsObj.monty b/src/test/resources/testPrograms/negativ/functionObject/funAsObj.monty new file mode 100644 index 0000000..8d51deb --- /dev/null +++ b/src/test/resources/testPrograms/negativ/functionObject/funAsObj.monty @@ -0,0 +1,6 @@ +Int square(Int x): + return x*x + +(Bool -> Int) sq := square + +println(sq(5)) \ No newline at end of file diff --git a/src/test/resources/testPrograms/negativ/generic/GenericInt.error b/src/test/resources/testPrograms/negativ/generic/GenericInt.error new file mode 100644 index 0000000..81cec8a --- /dev/null +++ b/src/test/resources/testPrograms/negativ/generic/GenericInt.error @@ -0,0 +1 @@ +ResolveVisitor caught error in VariableDeclaration at file: GenericInt.monty, line: 1, char: 0: The class Int has 0 Typeparameters but only 1 were provided \ No newline at end of file diff --git a/src/test/resources/testPrograms/negativ/generic/GenericInt.monty b/src/test/resources/testPrograms/negativ/generic/GenericInt.monty new file mode 100644 index 0000000..cf89dcb --- /dev/null +++ b/src/test/resources/testPrograms/negativ/generic/GenericInt.monty @@ -0,0 +1 @@ +Int i := 4 diff --git a/src/test/resources/testPrograms/negativ/generic/NotCompleteType.error b/src/test/resources/testPrograms/negativ/generic/NotCompleteType.error new file mode 100644 index 0000000..7aa2697 --- /dev/null +++ b/src/test/resources/testPrograms/negativ/generic/NotCompleteType.error @@ -0,0 +1 @@ +ResolveVisitor caught error in FunctionCall at file: NotCompleteType.monty, line: 4, char: 0: The class Tuple has 2 Typeparameters but only 1 were provided \ No newline at end of file diff --git a/src/test/resources/testPrograms/negativ/generic/NotCompleteType.monty b/src/test/resources/testPrograms/negativ/generic/NotCompleteType.monty new file mode 100644 index 0000000..74b5a6d --- /dev/null +++ b/src/test/resources/testPrograms/negativ/generic/NotCompleteType.monty @@ -0,0 +1,5 @@ +class Tuple: + pass + +Tuple() + diff --git a/src/test/resources/testPrograms/negativ/generic/RawType.error b/src/test/resources/testPrograms/negativ/generic/RawType.error new file mode 100644 index 0000000..bce015c --- /dev/null +++ b/src/test/resources/testPrograms/negativ/generic/RawType.error @@ -0,0 +1 @@ +ResolveVisitor caught error in FunctionCall at file: RawType.monty, line: 4, char: 0: The class Tuple has 2 Typeparameters but only 0 were provided \ No newline at end of file diff --git a/src/test/resources/testPrograms/negativ/generic/RawType.monty b/src/test/resources/testPrograms/negativ/generic/RawType.monty new file mode 100644 index 0000000..e00ed2f --- /dev/null +++ b/src/test/resources/testPrograms/negativ/generic/RawType.monty @@ -0,0 +1,5 @@ +class Tuple: + pass + +Tuple() + diff --git a/src/test/resources/testPrograms/negativ/generic/TypParameterInstantiation.error b/src/test/resources/testPrograms/negativ/generic/TypParameterInstantiation.error new file mode 100644 index 0000000..c9294d7 --- /dev/null +++ b/src/test/resources/testPrograms/negativ/generic/TypParameterInstantiation.error @@ -0,0 +1 @@ +ResolveVisitor caught error in FunctionCall at file: TypParameterInstantiation.monty, line: 3, char: 12: Type Variables can't be instantiated \ No newline at end of file diff --git a/src/test/resources/testPrograms/negativ/generic/TypParameterInstantiation.monty b/src/test/resources/testPrograms/negativ/generic/TypParameterInstantiation.monty new file mode 100644 index 0000000..d1c129b --- /dev/null +++ b/src/test/resources/testPrograms/negativ/generic/TypParameterInstantiation.monty @@ -0,0 +1,3 @@ +class Wrapper: + f(): + Tt t := Tt() \ No newline at end of file diff --git a/src/test/resources/testPrograms/negativ/generic/TypeBoundMismatch.error b/src/test/resources/testPrograms/negativ/generic/TypeBoundMismatch.error new file mode 100644 index 0000000..c00c5d7 --- /dev/null +++ b/src/test/resources/testPrograms/negativ/generic/TypeBoundMismatch.error @@ -0,0 +1 @@ +ResolveVisitor caught error in FunctionCall at file: TypeBoundMismatch.monty, line: 7, char: 18: Identifier is not defined: sayHello \ No newline at end of file diff --git a/src/test/resources/testPrograms/negativ/generic/TypeBoundMismatch.monty b/src/test/resources/testPrograms/negativ/generic/TypeBoundMismatch.monty new file mode 100644 index 0000000..b760116 --- /dev/null +++ b/src/test/resources/testPrograms/negativ/generic/TypeBoundMismatch.monty @@ -0,0 +1,7 @@ +class SayHello: + sayHello(): + println("Hello") + +case class Wrapper(Tt t) + +Wrapper(3).t.sayHello() diff --git a/src/test/resources/testPrograms/negativ/scoping/VariableAccess.error b/src/test/resources/testPrograms/negativ/scoping/VariableAccess.error index 227affb..244443b 100644 --- a/src/test/resources/testPrograms/negativ/scoping/VariableAccess.error +++ b/src/test/resources/testPrograms/negativ/scoping/VariableAccess.error @@ -1 +1 @@ -ResolveVisitor caught error in null: Identifier is not defined: b \ No newline at end of file +ResolveVisitor caught error in VariableAccess at file: VariableAccess.monty, line: 8, char: 0: Identifier is not defined: b \ No newline at end of file diff --git a/src/test/resources/testPrograms/negativ/scoping/VariableAccess2.error b/src/test/resources/testPrograms/negativ/scoping/VariableAccess2.error index ca5a8d9..97d2a3c 100644 --- a/src/test/resources/testPrograms/negativ/scoping/VariableAccess2.error +++ b/src/test/resources/testPrograms/negativ/scoping/VariableAccess2.error @@ -1 +1 @@ -ResolveVisitor caught error in null: Identifier is not defined: var \ No newline at end of file +ResolveVisitor caught error in VariableAccess at file: VariableAccess2.monty, line: 8, char: 16: Identifier is not defined: var \ No newline at end of file diff --git a/src/test/resources/testPrograms/negativ/scoping/VariableAccess3.error b/src/test/resources/testPrograms/negativ/scoping/VariableAccess3.error index 227affb..20cdb96 100644 --- a/src/test/resources/testPrograms/negativ/scoping/VariableAccess3.error +++ b/src/test/resources/testPrograms/negativ/scoping/VariableAccess3.error @@ -1 +1 @@ -ResolveVisitor caught error in null: Identifier is not defined: b \ No newline at end of file +ResolveVisitor caught error in VariableAccess at file: VariableAccess3.monty, line: 8, char: 0: Identifier is not defined: b \ No newline at end of file diff --git a/src/test/resources/testPrograms/negativ/scoping/VariableAccess4.error b/src/test/resources/testPrograms/negativ/scoping/VariableAccess4.error index ca5a8d9..5974ff7 100644 --- a/src/test/resources/testPrograms/negativ/scoping/VariableAccess4.error +++ b/src/test/resources/testPrograms/negativ/scoping/VariableAccess4.error @@ -1 +1 @@ -ResolveVisitor caught error in null: Identifier is not defined: var \ No newline at end of file +ResolveVisitor caught error in VariableAccess at file: VariableAccess4.monty, line: 7, char: 6: Identifier is not defined: var \ No newline at end of file diff --git a/src/test/resources/testPrograms/negativ/scoping/VariableAccess6.error b/src/test/resources/testPrograms/negativ/scoping/VariableAccess6.error index 46b12b7..a6d479e 100644 --- a/src/test/resources/testPrograms/negativ/scoping/VariableAccess6.error +++ b/src/test/resources/testPrograms/negativ/scoping/VariableAccess6.error @@ -1 +1 @@ -ResolveVisitor caught error in null: Identifier is not defined: answer \ No newline at end of file +ResolveVisitor caught error in VariableAccess at file: VariableAccess6.monty, line: 12, char: 7: Identifier is not defined: answer \ No newline at end of file diff --git a/src/test/resources/testPrograms/patternMatching/PatternMatchingJust.monty b/src/test/resources/testPrograms/patternMatching/PatternMatchingJust.monty new file mode 100644 index 0000000..6fc438d --- /dev/null +++ b/src/test/resources/testPrograms/patternMatching/PatternMatchingJust.monty @@ -0,0 +1,13 @@ +printMaybe(Maybe m): + case m of: + Just(String value): + println(value) + Nothing(): + println("empty") + +String decompose(Just l): + return (l.getValue()) + +printMaybe(Nothing()) +printMaybe(Just("Hello")) +printMaybe(Just("World")) \ No newline at end of file diff --git a/src/test/resources/testPrograms/patternMatching/PatternMatchingJust.output b/src/test/resources/testPrograms/patternMatching/PatternMatchingJust.output new file mode 100644 index 0000000..d6b4924 --- /dev/null +++ b/src/test/resources/testPrograms/patternMatching/PatternMatchingJust.output @@ -0,0 +1,3 @@ +empty +Hello +World diff --git a/src/test/resources/testPrograms/print/PrintBoolean.monty b/src/test/resources/testPrograms/print/PrintBoolean.monty index 8cf642e..2da28d4 100644 --- a/src/test/resources/testPrograms/print/PrintBoolean.monty +++ b/src/test/resources/testPrograms/print/PrintBoolean.monty @@ -4,3 +4,4 @@ print(true) print(false) +