Commit 0e25bbfe authored by Jürg Billeter's avatar Jürg Billeter Committed by Jürg Billeter
Browse files

specify array element type as type argument create declarations for array

2006-10-04  Jürg Billeter  <j@bitron.ch>

	* vala/valasymbolresolver.vala, vala/valasemanticanalyzer.vala: specify
	  array element type as type argument
	* vala/valacodegenerator.vala: create declarations for array length
	  variables, iterate over arrays by index if it has known length
	* vala/valacharacterliteral.vala: correct return type of get_char
	* vala/valanamespace.vala: process enums and flags first
	* vala/valavariabledeclarator.vala: set parent_node of initializer, add
	  replace method
	* tests/test-023.vala: test list construction
	* tests/Makefile.am: update

svn path=/trunk/; revision=139
parent f0e08776
2006-10-04 Jürg Billeter <j@bitron.ch>
* vala/valasymbolresolver.vala, vala/valasemanticanalyzer.vala: specify
array element type as type argument
* vala/valacodegenerator.vala: create declarations for array length
variables, iterate over arrays by index if it has known length
* vala/valacharacterliteral.vala: correct return type of get_char
* vala/valanamespace.vala: process enums and flags first
* vala/valavariabledeclarator.vala: set parent_node of initializer, add
replace method
* tests/test-023.vala: test list construction
* tests/Makefile.am: update
2006-10-03 Jürg Billeter <j@bitron.ch>
* vala/valacodegenerator.vala: don't use InstanceCast for callbacks
......
......@@ -23,4 +23,5 @@ EXTRA_DIST = \
test-020.vala \
test-021.vala \
test-022.vala \
test-023.vala \
$(NULL)
using GLib;
class Maman.Foo {
public void run () {
foreach (string s in create_list ()) {
stdout.printf (" %s", s);
}
}
public ref List<string> create_list () {
var s = new List<string>();
s.append ("2");
s.append ("3");
return s;
}
static int main (string[] args) {
stdout.printf ("List construction: 1");
var foo = new Foo ();
foo.run ();
stdout.printf (" 4\n");
return 0;
}
}
......@@ -70,8 +70,7 @@ public class Vala.CharacterLiteral : Literal {
*
* @return unicode character value
*/
public uint get_char () {
// FIXME: unichar return type
return (uint) value.next_char ().get_char ();
public unichar get_char () {
return value.next_char ().get_char ();
}
}
......@@ -235,8 +235,7 @@ public class Vala.CodeGenerator : CodeVisitor {
var i = filename;
while (i.len () > 0) {
var c = i.get_char ();
/* FIXME: remove explicit cast when implicit cast works */
if (c.isalnum () && c < (unichar) 128) {
if (c.isalnum () && c < 0x80) {
define.append_unichar (c.toupper ());
} else {
define.append_c ('_');
......@@ -1422,9 +1421,25 @@ public class Vala.CodeGenerator : CodeVisitor {
create_temp_decl (stmt, decl.initializer.temp_vars);
}
}
create_temp_decl (stmt, temp_vars);
temp_vars = null;
}
public override void visit_variable_declarator (VariableDeclarator! decl) {
if (decl.type_reference.data_type is Array) {
// create variables to store array dimensions
var arr = (Array) decl.type_reference.data_type;
for (int dim = 1; dim <= arr.rank; dim++) {
var len_decl = new VariableDeclarator (get_array_length_cname (decl.name, dim));
len_decl.type_reference = new TypeReference ();
len_decl.type_reference.data_type = int_type.data_type;
temp_vars.prepend (len_decl);
}
}
CCodeExpression rhs = null;
if (decl.initializer != null) {
rhs = (CCodeExpression) decl.initializer.ccodenode;
......@@ -1743,26 +1758,53 @@ public class Vala.CodeGenerator : CodeVisitor {
var cblock = new CCodeBlock ();
if (stmt.collection.static_type.data_type is Array) {
var it_name = "%s_it".printf (stmt.variable_name);
var citdecl = new CCodeDeclaration (stmt.collection.static_type.get_cname ());
citdecl.add_declarator (new CCodeVariableDeclarator (it_name));
cblock.add_statement (citdecl);
var arr = (Array) stmt.collection.static_type.data_type;
var cbody = new CCodeBlock ();
var array_len = get_array_length_cexpression (stmt.collection, 1);
var cdecl = new CCodeDeclaration (stmt.type_reference.get_cname ());
cdecl.add_declarator (new CCodeVariableDeclarator.with_initializer (stmt.variable_name, new CCodeIdentifier ("*%s".printf (it_name))));
cbody.add_statement (cdecl);
cbody.add_statement (stmt.body.ccodenode);
if (array_len is CCodeConstant) {
var it_name = "%s_it".printf (stmt.variable_name);
var ccond = new CCodeBinaryExpression (CCodeBinaryOperator.INEQUALITY, new CCodeIdentifier ("*%s".printf (it_name)), new CCodeConstant ("NULL"));
var citdecl = new CCodeDeclaration (stmt.collection.static_type.get_cname ());
citdecl.add_declarator (new CCodeVariableDeclarator (it_name));
cblock.add_statement (citdecl);
var cbody = new CCodeBlock ();
var cdecl = new CCodeDeclaration (stmt.type_reference.get_cname ());
cdecl.add_declarator (new CCodeVariableDeclarator.with_initializer (stmt.variable_name, new CCodeIdentifier ("*%s".printf (it_name))));
cbody.add_statement (cdecl);
cbody.add_statement (stmt.body.ccodenode);
var ccond = new CCodeBinaryExpression (CCodeBinaryOperator.INEQUALITY, new CCodeIdentifier ("*%s".printf (it_name)), new CCodeConstant ("NULL"));
var cfor = new CCodeForStatement (ccond, cbody);
cfor.add_initializer (new CCodeAssignment (new CCodeIdentifier (it_name), (CCodeExpression) stmt.collection.ccodenode));
cfor.add_iterator (new CCodeAssignment (new CCodeIdentifier (it_name), new CCodeBinaryExpression (CCodeBinaryOperator.PLUS, new CCodeIdentifier (it_name), new CCodeConstant ("1"))));
cblock.add_statement (cfor);
} else {
var it_name = (stmt.variable_name + "_it");
var cfor = new CCodeForStatement (ccond, cbody);
cfor.add_initializer (new CCodeAssignment (new CCodeIdentifier (it_name), (CCodeExpression) stmt.collection.ccodenode));
cfor.add_iterator (new CCodeAssignment (new CCodeIdentifier (it_name), new CCodeBinaryExpression (CCodeBinaryOperator.PLUS, new CCodeIdentifier (it_name), new CCodeConstant ("1"))));
cblock.add_statement (cfor);
var citdecl = new CCodeDeclaration ("int");
citdecl.add_declarator (new CCodeVariableDeclarator (it_name));
cblock.add_statement (citdecl);
var cbody = new CCodeBlock ();
var cdecl = new CCodeDeclaration (stmt.type_reference.get_cname ());
cdecl.add_declarator (new CCodeVariableDeclarator.with_initializer (stmt.variable_name, new CCodeElementAccess ((CCodeExpression) stmt.collection.ccodenode, new CCodeIdentifier (it_name))));
cbody.add_statement (cdecl);
cbody.add_statement (stmt.body.ccodenode);
var ccond = new CCodeBinaryExpression (CCodeBinaryOperator.LESS_THAN, new CCodeIdentifier (it_name), array_len);
var cfor = new CCodeForStatement (ccond, cbody);
cfor.add_initializer (new CCodeAssignment (new CCodeIdentifier (it_name), new CCodeConstant ("0")));
cfor.add_iterator (new CCodeAssignment (new CCodeIdentifier (it_name), new CCodeBinaryExpression (CCodeBinaryOperator.PLUS, new CCodeIdentifier (it_name), new CCodeConstant ("1"))));
cblock.add_statement (cfor);
}
} else if (stmt.collection.static_type.data_type == list_type ||
stmt.collection.static_type.data_type == slist_type) {
var it_name = "%s_it".printf (stmt.variable_name);
......@@ -1966,10 +2008,10 @@ public class Vala.CodeGenerator : CodeVisitor {
* @param expr an array creation expression
*/
public override void visit_end_array_creation_expression (ArrayCreationExpression! expr) {
/* FIXME: ranks > 1 not supported yet */
/* FIXME: rank > 1 not supported yet */
if (expr.rank > 1) {
expr.error = true;
Report.error (expr.source_reference, "Creating arrays with rank greater than 1 are not supported yet");
Report.error (expr.source_reference, "Creating arrays with rank greater than 1 is not supported yet");
}
var sizes = expr.get_sizes ();
......@@ -1990,7 +2032,7 @@ public class Vala.CodeGenerator : CodeVisitor {
ce.append_expression (new CCodeAssignment (name_cnode, gnew));
foreach (Expression e in expr.initializer_list.get_initializers ()) {
ce.append_expression (new CCodeAssignment (new CCodeElementAccess (name_cnode, new CCodeConstant (i.to_string ())), (CCodeExpression)e.ccodenode));
ce.append_expression (new CCodeAssignment (new CCodeElementAccess (name_cnode, new CCodeConstant (i.to_string ())), (CCodeExpression) e.ccodenode));
i++;
}
......@@ -2215,11 +2257,20 @@ public class Vala.CodeGenerator : CodeVisitor {
}
}
if (array_expr.symbol_reference != null &&
array_expr.symbol_reference.node is FormalParameter) {
var param = (FormalParameter) array_expr.symbol_reference.node;
if (!param.no_array_length) {
var length_expr = new CCodeIdentifier (get_array_length_cname (param.name, dim));
if (array_expr.symbol_reference != null) {
if (array_expr.symbol_reference.node is FormalParameter) {
var param = (FormalParameter) array_expr.symbol_reference.node;
if (!param.no_array_length) {
var length_expr = new CCodeIdentifier (get_array_length_cname (param.name, dim));
if (is_out) {
return new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, length_expr);
} else {
return length_expr;
}
}
} else if (array_expr.symbol_reference.node is VariableDeclarator) {
var decl = (VariableDeclarator) array_expr.symbol_reference.node;
var length_expr = new CCodeIdentifier (get_array_length_cname (decl.name, dim));
if (is_out) {
return new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, length_expr);
} else {
......
......@@ -166,6 +166,15 @@ public class Vala.Namespace : CodeNode {
public override void accept (CodeVisitor! visitor) {
visitor.visit_begin_namespace (this);
/* process enums and flags first to avoid order problems in C code */
foreach (Enum en in enums) {
en.accept (visitor);
}
foreach (Flags fl in flags_) {
fl.accept (visitor);
}
foreach (Class cl in classes) {
cl.accept (visitor);
}
......@@ -178,14 +187,6 @@ public class Vala.Namespace : CodeNode {
st.accept (visitor);
}
foreach (Enum en in enums) {
en.accept (visitor);
}
foreach (Flags fl in flags_) {
fl.accept (visitor);
}
foreach (Callback cb in callbacks) {
cb.accept (visitor);
}
......
......@@ -588,6 +588,7 @@ public class Vala.SemanticAnalyzer : CodeVisitor {
if (expr.initializer_list != null) {
expr.initializer_list.expected_type = expr.element_type.copy ();
expr.initializer_list.expected_type.data_type = expr.initializer_list.expected_type.data_type.get_array (expr.rank);
// FIXME: add element type to type_argument
}
}
......@@ -623,14 +624,18 @@ public class Vala.SemanticAnalyzer : CodeVisitor {
}
/* try to construct the type of the array */
if (expr.element_type != null) {
expr.static_type = expr.element_type;
expr.static_type.data_type = expr.element_type.data_type.get_array (expr.rank);
} else {
if (expr.element_type == null) {
expr.error = true;
Report.error (expr.source_reference, "Cannot determine the element type of the created array");
return;
}
expr.static_type = expr.element_type.copy ();
expr.static_type.data_type = expr.element_type.data_type.get_array (expr.rank);
expr.static_type.transfers_ownership = true;
expr.static_type.takes_ownership = true;
expr.static_type.add_type_argument (expr.element_type);
}
public override void visit_boolean_literal (BooleanLiteral! expr) {
......@@ -990,8 +995,15 @@ public class Vala.SemanticAnalyzer : CodeVisitor {
/* assign a static_type when possible */
if (expr.container.static_type.data_type is Array) {
expr.static_type = new TypeReference ();
expr.static_type.data_type = ((Array)expr.container.static_type.data_type).element_type;
var args = expr.container.static_type.get_type_arguments ();
if (args.length () != 1) {
expr.error = true;
Report.error (expr.source_reference, "internal error: array reference without type arguments");
return;
}
expr.static_type = (TypeReference) args.data;
} else {
expr.error = true;
Report.error (expr.source_reference, "The expression `%s' does not denote an Array".printf (expr.container.static_type.to_string ()));
......@@ -1551,6 +1563,7 @@ public class Vala.SemanticAnalyzer : CodeVisitor {
if (!is_type_compatible (a.right.static_type, a.left.static_type)) {
/* if there was an error on either side,
* i.e. a.{left|right}.static_type == null, skip type check */
a.error = true;
Report.error (a.source_reference, "Assignment: Cannot convert from `%s' to `%s'".printf (a.right.static_type.to_string (), a.left.static_type.to_string ()));
return;
}
......@@ -1577,7 +1590,47 @@ public class Vala.SemanticAnalyzer : CodeVisitor {
}
}
} else if (a.left is ElementAccess) {
// do nothing
var ea = (ElementAccess) a.left;
if (!is_type_compatible (a.right.static_type, a.left.static_type)) {
/* if there was an error on either side,
* i.e. a.{left|right}.static_type == null, skip type check */
a.error = true;
Report.error (a.source_reference, "Assignment: Cannot convert from `%s' to `%s'".printf (a.right.static_type.to_string (), a.left.static_type.to_string ()));
return;
}
if (memory_management) {
if (a.right.static_type.transfers_ownership) {
/* rhs transfers ownership of the expression */
var args = ea.container.static_type.get_type_arguments ();
if (args.length () != 1) {
a.error = true;
Report.error (ea.source_reference, "internal error: array reference without type arguments");
return;
}
var element_type = (TypeReference) args.data;
if (!element_type.takes_ownership) {
/* lhs doesn't own the value
* promote lhs type if it is a local variable
* error if it's not a local variable */
if (!(ea.container.symbol_reference.node is VariableDeclarator)) {
a.error = true;
Report.error (a.source_reference, "Invalid assignment from owned expression to unowned variable");
return;
}
element_type.takes_ownership = true;
}
} else if (a.left.static_type.takes_ownership) {
/* lhs wants to own the value
* rhs doesn't transfer the ownership
* code generator needs to add reference
* increment calls */
}
}
} else {
return;
}
......
......@@ -182,15 +182,20 @@ public class Vala.SymbolResolver : CodeVisitor {
}
if (type.data_type != null && !type.data_type.is_reference_type ()) {
/* reset takes_ownership for contexts where types
* are ref by default (field declarations)
/* reset takes_ownership of value-types for contexts
* where types are ref by default (field declarations)
*/
type.takes_ownership = false;
}
/* check for array */
if (type.array_rank > 0) {
var element_type = new TypeReference ();
element_type.data_type = type.data_type;
element_type.takes_ownership = true;
type.data_type = type.data_type.get_array (type.array_rank);
type.add_type_argument (element_type);
}
}
}
......@@ -34,13 +34,25 @@ public class Vala.VariableDeclarator : CodeNode, Invokable {
/**
* The optional initializer expression.
*/
public Expression initializer { get; set; }
public Expression initializer {
get {
return _initializer;
}
set {
_initializer = value;
if (_initializer != null) {
_initializer.parent_node = this;
}
}
}
/**
* The variable type.
*/
public TypeReference type_reference { get; set; }
private Expression _initializer;
/**
* Creates a new variable declarator.
*
......@@ -90,4 +102,10 @@ public class Vala.VariableDeclarator : CodeNode, Invokable {
public override bool is_invokable () {
return (type_reference.data_type is Callback);
}
public override void replace (CodeNode! old_node, CodeNode! new_node) {
if (initializer == old_node) {
initializer = (Expression) new_node;
}
}
}
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