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

test postfix and prefix expressions update support prefix and postfix

2007-02-26  Jürg Billeter  <j@bitron.ch>

	* 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
parent 03d2581b
2007-02-26 Jürg Billeter <j@bitron.ch>
* 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 <j@bitron.ch>
* vala/valasemanticanalyzer.vala, vala/valacodegenerator.vala: improve
......
......@@ -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)
Postfix and Prefix Expression Test: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
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;
}
}
......@@ -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;
}
}
......@@ -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) {
......
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