Gyoji Compiler
|
Tracks variables declared in each scope along with abels and goto statements in a highly simplified intermediate representation. More...
#include <function-scope.hpp>
Public Member Functions | |
~ScopeTracker () | |
Move along, nothing to see here. | |
void | scope_push (const Gyoji::context::SourceReference &_source_ref) |
void | scope_push_loop (const Gyoji::context::SourceReference &_source_ref, size_t _loop_break_blockid, size_t _loop_continue_blockid) |
void | scope_pop () |
void | label_define (std::string label_name, const Gyoji::context::SourceReference &_source_ref) |
bool | add_variable (std::string variable_name, const Gyoji::mir::Type *mir_type, const Gyoji::context::SourceReference &source_ref) |
bool | check (std::vector< std::pair< const ScopeOperation *, std::vector< const ScopeOperation * > > > &goto_fixups) const |
bool | is_in_loop () const |
const LocalVariable * | get_variable (std::string variable_name) const |
std::vector< std::string > | get_variables_to_unwind_for_root () const |
std::vector< std::string > | get_variables_to_unwind_for_scope () const |
std::vector< std::string > | get_variables_to_unwind_for_label (std::string &label) const |
Tracks variables declared in each scope along with abels and goto statements in a highly simplified intermediate representation.
This class exists to represent a scope in a highly simplified way that is specificatlly designed to provide all of the information needed to resolve labels and goto statements and unwind scopes when a goto/branch would take control of the program directly from one scope to another. Some of these constructs violate the 'normal' scope rules about variable declaration, so this is done in order to first check that the jump is legal and then to provide the information to the FunctionDefinitionResolver about what variables would be leaving scope when a goto occurs. In addition, there is logic here to deal with the fact that a 'goto' may precede its corresponding 'label' definition so that the code can be emitted anyway.
This scope tracker is only to be used inside the lowering process as an intermediate calculation and should not be used outside of that context.
ScopeTracker::~ScopeTracker | ( | ) |
Move along, nothing to see here.
Move along, nothing to see here.
bool ScopeTracker::add_variable | ( | std::string | variable_name, |
const Gyoji::mir::Type * | mir_type, | ||
const Gyoji::context::SourceReference & | source_ref | ||
) |
Defines a variable in the current scope.
bool ScopeTracker::check | ( | std::vector< std::pair< const ScopeOperation *, std::vector< const ScopeOperation * > > > & | goto_fixups | ) | const |
This method could definitely use a better name. It does a few things and it's important that they be done together even though they are only somewhat related.
The main thing the method does is evaluate the scope rules for 'goto' statements and make sure that the result of the 'goto' would not skip variable declarations or initializations at the target label.
As a side-effect of the calculations, it also determines which variables would go out of scope as a result of the 'goto' statement and thus which ones need to be un-declared and the destructors called.
The parameter given 'goto_fixups' is an 'out' parameter that fills the vector with all of the 'goto' statements along with the vector of variables that need to be un-declared before the Jump statment of the goto. The vector of variables is in the order in which they should be destructed, so order is important when processing the fixups to the MIR.
const LocalVariable * ScopeTracker::get_variable | ( | std::string | variable_name | ) | const |
Searches the current scope upwards toward the parent and returns the type of variable declared if it is defined. If it is not defined, returns nullptr to indicate that it's not defined anywhere in the current or parent scopes.
std::vector< std::string > Gyoji::frontend::lowering::ScopeTracker::get_variables_to_unwind_for_label | ( | std::string & | label | ) | const |
Returns the list of variables to unwind (in order) to get back to a common ancestor of the label.
std::vector< std::string > ScopeTracker::get_variables_to_unwind_for_root | ( | ) | const |
Returns the list of variables to unwind (in order) to get back to the root (like for a return).
std::vector< std::string > ScopeTracker::get_variables_to_unwind_for_scope | ( | ) | const |
Returns the list of variables to unwind (in order) to get back to the root (like for a return).
bool ScopeTracker::is_in_loop | ( | ) | const |
Returns true if this or any ancestor is a 'loop' that can be 'break' or 'continue' out of.
void ScopeTracker::label_define | ( | std::string | label_name, |
const Gyoji::context::SourceReference & | _source_ref | ||
) |
Adds a label to the current scope with the basic_block it knows about. If it was seen first in a 'goto', we pull it out of that list and put it into the scope where it belongs.
void ScopeTracker::scope_pop | ( | ) |
Pop out of current scope back to parent.
void ScopeTracker::scope_push | ( | const Gyoji::context::SourceReference & | _source_ref | ) |
Enter a new (un-named) scope.
void ScopeTracker::scope_push_loop | ( | const Gyoji::context::SourceReference & | _source_ref, |
size_t | _loop_break_blockid, | ||
size_t | _loop_continue_blockid | ||
) |
Pushes a 'loop' scope which knows where we would jump to in case of 'break' or 'continue'.