Commit f37c74e4 authored by Jürg Billeter's avatar Jürg Billeter

codegen: Add EmitContext class

parent 449a0c01
......@@ -769,10 +769,7 @@ public class Vala.CCodeArrayModule : CCodeMethodCallModule {
var block = new CCodeBlock ();
if (requires_copy (array_type.element_type)) {
var old_symbol = current_symbol;
var old_temp_vars = temp_vars;
current_symbol = null;
temp_vars = new ArrayList<LocalVariable> ();
push_context (new EmitContext ());
var cdecl = new CCodeDeclaration (array_type.get_cname ());
var cvardecl = new CCodeVariableDeclarator ("result");
......@@ -807,8 +804,8 @@ public class Vala.CCodeArrayModule : CCodeMethodCallModule {
var cfrag = new CCodeFragment ();
append_temp_decl (cfrag, temp_vars);
block.add_statement (cfrag);
current_symbol = old_symbol;
temp_vars = old_temp_vars;
pop_context ();
} else {
var dup_call = new CCodeFunctionCall (new CCodeIdentifier ("g_memdup"));
dup_call.add_argument (new CCodeIdentifier ("self"));
......@@ -851,10 +848,7 @@ public class Vala.CCodeArrayModule : CCodeMethodCallModule {
var block = new CCodeBlock ();
if (requires_copy (array_type.element_type)) {
var old_symbol = current_symbol;
var old_temp_vars = temp_vars;
current_symbol = null;
temp_vars = new ArrayList<LocalVariable> ();
push_context (new EmitContext ());
var idx_decl = new CCodeDeclaration ("int");
idx_decl.add_declarator (new CCodeVariableDeclarator ("i"));
......@@ -871,8 +865,8 @@ public class Vala.CCodeArrayModule : CCodeMethodCallModule {
var cfrag = new CCodeFragment ();
append_temp_decl (cfrag, temp_vars);
block.add_statement (cfrag);
current_symbol = old_symbol;
temp_vars = old_temp_vars;
pop_context ();
} else {
source_declarations.add_include ("string.h");
......
......@@ -27,11 +27,46 @@
* Code visitor generating C Code.
*/
public class Vala.CCodeBaseModule : CodeGenerator {
public class EmitContext {
public Symbol? current_symbol;
public ArrayList<Symbol> symbol_stack = new ArrayList<Symbol> ();
public TryStatement current_try;
public CCodeSwitchStatement state_switch_statement;
public ArrayList<LocalVariable> temp_vars = new ArrayList<LocalVariable> ();
public ArrayList<LocalVariable> temp_ref_vars = new ArrayList<LocalVariable> ();
public int next_temp_var_id;
public bool current_method_inner_error;
public Map<string,string> variable_name_map = new HashMap<string,string> (str_hash, str_equal);
public EmitContext (Symbol? symbol = null) {
current_symbol = symbol;
}
public void push_symbol (Symbol symbol) {
symbol_stack.add (current_symbol);
current_symbol = symbol;
}
public void pop_symbol () {
current_symbol = symbol_stack[symbol_stack.size - 1];
symbol_stack.remove_at (symbol_stack.size - 1);
}
}
public CodeContext context { get; set; }
public Symbol root_symbol;
public Symbol current_symbol;
public TryStatement current_try;
public EmitContext emit_context = new EmitContext ();
List<EmitContext> emit_context_stack = new ArrayList<EmitContext> ();
public Symbol current_symbol { get { return emit_context.current_symbol; } }
public TryStatement current_try {
get { return emit_context.current_try; }
set { emit_context.current_try = value; }
}
public TypeSymbol? current_type_symbol {
get {
......@@ -135,13 +170,17 @@ public class Vala.CCodeBaseModule : CodeGenerator {
// code nodes to be inserted before the current statement
// used by async method calls in coroutines
public CCodeFragment pre_statement_fragment;
// case statements to be inserted for the couroutine state
public CCodeSwitchStatement state_switch_statement;
public CCodeSwitchStatement state_switch_statement {
get { return emit_context.state_switch_statement; }
set { emit_context.state_switch_statement = value; }
}
/* all temporary variables */
public ArrayList<LocalVariable> temp_vars = new ArrayList<LocalVariable> ();
public ArrayList<LocalVariable> temp_vars { get { return emit_context.temp_vars; } }
/* temporary variables that own their content */
public ArrayList<LocalVariable> temp_ref_vars = new ArrayList<LocalVariable> ();
public ArrayList<LocalVariable> temp_ref_vars { get { return emit_context.temp_ref_vars; } }
/* cache to check whether a certain marshaller has been created yet */
public Set<string> user_marshal_set;
/* (constant) hash table with all predefined marshallers */
......@@ -149,12 +188,21 @@ public class Vala.CCodeBaseModule : CodeGenerator {
/* (constant) hash table with all reserved identifiers in the generated code */
Set<string> reserved_identifiers;
public int next_temp_var_id = 0;
public int next_temp_var_id {
get { return emit_context.next_temp_var_id; }
set { emit_context.next_temp_var_id = value; }
}
public int next_regex_id = 0;
public bool in_creation_method { get { return current_method is CreationMethod; } }
public bool in_constructor = false;
public bool in_static_or_class_context = false;
public bool current_method_inner_error = false;
public bool current_method_inner_error {
get { return emit_context.current_method_inner_error; }
set { emit_context.current_method_inner_error = value; }
}
public int next_coroutine_state = 1;
int next_block_id = 0;
Map<Block,int> block_map = new HashMap<Block,int> ();
......@@ -214,7 +262,7 @@ public class Vala.CCodeBaseModule : CodeGenerator {
public Set<string> wrappers;
Set<Symbol> generated_external_symbols;
public Map<string,string> variable_name_map = new HashMap<string,string> (str_hash, str_equal);
public Map<string,string> variable_name_map { get { return emit_context.variable_name_map; } }
public CCodeBaseModule () {
predefined_marshal_set = new HashSet<string> (str_hash, str_equal);
......@@ -475,6 +523,23 @@ public class Vala.CCodeBaseModule : CodeGenerator {
}
}
public void push_context (EmitContext emit_context) {
if (this.emit_context != null) {
emit_context_stack.add (this.emit_context);
}
this.emit_context = emit_context;
}
public void pop_context () {
if (emit_context_stack.size > 0) {
this.emit_context = emit_context_stack[emit_context_stack.size - 1];
emit_context_stack.remove_at (emit_context_stack.size - 1);
} else {
this.emit_context = null;
}
}
public CCodeIdentifier get_value_setter_function (DataType type_reference) {
var array_type = type_reference as ArrayType;
if (type_reference.data_type != null) {
......@@ -566,9 +631,7 @@ public class Vala.CCodeBaseModule : CodeGenerator {
user_marshal_set = new HashSet<string> (str_hash, str_equal);
next_temp_var_id = 0;
next_regex_id = 0;
variable_name_map.clear ();
gvaluecollector_h_needed = false;
requires_array_free = false;
......@@ -1224,21 +1287,7 @@ public class Vala.CCodeBaseModule : CodeGenerator {
check_type (prop.property_type);
int old_next_temp_var_id = next_temp_var_id;
var old_temp_vars = temp_vars;
var old_temp_ref_vars = temp_ref_vars;
var old_variable_name_map = variable_name_map;
next_temp_var_id = 0;
temp_vars = new ArrayList<LocalVariable> ();
temp_ref_vars = new ArrayList<LocalVariable> ();
variable_name_map = new HashMap<string,string> (str_hash, str_equal);
prop.accept_children (this);
next_temp_var_id = old_next_temp_var_id;
temp_vars = old_temp_vars;
temp_ref_vars = old_temp_ref_vars;
variable_name_map = old_variable_name_map;
}
public void generate_type_declaration (DataType type, CCodeDeclarationSpace decl_space) {
......@@ -1353,10 +1402,7 @@ public class Vala.CCodeBaseModule : CodeGenerator {
}
public override void visit_property_accessor (PropertyAccessor acc) {
var old_symbol = current_symbol;
bool old_method_inner_error = current_method_inner_error;
current_symbol = acc;
current_method_inner_error = false;
push_context (new EmitContext (acc));
var prop = (Property) acc.prop;
......@@ -1610,8 +1656,7 @@ public class Vala.CCodeBaseModule : CodeGenerator {
source_type_member_definition.append (function);
}
current_symbol = old_symbol;
current_method_inner_error = old_method_inner_error;
pop_context ();
}
public override void visit_destructor (Destructor d) {
......@@ -5004,16 +5049,8 @@ public class Vala.CCodeBaseModule : CodeGenerator {
var dt = (DelegateType) l.target_type;
l.method.cinstance_parameter_position = dt.delegate_symbol.cinstance_parameter_position;
var old_temp_vars = temp_vars;
var old_temp_ref_vars = temp_ref_vars;
temp_vars = new ArrayList<LocalVariable> ();
temp_ref_vars = new ArrayList<LocalVariable> ();
l.accept_children (this);
temp_vars = old_temp_vars;
temp_ref_vars = old_temp_ref_vars;
l.ccodenode = new CCodeIdentifier (l.method.get_cname ());
}
......@@ -5650,14 +5687,7 @@ public class Vala.CCodeBaseModule : CodeGenerator {
function.add_parameter (new CCodeFormalParameter ("self", "const " + st.get_cname () + "*"));
function.add_parameter (new CCodeFormalParameter ("dest", st.get_cname () + "*"));
int old_next_temp_var_id = next_temp_var_id;
var old_temp_vars = temp_vars;
var old_temp_ref_vars = temp_ref_vars;
var old_variable_name_map = variable_name_map;
next_temp_var_id = 0;
temp_vars = new ArrayList<LocalVariable> ();
temp_ref_vars = new ArrayList<LocalVariable> ();
variable_name_map = new HashMap<string,string> (str_hash, str_equal);
push_context (new EmitContext ());
var cblock = new CCodeBlock ();
var cfrag = new CCodeFragment ();
......@@ -5707,10 +5737,7 @@ public class Vala.CCodeBaseModule : CodeGenerator {
append_temp_decl (cfrag, temp_vars);
temp_vars.clear ();
next_temp_var_id = old_next_temp_var_id;
temp_vars = old_temp_vars;
temp_ref_vars = old_temp_ref_vars;
variable_name_map = old_variable_name_map;
pop_context ();
source_declarations.add_type_member_declaration (function.copy ());
function.block = cblock;
......
......@@ -261,22 +261,7 @@ public class Vala.CCodeMethodModule : CCodeStructModule {
}
public override void visit_method (Method m) {
var old_symbol = current_symbol;
bool old_method_inner_error = current_method_inner_error;
int old_next_temp_var_id = next_temp_var_id;
var old_temp_vars = temp_vars;
var old_temp_ref_vars = temp_ref_vars;
var old_variable_name_map = variable_name_map;
var old_try = current_try;
var old_state_switch_statement = state_switch_statement;
current_symbol = m;
current_method_inner_error = false;
next_temp_var_id = 0;
temp_vars = new ArrayList<LocalVariable> ();
temp_ref_vars = new ArrayList<LocalVariable> ();
variable_name_map = new HashMap<string,string> (str_hash, str_equal);
current_try = null;
state_switch_statement = null;
push_context (new EmitContext (m));
bool in_gobject_creation_method = false;
bool in_fundamental_creation_method = false;
......@@ -354,14 +339,7 @@ public class Vala.CCodeMethodModule : CCodeStructModule {
bool inner_error = current_method_inner_error;
current_symbol = old_symbol;
current_method_inner_error = old_method_inner_error;
next_temp_var_id = old_next_temp_var_id;
temp_vars = old_temp_vars;
temp_ref_vars = old_temp_ref_vars;
variable_name_map = old_variable_name_map;
current_try = old_try;
state_switch_statement = old_state_switch_statement;
pop_context ();
// do not declare overriding methods and interface implementations
if (m.is_abstract || m.is_virtual
......
......@@ -140,9 +140,9 @@ public class Vala.CCodeStructModule : CCodeBaseModule {
}
public override void visit_struct (Struct st) {
var old_symbol = current_symbol;
push_context (new EmitContext (st));
var old_instance_finalize_fragment = instance_finalize_fragment;
current_symbol = st;
instance_finalize_fragment = new CCodeFragment ();
generate_struct_declaration (st, source_declarations);
......@@ -166,8 +166,9 @@ public class Vala.CCodeStructModule : CCodeBaseModule {
add_struct_free_function (st);
}
current_symbol = old_symbol;
instance_finalize_fragment = old_instance_finalize_fragment;
pop_context ();
}
void add_struct_dup_function (Struct st) {
......
......@@ -26,11 +26,44 @@
* Code visitor generating C Code.
*/
public class Vala.DovaBaseModule : CodeGenerator {
public class EmitContext {
public Symbol? current_symbol;
public ArrayList<Symbol> symbol_stack = new ArrayList<Symbol> ();
public TryStatement current_try;
public ArrayList<LocalVariable> temp_vars = new ArrayList<LocalVariable> ();
public ArrayList<LocalVariable> temp_ref_vars = new ArrayList<LocalVariable> ();
public int next_temp_var_id;
public Map<string,string> variable_name_map = new HashMap<string,string> (str_hash, str_equal);
public EmitContext (Symbol? symbol = null) {
current_symbol = symbol;
}
public void push_symbol (Symbol symbol) {
symbol_stack.add (current_symbol);
current_symbol = symbol;
}
public void pop_symbol () {
current_symbol = symbol_stack[symbol_stack.size - 1];
symbol_stack.remove_at (symbol_stack.size - 1);
}
}
public CodeContext context { get; set; }
public Symbol root_symbol;
public Symbol current_symbol;
public TryStatement current_try;
public EmitContext emit_context = new EmitContext ();
List<EmitContext> emit_context_stack = new ArrayList<EmitContext> ();
public Symbol current_symbol { get { return emit_context.current_symbol; } }
public TryStatement current_try {
get { return emit_context.current_try; }
set { emit_context.current_try = value; }
}
public TypeSymbol? current_type_symbol {
get {
......@@ -127,13 +160,17 @@ public class Vala.DovaBaseModule : CodeGenerator {
public CCodeFragment pre_statement_fragment;
/* all temporary variables */
public ArrayList<LocalVariable> temp_vars = new ArrayList<LocalVariable> ();
public ArrayList<LocalVariable> temp_vars { get { return emit_context.temp_vars; } }
/* temporary variables that own their content */
public ArrayList<LocalVariable> temp_ref_vars = new ArrayList<LocalVariable> ();
public ArrayList<LocalVariable> temp_ref_vars { get { return emit_context.temp_ref_vars; } }
/* (constant) hash table with all reserved identifiers in the generated code */
Set<string> reserved_identifiers;
public int next_temp_var_id = 0;
public int next_temp_var_id {
get { return emit_context.next_temp_var_id; }
set { emit_context.next_temp_var_id = value; }
}
public int next_wrapper_id = 0;
public bool in_creation_method { get { return current_method is CreationMethod; } }
int next_block_id = 0;
......@@ -161,7 +198,7 @@ public class Vala.DovaBaseModule : CodeGenerator {
Set<Symbol> generated_external_symbols;
public Map<string,string> variable_name_map = new HashMap<string,string> (str_hash, str_equal);
public Map<string,string> variable_name_map { get { return emit_context.variable_name_map; } }
public DovaBaseModule () {
reserved_identifiers = new HashSet<string> (str_hash, str_equal);
......@@ -250,9 +287,6 @@ public class Vala.DovaBaseModule : CodeGenerator {
source_declarations.add_include ("dova-base.h");
}
next_temp_var_id = 0;
variable_name_map.clear ();
generated_external_symbols = new HashSet<Symbol> ();
......@@ -324,6 +358,23 @@ public class Vala.DovaBaseModule : CodeGenerator {
}
}
public void push_context (EmitContext emit_context) {
if (this.emit_context != null) {
emit_context_stack.add (this.emit_context);
}
this.emit_context = emit_context;
}
public void pop_context () {
if (emit_context_stack.size > 0) {
this.emit_context = emit_context_stack[emit_context_stack.size - 1];
emit_context_stack.remove_at (emit_context_stack.size - 1);
} else {
this.emit_context = null;
}
}
public override void visit_source_file (SourceFile source_file) {
if (csource_filename == null) {
csource_filename = source_file.get_csource_filename ();
......@@ -594,21 +645,7 @@ public class Vala.DovaBaseModule : CodeGenerator {
}
public override void visit_property (Property prop) {
int old_next_temp_var_id = next_temp_var_id;
var old_temp_vars = temp_vars;
var old_temp_ref_vars = temp_ref_vars;
var old_variable_name_map = variable_name_map;
next_temp_var_id = 0;
temp_vars = new ArrayList<LocalVariable> ();
temp_ref_vars = new ArrayList<LocalVariable> ();
variable_name_map = new HashMap<string,string> (str_hash, str_equal);
prop.accept_children (this);
next_temp_var_id = old_next_temp_var_id;
temp_vars = old_temp_vars;
temp_ref_vars = old_temp_ref_vars;
variable_name_map = old_variable_name_map;
}
public void generate_type_declaration (DataType type, CCodeDeclarationSpace decl_space) {
......@@ -2166,16 +2203,8 @@ public class Vala.DovaBaseModule : CodeGenerator {
var dt = (DelegateType) l.target_type;
l.method.cinstance_parameter_position = dt.delegate_symbol.cinstance_parameter_position;
var old_temp_vars = temp_vars;
var old_temp_ref_vars = temp_ref_vars;
temp_vars = new ArrayList<LocalVariable> ();
temp_ref_vars = new ArrayList<LocalVariable> ();
l.accept_children (this);
temp_vars = old_temp_vars;
temp_ref_vars = old_temp_ref_vars;
l.ccodenode = new CCodeIdentifier (l.method.get_cname ());
}
......
......@@ -791,9 +791,9 @@ public class Vala.DovaObjectModule : DovaArrayModule {
}
public override void visit_class (Class cl) {
var old_symbol = current_symbol;
push_context (new EmitContext (cl));
var old_instance_finalize_fragment = instance_finalize_fragment;
current_symbol = cl;
instance_finalize_fragment = new CCodeFragment ();
generate_class_declaration (cl, source_declarations);
......@@ -969,13 +969,13 @@ public class Vala.DovaObjectModule : DovaArrayModule {
source_type_member_definition.append (create_set_value_from_any_function ());
}
current_symbol = old_symbol;
instance_finalize_fragment = old_instance_finalize_fragment;
pop_context ();
}
public override void visit_interface (Interface iface) {
var old_symbol = current_symbol;
current_symbol = iface;
push_context (new EmitContext (iface));
generate_interface_declaration (iface, source_declarations);
......@@ -1072,7 +1072,7 @@ public class Vala.DovaObjectModule : DovaArrayModule {
iface.accept_children (this);
current_symbol = old_symbol;
pop_context ();
}
public override void generate_property_accessor_declaration (PropertyAccessor acc, CCodeDeclarationSpace decl_space) {
......@@ -1135,8 +1135,7 @@ public class Vala.DovaObjectModule : DovaArrayModule {
}
public override void visit_property_accessor (PropertyAccessor acc) {
var old_symbol = current_symbol;
current_symbol = acc;
push_context (new EmitContext (acc));
var prop = (Property) acc.prop;
......@@ -1261,7 +1260,7 @@ public class Vala.DovaObjectModule : DovaArrayModule {
source_type_member_definition.append (function);
}
current_symbol = old_symbol;
pop_context ();
}
public override void generate_interface_declaration (Interface iface, CCodeDeclarationSpace decl_space) {
......@@ -1372,19 +1371,7 @@ public class Vala.DovaObjectModule : DovaArrayModule {
}
public override void visit_method (Method m) {
var old_symbol = current_symbol;
int old_next_temp_var_id = next_temp_var_id;
var old_temp_vars = temp_vars;
var old_temp_ref_vars = temp_ref_vars;
var old_variable_name_map = variable_name_map;
var old_try = current_try;
current_symbol = m;
next_temp_var_id = 0;
temp_vars = new ArrayList<LocalVariable> ();
temp_ref_vars = new ArrayList<LocalVariable> ();
variable_name_map = new HashMap<string,string> (str_hash, str_equal);
current_try = null;
push_context (new EmitContext (m));
foreach (FormalParameter param in m.get_parameters ()) {
param.accept (this);
......@@ -1407,12 +1394,7 @@ public class Vala.DovaObjectModule : DovaArrayModule {
}
current_symbol = old_symbol;
next_temp_var_id = old_next_temp_var_id;
temp_vars = old_temp_vars;
temp_ref_vars = old_temp_ref_vars;
variable_name_map = old_variable_name_map;
current_try = old_try;
pop_context ();
generate_method_declaration (m, source_declarations);
......
......@@ -70,9 +70,9 @@ public class Vala.DovaStructModule : DovaBaseModule {
}
public override void visit_struct (Struct st) {
var old_symbol = current_symbol;
push_context (new EmitContext (st));
var old_instance_finalize_fragment = instance_finalize_fragment;
current_symbol = st;
instance_finalize_fragment = new CCodeFragment ();
generate_struct_declaration (st, source_declarations);
......@@ -83,8 +83,9 @@ public class Vala.DovaStructModule : DovaBaseModule {
st.accept_children (this);
current_symbol = old_symbol;
instance_finalize_fragment = old_instance_finalize_fragment;
pop_context ();
}
}
......@@ -92,8 +92,7 @@ public class Vala.GAsyncModule : GSignalModule {
datadecl.add_declarator (new CCodeVariableDeclarator ("data", new CCodeIdentifier ("_data")));
freeblock.add_statement (datadecl);
var old_symbol = current_symbol;
current_symbol = m;
push_context (new EmitContext (m));
foreach (FormalParameter param in m.get_parameters ()) {
if (param.direction != ParameterDirection.OUT) {
......@@ -129,7 +128,7 @@ public class Vala.GAsyncModule : GSignalModule {
}
}
current_symbol = old_symbol;
pop_context ();
var freecall = new CCodeFunctionCall (new CCodeIdentifier ("g_slice_free"));
freecall.add_argument (new CCodeIdentifier (dataname));
......
......@@ -492,7 +492,8 @@ public class Vala.GTypeModule : GErrorModule {
}
public override void visit_class (Class cl) {
var old_symbol = current_symbol;
push_context (new EmitContext (cl));
var old_param_spec_struct = param_spec_struct;
var old_prop_enum = prop_enum;
var old_class_init_fragment = class_init_fragment;
......@@ -501,7 +502,6 @@ public class Vala.GTypeModule : GErrorModule {
var old_base_finalize_fragment = base_finalize_fragment;
var old_instance_init_fragment = instance_init_fragment;
var old_instance_finalize_fragment = instance_finalize_fragment;
current_symbol = cl;
bool is_gtypeinstance = !cl.is_compact;
bool is_fundamental = is_gtypeinstance && cl.base_class == null;
......@@ -679,7 +679,6 @@ public class Vala.GTypeModule : GErrorModule {
}
}
current_symbol = old_symbol;
param_spec_struct = old_param_spec_struct;
prop_enum = old_prop_enum;
class_init_fragment = old_class_init_fragment;
......@@ -688,6 +687,8 @@ public class Vala.GTypeModule : GErrorModule {
base_finalize_fragment = old_base_finalize_fragment;
instance_init_fragment = old_instance_init_fragment;
instance_finalize_fragment = old_instance_finalize_fragment;
pop_context ();
}
private void add_type_value_table_init_function (Class cl) {
......@@ -1914,8 +1915,7 @@ public class Vala.GTypeModule : GErrorModule {
}
public override void visit_interface (Interface iface) {
var old_symbol = current_symbol;
current_symbol = iface;
push_context (new EmitContext (iface));
if (iface.get_cname().len () < 3) {
iface.error = true;
......@@ -1944,7 +1944,7 @@ public class Vala.GTypeModule : GErrorModule {
source_declarations.add_type_member_declaration (type_fun.get_source_declaration ());
source_type_member_definition.append (type_fun.get_definition ());
current_symbol = old_symbol;
pop_context ();
}
public virtual TypeRegisterFunction create_interface_register_function (Interface iface) {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment