Commit 6cb56978 authored by Jürg Billeter's avatar Jürg Billeter Committed by Jürg Billeter

Don't use UnresolvedType for array and pointer types, add basic support

2008-05-17  Juerg Billeter  <j@bitron.ch>

	* vala/valaarraytype.vala:
	* vala/valaclass.vala:
	* vala/valaparser.vala:
	* vala/valapointertype.vala:
	* vala/valasymbolresolver.vala:
	* vala/valaunresolvedtype.vala:
	* vapigen/valagidlparser.vala:

	Don't use UnresolvedType for array and pointer types, add basic
	support for arrays of arrays

svn path=/trunk/; revision=1395
parent 5899a524
2008-05-17 Jürg Billeter <j@bitron.ch>
* vala/valaarraytype.vala:
* vala/valaclass.vala:
* vala/valaparser.vala:
* vala/valapointertype.vala:
* vala/valasymbolresolver.vala:
* vala/valaunresolvedtype.vala:
* vapigen/valagidlparser.vala:
Don't use UnresolvedType for array and pointer types, add basic
support for arrays of arrays
2008-05-17 Ali Sabil <ali.sabil@gmail.com>
* vapigen/valagidlparser.vala: Automatically hide fields
......
......@@ -29,13 +29,21 @@ public class Vala.ArrayType : ReferenceType {
/**
* The element type.
*/
public DataType element_type { get; construct set; }
public DataType element_type {
get { return _element_type; }
set {
_element_type = value;
_element_type.parent_node = this;
}
}
/**
* The rank of this array.
*/
public int rank { get; construct set; }
public int rank { get; set; }
private DataType _element_type;
private ArrayLengthField length_field;
private ArrayResizeMethod resize_method;
private ArrayMoveMethod move_method;
......@@ -173,4 +181,14 @@ public class Vala.ArrayType : ReferenceType {
return "a" + element_type_signature;
}
public override void accept_children (CodeVisitor visitor) {
element_type.accept (visitor);
}
public override void replace_type (DataType old_type, DataType new_type) {
if (element_type == old_type) {
element_type = new_type;
}
}
}
......@@ -263,39 +263,15 @@ public class Vala.Class : Typesymbol {
*
* @param prop a property
*/
public void add_property (Property prop, bool no_field = false) {
public void add_property (Property prop) {
properties.add (prop);
scope.add (prop.name, prop);
prop.this_parameter = new FormalParameter ("this", new ClassInstanceType (this));
prop.scope.add (prop.this_parameter.name, prop.this_parameter);
if (!no_field && !external_package) {
bool empty_get = (prop.get_accessor != null && prop.get_accessor.body == null);
bool empty_set = (prop.set_accessor != null && prop.set_accessor.body == null);
if (empty_get != empty_set) {
if (empty_get) {
Report.error (prop.source_reference, "property getter must have a body");
} else if (empty_set) {
Report.error (prop.source_reference, "property setter must have a body");
}
prop.error = true;
return;
}
if (empty_get && empty_set) {
/* automatic property accessor body generation */
var field_type = prop.property_type.copy ();
var ut = field_type as UnresolvedType;
if (ut != null) {
field_type.value_owned = !ut.is_weak;
}
var f = new Field ("_%s".printf (prop.name), field_type, prop.default_expression, prop.source_reference);
f.access = SymbolAccessibility.PRIVATE;
prop.field = f;
add_field (f);
}
if (prop.field != null) {
add_field (prop.field);
}
}
......
......@@ -319,7 +319,7 @@ public class Vala.Parser : CodeVisitor {
skip_type_argument_list ();
while (accept (TokenType.STAR)) {
}
if (accept (TokenType.OPEN_BRACKET)) {
while (accept (TokenType.OPEN_BRACKET)) {
do {
if (current () != TokenType.COMMA && current () != TokenType.CLOSE_BRACKET) {
parse_expression ();
......@@ -332,7 +332,7 @@ public class Vala.Parser : CodeVisitor {
accept (TokenType.HASH);
}
DataType parse_type () throws ParseError {
DataType parse_type (bool owned_by_default = true) throws ParseError {
var begin = get_location ();
if (accept (TokenType.VOID)) {
......@@ -345,20 +345,34 @@ public class Vala.Parser : CodeVisitor {
bool is_dynamic = accept (TokenType.DYNAMIC);
bool is_weak = accept (TokenType.WEAK);
bool value_owned = owned_by_default;
if (owned_by_default) {
value_owned = !accept (TokenType.WEAK);
}
var sym = parse_symbol_name ();
Gee.List<DataType> type_arg_list = parse_type_argument_list (false);
int stars = 0;
DataType type = new UnresolvedType.from_symbol (sym, get_src (begin));
if (type_arg_list != null) {
foreach (DataType type_arg in type_arg_list) {
type.add_type_argument (type_arg);
}
}
while (accept (TokenType.STAR)) {
stars++;
type = new PointerType (type, get_src (begin));
}
bool nullable = stars > 0 || accept (TokenType.INTERR);
if (!(type is PointerType)) {
type.nullable = accept (TokenType.INTERR);
}
int array_rank = 0;
if (accept (TokenType.OPEN_BRACKET)) {
// array brackets in types are read from right to left,
// this is more logical, especially when nullable arrays
// or pointers are involved
while (accept (TokenType.OPEN_BRACKET)) {
int array_rank = 0;
do {
array_rank++;
// support for stack-allocated arrays
......@@ -370,26 +384,22 @@ public class Vala.Parser : CodeVisitor {
while (accept (TokenType.COMMA));
expect (TokenType.CLOSE_BRACKET);
nullable = accept (TokenType.INTERR);
// arrays contain strong references by default
type.value_owned = true;
type = new ArrayType (type, array_rank, get_src (begin));
type.nullable = accept (TokenType.INTERR);
}
if (accept (TokenType.OP_NEG)) {
Report.warning (get_last_src (), "obsolete syntax, types are non-null by default");
}
bool value_owned = accept (TokenType.HASH);
var type = new UnresolvedType.from_symbol (sym, get_src (begin));
if (type_arg_list != null) {
foreach (DataType type_arg in type_arg_list) {
type.add_type_argument (type_arg);
}
if (!owned_by_default) {
value_owned = accept (TokenType.HASH);
}
type.is_dynamic = is_dynamic;
type.is_weak = is_weak;
type.pointer_level = stars;
type.array_rank = array_rank;
type.nullable = nullable;
type.value_owned = value_owned;
return type;
}
......@@ -646,21 +656,34 @@ public class Vala.Parser : CodeVisitor {
Expression parse_array_creation_expression (SourceLocation begin, MemberAccess member) throws ParseError {
bool size_specified = false;
var size_specifier_list = new ArrayList<Expression> ();
Gee.List<Expression> size_specifier_list;
bool first = true;
DataType element_type = UnresolvedType.new_from_expression (member);
do {
Expression size = null;
if (current () != TokenType.CLOSE_BRACKET && current () != TokenType.COMMA) {
size = parse_expression ();
size_specified = true;
if (!first) {
// array of arrays: new T[][42]
element_type = new ArrayType (element_type, size_specifier_list.size, element_type.source_reference);
} else {
first = false;
}
size_specifier_list.add (size);
} while (accept (TokenType.COMMA));
expect (TokenType.CLOSE_BRACKET);
size_specifier_list = new ArrayList<Expression> ();
do {
Expression size = null;
if (current () != TokenType.CLOSE_BRACKET && current () != TokenType.COMMA) {
size = parse_expression ();
size_specified = true;
}
size_specifier_list.add (size);
} while (accept (TokenType.COMMA));
expect (TokenType.CLOSE_BRACKET);
} while (accept (TokenType.OPEN_BRACKET));
InitializerList initializer = null;
if (current () == TokenType.OPEN_BRACE) {
initializer = parse_initializer ();
}
var expr = new ArrayCreationExpression (UnresolvedType.new_from_expression (member), size_specifier_list.size, initializer, get_src (begin));
var expr = new ArrayCreationExpression (element_type, size_specifier_list.size, initializer, get_src (begin));
if (size_specified) {
foreach (Expression size in size_specifier_list) {
expr.append_size (size);
......@@ -763,8 +786,7 @@ public class Vala.Parser : CodeVisitor {
case TokenType.SIZEOF:
case TokenType.TYPEOF:
case TokenType.IDENTIFIER:
var ut = type as UnresolvedType;
if (ut != null && ut.is_weak) {
if (!type.value_owned) {
Report.warning (get_src (begin), "obsolete syntax, weak type modifier unused in cast expressions");
}
var inner = parse_unary_expression ();
......@@ -1312,10 +1334,6 @@ public class Vala.Parser : CodeVisitor {
variable_type = null;
} else {
variable_type = parse_type ();
var ut = variable_type as UnresolvedType;
if (ut != null && !ut.is_weak) {
variable_type.value_owned = true;
}
}
do {
DataType type_copy = null;
......@@ -1449,10 +1467,6 @@ public class Vala.Parser : CodeVisitor {
variable_type = null;
} else {
variable_type = parse_type ();
var ut = variable_type as UnresolvedType;
if (ut != null && !ut.is_weak) {
variable_type.value_owned = true;
}
}
var local = parse_local_variable (variable_type);
block.add_statement (new DeclarationStatement (local, local.source_reference));
......@@ -1493,10 +1507,6 @@ public class Vala.Parser : CodeVisitor {
expect (TokenType.FOREACH);
expect (TokenType.OPEN_PARENS);
var type = parse_type ();
var unresolved_type = type as UnresolvedType;
if (unresolved_type != null && !unresolved_type.is_weak) {
unresolved_type.value_owned = true;
}
string id = parse_identifier ();
expect (TokenType.IN);
var collection = parse_expression ();
......@@ -1966,7 +1976,7 @@ public class Vala.Parser : CodeVisitor {
var access = parse_access_modifier ();
parse_member_declaration_modifiers ();
expect (TokenType.CONST);
var type = parse_type ();
var type = parse_type (false);
string id = parse_identifier ();
Expression initializer = null;
if (accept (TokenType.ASSIGN)) {
......@@ -1984,10 +1994,6 @@ public class Vala.Parser : CodeVisitor {
var access = parse_access_modifier ();
var flags = parse_member_declaration_modifiers ();
var type = parse_type ();
var unresolved_type = type as UnresolvedType;
if (unresolved_type != null && !unresolved_type.is_weak) {
unresolved_type.value_owned = true;
}
string id = parse_identifier ();
var f = new Field (id, type, null, get_src_com (begin));
f.access = access;
......@@ -2032,10 +2038,6 @@ public class Vala.Parser : CodeVisitor {
var access = parse_access_modifier ();
var flags = parse_member_declaration_modifiers ();
var type = parse_type ();
var unresolved_type = type as UnresolvedType;
if (unresolved_type != null && !unresolved_type.is_weak) {
unresolved_type.value_owned = true;
}
string id = parse_identifier ();
parse_type_parameter_list ();
var method = new Method (id, type, get_src_com (begin));
......@@ -2094,7 +2096,8 @@ public class Vala.Parser : CodeVisitor {
var begin = get_location ();
var access = parse_access_modifier ();
var flags = parse_member_declaration_modifiers ();
var type = parse_type ();
bool is_weak = accept (TokenType.WEAK);
var type = parse_type (false);
string id = parse_identifier ();
var prop = new Property (id, type, null, null, get_src_com (begin));
prop.access = access;
......@@ -2161,6 +2164,29 @@ public class Vala.Parser : CodeVisitor {
}
}
expect (TokenType.CLOSE_BRACE);
if (!prop.is_abstract && !scanner.source_file.external_package) {
bool empty_get = (prop.get_accessor != null && prop.get_accessor.body == null);
bool empty_set = (prop.set_accessor != null && prop.set_accessor.body == null);
if (empty_get != empty_set) {
if (empty_get) {
Report.error (prop.source_reference, "property getter must have a body");
} else if (empty_set) {
Report.error (prop.source_reference, "property setter must have a body");
}
prop.error = true;
}
if (empty_get && empty_set) {
/* automatic property accessor body generation */
var field_type = prop.property_type.copy ();
field_type.value_owned = !is_weak;
prop.field = new Field ("_%s".printf (prop.name), field_type, prop.default_expression, prop.source_reference);
prop.field.access = SymbolAccessibility.PRIVATE;
}
}
return prop;
}
......@@ -2543,16 +2569,13 @@ public class Vala.Parser : CodeVisitor {
direction = ParameterDirection.REF;
}
var type = parse_type ();
var ut = type as UnresolvedType;
if (ut != null) {
if (direction != ParameterDirection.IN && !ut.is_weak) {
ut.value_owned = true;
} else if (direction == ParameterDirection.IN && ut.is_weak) {
Report.error (type.source_reference, "in parameters are weak by default");
} else if (direction != ParameterDirection.IN && ut.value_owned) {
Report.error (type.source_reference, "out parameters own the value by default");
}
DataType type;
if (direction == ParameterDirection.IN) {
// in parameters are weak by default
type = parse_type (false);
} else {
// out parameters own the value by default
type = parse_type (true);
}
string id = parse_identifier ();
var param = new FormalParameter (id, type, get_src (begin));
......@@ -2604,10 +2627,6 @@ public class Vala.Parser : CodeVisitor {
var flags = parse_member_declaration_modifiers ();
expect (TokenType.DELEGATE);
var type = parse_type ();
var unresolved_type = type as UnresolvedType;
if (unresolved_type != null && !unresolved_type.is_weak) {
unresolved_type.value_owned = true;
}
var sym = parse_symbol_name ();
var type_param_list = parse_type_parameter_list ();
var d = new Delegate (sym.name, type, get_src_com (begin));
......@@ -2683,10 +2702,6 @@ public class Vala.Parser : CodeVisitor {
case TokenType.WEAK:
case TokenType.IDENTIFIER:
var type = parse_type ();
var ut = type as UnresolvedType;
if (ut != null && !ut.is_weak) {
type.value_owned = true;
}
list.add (type);
break;
default:
......
......@@ -30,11 +30,20 @@ public class Vala.PointerType : DataType {
/**
* The base type the pointer is referring to.
*/
public DataType base_type { get; set; }
public DataType base_type {
get { return _base_type; }
set {
_base_type = value;
_base_type.parent_node = this;
}
}
public PointerType (DataType base_type) {
private DataType _base_type;
public PointerType (DataType base_type, SourceReference? source_reference = null) {
this.base_type = base_type;
nullable = true;
this.source_reference = source_reference;
}
public override string to_string () {
......@@ -88,4 +97,14 @@ public class Vala.PointerType : DataType {
public override string? get_type_id () {
return "G_TYPE_POINTER";
}
public override void accept_children (CodeVisitor visitor) {
base_type.accept (visitor);
}
public override void replace_type (DataType old_type, DataType new_type) {
if (base_type == old_type) {
base_type = new_type;
}
}
}
......@@ -280,32 +280,12 @@ public class Vala.SymbolResolver : CodeVisitor {
type.add_type_argument (type_arg);
}
for (int pointer_level = unresolved_type.pointer_level; pointer_level > 0; pointer_level--) {
var base_type = type;
base_type.value_owned = false;
base_type.nullable = false;
base_type.is_dynamic = false;
type = new PointerType (base_type);
}
/* check for array */
if (unresolved_type.array_rank > 0) {
var element_type = type;
// array contains strong references by default
element_type.value_owned = true;
element_type.nullable = false;
type = new ArrayType (element_type, unresolved_type.array_rank, unresolved_type.source_reference);
type.value_owned = unresolved_type.value_owned;
type.nullable = unresolved_type.nullable;
}
return type;
}
public override void visit_data_type (DataType data_type) {
data_type.accept_children (this);
if (!(data_type is UnresolvedType)) {
return;
}
......
......@@ -33,23 +33,6 @@ public class Vala.UnresolvedType : DataType {
*/
public UnresolvedSymbol unresolved_symbol { get; set; }
/**
* Specifies the rank of the array this reference is possibly referring
* to. "0" indicates no array.
*/
public int array_rank { get; set; }
/**
* Specifies the level of the pointer if this is a pointer-type. "0"
* indicates no pointer-type.
*/
public int pointer_level { get; set; }
/**
* The weak modifier has been specified.
*/
public bool is_weak { get; set; }
public UnresolvedType () {
}
......@@ -109,9 +92,6 @@ public class Vala.UnresolvedType : DataType {
result.nullable = nullable;
result.is_dynamic = is_dynamic;
result.unresolved_symbol = unresolved_symbol.copy ();
result.array_rank = array_rank;
result.pointer_level = pointer_level;
result.is_weak = is_weak;
foreach (DataType arg in get_type_arguments ()) {
result.add_type_argument (arg.copy ());
......
......@@ -874,7 +874,7 @@ public class Vala.GIdlParser : CodeVisitor {
} else if (member.type == IdlNodeTypeId.PROPERTY) {
var prop = parse_property ((IdlNodeProperty) member);
if (prop != null) {
cl.add_property (prop, true);
cl.add_property (prop);
}
} else if (member.type == IdlNodeTypeId.SIGNAL) {
var sig = parse_signal ((IdlNodeSignal) member);
......@@ -1040,7 +1040,7 @@ public class Vala.GIdlParser : CodeVisitor {
if (type == null) {
return element_type;
}
type.array_rank = 1;
return new ArrayType (element_type, 1, element_type.source_reference);
} else if (type_node.tag == TypeTag.LIST) {
type.unresolved_symbol = new UnresolvedSymbol (new UnresolvedSymbol (null, "GLib"), "List");
} else if (type_node.tag == TypeTag.SLIST) {
......@@ -1073,7 +1073,7 @@ public class Vala.GIdlParser : CodeVisitor {
} else if (n == "guchar" || n == "guint8") {
type.unresolved_symbol = new UnresolvedSymbol (null, "uchar");
if (type_node.is_pointer) {
type.array_rank = 1;
return new ArrayType (type, 1, type.source_reference);
}
} else if (n == "gushort") {
type.unresolved_symbol = new UnresolvedSymbol (null, "ushort");
......@@ -1104,11 +1104,11 @@ public class Vala.GIdlParser : CodeVisitor {
} else if (n == "GType") {
type.unresolved_symbol = new UnresolvedSymbol (new UnresolvedSymbol (null, "GLib"), "Type");
if (type_node.is_pointer) {
type.array_rank = 1;
return new ArrayType (type, 1, type.source_reference);
}
} else if (n == "GStrv") {
type.unresolved_symbol = new UnresolvedSymbol (null, "string");
type.array_rank = 1;
return new ArrayType (type, 1, type.source_reference);
} else {
var named_type = parse_type_string (n);
type = named_type as UnresolvedType;
......@@ -1275,7 +1275,8 @@ public class Vala.GIdlParser : CodeVisitor {
m.sentinel = eval (nv[1]);
} else if (nv[0] == "is_array") {
if (eval (nv[1]) == "1") {
((UnresolvedType) return_type).array_rank = 1;
return_type = new ArrayType (return_type, 1, return_type.source_reference);
m.return_type = return_type;
}
} else if (nv[0] == "throws") {
if (eval (nv[1]) == "0") {
......@@ -1362,7 +1363,8 @@ public class Vala.GIdlParser : CodeVisitor {
var nv = attr.split ("=", 2);
if (nv[0] == "is_array") {
if (eval (nv[1]) == "1") {
((UnresolvedType) param_type).array_rank = 1;
param_type = new ArrayType (param_type, 1, param_type.source_reference);
p.parameter_type = param_type;
p.direction = ParameterDirection.IN;
}
} else if (nv[0] == "is_out") {
......@@ -1418,7 +1420,8 @@ public class Vala.GIdlParser : CodeVisitor {
if (last_param != null && p.name == "n_" + last_param.name) {
// last_param is array, p is array length
((UnresolvedType) last_param_type).array_rank = 1;
last_param_type = new ArrayType (last_param_type, 1, last_param_type.source_reference);
last_param.parameter_type = last_param_type;
last_param.direction = ParameterDirection.IN;
// hide array length param
......@@ -1618,7 +1621,7 @@ public class Vala.GIdlParser : CodeVisitor {
}
} else if (nv[0] == "is_array") {
if (eval (nv[1]) == "1") {
((UnresolvedType) type).array_rank = 1;
type = new ArrayType (type, 1, type.source_reference);
}
} else if (nv[0] == "weak") {
if (eval (nv[1]) == "0") {
......@@ -1741,7 +1744,8 @@ public class Vala.GIdlParser : CodeVisitor {
var nv = attr.split ("=", 2);
if (nv[0] == "is_array") {
if (eval (nv[1]) == "1") {
((UnresolvedType) param_type).array_rank = 1;
param_type = new ArrayType (param_type, 1, param_type.source_reference);
p.parameter_type = param_type;
p.direction = ParameterDirection.IN;
}
} else if (nv[0] == "is_out") {
......
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