+2006-06-14 Jürg Billeter <j@bitron.ch>
+
+ * vala/parser.y: set is_lvalue_ref in property declarations
+ * vala/valacodecontext.vala: use non-null parameter types
+ * vala/valasymbolresolver.vala: fix lookup in namespaces of using
+ directives, reset is_lvalue_ref where appropriate
+ * vala/valasemanticanalyzer.vala: use non-null parameter types,
+ correctly set is_ref and is_lvalue_ref in variable declarators
+ * vala/valamemorymanager.vala: support methods which transfer ownership
+ of arguments and or return value, analyze assignments
+ * vala/valacodegenerator.vala: add missing reference increment calls,
+ small memory management improvements
+ * vala/valaclass.vala: use non-null parameter types
+ * vala/valaexpression.vala: add ref_missing
+ * vala/valastruct.vala: support ref_function attribute, use non-null
+ parameter types
+ * vala/valatype.vala: let get_upper_case_cname return ref string
+ * vala/valatypereference.vala: add copy method
+ * ccode/valaccodeconditionalexpression.vala
+ * ccode/valaccodefunctioncall.vala: use non-null parameter types
+ * ccode/Makefile.am: update
+ * compiler/valacompiler.vala: process attributes before resolving
+ symbols to have reference_type information available in resolver
+ * vapi/glib-2.0.vala: add ref_function attributes to string and List,
+ use ref parameters in List and HashTable until the compiler can handle
+ it correctly
+
2006-06-14 Jürg Billeter <j@bitron.ch>
* vala/parser.y: set is_lvalue_ref for variables and fields
valaccodecomment.c \
valaccodecomment.h \
valaccodecomment.vala \
+ valaccodeconditionalexpression.c \
+ valaccodeconditionalexpression.h \
+ valaccodeconditionalexpression.vala \
valaccodeconstant.c \
valaccodeconstant.h \
valaccodeconstant.vala \
--- /dev/null
+/* valaccodeconditionalexpression.vala
+ *
+ * Copyright (C) 2006 Jürg Billeter
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * Author:
+ * Jürg Billeter <j@bitron.ch>
+ */
+
+using GLib;
+
+namespace Vala {
+ public class CCodeConditionalExpression : CCodeExpression {
+ public CCodeExpression condition { get; construct; }
+ public CCodeExpression true_expression { get; construct; }
+ public CCodeExpression false_expression { get; construct; }
+
+ public override void write (CCodeWriter writer) {
+ writer.write_string ("(");
+ condition.write (writer);
+ writer.write_string (" ? ");
+ true_expression.write (writer);
+ writer.write_string (" : ");
+ false_expression.write (writer);
+ writer.write_string (")");
+ }
+ }
+}
public CCodeExpression call { get; construct; }
List<CCodeExpression> arguments;
- public void add_argument (CCodeExpression expr) {
+ public void add_argument (CCodeExpression! expr) {
arguments.append (expr);
}
- public override void write (CCodeWriter writer) {
+ public override void write (CCodeWriter! writer) {
call.write (writer);
writer.write_string (" (");
}
}
- private ref string get_package_path (string pkg) {
+ private ref string get_package_path (string! pkg) {
var basename = "%s.vala".printf (pkg);
if (vapi_directories != null) {
return null;
}
- private bool add_package (string pkg) {
+ private bool add_package (string! pkg) {
var package_path = get_package_path (pkg);
if (package_path == null) {
return quit ();
}
- var resolver = new SymbolResolver ();
- resolver.resolve (context);
+ var attributeprocessor = new AttributeProcessor ();
+ attributeprocessor.process (context);
if (Report.get_errors () > 0) {
return quit ();
}
- var attributeprocessor = new AttributeProcessor ();
- attributeprocessor.process (context);
+ var resolver = new SymbolResolver ();
+ resolver.resolve (context);
if (Report.get_errors () > 0) {
return quit ();
property_declaration
: comment opt_attributes opt_access_modifier opt_modifiers type IDENTIFIER OPEN_BRACE get_accessor_declaration opt_set_accessor_declaration CLOSE_BRACE
{
+ if (!vala_type_reference_get_is_weak ($5)) {
+ vala_type_reference_set_is_lvalue_ref ($5, TRUE);
+ }
+
$$ = vala_property_new ($6, $5, $8, $9, src_com (@5, $1));
}
| comment opt_attributes opt_access_modifier opt_modifiers type IDENTIFIER OPEN_BRACE set_accessor_declaration CLOSE_BRACE
{
+ if (!vala_type_reference_get_is_weak ($5)) {
+ vala_type_reference_set_is_lvalue_ref ($5, TRUE);
+ }
+
$$ = vala_property_new ($6, $5, NULL, $8, src_com (@5, $1));
}
;
public string lower_case_csuffix;
public bool has_private_fields;
- public static ref Class new (string name, SourceReference source) {
+ public static ref Class new (string! name, SourceReference source) {
return (new Class (name = name, source_reference = source));
}
- public void add_base_type (TypeReference type) {
+ public void add_base_type (TypeReference! type) {
base_types.append (type);
}
- public void add_type_parameter (TypeParameter p) {
+ public void add_type_parameter (TypeParameter! p) {
type_parameters.append (p);
p.type = this;
}
- public void add_constant (Constant c) {
+ public void add_constant (Constant! c) {
constants.append (c);
}
- public void add_field (Field f) {
+ public void add_field (Field! f) {
fields.append (f);
if (f.access == MemberAccessibility.PRIVATE) {
has_private_fields = true;
return fields.copy ();
}
- public void add_method (Method m) {
- return_if_fail (m != null);
-
+ public void add_method (Method! m) {
methods.append (m);
}
return methods.copy ();
}
- public void add_property (Property prop) {
+ public void add_property (Property! prop) {
properties.append (prop);
if (prop.set_accessor != null && prop.set_accessor.body == null) {
return properties.copy ();
}
- public void add_signal (Signal sig) {
+ public void add_signal (Signal! sig) {
signals.append (sig);
}
return signals.copy ();
}
- public override void accept (CodeVisitor visitor) {
+ public override void accept (CodeVisitor! visitor) {
visitor.visit_begin_class (this);
foreach (TypeReference type in base_types) {
return cname;
}
- public void set_cname (string cname) {
+ public void set_cname (string! cname) {
this.cname = cname;
}
return lower_case_csuffix;
}
- public void set_lower_case_csuffix (string csuffix) {
+ public void set_lower_case_csuffix (string! csuffix) {
this.lower_case_csuffix = csuffix;
}
return "%s%s%s".printf (@namespace.get_lower_case_cprefix (), infix, get_lower_case_csuffix ());
}
- public override ref string get_upper_case_cname (string infix) {
+ public override ref string get_upper_case_cname (string! infix) {
return get_lower_case_cname (infix).up ();
}
return true;
}
- void process_ccode_attribute (Attribute a) {
+ void process_ccode_attribute (Attribute! a) {
foreach (NamedArgument arg in a.args) {
if (arg.name == "cname") {
/* this will already be checked during semantic analysis */
return source_files.copy ();
}
- public void add_source_file (SourceFile file) {
+ public void add_source_file (SourceFile! file) {
source_files.append (file);
}
- public void accept (CodeVisitor visitor) {
+ public void accept (CodeVisitor! visitor) {
foreach (SourceFile file in source_files) {
file.accept (visitor);
}
}
- private SourceFile find_cycle_head (SourceFile file) {
+ private SourceFile find_cycle_head (SourceFile! file) {
foreach (SourceFile dep in file.header_internal_full_dependencies) {
foreach (SourceFile cycle_file in file.cycle.files) {
if (dep == cycle_file) {
return file;
}
- private void visit (SourceFile file, List<SourceFile> chain) {
+ private void visit (SourceFile! file, List<SourceFile> chain) {
var l = chain.copy ();
l.append (file);
CCodeFunction function;
CCodeBlock block;
+ /* all temporary variables */
List<VariableDeclarator> temp_vars;
+ /* temporary variables that own their content */
+ List<VariableDeclarator> temp_ref_vars;
private int next_temp_var_id = 0;
public override void visit_end_full_expression (Expression! expr) {
if (!memory_management) {
temp_vars = null;
+ temp_ref_vars = null;
return;
}
* expression
*/
- if (temp_vars == null) {
+ expr.temp_vars = temp_vars;
+ temp_vars = null;
+
+ if (temp_ref_vars == null) {
/* nothing to do without temporary variables */
return;
}
var full_expr_decl = get_temp_variable_declarator (expr.static_type);
+ expr.temp_vars.append (full_expr_decl);
var expr_list = new CCodeCommaExpression ();
expr_list.inner.append (new CCodeAssignment (left = new CCodeIdentifier (name = full_expr_decl.name), right = expr.ccodenode));
- foreach (VariableDeclarator decl in temp_vars) {
+ foreach (VariableDeclarator decl in temp_ref_vars) {
expr_list.inner.append (get_unref_expression (decl.name, decl.type_reference));
}
expr.ccodenode = expr_list;
- temp_vars.append (full_expr_decl);
-
- expr.temp_vars = temp_vars;
- temp_vars = null;
+ temp_ref_vars = null;
}
private void append_temp_decl (CCodeFragment! cfrag, List<VariableDeclarator> temp_vars) {
/* free temporary objects */
if (!memory_management) {
temp_vars = null;
+ temp_ref_vars = null;
return;
}
cfrag.append (stmt.ccodenode);
- foreach (VariableDeclarator decl in temp_vars) {
+ foreach (VariableDeclarator decl in temp_ref_vars) {
cfrag.append (new CCodeExpressionStatement (expression = get_unref_expression (decl.name, decl.type_reference)));
}
stmt.ccodenode = cfrag;
temp_vars = null;
+ temp_ref_vars = null;
}
private void create_temp_decl (Statement! stmt, List<VariableDeclarator> temp_vars) {
var base_type = (Type_) current_symbol.node;
process_cmember (expr, pub_inst, base_type);
+
+ visit_expression (expr);
}
public override void visit_parenthesized_expression (ParenthesizedExpression! expr) {
expr.ccodenode = new CCodeParenthesizedExpression (inner = (CCodeExpression) expr.inner.ccodenode);
+
+ visit_expression (expr);
}
public override void visit_member_access (MemberAccess! expr) {
}
process_cmember (expr, pub_inst, base_type);
+
+ visit_expression (expr);
}
public override void visit_invocation_expression (InvocationExpression! expr) {
}
}
+ private ref CCodeExpression get_ref_expression (Expression! expr) {
+ /* (temp = expr, temp == NULL ? temp : ref (temp)) */
+
+ var decl = get_temp_variable_declarator (expr.static_type);
+ temp_vars.prepend (decl);
+
+ var ctemp = new CCodeIdentifier (name = decl.name);
+
+ var cisnull = new CCodeBinaryExpression (operator = CCodeBinaryOperator.EQUALITY, left = ctemp, right = new CCodeConstant (name = "NULL"));
+
+ var ccall = new CCodeFunctionCall (call = new CCodeIdentifier (name = expr.static_type.type.get_ref_function ()));
+ ccall.add_argument (ctemp);
+
+ var ccomma = new CCodeCommaExpression ();
+ ccomma.inner.append (new CCodeAssignment (left = ctemp, right = expr.ccodenode));
+ ccomma.inner.append (new CCodeConditionalExpression (condition = cisnull, true_expression = ctemp, false_expression = ccall));
+
+ return ccomma;
+ }
+
private void visit_expression (Expression! expr) {
if (expr.ref_leaked) {
var decl = get_temp_variable_declarator (expr.static_type);
temp_vars.prepend (decl);
+ temp_ref_vars.prepend (decl);
expr.ccodenode = new CCodeAssignment (left = new CCodeIdentifier (name = decl.name), right = expr.ccodenode);
+ } else if (expr.ref_missing) {
+ expr.ccodenode = get_ref_expression (expr);
}
}
/* set by memory manager, used by code generator */
public bool ref_leaked;
+ public bool ref_missing;
/* set and used by code generator */
public List<VariableDeclarator> temp_vars;
namespace Vala {
public class MemoryManager : CodeVisitor {
+ Symbol current_symbol;
+
public void analyze (CodeContext! context) {
context.accept (this);
}
}
}
+ private void visit_possibly_missing_copy_expression (Expression! expr) {
+ if (expr.static_type != null &&
+ !expr.static_type.is_ref) {
+ /* mark reference as missing */
+ expr.ref_missing = true;
+ }
+ }
+
+ public override void visit_begin_method (Method! m) {
+ current_symbol = m.symbol;
+ }
+
public override void visit_expression_statement (ExpressionStatement! stmt) {
visit_possibly_leaked_expression (stmt.expression);
}
public override void visit_return_statement (ReturnStatement! stmt) {
if (stmt.return_expression != null) {
- visit_possibly_leaked_expression (stmt.return_expression);
+ var m = (Method) current_symbol.node;
+
+ if (m.return_type.is_ref) {
+ visit_possibly_missing_copy_expression (stmt.return_expression);
+ } else {
+ visit_possibly_leaked_expression (stmt.return_expression);
+ }
}
}
}
public override void visit_invocation_expression (InvocationExpression! expr) {
+ var m = (Method) expr.call.symbol_reference.node;
+ var params = m.get_parameters ();
foreach (Expression arg in expr.argument_list) {
- visit_possibly_leaked_expression (arg);
+ if (params != null) {
+ var param = (FormalParameter) params.data;
+ if (!param.ellipsis
+ && ((param.type_reference.type != null
+ && param.type_reference.type.is_reference_type ())
+ || param.type_reference.type_parameter != null)) {
+ if (param.type_reference.is_ref) {
+ visit_possibly_missing_copy_expression (arg);
+ } else {
+ visit_possibly_leaked_expression (arg);
+ }
+ }
+
+ params = params.next;
+ } else {
+ visit_possibly_leaked_expression (arg);
+ }
}
}
visit_possibly_leaked_expression (expr.left);
visit_possibly_leaked_expression (expr.right);
}
+
+ public override void visit_assignment (Assignment! a) {
+ if (a.left.static_type.is_lvalue_ref) {
+ visit_possibly_missing_copy_expression (a.right);
+ } else {
+ visit_possibly_leaked_expression (a.right);
+ }
+ }
}
}
context.accept (this);
}
- public override void visit_begin_source_file (SourceFile file) {
+ public override void visit_begin_source_file (SourceFile! file) {
current_source_file = file;
current_using_directives = file.get_using_directives ();
}
- public override void visit_end_source_file (SourceFile file) {
+ public override void visit_end_source_file (SourceFile! file) {
current_using_directives = null;
}
- public override void visit_begin_namespace (Namespace ns) {
+ public override void visit_begin_namespace (Namespace! ns) {
current_symbol = ns.symbol;
}
- public override void visit_end_namespace (Namespace ns) {
+ public override void visit_end_namespace (Namespace! ns) {
current_symbol = current_symbol.parent_symbol;
}
- public override void visit_begin_class (Class cl) {
+ public override void visit_begin_class (Class! cl) {
current_symbol = cl.symbol;
if (cl.base_class != null) {
}
}
- public override void visit_end_class (Class cl) {
+ public override void visit_end_class (Class! cl) {
current_symbol = current_symbol.parent_symbol;
}
- public override void visit_begin_struct (Struct st) {
+ public override void visit_begin_struct (Struct! st) {
current_symbol = st.symbol;
}
- public override void visit_end_struct (Struct st) {
+ public override void visit_end_struct (Struct! st) {
current_symbol = current_symbol.parent_symbol;
}
- public override void visit_field (Field f) {
+ public override void visit_field (Field! f) {
if (f.access == MemberAccessibility.PUBLIC) {
if (f.type_reference.type != null) {
/* is null if it references a type parameter */
}
}
- public override void visit_begin_method (Method m) {
+ public override void visit_begin_method (Method! m) {
current_symbol = m.symbol;
if (m.return_type.type != null) {
}
}
- public override void visit_end_method (Method m) {
+ public override void visit_end_method (Method! m) {
current_symbol = current_symbol.parent_symbol;
if (m.is_virtual || m.is_override) {
}
}
- public override void visit_formal_parameter (FormalParameter p) {
+ public override void visit_formal_parameter (FormalParameter! p) {
if (!p.ellipsis) {
if (p.type_reference.type != null) {
/* is null if it references a type parameter */
}
}
- public override void visit_end_property (Property prop) {
+ public override void visit_end_property (Property! prop) {
if (prop.type_reference.type != null) {
/* is null if it references a type parameter */
current_source_file.add_symbol_dependency (prop.type_reference.type.symbol, SourceFileDependencyType.HEADER_SHALLOW);
}
}
- public override void visit_begin_constructor (Constructor c) {
+ public override void visit_begin_constructor (Constructor! c) {
current_symbol = c.symbol;
}
- public override void visit_end_constructor (Constructor c) {
+ public override void visit_end_constructor (Constructor! c) {
current_symbol = current_symbol.parent_symbol;
}
- public override void visit_begin_destructor (Destructor d) {
+ public override void visit_begin_destructor (Destructor! d) {
current_symbol = d.symbol;
}
- public override void visit_end_destructor (Destructor d) {
+ public override void visit_end_destructor (Destructor! d) {
current_symbol = current_symbol.parent_symbol;
}
- public override void visit_named_argument (NamedArgument n) {
+ public override void visit_named_argument (NamedArgument! n) {
}
- public override void visit_begin_block (Block b) {
+ public override void visit_begin_block (Block! b) {
current_symbol = b.symbol;
}
- public override void visit_end_block (Block b) {
+ public override void visit_end_block (Block! b) {
current_symbol = current_symbol.parent_symbol;
}
- public override void visit_variable_declarator (VariableDeclarator decl) {
+ public override void visit_variable_declarator (VariableDeclarator! decl) {
if (decl.type_reference == null) {
/* var type */
- decl.type_reference = decl.initializer.static_type;
+ decl.type_reference = decl.initializer.static_type.copy ();
+ decl.type_reference.is_lvalue_ref = decl.type_reference.is_ref;
+ decl.type_reference.is_ref = false;
}
if (decl.type_reference.type != null) {
current_symbol.add (decl.name, decl.symbol);
}
- public override void visit_expression_statement (ExpressionStatement stmt) {
+ public override void visit_expression_statement (ExpressionStatement! stmt) {
if (stmt.expression.static_type != null &&
stmt.expression.static_type.is_ref) {
Report.warning (stmt.source_reference, "Short-living reference");
}
}
- public override void visit_begin_foreach_statement (ForeachStatement stmt) {
+ public override void visit_begin_foreach_statement (ForeachStatement! stmt) {
if (stmt.type_reference.type != null) {
current_source_file.add_symbol_dependency (stmt.type_reference.type.symbol, SourceFileDependencyType.SOURCE);
}
current_symbol.add (stmt.variable_name, stmt.symbol);
}
- public override void visit_boolean_literal (BooleanLiteral expr) {
+ public override void visit_boolean_literal (BooleanLiteral! expr) {
expr.static_type = bool_type;
}
- public override void visit_character_literal (CharacterLiteral expr) {
+ public override void visit_character_literal (CharacterLiteral! expr) {
expr.static_type = new TypeReference ();
expr.static_type.type = (Type_) root_symbol.lookup ("char").node;
}
- public override void visit_integer_literal (IntegerLiteral expr) {
+ public override void visit_integer_literal (IntegerLiteral! expr) {
expr.static_type = new TypeReference ();
expr.static_type.type = (Type_) root_symbol.lookup ("int").node;
}
- public override void visit_real_literal (IntegerLiteral expr) {
+ public override void visit_real_literal (IntegerLiteral! expr) {
expr.static_type = new TypeReference ();
expr.static_type.type = (Type_) root_symbol.lookup ("double").node;
}
- public override void visit_string_literal (StringLiteral expr) {
+ public override void visit_string_literal (StringLiteral! expr) {
expr.static_type = string_type;
}
- public override void visit_null_literal (NullLiteral expr) {
+ public override void visit_null_literal (NullLiteral! expr) {
/* empty TypeReference represents null */
expr.static_type = new TypeReference ();
}
- public override void visit_literal_expression (LiteralExpression expr) {
+ public override void visit_literal_expression (LiteralExpression! expr) {
expr.static_type = expr.literal.static_type;
}
- TypeReference get_static_type_for_node (CodeNode node) {
+ TypeReference get_static_type_for_node (CodeNode! node) {
if (node is Field) {
var f = (Field) node;
return f.type_reference;
return null;
}
- Symbol symbol_lookup_inherited (Symbol sym, string name) {
+ Symbol symbol_lookup_inherited (Symbol! sym, string! name) {
var result = sym.lookup (name);
if (result == null && sym.node is Class) {
var cl = (Class) sym.node;
return result;
}
- public override void visit_simple_name (SimpleName expr) {
+ public override void visit_simple_name (SimpleName! expr) {
var sym = current_symbol;
while (sym != null && expr.symbol_reference == null) {
expr.symbol_reference = symbol_lookup_inherited (sym, expr.name);
expr.static_type = get_static_type_for_node (expr.symbol_reference.node);
}
- public override void visit_parenthesized_expression (ParenthesizedExpression expr) {
+ public override void visit_parenthesized_expression (ParenthesizedExpression! expr) {
expr.static_type = expr.inner.static_type;
}
- public override void visit_member_access (MemberAccess expr) {
+ public override void visit_member_access (MemberAccess! expr) {
if (expr.inner.static_type == null
&& expr.inner.symbol_reference == null) {
/* if there was an error in the inner expression, skip this check */
expr.static_type = get_static_type_for_node (expr.symbol_reference.node);
}
- private bool is_type_compatible (TypeReference expression_type, TypeReference expected_type) {
+ private bool is_type_compatible (TypeReference! expression_type, TypeReference! expected_type) {
/* null can be casted to any reference or array type */
if (expression_type.type == null && (expected_type.type.is_reference_type () || expected_type.array)) {
return true;
return false;
}
- public override void visit_invocation_expression (InvocationExpression expr) {
+ public override void visit_invocation_expression (InvocationExpression! expr) {
if (expr.call.symbol_reference == null) {
/* if method resolving didn't succeed, skip this check */
return;
}
}
- public override void visit_object_creation_expression (ObjectCreationExpression expr) {
+ public override void visit_object_creation_expression (ObjectCreationExpression! expr) {
if (expr.type_reference.type == null) {
/* if type resolving didn't succeed, skip this check */
return;
expr.static_type.is_ref = true;
}
- public override void visit_unary_expression (UnaryExpression expr) {
+ public override void visit_unary_expression (UnaryExpression! expr) {
if (expr.inner.static_type == null) {
/* if there was an error in the inner expression, skip type check */
return;
}
}
- public override void visit_cast_expression (CastExpression expr) {
+ public override void visit_cast_expression (CastExpression! expr) {
if (expr.type_reference.type == null) {
/* if type resolving didn't succeed, skip this check */
return;
expr.static_type = expr.type_reference;
}
- private bool check_binary_type (BinaryExpression expr, string operation) {
+ private bool check_binary_type (BinaryExpression! expr, string! operation) {
if (!is_type_compatible (expr.right.static_type, expr.left.static_type)) {
Report.error (expr.source_reference, "%s: Cannot convert from `%s' to `%s'".printf (operation, expr.right.static_type.to_string (), expr.left.static_type.to_string ()));
return false;
return true;
}
- public override void visit_binary_expression (BinaryExpression expr) {
+ public override void visit_binary_expression (BinaryExpression! expr) {
if (expr.left.static_type == null
|| expr.right.static_type == null) {
/* if there were any errors in inner expressions, skip type check */
}
}
- public override void visit_type_check (TypeCheck expr) {
+ public override void visit_type_check (TypeCheck! expr) {
if (expr.type_reference.type == null) {
/* if type resolving didn't succeed, skip this check */
return;
expr.static_type = bool_type;
}
- public override void visit_assignment (Assignment a) {
+ public override void visit_assignment (Assignment! a) {
if (a.left.symbol_reference.node is Signal) {
var sig = (Signal) a.left.symbol_reference.node;
} else if (a.left.symbol_reference.node is Property) {
Report.error (a.source_reference, "Invalid assignment from owned expression to unowned variable");
}
- a.left.static_type.is_ref = true;
+ a.left.static_type.is_lvalue_ref = true;
}
} else if (a.left.static_type.is_lvalue_ref) {
/* lhs wants to own the value
}
}
}
+
+ a.static_type = a.left.static_type;
}
}
}
List<Method> methods;
public string cname;
+ public string ref_function;
public string lower_case_csuffix;
bool reference_type;
- public static ref Struct new (string name, SourceReference source) {
+ public static ref Struct new (string! name, SourceReference source) {
return (new Struct (name = name, source_reference = source));
}
- public void add_type_parameter (TypeParameter p) {
+ public void add_type_parameter (TypeParameter! p) {
type_parameters.append (p);
p.type = this;
}
- public void add_constant (Constant c) {
+ public void add_constant (Constant! c) {
constants.append (c);
}
- public void add_field (Field f) {
+ public void add_field (Field! f) {
fields.append (f);
}
return fields.copy ();
}
- public void add_method (Method m) {
+ public void add_method (Method! m) {
return_if_fail (m != null);
methods.append (m);
return methods.copy ();
}
- public override void accept (CodeVisitor visitor) {
+ public override void accept (CodeVisitor! visitor) {
visitor.visit_begin_struct (this);
foreach (TypeParameter p in type_parameters) {
return cname;
}
- public void set_cname (string cname) {
+ public void set_cname (string! cname) {
this.cname = cname;
}
return lower_case_csuffix;
}
- public void set_lower_case_csuffix (string csuffix) {
+ public void set_lower_case_csuffix (string! csuffix) {
this.lower_case_csuffix = csuffix;
}
return reference_type;
}
- void process_ccode_attribute (Attribute a) {
+ private void process_ccode_attribute (Attribute! a) {
foreach (NamedArgument arg in a.args) {
if (arg.name == "cname") {
/* this will already be checked during semantic analysis */
}
}
+ private void process_ref_type_attribute (Attribute! a) {
+ reference_type = true;
+ foreach (NamedArgument arg in a.args) {
+ if (arg.name == "ref_function") {
+ /* this will already be checked during semantic analysis */
+ if (arg.argument is LiteralExpression) {
+ var lit = ((LiteralExpression) arg.argument).literal;
+ if (lit is StringLiteral) {
+ set_ref_function (((StringLiteral) lit).eval ());
+ }
+ }
+ }
+ }
+ }
+
public void process_attributes () {
foreach (Attribute a in attributes) {
if (a.name == "CCode") {
process_ccode_attribute (a);
} else if (a.name == "ReferenceType") {
- reference_type = true;
+ process_ref_type_attribute (a);
}
}
}
return false;
}
+ public override string get_ref_function () {
+ if (ref_function == null) {
+ Report.warning (source_reference, "type foo is missing a copy/reference increment function");
+ ref_function = "g_strdup";
+ }
+ return ref_function;
+ }
+
+ public void set_ref_function (string! name) {
+ this.ref_function = name;
+ }
+
public override string get_free_function () {
return "g_free";
}
if (sym == null) {
foreach (NamespaceReference ns in current_using_directives) {
var local_sym = ns.namespace_symbol.lookup (type.type_name);
- if (sym != null && local_sym != null) {
- Report.error (type.source_reference, "`%s' is an ambiguous reference between `%s' and `%s'".printf (type.type_name, sym.get_full_name (), local_sym.get_full_name ()));
- return;
+ if (local_sym != null) {
+ if (sym != null) {
+ Report.error (type.source_reference, "`%s' is an ambiguous reference between `%s' and `%s'".printf (type.type_name, sym.get_full_name (), local_sym.get_full_name ()));
+ return;
+ }
+ sym = local_sym;
}
- sym = local_sym;
}
}
if (sym == null) {
}
type.type = (Type_) sym.node;
}
+
+ if (type.type != null && !type.type.is_reference_type ()) {
+ /* reset is_lvalue_ref for contexts where types
+ * are ref by default (field declarations)
+ */
+ type.is_lvalue_ref = false;
+ }
}
}
}
public abstract string get_ref_function ();
public abstract string get_free_function ();
- public abstract string get_upper_case_cname (string infix);
+ public abstract ref string get_upper_case_cname (string infix);
public abstract string get_lower_case_cname (string infix);
public List<string> cheader_filenames;
return "null";
}
}
+
+ public ref TypeReference copy () {
+ var result = new TypeReference ();
+ result.is_ref = is_ref;
+ result.is_lvalue_ref = is_lvalue_ref;
+ result.is_weak = is_weak;
+ result.is_out = is_out;
+ result.array = array;
+ result.array_own = array_own;
+ result.non_null = non_null;
+ result.type = type;
+ result.type_parameter = type_parameter;
+
+ return result;
+ }
}
}
public unichar tolower ();
}
-[ReferenceType ()]
+[ReferenceType (ref_function = "g_strdup")]
[CCode (cname = "char", cheader_filename = "string.h,glib.h")]
public struct string {
[CCode (cname = "g_str_has_suffix")]
string arg_description;
}
- [ReferenceType ()]
+ [ReferenceType (ref_function = "g_list_copy")]
public struct List<G> {
[ReturnsModifiedPointer ()]
- public void append (G data);
+ public void append (ref G data);
[ReturnsModifiedPointer ()]
- public void prepend (G data);
+ public void prepend (ref G data);
[ReturnsModifiedPointer ()]
- public void insert (G data, int position);
+ public void insert (ref G data, int position);
[ReturnsModifiedPointer ()]
public void insert_before (List<G> sibling, G data);
[ReturnsModifiedPointer ()]
[ReferenceType ()]
public struct HashTable<K,V> {
public static ref HashTable new (HashFunc hash_func, EqualFunc key_equal_func);
- public void insert (K key, V value);
+ public void insert (ref K key, ref V value);
public V lookup (K key);
}