aboutsummaryrefslogtreecommitdiff
path: root/src/main/java/org/zwobble
diff options
context:
space:
mode:
Diffstat (limited to 'src/main/java/org/zwobble')
-rw-r--r--src/main/java/org/zwobble/couscous/ast/AnnotationNode.java5
-rw-r--r--src/main/java/org/zwobble/couscous/ast/AssignmentNode.java7
-rw-r--r--src/main/java/org/zwobble/couscous/ast/CastNode.java5
-rw-r--r--src/main/java/org/zwobble/couscous/ast/ClassNode.java10
-rw-r--r--src/main/java/org/zwobble/couscous/ast/ConstructorCallNode.java11
-rw-r--r--src/main/java/org/zwobble/couscous/ast/ConstructorNode.java9
-rw-r--r--src/main/java/org/zwobble/couscous/ast/ExpressionStatementNode.java5
-rw-r--r--src/main/java/org/zwobble/couscous/ast/FieldAccessNode.java8
-rw-r--r--src/main/java/org/zwobble/couscous/ast/FieldDeclarationNode.java8
-rw-r--r--src/main/java/org/zwobble/couscous/ast/FormalArgumentNode.java5
-rw-r--r--src/main/java/org/zwobble/couscous/ast/IfStatementNode.java8
-rw-r--r--src/main/java/org/zwobble/couscous/ast/InstanceReceiver.java5
-rw-r--r--src/main/java/org/zwobble/couscous/ast/LiteralNode.java13
-rw-r--r--src/main/java/org/zwobble/couscous/ast/LocalVariableDeclarationNode.java7
-rw-r--r--src/main/java/org/zwobble/couscous/ast/MethodCallNode.java9
-rw-r--r--src/main/java/org/zwobble/couscous/ast/MethodNode.java11
-rw-r--r--src/main/java/org/zwobble/couscous/ast/ReturnNode.java7
-rw-r--r--src/main/java/org/zwobble/couscous/ast/StaticReceiver.java5
-rw-r--r--src/main/java/org/zwobble/couscous/ast/TernaryConditionalNode.java8
-rw-r--r--src/main/java/org/zwobble/couscous/ast/ThisReferenceNode.java5
-rw-r--r--src/main/java/org/zwobble/couscous/ast/TypeCoercionNode.java7
-rw-r--r--src/main/java/org/zwobble/couscous/ast/VariableReferenceNode.java5
-rw-r--r--src/main/java/org/zwobble/couscous/ast/WhileNode.java7
-rw-r--r--src/main/java/org/zwobble/couscous/ast/visitors/NodeTransformer.java185
-rw-r--r--src/main/java/org/zwobble/couscous/backends/csharp/CsharpCodeGenerator.java68
-rw-r--r--src/main/java/org/zwobble/couscous/backends/csharp/CsharpPrimitiveMethods.java19
-rw-r--r--src/main/java/org/zwobble/couscous/backends/csharp/CsharpSerializer.java67
27 files changed, 440 insertions, 69 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));
+ }
+}
diff --git a/src/main/java/org/zwobble/couscous/backends/csharp/CsharpCodeGenerator.java b/src/main/java/org/zwobble/couscous/backends/csharp/CsharpCodeGenerator.java
new file mode 100644
index 0000000..9e48e9a
--- /dev/null
+++ b/src/main/java/org/zwobble/couscous/backends/csharp/CsharpCodeGenerator.java
@@ -0,0 +1,68 @@
+package org.zwobble.couscous.backends.csharp;
+
+import com.google.common.collect.ImmutableMap;
+import org.zwobble.couscous.ast.*;
+import org.zwobble.couscous.ast.visitors.NodeTransformer;
+import org.zwobble.couscous.values.*;
+
+import java.util.Map;
+import java.util.Optional;
+
+public class CsharpCodeGenerator extends NodeTransformer {
+ private final static Map<TypeName, TypeName> PRIMITIVES = ImmutableMap.<TypeName, TypeName>builder()
+ .put(IntegerValue.REF, TypeName.of("int"))
+ .put(StringValue.REF, TypeName.of("string"))
+ .put(BooleanValue.REF, TypeName.of("bool"))
+ .put(ObjectValues.OBJECT, TypeName.of("object"))
+ .put(ObjectValues.CLASS, TypeName.of("System.Type"))
+ .put(UnitValue.REF, TypeName.of("void"))
+ .build();
+
+ private final String namespace;
+
+ public static Node generateCode(Node node, String namespace) {
+ return new CsharpCodeGenerator(namespace).generateCode(node);
+ }
+
+ private CsharpCodeGenerator(String namespace) {
+ this.namespace = namespace;
+ }
+
+ private Node generateCode(Node node) {
+ return node.accept(this);
+ }
+
+ @Override
+ public TypeName transform(TypeName type) {
+ if (PRIMITIVES.containsKey(type)) {
+ return PRIMITIVES.get(type);
+ } else {
+ return addPrefix(type, namespace);
+ }
+ }
+
+ @Override
+ public ExpressionNode visit(MethodCallNode call) {
+ return toPrimitiveMethod(call).orElseGet(() -> super.visit(call));
+ }
+
+ private Optional<ExpressionNode> toPrimitiveMethod(MethodCallNode call) {
+ return call.getReceiver().accept(new Receiver.Mapper<Optional<ExpressionNode>>() {
+ @Override
+ public Optional<ExpressionNode> visit(ExpressionNode receiver) {
+ return Optional.empty();
+ }
+
+ @Override
+ public Optional<ExpressionNode> visit(TypeName receiver) {
+ return CsharpPrimitiveMethods.getPrimitiveStaticMethod(receiver, call.getMethodName())
+ .map(generator -> generator.generate(call.getArguments()));
+ }
+ });
+
+ }
+
+ private TypeName addPrefix(TypeName name, String namespace) {
+ return TypeName.of(namespace + "." + name.getQualifiedName());
+ }
+}
diff --git a/src/main/java/org/zwobble/couscous/backends/csharp/CsharpPrimitiveMethods.java b/src/main/java/org/zwobble/couscous/backends/csharp/CsharpPrimitiveMethods.java
index b53560d..9424b2d 100644
--- a/src/main/java/org/zwobble/couscous/backends/csharp/CsharpPrimitiveMethods.java
+++ b/src/main/java/org/zwobble/couscous/backends/csharp/CsharpPrimitiveMethods.java
@@ -3,25 +3,24 @@ package org.zwobble.couscous.backends.csharp;
import com.google.common.collect.ImmutableMap;
import org.zwobble.couscous.ast.ExpressionNode;
import org.zwobble.couscous.ast.TypeName;
-import org.zwobble.couscous.backends.SourceCodeWriter;
import org.zwobble.couscous.values.ObjectValues;
import java.util.List;
import java.util.Map;
import java.util.Optional;
+import static org.zwobble.couscous.ast.MethodCallNode.staticMethodCall;
+import static org.zwobble.couscous.util.ExtraLists.list;
+
public class CsharpPrimitiveMethods {
private static final Map<String, PrimitiveStaticMethodGenerator> STATIC_INT_METHODS =
ImmutableMap.<String, PrimitiveStaticMethodGenerator>builder()
- .put("parseInt", (arguments, writer) -> {
- writer.writeIdentifier("int");
- writer.writeSymbol(".");
- writer.writeIdentifier("Parse");
- writer.writeSymbol("(");
- writer.writeIdentifier(CsharpSerializer.serialize(arguments.get(0), ""));
- writer.writeSymbol(")");
- })
+ .put("parseInt", arguments -> staticMethodCall(
+ TypeName.of("int"),
+ "Parse",
+ list(arguments.get(0)),
+ TypeName.of("int")))
.build();
@@ -37,6 +36,6 @@ public class CsharpPrimitiveMethods {
@FunctionalInterface
public interface PrimitiveStaticMethodGenerator {
- void generate(List<ExpressionNode> arguments, SourceCodeWriter writer);
+ ExpressionNode generate(List<ExpressionNode> arguments);
}
}
diff --git a/src/main/java/org/zwobble/couscous/backends/csharp/CsharpSerializer.java b/src/main/java/org/zwobble/couscous/backends/csharp/CsharpSerializer.java
index 275ae13..ffd2f02 100644
--- a/src/main/java/org/zwobble/couscous/backends/csharp/CsharpSerializer.java
+++ b/src/main/java/org/zwobble/couscous/backends/csharp/CsharpSerializer.java
@@ -1,24 +1,13 @@
package org.zwobble.couscous.backends.csharp;
-import com.google.common.collect.ImmutableMap;
import org.zwobble.couscous.ast.*;
import org.zwobble.couscous.ast.visitors.NodeVisitor;
import org.zwobble.couscous.backends.SourceCodeWriter;
-import org.zwobble.couscous.values.*;
+import org.zwobble.couscous.values.PrimitiveValueVisitor;
import java.util.List;
-import java.util.Map;
public class CsharpSerializer implements NodeVisitor {
- private final static Map<TypeName, String> PRIMITIVES = ImmutableMap.<TypeName, String>builder()
- .put(IntegerValue.REF, "int")
- .put(StringValue.REF, "string")
- .put(BooleanValue.REF, "bool")
- .put(ObjectValues.OBJECT, "object")
- .put(ObjectValues.CLASS, "System.Type")
- .put(UnitValue.REF, "void")
- .build();
-
public static String serialize(Node node, String namespace) {
SourceCodeWriter writer = new SourceCodeWriter(
(writer2) -> {
@@ -29,17 +18,16 @@ public class CsharpSerializer implements NodeVisitor {
writer2.writeStatement(() -> writer2.writeSymbol("}"));
}
);
- CsharpSerializer serializer = new CsharpSerializer(writer, namespace);
- serializer.write(node);
+ CsharpSerializer serializer = new CsharpSerializer(writer);
+
+ serializer.write(CsharpCodeGenerator.generateCode(node, namespace));
return writer.asString();
}
private final SourceCodeWriter writer;
- private final String namespace;
- private CsharpSerializer(SourceCodeWriter writer, String namespace) {
+ private CsharpSerializer(SourceCodeWriter writer) {
this.writer = writer;
- this.namespace = namespace;
}
private void write(Node node) {
@@ -117,32 +105,10 @@ public class CsharpSerializer implements NodeVisitor {
@Override
public void visit(MethodCallNode methodCall) {
- if (!writePrimitiveMethod(methodCall)) {
- write(methodCall.getReceiver());
- writer.writeSymbol(".");
- writer.writeIdentifier(methodCall.getMethodName());
- writeArguments(methodCall.getArguments());
- }
- }
-
- private boolean writePrimitiveMethod(MethodCallNode methodCall) {
- return methodCall.getReceiver().accept(new Receiver.Mapper<Boolean>() {
- @Override
- public Boolean visit(ExpressionNode receiver) {
- return false;
- }
-
- @Override
- public Boolean visit(TypeName receiver) {
- // TODO: transform AST before serialisation instead of exposing write to CsharpPrimitiveMethods
- return CsharpPrimitiveMethods.getPrimitiveStaticMethod(receiver, methodCall.getMethodName())
- .map(generator -> {
- generator.generate(methodCall.getArguments(), writer);
- return true;
- })
- .orElse(false);
- }
- });
+ write(methodCall.getReceiver());
+ writer.writeSymbol(".");
+ writer.writeIdentifier(methodCall.getMethodName());
+ writeArguments(methodCall.getArguments());
}
@Override
@@ -278,13 +244,9 @@ public class CsharpSerializer implements NodeVisitor {
@Override
public void visit(ClassNode classNode) {
- String namespace = this.namespace +
- classNode.getName().getPackage()
- .map(packageName -> "." + packageName)
- .orElse("");
writer.writeKeyword("namespace");
writer.writeSpace();
- writer.writeIdentifier(namespace);
+ writer.writeIdentifier(classNode.getName().getPackage().get());
writer.startBlock();
writer.writeStatement(() -> {
writer.writeKeyword("internal");
@@ -323,15 +285,10 @@ public class CsharpSerializer implements NodeVisitor {
}
private void writeTypeReference(TypeName value) {
- // TODO: process the nodes before serialization
- if (PRIMITIVES.containsKey(value)) {
- writer.writeIdentifier(PRIMITIVES.get(value));
- } else {
- writer.writeIdentifier(typeReference(value));
- }
+ writer.writeIdentifier(typeReference(value));
}
private String typeReference(TypeName value) {
- return namespace + "." + value.getQualifiedName();
+ return value.getQualifiedName();
}
}