From: Jürg Billeter Date: Mon, 26 Feb 2007 22:18:58 +0000 (+0000) Subject: test postfix and prefix expressions update support prefix and postfix X-Git-Tag: VALA_0_0_6~8 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=f50532e7b35cdcfce6ae30b0ed4599003bd4f547;p=thirdparty%2Fvala.git test postfix and prefix expressions update support prefix and postfix 2007-02-26 Jürg Billeter * tests/test-027.vala, tests/test-027.out: test postfix and prefix expressions * tests/Makefile.am: update * vala/valasemanticanalyzer.vala, vala/valacodegenerator.vala: support prefix and postfix expressions for properties and parenthesized expressions svn path=/trunk/; revision=199 --- diff --git a/vala/ChangeLog b/vala/ChangeLog index 7bd8a3e31..87d663452 100644 --- a/vala/ChangeLog +++ b/vala/ChangeLog @@ -1,3 +1,12 @@ +2007-02-26 Jürg Billeter + + * tests/test-027.vala, tests/test-027.out: test postfix and prefix + expressions + * tests/Makefile.am: update + * vala/valasemanticanalyzer.vala, vala/valacodegenerator.vala: support + prefix and postfix expressions for properties and parenthesized + expressions + 2007-02-25 Jürg Billeter * vala/valasemanticanalyzer.vala, vala/valacodegenerator.vala: improve diff --git a/vala/tests/Makefile.am b/vala/tests/Makefile.am index 182b7121f..ca342fd68 100644 --- a/vala/tests/Makefile.am +++ b/vala/tests/Makefile.am @@ -29,6 +29,7 @@ TESTS = \ test-024.vala \ test-025.vala \ test-026.vala \ + test-027.vala \ $(NULL) EXTRA_DIST = \ @@ -60,4 +61,5 @@ EXTRA_DIST = \ test-024.out \ test-025.out \ test-026.out \ + test-027.out \ $(NULL) diff --git a/vala/tests/test-027.out b/vala/tests/test-027.out new file mode 100644 index 000000000..2d8288039 --- /dev/null +++ b/vala/tests/test-027.out @@ -0,0 +1 @@ +Postfix and Prefix Expression Test: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 diff --git a/vala/tests/test-027.vala b/vala/tests/test-027.vala new file mode 100644 index 000000000..e01bdd482 --- /dev/null +++ b/vala/tests/test-027.vala @@ -0,0 +1,60 @@ +using GLib; + +class Maman.Bar { + public int foo { get; set; } + + public void run () { + /* test with local variable */ + int i = 1; + stdout.printf (" %d", ++i); + + stdout.printf (" %d", i + 1); + + i = 4; + stdout.printf (" %d", i++); + + stdout.printf (" %d", i); + + i = 7; + stdout.printf (" %d", --(i)); + + stdout.printf (" %d", i + 1); + + i = 8; + stdout.printf (" %d", (i)--); + + stdout.printf (" %d", i + 2); + + /* test with field */ + foo = 9; + stdout.printf (" %d", ++foo); + + stdout.printf (" %d", foo + 1); + + foo = 12; + stdout.printf (" %d", foo++); + + stdout.printf (" %d", foo); + + foo = 15; + stdout.printf (" %d", --(foo)); + + stdout.printf (" %d", foo + 1); + + foo = 16; + stdout.printf (" %d", (foo)--); + + stdout.printf (" %d", foo + 2); + } + + static int main (string[] args) { + stdout.printf ("Postfix and Prefix Expression Test: 1"); + + var bar = new Bar (); + bar.run (); + + stdout.printf (" 18\n"); + + return 0; + } +} diff --git a/vala/vala/valacodegenerator.vala b/vala/vala/valacodegenerator.vala index 6ea39a3d1..198d4e51d 100644 --- a/vala/vala/valacodegenerator.vala +++ b/vala/vala/valacodegenerator.vala @@ -3025,6 +3025,31 @@ public class Vala.CodeGenerator : CodeVisitor { } public override void visit_postfix_expression (PostfixExpression! expr) { + MemberAccess ma = find_property_access (expr.inner); + if (ma != null) { + // property postfix expression + var prop = (Property) ma.symbol_reference.node; + + var ccomma = new CCodeCommaExpression (); + + // assign current value to temp variable + var temp_decl = get_temp_variable_declarator (prop.type_reference); + temp_vars.prepend (temp_decl); + ccomma.append_expression (new CCodeAssignment (new CCodeIdentifier (temp_decl.name), (CCodeExpression) expr.inner.ccodenode)); + + // increment/decrement property + var op = expr.increment ? CCodeBinaryOperator.PLUS : CCodeBinaryOperator.MINUS; + var cexpr = new CCodeBinaryExpression (op, new CCodeIdentifier (temp_decl.name), new CCodeConstant ("1")); + var ccall = get_property_set_call (prop, ma, cexpr); + ccomma.append_expression (ccall); + + // return previous value + ccomma.append_expression (new CCodeIdentifier (temp_decl.name)); + + expr.ccodenode = ccomma; + return; + } + var op = expr.increment ? CCodeUnaryOperator.POSTFIX_INCREMENT : CCodeUnaryOperator.POSTFIX_DECREMENT; expr.ccodenode = new CCodeUnaryExpression (op, (CCodeExpression) expr.inner.ccodenode); @@ -3032,6 +3057,24 @@ public class Vala.CodeGenerator : CodeVisitor { visit_expression (expr); } + private MemberAccess find_property_access (Expression! expr) { + if (expr is ParenthesizedExpression) { + var pe = (ParenthesizedExpression) expr; + return find_property_access (pe.inner); + } + + if (!(expr is MemberAccess)) { + return null; + } + + var ma = (MemberAccess) expr; + if (ma.symbol_reference.node is Property) { + return ma; + } + + return null; + } + private ref CCodeExpression get_ref_expression (Expression! expr) { /* (temp = expr, temp == NULL ? NULL : ref (temp)) * @@ -3324,7 +3367,6 @@ public class Vala.CodeGenerator : CodeVisitor { if (a.left.symbol_reference != null && a.left.symbol_reference.node is Property) { var prop = (Property) a.left.symbol_reference.node; - var cl = (Class) prop.symbol.parent_symbol.node; if (ma.inner == null && a.parent_node is Statement && ((Statement) a.parent_node).construction) { @@ -3356,43 +3398,10 @@ public class Vala.CodeGenerator : CodeVisitor { 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 (new CCodeIdentifier (set_func)); - - /* target instance is first argument */ - ref CCodeExpression instance; - var req_cast = false; - - if (ma.inner == null) { - instance = new CCodeIdentifier ("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 (new CCodeIdentifier (((DataType) prop.symbol.parent_symbol.node).get_upper_case_cname (null))); - ccast.add_argument (instance); - instance = ccast; - } - - ccall.add_argument (instance); - 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 + if (!prop.no_accessor_method + && 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) { @@ -3427,14 +3436,15 @@ public class Vala.CodeGenerator : CodeVisitor { } cexpr = new CCodeBinaryExpression (cop, (CCodeExpression) a.left.ccodenode, new CCodeParenthesizedExpression (cexpr)); } - - ccall.add_argument (cexpr); - if (prop.no_accessor_method) { - ccall.add_argument (new CCodeConstant ("NULL")); - } + var ccall = get_property_set_call (prop, ma, cexpr); + + // assignments are expressions, so return the current property value + var ccomma = new CCodeCommaExpression (); + ccomma.append_expression (ccall); // update property + ccomma.append_expression ((CCodeExpression) ma.ccodenode); // current property value - a.ccodenode = ccall; + a.ccodenode = ccomma; } } else if (a.left.symbol_reference != null && a.left.symbol_reference.node is Signal) { var sig = (Signal) a.left.symbol_reference.node; @@ -3543,4 +3553,51 @@ public class Vala.CodeGenerator : CodeVisitor { a.ccodenode = new CCodeAssignment ((CCodeExpression) a.left.ccodenode, rhs, cop); } } + + private ref CCodeFunctionCall get_property_set_call (Property! prop, MemberAccess! ma, CCodeExpression! cexpr) { + 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 (new CCodeIdentifier (set_func)); + + /* target instance is first argument */ + ref CCodeExpression instance; + var req_cast = false; + + if (ma.inner == null) { + instance = new CCodeIdentifier ("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 (new CCodeIdentifier (((DataType) prop.symbol.parent_symbol.node).get_upper_case_cname (null))); + ccast.add_argument (instance); + instance = ccast; + } + + ccall.add_argument (instance); + + if (prop.no_accessor_method) { + /* property name is second argument of g_object_set */ + ccall.add_argument (prop.get_canonical_cconstant ()); + } + + ccall.add_argument (cexpr); + + if (prop.no_accessor_method) { + ccall.add_argument (new CCodeConstant ("NULL")); + } + + return ccall; + } } diff --git a/vala/vala/valasemanticanalyzer.vala b/vala/vala/valasemanticanalyzer.vala index 0057a6ef0..5d32d39ea 100644 --- a/vala/vala/valasemanticanalyzer.vala +++ b/vala/vala/valasemanticanalyzer.vala @@ -1255,18 +1255,17 @@ public class Vala.SemanticAnalyzer : CodeVisitor { return; } - if (!(expr.inner is MemberAccess)) { + var ma = find_member_access (expr.inner); + if (ma == null) { expr.error = true; - Report.error (expr.source_reference, "Prefix operators currently not supported for this expression"); + Report.error (expr.source_reference, "Prefix operators not supported for this expression"); return; } - var ma = (MemberAccess) expr.inner; - var old_value = new MemberAccess (ma.inner, ma.member_name); var bin = new BinaryExpression (expr.operator == UnaryOperator.INCREMENT ? BinaryOperator.PLUS : BinaryOperator.MINUS, old_value, new LiteralExpression (new IntegerLiteral ("1"))); - var assignment = new Assignment (expr.inner, bin); + var assignment = new Assignment (ma, bin); expr.parent_node.replace (expr, assignment); assignment.accept (this); return; @@ -1284,6 +1283,19 @@ public class Vala.SemanticAnalyzer : CodeVisitor { return; } } + + private MemberAccess find_member_access (Expression! expr) { + if (expr is ParenthesizedExpression) { + var pe = (ParenthesizedExpression) expr; + return find_member_access (pe.inner); + } + + if (expr is MemberAccess) { + return (MemberAccess) expr; + } + + return null; + } public override void visit_cast_expression (CastExpression! expr) { if (expr.type_reference.data_type == null) {