public void VisitConstantFloat(DMASTConstantFloat constant) { Result = new Expressions.Number(constant.Location, constant.Value); }
public void ProcessStatementSet(DMASTProcStatementSet statementSet) { var attribute = statementSet.Attribute.ToLower(); if (!DMExpression.TryConstant(_dmObject, _proc, statementSet.Value, out var constant)) { throw new CompileErrorException(statementSet.Location, $"{attribute} attribute should be a constant"); } switch (statementSet.Attribute.ToLower()) { case "waitfor": { _proc.WaitFor(constant.IsTruthy()); break; } case "opendream_unimplemented": { if (constant.IsTruthy()) { _proc.Attributes |= ProcAttributes.Unimplemented; } else { _proc.Attributes &= ~ProcAttributes.Unimplemented; } break; } case "hidden": if (constant.IsTruthy()) { _proc.Attributes |= ProcAttributes.Hidden; } else { _proc.Attributes &= ~ProcAttributes.Hidden; } if (!DMCompiler.Settings.SuppressUnimplementedWarnings) { DMCompiler.Warning(new CompilerWarning(statementSet.Location, "set hidden is not implemented")); } break; case "popup_menu": if (constant.IsTruthy()) // The default is to show it so we flag it if it's hidden { _proc.Attributes &= ~ProcAttributes.HidePopupMenu; } else { _proc.Attributes |= ProcAttributes.HidePopupMenu; } if (!DMCompiler.Settings.SuppressUnimplementedWarnings) { DMCompiler.Warning(new CompilerWarning(statementSet.Location, "set popup_menu is not implemented")); } break; case "instant": if (constant.IsTruthy()) { _proc.Attributes |= ProcAttributes.Instant; } else { _proc.Attributes &= ~ProcAttributes.Instant; } if (!DMCompiler.Settings.SuppressUnimplementedWarnings) { DMCompiler.Warning(new CompilerWarning(statementSet.Location, "set instant is not implemented")); } break; case "background": if (constant.IsTruthy()) { _proc.Attributes |= ProcAttributes.Background; } else { _proc.Attributes &= ~ProcAttributes.Background; } if (!DMCompiler.Settings.SuppressUnimplementedWarnings) { DMCompiler.Warning(new CompilerWarning(statementSet.Location, "set background is not implemented")); } break; case "name": DMASTConstantString name = statementSet.Value as DMASTConstantString; if (name is null) { throw new CompileErrorException(statementSet.Location, "bad text"); } _proc.VerbName = name.Value; if (!DMCompiler.Settings.SuppressUnimplementedWarnings) { DMCompiler.Warning(new CompilerWarning(statementSet.Location, "set name is not implemented")); } break; case "category": DMASTConstantString category = statementSet.Value as DMASTConstantString; if (category is null) { throw new CompileErrorException(statementSet.Location, "bad text"); } _proc.VerbCategory = category.Value; if (!DMCompiler.Settings.SuppressUnimplementedWarnings) { DMCompiler.Warning(new CompilerWarning(statementSet.Location, "set category is not implemented")); } break; case "desc": DMASTConstantString desc = statementSet.Value as DMASTConstantString; if (desc is null) { throw new CompileErrorException(statementSet.Location, "bad text"); } _proc.VerbDesc = desc.Value; if (!DMCompiler.Settings.SuppressUnimplementedWarnings) { DMCompiler.Warning(new CompilerWarning(statementSet.Location, "set desc is not implemented")); } break; case "invisibility": // The ref says 0-101 for atoms and 0-100 for verbs // BYOND doesn't clamp the actual var value but it does seem to treat out-of-range values as their extreme DMASTConstantFloat invisFloat = statementSet.Value as DMASTConstantFloat; if (invisFloat is null) { DMASTConstantInteger invisInt = statementSet.Value as DMASTConstantInteger; if (invisInt is null) { throw new CompileErrorException(statementSet.Location, "bad num"); } _proc.Invisibility = Convert.ToSByte(Math.Clamp(invisInt.Value, 0, 100)); } else { _proc.Invisibility = Convert.ToSByte(Math.Clamp(Math.Floor(invisFloat.Value), 0, 100)); } if (!DMCompiler.Settings.SuppressUnimplementedWarnings) { DMCompiler.Warning(new CompilerWarning(statementSet.Location, "set invisibility is not implemented")); } break; case "src": if (!DMCompiler.Settings.SuppressUnimplementedWarnings) { DMCompiler.Warning(new CompilerWarning(statementSet.Location, "set src is not implemented")); } break; } }
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 }