예제 #1
0
        public override ScriptVariableType Process(ScriptParser parser, int level)
        {
            base.Process(parser, level);

            bool hadErrors = false;

            try { LType = LValue.Process(parser, level + 1); }
            catch (ScriptCriticalErrorException) { hadErrors = true; }

            try { RType = RValue.Process(parser, level + 1); }
            catch (ScriptCriticalErrorException) { hadErrors = true; }

            if (hadErrors)
            {
                throw new ScriptCriticalErrorException();                 // we are not going to try the operator because one of nodes had an error
            }
            dynamic a, b, c;

            a = LType.GetSampleValue();
            b = RType.GetSampleValue();
            try {
                c          = ApplyOperator(a, b);
                ResultType = ScriptVariableTypeExtension.GetScriptVariableType(c);
            }
            catch (UserFriendlyException) {
                throw;
            }
            catch {
                parser.Errors.Add(new ErrorInfo(ErrorLevel.CriticalError, ErrorCode.OperatorCannotBeApplied2, this, LType, RType));
                throw new ScriptCriticalErrorException();
            }

            return(ResultType);
        }
        public static IExecutionTreeNode ImplicitCast(ScriptParser parser, int level, ScriptVariableType requiredType, IExecutionTreeNode node)
        {
            ScriptVariableType acceptableTypes = ScriptVariableType.Undefined;

            // implicit cast is allowed only in loseless cases (except floating point types)
            switch (requiredType)
            {
            case ScriptVariableType.Short: acceptableTypes = ScriptVariableType.Short | ScriptVariableType.Byte | ScriptVariableType.SByte; break;

            case ScriptVariableType.UShort: acceptableTypes = ScriptVariableType.UShort | ScriptVariableType.Byte; break;

            case ScriptVariableType.Int: acceptableTypes = ScriptVariableType.Int | ScriptVariableType.UShort | ScriptVariableType.Short | ScriptVariableType.Byte | ScriptVariableType.SByte; break;

            case ScriptVariableType.UInt: acceptableTypes = ScriptVariableType.UInt | ScriptVariableType.UShort | ScriptVariableType.Byte; break;

            case ScriptVariableType.Long: acceptableTypes = ScriptVariableType.Long | ScriptVariableType.UInt | ScriptVariableType.Int | ScriptVariableType.UShort | ScriptVariableType.Short | ScriptVariableType.Byte | ScriptVariableType.SByte; break;

            case ScriptVariableType.ULong: acceptableTypes = ScriptVariableType.ULong | ScriptVariableType.UInt | ScriptVariableType.UShort | ScriptVariableType.Byte; break;

            case ScriptVariableType.Float: acceptableTypes = ScriptVariableType.Float | ScriptVariableType.UInt | ScriptVariableType.Int | ScriptVariableType.UShort | ScriptVariableType.Short | ScriptVariableType.Byte | ScriptVariableType.SByte; break;

            case ScriptVariableType.Double: acceptableTypes = ScriptVariableType.Double | ScriptVariableType.Float | ScriptVariableType.ULong | ScriptVariableType.Long | ScriptVariableType.UInt | ScriptVariableType.Int | ScriptVariableType.UShort | ScriptVariableType.Short | ScriptVariableType.Byte | ScriptVariableType.SByte; break;

            case ScriptVariableType.Decimal: acceptableTypes = ScriptVariableType.Decimal | ScriptVariableType.Double | ScriptVariableType.Float | ScriptVariableType.ULong | ScriptVariableType.Long | ScriptVariableType.UInt | ScriptVariableType.Int | ScriptVariableType.UShort | ScriptVariableType.Short | ScriptVariableType.Byte | ScriptVariableType.SByte; break;
            }
            acceptableTypes = acceptableTypes | requiredType;
            ScriptVariableType type = node.Process(parser, level);

            if (type == requiredType)
            {
                return(node);
            }

            if ((type & acceptableTypes) == ScriptVariableType.Undefined)
            {
                parser.Errors.Add(new ErrorInfo(ErrorLevel.Error, ErrorCode.NoImplicitConversion, node, type, requiredType));
                return(node);                // assume when the error is fixed no implicit cast will be required
            }

            TypeCastExecutionNode typeCast = new TypeCastExecutionNode(node.Parent, node.Line, node.Character);

            node.Parent           = typeCast;
            typeCast.CastFromType = type;
            typeCast.CastToType   = requiredType;
            typeCast.Value        = node;
            typeCast.IsImplicit   = true;

            typeCast.CastToSystemType = typeCast.CastToType.GetSystemType();

            if (parser.DebugParsing)
            {
                Utils.IndentedOutput(level, "Inserting implicit cast from '{0}' to '{1}' ({2})", typeCast.CastFromType, typeCast.CastToType, typeCast.CastToSystemType);
            }

            return(typeCast);
        }
예제 #3
0
 public override ScriptVariableType Process(ScriptParser parser, int level)
 {
     base.Process(parser, level);
     if (ExitValue != null)
     {
         // we don't care what will be returned, but prefer int if numeric value is going to be returned
         ExitValueType = ExitValue.Process(parser, level + 1);
     }
     return(ScriptVariableType.Undefined);
 }
 public override ScriptVariableType Process(ScriptParser parser, int level)
 {
     base.Process(parser, level);
     Condition = TypeCastExecutionNode.ImplicitCast(parser, level + 1, ScriptVariableType.Bool, Condition);
     if (TrueNode != null)
     {
         TrueNode.Process(parser, level + 1);
     }
     if (FalseNode != null)
     {
         FalseNode.Process(parser, level + 1);
     }
     return(ScriptVariableType.Undefined);
 }
 public override ScriptVariableType Process(ScriptParser parser, int level)
 {
     base.Process(parser, level);
     if (Condition != null)
     {
         Condition = TypeCastExecutionNode.ImplicitCast(parser, level + 1, ScriptVariableType.Bool, Condition);
     }
     if (Code != null)
     {
         Code.Process(parser, level + 1);
     }
     if (Code == null && Condition == null)
     {
         parser.Errors.Add(new ErrorInfo(ErrorLevel.Error, ErrorCode.LoopWithNoConditionNorCode, this));
     }
     return(ScriptVariableType.Undefined);
 }
        public override ScriptVariableType Process(ScriptParser parser, int level)
        {
            base.Process(parser, level);

            CastFromType     = Value.Process(parser, level + 1);
            CastToSystemType = CastToType.GetSystemType();

            dynamic a = CastFromType.GetSampleValue();

            try {
                a = Convert.ChangeType(a, CastToSystemType);
            }
            catch {
                parser.Errors.Add(new ErrorInfo(ErrorLevel.Error, ErrorCode.NoExplicitConversion, this, CastFromType, CastToType));
            }

            if (parser.DebugParsing)
            {
                Utils.IndentedOutput(level, "Explicit cast from '{0}' to '{1}' ({2})", CastFromType, CastToType, CastToSystemType);
            }

            return(CastToType);
        }
예제 #7
0
        public override ScriptVariableType Process(ScriptParser parser, int level)
        {
            base.Process(parser, level);

            ValueType = Value.Process(parser, level + 1);

            dynamic a, b;

            a = ValueType.GetSampleValue();
            try {
                b          = ApplyOperator(ref a);
                ResultType = ScriptVariableTypeExtension.GetScriptVariableType(b);
            }
            catch (UserFriendlyException) {
                throw;
            }
            catch {
                parser.Errors.Add(new ErrorInfo(ErrorLevel.CriticalError, ErrorCode.OperatorCannotBeApplied1, this, ValueType));
                throw new ScriptCriticalErrorException();
            }

            return(ValueType);
        }
 public override ScriptVariableType Process(ScriptParser parser, int level)
 {
     base.Process(parser, level);
     parser.IncrementScopeLevel(false);
     if (Init != null)
     {
         Init.Process(parser, level + 1);
     }
     if (Condition != null)
     {
         Condition = TypeCastExecutionNode.ImplicitCast(parser, level + 1, ScriptVariableType.Bool, Condition);
     }
     if (Final != null)
     {
         Final.Process(parser, level + 1);
     }
     if (Code != null)
     {
         Code.Process(parser, level + 1);
     }
     parser.DecrementScopeLevel(false);
     return(ScriptVariableType.Undefined);
 }
        public override ScriptVariableType Process(ScriptParser parser, int level)
        {
            base.Process(parser, level);

            if (parser.RequiredReturnType != ScriptVariableType.Undefined)
            {
                // Within a function
                if (parser.RequiredReturnType == ScriptVariableType.Void && ReturnValue != null)
                {
                    parser.Errors.Add(new ErrorInfo(ErrorLevel.Error, ErrorCode.FunctionMustNotReturnAValue, this));
                }
                else if (parser.RequiredReturnType != ScriptVariableType.Void)
                {
                    if (ReturnValue == null)
                    {
                        parser.Errors.Add(new ErrorInfo(ErrorLevel.Error, ErrorCode.FunctionMustReturnAValue, this));
                    }
                    else
                    {
                        ReturnValue     = TypeCastExecutionNode.ImplicitCast(parser, level + 1, parser.RequiredReturnType, ReturnValue);
                        ReturnValueType = parser.RequiredReturnType;
                    }
                }
                IsInGlobalScope = false;
            }
            else
            {
                // Within the global scope. Anything or nothing may be returned (works same as 'exit').
                if (ReturnValue != null)
                {
                    ReturnValueType = ReturnValue.Process(parser, level + 1);
                }
                IsInGlobalScope = true;
            }
            return(ScriptVariableType.Undefined);
        }
예제 #10
0
        public override ScriptVariableType Process(ScriptParser parser, int level)
        {
            base.Process(parser, level);

            IExecutionTreeNode node = null;

            if (m_Parent != null && CreateOwnVariableScope)
            {
                parser.IncrementScopeLevel(false);
            }

            int  i, processCount = 0;
            bool exitFound = false;

            for (i = 0; i < m_Children.Count; i++)
            {
                node      = m_Children[i];
                exitFound = (node is ReturnExecutionNode || node is ExitExecutionNode);
                if (exitFound && i < m_Children.Count - 1)
                {
                    parser.Errors.Add(new ErrorInfo(ErrorLevel.Warning, ErrorCode.UnreachableCode, m_Children[i + 1]));
                    break;
                }
                processCount++;
            }
            if (level == 0 && !exitFound)
            {
                if (m_Parent != null && parser.RequiredReturnType != ScriptVariableType.Undefined && parser.RequiredReturnType != ScriptVariableType.Void)
                {
                    parser.Errors.Add(new ErrorInfo(ErrorLevel.Error, ErrorCode.NotAllCodePathsReturnAValue, this));
                    // return;
                }
                if (m_Parent == null && node != null && node.HasResult)
                {
                    // Not within a function, but at the very end of the script.
                    // Make result of the last statement to be returned as an
                    // exit data of the script. This is needed to simplify
                    // scripts that work as conditions of some scripted objects
                    // like dialogues or quests.
                    ExitExecutionNode exitNode = new ExitExecutionNode(this, node.Line, node.Character);
                    exitNode.ExitValue = node;
                    node.Parent        = exitNode;
                    m_Children[m_Children.Count - 1] = exitNode;
                }
            }

            // processing has to be done AFTER virtual exit node is incorporated
            for (i = 0; i < processCount; i++)
            {
                node = m_Children[i];

                try { node.Process(parser, level + 1); }
                catch (ScriptCriticalErrorException) {}

                if ((node is ReturnExecutionNode || node is ExitExecutionNode) && i < m_Children.Count - 1)
                {
                    break;
                }
            }

            // Don't decrement scope level for root node to keep global
            // variables in the variable stack. This is required for functions
            // to know what global variables they will have access to while
            // parsing.
            if (m_Parent != null && CreateOwnVariableScope)
            {
                parser.DecrementScopeLevel(false);
            }

            return(ScriptVariableType.Undefined);
        }