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
|
package org.zwobble.couscous.backends.csharp;
import com.google.common.collect.ImmutableMap;
import org.zwobble.couscous.ast.ExpressionNode;
import org.zwobble.couscous.ast.types.ScalarType;
import org.zwobble.couscous.values.BooleanValue;
import org.zwobble.couscous.values.IntegerValue;
import org.zwobble.couscous.values.ObjectValues;
import org.zwobble.couscous.values.StringValue;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import static org.zwobble.couscous.ast.FieldAccessNode.fieldAccess;
import static org.zwobble.couscous.ast.MethodCallNode.methodCall;
import static org.zwobble.couscous.ast.MethodCallNode.staticMethodCall;
import static org.zwobble.couscous.ast.Operations.integerSubtract;
import static org.zwobble.couscous.util.ExtraLists.list;
public class CsharpPrimitiveMethods {
private static final Map<String, PrimitiveMethodGenerator> BOOLEAN_METHODS;
static {
ImmutableMap.Builder<String, PrimitiveMethodGenerator> methods = ImmutableMap.builder();
BOOLEAN_METHODS = methods.build();
}
private static final Map<String, PrimitiveMethodGenerator> BOXED_INT_METHODS;
static {
ImmutableMap.Builder<String, PrimitiveMethodGenerator> methods = ImmutableMap.builder();
methods.put("toString", ((receiver, arguments) -> methodCall(
receiver,
"ToString",
list(),
StringValue.REF)));
BOXED_INT_METHODS = methods.build();
}
private static final Map<String, PrimitiveMethodGenerator> STRING_METHODS;
static {
ImmutableMap.Builder<String, PrimitiveMethodGenerator> methods = ImmutableMap.builder();
methods.put("length", (receiver, arguments) -> fieldAccess(receiver, "Length", IntegerValue.REF));
methods.put("substring", (receiver, arguments) -> {
ExpressionNode startIndex = arguments.get(0);
ExpressionNode endIndex = arguments.get(1);
ExpressionNode length = integerSubtract(endIndex, startIndex);
// TODO: handle length going beyond end-of-string
return methodCall(
receiver,
"Substring",
list(startIndex, length),
StringValue.REF);
});
methods.put("toLowerCase", (receiver, arguments) -> methodCall(
receiver,
"ToLower",
list(),
StringValue.REF));
methods.put("equals", (receiver, arguments) -> methodCall(
receiver,
"Equals",
arguments,
StringValue.REF));
STRING_METHODS = methods.build();
}
private static final Map<ScalarType, Map<String, PrimitiveMethodGenerator>> METHODS =
ImmutableMap.<ScalarType, Map<String, PrimitiveMethodGenerator>>builder()
.put(BooleanValue.REF, BOOLEAN_METHODS)
.put(StringValue.REF, STRING_METHODS)
.put(ObjectValues.BOXED_INT, BOXED_INT_METHODS)
.build();
private static final Map<String, PrimitiveStaticMethodGenerator> STATIC_INT_METHODS =
ImmutableMap.<String, PrimitiveStaticMethodGenerator>builder()
.put("parseInt", arguments -> staticMethodCall(
ScalarType.of("int"),
"Parse",
list(arguments.get(0)),
ScalarType.of("int")))
.build();
private static final Map<ScalarType, Map<String, PrimitiveStaticMethodGenerator>> STATIC_METHODS =
ImmutableMap.<ScalarType, Map<String, PrimitiveStaticMethodGenerator>>builder()
.put(ObjectValues.BOXED_INT, STATIC_INT_METHODS)
.build();
public static Optional<PrimitiveMethodGenerator> getPrimitiveMethod(ScalarType type, String methodName) {
return Optional.ofNullable(METHODS.get(type))
.flatMap(methodsForType -> Optional.ofNullable(methodsForType.get(methodName)));
}
@FunctionalInterface
public interface PrimitiveMethodGenerator {
ExpressionNode generate(ExpressionNode receiver, List<ExpressionNode> arguments);
}
public static Optional<PrimitiveStaticMethodGenerator> getPrimitiveStaticMethod(ScalarType type, String methodName) {
return Optional.ofNullable(STATIC_METHODS.get(type))
.flatMap(methodsForType -> Optional.ofNullable(methodsForType.get(methodName)));
}
@FunctionalInterface
public interface PrimitiveStaticMethodGenerator {
ExpressionNode generate(List<ExpressionNode> arguments);
}
}
|