예제 #1
0
 public void VisitConstantFloat(DMASTConstantFloat constant)
 {
     Result = new Expressions.Number(constant.Location, constant.Value);
 }
예제 #2
0
        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;
            }
        }
예제 #3
0
        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
        }