summaryrefslogtreecommitdiff
path: root/dice-lang/src/main/java/bjc/dicelang/ast/DiceASTInliner.java
blob: 7f5f2d77298adc8e46f9daec11c0409d88c0cec9 (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
package bjc.dicelang.ast;

import bjc.utils.funcdata.FunctionalList;
import bjc.utils.funcdata.IList;
import bjc.utils.funcdata.IMap;
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,
			IMap<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,
			IMap<String, ITree<IDiceASTNode>> enviroment,
			boolean specificInline, IList<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,
			IMap<String, ITree<IDiceASTNode>> enviroment,
			IList<String> variables) {
		return selectiveInline(ast, enviroment,
				variables.toArray(new String[0]));
	}

	/**
	 * 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,
			IMap<String, ITree<IDiceASTNode>> enviroment,
			String... variables) {
		if (variables != null && variables.length > 0) {
			IList<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);
		});
	}
}