//--- determine if name is already in scope. public bool IsDefined(String name) { bool defined = symbols.IsDefined(name); // look in current symbol table. if (defined || outer == null) { // either name is found in current symbol table or there is no outer table - so return what we've got. return(defined); } else { return(outer.IsDefined(name)); // not found so search recursively through outer scope. } } // end IsDefined method.
public bool IsDefinedInParent(String name) { ISymbolTable scopeRef = parent; while (scopeRef != null) { if (scopeRef.IsDefined(name)) { return(true); } scopeRef = scopeRef.Parent; } return(false); }
public override bool VisitAssignmentExpression(AssignmentExpression assignExp) { if (assignExp.Target.NodeType == NodeType.VariableRefExpression) { // Convert to declaration if not found on the scope VariableReferenceExpression varRef = (VariableReferenceExpression)assignExp.Target; ISymbolTable scope = varRef.SymbolTable; System.Diagnostics.Debug.Assert(scope != null); String name = varRef.Identifier.Name; if (!scope.IsDefined(name)) // TODO: The rules are slighly more complicated than that. { errorReport.Disable(); SingleVariableDeclarationStatement varDecl = new SingleVariableDeclarationStatement(varRef.Identifier); IStatement stmt = ASTUtils.GetParentStatement(varRef); System.Diagnostics.Debug.Assert(stmt != null); IStatementContainer stmts = stmt.Parent as IStatementContainer; int index = stmts.Statements.IndexOf(stmt); varDecl.InitExp = assignExp.Value; // stmts.Statements.Insert(index, varDecl); stmts.Statements.Replace(stmt, varDecl); if (!ApplyDeclarationRules(varRef.Identifier, scope, varDecl, stmt)) { stmts.Statements.Remove(varDecl); } errorReport.Enable(); } } return(base.VisitAssignmentExpression(assignExp)); }
public override bool VisitParameterIdentifier(ParameterIdentifier parameterIdentifier) { ISymbolTable namescope = parameterIdentifier.Parent.SymbolTable; System.Diagnostics.Debug.Assert(namescope != null); System.Diagnostics.Debug.Assert(namescope.ScopeType == ScopeType.Method || namescope.ScopeType == ScopeType.Block); if (!identifierService.IsValidFormatParameterName(parameterIdentifier.Name)) { errorReport.Error("TODOFILENAME", parameterIdentifier.Position, "'{0}' is an invalid parameter name.", parameterIdentifier.Name); return(false); } System.Diagnostics.Debug.Assert(!namescope.IsDefined(parameterIdentifier.Name)); namescope.AddVariable(parameterIdentifier); return(base.VisitParameterIdentifier(parameterIdentifier)); }
private void EnsureTypeDeclarationsBelongsToThisScope(MultipleVariableDeclarationStatement varDecl, IList stmts) { ISymbolTable namescope = varDecl.Parent.SymbolTable; System.Diagnostics.Debug.Assert(namescope != null); foreach (SingleVariableDeclarationStatement typeDecl in stmts) { Identifier ident = typeDecl.Identifier; // Most simple of cases: duplicated declaration if (namescope.IsDefined(ident.Name)) { errorReport.Error("TODOFILENAME", typeDecl.Position, "Sorry but '{0}' is already defined.", ident.Name); continue; } ApplyDeclarationRules(ident, namescope, typeDecl, varDecl); } }
private bool ApplyDeclarationRules(Identifier ident, ISymbolTable namescope, SingleVariableDeclarationStatement typeDecl, IStatement statem) { // Second simple case: a local var and we are on the right place to // declare it if (ident.Type == IdentifierType.Local && (namescope.ScopeType == ScopeType.Method || namescope.ScopeType == ScopeType.Compound || namescope.ScopeType == ScopeType.Block)) { namescope.AddVariable(ident); return(true); } // More complex: a block or compound tries to redefine a variable if (ident.Type == IdentifierType.Local && (namescope.ScopeType == ScopeType.Compound || namescope.ScopeType == ScopeType.Block)) { if (namescope.Parent.IsDefined(ident.Name)) { errorReport.Error("TODOFILENAME", typeDecl.Position, "Sorry but '{0}' is already defined in a parent scope.", ident.Name); return(false); } } // Local variables at class level? // We will support that as a type initializer, but not now. if (ident.Type == IdentifierType.Local && namescope.ScopeType == ScopeType.Type) { errorReport.Error("TODOFILENAME", typeDecl.Position, "At type level, just instance or static fields are allowed (yet)"); return(false); } // Static or instance in a method/block/compound are moved // to the parent class or source unit level if (ident.Type == IdentifierType.InstanceField || ident.Type == IdentifierType.StaticField) { if (namescope.ScopeType == ScopeType.SourceUnit || namescope.ScopeType == ScopeType.Type) { namescope.AddVariable(ident); } else if (namescope.ScopeType == ScopeType.Method || namescope.ScopeType == ScopeType.Compound || namescope.ScopeType == ScopeType.Block) { IASTNode node = statem.Parent; while (node != null && node.NodeType != NodeType.TypeDefinition && node.NodeType != NodeType.SourceUnit) { node = node.Parent; } if (node == null || node.SymbolTable == null) { errorReport.Error("TODOFILENAME", typeDecl.Position, "Compiler error: The instance of static declaration '{0}' could not be mapped to a parent type", ident.Name); return(false); } ISymbolTable parentScope = node.SymbolTable; IStatementContainer typeStmtsContainer = node as IStatementContainer; System.Diagnostics.Debug.Assert(parentScope != null); System.Diagnostics.Debug.Assert(typeStmtsContainer != null); if (parentScope.IsDefined(ident.Name)) { errorReport.Error("TODOFILENAME", typeDecl.Position, "Sorry but '{0}' is already defined.", ident.Name); return(false); } else { parentScope.AddVariable(ident); // We can replace the declaration on the method // body with an assignment if and only if this type decl has // an init expression, so CreateAssignmentFromTypeDecl can return null AssignmentExpression assignExp = CreateAssignmentFromTypeDecl(typeDecl); ExpressionStatement assignExpStmt = new ExpressionStatement(assignExp); typeDecl.ConvertInitExpressionToDependency(); // Replace the declaration with an assignment (statem.Parent as IStatementContainer).Statements.Replace(typeDecl, assignExpStmt); // Add the member/field declaration to the parent typeStmtsContainer.Statements.Add(typeDecl); // TODO: Link assignment expression and typeDecl to help // find out the type of the field later return(true); } } } return(false); }