public void VisitProcCall(DMASTProcCall procCall) { // arglist hack if (procCall.Callable is DMASTCallableProcIdentifier ident) { if (ident.Identifier == "arglist") { if (procCall.Parameters.Length != 1) { throw new CompileErrorException(procCall.Location, "arglist must have 1 argument"); } var expr = DMExpression.Create(_dmObject, _proc, procCall.Parameters[0].Value, _inferredPath); Result = new Expressions.Arglist(procCall.Location, expr); return; } } var target = DMExpression.Create(_dmObject, _proc, (DMASTExpression)procCall.Callable, _inferredPath); var args = new ArgumentList(procCall.Location, _dmObject, _proc, procCall.Parameters); Result = new Expressions.ProcCall(procCall.Location, target, args); }
private void SimplifyExpression(ref DMASTExpression expression) { if (expression == null || expression is DMASTExpressionConstant || expression is DMASTCallable) { return; } #region Comparators DMASTEqual equal = expression as DMASTEqual; if (equal != null) { SimplifyExpression(ref equal.A); SimplifyExpression(ref equal.B); return; } DMASTNotEqual notEqual = expression as DMASTNotEqual; if (notEqual != null) { SimplifyExpression(ref notEqual.A); SimplifyExpression(ref notEqual.B); return; } DMASTLessThan lessThan = expression as DMASTLessThan; if (lessThan != null) { SimplifyExpression(ref lessThan.A); SimplifyExpression(ref lessThan.B); return; } DMASTLessThanOrEqual lessThanOrEqual = expression as DMASTLessThanOrEqual; if (lessThanOrEqual != null) { SimplifyExpression(ref lessThanOrEqual.A); SimplifyExpression(ref lessThanOrEqual.B); return; } DMASTGreaterThan greaterThan = expression as DMASTGreaterThan; if (greaterThan != null) { SimplifyExpression(ref greaterThan.A); SimplifyExpression(ref greaterThan.B); return; } DMASTGreaterThanOrEqual greaterThanOrEqual = expression as DMASTGreaterThanOrEqual; if (greaterThanOrEqual != null) { SimplifyExpression(ref greaterThanOrEqual.A); SimplifyExpression(ref greaterThanOrEqual.B); return; } #endregion Comparators #region Math DMASTNegate negate = expression as DMASTNegate; if (negate != null) { SimplifyExpression(ref negate.Expression); if (negate.Expression is not DMASTExpressionConstant) { return; } DMASTConstantInteger exprInteger = negate.Expression as DMASTConstantInteger; DMASTConstantFloat exprFloat = negate.Expression as DMASTConstantFloat; if (exprInteger != null) { expression = new DMASTConstantInteger(-exprInteger.Value); } else if (exprFloat != null) { expression = new DMASTConstantFloat(-exprFloat.Value); } return; } DMASTNot not = expression as DMASTNot; if (not != null) { SimplifyExpression(ref not.Expression); if (not.Expression is not DMASTExpressionConstant) { return; } DMASTConstantInteger exprInteger = not.Expression as DMASTConstantInteger; DMASTConstantFloat exprFloat = not.Expression as DMASTConstantFloat; if (exprInteger != null) { expression = new DMASTConstantInteger((exprInteger.Value != 0) ? 1 : 0); } else if (exprFloat != null) { expression = new DMASTConstantFloat((exprFloat.Value != 0) ? 1 : 0); } return; } DMASTOr or = expression as DMASTOr; if (or != null) { SimplifyExpression(ref or.A); SimplifyExpression(ref or.B); if (or.A is not DMASTExpressionConstant || or.B is not DMASTExpressionConstant) { return; } DMASTConstantInteger aInteger = or.A as DMASTConstantInteger; DMASTConstantInteger bInteger = or.B as DMASTConstantInteger; if (aInteger != null && bInteger != null) { expression = new DMASTConstantInteger(((aInteger.Value != 0) || (bInteger.Value != 0)) ? 1 : 0); } return; } DMASTAnd and = expression as DMASTAnd; if (and != null) { SimplifyExpression(ref and.A); SimplifyExpression(ref and.B); if (and.A is not DMASTExpressionConstant || and.B is not DMASTExpressionConstant) { return; } DMASTConstantInteger aInteger = and.A as DMASTConstantInteger; DMASTConstantInteger bInteger = and.B as DMASTConstantInteger; if (aInteger != null && bInteger != null) { expression = new DMASTConstantInteger(((aInteger.Value != 0) && (bInteger.Value != 0)) ? 1 : 0); } return; } DMASTLeftShift leftShift = expression as DMASTLeftShift; if (leftShift != null) { SimplifyExpression(ref leftShift.A); SimplifyExpression(ref leftShift.B); if (leftShift.A is not DMASTExpressionConstant || leftShift.B is not DMASTExpressionConstant) { return; } DMASTConstantInteger aInteger = leftShift.A as DMASTConstantInteger; DMASTConstantInteger bInteger = leftShift.B as DMASTConstantInteger; if (aInteger != null && bInteger != null) { expression = new DMASTConstantInteger(aInteger.Value << bInteger.Value); } return; } DMASTRightShift rightShift = expression as DMASTRightShift; if (rightShift != null) { SimplifyExpression(ref rightShift.A); SimplifyExpression(ref rightShift.B); if (rightShift.A is not DMASTExpressionConstant || rightShift.B is not DMASTExpressionConstant) { return; } DMASTConstantInteger aInteger = rightShift.A as DMASTConstantInteger; DMASTConstantInteger bInteger = rightShift.B as DMASTConstantInteger; if (aInteger != null && bInteger != null) { expression = new DMASTConstantInteger(aInteger.Value >> bInteger.Value); } return; } DMASTBinaryAnd binaryAnd = expression as DMASTBinaryAnd; if (binaryAnd != null) { SimplifyExpression(ref binaryAnd.A); SimplifyExpression(ref binaryAnd.B); if (binaryAnd.A is not DMASTExpressionConstant || binaryAnd.B is not DMASTExpressionConstant) { return; } DMASTConstantInteger aInteger = binaryAnd.A as DMASTConstantInteger; DMASTConstantInteger bInteger = binaryAnd.B as DMASTConstantInteger; if (aInteger != null && bInteger != null) { expression = new DMASTConstantInteger(aInteger.Value & bInteger.Value); } return; } DMASTBinaryOr binaryOr = expression as DMASTBinaryOr; if (binaryOr != null) { SimplifyExpression(ref binaryOr.A); SimplifyExpression(ref binaryOr.B); if (binaryOr.A is not DMASTExpressionConstant || binaryOr.B is not DMASTExpressionConstant) { return; } DMASTConstantInteger aInteger = binaryOr.A as DMASTConstantInteger; DMASTConstantInteger bInteger = binaryOr.B as DMASTConstantInteger; if (aInteger != null && bInteger != null) { expression = new DMASTConstantInteger(aInteger.Value | bInteger.Value); } return; } DMASTBinaryNot binaryNot = expression as DMASTBinaryNot; if (binaryNot != null) { SimplifyExpression(ref binaryNot.Value); if (binaryNot.Value is not DMASTExpressionConstant) { return; } DMASTConstantInteger valueInteger = binaryNot.Value as DMASTConstantInteger; if (valueInteger != null) { expression = new DMASTConstantInteger((~valueInteger.Value) & 0xFFFFFF); } return; } DMASTAdd add = expression as DMASTAdd; if (add != null) { SimplifyExpression(ref add.A); SimplifyExpression(ref add.B); if (add.A is not DMASTExpressionConstant || add.B is not DMASTExpressionConstant) { return; } DMASTConstantInteger aInteger = add.A as DMASTConstantInteger; DMASTConstantFloat aFloat = add.A as DMASTConstantFloat; DMASTConstantString aString = add.A as DMASTConstantString; DMASTConstantInteger bInteger = add.B as DMASTConstantInteger; DMASTConstantFloat bFloat = add.B as DMASTConstantFloat; DMASTConstantString bString = add.B as DMASTConstantString; if (aInteger != null && bInteger != null) { expression = new DMASTConstantInteger(aInteger.Value + bInteger.Value); } else if (aInteger != null && bFloat != null) { expression = new DMASTConstantFloat(aInteger.Value + bFloat.Value); } else if (aFloat != null && bInteger != null) { expression = new DMASTConstantFloat(aFloat.Value + bInteger.Value); } else if (aString != null && bString != null) { expression = new DMASTConstantString(aString.Value + bString.Value); } return; } DMASTSubtract subtract = expression as DMASTSubtract; if (subtract != null) { SimplifyExpression(ref subtract.A); SimplifyExpression(ref subtract.B); if (subtract.A is not DMASTExpressionConstant || subtract.B is not DMASTExpressionConstant) { return; } DMASTConstantInteger aInteger = subtract.A as DMASTConstantInteger; DMASTConstantInteger bInteger = subtract.B as DMASTConstantInteger; if (aInteger != null && bInteger != null) { expression = new DMASTConstantInteger(aInteger.Value - bInteger.Value); } return; } DMASTMultiply multiply = expression as DMASTMultiply; if (multiply != null) { SimplifyExpression(ref multiply.A); SimplifyExpression(ref multiply.B); if (multiply.A is not DMASTExpressionConstant || multiply.B is not DMASTExpressionConstant) { return; } DMASTConstantInteger aInteger = multiply.A as DMASTConstantInteger; DMASTConstantFloat aFloat = multiply.A as DMASTConstantFloat; DMASTConstantInteger bInteger = multiply.B as DMASTConstantInteger; DMASTConstantFloat bFloat = multiply.B as DMASTConstantFloat; if (aInteger != null && bInteger != null) { expression = new DMASTConstantInteger(aInteger.Value * bInteger.Value); } else if (aInteger != null && bFloat != null) { expression = new DMASTConstantFloat(aInteger.Value * bFloat.Value); } else if (aFloat != null && bInteger != null) { expression = new DMASTConstantFloat(aFloat.Value * bInteger.Value); } else if (aFloat != null && bFloat != null) { expression = new DMASTConstantFloat(aFloat.Value * bFloat.Value); } return; } DMASTDivide divide = expression as DMASTDivide; if (divide != null) { SimplifyExpression(ref divide.A); SimplifyExpression(ref divide.B); if (divide.A is not DMASTExpressionConstant || divide.B is not DMASTExpressionConstant) { return; } DMASTConstantInteger aInteger = divide.A as DMASTConstantInteger; DMASTConstantFloat aFloat = divide.A as DMASTConstantFloat; DMASTConstantInteger bInteger = divide.B as DMASTConstantInteger; DMASTConstantFloat bFloat = divide.B as DMASTConstantFloat; if (aInteger != null && bInteger != null) { if (aInteger.Value % bInteger.Value == 0) { expression = new DMASTConstantFloat(aInteger.Value / bInteger.Value); } else { expression = new DMASTConstantFloat((float)aInteger.Value / (float)bInteger.Value); } } else if (aFloat != null && bInteger != null) { expression = new DMASTConstantFloat(aFloat.Value / bInteger.Value); } else if (aFloat != null && bFloat != null) { expression = new DMASTConstantFloat(aFloat.Value / bFloat.Value); } return; } DMASTModulus modulus = expression as DMASTModulus; if (modulus != null) { SimplifyExpression(ref modulus.A); SimplifyExpression(ref modulus.B); if (modulus.A is not DMASTExpressionConstant || modulus.B is not DMASTExpressionConstant) { return; } DMASTConstantInteger aInteger = modulus.A as DMASTConstantInteger; DMASTConstantInteger bInteger = modulus.B as DMASTConstantInteger; if (aInteger != null && bInteger != null) { expression = new DMASTConstantInteger(aInteger.Value % bInteger.Value); } return; } DMASTPower power = expression as DMASTPower; if (modulus != null) { SimplifyExpression(ref modulus.A); SimplifyExpression(ref modulus.B); if (modulus.A is not DMASTExpressionConstant || modulus.B is not DMASTExpressionConstant) { return; } DMASTConstantInteger aInteger = modulus.A as DMASTConstantInteger; DMASTConstantInteger bInteger = modulus.B as DMASTConstantInteger; if (aInteger != null && bInteger != null) { expression = new DMASTConstantInteger((int)Math.Pow(aInteger.Value, bInteger.Value)); } return; } DMASTAppend append = expression as DMASTAppend; if (append != null) { SimplifyExpression(ref append.A); SimplifyExpression(ref append.B); return; } DMASTRemove remove = expression as DMASTRemove; if (remove != null) { SimplifyExpression(ref remove.A); SimplifyExpression(ref remove.B); return; } DMASTCombine combine = expression as DMASTCombine; if (combine != null) { SimplifyExpression(ref combine.A); SimplifyExpression(ref combine.B); return; } DMASTMask mask = expression as DMASTMask; if (mask != null) { SimplifyExpression(ref mask.A); SimplifyExpression(ref mask.B); return; } #endregion Math #region Others DMASTList list = expression as DMASTList; if (list != null) { foreach (DMASTCallParameter parameter in list.Values) { SimplifyExpression(ref parameter.Value); } return; } DMASTNewPath newPath = expression as DMASTNewPath; if (newPath != null) { if (newPath.Parameters != null) { foreach (DMASTCallParameter parameter in newPath.Parameters) { SimplifyExpression(ref parameter.Value); } } return; } DMASTNewIdentifier newCallable = expression as DMASTNewIdentifier; if (newCallable != null) { if (newCallable.Parameters != null) { foreach (DMASTCallParameter parameter in newCallable.Parameters) { SimplifyExpression(ref parameter.Value); } } return; } DMASTProcCall procCall = expression as DMASTProcCall; if (procCall != null) { foreach (DMASTCallParameter parameter in procCall.Parameters) { SimplifyExpression(ref parameter.Value); } return; } DMASTAssign assign = expression as DMASTAssign; if (assign != null) { SimplifyExpression(ref assign.Expression); SimplifyExpression(ref assign.Value); return; } DMASTListIndex listIndex = expression as DMASTListIndex; if (listIndex != null) { SimplifyExpression(ref listIndex.Expression); SimplifyExpression(ref listIndex.Index); return; } DMASTStringFormat stringFormat = expression as DMASTStringFormat; if (stringFormat != null) { for (int i = 0; i < stringFormat.InterpolatedValues.Length; i++) { DMASTExpression simplifiedValue = stringFormat.InterpolatedValues[i]; SimplifyExpression(ref simplifiedValue); stringFormat.InterpolatedValues[i] = simplifiedValue; } return; } #endregion Others }