void ParseVarset(ScopeGroup getter, ScopeGroup scope, VarSetNode varSetNode) { var varSetData = new ParseExpressionTree(this, getter, scope, varSetNode.Variable); if (!(varSetData.ResultingVariable is IndexedVar)) { throw SyntaxErrorException.VariableIsReadonly(varSetData.ResultingVariable.Name, varSetNode.Location); } IndexedVar variable = (IndexedVar)varSetData.ResultingVariable; Element[] index = varSetData.VariableIndex; Element value = null; if (varSetNode.Value != null) { value = ParseExpression(getter, scope, varSetNode.Value); } Element initialVar = variable.GetVariable(varSetData.Target); Operation?operation = null; switch (varSetNode.Operation) { case "+=": operation = Operation.Add; break; case "-=": operation = Operation.Subtract; break; case "*=": operation = Operation.Multiply; break; case "/=": operation = Operation.Divide; break; case "^=": operation = Operation.RaiseToPower; break; case "%=": operation = Operation.Modulo; break; case "++": operation = Operation.Add; value = 1; break; case "--": operation = Operation.Subtract; value = 1; break; } if (operation == null) { Actions.AddRange(variable.SetVariable(value, varSetData.Target, index)); } else { Actions.AddRange(variable.ModifyVariable((Operation)operation, value, varSetData.Target, index)); } }
public Element ParseExpression(ScopeGroup getter, ScopeGroup scope, Node expression) { switch (expression) { // Math and boolean operations. case OperationNode operationNode: { Element left = ParseExpression(getter, scope, operationNode.Left); Element right = ParseExpression(getter, scope, operationNode.Right); /* * if (Constants.BoolOperations.Contains(operationNode.Operation)) * { * if (left.ElementData.ValueType != Elements.ValueType.Any && left.ElementData.ValueType != Elements.ValueType.Boolean) * throw new SyntaxErrorException($"Expected boolean, got {left .ElementData.ValueType.ToString()} instead.", ((Node)operationNode.Left).Range); * * if (right.ElementData.ValueType != Elements.ValueType.Any && right.ElementData.ValueType != Elements.ValueType.Boolean) * throw new SyntaxErrorException($"Expected boolean, got {right.ElementData.ValueType.ToString()} instead.", ((Node)operationNode.Right).Range); * } */ switch (operationNode.Operation) { // Math: ^, *, %, /, +, - case "^": return(Element.Part <V_RaiseToPower>(left, right)); case "*": return(left * right); case "%": return(left % right); case "/": return(left / right); case "+": return(left + right); case "-": return(left - right); // BoolCompare: &&, || case "&&": return(Element.Part <V_And>(left, right)); case "||": return(Element.Part <V_Or>(left, right)); // Compare: <, <=, ==, >=, >, != case "<": return(left < right); case "<=": return(left <= right); case "==": return(Element.Part <V_Compare>(left, EnumData.GetEnumValue(Operators.Equal), right)); case ">=": return(left >= right); case ">": return(left > right); case "!=": return(Element.Part <V_Compare>(left, EnumData.GetEnumValue(Operators.NotEqual), right)); } throw new Exception($"Operation {operationNode.Operation} not implemented."); } // Number case NumberNode numberNode: return(numberNode.Value); // Bool case BooleanNode boolNode: if (boolNode.Value) { return(new V_True()); } else { return(new V_False()); } // Not operation case NotNode notNode: return(!(ParseExpression(getter, scope, notNode.Value))); case InvertNode invertNode: return(-ParseExpression(getter, scope, invertNode.Value)); // Strings case StringNode stringNode: Element[] stringFormat = new Element[stringNode.Format?.Length ?? 0]; for (int i = 0; i < stringFormat.Length; i++) { stringFormat[i] = ParseExpression(getter, scope, stringNode.Format[i]); } if (stringNode.Localized) { return(V_String.ParseString(stringNode.Location, stringNode.Value, stringFormat)); } else { return(V_CustomString.ParseString(stringNode.Location, stringNode.Value, stringFormat)); } // Null case NullNode nullNode: return(new V_Null()); // TODO check if groups need to be implemented here // Methods case MethodNode methodNode: return(ParseMethod(getter, scope, methodNode, true)); // Variable case VariableNode variableNode: Element[] index = new Element[variableNode.Index.Length]; for (int i = 0; i < index.Length; i++) { index[i] = ParseExpression(getter, scope, variableNode.Index[i]); } Var var = scope.GetVar(getter, variableNode.Name, variableNode.Location); if (!var.Gettable()) { throw SyntaxErrorException.VariableIsReadonly(var.Name, variableNode.Location); } Element result = var.GetVariable(); for (int i = 0; i < index.Length; i++) { result = Element.Part <V_ValueInArray>(result, index[i]); } return(result); // Get value in array case ValueInArrayNode viaNode: return(Element.Part <V_ValueInArray>(ParseExpression(getter, scope, viaNode.Value), ParseExpression(getter, scope, viaNode.Index))); // Create array case CreateArrayNode createArrayNode: { Element prev = null; Element current = null; for (int i = 0; i < createArrayNode.Values.Length; i++) { current = new V_Append() { ParameterValues = new IWorkshopTree[2] }; if (prev != null) { current.ParameterValues[0] = prev; } else { current.ParameterValues[0] = new V_EmptyArray(); } current.ParameterValues[1] = ParseExpression(getter, scope, createArrayNode.Values[i]); prev = current; } return(current ?? new V_EmptyArray()); } // Ternary Conditional (a ? b : c) case TernaryConditionalNode ternaryNode: return(Element.TernaryConditional ( ParseExpression(getter, scope, ternaryNode.Condition), ParseExpression(getter, scope, ternaryNode.Consequent), ParseExpression(getter, scope, ternaryNode.Alternative) )); // Enums case EnumNode enumNode: return(EnumData.ToElement(enumNode.EnumMember) ?? throw SyntaxErrorException.EnumCantBeValue(enumNode.Type, enumNode.Location)); // New object case CreateObjectNode createObjectNode: DefinedType typeData = ParserData.GetDefinedType(createObjectNode.TypeName, createObjectNode.Location); return(typeData.New(createObjectNode, getter, scope, this)); // Expression tree case ExpressionTreeNode expressionTree: return(new ParseExpressionTree(this, getter, scope, expressionTree).ResultingElement); // This case ThisNode thisNode: return(getter.GetThis(thisNode.Location)); // Type convert case TypeConvertNode typeConvertNode: DefinedType type = ParserData.GetDefinedType(typeConvertNode.Type, typeConvertNode.Location); Element element = ParseExpression(getter, scope, typeConvertNode.Expression); type.GetSource(this, element, typeConvertNode.Location); return(element); case RootNode rootNode: throw new SyntaxErrorException("'root' cannot be used like an expression.", rootNode.Location); } throw new Exception(); }