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); }
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); }
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); }
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); }