+2006-08-02 Jürg Billeter <j@bitron.ch>
+
+ * vala/parser.y, vala/valacodevisitor.vala, vala/valasymbolbuilder.vala,
+ vala/valasemanticanalyzer.vala, vala/valacodegenerator.vala,
+ vala/valainterfacewriter.vala, vala/valaclass.vala,
+ vala/valaexpressionstatement.vala, vala/valamethod.vala,
+ vala/valaobjectcreationexpression.vala, vala/valastatement.vala,
+ vala/valastruct.vala: add support for construction methods
+ * vala/valabooleanliteral.vala, vala/valaexpression.vala,
+ vala/valaintegerliteral.vala, vala/valaliteral.vala,
+ vala/valaliteralexpression.vala, vala/valamemberaccess.vala: add
+ to_string method
+ * vala/valamemberaccess.vala, vala/valatypereference.vala: support
+ storing type arguments in MemberAccess
+ * vala/valacodenode.vala: add parent_node property
+ * vala/parser.y, vala/valaifstatement.vala: only allow blocks as
+ embedded statements
+ * vala/valaenum.vala: implement get_type_id method
+ * vala/valainterfacewriter.vala: output default expressions of formal
+ parameters
+ * vala/valaformalparameter.vala: visit default expression
+ * vala/valaobjectcreationexpression.vala, vala/valanullliteral.vala,
+ vala/valaproperty.vala, vala/valapropertyaccessor.vala: add interface
+ documentation, use implicit namespace specification
+ * vala/vala.h: add valaelementaccess.h and valarealliteral.h
+ * ccode/valaccodememberaccess.vala: don't mark is_pointer as construct
+ * vapi/glib-2.0.vala: add GValue
+ * vapi/gtk+-2.0.vala: small updates
+
2006-07-31 Jürg Billeter <j@bitron.ch>
* vala/parser.y: support prefix increment and decrement, fix parsing
/**
* Specifies whether the member access happens by pointer dereferencing.
*/
- public bool is_pointer { get; set construct; }
+ public bool is_pointer { get; set; }
public override void write (CCodeWriter! writer) {
inner.write (writer);
%token <str> STRING_LITERAL "string"
%type <str> comment
+%type <str> opt_identifier
%type <literal> literal
%type <literal> boolean_literal
%type <type_reference> type_name
%type <expression> simple_name
%type <expression> parenthesized_expression
%type <expression> member_access
-%type <str> identifier_or_new
%type <expression> invocation_expression
%type <expression> element_access
%type <expression> post_increment_expression
%type <list> type_argument_list
%type <list> type_arguments
%type <type_reference> type_argument
+%type <expression> member_name
/* expect shift/reduce conflict on if/else */
%expect 1
| COMMA
;
+opt_identifier
+ : /* empty */
+ {
+ $$ = NULL;
+ }
+ | IDENTIFIER
+ ;
+
literal
: boolean_literal
| INTEGER_LITERAL
;
simple_name
- : IDENTIFIER
+ : IDENTIFIER opt_type_argument_list
{
ValaSourceReference *src = src(@1);
$$ = VALA_EXPRESSION (vala_member_access_new (NULL, $1, src));
g_free ($1);
g_object_unref (src);
+
+ if ($2 != NULL) {
+ GList *l;
+ for (l = $2; l != NULL; l = l->next) {
+ vala_member_access_add_type_argument (VALA_MEMBER_ACCESS ($$), l->data);
+ g_object_unref (l->data);
+ }
+ g_list_free ($2);
+ }
}
;
;
member_access
- : primary_expression DOT identifier_or_new
+ : primary_expression DOT IDENTIFIER opt_type_argument_list
{
ValaSourceReference *src = src(@3);
$$ = VALA_EXPRESSION (vala_member_access_new ($1, $3, src));
- g_object_unref (src);
g_object_unref ($1);
g_free ($3);
- }
- ;
+ g_object_unref (src);
-identifier_or_new
- : IDENTIFIER
- | NEW
- {
- $$ = g_strdup ("new");
+ if ($4 != NULL) {
+ GList *l;
+ for (l = $4; l != NULL; l = l->next) {
+ vala_member_access_add_type_argument (VALA_MEMBER_ACCESS ($$), l->data);
+ g_object_unref (l->data);
+ }
+ g_list_free ($4);
+ }
}
;
;
object_creation_expression
- : NEW type open_parens opt_named_argument_list CLOSE_PARENS
+ : NEW member_name open_parens opt_argument_list CLOSE_PARENS
{
ValaSourceReference *src = src(@2);
- $$ = VALA_EXPRESSION (vala_object_creation_expression_new ($2, $4, src));
+ ValaObjectCreationExpression *expr = vala_object_creation_expression_new ($2, src);
g_object_unref ($2);
+ g_object_unref (src);
+
if ($4 != NULL) {
+ GList *l;
+ for (l = $4; l != NULL; l = l->next) {
+ vala_object_creation_expression_add_argument (expr, l->data);
+ g_object_unref (l->data);
+ }
g_list_free ($4);
}
- g_object_unref (src);
+
+ $$ = VALA_EXPRESSION (expr);
}
;
/* don't use type to prevent reduce/reduce conflict */
local_variable_type
- : primary_expression opt_type_argument_list opt_op_neg
+ : primary_expression opt_op_neg
{
ValaSourceReference *src = src(@1);
$$ = vala_type_reference_new_from_expression ($1, src);
+ g_object_unref ($1);
g_object_unref (src);
- if ($3) {
+ if ($2) {
vala_type_reference_set_non_null ($$, TRUE);
}
- GList *l;
- for (l = $2; l != NULL; l = l->next) {
- vala_type_reference_add_type_argument ($$, l->data);
- g_object_unref (l->data);
- }
- g_list_free ($2);
- g_object_unref ($1);
}
- | REF primary_expression opt_type_argument_list opt_op_neg
+ | REF primary_expression opt_op_neg
{
ValaSourceReference *src = src(@2);
$$ = vala_type_reference_new_from_expression ($2, src);
+ g_object_unref ($2);
g_object_unref (src);
vala_type_reference_set_takes_ownership ($$, TRUE);
- if ($4) {
+ if ($3) {
vala_type_reference_set_non_null ($$, TRUE);
}
- GList *l;
- for (l = $3; l != NULL; l = l->next) {
- vala_type_reference_add_type_argument ($$, l->data);
- g_object_unref (l->data);
- }
- g_list_free ($3);
- g_object_unref ($2);
}
| local_variable_type array_qualifier
{
ValaSourceReference *src = src_com(@2, $1);
$$ = VALA_STATEMENT (vala_expression_statement_new ($2, src));
g_object_unref (src);
+ vala_code_node_set_parent_node (VALA_CODE_NODE ($2), VALA_CODE_NODE ($$));
g_object_unref ($2);
}
;
if_statement
: comment IF open_parens expression CLOSE_PARENS embedded_statement
{
+ ValaBlock *true_block;
+ if (VALA_IS_BLOCK ($6)) {
+ true_block = VALA_BLOCK ($6);
+ } else {
+ true_block = vala_block_new (vala_code_node_get_source_reference (VALA_CODE_NODE ($6)));
+ vala_block_add_statement (true_block, $6);
+ g_object_unref ($6);
+ }
+
ValaSourceReference *src = src_com(@4, $1);
- $$ = VALA_STATEMENT (vala_if_statement_new ($4, $6, NULL, src));
+ $$ = VALA_STATEMENT (vala_if_statement_new ($4, true_block, NULL, src));
g_object_unref (src);
g_object_unref ($4);
- g_object_unref ($6);
+ g_object_unref (true_block);
}
| comment IF open_parens expression CLOSE_PARENS embedded_statement ELSE embedded_statement
{
+ ValaBlock *true_block;
+ if (VALA_IS_BLOCK ($6)) {
+ true_block = VALA_BLOCK ($6);
+ } else {
+ true_block = vala_block_new (vala_code_node_get_source_reference (VALA_CODE_NODE ($6)));
+ vala_block_add_statement (true_block, $6);
+ g_object_unref ($6);
+ }
+
+ ValaBlock *false_block;
+ if (VALA_IS_BLOCK ($8)) {
+ false_block = VALA_BLOCK ($8);
+ } else {
+ false_block = vala_block_new (vala_code_node_get_source_reference (VALA_CODE_NODE ($8)));
+ vala_block_add_statement (false_block, $8);
+ g_object_unref ($8);
+ }
+
ValaSourceReference *src = src_com(@4, $1);
- $$ = VALA_STATEMENT (vala_if_statement_new ($4, $6, $8, src));
+ $$ = VALA_STATEMENT (vala_if_statement_new ($4, true_block, false_block, src));
g_object_unref (src);
g_object_unref ($4);
- g_object_unref ($6);
- g_object_unref ($8);
+ g_object_unref (true_block);
+ g_object_unref (false_block);
}
;
;
method_header
- : comment opt_attributes opt_access_modifier opt_modifiers type identifier_or_new OPEN_PARENS opt_formal_parameter_list CLOSE_PARENS
+ : comment opt_attributes opt_access_modifier opt_modifiers type IDENTIFIER OPEN_PARENS opt_formal_parameter_list CLOSE_PARENS
{
GList *l;
g_object_unref ($5);
g_free ($6);
}
+ | comment opt_attributes opt_access_modifier CONSTRUCT opt_identifier OPEN_PARENS opt_formal_parameter_list CLOSE_PARENS
+ {
+ GList *l;
+
+ ValaSourceReference *src = src_com(@4, $1);
+ $$ = vala_method_new ($5, NULL, src);
+ g_free ($5);
+ g_object_unref (src);
+ vala_method_set_construction ($$, TRUE);
+ vala_method_set_instance ($$, FALSE);
+ if ($3 != 0) {
+ $$->access = $3;
+ }
+ VALA_CODE_NODE($$)->attributes = $2;
+
+ if ($7 != NULL) {
+ for (l = $7; l != NULL; l = l->next) {
+ vala_method_add_parameter ($$, l->data);
+ g_object_unref (l->data);
+ }
+ g_list_free ($7);
+ }
+ }
;
method_body
;
signal_declaration
- : comment opt_attributes opt_access_modifier SIGNAL type identifier_or_new OPEN_PARENS opt_formal_parameter_list CLOSE_PARENS SEMICOLON
+ : comment opt_attributes opt_access_modifier SIGNAL type IDENTIFIER OPEN_PARENS opt_formal_parameter_list CLOSE_PARENS SEMICOLON
{
GList *l;
| OPEN_CAST_PARENS
;
+member_name
+ : IDENTIFIER opt_type_argument_list
+ {
+ ValaSourceReference *src = src(@1);
+ $$ = VALA_EXPRESSION (vala_member_access_new (NULL, $1, src));
+ g_free ($1);
+ g_object_unref (src);
+
+ if ($2 != NULL) {
+ GList *l;
+ for (l = $2; l != NULL; l = l->next) {
+ vala_member_access_add_type_argument (VALA_MEMBER_ACCESS ($$), l->data);
+ g_object_unref (l->data);
+ }
+ g_list_free ($2);
+ }
+ }
+ | member_name DOT IDENTIFIER opt_type_argument_list
+ {
+ ValaSourceReference *src = src(@1);
+ $$ = VALA_EXPRESSION (vala_member_access_new ($1, $3, src));
+ g_object_unref ($1);
+ g_free ($3);
+ g_object_unref (src);
+
+ if ($4 != NULL) {
+ GList *l;
+ for (l = $4; l != NULL; l = l->next) {
+ vala_member_access_add_type_argument (VALA_MEMBER_ACCESS ($$), l->data);
+ g_object_unref (l->data);
+ }
+ g_list_free ($4);
+ }
+ }
+ ;
+
%%
extern FILE *yyin;
#include <vala/valadeclarationstatement.h>
#include <vala/valadestructor.h>
#include <vala/valadostatement.h>
+#include <vala/valaelementaccess.h>
#include <vala/valaemptystatement.h>
#include <vala/valaenum.h>
#include <vala/valaenumvalue.h>
#include <vala/valapostfixexpression.h>
#include <vala/valaproperty.h>
#include <vala/valapropertyaccessor.h>
+#include <vala/valarealliteral.h>
#include <vala/valareturnstatement.h>
#include <vala/valasignal.h>
#include <vala/valasourcefile.h>
public override void accept (CodeVisitor! visitor) {
visitor.visit_boolean_literal (this);
}
+
+ public override ref string! to_string () {
+ if (value) {
+ return "true";
+ } else {
+ return "false";
+ }
+ }
}
private List<Signal> signals;
/**
+ * Specifies the default construction method.
+ */
+ public Method default_construction_method { get; set; }
+
+ /**
* Specifies the instance constructor.
*/
public Constructor constructor { get; set; }
private int next_temp_var_id = 0;
TypeReference bool_type;
+ TypeReference int_type;
TypeReference string_type;
/**
bool_type = new TypeReference ();
bool_type.data_type = (DataType) root_symbol.lookup ("bool").node;
+ int_type = new TypeReference ();
+ int_type.data_type = (DataType) root_symbol.lookup ("int").node;
+
string_type = new TypeReference ();
string_type.data_type = (DataType) root_symbol.lookup ("string").node;
if (prop.type_reference.data_type is Class) {
cspec.call = new CCodeIdentifier (name = "g_param_spec_object");
cspec.add_argument (new CCodeIdentifier (name = prop.type_reference.data_type.get_upper_case_cname ("TYPE_")));
- } else if (prop.type_reference.type_name == "string") {
+ } else if (prop.type_reference.data_type == string_type.data_type) {
cspec.call = new CCodeIdentifier (name = "g_param_spec_string");
cspec.add_argument (new CCodeConstant (name = "NULL"));
- } else if (prop.type_reference.type_name == "int"
+ } else if (prop.type_reference.data_type == int_type.data_type
|| prop.type_reference.data_type is Enum) {
cspec.call = new CCodeIdentifier (name = "g_param_spec_int");
cspec.add_argument (new CCodeConstant (name = "G_MININT"));
cspec.add_argument (new CCodeConstant (name = "G_MAXINT"));
cspec.add_argument (new CCodeConstant (name = "0"));
- } else if (prop.type_reference.type_name == "bool") {
+ } else if (prop.type_reference.data_type == bool_type.data_type) {
cspec.call = new CCodeIdentifier (name = "g_param_spec_boolean");
cspec.add_argument (new CCodeConstant (name = "FALSE"));
} else {
}
if (prop.set_accessor != null) {
pflags = "%s%s".printf (pflags, " | G_PARAM_WRITABLE");
- if (prop.set_accessor.construct_) {
+ if (prop.set_accessor.construction) {
if (prop.set_accessor.writable) {
pflags = "%s%s".printf (pflags, " | G_PARAM_CONSTRUCT");
} else {
source_type_member_definition.append (function);
}
+ private ref CCodeIdentifier! get_value_setter_function (TypeReference! type_reference) {
+ if (type_reference.data_type is Class) {
+ return new CCodeIdentifier (name = "g_value_set_object");
+ } else if (type_reference.data_type == string_type.data_type) {
+ return new CCodeIdentifier (name = "g_value_set_string");
+ } else if (type_reference.type_name == "int"
+ || type_reference.data_type is Enum) {
+ return new CCodeIdentifier (name = "g_value_set_int");
+ } else if (type_reference.data_type == bool_type.data_type) {
+ return new CCodeIdentifier (name = "g_value_set_boolean");
+ } else {
+ return new CCodeIdentifier (name = "g_value_set_pointer");
+ }
+ }
+
private void add_get_property_function (Class! cl) {
var get_prop = new CCodeFunction (name = "%s_get_property".printf (cl.get_lower_case_cname (null)), return_type = "void");
get_prop.add_parameter (new CCodeFormalParameter (type_name = "GObject *", name = "object"));
var ccall = new CCodeFunctionCall (call = new CCodeIdentifier (name = "%s_get_%s".printf (cl.get_lower_case_cname (null), prop.name)));
ccall.add_argument (new CCodeIdentifier (name = "self"));
var csetcall = new CCodeFunctionCall ();
- if (prop.type_reference.data_type is Class) {
- csetcall.call = new CCodeIdentifier (name = "g_value_set_object");
- } else if (prop.type_reference.type_name == "string") {
- csetcall.call = new CCodeIdentifier (name = "g_value_set_string");
- } else if (prop.type_reference.type_name == "int"
- || prop.type_reference.data_type is Enum) {
- csetcall.call = new CCodeIdentifier (name = "g_value_set_int");
- } else if (prop.type_reference.type_name == "bool") {
- csetcall.call = new CCodeIdentifier (name = "g_value_set_boolean");
- } else {
- csetcall.call = new CCodeIdentifier (name = "g_value_set_pointer");
- }
+ csetcall.call = get_value_setter_function (prop.type_reference);
csetcall.add_argument (new CCodeIdentifier (name = "value"));
csetcall.add_argument (ccall);
ccase.add_statement (new CCodeExpressionStatement (expression = csetcall));
public override void visit_end_method (Method! m) {
current_symbol = current_symbol.parent_symbol;
- if (m.name == "init") {
- return;
- }
-
function = new CCodeFunction (name = m.get_real_cname (), return_type = m.return_type.get_cname ());
CCodeFunctionDeclarator vdeclarator = null;
source_type_member_definition.append (new CCodeComment (text = m.source_reference.comment));
}
source_type_member_definition.append (function);
+
+ if (m.construction) {
+ // declare construction parameter array
+ var cparamsinit = new CCodeFunctionCall (call = new CCodeIdentifier (name = "g_new0"));
+ cparamsinit.add_argument (new CCodeIdentifier (name = "GParameter"));
+ cparamsinit.add_argument (new CCodeConstant (name = m.n_construction_params.to_string ()));
+
+ var cdecl = new CCodeDeclaration (type_name = "GParameter *");
+ cdecl.add_declarator (new CCodeVariableDeclarator (name = "__params", initializer = cparamsinit));
+ cinit.append (cdecl);
+
+ cdecl = new CCodeDeclaration (type_name = "GParameter *");
+ cdecl.add_declarator (new CCodeVariableDeclarator (name = "__params_it", initializer = new CCodeIdentifier (name = "__params")));
+ cinit.append (cdecl);
+ }
}
}
source_type_member_definition.append (vfunc);
}
- if (m.name == "main") {
+ if (m.construction) {
+ var creturn = new CCodeReturnStatement ();
+ creturn.return_expression = new CCodeIdentifier (name = "self");
+ function.block.add_statement (creturn);
+ }
+
+ if (m.name != null && m.name == "main") {
var cmain = new CCodeFunction (name = "main", return_type = "int");
cmain.add_parameter (new CCodeFormalParameter (type_name = "int", name = "argc"));
cmain.add_parameter (new CCodeFormalParameter (type_name = "char **", name = "argv"));
this_type.data_type = cl;
var cparam = new CCodeFormalParameter (type_name = this_type.get_cname (), name = "self");
function.add_parameter (cparam);
- if (acc.writable || acc.construct_) {
+ if (acc.writable || acc.construction) {
function.add_parameter (new CCodeFormalParameter (type_name = prop.type_reference.get_cname (), name = "value"));
}
public override void visit_begin_block (Block! b) {
current_symbol = b.symbol;
}
+
+ private void add_object_creation (CCodeBlock! b) {
+ var cl = (Class) current_type_symbol.node;
+
+ var ccall = new CCodeFunctionCall (call = new CCodeIdentifier (name = "g_object_newv"));
+ ccall.add_argument (new CCodeConstant (name = cl.get_type_id ()));
+ ccall.add_argument (new CCodeConstant (name = "__params_it - __params"));
+ ccall.add_argument (new CCodeConstant (name = "__params"));
+
+ var cdecl = new CCodeVariableDeclarator (name = "self");
+ cdecl.initializer = ccall;
+
+ var cdeclaration = new CCodeDeclaration (type_name = "%s *".printf (cl.get_cname ()));
+ cdeclaration.add_declarator (cdecl);
+
+ b.add_statement (cdeclaration);
+ }
public override void visit_end_block (Block! b) {
var local_vars = b.get_local_variables ();
foreach (VariableDeclarator decl in local_vars) {
decl.symbol.active = false;
}
+
+ bool in_construction = b.construction;
var cblock = new CCodeBlock ();
foreach (Statement stmt in b.get_statements ()) {
+ if (in_construction && !stmt.construction) {
+ // construction part of construction method ends here
+ add_object_creation (cblock);
+ in_construction = false;
+ }
+
var src = stmt.source_reference;
if (src != null && src.comment != null) {
cblock.add_statement (new CCodeComment (text = src.comment));
}
}
+ if (in_construction) {
+ // construction method doesn't contain non-construction parts
+ add_object_creation (cblock);
+ }
+
if (memory_management) {
foreach (VariableDeclarator decl in local_vars) {
if (decl.type_reference.data_type.is_reference_type () && decl.type_reference.takes_ownership) {
}
}
- public override void visit_object_creation_expression (ObjectCreationExpression! expr) {
- if (expr.type_reference.data_type is Class) {
- var ccall = new CCodeFunctionCall (call = new CCodeIdentifier (name = "g_object_new"));
-
- ccall.add_argument (new CCodeConstant (name = expr.type_reference.data_type.get_upper_case_cname ("TYPE_")));
+ public override void visit_end_object_creation_expression (ObjectCreationExpression! expr) {
+ if (expr.symbol_reference == null) {
+ // no construction method
+ if (expr.type_reference.data_type is Class) {
+ var ccall = new CCodeFunctionCall (call = new CCodeIdentifier (name = "g_object_new"));
+
+ ccall.add_argument (new CCodeConstant (name = expr.type_reference.data_type.get_type_id ()));
- foreach (NamedArgument arg in expr.named_argument_list) {
- ccall.add_argument (new CCodeConstant (name = "\"%s\"".printf (arg.name)));
- ccall.add_argument ((CCodeExpression) arg.argument.ccodenode);
+ ccall.add_argument (new CCodeConstant (name = "NULL"));
+
+ expr.ccodenode = ccall;
+ } else {
+ var ccall = new CCodeFunctionCall (call = new CCodeIdentifier (name = "g_new0"));
+
+ ccall.add_argument (new CCodeConstant (name = expr.type_reference.data_type.get_cname ()));
+
+ ccall.add_argument (new CCodeConstant (name = "1"));
+
+ expr.ccodenode = ccall;
}
- ccall.add_argument (new CCodeConstant (name = "NULL"));
-
- expr.ccodenode = ccall;
} else {
- var ccall = new CCodeFunctionCall (call = new CCodeIdentifier (name = "g_new0"));
+ // use construction method
+ var m = (Method) expr.symbol_reference.node;
+ var params = m.get_parameters ();
+
+ var ccall = new CCodeFunctionCall (call = new CCodeIdentifier (name = m.get_cname ()));
+
+ var i = 1;
+ foreach (Expression arg in expr.get_argument_list ()) {
+ /* explicitly use strong reference as ccall gets
+ * unrefed at end of inner block
+ */
+ ref CCodeExpression cexpr = (CCodeExpression) arg.ccodenode;
+ if (params != null) {
+ var param = (FormalParameter) params.data;
+ if (!param.ellipsis
+ && param.type_reference.data_type != null
+ && param.type_reference.data_type.is_reference_type ()
+ && arg.static_type.data_type != null
+ && param.type_reference.data_type != arg.static_type.data_type) {
+ var ccall = new CCodeFunctionCall (call = new CCodeIdentifier (name = param.type_reference.data_type.get_upper_case_cname (null)));
+ ccall.add_argument (cexpr);
+ cexpr = ccall;
+ }
+ }
+
+ ccall.add_argument (cexpr);
+ i++;
+
+ if (params != null) {
+ params = params.next;
+ }
+ }
+ while (params != null) {
+ var param = (FormalParameter) params.data;
+
+ if (param.ellipsis) {
+ break;
+ }
+
+ if (param.default_expression == null) {
+ Report.error (expr.source_reference, "no default expression for argument %d".printf (i));
+ return;
+ }
+
+ /* evaluate default expression here as the code
+ * generator might not have visited the formal
+ * parameter yet */
+ param.default_expression.accept (this);
- ccall.add_argument (new CCodeConstant (name = expr.type_reference.data_type.get_cname ()));
+ ccall.add_argument ((CCodeExpression) param.default_expression.ccodenode);
+ i++;
- ccall.add_argument (new CCodeConstant (name = "1"));
+ params = params.next;
+ }
expr.ccodenode = ccall;
}
if (a.left.symbol_reference.node is Property) {
var prop = (Property) a.left.symbol_reference.node;
var cl = (Class) prop.symbol.parent_symbol.node;
-
- var set_func = "g_object_set";
- if (!prop.no_accessor_method) {
- set_func = "%s_set_%s".printf (cl.get_lower_case_cname (null), prop.name);
- }
-
- var ccall = new CCodeFunctionCall (call = new CCodeIdentifier (name = set_func));
+ if (ma.inner == null && a.parent_node is Statement &&
+ ((Statement) a.parent_node).construction) {
+ // this property is used as a construction parameter
+ var cpointer = new CCodeIdentifier (name = "__params_it");
+
+ var ccomma = new CCodeCommaExpression ();
+ // set name in array for current parameter
+ var cnamemember = new CCodeMemberAccess (inner = cpointer, member_name = "name", is_pointer = true);
+ var cnameassign = new CCodeAssignment (left = cnamemember, right = prop.get_canonical_cconstant ());
+ ccomma.append_expression (cnameassign);
+
+ var gvaluearg = new CCodeUnaryExpression (operator = CCodeUnaryOperator.ADDRESS_OF, inner = new CCodeMemberAccess (inner = cpointer, member_name = "value", is_pointer = true));
+
+ // initialize GValue in array for current parameter
+ var cvalueinit = new CCodeFunctionCall (call = new CCodeIdentifier (name = "g_value_init"));
+ cvalueinit.add_argument (gvaluearg);
+ cvalueinit.add_argument (new CCodeIdentifier (name = prop.type_reference.data_type.get_type_id ()));
+ ccomma.append_expression (cvalueinit);
+
+ // set GValue for current parameter
+ var cvalueset = new CCodeFunctionCall (call = get_value_setter_function (prop.type_reference));
+ cvalueset.add_argument (gvaluearg);
+ cvalueset.add_argument ((CCodeExpression) a.right.ccodenode);
+ ccomma.append_expression (cvalueset);
+
+ // move pointer to next parameter in array
+ ccomma.append_expression (new CCodeUnaryExpression (operator = CCodeUnaryOperator.POSTFIX_INCREMENT, inner = cpointer));
+
+ a.ccodenode = ccomma;
+ } else {
+ var set_func = "g_object_set";
+
+ if (!prop.no_accessor_method) {
+ set_func = "%s_set_%s".printf (cl.get_lower_case_cname (null), prop.name);
+ }
+
+ var ccall = new CCodeFunctionCall (call = new CCodeIdentifier (name = set_func));
- /* target instance is first argument */
- ref CCodeExpression instance;
- var req_cast = false;
+ /* target instance is first argument */
+ ref CCodeExpression instance;
+ var req_cast = false;
- if (ma.inner == null) {
- instance = new CCodeIdentifier (name = "self");
- /* require casts for inherited properties */
- req_cast = (prop.symbol.parent_symbol != current_type_symbol);
- } else {
- instance = (CCodeExpression) ma.inner.ccodenode;
- /* require casts if the type of the used instance is
- * different than the type which declared the property */
- req_cast = prop.symbol.parent_symbol.node != ma.inner.static_type.data_type;
- }
-
- if (req_cast && ((DataType) prop.symbol.parent_symbol.node).is_reference_type ()) {
- var ccast = new CCodeFunctionCall (call = new CCodeIdentifier (name = ((DataType) prop.symbol.parent_symbol.node).get_upper_case_cname (null)));
- ccast.add_argument (instance);
- instance = ccast;
- }
+ if (ma.inner == null) {
+ instance = new CCodeIdentifier (name = "self");
+ /* require casts for inherited properties */
+ req_cast = (prop.symbol.parent_symbol != current_type_symbol);
+ } else {
+ instance = (CCodeExpression) ma.inner.ccodenode;
+ /* require casts if the type of the used instance is
+ * different than the type which declared the property */
+ req_cast = prop.symbol.parent_symbol.node != ma.inner.static_type.data_type;
+ }
+
+ if (req_cast && ((DataType) prop.symbol.parent_symbol.node).is_reference_type ()) {
+ var ccast = new CCodeFunctionCall (call = new CCodeIdentifier (name = ((DataType) prop.symbol.parent_symbol.node).get_upper_case_cname (null)));
+ ccast.add_argument (instance);
+ instance = ccast;
+ }
- ccall.add_argument (instance);
+ ccall.add_argument (instance);
+
+ ref CCodeExpression cexpr = (CCodeExpression) a.right.ccodenode;
- ref CCodeExpression cexpr = (CCodeExpression) a.right.ccodenode;
-
- if (prop.no_accessor_method) {
- /* property name is second argument of g_object_set */
- ccall.add_argument (prop.get_canonical_cconstant ());
- } else if (prop.type_reference.data_type != null
- && prop.type_reference.data_type.is_reference_type ()
- && a.right.static_type.data_type != null
- && prop.type_reference.data_type != a.right.static_type.data_type) {
- /* cast is necessary */
- var ccast = new CCodeFunctionCall (call = new CCodeIdentifier (name = prop.type_reference.data_type.get_upper_case_cname (null)));
- ccast.add_argument (cexpr);
- cexpr = ccast;
- }
+ if (prop.no_accessor_method) {
+ /* property name is second argument of g_object_set */
+ ccall.add_argument (prop.get_canonical_cconstant ());
+ } else if (prop.type_reference.data_type != null
+ && prop.type_reference.data_type.is_reference_type ()
+ && a.right.static_type.data_type != null
+ && prop.type_reference.data_type != a.right.static_type.data_type) {
+ /* cast is necessary */
+ var ccast = new CCodeFunctionCall (call = new CCodeIdentifier (name = prop.type_reference.data_type.get_upper_case_cname (null)));
+ ccast.add_argument (cexpr);
+ cexpr = ccast;
+ }
+
+ ccall.add_argument (cexpr);
- ccall.add_argument (cexpr);
-
- if (prop.no_accessor_method) {
- ccall.add_argument (new CCodeConstant (name = "NULL"));
+ if (prop.no_accessor_method) {
+ ccall.add_argument (new CCodeConstant (name = "NULL"));
+ }
+
+ a.ccodenode = ccall;
}
-
- a.ccodenode = ccall;
} else if (a.left.symbol_reference.node is Signal) {
var sig = (Signal) a.left.symbol_reference.node;
*/
public abstract class Vala.CodeNode {
/**
+ * Parent of this code node.
+ */
+ public CodeNode parent_node { get; set; }
+
+ /**
* Symbol that corresponds to this code node.
*/
public Symbol symbol { get; set; }
}
/**
- * Visit operation called for object creation expressions.
+ * Visit operation called at beginning of object creation
+ * expressions.
*
* @param expr an object creation expression
*/
- public virtual void visit_object_creation_expression (ObjectCreationExpression! expr) {
+ public virtual void visit_begin_object_creation_expression (ObjectCreationExpression! expr) {
+ }
+
+ /**
+ * Visit operation called at end of object creation expressions.
+ *
+ * @param expr an object creation expression
+ */
+ public virtual void visit_end_object_creation_expression (ObjectCreationExpression! expr) {
}
/**
}
}
}
+
+ public override string get_type_id () {
+ // FIXME: use GType-registered enums
+ return "G_TYPE_INT";
+ }
}
* The code generator sets and uses them for memory management.
*/
public List<VariableDeclarator> temp_vars;
+
+ public abstract ref string! to_string ();
}
visitor.visit_expression_statement (this);
}
+
+ public override int get_number_of_set_construction_parameters () {
+ if (expression is Assignment) {
+ var assign = (Assignment) expression;
+ if (assign.left is MemberAccess) {
+ var ma = (MemberAccess) assign.left;
+ if (ma.symbol_reference != null) {
+ if (ma.symbol_reference.node is Property) {
+ var prop = (Property) ma.symbol_reference.node;
+ return 1;
+ }
+ }
+ }
+ }
+
+ return -1;
+ }
}
public override void accept (CodeVisitor! visitor) {
if (!ellipsis) {
type_reference.accept (visitor);
+
+ if (default_expression != null) {
+ default_expression.accept (visitor);
+ }
}
visitor.visit_formal_parameter (this);
/**
* The statement to be evaluated if the condition holds.
*/
- public Statement! true_statement { get; set construct; }
+ public Block! true_statement { get; set construct; }
/**
* The optional statement to be evaluated if the condition doesn't hold.
*/
- public Statement false_statement { get; set construct; }
+ public Block false_statement { get; set construct; }
/**
* Creates a new if statement.
* @param false_stmt statement to be evaluated if condition is false
* @return newly created if statement
*/
- public static ref IfStatement! new (Expression! cond, Statement! true_stmt, Statement false_stmt, SourceReference source) {
+ public static ref IfStatement! new (Expression! cond, Block! true_stmt, Block false_stmt, SourceReference source) {
return (new IfStatement (condition = cond, true_statement = true_stmt, false_statement = false_stmt, source_reference = source));
}
public override void accept (CodeVisitor! visitor) {
visitor.visit_integer_literal (this);
}
+
+ public override ref string! to_string () {
+ return value;
+ }
}
write_indent ();
write_string ("public ");
- if (!m.instance) {
+ if (m.construction) {
+ write_string ("construct ");
+ } else if (!m.instance) {
write_string ("static ");
} else if (m.is_abstract) {
write_string ("abstract ");
write_string ("virtual ");
}
- var type = m.return_type.data_type;
- if (type == null) {
- write_string ("void");
- } else {
- if (m.return_type.transfers_ownership) {
- write_string ("ref ");
+ if (!m.construction) {
+ var type = m.return_type.data_type;
+ if (type == null) {
+ write_string ("void");
+ } else {
+ if (m.return_type.transfers_ownership) {
+ write_string ("ref ");
+ }
+ write_string (m.return_type.data_type.symbol.get_full_name ());
}
- write_string (m.return_type.data_type.symbol.get_full_name ());
}
- write_string (" ");
- write_identifier (m.name);
+ if (m.name != null) {
+ write_string (" ");
+ write_identifier (m.name);
+ }
+
write_string (" (");
bool first = true;
write_string (" ");
write_identifier (param.name);
+
+ if (param.default_expression != null) {
+ write_string (" = ");
+ write_string (param.default_expression.to_string ());
+ }
}
write_string (");");
if (prop.set_accessor.writable) {
write_string (" set");
}
- if (prop.set_accessor.construct_) {
+ if (prop.set_accessor.construction) {
write_string (" construct");
}
write_string (";");
* Specifies the type of this literal.
*/
public TypeReference static_type { get; set; }
+
+ public abstract ref string! to_string ();
}
visitor.visit_literal_expression (this);
}
+
+ public override ref string! to_string () {
+ return literal.to_string ();
+ }
}
* The name of the member.
*/
public string! member_name { get; set construct; }
+
+ private List<TypeReference> type_argument_list;
/**
* Creates a new member access expression.
return new MemberAccess (inner = inner, member_name = member, source_reference = source);
}
+ /**
+ * Appends the specified type as generic type argument.
+ *
+ * @param arg a type reference
+ */
+ public void add_type_argument (TypeReference! arg) {
+ type_argument_list.append (arg);
+ }
+
+ /**
+ * Returns a copy of the list of generic type arguments.
+ *
+ * @return type argument list
+ */
+ public ref List<TypeReference> get_type_arguments () {
+ return type_argument_list.copy ();
+ }
+
public override void accept (CodeVisitor! visitor) {
if (inner != null) {
inner.accept (visitor);
visitor.visit_member_access (this);
}
+
+ public override ref string! to_string () {
+ if (inner == null) {
+ return member_name;
+ } else {
+ return "%s.%s".printf (inner.to_string (), member_name);
+ }
+ }
}
/**
* The symbol name of this method.
*/
- public string! name { get; set construct; }
+ public string name { get; set; }
/**
* The return type of this method.
*/
- public TypeReference! return_type { get; set construct; }
+ public TypeReference return_type { get; set; }
- public Statement body { get; set; }
+ public Block body { get; set; }
/**
* Specifies the accessibility of this method. Public accessibility
* of a base type.
*/
public bool overrides { get; set; }
+
+ /**
+ * Specifies whether this is a construction method.
+ */
+ public bool construction { get; set; }
+
+ /**
+ * Specifies the number of parameters this construction method sets.
+ */
+ public int n_construction_params { get; set; }
/**
* Specifies whether the C method returns a new instance pointer which
* @param source reference to source code
* @return newly created method
*/
- public static ref Method! new (string! name, TypeReference! return_type, SourceReference source) {
+ public static ref Method! new (string name, TypeReference return_type, SourceReference source) {
return (new Method (name = name, return_type = return_type, source_reference = source));
}
public override void accept (CodeVisitor! visitor) {
visitor.visit_begin_method (this);
- return_type.accept (visitor);
+ if (return_type != null) {
+ return_type.accept (visitor);
+ }
foreach (FormalParameter param in parameters) {
param.accept (visitor);
if (cname == null) {
var parent = symbol.parent_symbol.node;
if (parent is DataType) {
- cname = "%s_%s".printf (((DataType) parent).get_lower_case_cname (null), name);
+ if (construction) {
+ if (name == null) {
+ cname = "%s_new".printf (((DataType) parent).get_lower_case_cname (null));
+ } else {
+ cname = "%s_new_%s".printf (((DataType) parent).get_lower_case_cname (null), name);
+ }
+ } else {
+ cname = "%s_%s".printf (((DataType) parent).get_lower_case_cname (null), name);
+ }
} else if (parent is Namespace) {
cname = "%s%s".printf (((Namespace) parent).get_lower_case_cprefix (), name);
} else {
using GLib;
-namespace Vala {
- public class NullLiteral : Literal {
- public static ref NullLiteral! new (SourceReference source) {
- return (new NullLiteral (source_reference = source));
- }
-
- public override void accept (CodeVisitor! visitor) {
- visitor.visit_null_literal (this);
- }
+/**
+ * Represents a literal `null' in the source code.
+ */
+public class Vala.NullLiteral : Literal {
+ /**
+ * Creates a new null literal.
+ *
+ * @param source reference to source code
+ * @return newly created null literal
+ */
+ public static ref NullLiteral! new (SourceReference source) {
+ return (new NullLiteral (source_reference = source));
+ }
+
+ public override void accept (CodeVisitor! visitor) {
+ visitor.visit_null_literal (this);
+ }
+
+ public override ref string! to_string () {
+ return "null";
}
}
using GLib;
-namespace Vala {
- public class ObjectCreationExpression : Expression {
- public TypeReference type_reference { get; construct; }
- public List<NamedArgument> named_argument_list { get; construct; }
+/**
+ * Represents an object creation expression in the source code.
+ */
+public class Vala.ObjectCreationExpression : Expression {
+ /**
+ * The object type to create.
+ */
+ public TypeReference type_reference { get; set; }
- public static ref ObjectCreationExpression new (TypeReference type, List<NamedArgument> named_argument_list, SourceReference source) {
- return (new ObjectCreationExpression (type_reference = type, named_argument_list = named_argument_list, source_reference = source));
- }
-
- public override void accept (CodeVisitor! visitor) {
+ /**
+ * The construction method to use. May be null to indicate that
+ * the default construction method should be used.
+ */
+ public Method constructor { get; set; }
+
+ /**
+ * The construction method to use or the data type to be created
+ * with the default construction method.
+ */
+ public MemberAccess member_name { get; set; }
+
+ private List<Expression> argument_list;
+
+ /**
+ * Creates a new object creation expression.
+ *
+ * @param type object type to create
+ * @param source reference to source code
+ * @return newly created object creation expression
+ */
+ public static ref ObjectCreationExpression! new (MemberAccess! name, SourceReference source) {
+ return (new ObjectCreationExpression (member_name = name, source_reference = source));
+ }
+
+ /**
+ * Appends the specified expression to the list of arguments.
+ *
+ * @param arg an argument
+ */
+ public void add_argument (Expression! arg) {
+ argument_list.append (arg);
+ }
+
+ /**
+ * Returns a copy of the argument list.
+ *
+ * @return argument list
+ */
+ public ref List<Expression> get_argument_list () {
+ return argument_list.copy ();
+ }
+
+ public override void accept (CodeVisitor! visitor) {
+ if (type_reference != null) {
type_reference.accept (visitor);
-
- foreach (NamedArgument arg in named_argument_list) {
- arg.accept (visitor);
- }
+ }
+
+ if (member_name != null) {
+ member_name.accept (visitor);
+ }
- visitor.visit_object_creation_expression (this);
+ visitor.visit_begin_object_creation_expression (this);
+
+ foreach (Expression arg in argument_list) {
+ arg.accept (visitor);
}
+
+ visitor.visit_end_object_creation_expression (this);
}
}
using GLib;
-namespace Vala {
- public class Property : CodeNode {
- public string name { get; construct; }
- public TypeReference type_reference { get; construct; }
- public PropertyAccessor get_accessor { get; construct; }
- public PropertyAccessor set_accessor { get; construct; }
- public MemberAccessibility access;
- public FormalParameter this_parameter;
- public bool no_accessor_method;
-
- public static ref Property new (string name, TypeReference type, PropertyAccessor get_accessor, PropertyAccessor set_accessor, SourceReference source) {
- return (new Property (name = name, type_reference = type, get_accessor = get_accessor, set_accessor = set_accessor, source_reference = source));
- }
-
- public override void accept (CodeVisitor! visitor) {
- visitor.visit_begin_property (this);
+/**
+ * Represents a property declaration in the source code.
+ */
+public class Vala.Property : CodeNode {
+ /**
+ * The property name.
+ */
+ public string! name { get; set construct; }
+
+ /**
+ * The property type.
+ */
+ public TypeReference! type_reference { get; set construct; }
+
+ /**
+ * The get accessor of this property if available.
+ */
+ public PropertyAccessor get_accessor { get; set; }
+
+ /**
+ * The set/construct accessor of this property if available.
+ */
+ public PropertyAccessor set_accessor { get; set; }
+
+ /**
+ * Specifies the accessibility of this property. Public accessibility
+ * doesn't limit access. Default accessibility limits access to this
+ * program or library. Private accessibility limits access to the parent
+ * class.
+ */
+ public MemberAccessibility access { get; set; }
+
+ /**
+ * Represents the generated ´this' parameter in this property.
+ */
+ public FormalParameter this_parameter { get; set; }
+
+ /**
+ * Specifies whether the implementation of this property does not
+ * provide getter/setter methods.
+ */
+ public bool no_accessor_method { get; set; }
+
+ /**
+ * Creates a new property.
+ *
+ * @param name property name
+ * @param type property type
+ * @param get_accessor get accessor
+ * @param set_accessor set/construct accessor
+ * @param source reference to source code
+ * @return newly created property
+ */
+ public static ref Property! new (string! name, TypeReference! type, PropertyAccessor get_accessor, PropertyAccessor set_accessor, SourceReference source) {
+ return (new Property (name = name, type_reference = type, get_accessor = get_accessor, set_accessor = set_accessor, source_reference = source));
+ }
+
+ public override void accept (CodeVisitor! visitor) {
+ visitor.visit_begin_property (this);
- type_reference.accept (visitor);
-
- if (get_accessor != null) {
- get_accessor.accept (visitor);
- }
- if (set_accessor != null) {
- set_accessor.accept (visitor);
- }
+ type_reference.accept (visitor);
- visitor.visit_end_property (this);
+ if (get_accessor != null) {
+ get_accessor.accept (visitor);
}
-
- public ref string get_upper_case_cname () {
- return "%s_%s".printf (((Class) symbol.parent_symbol.node).get_lower_case_cname (null), Namespace.camel_case_to_lower_case (name)).up ();
+ if (set_accessor != null) {
+ set_accessor.accept (visitor);
}
+
+ visitor.visit_end_property (this);
+ }
+
+ /**
+ * Returns the C name of this property in upper case. Words are
+ * separated by underscores. The upper case C name of the class is
+ * prefix of the result.
+ *
+ * @return the upper case name to be used in C code
+ */
+ public ref string! get_upper_case_cname () {
+ return "%s_%s".printf (((Class) symbol.parent_symbol.node).get_lower_case_cname (null), Namespace.camel_case_to_lower_case (name)).up ();
+ }
+
+ /**
+ * Returns the string literal of this property to be used in C code.
+ *
+ * @return string literal to be used in C code
+ */
+ public ref CCodeConstant! get_canonical_cconstant () {
+ var str = String.new ("\"");
- public ref CCodeConstant get_canonical_cconstant () {
- var str = String.new ("\"");
-
- string i = name;
-
- while (i.len () > 0) {
- unichar c = i.get_char ();
- if (c == '_') {
- str.append_c ('-');
- } else {
- str.append_unichar (c);
- }
-
- i = i.next_char ();
+ string i = name;
+
+ while (i.len () > 0) {
+ unichar c = i.get_char ();
+ if (c == '_') {
+ str.append_c ('-');
+ } else {
+ str.append_unichar (c);
}
- str.append_c ('"');
-
- return new CCodeConstant (name = str.str);
+ i = i.next_char ();
}
- public void process_attributes () {
- foreach (Attribute a in attributes) {
- if (a.name == "NoAccessorMethod") {
- no_accessor_method = true;
- }
+ str.append_c ('"');
+
+ return new CCodeConstant (name = str.str);
+ }
+
+ /**
+ * Process all associated attributes.
+ */
+ public void process_attributes () {
+ foreach (Attribute a in attributes) {
+ if (a.name == "NoAccessorMethod") {
+ no_accessor_method = true;
}
}
}
using GLib;
-namespace Vala {
- public class PropertyAccessor : CodeNode {
- public bool readable { get; construct; }
- public bool writable { get; construct; }
- public bool construct_ { get; construct; }
- public Statement body { get; construct; }
- public FormalParameter value_parameter;
-
- public static ref PropertyAccessor new (bool readable, bool writable, bool construct_, Statement body, SourceReference source) {
- return (new PropertyAccessor (readable = readable, writable = writable, construct_ = construct_, body = body, source_reference = source));
- }
-
- public override void accept (CodeVisitor! visitor) {
- visitor.visit_begin_property_accessor (this);
+/**
+ * Represents a get or set accessor of a property in the source code.
+ */
+public class Vala.PropertyAccessor : CodeNode {
+ /**
+ * Specifies whether this accessor may be used to get the property.
+ */
+ public bool readable { get; set; }
+
+ /**
+ * Specifies whether this accessor may be used to set the property.
+ */
+ public bool writable { get; set; }
+
+ /**
+ * Specifies whether this accessor may be used to construct the
+ * property.
+ */
+ public bool construction { get; set; }
+
+ /**
+ * The accessor body.
+ */
+ public Statement body { get; set; }
+
+ /**
+ * Represents the generated value parameter in a set accessor.
+ */
+ public FormalParameter value_parameter { get; set; }
+
+ /**
+ * Creates a new property accessor.
+ *
+ * @param readable true if get accessor, false otherwise
+ * @param writable true if set accessor, false otherwise
+ * @param construction true if construct accessor, false otherwise
+ * @param body accessor body
+ * @param source reference to source code
+ * @return newly created property accessor
+ */
+ public static ref PropertyAccessor! new (bool readable, bool writable, bool construction, Statement body, SourceReference source) {
+ return (new PropertyAccessor (readable = readable, writable = writable, construction = construction, body = body, source_reference = source));
+ }
+
+ public override void accept (CodeVisitor! visitor) {
+ visitor.visit_begin_property_accessor (this);
- if (body != null) {
- body.accept (visitor);
- }
-
- visitor.visit_end_property_accessor (this);
+ if (body != null) {
+ body.accept (visitor);
}
+
+ visitor.visit_end_property_accessor (this);
}
}
}
public override void visit_begin_method (Method! m) {
+ if (m.construction) {
+ m.return_type = new TypeReference ();
+ m.return_type.data_type = (DataType) current_symbol.node;
+ m.return_type.transfers_ownership = true;
+
+ if (m.body != null) {
+ m.body.construction = true;
+ }
+ }
+
current_symbol = m.symbol;
current_return_type = m.return_type;
return;
}
}
+
+ if (m.construction && m.body != null) {
+ int n_params = 0;
+ foreach (Statement stmt in m.body.get_statements ()) {
+ int params = stmt.get_number_of_set_construction_parameters ();
+ if (params == -1) {
+ break;
+ }
+ n_params += params;
+ stmt.construction = true;
+ }
+ m.n_construction_params = n_params;
+ }
}
public override void visit_formal_parameter (FormalParameter! p) {
}
}
}
-
- public override void visit_end_invocation_expression (InvocationExpression! expr) {
- if (expr.error) {
- return;
- }
-
- var msym = expr.call.symbol_reference;
-
- TypeReference ret_type;
- List<FormalParameter> params;
-
- if (msym.node is VariableDeclarator) {
- var decl = (VariableDeclarator) msym.node;
- var cb = (Callback) decl.type_reference.data_type;
- ret_type = cb.return_type;
- params = cb.get_parameters ();
- } else if (msym.node is FormalParameter) {
- var param = (FormalParameter) msym.node;
- var cb = (Callback) param.type_reference.data_type;
- ret_type = cb.return_type;
- params = cb.get_parameters ();
- } else if (msym.node is Field) {
- var f = (Field) msym.node;
- var cb = (Callback) f.type_reference.data_type;
- ret_type = cb.return_type;
- params = cb.get_parameters ();
- } else if (msym.node is Method) {
- var m = (Method) msym.node;
- ret_type = m.return_type;
- params = m.get_parameters ();
- } else if (msym.node is Signal) {
- var sig = (Signal) msym.node;
- ret_type = sig.return_type;
- params = sig.get_parameters ();
- }
- expr.static_type = ret_type;
-
- var args = expr.get_argument_list ();
+ private bool check_arguments (Expression! expr, Symbol! msym, List<FormalParameter> params, List<Expression> args) {
List arg_it = args;
bool ellipsis = false;
if (arg_it == null) {
if (param.default_expression == null) {
+ expr.error = true;
Report.error (expr.source_reference, "Too few arguments, method `%s' does not take %d arguments".printf (msym.get_full_name (), args.length ()));
- return;
+ return false;
}
} else {
var arg = (Expression) arg_it.data;
if (arg.static_type != null && !is_type_compatible (arg.static_type, param.type_reference)) {
/* if there was an error in the argument,
* i.e. arg.static_type == null, skip type check */
+ expr.error = true;
Report.error (expr.source_reference, "Argument %d: Cannot convert from `%s' to `%s'".printf (i + 1, arg.static_type.to_string (), param.type_reference.to_string ()));
- return;
+ return false;
}
arg_it = arg_it.next;
}
if (!ellipsis && arg_it != null) {
+ expr.error = true;
Report.error (expr.source_reference, "Too many arguments, method `%s' does not take %d arguments".printf (msym.get_full_name (), args.length ()));
+ return false;
+ }
+
+ return true;
+ }
+
+ public override void visit_end_invocation_expression (InvocationExpression! expr) {
+ if (expr.error) {
return;
}
+
+ var msym = expr.call.symbol_reference;
+
+ TypeReference ret_type;
+ List<FormalParameter> params;
+
+ if (msym.node is VariableDeclarator) {
+ var decl = (VariableDeclarator) msym.node;
+ var cb = (Callback) decl.type_reference.data_type;
+ ret_type = cb.return_type;
+ params = cb.get_parameters ();
+ } else if (msym.node is FormalParameter) {
+ var param = (FormalParameter) msym.node;
+ var cb = (Callback) param.type_reference.data_type;
+ ret_type = cb.return_type;
+ params = cb.get_parameters ();
+ } else if (msym.node is Field) {
+ var f = (Field) msym.node;
+ var cb = (Callback) f.type_reference.data_type;
+ ret_type = cb.return_type;
+ params = cb.get_parameters ();
+ } else if (msym.node is Method) {
+ var m = (Method) msym.node;
+ ret_type = m.return_type;
+ params = m.get_parameters ();
+ } else if (msym.node is Signal) {
+ var sig = (Signal) msym.node;
+ ret_type = sig.return_type;
+ params = sig.get_parameters ();
+ }
+
+ expr.static_type = ret_type;
+
+ check_arguments (expr, msym, params, expr.get_argument_list ());
}
public override void visit_element_access (ElementAccess! expr) {
expr.static_type = expr.inner.static_type;
}
- public override void visit_object_creation_expression (ObjectCreationExpression! expr) {
- if (expr.type_reference.data_type == null) {
- /* if type resolving didn't succeed, skip this check */
- return;
- }
+ public override void visit_end_object_creation_expression (ObjectCreationExpression! expr) {
+ DataType type = null;
- if (!expr.type_reference.data_type.is_reference_type ()) {
+ if (expr.type_reference == null) {
+ if (expr.member_name == null) {
+ expr.error = true;
+ Report.error (expr.source_reference, "Incomplete object creation expression");
+ return;
+ }
+
+ if (expr.member_name.symbol_reference == null) {
+ expr.error = true;
+ return;
+ }
+
+ var constructor_node = expr.member_name.symbol_reference.node;
+ var type_node = expr.member_name.symbol_reference.node;
+
+ if (constructor_node is Method) {
+ type_node = constructor_node.symbol.parent_symbol.node;
+
+ var constructor = (Method) constructor_node;
+ if (!constructor.construction) {
+ expr.error = true;
+ Report.error (expr.source_reference, "`%s' is not a construction method".printf (constructor.symbol.get_full_name ()));
+ return;
+ }
+
+ expr.symbol_reference = constructor.symbol;
+ }
+
+ if (type_node is Class || type_node is Struct) {
+ type = (DataType) type_node;
+ } else {
+ expr.error = true;
+ Report.error (expr.source_reference, "`%s' is not a class or struct".printf (type.symbol.get_full_name ()));
+ return;
+ }
+ }
+
+ if (!type.is_reference_type ()) {
expr.error = true;
Report.error (expr.source_reference, "Can't create instance of value type `%s'".printf (expr.type_reference.to_string ()));
return;
}
- current_source_file.add_symbol_dependency (expr.type_reference.data_type.symbol, SourceFileDependencyType.SOURCE);
+ current_source_file.add_symbol_dependency (type.symbol, SourceFileDependencyType.SOURCE);
+
+ expr.type_reference = new TypeReference ();
+ expr.type_reference.data_type = type;
expr.static_type = expr.type_reference.copy ();
expr.static_type.transfers_ownership = true;
- if (expr.type_reference.data_type is Class) {
- var cl = (Class) expr.type_reference.data_type;
+ if (type is Class) {
+ var cl = (Class) type;
if (cl.is_abstract) {
expr.static_type = null;
expr.error = true;
- Report.error (expr.source_reference, "Can't create instance of abstract class `%s'".printf (expr.type_reference.to_string ()));
+ Report.error (expr.source_reference, "Can't create instance of abstract class `%s'".printf (cl.symbol.get_full_name ()));
return;
}
+ if (expr.symbol_reference == null && cl.default_construction_method != null) {
+ expr.symbol_reference = cl.default_construction_method.symbol;
+ }
+
while (cl != null) {
if (cl == initially_unowned_type) {
expr.static_type.floating_reference = true;
cl = cl.base_class;
}
- } else if (expr.named_argument_list.length () != 0) {
+ } else if (type is Struct) {
+ var st = (Struct) type;
+
+ if (expr.symbol_reference == null && st.default_construction_method != null) {
+ expr.symbol_reference = st.default_construction_method.symbol;
+ }
+ }
+
+ if (expr.symbol_reference == null && expr.get_argument_list ().length () != 0) {
expr.static_type = null;
expr.error = true;
- Report.error (expr.source_reference, "No arguments allowed when constructing struct `%s'".printf (expr.type_reference.to_string ()));
+ Report.error (expr.source_reference, "No arguments allowed when constructing type `%s'".printf (type.symbol.get_full_name ()));
return;
}
+
+ if (expr.symbol_reference != null) {
+ var m = (Method) expr.symbol_reference.node;
+ check_arguments (expr, m.symbol, m.get_parameters (), expr.get_argument_list ());
+ }
}
public override void visit_unary_expression (UnaryExpression! expr) {
* Base class for all statement types.
*/
public abstract class Vala.Statement : CodeNode {
+ /**
+ * Specifies whether this statement is in the construction part
+ * of a construction method.
+ */
+ public bool construction { get; set; }
+
+ /**
+ * Returns the number of construction parameters this statement sets in
+ * maximum or -1 if this statement may not be used in the construction
+ * part of a construction method.
+ *
+ * @return number of construction parameters set or -1
+ */
+ public virtual int get_number_of_set_construction_parameters () {
+ return -1;
+ }
}
string marshaller_type_name;
/**
+ * Specifies the default construction method.
+ */
+ public Method default_construction_method { get; set; }
+
+ /**
* Creates a new struct.
*
* @param name type name
current_symbol = current_symbol.parent_symbol;
}
- private Symbol add_symbol (string! name, CodeNode! node) {
- if (current_symbol.lookup (name) != null) {
- node.error = true;
- Report.error (node.source_reference, "`%s' already contains a definition for `%s'".printf (current_symbol.get_full_name (), name));
- return null;
+ private Symbol add_symbol (string name, CodeNode! node) {
+ if (name != null) {
+ if (current_symbol.lookup (name) != null) {
+ node.error = true;
+ Report.error (node.source_reference, "`%s' already contains a definition for `%s'".printf (current_symbol.get_full_name (), name));
+ return null;
+ }
}
node.symbol = new Symbol (node = node);
- current_symbol.add (name, node.symbol);
+ if (name != null) {
+ current_symbol.add (name, node.symbol);
+ } else {
+ node.symbol.parent_symbol = current_symbol;
+ }
return node.symbol;
}
return;
}
- if (m.instance) {
+ if (m.construction) {
+ var type_node = m.symbol.parent_symbol.node;
+ if (!(type_node is Class || type_node is Struct)) {
+ Report.error (m.source_reference, "construction methods may only be declared within classes and structs");
+
+ m.error = true;
+ return;
+ }
+
+ if (m.name == null) {
+ if (type_node is Class) {
+ ((Class) type_node).default_construction_method = m;
+ } else if (type_node is Struct) {
+ ((Struct) type_node).default_construction_method = m;
+ }
+ }
+ } else if (m.instance) {
if (!(m.symbol.parent_symbol.node is DataType)) {
Report.error (m.source_reference, "instance methods not allowed outside of data types");
return;
}
- if (acc.writable || acc.construct_) {
+ if (acc.writable || acc.construction) {
acc.value_parameter = new FormalParameter (name = "value", type_reference = ((Property) current_symbol.parent_symbol.node).type_reference);
acc.value_parameter.symbol = new Symbol (node = acc.value_parameter);
string ns = null;
string type_name = null;
if (expr is MemberAccess) {
+ TypeReference type_ref = null;
+
MemberAccess ma = (MemberAccess) expr;
if (ma.inner != null) {
if (ma.inner is MemberAccess) {
var simple = (MemberAccess) ma.inner;
- return (new TypeReference (namespace_name = simple.member_name, type_name = ma.member_name, source_reference = source));
+ type_ref = new TypeReference (namespace_name = simple.member_name, type_name = ma.member_name, source_reference = source);
}
} else {
- return (new TypeReference (type_name = ma.member_name, source_reference = source));
+ type_ref = new TypeReference (type_name = ma.member_name, source_reference = source);
+ }
+
+ if (type_ref != null) {
+ var type_args = ma.get_type_arguments ();
+ foreach (TypeReference arg in type_args) {
+ type_ref.add_type_argument (arg);
+ }
+
+ return type_ref;
}
}
public abstract class InitiallyUnowned : Object {
}
+ [ReferenceType (free_function = "g_free")]
+ public struct Value {
+ public Object get_object ();
+ }
+
[ReferenceType (dup_function = "g_main_loop_ref", free_function = "g_main_loop_unref")]
public struct MainLoop {
public static ref MainLoop new (MainContext context, bool is_running);
public bool use_markup { get; set; }
}
+ public class ProgressBar : Widget {
+ public void pulse ();
+ }
+
public class StatusIcon {
public static ref StatusIcon! new_from_stock (string! stock_id);
}
public interface TreeModel {
+ public abstract void get_value (ref TreeIter iter, int column, GLib.Value value);
+ }
+
+ public class TreeSelection {
+ public bool get_selected (out TreeModel model, ref TreeIter iter);
+
+ public signal void changed ();
}
public struct TreeIter {
public pointer user_data3;
}
+ [CCode (cprefix = "GTK_TREE_VIEW_COLUMN_")]
+ public enum TreeViewColumnSizing {
+ FIXED
+ }
+
public class TreeViewColumn : Object {
[FloatingReference ()]
public static ref TreeViewColumn new_with_attributes (string title, CellRenderer cell, ...);
+
+ public int fixed_width { get; set; }
+ public TreeViewColumnSizing sizing { get; set; }
}
public class TreeView : Container {
public TreeModel model { get; set; }
+ public TreeSelection get_selection ();
public int append_column (TreeViewColumn column);
}
public static ref VBox new (bool homogeneous, int spacing);
}
+ public class VPaned : Paned {
+ }
+
public class Notebook : Container {
public int append_page (Widget child, Widget tab_label);
}
public signal void destroy ();
}
+ public abstract class Paned : Container {
+ public void pack2 (Widget! child, bool resize, bool shrink);
+ }
+
public abstract class Widget : Object {
public void show ();
public void show_all ();
+ public void hide ();
[NoAccessorMethod ()]
public bool visible { get; set; }