internal override void ResolveVariableOrigins(ParserContext parser, VariableScope varIds, VariableIdAllocPhase phase) { this.IterationExpression.ResolveVariableOrigins(parser, varIds, phase); if ((phase & VariableIdAllocPhase.REGISTER) != 0) { varIds.RegisterVariable(this.IterationType, this.IterationVariable.Value); this.IndexLocalId = varIds.RegisterSyntheticVariable(AType.Integer(this.FirstToken)); this.ListLocalId = varIds.RegisterSyntheticVariable(AType.Any(this.FirstToken)); } if (phase != VariableIdAllocPhase.REGISTER_AND_ALLOC) { foreach (Executable ex in this.Code) { ex.ResolveVariableOrigins(parser, varIds, phase); } } else { foreach (Executable ex in this.Code) { ex.ResolveVariableOrigins(parser, varIds, VariableIdAllocPhase.REGISTER); } foreach (Executable ex in this.Code) { ex.ResolveVariableOrigins(parser, varIds, VariableIdAllocPhase.ALLOC); } } this.IterationVariableId = varIds.GetVarId(this.IterationVariable); }
internal override void ResolveVariableOrigins(ParserContext parser, VariableScope varIds, VariableIdAllocPhase phase) { if ((phase & VariableIdAllocPhase.ALLOC) != 0) { this.VarId = varIds.GetVarId(this.FirstToken); if (this.VarId == null) { string name = this.FirstToken.Value; if (parser.ScopeManager.IsValidAssemblyNameFromLocale(this.Locale, name)) { throw new ParserException(this, "'" + name + "' is referenced but not imported in this file."); } Node owner = this.Owner; while (owner != null && !(owner is ClassDefinition)) { owner = owner.Owner; } if (owner != null) { ClassDefinition cd = (ClassDefinition)owner; foreach (FieldDefinition fd in cd.Fields) { if (fd.NameToken.Value == name) { string message = "'" + name + "' is used like a local variable but it is " + (fd.Modifiers.HasStatic ? "a static" : "an instance") + " field."; message += " Did you mean '" + (fd.Modifiers.HasStatic ? cd.NameToken.Value : "this") + "." + name + "' instead of '" + name + "'?"; throw new ParserException(this, message); } } foreach (FunctionDefinition fd in cd.Methods) { if (fd.NameToken.Value == name) { string message = "'" + name + "' is used like a standalone function but it is " + (fd.Modifiers.HasStatic ? "a static" : "an instance") + " method."; message += " Did you mean '" + (fd.Modifiers.HasStatic ? cd.NameToken.Value : "this") + "." + name + "' instead of '" + name + "'?"; throw new ParserException(this, message); } } } if (this.Owner is ConstDefinition) { throw new ParserException(this, "The expression '" + name + "' is not defined. Are you missing a const definition?"); } // TODO: But if it's being called like a function then... // - give a better error message "function 'foo' is not defined" // - give an even better error message when there's a class or instance function with the same name // e.g. "'foo' is a static function and must be invoked with the class name: FooClass.foo(...) // - if there's a method, suggest using "this." // - if the variable name matches a library that is available, suggest it as a missing import. throw new ParserException(this, "The variable '" + name + "' is used but is never assigned to."); } } }
internal override void ResolveVariableOrigins(ParserContext parser, VariableScope varIds, VariableIdAllocPhase phase) { foreach (Executable ex in this.TryBlock) { ex.ResolveVariableOrigins(parser, varIds, phase); } foreach (CatchBlock cb in this.CatchBlocks) { if (cb.ExceptionVariableToken != null) { if ((phase & VariableIdAllocPhase.REGISTER) != 0) { // TODO: this is a little flawed. Should find the common base class. AType exceptionType = cb.Types.Length == 1 ? AType.ProvideRoot(cb.TypeTokens[0], cb.Types[0]) : AType.ProvideRoot(cb.CatchToken, "Core.Exception"); varIds.RegisterVariable(exceptionType, cb.ExceptionVariableToken.Value); } if ((phase & VariableIdAllocPhase.ALLOC) != 0) { cb.VariableLocalScopeId = varIds.GetVarId(cb.ExceptionVariableToken); } } foreach (Executable ex in cb.Code) { ex.ResolveVariableOrigins(parser, varIds, phase); } } if (this.FinallyBlock != null) { foreach (Executable ex in this.FinallyBlock) { ex.ResolveVariableOrigins(parser, varIds, phase); } } }
internal override void ResolveVariableOrigins(ParserContext parser, VariableScope varIds, VariableIdAllocPhase phase) { if ((phase & VariableIdAllocPhase.ALLOC) != 0) { this.VarId = varIds.GetVarId(this.FirstToken); if (this.VarId == null) { string name = this.FirstToken.Value; if (parser.ScopeManager.IsAlreadyImportedAnywhere(this.Locale, name)) { throw new ParserException(this, "'" + name + "' is referenced but not imported in this file."); } Node owner = this.Owner; while (owner != null && !(owner is ClassDefinition)) { owner = owner.Owner; } if (owner != null) { ClassDefinition cd = (ClassDefinition)owner; foreach (FieldDefinition fd in cd.Fields) { if (fd.NameToken.Value == name) { string message = "'" + name + "' is used like a local variable but it is " + (fd.Modifiers.HasStatic ? "a static" : "an instance") + " field."; message += " Did you mean '" + (fd.Modifiers.HasStatic ? cd.NameToken.Value : "this") + "." + name + "' instead of '" + name + "'?"; throw new ParserException(this, message); } } foreach (FunctionDefinition fd in cd.Methods) { if (fd.NameToken.Value == name) { string message = "'" + name + "' is used like a standalone function but it is " + (fd.Modifiers.HasStatic ? "a static" : "an instance") + " method."; message += " Did you mean '" + (fd.Modifiers.HasStatic ? cd.NameToken.Value : "this") + "." + name + "' instead of '" + name + "'?"; throw new ParserException(this, message); } } } if (this.Owner is ConstDefinition) { throw new ParserException(this, "The expression '" + name + "' is not defined. Are you missing a const definition?"); } if (this.DirectOwner != null && this.DirectOwner is FunctionCall) { throw new ParserException(this.FirstToken, "Function '" + name + "' is not defined."); } if (this.CompilationScope.Dependencies.Where(dep => dep.Name == name).FirstOrDefault() != null) { throw new ParserException(this.FirstToken, "The library '" + name + "' is referenced here, but it has not been imported in this file. Add 'import " + name + "' to use it."); } throw new ParserException(this, "The variable '" + name + "' is used but is never assigned to."); } } }