public override void visit_property(Property prop) { base.visit_property(prop); if (is_gobject_property(prop) && prop.parent_symbol is Class) { prop_enum.add_value(new CCodeEnumValue(get_ccode_upper_case_name(prop))); if (prop.initializer != null && prop.set_accessor != null && !prop.set_accessor.automatic_body) { // generate a custom initializer if it couldn't be done at class_init time bool has_spec_initializer = prop.property_type.data_type is ValaEnum; if (!has_spec_initializer && prop.property_type.data_type is Struct) { var param_spec_func = get_ccode_param_spec_function(prop.property_type.data_type); has_spec_initializer = param_spec_func != "g_param_spec_boxed"; } if (!has_spec_initializer) { push_context(instance_init_context); prop.initializer.emit(this); var inst_ma = MemberAccess.simple("this"); inst_ma.target_value = new GLibValue(get_data_type_for_symbol((Class)prop.parent_symbol), new CCodeIdentifier("self"), true); store_property(prop, inst_ma, prop.initializer.target_value); temp_ref_values.Clear(); pop_context(); } } } }
public override bool check(CodeContext context) { // convert to simple loop var block = new Block(source_reference); // initializer foreach (var init_expr in initializer) { block.add_statement(new ExpressionStatement(init_expr, init_expr.source_reference)); } // do not generate if block if condition is always true if (condition == null || always_true(condition)) { } else if (always_false(condition)) { // do not generate if block if condition is always false body.insert_statement(0, new BreakStatement(condition.source_reference)); } else { // condition var if_condition = new UnaryExpression(UnaryOperator.LOGICAL_NEGATION, condition, condition.source_reference); var true_block = new Block(condition.source_reference); true_block.add_statement(new BreakStatement(condition.source_reference)); var if_stmt = new IfStatement(if_condition, true_block, null, condition.source_reference); body.insert_statement(0, if_stmt); } // iterator var first_local = new LocalVariable(context.analyzer.bool_type.copy(), get_temp_name(), new BooleanLiteral(true, source_reference), source_reference); block.add_statement(new DeclarationStatement(first_local, source_reference)); var iterator_block = new Block(source_reference); foreach (var it_expr in iterator) { iterator_block.add_statement(new ExpressionStatement(it_expr, it_expr.source_reference)); } var first_if = new IfStatement(new UnaryExpression(UnaryOperator.LOGICAL_NEGATION, MemberAccess.simple(first_local.name, source_reference), source_reference), iterator_block, null, source_reference); body.insert_statement(0, first_if); body.insert_statement(1, new ExpressionStatement(new Assignment(MemberAccess.simple(first_local.name, source_reference), new BooleanLiteral(false, source_reference), AssignmentOperator.SIMPLE, source_reference), source_reference)); block.add_statement(new Loop(body, source_reference)); var parent_block = (Block)parent_node; parent_block.replace_statement(this, block); return(block.check(context)); }
void visit_subroutine(Subroutine m) { if (m.body == null) { return; } m.entry_block = BasicBlock.entry(); m.return_block = new BasicBlock(); m.exit_block = BasicBlock.exit(); m.return_block.connect(m.exit_block); if (m is Method) { // ensure out parameters are defined at end of method foreach (var param in ((Method)m).get_parameters()) { if (param.direction == ParameterDirection.OUT) { var param_ma = MemberAccess.simple(param.name, param.source_reference); param_ma.symbol_reference = param; m.return_block.add_node(param_ma); } } } current_block = new BasicBlock(); m.entry_block.connect(current_block); current_block.add_node(m); jump_stack.Add(JumpTarget.return_target(m.return_block)); jump_stack.Add(JumpTarget.exit_target(m.exit_block)); m.accept_children(this); jump_stack.RemoveAt(jump_stack.Count - 1); if (current_block != null) { // end of method body reachable if (m.has_result) { Report.error(m.source_reference, "missing return statement at end of subroutine body"); m.error = true; } current_block.connect(m.return_block); } analyze_body(m.entry_block); }
public override bool check(CodeContext context) { // convert to simple loop // do not generate variable and if block if condition is always true if (always_true(condition)) { var loop = new Loop(body, source_reference); var _parent_block = parent_node as Block; _parent_block.replace_statement(this, loop); return(loop.check(context)); } var block = new Block(source_reference); var first_local = new LocalVariable(context.analyzer.bool_type.copy(), get_temp_name(), new BooleanLiteral(true, source_reference), source_reference); block.add_statement(new DeclarationStatement(first_local, source_reference)); var if_condition = new UnaryExpression(UnaryOperator.LOGICAL_NEGATION, condition, condition.source_reference); var true_block = new Block(condition.source_reference); true_block.add_statement(new BreakStatement(condition.source_reference)); var if_stmt = new IfStatement(if_condition, true_block, null, condition.source_reference); var condition_block = new Block(condition.source_reference); condition_block.add_statement(if_stmt); var first_if = new IfStatement(new UnaryExpression(UnaryOperator.LOGICAL_NEGATION, MemberAccess.simple(first_local.name, source_reference), source_reference), condition_block, null, source_reference); body.insert_statement(0, first_if); body.insert_statement(1, new ExpressionStatement(new Assignment(MemberAccess.simple(first_local.name, source_reference), new BooleanLiteral(false, source_reference), AssignmentOperator.SIMPLE, source_reference), source_reference)); block.add_statement(new Loop(body, source_reference)); var parent_block = (Block)parent_node; parent_block.replace_statement(this, block); return(block.check(context)); }
// Create an access to a temporary variable, with proper reference transfer if needed public static Expression create_temp_access(LocalVariable local, DataType target_type) { Expression temp_access = MemberAccess.simple(local.name, local.source_reference); var target_owned = target_type != null && target_type.value_owned; if (target_owned && local.variable_type.is_disposable()) { temp_access = new ReferenceTransferExpression(temp_access, local.source_reference); temp_access.target_type = target_type != null?target_type.copy() : local.variable_type.copy(); temp_access.target_type.value_owned = true; } else { temp_access.target_type = target_type != null?target_type.copy() : null; } return(temp_access); }
bool check_with_index(CodeContext context, DataType collection_type) { var get_method = collection_type.get_member("get") as Method; if (get_method == null) { return(false); } if (get_method.get_parameters().Count != 1) { return(false); } var size_property = collection_type.get_member("size") as Property; if (size_property == null) { return(false); } add_statement(new DeclarationStatement(new LocalVariable(null, "_%s_list".printf(variable_name), collection, source_reference), source_reference)); add_statement(new DeclarationStatement(new LocalVariable(null, "_%s_size".printf(variable_name), new MemberAccess(MemberAccess.simple("_%s_list".printf(variable_name), source_reference), "size", source_reference), source_reference), source_reference)); add_statement(new DeclarationStatement(new LocalVariable(null, "_%s_index".printf(variable_name), new UnaryExpression(UnaryOperator.MINUS, new IntegerLiteral("1", source_reference), source_reference), source_reference), source_reference)); var next = new UnaryExpression(UnaryOperator.INCREMENT, MemberAccess.simple("_%s_index".printf(variable_name), source_reference), source_reference); var conditional = new BinaryExpression(BinaryOperator.LESS_THAN, next, MemberAccess.simple("_%s_size".printf(variable_name), source_reference), source_reference); var loop = new WhileStatement(conditional, body, source_reference); add_statement(loop); var get_call = new MethodCall(new MemberAccess(MemberAccess.simple("_%s_list".printf(variable_name), source_reference), "get", source_reference), source_reference); get_call.add_argument(MemberAccess.simple("_%s_index".printf(variable_name), source_reference)); body.insert_statement(0, new DeclarationStatement(new LocalVariable(type_reference, variable_name, get_call, source_reference), source_reference)); is_checked = false; return(base.check(context)); }
public override bool check(CodeContext context) { if (is_checked) { return(!error); } is_checked = true; return_type.check(context); foreach (Parameter param in parameters) { if (param.ellipsis) { Report.error(param.source_reference, "Signals with variable argument lists are not supported"); return(false); } param.check(context); } if (!is_virtual && body != null) { Report.error(source_reference, "Only virtual signals can have a default signal handler body"); } if (is_virtual) { default_handler = new Method(name, return_type, source_reference); default_handler.owner = owner; default_handler.access = access; default_handler.external = external; default_handler.hides = hides; default_handler.is_virtual = true; default_handler.signal_reference = this; default_handler.body = body; foreach (Parameter param in parameters) { default_handler.add_parameter(param); } var cl = parent_symbol as ObjectTypeSymbol; cl.add_hidden_method(default_handler); default_handler.check(context); } if (!external_package && get_attribute("HasEmitter") != null) { emitter = new Method(name, return_type, source_reference); emitter.owner = owner; emitter.access = access; var body = new Block(source_reference); var call = new MethodCall(MemberAccess.simple(name, source_reference), source_reference); foreach (Parameter param in parameters) { emitter.add_parameter(param); call.add_argument(MemberAccess.simple(param.name, source_reference)); } if (return_type is VoidType) { body.add_statement(new ExpressionStatement(call, source_reference)); } else { body.add_statement(new ReturnStatement(call, source_reference)); } emitter.body = body; var cl = parent_symbol as ObjectTypeSymbol; cl.add_hidden_method(emitter); emitter.check(context); } if (!external_package && !hides && get_hidden_member() != null) { Report.warning(source_reference, "%s hides inherited signal `%s'. Use the `new' keyword if hiding was intentional".printf(get_full_name(), get_hidden_member().get_full_name())); } return(!error); }
bool check_with_iterator(CodeContext context, DataType collection_type) { use_iterator = true; if (check_with_index(context, collection_type)) { return(true); } var iterator_method = collection_type.get_member("iterator") as Method; if (iterator_method == null) { Report.error(collection.source_reference, "`%s' does not have an `iterator' method".printf(collection_type.ToString())); error = true; return(false); } if (iterator_method.get_parameters().Count != 0) { Report.error(collection.source_reference, "`%s' must not have any parameters".printf(iterator_method.get_full_name())); error = true; return(false); } var iterator_type = iterator_method.return_type.get_actual_type(collection_type, null, this); if (iterator_type is VoidType) { Report.error(collection.source_reference, "`%s' must return an iterator".printf(iterator_method.get_full_name())); error = true; return(false); } var iterator_call = new MethodCall(new MemberAccess(collection, "iterator", source_reference), source_reference); add_statement(new DeclarationStatement(new LocalVariable(iterator_type, "_%s_it".printf(variable_name), iterator_call, source_reference), source_reference)); var next_value_method = iterator_type.get_member("next_value") as Method; var next_method = iterator_type.get_member("next") as Method; if (next_value_method != null) { if (next_value_method.get_parameters().Count != 0) { Report.error(collection.source_reference, "`%s' must not have any parameters".printf(next_value_method.get_full_name())); error = true; return(false); } var element_type = next_value_method.return_type.get_actual_type(iterator_type, null, this); if (!element_type.nullable) { Report.error(collection.source_reference, "return type of `%s' must be nullable".printf(next_value_method.get_full_name())); error = true; return(false); } if (!analyze_element_type(element_type)) { return(false); } add_statement(new DeclarationStatement(new LocalVariable(type_reference, variable_name, null, source_reference), source_reference)); var next_value_call = new MethodCall(new MemberAccess(MemberAccess.simple("_%s_it".printf(variable_name), source_reference), "next_value", source_reference), source_reference); var assignment = new Assignment(new MemberAccess(null, variable_name, source_reference), next_value_call, AssignmentOperator.SIMPLE, source_reference); var conditional = new BinaryExpression(BinaryOperator.INEQUALITY, assignment, new NullLiteral(source_reference), source_reference); var loop = new WhileStatement(conditional, body, source_reference); add_statement(loop); } else if (next_method != null) { if (next_method.get_parameters().Count != 0) { Report.error(collection.source_reference, "`%s' must not have any parameters".printf(next_method.get_full_name())); error = true; return(false); } if (!next_method.return_type.compatible(context.analyzer.bool_type)) { Report.error(collection.source_reference, "`%s' must return a boolean value".printf(next_method.get_full_name())); error = true; return(false); } var get_method = iterator_type.get_member("get") as Method; if (get_method == null) { Report.error(collection.source_reference, "`%s' does not have a `get' method".printf(iterator_type.ToString())); error = true; return(false); } if (get_method.get_parameters().Count != 0) { Report.error(collection.source_reference, "`%s' must not have any parameters".printf(get_method.get_full_name())); error = true; return(false); } var element_type = get_method.return_type.get_actual_type(iterator_type, null, this); if (element_type is VoidType) { Report.error(collection.source_reference, "`%s' must return an element".printf(get_method.get_full_name())); error = true; return(false); } if (!analyze_element_type(element_type)) { return(false); } var next_call = new MethodCall(new MemberAccess(MemberAccess.simple("_%s_it".printf(variable_name), source_reference), "next", source_reference), source_reference); var loop = new WhileStatement(next_call, body, source_reference); add_statement(loop); var get_call = new MethodCall(new MemberAccess(MemberAccess.simple("_%s_it".printf(variable_name), source_reference), "get", source_reference), source_reference); body.insert_statement(0, new DeclarationStatement(new LocalVariable(type_reference, variable_name, get_call, source_reference), source_reference)); } else { Report.error(collection.source_reference, "`%s' does not have a `next_value' or `next' method".printf(iterator_type.ToString())); error = true; return(false); } is_checked = false; return(base.check(context)); }
public override bool check(CodeContext context) { if (is_checked) { return(!error); } is_checked = true; if (class_name != null && class_name != parent_symbol.name) { // class_name is null for constructors generated by GIdlParser Report.error(source_reference, "missing return type in method `%s.%s´".printf(context.analyzer.current_symbol.get_full_name(), class_name)); error = true; return(false); } var old_source_file = context.analyzer.current_source_file; var old_symbol = context.analyzer.current_symbol; if (source_reference != null) { context.analyzer.current_source_file = source_reference.file; } context.analyzer.current_symbol = this; foreach (Parameter param in get_parameters()) { param.check(context); } foreach (DataType error_type in get_error_types()) { error_type.check(context); } foreach (Expression precondition in get_preconditions()) { precondition.check(context); } foreach (Expression postcondition in get_postconditions()) { postcondition.check(context); } if (body != null) { body.check(context); var cl = parent_symbol as Class; // ensure we chain up to base constructor if (!chain_up && cl != null && cl.base_class != null) { if (cl.base_class.default_construction_method != null && !cl.base_class.default_construction_method.has_construct_function) { // directly chain up to Object var old_insert_block = context.analyzer.insert_block; context.analyzer.current_symbol = body; context.analyzer.insert_block = body; var stmt = new ExpressionStatement(new MethodCall(new MemberAccess(MemberAccess.simple("GLib", source_reference), "Object", source_reference), source_reference), source_reference); body.insert_statement(0, stmt); stmt.check(context); context.analyzer.current_symbol = this; context.analyzer.insert_block = old_insert_block; } else if (cl.base_class.default_construction_method == null || cl.base_class.default_construction_method.access == SymbolAccessibility.PRIVATE) { Report.error(source_reference, "unable to chain up to private base constructor"); } else if (cl.base_class.default_construction_method.get_required_arguments() > 0) { Report.error(source_reference, "unable to chain up to base constructor requiring arguments"); } else { var old_insert_block = context.analyzer.insert_block; context.analyzer.current_symbol = body; context.analyzer.insert_block = body; var stmt = new ExpressionStatement(new MethodCall(new BaseAccess(source_reference), source_reference), source_reference); body.insert_statement(0, stmt); stmt.check(context); context.analyzer.current_symbol = this; context.analyzer.insert_block = old_insert_block; } } } context.analyzer.current_source_file = old_source_file; context.analyzer.current_symbol = old_symbol; if (is_abstract || is_virtual || overrides) { Report.error(source_reference, "The creation method `%s' cannot be marked as override, virtual, or abstract".printf(get_full_name())); return(false); } // check that all errors that can be thrown in the method body are declared if (body != null) { foreach (DataType body_error_type in body.get_error_types()) { bool can_propagate_error = false; foreach (DataType method_error_type in get_error_types()) { if (body_error_type.compatible(method_error_type)) { can_propagate_error = true; } } if (!can_propagate_error && !((ErrorType)body_error_type).dynamic_error) { Report.warning(body_error_type.source_reference, "unhandled error `%s'".printf(body_error_type.ToString())); } } } return(!error); }
public override bool check(CodeContext context) { if (is_checked) { return(!error); } is_checked = true; if (!value_type.check(context)) { error = true; return(false); } var old_symbol = context.analyzer.current_symbol; context.analyzer.current_symbol = this; if (writable || construction) { value_parameter = new Parameter("value", value_type, source_reference); } if (prop.source_type == SourceFileType.SOURCE) { if (body == null && !prop.interface_only && !prop.is_abstract) { /* no accessor body specified, insert default body */ automatic_body = true; body = new Block(source_reference); var ma = MemberAccess.simple("_%s".printf(prop.name), source_reference); if (readable) { body.add_statement(new ReturnStatement(ma, source_reference)); } else { Expression value = MemberAccess.simple("value", source_reference); if (value_type.value_owned) { value = new ReferenceTransferExpression(value, source_reference); } var assignment = new Assignment(ma, value, AssignmentOperator.SIMPLE, source_reference); body.add_statement(new ExpressionStatement(assignment)); } } } if ((prop.is_abstract || prop.is_virtual || prop.overrides) && access == SymbolAccessibility.PRIVATE) { error = true; Report.error(source_reference, "Property `%s' with private accessor cannot be marked as abstract, virtual or override".printf(prop.get_full_name())); return(false); } if (body != null) { if (writable || construction) { body.scope.add(value_parameter.name, value_parameter); } body.check(context); foreach (DataType body_error_type in body.get_error_types()) { if (!((ErrorType)body_error_type).dynamic_error) { Report.warning(body_error_type.source_reference, "unhandled error `%s'".printf(body_error_type.ToString())); } } } context.analyzer.current_symbol = old_symbol; return(!error); }