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); } }
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); }
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)); }
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)); }
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); } }
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); }
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; }
public void Copy(FileDiagnostics diagnostics) { diagnostics.Error($"Multiple '{Type.ToString().ToLower()}' attributes.", Range); }