public IVariable GetVariable(string name, Scope getter, FileDiagnostics diagnostics, DocRange range)
        {
            IVariable element = null;
            Scope     current = this;

            while (current != null && element == null)
            {
                element = current.Variables.FirstOrDefault(element => element.Name == name);
                current = current.Parent;
            }

            if (range != null && element == null)
            {
                diagnostics.Error(string.Format("The variable {0} does not exist in the {1}.", name, ErrorName), range);
            }

            if (element != null && getter != null && !getter.AccessorMatches(element))
            {
                if (range == null)
                {
                    throw new Exception();
                }
                diagnostics.Error(string.Format("'{0}' is inaccessable due to its access level.", name), range);
            }

            return(element);
        }
        private void ValidateAttribute(FileDiagnostics diagnostics, AttributeContext newAttribute)
        {
            // Virtual attribute on a static method (static attribute was first.)
            if (IsAttribute(AttributeType.Static) && newAttribute.Type == AttributeType.Virtual)
            {
                diagnostics.Error("Static methods cannot be virtual.", newAttribute.Range);
            }

            // Static attribute on a virtual method (virtual attribute was first.)
            if (IsAttribute(AttributeType.Virtual) && newAttribute.Type == AttributeType.Static)
            {
                diagnostics.Error("Virtual methods cannot be static.", newAttribute.Range);
            }
        }
        public void AddMacro(MacroVar macro, FileDiagnostics diagnostics, DocRange range, bool checkConflicts = true)
        {
            if (macro == null)
            {
                throw new ArgumentNullException(nameof(macro));
            }
            if (Variables.Contains(macro))
            {
                throw new Exception("macro reference is already in scope.");
            }

            if (checkConflicts && HasConflict(macro))
            {
                string message = "A macro with the same name and parameter types was already defined in this scope.";

                if (diagnostics != null && range != null)
                {
                    diagnostics.Error(message, range);
                    return;
                }
                else
                {
                    throw new Exception(message);
                }
            }

            Variables.Add(macro);
        }
 public void AddDiagnostics(FileDiagnostics diagnostics)
 {
     foreach (OverloadMatchError error in Errors)
     {
         diagnostics.Error(error.Message, error.Range);
     }
 }
        /// <summary>
        /// Adds a variable to the current scope.
        /// When handling variables added by the user, supply the diagnostics and range to show the syntax error at.
        /// When handling variables added internally, have the diagnostics and range parameters be null. An exception will be thrown instead if there is a syntax error.
        /// </summary>
        /// <param name="variable">The variable that will be added to the current scope. If the object reference is already in the direct scope, an exception will be thrown.</param>
        /// <param name="diagnostics">The file diagnostics to throw errors with. Should be null when adding variables internally.</param>
        /// <param name="range">The document range to throw errors at. Should be null when adding variables internally.</param>
        public void AddVariable(IVariable variable, FileDiagnostics diagnostics, DocRange range)
        {
            if (variable == null)
            {
                throw new ArgumentNullException(nameof(variable));
            }
            if (Variables.Contains(variable))
            {
                throw new Exception("variable reference is already in scope.");
            }

            if (IsVariable(variable.Name))
            {
                string message = string.Format("A variable of the name {0} was already defined in this scope.", variable.Name);

                if (diagnostics != null && range != null)
                {
                    diagnostics.Error(message, range);
                }
                else
                {
                    throw new Exception(message);
                }
            }
            else
            {
                Variables.Add(variable);
            }
        }
示例#6
0
 protected virtual void TypeCheck()
 {
     // If the type of the variable is a constant workshop value and there is no initial value, throw a syntax error.
     if (_varInfo.Type != null && _varInfo.Type.IsConstant() && _varInfo.InitialValueContext == null)
     {
         _diagnostics.Error("Variables with constant workshop types must have an initial value.", _nameRange);
     }
 }
        protected virtual void TypeCheck()
        {
            if (_nameRange == null)
            {
                return;
            }

            // If the type of the variable is a constant workshop value and there is no initial value, throw a syntax error.
            if (_varInfo.Type != null && _varInfo.Type.IsConstant() && _varInfo.InitialValueContext == null)
            {
                _diagnostics.Error("Variables with constant workshop types must have an initial value", _nameRange);
            }

            if (ComponentCollection.IsAttribute(AttributeType.Static) && SemanticsHelper.RecursivelyGetGenerics(_varInfo.Type).Any(type => type is AnonymousType))
            {
                _diagnostics.Error("Static variables cannot use anonymous types", _nameRange);
            }
        }
        public IVariable GetVariable(string name, Scope getter, FileDiagnostics diagnostics, DocRange range, bool methodGroupsOnly)
        {
            IVariable element = GetVariable(name, methodGroupsOnly);

            if (range != null && element == null)
            {
                diagnostics.Error(string.Format("The variable {0} does not exist in the {1}.", name, ErrorName), range);
            }

            if (element != null && getter != null && !getter.AccessorMatches(element))
            {
                if (range == null)
                {
                    throw new Exception();
                }
                diagnostics.Error(string.Format("'{0}' is inaccessable due to its access level.", name), range);
            }

            return(element);
        }
        public CodeType GetCodeType(string name, FileDiagnostics diagnostics, DocRange range)
        {
            var type = types.FirstOrDefault(type => type.Name == name);

            if (range != null && type == null)
            {
                diagnostics.Error(string.Format("The type {0} does not exist.", name), range);
            }

            return(type);
        }
示例#10
0
        private static T GetMember <T>(string groupName, string name, FileDiagnostics diagnostics, DocRange range)
        {
            foreach (var m in EnumData.GetEnum <T>().Members)
            {
                if (name == m.CodeName)
                {
                    return((T)m.Value);
                }
            }

            diagnostics.Error("Invalid " + groupName + " value.", range);
            return(default(T));
        }
示例#11
0
        private void ValidateAttribute(FileDiagnostics diagnostics, MethodAttributeContext newAttribute)
        {
            // The attribute is not allowed.
            if (DisallowAttributes().Contains(newAttribute.Type))
            {
                diagnostics.Error("The '" + newAttribute.Type.ToString().ToLower() + "' attribute is not allowed.", newAttribute.Range);
            }
            else
            {
                // Virtual attribute on a static method (static attribute was first.)
                if (ResultAppender.IsStatic() && newAttribute.Type == MethodAttributeType.Virtual)
                {
                    diagnostics.Error("Static methods cannot be virtual.", newAttribute.Range);
                }

                // Static attribute on a virtual method (virtual attribute was first.)
                if (ResultAppender.IsVirtual() && newAttribute.Type == MethodAttributeType.Static)
                {
                    diagnostics.Error("Virtual methods cannot be static.", newAttribute.Range);
                }
            }
        }
        private static T GetMember <T>(string groupName, string name, FileDiagnostics diagnostics, DocRange range) where T : Enum
        {
            var elementEnum = ElementRoot.Instance.GetEnum(groupName);

            foreach (var m in elementEnum.Members)
            {
                if (name == m.CodeName())
                {
                    return(m.ToEnum <T>());
                }
            }

            diagnostics.Error("Invalid " + groupName + " value.", range);
            return(default(T));
        }
示例#13
0
        public void Reject(FileDiagnostics diagnostics)
        {
            switch (Type)
            {
            // Accessors
            case AttributeType.Public:
            case AttributeType.Protected:
            case AttributeType.Private:
                diagnostics.Error("Accessor not valid here.", Range);
                break;

            // Workshop ID override
            case AttributeType.ID:
                diagnostics.Error($"Cannot override workshop variable ID here.", Range);
                break;

            // Extended collection
            case AttributeType.Ext:
                diagnostics.Error($"Cannot put variable in the extended collection.", Range);
                break;

            // Initial value
            case AttributeType.Initial:
                diagnostics.Error($"Variable cannot have an initial value.", Range);
                break;

            // Use attribute name
            case AttributeType.Static:
            case AttributeType.Globalvar:
            case AttributeType.Playervar:
            case AttributeType.Ref:
            default:
                diagnostics.Error($"'{Type.ToString().ToLower()}' attribute not valid here.", Range);
                break;
            }
        }
        public void Reserve(int id, bool isGlobal, FileDiagnostics diagnostics, DocRange range)
        {
            // Throw a syntax error if the ID was already reserved.
            if (reservedIDs(isGlobal).Contains(id))
            {
                string msg = string.Format("The id {0} is already reserved in the {1} collection.", id, isGlobal ? "global" : "player");

                if (range != null)
                {
                    diagnostics.Error(msg, range);
                }
            }
            // Add the ID to the reserved list.
            else
            {
                reservedIDs(isGlobal).Add(id);
            }
        }
示例#15
0
        public IScopeable GetVariable(string name, FileDiagnostics diagnostics, DocRange range)
        {
            IScopeable element = null;
            Scope      current = this;

            while (current != null && element == null)
            {
                element = current.Variables.FirstOrDefault(element => element.Name == name);
                current = current.Parent;
            }

            if (range != null && element == null)
            {
                diagnostics.Error(string.Format("The variable {0} does not exist in the {1}.", name, ErrorName), range);
            }

            return(element);
        }
示例#16
0
        public void AddMethod(IMethod method, FileDiagnostics diagnostics, DocRange range)
        {
            var allMethods = AllMethodsInScope();

            if (method == null)
            {
                throw new ArgumentNullException(nameof(method));
            }
            if (allMethods.Contains(method))
            {
                throw new Exception("method reference is already in scope.");
            }

            foreach (var m in allMethods)
            {
                if (method.Name == m.Name && method.Parameters.Length == m.Parameters.Length)
                {
                    bool matches = true;
                    for (int p = 0; p < method.Parameters.Length; p++)
                    {
                        if (method.Parameters[p].Type != m.Parameters[p].Type)
                        {
                            matches = false;
                        }
                    }

                    if (matches)
                    {
                        if (range == null)
                        {
                            throw new Exception();
                        }
                        diagnostics.Error("A method with the same name and parameter types was already defined in this scope.", range);
                        return;
                    }
                }
            }

            Methods.Add(method);
        }
        protected void Inherit(CodeType extend, FileDiagnostics diagnostics, DocRange range)
        {
            if (extend == null)
            {
                throw new ArgumentNullException(nameof(extend));
            }

            string errorMessage = null;

            if (!extend.CanBeExtended)
            {
                errorMessage = "Type '" + extend.Name + "' cannot be inherited.";
            }

            else if (extend == this)
            {
                errorMessage = "Cannot extend self.";
            }

            else if (extend.Implements(this))
            {
                errorMessage = $"The class {extend.Name} extends this class.";
            }

            if (errorMessage != null)
            {
                if (diagnostics == null || range == null)
                {
                    throw new Exception(errorMessage);
                }
                else
                {
                    diagnostics.Error(errorMessage, range);
                    return;
                }
            }

            Extends = extend;
        }
        public bool Apply(FileDiagnostics diagnostics, AttributeContext attribute)
        {
            if (_disallowedAttributes.Contains(attribute.Type))
            {
                diagnostics.Error("The '" + attribute.Type.ToString().ToLower() + "' attribute is not allowed.", attribute.Range);
                return(false);
            }

            // Apply the attribute.
            switch (attribute.Type)
            {
            // Accessors
            case AttributeType.Public: Accessor = AccessLevel.Public; break;

            case AttributeType.Protected: Accessor = AccessLevel.Protected; break;

            case AttributeType.Private: Accessor = AccessLevel.Private; break;

            // Apply static
            case AttributeType.Static: IsStatic = true; break;

            // Apply virtual
            case AttributeType.Virtual: IsVirtual = true; break;

            // Apply override
            case AttributeType.Override: IsOverride = true; break;

            // Apply Recursive
            case AttributeType.Recursive: IsRecursive = true; break;

            // Apply Variables

            default: throw new NotImplementedException();
            }

            return(true);
        }
        /// <summary>
        /// Adds a method to the current scope.
        /// When handling methods added by the user, supply the diagnostics and range to show the syntax error at.
        /// When handling methods added internally, have the diagnostics and range parameters be null. An exception will be thrown instead if there is a syntax error.
        /// </summary>
        /// <param name="method">The method that will be added to the current scope. If the object reference is already in the direct scope, an exception will be thrown.</param>
        /// <param name="diagnostics">The file diagnostics to throw errors with. Should be null when adding methods internally.</param>
        /// <param name="range">The document range to throw errors at. Should be null when adding methods internally.</param>
        public void AddMethod(IMethod method, FileDiagnostics diagnostics, DocRange range, bool checkConflicts = true)
        {
            if (method == null)
            {
                throw new ArgumentNullException(nameof(method));
            }

            if (checkConflicts && HasConflict(method))
            {
                string message = "A method with the same name and parameter types was already defined in this scope.";

                if (diagnostics != null && range != null)
                {
                    diagnostics.Error(message, range);
                    return;
                }
                else
                {
                    throw new Exception(message);
                }
            }

            AddNativeMethod(method);
        }
 public void Error(string message, DocRange errorRange) => _diagnostics.Error(message, errorRange);
        public VariableResolve(VariableResolveOptions options, IExpression expression, DocRange expressionRange, FileDiagnostics diagnostics)
        {
            // The expression is a variable.
            if (expression is CallVariableAction)
            {
                // Get the variable being set and the range.
                SetVariable   = (CallVariableAction)expression;
                VariableRange = expressionRange;
            }
            // The expression is an expression tree.
            else if (expression is ExpressionTree tree)
            {
                Tree = tree;
                if (tree.Completed)
                {
                    // If the resulting expression in the tree is not a variable.
                    if (tree.Result is CallVariableAction == false)
                    {
                        NotAVariableRange = tree.ExprContextTree.Last().GetRange();
                    }
                    else
                    {
                        // Get the variable and the range.
                        SetVariable   = (CallVariableAction)tree.Result;
                        VariableRange = tree.ExprContextTree.Last().GetRange();
                    }
                }
            }
            // The expression is not a variable.
            else if (expression != null)
            {
                NotAVariableRange = expressionRange;
            }

            // NotAVariableRange will not be null if the resulting expression is a variable.
            if (NotAVariableRange != null)
            {
                diagnostics.Error("Expected a variable.", NotAVariableRange);
            }

            // Make sure the variable can be set to.
            if (SetVariable != null)
            {
                // Check if the variable is settable.
                if (options.ShouldBeSettable && !SetVariable.Calling.Settable())
                {
                    diagnostics.Error($"The variable '{SetVariable.Calling.Name}' cannot be set to.", VariableRange);
                }

                // Check if the variable is a whole workshop variable.
                if (options.FullVariable)
                {
                    Var asVar = SetVariable.Calling as Var;
                    if (asVar == null || asVar.StoreType != StoreType.FullVariable)
                    {
                        diagnostics.Error($"The variable '{SetVariable.Calling.Name}' cannot be indexed.", VariableRange);
                    }
                }

                // Check for indexers.
                if (!options.CanBeIndexed && SetVariable.Index.Length != 0)
                {
                    diagnostics.Error($"The variable '{SetVariable.Calling.Name}' cannot be indexed.", VariableRange);
                }
            }

            DoesResolveToVariable = SetVariable != null;
        }
示例#22
0
 public void Copy(FileDiagnostics diagnostics)
 {
     diagnostics.Error($"Multiple '{Type.ToString().ToLower()}' attributes.", Range);
 }