From bf5f97983a7cd58e5d1147d6d6d93c2b307fe0fb Mon Sep 17 00:00:00 2001 From: bculkin2442 Date: Mon, 18 Apr 2016 17:22:36 -0400 Subject: Implemented arrays --- .../java/bjc/dicelang/ast/DiceASTEvaluator.java | 125 ++++++++++++++++----- 1 file changed, 98 insertions(+), 27 deletions(-) (limited to 'dice-lang/src/main/java/bjc/dicelang/ast/DiceASTEvaluator.java') diff --git a/dice-lang/src/main/java/bjc/dicelang/ast/DiceASTEvaluator.java b/dice-lang/src/main/java/bjc/dicelang/ast/DiceASTEvaluator.java index aeecb38..7d073d4 100644 --- a/dice-lang/src/main/java/bjc/dicelang/ast/DiceASTEvaluator.java +++ b/dice-lang/src/main/java/bjc/dicelang/ast/DiceASTEvaluator.java @@ -1,6 +1,7 @@ package bjc.dicelang.ast; import bjc.dicelang.ComplexDice; +import bjc.dicelang.ast.nodes.DiceASTType; import bjc.dicelang.ast.nodes.DiceLiteralNode; import bjc.dicelang.ast.nodes.DiceLiteralType; import bjc.dicelang.ast.nodes.IDiceASTNode; @@ -8,9 +9,12 @@ import bjc.dicelang.ast.nodes.ILiteralDiceNode; import bjc.dicelang.ast.nodes.IntegerLiteralNode; import bjc.dicelang.ast.nodes.OperatorDiceNode; import bjc.dicelang.ast.nodes.VariableDiceNode; +import bjc.utils.data.IHolder; import bjc.utils.data.IPair; +import bjc.utils.data.Identity; import bjc.utils.data.LazyPair; import bjc.utils.data.Pair; +import bjc.utils.funcdata.FunctionalList; import bjc.utils.funcdata.FunctionalMap; import bjc.utils.funcdata.IFunctionalList; import bjc.utils.funcdata.IFunctionalMap; @@ -71,12 +75,27 @@ public class DiceASTEvaluator { return parseLet(enviroment, nodes); }); + operatorCollapsers.put(OperatorDiceNode.ARRAY, (nodes) -> { + ITree returnedTree = + new Tree<>(OperatorDiceNode.ARRAY); + IFunctionalList resultList = new FunctionalList<>(); + + nodes.forEach((element) -> { + element.doWith((result, tree) -> { + resultList.add(result); + returnedTree.addChild(tree); + }); + }); + + return new Pair<>(new ArrayResult(resultList), returnedTree); + }); + return operatorCollapsers; } - private static IPair> parseLet( + private static IPair> parseLet( IFunctionalMap> enviroment, - IFunctionalList>> nodes) { + IFunctionalList>> nodes) { if (nodes.getSize() != 2) { throw new UnsupportedOperationException( "Can only use let with two expressions."); @@ -90,7 +109,7 @@ public class DiceASTEvaluator { enviroment.extend(); evaluateAST(bindTree, letEnviroment); - int exprResult = evaluateAST(expressionTree, letEnviroment); + IResult exprResult = evaluateAST(expressionTree, letEnviroment); IFunctionalList> childrn = nodes.map((pair) -> pair.getRight()); @@ -108,7 +127,7 @@ public class DiceASTEvaluator { * The enviroment to look up variables in * @return The integer value of the expression */ - public static int evaluateAST(ITree expression, + public static IResult evaluateAST(ITree expression, IFunctionalMap> enviroment) { IFunctionalMap collapsers = buildOperations(enviroment); @@ -118,7 +137,7 @@ public class DiceASTEvaluator { (pair) -> pair.getLeft()); } - private static IPair> evaluateLeaf( + private static IPair> evaluateLeaf( IDiceASTNode leafNode, IFunctionalMap> enviroment) { ITree returnedAST = new Tree<>(leafNode); @@ -139,31 +158,35 @@ public class DiceASTEvaluator { } } - private static Integer bindLiteralValue(IDiceASTNode leafNode, + private static IResult bindLiteralValue(IDiceASTNode leafNode, IFunctionalMap> enviroment) { String variableName = ((VariableDiceNode) leafNode).getVariable(); if (enviroment.containsKey(variableName)) { - int result = + IResult result = evaluateAST(enviroment.get(variableName), enviroment); return result; } - throw new UnsupportedOperationException( - "Attempted to dereference unbound variable " - + variableName); + // Allow for array assignment easily + return new IntegerResult(0); } - private static int evaluateLiteral(IDiceASTNode leafNode) { + private static IResult evaluateLiteral(IDiceASTNode leafNode) { DiceLiteralType literalType = ((ILiteralDiceNode) leafNode).getLiteralType(); switch (literalType) { case DICE: - return ((DiceLiteralNode) leafNode).getValue().roll(); + int diceRoll = + ((DiceLiteralNode) leafNode).getValue().roll(); + + return new IntegerResult(diceRoll); case INTEGER: - return ((IntegerLiteralNode) leafNode).getValue(); + int val = ((IntegerLiteralNode) leafNode).getValue(); + + return new IntegerResult(val); default: throw new UnsupportedOperationException("Literal value '" + leafNode + "' is of a type (" + literalType @@ -171,22 +194,19 @@ public class DiceASTEvaluator { } } - private static IPair> parseBinding( + private static IPair> parseBinding( IFunctionalMap> enviroment, - IFunctionalList>> nodes) { + IFunctionalList>> nodes) { if (nodes.getSize() != 2) { throw new UnsupportedOperationException( "Can only bind nodes with two children. Problem children are " + nodes); } - IPair> nameNode = nodes.getByIndex(0); - IPair> valueNode = + IPair> nameNode = nodes.getByIndex(0); + IPair> valueNode = nodes.getByIndex(1); - // Force valueNode to materialize for debugging purposes - valueNode.merge((l, r) -> null); - return nameNode.bindRight((nameTree) -> { return valueNode.bind((valueValue, valueTree) -> { if (DiceASTUtils.containsSimpleVariable(nameTree)) { @@ -196,6 +216,36 @@ public class DiceASTEvaluator { enviroment.put(varName, valueTree); + return new Pair<>(valueValue, nameTree); + } else if (nameTree.getHead() == OperatorDiceNode.ARRAY) { + if (valueTree.getHead() == OperatorDiceNode.ARRAY) { + if (nameTree.getChildrenCount() != valueTree + .getChildrenCount()) { + throw new UnsupportedOperationException( + "Array assignment must be between two equal length arrays"); + } + + IHolder childCount = new Identity<>(0); + + nameTree.doForChildren((child) -> { + doArrayAssign(enviroment, nameNode, nameTree, + valueTree, childCount, child); + + childCount.transform(val -> val + 1); + }); + + return new Pair<>(valueValue, nameTree); + } + + nameTree.doForChildren((child) -> { + String varName = child.transformHead((nameNod) -> { + return ((VariableDiceNode) nameNod) + .getVariable(); + }); + + enviroment.put(varName, valueTree); + }); + return new Pair<>(valueValue, nameTree); } @@ -206,24 +256,45 @@ public class DiceASTEvaluator { }); } - private static IPair> parseGroup( - IFunctionalList>> nodes) { + private static void doArrayAssign( + IFunctionalMap> enviroment, + IPair> nameNode, + ITree nameTree, ITree valueTree, + IHolder childCount, ITree child) { + if (nameTree.getHead().getType() != DiceASTType.VARIABLE) { + throw new UnsupportedOperationException( + "Assigning to complex variables isn't supported. Problem node is " + + nameNode.getRight()); + } + + String varName = child.transformHead((nameNod) -> { + return ((VariableDiceNode) nameNod).getVariable(); + }); + + enviroment.put(varName, valueTree.getChild(childCount.getValue())); + + childCount.transform(val -> val + 1); + } + + private static IPair> parseGroup( + IFunctionalList>> nodes) { if (nodes.getSize() != 2) { throw new UnsupportedOperationException( "Can only form a group from two dice"); } - IPair> numberDiceNode = + IPair> numberDiceNode = nodes.getByIndex(0); - IPair> diceTypeNode = + IPair> diceTypeNode = nodes.getByIndex(1); return numberDiceNode.bind((numberDiceValue, numberDiceTree) -> { return diceTypeNode.bind((diceTypeValue, diceTypeTree) -> { - ComplexDice cDice = - new ComplexDice(numberDiceValue, diceTypeValue); + ComplexDice cDice = new ComplexDice( + ((IntegerResult) numberDiceValue).getValue(), + ((IntegerResult) diceTypeValue).getValue()); - return new Pair<>(cDice.roll(), + return new Pair<>(new IntegerResult(cDice.roll()), new Tree<>(OperatorDiceNode.GROUP, numberDiceTree, diceTypeTree)); }); -- cgit v1.2.3