blob: adf306ff19bb43416e83973e5ba26b661afb39ee (
plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
|
package org.zwobble.couscous.backends.csharp;
import com.google.common.collect.Iterables;
import org.zwobble.couscous.Backend;
import org.zwobble.couscous.ast.*;
import org.zwobble.couscous.ast.visitors.ExpressionNodeMapper;
import org.zwobble.couscous.values.PrimitiveValueVisitor;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.List;
import static com.google.common.collect.Iterables.transform;
import static org.zwobble.couscous.util.ExtraLists.list;
public class CsharpBackend implements Backend {
private final Path directoryPath;
private final String namespace;
public CsharpBackend(Path directoryPath, String namespace) {
this.directoryPath = directoryPath;
this.namespace = namespace;
}
@Override
public void compile(List<ClassNode> classes) throws IOException {
Files.write(
directoryPath.resolve("Program.cs"),
Iterables.concat(
transform(
classes,
classNode -> compileClass(classNode)),
list(
"namespace " + namespace + ".java.lang {" +
" internal class String { }" +
"}")));
}
private String compileClass(ClassNode classNode) {
String namespace = this.namespace +
classNode.getName().getPackage()
.map(packageName -> packageName + ".")
.orElse("");
return "namespace " + namespace + " {" +
" internal class " + classNode.getSimpleName() + " {" +
String.join("\n", transform(classNode.getMethods(), method -> compileMethod(method))) +
" }" +
"}";
}
private String compileMethod(MethodNode method) {
ReturnNode returnNode = (ReturnNode) method.getBody().get(0);
return
"public static dynamic " + method.getName() + "() {" +
" return " + compileExpression(returnNode.getValue()) + ";" +
"}";
}
private String compileExpression(ExpressionNode value) {
return value.accept(new ExpressionNodeMapper<String>() {
@Override
public String visit(LiteralNode literal) {
return literal.getValue().accept(new PrimitiveValueVisitor<String>() {
@Override
public String visitInteger(int value) {
return Integer.toString(value);
}
@Override
public String visitString(String value) {
// TODO: escaping
return "\"" + value + "\"";
}
@Override
public String visitBoolean(boolean value) {
return value ? "true" : "false";
}
@Override
public String visitUnit() {
throw new UnsupportedOperationException();
}
@Override
public String visitType(TypeName value) {
return "typeof(" + namespace + "." + value.getQualifiedName() + ")";
}
});
}
@Override
public String visit(VariableReferenceNode variableReference) {
throw new UnsupportedOperationException();
}
@Override
public String visit(ThisReferenceNode reference) {
throw new UnsupportedOperationException();
}
@Override
public String visit(AssignmentNode assignment) {
throw new UnsupportedOperationException();
}
@Override
public String visit(TernaryConditionalNode ternaryConditional) {
throw new UnsupportedOperationException();
}
@Override
public String visit(MethodCallNode methodCall) {
throw new UnsupportedOperationException();
}
@Override
public String visit(ConstructorCallNode call) {
throw new UnsupportedOperationException();
}
@Override
public String visit(FieldAccessNode fieldAccess) {
throw new UnsupportedOperationException();
}
@Override
public String visit(TypeCoercionNode typeCoercion) {
throw new UnsupportedOperationException();
}
@Override
public String visit(CastNode cast) {
throw new UnsupportedOperationException();
}
});
}
}
|