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
|
package bjc.dicelang.ast;
import bjc.utils.funcdata.FunctionalList;
import bjc.utils.funcdata.IFunctionalList;
import bjc.utils.funcdata.IFunctionalMap;
import bjc.utils.funcdata.ITree;
import bjc.utils.funcdata.Tree;
import bjc.dicelang.ast.nodes.DiceASTType;
import bjc.dicelang.ast.nodes.IDiceASTNode;
import bjc.dicelang.ast.nodes.VariableDiceNode;
/**
* Inline variables in a dice AST
*
* @author ben
*
*/
public class DiceASTInliner {
/**
* Inline all the variables in the AST
*
* @param ast
* The AST to inline variables into
* @param enviroment
* The enviroment to inline from
* @return The inlined AST
*/
public static ITree<IDiceASTNode> inlineAll(ITree<IDiceASTNode> ast,
IFunctionalMap<String, ITree<IDiceASTNode>> enviroment) {
// Tell the compiler that the null is for the entire varargs
// parameter, not a single one with a null value
return selectiveInline(ast, enviroment, (String[]) null);
}
private static ITree<IDiceASTNode> inlineNode(IDiceASTNode node,
IFunctionalMap<String, ITree<IDiceASTNode>> enviroment,
boolean specificInline,
IFunctionalList<String> variableNames) {
if (node.getType() != DiceASTType.VARIABLE) {
return new Tree<>(node);
}
String variableName = ((VariableDiceNode) node).getVariable();
if (specificInline) {
if (variableNames.contains(variableName)) {
if (!enviroment.containsKey(variableName)) {
throw new UnsupportedOperationException(
"Attempted to inline non-existant variable "
+ variableName);
}
return enviroment.get(variableName);
}
} else {
if (!enviroment.containsKey(variableName)) {
throw new UnsupportedOperationException(
"Attempted to inline non-existant variable "
+ variableName);
}
return enviroment.get(variableName);
}
return new Tree<>(node);
}
/**
* Inline the specified variables in the AST
*
* @param ast
* The AST to inline variables into
* @param enviroment
* The enviroment to inline from
* @param variables
* The variables to inline
* @return The inlined AST
*/
public static ITree<IDiceASTNode> selectiveInline(
ITree<IDiceASTNode> ast,
IFunctionalMap<String, ITree<IDiceASTNode>> enviroment,
String... variables) {
if (variables != null && variables.length > 0) {
IFunctionalList<String> variableNames = new FunctionalList<>(
variables);
return ast.flatMapTree((node) -> {
return inlineNode(node, enviroment, true, variableNames);
});
}
return ast.flatMapTree((node) -> {
return inlineNode(node, enviroment, false, null);
});
}
/**
* Inline the specified variables in the AST
*
* @param ast
* The AST to inline variables into
* @param enviroment
* The enviroment to inline from
* @param variables
* The variables to inline
* @return The inlined AST
*/
public static ITree<IDiceASTNode> selectiveInline(
ITree<IDiceASTNode> ast,
IFunctionalMap<String, ITree<IDiceASTNode>> enviroment,
IFunctionalList<String> variables) {
return selectiveInline(ast, enviroment,
variables.toArray(new String[0]));
}
}
|