-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathLambda.java
More file actions
127 lines (107 loc) · 3.8 KB
/
Copy pathLambda.java
File metadata and controls
127 lines (107 loc) · 3.8 KB
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
package jtree.nodes;
import static jtree.util.Utils.*;
import java.util.List;
import java.util.Objects;
import java.util.function.Consumer;
import jtree.util.Either;
import jtree.util.Utils;
import lombok.EqualsAndHashCode;
import lombok.Getter;
import lombok.Setter;
import lombok.NonNull;
@EqualsAndHashCode
@Getter @Setter
public class Lambda extends Node implements Expression {
protected @NonNull Either<? extends List<FormalParameter>, ? extends List<InformalParameter>> parameters;
protected @NonNull Either<Block, ? extends Expression> body;
public Lambda(List<? extends LambdaParameter> parameters, Block body) {
this(makeParameters(parameters), body);
}
public Lambda(List<? extends LambdaParameter> parameters, Expression body) {
this(makeParameters(parameters), body);
}
public Lambda(List<? extends LambdaParameter> parameters, Either<Block, ? extends Expression> body) {
this(makeParameters(parameters), body);
}
public Lambda(Either<? extends List<FormalParameter>, ? extends List<InformalParameter>> parameters, Block body) {
this(parameters, Either.first(body));
}
public Lambda(Either<? extends List<FormalParameter>, ? extends List<InformalParameter>> parameters, Expression body) {
this(parameters, Either.second(body));
}
public Lambda(Either<? extends List<FormalParameter>, ? extends List<InformalParameter>> parameters, Either<Block, ? extends Expression> body) {
setParameters(parameters);
setBody(body);
}
@SuppressWarnings("unchecked")
private static Either<? extends List<FormalParameter>, ? extends List<InformalParameter>> makeParameters(List<? extends LambdaParameter> parameters) {
if(parameters.isEmpty()) {
return Either.second(emptyList());
} else {
var first = parameters.get(0);
if(first instanceof InformalParameter) {
for(int i = 1; i < parameters.size(); i++) {
InformalParameter.class.cast(parameters.get(i));
}
return Either.second((List<InformalParameter>)parameters);
} else {
for(var param : parameters) {
FormalParameter.class.cast(param);
}
return Either.first((List<FormalParameter>)parameters);
}
}
}
@Override
public Precedence precedence() {
return Precedence.ASSIGNMENT;
}
@Override
public Lambda clone() {
return new Lambda(clone(getParameters()), clone(getBody()));
}
@Override
public String toCode() {
String result;
var eitherParameters = getParameters();
if(eitherParameters.isFirst()) {
result = "(" + joinNodes(", ", eitherParameters.first()) + ")";
} else {
var parameters = eitherParameters.second();
if(parameters.size() == 1) {
result = parameters.get(0).toCode();
} else {
result = "(" + joinNodes(", ", parameters) + ")";
}
}
result += " -> ";
var body = getBody();
if(body.isFirst()) {
var block = body.first();
result += block.isEmpty()? "{}" : block.toCode();
} else {
result += body.second().toCode();
}
return result;
}
public void setParameters(@NonNull Either<? extends List<FormalParameter>, ? extends List<InformalParameter>> parameters) {
this.parameters = parameters.map(Utils::newList, Utils::newList);
}
public void setBody(@NonNull Either<Block, ? extends Expression> body) {
Objects.requireNonNull(body.getValue());
this.body = body;
}
public final void setBody(Block body) {
setBody(Either.first(body));
}
public final void setBody(Expression body) {
setBody(Either.second(body));
}
@Override
public <N extends INode> void accept(TreeVisitor visitor, Node parent, Consumer<N> replacer) {
if(visitor.visitLambda(this, parent, cast(replacer))) {
getParameters().accept(params -> visitList(visitor, params), params -> visitList(visitor, params));
getBody().accept(block -> block.<Block>accept(visitor, this, this::setBody), expr -> expr.<Expression>accept(visitor, this, this::setBody));
}
}
}