/** * \file block.cpp * \brief Block Scope * * Block scope, that is, part of a piece of code. * * \author Stefan Reuther */ INTERFACE: #include "scope.h" #include "type_rep.h" #include "ptree_nodes.h" class Function_signature; class Block_scope : public Abstract_scope { /** if set, symbols declared in the parent are treated identical to those declared here. */ bool use_parent; std::string fun_prefix, block_prefix; Abstract_scope* nonblock; Type this_type; Function_signature* fsig; }; IMPLEMENTATION: #include #include "except.h" #include "symbol_name.h" #include "annotation.h" #include "function.h" #include "variable.h" #include "init_handler.h" /** Block that implements a function. \param fsig the function */ PUBLIC Block_scope::Block_scope(Function_signature* fsig) : Abstract_scope(fsig->get_function()->get_declared_scope()), use_parent(false), fun_prefix(Symbol_name::get_mangled_scope_from_symbol(fsig->get_function()->get_name())), block_prefix(Symbol_name::get_mangled_block_scope(fun_prefix)), this_type(fsig->get_this_type()), fsig(fsig) // Why the heck halluziniert Emacs hier unbalanced parantheses? { } /** Sub-block inside another block. \param parent parent block \param use_parent true iff this "inherits" our parent's variables. This is needed to implement combined scopes like "if (int i = ...) { ... }". */ PUBLIC Block_scope::Block_scope(Block_scope* parent, bool use_parent) : Abstract_scope(parent), use_parent(use_parent), fun_prefix(parent->fun_prefix), block_prefix(Symbol_name::get_mangled_block_scope(fun_prefix)), this_type(parent->get_this_type()), fsig(parent->fsig) { } PUBLIC Block_scope::~Block_scope() { } PUBLIC Variable_symbol* Block_scope::add_variable(Storage_class_specifier storage, Type type, Ptree* name, Ptree* init, Ptree* bitsize) { if (bitsize) compile_error("local variables can't have bitsize"); if (!name && storage != s_Parameter) compile_error("you cannot declare nameless local variables"); if (storage == s_None) storage = s_Auto; else if (storage == s_Auto || storage == s_Parameter || storage == s_Register || storage == s_Static) ; else if (storage == s_Extern) compile_error("FIXME: extern within a function"); else compile_error("invalid storage class for local variable"); /* process initializer */ if (init) init = Init_handler(this, init, true).process_initializer(type.get_unqualified_type()); /* since there is no way to predeclare a local variable, just add it to the symbol table. add_symbol will bomb out if something goes wrong. */ Symbol_name sym_name (name, this, false); if (sym_name.is_template()) compile_error("template variables are not allowed"); if (sym_name.is_qualified()) compile_error("can't define qualified ids in block scope"); Variable_symbol* vsym = new Variable_symbol(type, storage, init, 0, Symbol::st_Defined); add_symbol(sym_name.get_name(), vsym); /* if it is a parameter, tell the function about it */ if (storage == s_Parameter) fsig->add_parameter(vsym); return vsym; } PUBLIC Function_signature* Block_scope::add_function_decl(Storage_class_specifier storage, Function_specifier_set fspec, Type type, const Symbol_name& sym_name) { compile_error("geht auch noch nicht"); } PUBLIC void Block_scope::add_function_implementation(Function_signature* fsig, Block_scope* scope, Ptree* defn, Ptree* initializer) { compile_error("geht erst recht nicht"); } PUBLIC void Block_scope::add_symbol(std::string name, Symbol* sym) { /* FIXME: we should reject "for (int i = 0; ;) int i;". Therefore, we should look whether the parent defines this symbol. This makes problems when the inner scope defines "struct i" because then the outer "i" will no longer be found. We can't just dump the symbol in the parent's scope because that might be used by several child scopes: "if (int i = f()) { here } else { and_here }". A possible solution would move from looking up Symbol_pairs to Symbols. */ Symbol_table::get_instance().add_symbol(get_unique_name(name), name.length(), sym); } PUBLIC std::string Block_scope::get_unique_name(std::string name) { return Symbol_name::get_mangled_symbol_name(block_prefix, name); } PUBLIC Type Block_scope::get_this_type() const { return this_type; } PUBLIC inline Function_signature* Block_scope::get_function() const { return fsig; } PUBLIC void Block_scope::set_this_type(Type t) { this_type = t; } PUBLIC Symbol_pair Block_scope::lookup_here(std::string name, bool for_decl) { if (Symbol_pair p = Symbol_table::get_instance().get_symbol(get_unique_name(name))) return p; if (use_parent) return get_parent()->lookup_here(name, for_decl); else return Symbol_pair(); }