package bjc.dicelang.ast; import java.util.function.Function; import bjc.utils.funcdata.FunctionalList; import bjc.utils.funcdata.FunctionalMap; import bjc.utils.parserutils.AST; /** * Freeze references in a dice AST, replacing variable references with what * the variables refer to * * @author ben * */ public class DiceASTFreezer { private static class NodeFreezer implements Function> { private FunctionalMap> enviroment; public NodeFreezer(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 SelectiveFreezer extends NodeFreezer { private FunctionalList variableNames; public SelectiveFreezer( 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); } } } /** * Freeze the references in an AST * * @param tree * The tree to freeze references in * @param env * The enviroment to get reference values from * @return The tree with references frozen */ public static AST freezeAST(AST tree, FunctionalMap> env) { return selectiveFreeze(tree, env); } /** * Freeze the references in an expression backed by an AST * * @param tree * The tree-backed expression to freeze references in * @param env * The enviroment to get reference values from * @return The tree with references frozen */ public static AST freezeAST(DiceASTExpression tree, FunctionalMap env) { return freezeAST(tree.getAst(), env.mapValues(expression -> expression.getAst())); } /** * Freeze references to specified variables * * @param tree * The tree-backed expression to freeze references in * @param env * The enviroment to resolve variables against * @param varNames * The names of the variables to freeze * @return An AST with the specified variables frozen */ public static AST selectiveFreeze(AST tree, FunctionalMap> env, String... varNames) { return selectiveFreeze(tree, env, new FunctionalList<>(varNames)); } /** * Freeze references to specified variables * * @param tree * The tree-backed expression to freeze references in * @param env * The enviroment to resolve variables against * @param varNames * The names of the variables to freeze * @return An AST with the specified variables frozen */ public static AST selectiveFreeze(AST tree, FunctionalMap> env, FunctionalList varNames) { return tree.expand(new SelectiveFreezer(env, varNames)); } }