blob: 3fe1d5e8142a8a6519ad246ab39bb092347817f4 (
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
140
141
142
143
144
145
146
147
148
149
150
151
|
package org.zwobble.couscous.backends.csharp;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.Iterables;
import com.google.common.io.Resources;
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.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.List;
import static com.google.common.collect.Iterables.transform;
public class CsharpBackend implements Backend {
private static final List<String> RUNTIME_FILES = ImmutableList.of(
"java/lang/String.cs");
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)),
transform(
RUNTIME_FILES,
runtimeFile -> readRuntimeFile(runtimeFile))));
}
private String readRuntimeFile(String runtimeFile) {
try {
return Resources.toString(Resources.getResource("csharp/runtime/" + runtimeFile), StandardCharsets.UTF_8);
} catch (IOException exception) {
throw new RuntimeException(exception);
}
}
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();
}
});
}
}
|