aboutsummaryrefslogtreecommitdiff
path: root/src/main/java/org/zwobble/couscous/backends/csharp/CsharpBackend.java
blob: f8a2d506cf22b86b70613abc0b3bb8ce85d69f23 (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
package org.zwobble.couscous.backends.csharp;

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;

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"),
            transform(
                classes,
                classNode -> compileClass(classNode)
        ));
    }

    private String compileClass(ClassNode classNode) {
        String namespace = this.namespace +
            classNode.getName().getPackage()
                .map(packageName -> packageName + ".")
                .orElse("");
        return "namespace " + namespace + " {" +
            "    public 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 string " + 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) {
                        throw new UnsupportedOperationException();
                    }
                });
            }

            @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();
            }
        });
    }
}