Skip to content

Commit

Permalink
Merge pull request #41 from cpfr/closures
Browse files Browse the repository at this point in the history
Closures and bug fixes
  • Loading branch information
cpfr committed Nov 25, 2015
2 parents 77e31b7 + 7c52f0c commit 19e46c9
Show file tree
Hide file tree
Showing 35 changed files with 580 additions and 111 deletions.
13 changes: 9 additions & 4 deletions src/main/antlr4/de/uni/bremen/monty/moco/antlr/Monty.g4
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,11 @@ grammar Monty;

import lex;


nativeAnnotation
: '@native'
;

compilationUnit
: EndOfLine* moduleDeclaration EOF
;
Expand All @@ -28,7 +33,7 @@ independentDeclaration
;

classDeclaration
: AbstractKeyword? 'class' type ('inherits' typeList)?
: nativeAnnotation? AbstractKeyword? 'class' type ('inherits' typeList)?
':' EndOfLine
Indent
(memberDeclaration+ | 'pass' EndOfLine)
Expand Down Expand Up @@ -83,7 +88,7 @@ typeList
;

functionDeclaration
: (type)?
: nativeAnnotation? (type)?
Identifier
Lparenthesis parameterList? Rparenthesis ':' EndOfLine
statementBlock
Expand Down Expand Up @@ -193,9 +198,9 @@ expressionList
;

expression
: functionCall
| primary
: primary
| functionExpression
| functionCall
| ifExprThen=expression 'if' ifExpCondition=expression 'else' ifExprElse=expression
| left=expression accessOperator right=expression
| <assoc=right> (plusMinusOperator | notOperator) singleExpression=expression
Expand Down
31 changes: 24 additions & 7 deletions src/main/java/de/uni/bremen/monty/moco/ast/ASTBuilder.java
Original file line number Diff line number Diff line change
Expand Up @@ -233,7 +233,8 @@ public ASTNode visitFunctionCall(FunctionCallContext ctx) {
private void buildDefaultFunctions(boolean isFunction, List<DefaultParameterContext> defaultParameter,
List<VariableDeclaration> allVariableDeclarations, List<VariableDeclaration> params,
List<Expression> defaultExpression, List<VariableDeclaration> defaultVariableDeclaration,
Identifier identifier, Token token, TypeContext typeContext, DeclarationType declarationTypeCopy) {
Identifier identifier, Token token, TypeContext typeContext, DeclarationType declarationTypeCopy,
boolean isNative) {

for (int defaultParameterIdx = 0; defaultParameterIdx < defaultParameter.size(); defaultParameterIdx++) {
Block block = new Block(position(token));
Expand All @@ -252,8 +253,12 @@ private void buildDefaultFunctions(boolean isFunction, List<DefaultParameterCont
}
}

List<VariableDeclaration> subParams =
allVariableDeclarations.subList(0, params.size() + defaultParameterIdx);
List<VariableDeclaration> subParams = new ArrayList<>(params.size() + defaultParameterIdx);
for (int i = 0; i < params.size() + defaultParameterIdx; i++) {
VariableDeclaration var = allVariableDeclarations.get(i);
subParams.add(new VariableDeclaration(var.getPosition(), var.getIdentifier(), var.getTypeIdentifier(),
var.getDeclarationType()));
}

Expression expression =
new FunctionCall(position(token), new ResolvableIdentifier(identifier.getSymbol()), l);
Expand All @@ -275,13 +280,15 @@ private void buildDefaultFunctions(boolean isFunction, List<DefaultParameterCont
FunctionDeclaration funDecl =
new FunctionDeclaration(position(token), identifier, block, subParams, declarationTypeCopy,
returnTypeIdent);
funDecl.setNative(isNative);

currentBlocks.peek().addDeclaration(funDecl);
}
}

private FunctionDeclaration buildFunctions(boolean isFunction, ParameterListContext parameterListContext,
Token token, TypeContext typeContext, StatementBlockContext statementBlockContext, Identifier identifier) {
Token token, TypeContext typeContext, StatementBlockContext statementBlockContext, Identifier identifier,
boolean isNative) {

FunctionDeclaration.DeclarationType declarationTypeCopy = currentFunctionContext;
List<VariableDeclaration> params = parameterListToVarDeclList(parameterListContext);
Expand All @@ -308,7 +315,8 @@ private FunctionDeclaration buildFunctions(boolean isFunction, ParameterListCont
identifier,
token,
typeContext,
declarationTypeCopy);
declarationTypeCopy,
isNative);

FunctionDeclaration funDecl;

Expand All @@ -320,6 +328,7 @@ private FunctionDeclaration buildFunctions(boolean isFunction, ParameterListCont
funDecl =
new FunctionDeclaration(position(token), identifier, (Block) visit(statementBlockContext),
allVariableDeclarations, declarationTypeCopy, returnTypeIdent);
funDecl.setNative(isNative);
if (funDecl.isUnbound()) {
FunctionWrapperFactory.generateWrapperClass(funDecl, tupleDeclarationFactory);
currentBlocks.peek().addDeclaration(funDecl.getWrapperClass());
Expand Down Expand Up @@ -350,14 +359,16 @@ private FunctionDeclaration buildAbstractMethod(boolean functionDeclaration,
@Override
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())));
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<Statement> list = proc.getBody().getStatements();
Expand Down Expand Up @@ -398,8 +409,14 @@ private ASTNode createGenerator(Position pos, ResolvableIdentifier className, Re
allParams.addAll(params);
allParams.addAll(defaultParams);

List<VariableDeclaration> allParamsCopy = new ArrayList<>(allParams.size());
for (VariableDeclaration param : allParams) {
allParamsCopy.add(new VariableDeclaration(param.getPosition(), param.getIdentifier(),
param.getTypeIdentifier(), param.getDeclarationType()));
}

ClassDeclaration iterator =
GeneratorClassFactory.generateGeneratorIteratorClass(pos, allParams, body, returnType);
GeneratorClassFactory.generateGeneratorIteratorClass(pos, allParamsCopy, body, returnType);
currentBlocks.peek().addDeclaration(iterator);

ClassDeclaration generator =
Expand Down
12 changes: 11 additions & 1 deletion src/main/java/de/uni/bremen/monty/moco/ast/BasicASTNode.java
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,8 @@ public abstract class BasicASTNode implements ASTNode {

private BitSet visitedFlags = new BitSet(NUMBER_OF_VISITORS);

private boolean isNativeNode = false;

/** Constructor.
*
* @param position
Expand All @@ -82,7 +84,7 @@ public ASTNode getParentNode() {
*
* @return the parent node */
public ASTNode getParentNodeByType(Class type) {
ASTNode n = this;
ASTNode n = getParentNode();
while ((!type.isInstance(n)) && (n != null)) {
n = n.getParentNode();
}
Expand Down Expand Up @@ -128,4 +130,12 @@ public Scope getScope() {
public BitSet getVisitedFlags() {
return visitedFlags;
}

public boolean isNative() {
return isNativeNode;
}

public void setNative(boolean isNative) {
isNativeNode = isNative;
}
}
8 changes: 6 additions & 2 deletions src/main/java/de/uni/bremen/monty/moco/ast/ClassScope.java
Original file line number Diff line number Diff line change
Expand Up @@ -109,12 +109,16 @@ protected Declaration resolveMember(ResolvableIdentifier identifier) {
* @param identifier
* the identifier to resolve
* @return the list of function declarations */
protected List<FunctionDeclaration> resolveFunctionMember(ResolvableIdentifier identifier) {
List<FunctionDeclaration> result = new ArrayList<FunctionDeclaration>();
protected List<Declaration> resolveFunctionMember(ResolvableIdentifier identifier) {
List<Declaration> result = new ArrayList<>();

if (functions.containsKey(identifier)) {
result.addAll(functions.get(identifier));
}
if (members.containsKey(identifier)) {
result.add(members.get(identifier));
}

for (ClassScope scope : parentClassesScopes) {
result.addAll(scope.resolveFunctionMember(identifier));
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,10 +44,10 @@
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.visitor.BaseVisitor;

import java.util.ArrayList;
import java.util.List;
import java.util.*;

/** A FunctionDeclaration represents the declaration of a function in the AST.
* <p>
Expand Down Expand Up @@ -80,6 +80,8 @@ public enum DeclarationType {

private boolean returnTypeMustBeInferred = false;

private Map<VariableDeclaration, VariableDeclaration> closureVars = new HashMap<>();

/** Constructor.
*
* @param position
Expand Down Expand Up @@ -396,10 +398,9 @@ protected void splitReturnStatement(boolean tupleInsteadOfVoid) {
// add the new ones
Expression oldCall = oldRet.getParameter();
oldCall.setParentNode(getBody());
if (oldCall instanceof FunctionCall) {
getBody().addStatement((FunctionCall) oldCall);
} else if (oldCall instanceof WrappedFunctionCall) {
getBody().addStatement((WrappedFunctionCall) oldCall);

if (oldCall instanceof Statement) {
getBody().addStatement((Statement) oldCall);
} else {
throw new RuntimeException("invalid AST!");
}
Expand All @@ -414,4 +415,47 @@ public String toString() {
}
return String.format("%s(%s)", getIdentifier().toString(), params);
}

private VariableDeclaration checkSelfVariable(VariableDeclaration var) {
if (var.getIdentifier().getSymbol().equals("self")) {
for (VariableDeclaration key : closureVars.keySet()) {
if (key.getIdentifier().getSymbol().equals("self")) {
return key;
}
}
}
return var;
}

public VariableDeclaration addClosureVariable(VariableDeclaration var) {
var = checkSelfVariable(var);
if (!closureVars.containsKey(var)) {
VariableDeclaration attr =
new VariableDeclaration(var.getPosition(), var.getIdentifier(), var.getTypeIdentifier(),
VariableDeclaration.DeclarationType.ATTRIBUTE);
attr.setParentNode(var.getParentNode());
attr.setScope(var.getScope());
attr.setType(var.getType());
closureVars.put(var, attr);
return attr;
}
return closureVars.get(var);
}

public boolean isClosure() {
return closureVars.size() > 0;
}

public VariableDeclaration getClosureVariable(VariableDeclaration var) {
var = checkSelfVariable(var);
return closureVars.get(var);
}

public Collection<VariableDeclaration> getClosureVariables() {
return closureVars.values();
}

public Collection<VariableDeclaration> getClosureVariableOriginalDeclarations() {
return closureVars.keySet();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -98,8 +98,4 @@ public void visitChildren(BaseVisitor visitor) {
}
visitor.visitDoubleDispatched(block);
}

public boolean isNative() {
return !getIdentifier().getSymbol().startsWith("_");
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@
import de.uni.bremen.monty.moco.visitor.BaseVisitor;

public class SelfExpression extends Expression {
private boolean inClosure = false;

public SelfExpression(Position position) {
super(position);
Expand All @@ -55,4 +56,12 @@ public void visit(BaseVisitor visitor) {
@Override
public void visitChildren(BaseVisitor visitor) {
}

public void setInClosure() {
inClosure = true;
}

public boolean isInClosure() {
return inClosure;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ public class VariableAccess extends Expression {
/** Identifier of the variable to access. */
private final ResolvableIdentifier identifier;
private Declaration declaration;
private boolean isClosureVar = false;

/** Is this a L-value? */
private boolean lValue = false;
Expand Down Expand Up @@ -98,4 +99,12 @@ public Declaration getDeclaration() {
public void setDeclaration(Declaration declaration) {
this.declaration = declaration;
}

public void setClosureVariable(boolean closure) {
isClosureVar = closure;
}

public boolean isClosureVariable() {
return isClosureVar;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@
package de.uni.bremen.monty.moco.ast.statement;

import de.uni.bremen.monty.moco.ast.*;
import de.uni.bremen.monty.moco.ast.declaration.FunctionDeclaration;
import de.uni.bremen.monty.moco.ast.expression.Expression;
import de.uni.bremen.monty.moco.visitor.BaseVisitor;

Expand All @@ -50,6 +51,8 @@ public class Assignment extends BasicASTNode implements Statement {
/** The right side. */
private final Expression right;

private FunctionDeclaration correspondingFunWrapper = null;

/** Constructor.
*
* @param position
Expand Down Expand Up @@ -91,4 +94,15 @@ public void visitChildren(BaseVisitor visitor) {
visitor.visitDoubleDispatched(right);
}

public boolean belongsToFunctionWrapper() {
return correspondingFunWrapper != null;
}

public void setCorrespondingFunctionWrapper(FunctionDeclaration fun) {
correspondingFunWrapper = fun;
}

public FunctionDeclaration getCorrespondingFunctionWrapper() {
return correspondingFunWrapper;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -398,6 +398,30 @@ public LLVMIdentifier<LLVMType> accessMember(CodeContext c, LLVMIdentifier<LLVMP
return result;
}

public LLVMIdentifier<LLVMType> accessClosureContextMember(CodeContext c, ClassDeclaration closureClass,
VariableDeclaration varDecl, VariableAccess varAccess, TypeDeclaration variableType,
LLVMIdentifier<LLVMPointer<LLVMType>> context) {

LLVMType contextType = LLVMTypeFactory.struct(nameMangler.mangleClass(closureClass) + "_closure_context");
LLVMIdentifier<LLVMType> contextLlvmIdentifier =
accessMember(c, context, closureClass.getLastAttributeIndex(), contextType, false);
LLVMIdentifier<LLVMType> result =
accessMember(
c,
llvmIdentifierFactory.pointerTo(contextLlvmIdentifier),
varDecl.getAttributeIndex(),
variableType,
!varAccess.getLValue());
return result;
}

public LLVMIdentifier<LLVMType> accessClosureContextMember(CodeContext c, ClassDeclaration closureClass,
VariableDeclaration varDecl, VariableAccess varAccess, TypeDeclaration variableType) {

LLVMIdentifier<LLVMPointer<LLVMType>> self = resolveLocalVarName("..ctx..", closureClass, false);
return accessClosureContextMember(c, closureClass, varDecl, varAccess, variableType, self);
}

public LLVMIdentifier<LLVMType> accessContextMember(CodeContext c, ClassDeclaration generatorClass,
VariableDeclaration varDecl, VariableAccess varAccess, TypeDeclaration variableType) {

Expand All @@ -410,7 +434,7 @@ public LLVMIdentifier<LLVMType> accessContextMember(CodeContext c, ClassDeclarat
(LLVMIdentifier<LLVMPointer<LLVMType>>) self,
generatorClass.getLastAttributeIndex(),
contextType,
false); // TODO: richtig?
false);
LLVMIdentifier<LLVMType> result =
accessMember(
c,
Expand Down
Loading

0 comments on commit 19e46c9

Please sign in to comment.