/// <summary> /// Add an object symbol to the current scope. /// Note: /// This method won't check if the symbol is redefined, /// although in this situation Add() will throw an exception. /// Caller should call ContainsSymbolInCurrentScope() first. /// </summary> /// <param name="symbol"></param> /// <param name="type"></param> /// <param name="declaration"></param> public void AddObj(string symbol, T type, SymbolEntry.Link link, EObj.Storage storage, Position pos) { if (storage == EObj.Storage.AUTO || storage == EObj.Storage.REGISTER) { // This is a dynamic object. // In this implementation, register and auto are the same. scopes.Peek().AddSymbol(new EObj(dynamicId.ToString(), symbol, type, pos, link, storage)); ASTEnv.AddLocal(dynamicId.ToString(), symbol, type); dynamicId++; } else { string uid = string.Format("__static_{0}_{1}", symbol, staticId++); if (storage == EObj.Storage.STATIC) { // This is a static object, check its linkage (either external or internal). scopes.Peek().AddSymbol(new EObj(uid, symbol, type, pos, link, storage)); AST.Env.AddStaticObj(uid, symbol, type, link == SymbolEntry.Link.EXTERNAL, false); } else { // This is an external object, the linkage must be external. scopes.Peek().AddSymbol(new EObj(uid, symbol, type, pos, link, storage)); AST.Env.AddStaticObj(uid, symbol, type, true, true); } } }
/// <summary> /// Exit this scope. /// </summary> public void PopScope() { if (scopes.Peek().kind == ScopeKind.BLOCK) { ASTEnv.PopBlock(); } scopes.Pop(); }
/// <summary> /// Push a block scope. /// </summary> public void PushBlockScope() { scopes.Push(new Scope(ScopeKind.BLOCK)); ASTEnv.PushBlock(); }