package bjc.dicelang.ast; import java.util.function.Function; import bjc.dicelang.ast.nodes.DiceASTType; import bjc.dicelang.ast.nodes.IDiceASTNode; import bjc.dicelang.ast.nodes.VariableDiceNode; import bjc.utils.funcdata.FunctionalList; import bjc.utils.funcdata.FunctionalMap; import bjc.utils.parserutils.AST; /** * Inline references in a dice AST, replacing variable references with what * the variables refer to * * @author ben * */ public class DiceASTInliner { private static class NodeInliner implements Function> { private FunctionalMap> enviroment; public NodeInliner(FunctionalMap> env) { enviroment = env; } @Override public AST apply(IDiceASTNode nod) { if (nod.getType() == DiceASTType.VARIABLE) { return expandNode((VariableDiceNode) nod); } else { return new AST<>(nod); } } protected AST expandNode(VariableDiceNode variableNode) { String varName = variableNode.getVariable(); if (!enviroment.containsKey(varName)) { throw new IllegalArgumentException( "Attempted to freeze reference" + " to an undefined variable " + varName); } return enviroment.get(varName); } } private static final class SelectiveInliner extends NodeInliner { private FunctionalList variableNames; public SelectiveInliner( FunctionalMap> env, FunctionalList varNames) { super(env); variableNames = varNames; } @Override protected AST expandNode(VariableDiceNode variableNode) { if (variableNames.contains(variableNode.getVariable())) { return super.expandNode(variableNode); } else { return new AST<>(variableNode); } } } /** * Inline the references in an AST * * @param tree * The tree to inline references in * @param env * The enviroment to get reference values from * @return The tree with references inlined */ public static AST inlineAST(AST tree, FunctionalMap> env) { return selectiveInline(tree, env); } /** * Inline the references in an expression backed by an AST * * @param tree * The tree-backed expression to inline references in * @param env * The enviroment to get reference values from * @return The tree with references inlined */ public static AST inlineAST(DiceASTExpression tree, FunctionalMap env) { return inlineAST(tree.getAst(), env.mapValues(expression -> expression.getAst())); } /** * Inline references to specified variables * * @param tree * The tree-backed expression to inline references in * @param env * The enviroment to resolve variables against * @param varNames * The names of the variables to inline * @return An AST with the specified variables inlined */ public static AST selectiveInline(AST tree, FunctionalMap> env, String... varNames) { return selectiveInline(tree, env, new FunctionalList<>(varNames)); } /** * Inline references to specified variables * * @param tree * The tree-backed expression to inline references in * @param env * The enviroment to resolve variables against * @param varNames * The names of the variables to inline * @return An AST with the specified variables inline */ public static AST selectiveInline(AST tree, FunctionalMap> env, FunctionalList varNames) { return tree.expand(new SelectiveInliner(env, varNames)); } }