-
Notifications
You must be signed in to change notification settings - Fork 34
/
Expr.java
191 lines (150 loc) · 5.22 KB
/
Expr.java
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
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
package com.stuffwithstuff.magpie.ast;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import com.stuffwithstuff.magpie.ast.pattern.MatchCase;
import com.stuffwithstuff.magpie.ast.pattern.Pattern;
import com.stuffwithstuff.magpie.parser.Position;
import com.stuffwithstuff.magpie.util.Pair;
/**
* Base class for AST expression node classes. Any chunk of Magpie code can be
* represented by an instance of one of the subclasses of this class.
*
* <p>Also includes factory methods to create the appropriate nodes. Aside from
* being a bit more terse, these methods perform some basic desugaring and
* simplification such as expanding special forms and discarding useless nodes.
*
* @author bob
*/
public abstract class Expr {
public static Expr assign(Position position, Expr receiver, String name,
Expr value) {
return new AssignExpr(position, receiver, name, value);
}
public static Expr bool(boolean value) {
return bool(Position.none(), value);
}
public static Expr bool(Position position, boolean value) {
return new BoolExpr(position, value);
}
public static Expr block(List<Expr> exprs) {
return block(exprs, null);
}
public static Expr block(List<Expr> exprs, Expr catchExpr) {
// Discard unneeded blocks.
if (catchExpr == null) {
switch (exprs.size()) {
case 0:
return nothing();
case 1:
return exprs.get(0);
default:
return new BlockExpr(exprs, null);
}
} else {
return new BlockExpr(exprs, catchExpr);
}
}
public static Expr block(Expr... exprs) {
return new BlockExpr(Arrays.asList(exprs));
}
public static Expr break_(Position position) {
return new BreakExpr(position);
}
public static FnExpr fn(Expr body) {
return new FnExpr(Position.none(), body);
}
public static FnExpr fn(Position position, Expr body) {
return new FnExpr(position, body);
}
public static FnExpr fn(Position position, Pattern pattern, Expr body) {
return new FnExpr(position, pattern, body);
}
// TODO(bob): Hackish. Eliminate.
public static Expr if_(Expr condition, Expr thenExpr, Expr elseExpr) {
List<MatchCase> cases = new ArrayList<MatchCase>();
cases.add(new MatchCase(Pattern.value(Expr.bool(true)), thenExpr));
cases.add(new MatchCase(elseExpr));
return match(Position.surrounding(condition, elseExpr),
condition,
cases);
}
public static Expr int_(int value) {
return int_(Position.none(), value);
}
public static Expr int_(Position position, int value) {
return new IntExpr(position, value);
}
public static Expr loop(Position position, Expr body) {
return new LoopExpr(position, body);
}
public static Expr match(Position position,
Expr value, List<MatchCase> cases) {
return new MatchExpr(position, value, cases);
}
public static Expr message(Position position, Expr receiver, String name, Expr arg) {
return new MessageExpr(position, receiver, name, arg);
}
public static Expr message(Position position, Expr receiver, String name) {
return message(position, receiver, name, Expr.nothing());
}
public static Expr method(Position position, String name, Pattern pattern, Expr body) {
return new MethodExpr(position, name, pattern, body);
}
public static Expr name(Position position, String name) {
return message(position, null, name, null);
}
public static Expr name(String name) {
return name(Position.none(), name);
}
public static Expr nothing() {
return nothing(Position.none());
}
public static Expr nothing(Position position) {
return new NothingExpr(Position.none());
}
public static Expr record(Position position,
List<Pair<String, Expr>> fields) {
return new RecordExpr(position, fields);
}
public static Expr scope(Expr body) {
// Unwrap redundant scopes.
if (body instanceof ScopeExpr) return body;
return new ScopeExpr(body);
}
public static Expr string(String text) {
return string(Position.none(), text);
}
public static Expr string(Position position, String text) {
return new StringExpr(position, text);
}
public static Expr tuple(List<Expr> fields) {
return new TupleExpr(fields);
}
public static Expr tuple(Expr... fields) {
return new TupleExpr(Arrays.asList(fields));
}
public static Expr var(String name, Expr value) {
return var(value.getPosition(), name, value);
}
public static Expr var(Position position, String name, Expr value) {
return var(position, Pattern.variable(name), value);
}
public static Expr var(Position position, Pattern pattern, Expr value) {
return new VariableExpr(position, pattern, value);
}
public Expr(Position position) {
mPosition = position;
}
public Position getPosition() { return mPosition; }
public abstract <TReturn, TContext> TReturn accept(
ExprVisitor<TReturn, TContext> visitor, TContext context);
@Override
public String toString() {
StringBuilder builder = new StringBuilder();
toString(builder, "");
return builder.toString();
}
public abstract void toString(StringBuilder builder, String indent);
private final Position mPosition;
}