diff options
| author | Michael Williamson <mike@zwobble.org> | 2016-01-17 18:02:27 +0000 |
|---|---|---|
| committer | Michael Williamson <mike@zwobble.org> | 2016-01-17 18:02:27 +0000 |
| commit | cd244418efb005c27b1018458767c57dfa09e046 (patch) | |
| tree | 9a536359b38446a6271659337cc6803aab1529b9 /src/main/java/org/zwobble/couscous/ast | |
| parent | 013265afb2432181de05a109fd8fe7823d8f3d69 (diff) | |
Add transformation pass to C# backend
Diffstat (limited to 'src/main/java/org/zwobble/couscous/ast')
24 files changed, 351 insertions, 4 deletions
diff --git a/src/main/java/org/zwobble/couscous/ast/AnnotationNode.java b/src/main/java/org/zwobble/couscous/ast/AnnotationNode.java index 0d135ba..e102af7 100644 --- a/src/main/java/org/zwobble/couscous/ast/AnnotationNode.java +++ b/src/main/java/org/zwobble/couscous/ast/AnnotationNode.java @@ -1,6 +1,7 @@ package org.zwobble.couscous.ast; import org.zwobble.couscous.ast.visitors.NodeMapper; +import org.zwobble.couscous.ast.visitors.NodeTransformer; public class AnnotationNode implements Node { public static AnnotationNode annotation(TypeName type) { @@ -22,6 +23,10 @@ public class AnnotationNode implements Node { return visitor.visit(this); } + public AnnotationNode transform(NodeTransformer transformer) { + return new AnnotationNode(transformer.transform(type)); + } + @Override public String toString() { return "AnnotationNode(type=" + type + ")"; diff --git a/src/main/java/org/zwobble/couscous/ast/AssignmentNode.java b/src/main/java/org/zwobble/couscous/ast/AssignmentNode.java index 15ecf8f..dd1a9f3 100644 --- a/src/main/java/org/zwobble/couscous/ast/AssignmentNode.java +++ b/src/main/java/org/zwobble/couscous/ast/AssignmentNode.java @@ -1,6 +1,7 @@ package org.zwobble.couscous.ast; import org.zwobble.couscous.ast.visitors.ExpressionNodeMapper; +import org.zwobble.couscous.ast.visitors.NodeTransformer; import java.util.function.Function; @@ -52,6 +53,12 @@ public class AssignmentNode implements ExpressionNode { replace.apply(value)); } + public ExpressionNode transform(NodeTransformer transformer) { + return new AssignmentNode( + (AssignableExpressionNode) transformer.visit(target), + transformer.visit(value)); + } + @Override public TypeName getType() { return value.getType(); diff --git a/src/main/java/org/zwobble/couscous/ast/CastNode.java b/src/main/java/org/zwobble/couscous/ast/CastNode.java index e81cd94..1f61941 100644 --- a/src/main/java/org/zwobble/couscous/ast/CastNode.java +++ b/src/main/java/org/zwobble/couscous/ast/CastNode.java @@ -1,6 +1,7 @@ package org.zwobble.couscous.ast; import org.zwobble.couscous.ast.visitors.ExpressionNodeMapper; +import org.zwobble.couscous.ast.visitors.NodeTransformer; import java.util.function.Function; @@ -36,6 +37,10 @@ public class CastNode implements ExpressionNode { return new CastNode(replace.apply(expression), type); } + public ExpressionNode transform(NodeTransformer transformer) { + return new CastNode(transformer.visit(expression), transformer.transform(type)); + } + @Override public String toString() { return "CastNode(" + diff --git a/src/main/java/org/zwobble/couscous/ast/ClassNode.java b/src/main/java/org/zwobble/couscous/ast/ClassNode.java index 3545084..8b54be6 100644 --- a/src/main/java/org/zwobble/couscous/ast/ClassNode.java +++ b/src/main/java/org/zwobble/couscous/ast/ClassNode.java @@ -1,6 +1,7 @@ package org.zwobble.couscous.ast; import org.zwobble.couscous.ast.visitors.NodeMapper; +import org.zwobble.couscous.ast.visitors.NodeTransformer; import java.util.List; import java.util.Set; @@ -66,6 +67,15 @@ public class ClassNode implements Node { return visitor.visit(this); } + public ClassNode transform(NodeTransformer transformer) { + return new ClassNode( + transformer.transform(name), + transformer.transformTypes(superTypes), + transformer.transformFields(fields), + transformer.visit(constructor), + transformer.transformMethods(methods)); + } + @Override public String toString() { return "ClassNode(" + diff --git a/src/main/java/org/zwobble/couscous/ast/ConstructorCallNode.java b/src/main/java/org/zwobble/couscous/ast/ConstructorCallNode.java index cad359d..ecbdc00 100644 --- a/src/main/java/org/zwobble/couscous/ast/ConstructorCallNode.java +++ b/src/main/java/org/zwobble/couscous/ast/ConstructorCallNode.java @@ -1,10 +1,11 @@ package org.zwobble.couscous.ast; +import org.zwobble.couscous.ast.visitors.ExpressionNodeMapper; +import org.zwobble.couscous.ast.visitors.NodeTransformer; + import java.util.List; import java.util.function.Function; -import org.zwobble.couscous.ast.visitors.ExpressionNodeMapper; - import static org.zwobble.couscous.util.ExtraLists.eagerMap; public class ConstructorCallNode implements ExpressionNode { @@ -43,6 +44,12 @@ public class ConstructorCallNode implements ExpressionNode { return new ConstructorCallNode(type, eagerMap(arguments, replace::apply)); } + public ExpressionNode transform(NodeTransformer transformer) { + return new ConstructorCallNode( + transformer.transform(type), + transformer.transformExpressions(arguments)); + } + @Override public String toString() { return "ConstructorCallNode(type=" + type + ", arguments=" + arguments diff --git a/src/main/java/org/zwobble/couscous/ast/ConstructorNode.java b/src/main/java/org/zwobble/couscous/ast/ConstructorNode.java index 0d4bad8..fab931b 100644 --- a/src/main/java/org/zwobble/couscous/ast/ConstructorNode.java +++ b/src/main/java/org/zwobble/couscous/ast/ConstructorNode.java @@ -1,6 +1,7 @@ package org.zwobble.couscous.ast; import org.zwobble.couscous.ast.visitors.NodeMapper; +import org.zwobble.couscous.ast.visitors.NodeTransformer; import java.util.Collections; import java.util.List; @@ -17,7 +18,7 @@ public class ConstructorNode implements CallableNode { private final List<FormalArgumentNode> arguments; private final List<StatementNode> body; - public ConstructorNode( + private ConstructorNode( List<FormalArgumentNode> arguments, List<StatementNode> body) { this.arguments = arguments; @@ -37,6 +38,12 @@ public class ConstructorNode implements CallableNode { return visitor.visit(this); } + public ConstructorNode transform(NodeTransformer transformer) { + return new ConstructorNode( + transformer.transformFormalArguments(arguments), + transformer.transformStatements(body)); + } + @Override public String toString() { return "ConstructorNode(arguments=" + arguments + ", body=" + body diff --git a/src/main/java/org/zwobble/couscous/ast/ExpressionStatementNode.java b/src/main/java/org/zwobble/couscous/ast/ExpressionStatementNode.java index 0ac7381..68acedb 100644 --- a/src/main/java/org/zwobble/couscous/ast/ExpressionStatementNode.java +++ b/src/main/java/org/zwobble/couscous/ast/ExpressionStatementNode.java @@ -1,5 +1,6 @@ package org.zwobble.couscous.ast; +import org.zwobble.couscous.ast.visitors.NodeTransformer; import org.zwobble.couscous.ast.visitors.StatementNodeMapper; import java.util.function.Function; @@ -29,6 +30,10 @@ public class ExpressionStatementNode implements StatementNode { return new ExpressionStatementNode(replace.apply(expression)); } + public StatementNode transform(NodeTransformer transformer) { + return new ExpressionStatementNode(transformer.visit(expression)); + } + @Override public String toString() { return "ExpressionStatementNode(expression=" + expression + ")"; diff --git a/src/main/java/org/zwobble/couscous/ast/FieldAccessNode.java b/src/main/java/org/zwobble/couscous/ast/FieldAccessNode.java index 9f881b4..3224b5d 100644 --- a/src/main/java/org/zwobble/couscous/ast/FieldAccessNode.java +++ b/src/main/java/org/zwobble/couscous/ast/FieldAccessNode.java @@ -2,6 +2,7 @@ package org.zwobble.couscous.ast; import org.zwobble.couscous.ast.visitors.AssignableExpressionNodeVisitor; import org.zwobble.couscous.ast.visitors.ExpressionNodeMapper; +import org.zwobble.couscous.ast.visitors.NodeTransformer; import java.util.function.Function; @@ -48,6 +49,13 @@ public class FieldAccessNode implements AssignableExpressionNode { return new FieldAccessNode(replace.apply(left), fieldName, type); } + public ExpressionNode transform(NodeTransformer transformer) { + return new FieldAccessNode( + transformer.visit(left), + fieldName, + transformer.transform(type)); + } + @Override public void accept(AssignableExpressionNodeVisitor mapper) { mapper.visit(this); diff --git a/src/main/java/org/zwobble/couscous/ast/FieldDeclarationNode.java b/src/main/java/org/zwobble/couscous/ast/FieldDeclarationNode.java index 7fea43c..3b27b9e 100644 --- a/src/main/java/org/zwobble/couscous/ast/FieldDeclarationNode.java +++ b/src/main/java/org/zwobble/couscous/ast/FieldDeclarationNode.java @@ -1,7 +1,7 @@ package org.zwobble.couscous.ast; import org.zwobble.couscous.ast.visitors.NodeMapper; -import org.zwobble.couscous.ast.visitors.NodeVisitor; +import org.zwobble.couscous.ast.visitors.NodeTransformer; public class FieldDeclarationNode implements Node { public static FieldDeclarationNode field(String name, TypeName type) { @@ -29,6 +29,12 @@ public class FieldDeclarationNode implements Node { return visitor.visit(this); } + public FieldDeclarationNode transform(NodeTransformer transformer) { + return new FieldDeclarationNode( + name, + transformer.transform(type)); + } + @Override public String toString() { return "FieldDeclarationNode(name=" + name + ", type=" + type + ")"; diff --git a/src/main/java/org/zwobble/couscous/ast/FormalArgumentNode.java b/src/main/java/org/zwobble/couscous/ast/FormalArgumentNode.java index 41fb982..f7d7f42 100644 --- a/src/main/java/org/zwobble/couscous/ast/FormalArgumentNode.java +++ b/src/main/java/org/zwobble/couscous/ast/FormalArgumentNode.java @@ -1,6 +1,7 @@ package org.zwobble.couscous.ast; import org.zwobble.couscous.ast.visitors.NodeMapper; +import org.zwobble.couscous.ast.visitors.NodeTransformer; public class FormalArgumentNode implements VariableNode, Node { public static FormalArgumentNode formalArg(VariableDeclaration declaration) { @@ -30,6 +31,10 @@ public class FormalArgumentNode implements VariableNode, Node { return visitor.visit(this); } + public FormalArgumentNode transform(NodeTransformer transformer) { + return new FormalArgumentNode(transformer.transform(declaration)); + } + @Override public String toString() { return "FormalArgumentNode(declaration=" + declaration + ")"; diff --git a/src/main/java/org/zwobble/couscous/ast/IfStatementNode.java b/src/main/java/org/zwobble/couscous/ast/IfStatementNode.java index 8b4709a..972f0a4 100644 --- a/src/main/java/org/zwobble/couscous/ast/IfStatementNode.java +++ b/src/main/java/org/zwobble/couscous/ast/IfStatementNode.java @@ -1,5 +1,6 @@ package org.zwobble.couscous.ast; +import org.zwobble.couscous.ast.visitors.NodeTransformer; import org.zwobble.couscous.ast.visitors.StatementNodeMapper; import java.util.List; @@ -53,6 +54,13 @@ public class IfStatementNode implements StatementNode { eagerMap(falseBranch, statement -> statement.replaceExpressions(replace))); } + public StatementNode transform(NodeTransformer transformer) { + return new IfStatementNode( + transformer.visit(condition), + transformer.transformStatements(trueBranch), + transformer.transformStatements(falseBranch)); + } + @Override public String toString() { return "IfStatementNode(condition=" + condition + ", trueBranch=" diff --git a/src/main/java/org/zwobble/couscous/ast/InstanceReceiver.java b/src/main/java/org/zwobble/couscous/ast/InstanceReceiver.java index 926af5d..ed32dc4 100644 --- a/src/main/java/org/zwobble/couscous/ast/InstanceReceiver.java +++ b/src/main/java/org/zwobble/couscous/ast/InstanceReceiver.java @@ -1,6 +1,7 @@ package org.zwobble.couscous.ast; import org.zwobble.couscous.ast.visitors.NodeMapper; +import org.zwobble.couscous.ast.visitors.NodeTransformer; import java.util.function.Function; @@ -29,6 +30,10 @@ public class InstanceReceiver implements Receiver { return visitor.visit(expression); } + public Receiver transform(NodeTransformer transformer) { + return new InstanceReceiver(transformer.visit(expression)); + } + @Override public <T> T accept(NodeMapper<T> visitor) { return visitor.visit(this); diff --git a/src/main/java/org/zwobble/couscous/ast/LiteralNode.java b/src/main/java/org/zwobble/couscous/ast/LiteralNode.java index ed2aaf0..5753650 100644 --- a/src/main/java/org/zwobble/couscous/ast/LiteralNode.java +++ b/src/main/java/org/zwobble/couscous/ast/LiteralNode.java @@ -1,6 +1,7 @@ package org.zwobble.couscous.ast; import org.zwobble.couscous.ast.visitors.ExpressionNodeMapper; +import org.zwobble.couscous.ast.visitors.NodeTransformer; import org.zwobble.couscous.values.*; import java.util.function.Function; @@ -58,6 +59,18 @@ public class LiteralNode implements ExpressionNode { return this; } + public ExpressionNode transform(NodeTransformer transformer) { + return new LiteralNode(transformValue(transformer), transformer.transform(type)); + } + + private PrimitiveValue transformValue(NodeTransformer transformer) { + if (value instanceof TypeValue) { + return new TypeValue(transformer.transform(((TypeValue)value).getValue())); + } else { + return value; + } + } + @Override public String toString() { return "LiteralNode(value=" + value + ", type=" + type + ")"; diff --git a/src/main/java/org/zwobble/couscous/ast/LocalVariableDeclarationNode.java b/src/main/java/org/zwobble/couscous/ast/LocalVariableDeclarationNode.java index a165070..4ee0e97 100644 --- a/src/main/java/org/zwobble/couscous/ast/LocalVariableDeclarationNode.java +++ b/src/main/java/org/zwobble/couscous/ast/LocalVariableDeclarationNode.java @@ -1,6 +1,7 @@ package org.zwobble.couscous.ast; import org.zwobble.couscous.ast.identifiers.Identifier; +import org.zwobble.couscous.ast.visitors.NodeTransformer; import org.zwobble.couscous.ast.visitors.StatementNodeMapper; import java.util.function.Function; @@ -58,6 +59,12 @@ public class LocalVariableDeclarationNode implements VariableNode, StatementNode return new LocalVariableDeclarationNode(declaration, replace.apply(initialValue)); } + public StatementNode transform(NodeTransformer transformer) { + return new LocalVariableDeclarationNode( + transformer.transform(declaration), + transformer.visit(initialValue)); + } + @Override public String toString() { return "LocalVariableDeclarationNode(declaration=" + declaration diff --git a/src/main/java/org/zwobble/couscous/ast/MethodCallNode.java b/src/main/java/org/zwobble/couscous/ast/MethodCallNode.java index b50250d..5a67bc2 100644 --- a/src/main/java/org/zwobble/couscous/ast/MethodCallNode.java +++ b/src/main/java/org/zwobble/couscous/ast/MethodCallNode.java @@ -1,6 +1,7 @@ package org.zwobble.couscous.ast; import org.zwobble.couscous.ast.visitors.ExpressionNodeMapper; +import org.zwobble.couscous.ast.visitors.NodeTransformer; import java.util.List; import java.util.function.Function; @@ -95,6 +96,14 @@ public class MethodCallNode implements ExpressionNode { type); } + public ExpressionNode transform(NodeTransformer transformer) { + return new MethodCallNode( + transformer.visit(receiver), + methodName, + transformer.transformExpressions(arguments), + transformer.transform(type)); + } + @Override public String toString() { return "MethodCallNode(receiver=" + receiver + ", methodName=" diff --git a/src/main/java/org/zwobble/couscous/ast/MethodNode.java b/src/main/java/org/zwobble/couscous/ast/MethodNode.java index 5ee3a7d..b5dfd39 100644 --- a/src/main/java/org/zwobble/couscous/ast/MethodNode.java +++ b/src/main/java/org/zwobble/couscous/ast/MethodNode.java @@ -2,6 +2,7 @@ package org.zwobble.couscous.ast; import com.google.common.collect.ImmutableList; import org.zwobble.couscous.ast.visitors.NodeMapper; +import org.zwobble.couscous.ast.visitors.NodeTransformer; import org.zwobble.couscous.values.UnitValue; import java.util.List; @@ -151,6 +152,16 @@ public class MethodNode implements CallableNode { return visitor.visit(this); } + public MethodNode transform(NodeTransformer transformer) { + return new MethodNode( + transformer.transformAnnotations(annotations), + isStatic, + name, + transformer.transformFormalArguments(arguments), + transformer.transform(returnType), + transformer.transformStatements(body)); + } + @Override public String toString() { return "MethodNode(" + diff --git a/src/main/java/org/zwobble/couscous/ast/ReturnNode.java b/src/main/java/org/zwobble/couscous/ast/ReturnNode.java index 68330af..5bd5987 100644 --- a/src/main/java/org/zwobble/couscous/ast/ReturnNode.java +++ b/src/main/java/org/zwobble/couscous/ast/ReturnNode.java @@ -1,5 +1,6 @@ package org.zwobble.couscous.ast; +import org.zwobble.couscous.ast.visitors.NodeTransformer; import org.zwobble.couscous.ast.visitors.StatementNodeMapper; import java.util.function.Function; @@ -29,6 +30,12 @@ public class ReturnNode implements StatementNode { return new ReturnNode(replace.apply(value)); } + public StatementNode transform(NodeTransformer transformer) { + // TODO: remove duplication with replaceExpressions + // (can probably implement replaceExpressions with transform) + return new ReturnNode(transformer.visit(value)); + } + @Override public String toString() { return "ReturnNode(value=" + value + ")"; diff --git a/src/main/java/org/zwobble/couscous/ast/StaticReceiver.java b/src/main/java/org/zwobble/couscous/ast/StaticReceiver.java index 4d35376..7814108 100644 --- a/src/main/java/org/zwobble/couscous/ast/StaticReceiver.java +++ b/src/main/java/org/zwobble/couscous/ast/StaticReceiver.java @@ -1,6 +1,7 @@ package org.zwobble.couscous.ast; import org.zwobble.couscous.ast.visitors.NodeMapper; +import org.zwobble.couscous.ast.visitors.NodeTransformer; import java.util.function.Function; @@ -34,6 +35,10 @@ public class StaticReceiver implements Receiver { return visitor.visit(this); } + public Receiver transform(NodeTransformer transformer) { + return new StaticReceiver(transformer.transform(type)); + } + @Override public String toString() { return "StaticReceiver(" + diff --git a/src/main/java/org/zwobble/couscous/ast/TernaryConditionalNode.java b/src/main/java/org/zwobble/couscous/ast/TernaryConditionalNode.java index f370b0a..c49bbc5 100644 --- a/src/main/java/org/zwobble/couscous/ast/TernaryConditionalNode.java +++ b/src/main/java/org/zwobble/couscous/ast/TernaryConditionalNode.java @@ -1,6 +1,7 @@ package org.zwobble.couscous.ast; import org.zwobble.couscous.ast.visitors.ExpressionNodeMapper; +import org.zwobble.couscous.ast.visitors.NodeTransformer; import java.util.function.Function; @@ -50,6 +51,13 @@ public class TernaryConditionalNode implements ExpressionNode { replace.apply(ifFalse)); } + public ExpressionNode transform(NodeTransformer transformer) { + return new TernaryConditionalNode( + transformer.visit(condition), + transformer.visit(ifTrue), + transformer.visit(ifFalse)); + } + @Override public TypeName getType() { return ifTrue.getType(); diff --git a/src/main/java/org/zwobble/couscous/ast/ThisReferenceNode.java b/src/main/java/org/zwobble/couscous/ast/ThisReferenceNode.java index a4851c8..6056abd 100644 --- a/src/main/java/org/zwobble/couscous/ast/ThisReferenceNode.java +++ b/src/main/java/org/zwobble/couscous/ast/ThisReferenceNode.java @@ -1,6 +1,7 @@ package org.zwobble.couscous.ast; import org.zwobble.couscous.ast.visitors.ExpressionNodeMapper; +import org.zwobble.couscous.ast.visitors.NodeTransformer; import java.util.function.Function; @@ -34,6 +35,10 @@ public class ThisReferenceNode implements ExpressionNode, ReferenceNode { return visitor.visit(this); } + public ExpressionNode transform(NodeTransformer transformer) { + return new ThisReferenceNode(transformer.transform(type)); + } + @Override public String toString() { return "ThisReferenceNode(type=" + type + ")"; diff --git a/src/main/java/org/zwobble/couscous/ast/TypeCoercionNode.java b/src/main/java/org/zwobble/couscous/ast/TypeCoercionNode.java index 1ffdd95..04ba7d1 100644 --- a/src/main/java/org/zwobble/couscous/ast/TypeCoercionNode.java +++ b/src/main/java/org/zwobble/couscous/ast/TypeCoercionNode.java @@ -1,6 +1,7 @@ package org.zwobble.couscous.ast; import org.zwobble.couscous.ast.visitors.ExpressionNodeMapper; +import org.zwobble.couscous.ast.visitors.NodeTransformer; import java.util.function.Function; @@ -36,6 +37,12 @@ public class TypeCoercionNode implements ExpressionNode { return new TypeCoercionNode(replace.apply(expression), type); } + public ExpressionNode transform(NodeTransformer transformer) { + return new TypeCoercionNode( + transformer.visit(expression), + transformer.transform(type)); + } + @Override public String toString() { return "TypeCoercionNode(" + diff --git a/src/main/java/org/zwobble/couscous/ast/VariableReferenceNode.java b/src/main/java/org/zwobble/couscous/ast/VariableReferenceNode.java index c1b022a..b907c6d 100644 --- a/src/main/java/org/zwobble/couscous/ast/VariableReferenceNode.java +++ b/src/main/java/org/zwobble/couscous/ast/VariableReferenceNode.java @@ -3,6 +3,7 @@ package org.zwobble.couscous.ast; import org.zwobble.couscous.ast.identifiers.Identifier; import org.zwobble.couscous.ast.visitors.AssignableExpressionNodeVisitor; import org.zwobble.couscous.ast.visitors.ExpressionNodeMapper; +import org.zwobble.couscous.ast.visitors.NodeTransformer; import java.util.function.Function; @@ -54,6 +55,10 @@ public class VariableReferenceNode implements AssignableExpressionNode, Referenc return visitor.visit(this); } + public ExpressionNode transform(NodeTransformer transformer) { + return new VariableReferenceNode(transformer.transform(referent)); + } + @Override public String toString() { return "VariableReferenceNode(referent=" + referent + ")"; diff --git a/src/main/java/org/zwobble/couscous/ast/WhileNode.java b/src/main/java/org/zwobble/couscous/ast/WhileNode.java index 6462821..34d1883 100644 --- a/src/main/java/org/zwobble/couscous/ast/WhileNode.java +++ b/src/main/java/org/zwobble/couscous/ast/WhileNode.java @@ -1,6 +1,7 @@ package org.zwobble.couscous.ast; import com.google.common.base.Objects; +import org.zwobble.couscous.ast.visitors.NodeTransformer; import org.zwobble.couscous.ast.visitors.StatementNodeMapper; import java.util.List; @@ -41,6 +42,12 @@ public class WhileNode implements StatementNode { eagerMap(body, statement -> statement.replaceExpressions(replace))); } + public StatementNode transform(NodeTransformer transformer) { + return new WhileNode( + transformer.visit(condition), + transformer.transformStatements(body)); + } + @Override public boolean equals(Object o) { if (this == o) return true; diff --git a/src/main/java/org/zwobble/couscous/ast/visitors/NodeTransformer.java b/src/main/java/org/zwobble/couscous/ast/visitors/NodeTransformer.java new file mode 100644 index 0000000..539acd0 --- /dev/null +++ b/src/main/java/org/zwobble/couscous/ast/visitors/NodeTransformer.java @@ -0,0 +1,185 @@ +package org.zwobble.couscous.ast.visitors; + +import com.google.common.base.Function; +import com.google.common.collect.ImmutableList; +import com.google.common.collect.ImmutableSet; +import com.google.common.collect.Iterables; +import org.zwobble.couscous.ast.*; + +import java.util.List; +import java.util.Set; + +public class NodeTransformer implements ExpressionNodeMapper<ExpressionNode>, StatementNodeMapper<StatementNode>, NodeMapper<Node> { + // TODO: tidy up transform vs visit + public TypeName transform(TypeName type) { + return type; + } + + public ExpressionNode visit(ExpressionNode value) { + return value.accept((ExpressionNodeMapper<ExpressionNode>)this); + } + + @Override + public ExpressionNode visit(LiteralNode literal) { + return literal.transform(this); + } + + @Override + public ExpressionNode visit(VariableReferenceNode variableReference) { + return variableReference.transform(this); + } + + @Override + public ExpressionNode visit(ThisReferenceNode reference) { + return reference.transform(this); + } + + @Override + public ExpressionNode visit(AssignmentNode assignment) { + return assignment.transform(this); + } + + @Override + public ExpressionNode visit(TernaryConditionalNode ternaryConditional) { + return ternaryConditional.transform(this); + } + + @Override + public ExpressionNode visit(MethodCallNode methodCall) { + return methodCall.transform(this); + } + + @Override + public ExpressionNode visit(ConstructorCallNode call) { + return call.transform(this); + } + + @Override + public ExpressionNode visit(FieldAccessNode fieldAccess) { + return fieldAccess.transform(this); + } + + @Override + public ExpressionNode visit(TypeCoercionNode typeCoercion) { + return typeCoercion.transform(this); + } + + @Override + public ExpressionNode visit(CastNode cast) { + return cast.transform(this); + } + + public Receiver visit(Receiver receiver) { + // TODO: remove cast + return (Receiver) receiver.accept(this); + } + + @Override + public Node visit(InstanceReceiver receiver) { + return receiver.transform(this); + } + + @Override + public Node visit(StaticReceiver receiver) { + return receiver.transform(this); + } + + public VariableDeclaration transform(VariableDeclaration declaration) { + return VariableDeclaration.var(declaration.getId(), declaration.getName(), transform(declaration.getType())); + } + + public StatementNode visit(StatementNode statement) { + return statement.accept((StatementNodeMapper<StatementNode>)this); + } + + @Override + public StatementNode visit(ReturnNode returnNode) { + return returnNode.transform(this); + } + + @Override + public StatementNode visit(ExpressionStatementNode expressionStatement) { + return expressionStatement.transform(this); + } + + @Override + public StatementNode visit(LocalVariableDeclarationNode localVariableDeclaration) { + return localVariableDeclaration.transform(this); + } + + @Override + public StatementNode visit(IfStatementNode ifStatement) { + return ifStatement.transform(this); + } + + @Override + public StatementNode visit(WhileNode whileLoop) { + return whileLoop.transform(this); + } + + @Override + public FormalArgumentNode visit(FormalArgumentNode formalArgumentNode) { + return formalArgumentNode.transform(this); + } + + @Override + public AnnotationNode visit(AnnotationNode annotation) { + return annotation.transform(this); + } + + @Override + public MethodNode visit(MethodNode method) { + return method.transform(this); + } + + @Override + public ConstructorNode visit(ConstructorNode constructor) { + return constructor.transform(this); + } + + @Override + public FieldDeclarationNode visit(FieldDeclarationNode field) { + return field.transform(this); + } + + @Override + public ClassNode visit(ClassNode classNode) { + return classNode.transform(this); + } + + public List<AnnotationNode> transformAnnotations(List<AnnotationNode> annotations) { + return transformList(annotations, this::visit); + } + + public Set<TypeName> transformTypes(Set<TypeName> superTypes) { + return transformSet(superTypes, this::transform); + } + + public List<FieldDeclarationNode> transformFields(List<FieldDeclarationNode> fields) { + return transformList(fields, this::visit); + } + + public List<MethodNode> transformMethods(List<MethodNode> methods) { + return transformList(methods, this::visit); + } + + public List<StatementNode> transformStatements(List<StatementNode> body) { + return transformList(body, this::visit); + } + + public List<ExpressionNode> transformExpressions(List<? extends ExpressionNode> expressions) { + return transformList(expressions, this::visit); + } + + public List<FormalArgumentNode> transformFormalArguments(List<FormalArgumentNode> arguments) { + return transformList(arguments, this::visit); + } + + private <T> Set<T> transformSet(Set<T> values, Function<T, T> function) { + return ImmutableSet.copyOf(Iterables.transform(values, function)); + } + + private <T> List<T> transformList(List<? extends T> values, Function<T, T> function) { + return ImmutableList.copyOf(Iterables.transform(values, function)); + } +} |
