summaryrefslogtreecommitdiff
path: root/dice-lang/src/bjc/dicelang/ast/optimization/ArithmeticCollapser.java
blob: 69cc3793d48ac692e7462431553e87f5fdc32c20 (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
package bjc.dicelang.ast.optimization;

import java.util.function.BinaryOperator;

import bjc.utils.data.ITree;
import bjc.utils.funcdata.IList;
import bjc.utils.data.Tree;

import bjc.dicelang.ast.DiceASTUtils;
import bjc.dicelang.ast.nodes.DiceASTType;
import bjc.dicelang.ast.nodes.IDiceASTNode;
import bjc.dicelang.ast.nodes.ILiteralDiceNode;
import bjc.dicelang.ast.nodes.IntegerLiteralNode;
import bjc.dicelang.ast.nodes.OperatorDiceNode;

class ArithmeticCollapser {
	private BinaryOperator<Integer>	reducer;
	private OperatorDiceNode		type;

	public ArithmeticCollapser(BinaryOperator<Integer> reducr,
			OperatorDiceNode typ) {
		reducer = reducr;
		this.type = typ;
	}

	public ITree<IDiceASTNode> collapse(
			IList<ITree<IDiceASTNode>> children) {
		boolean allConstant = children.allMatch((subtree) -> {
			return subtree.transformHead((node) -> {
				if (node.getType() == DiceASTType.LITERAL) {
					return ((ILiteralDiceNode) node).canOptimize();
				}

				return false;
			});
		});

		if (!allConstant) {
			return new Tree<>(type, children);
		}

		int initState = DiceASTUtils.literalToInteger(children.first());

		return children.tail().reduceAux(initState,
				(currentNode, state) -> {
					return reducer.apply(state,
							DiceASTUtils.literalToInteger(currentNode));
				}, (state) -> new Tree<>(new IntegerLiteralNode(state)));
	}
}