From 15f4c8e74c9c11188eb01d4dc1a6dbf222d530e7 Mon Sep 17 00:00:00 2001 From: Mathias Hasselmann Date: Tue, 4 Sep 2007 21:19:27 +0000 Subject: [PATCH] support strings in switch statements, fixes bug 473462 2007-09-04 Mathias Hasselmann * gobject/valacodegenerator.vala: support strings in switch statements, fixes bug 473462 svn path=/trunk/; revision=581 --- ChangeLog | 5 ++ gobject/valacodegenerator.vala | 136 +++++++++++++++++++++++++++++++---------- tests/Makefile.am | 2 + tests/test-037.exp | 1 + tests/test-037.vala | 46 ++++++++++++++ 5 files changed, 158 insertions(+), 32 deletions(-) create mode 100644 tests/test-037.exp create mode 100644 tests/test-037.vala diff --git a/ChangeLog b/ChangeLog index 8302778..b4fcc57 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +2007-09-04 Mathias Hasselmann + + * gobject/valacodegenerator.vala: support strings in switch + statements, fixes bug 473462 + 2007-09-04 Jürg Billeter * vala/valacodenode.vala, ccode/valaccodebreakstatement.vala, diff --git a/gobject/valacodegenerator.vala b/gobject/valacodegenerator.vala index f2632bb..c880697 100644 --- a/gobject/valacodegenerator.vala +++ b/gobject/valacodegenerator.vala @@ -104,6 +104,7 @@ public class Vala.CodeGenerator : CodeVisitor { DataType gslist_type; DataType gstring_type; DataType garray_type; + TypeReference gquark_type; TypeReference mutex_type; DataType type_module_type; DataType iterable_type; @@ -256,7 +257,10 @@ public class Vala.CodeGenerator : CodeVisitor { gslist_type = (DataType) glib_ns.scope.lookup ("SList"); gstring_type = (DataType) glib_ns.scope.lookup ("String"); garray_type = (DataType) glib_ns.scope.lookup ("Array"); - + + gquark_type = new TypeReference (); + gquark_type.data_type = (DataType) glib_ns.scope.lookup ("Quark"); + mutex_type = new TypeReference (); mutex_type.data_type = (DataType) glib_ns.scope.lookup ("Mutex"); @@ -311,7 +315,7 @@ public class Vala.CodeGenerator : CodeVisitor { var error_domain_define = new CCodeMacroReplacement (en.get_upper_case_cname (), quark_fun_name + " ()"); header_type_definition.append (error_domain_define); - var cquark_fun = new CCodeFunction (quark_fun_name, "GQuark"); + var cquark_fun = new CCodeFunction (quark_fun_name, gquark_type.data_type.get_cname ()); var cquark_block = new CCodeBlock (); var cquark_call = new CCodeFunctionCall (new CCodeIdentifier ("g_quark_from_static_string")); @@ -512,7 +516,11 @@ public class Vala.CodeGenerator : CodeVisitor { } private bool is_constant_ccode_expression (CCodeExpression! cexpr) { - return (cexpr is CCodeConstant); + if (cexpr is CCodeConstant) + return true; + + var cparenthesized = (cexpr as CCodeParenthesizedExpression); + return (null != cparenthesized && is_constant_ccode_expression (cparenthesized.inner)); } public override void visit_formal_parameter (FormalParameter! p) { @@ -1285,55 +1293,119 @@ public class Vala.CodeGenerator : CodeVisitor { stmt.expression.temp_vars.insert (0, temp_decl); var ctemp = new CCodeIdentifier (temp_decl.name); - var cinit = new CCodeAssignment (ctemp, (CCodeExpression) stmt.expression.ccodenode); - + var czero = new CCodeConstant ("0"); + var cswitchblock = new CCodeFragment (); - cswitchblock.append (new CCodeExpressionStatement (cinit)); stmt.ccodenode = cswitchblock; + var is_string_cmp = temp_decl.type_reference.data_type.is_subtype_of (string_type.data_type); + + if (is_string_cmp) { + var cisnull = new CCodeBinaryExpression (CCodeBinaryOperator.EQUALITY, new CCodeConstant ("NULL"), ctemp); + var cquark = new CCodeFunctionCall (new CCodeIdentifier ("g_quark_from_string")); + cquark.add_argument (ctemp); + + var ccond = new CCodeConditionalExpression (cisnull, new CCodeConstant ("0"), cquark); + + temp_decl = get_temp_variable_declarator (gquark_type); + stmt.expression.temp_vars.insert (0, temp_decl); + + var label_count = 0; + + foreach (SwitchSection section in stmt.get_sections ()) { + if (section.has_default_label ()) { + continue; + } + + foreach (SwitchLabel label in section.get_labels ()) { + var cexpr = (CCodeExpression) label.expression.ccodenode; + + if (is_constant_ccode_expression (cexpr)) { + var cname = "%s_label%d".printf (temp_decl.name, label_count++); + var cdecl = new CCodeDeclaration (gquark_type.get_cname ()); + + cdecl.modifiers = CCodeModifiers.STATIC; + cdecl.add_declarator (new CCodeVariableDeclarator.with_initializer (cname, czero)); + + cswitchblock.append (cdecl); + } + } + } + + cswitchblock.append (new CCodeExpressionStatement (cinit)); + + ctemp = new CCodeIdentifier (temp_decl.name); + cinit = new CCodeAssignment (ctemp, ccond); + } + + cswitchblock.append (new CCodeExpressionStatement (cinit)); create_temp_decl (stmt, stmt.expression.temp_vars); Collection default_statements = null; - + var label_count = 0; + // generate nested if statements CCodeStatement ctopstmt = null; CCodeIfStatement coldif = null; + foreach (SwitchSection section in stmt.get_sections ()) { if (section.has_default_label ()) { default_statements = section.get_statements (); - } else { - CCodeBinaryExpression cor = null; - foreach (SwitchLabel label in section.get_labels ()) { - var ccmp = new CCodeBinaryExpression (CCodeBinaryOperator.EQUALITY, ctemp, (CCodeExpression) label.expression.ccodenode); - if (cor == null) { - cor = ccmp; + continue; + } + + CCodeBinaryExpression cor = null; + foreach (SwitchLabel label in section.get_labels ()) { + var cexpr = (CCodeExpression) label.expression.ccodenode; + + if (is_string_cmp) { + if (is_constant_ccode_expression (cexpr)) { + var cname = new CCodeIdentifier ("%s_label%d".printf (temp_decl.name, label_count++)); + var ccond = new CCodeBinaryExpression (CCodeBinaryOperator.INEQUALITY, czero, cname); + var ccall = new CCodeFunctionCall (new CCodeIdentifier ("g_quark_from_static_string")); + var cinit = new CCodeParenthesizedExpression (new CCodeAssignment (cname, ccall)); + + ccall.add_argument (cexpr); + + cexpr = new CCodeConditionalExpression (ccond, cname, cinit); } else { - cor = new CCodeBinaryExpression (CCodeBinaryOperator.OR, cor, ccmp); + var ccall = new CCodeFunctionCall (new CCodeIdentifier ("g_quark_from_string")); + ccall.add_argument (cexpr); + cexpr = ccall; } } - - var cblock = new CCodeBlock (); - foreach (CodeNode body_stmt in section.get_statements ()) { - if (body_stmt.ccodenode is CCodeFragment) { - foreach (CCodeStatement cstmt in ((CCodeFragment) body_stmt.ccodenode).get_children ()) { - cblock.add_statement (cstmt); - } - } else { - cblock.add_statement ((CCodeStatement) body_stmt.ccodenode); - } + + var ccmp = new CCodeBinaryExpression (CCodeBinaryOperator.EQUALITY, ctemp, cexpr); + + if (cor == null) { + cor = ccmp; + } else { + cor = new CCodeBinaryExpression (CCodeBinaryOperator.OR, cor, ccmp); } - - var cdo = new CCodeDoStatement (cblock, new CCodeConstant ("0")); - - var cif = new CCodeIfStatement (cor, cdo); - if (coldif != null) { - coldif.false_statement = cif; + } + + var cblock = new CCodeBlock (); + foreach (CodeNode body_stmt in section.get_statements ()) { + if (body_stmt.ccodenode is CCodeFragment) { + foreach (CCodeStatement cstmt in ((CCodeFragment) body_stmt.ccodenode).get_children ()) { + cblock.add_statement (cstmt); + } } else { - ctopstmt = cif; + cblock.add_statement ((CCodeStatement) body_stmt.ccodenode); } - coldif = cif; } + + var cdo = new CCodeDoStatement (cblock, new CCodeConstant ("0")); + var cif = new CCodeIfStatement (cor, cdo); + + if (coldif != null) { + coldif.false_statement = cif; + } else { + ctopstmt = cif; + } + + coldif = cif; } if (default_statements != null) { diff --git a/tests/Makefile.am b/tests/Makefile.am index 34ab314..4bd0354 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -70,6 +70,7 @@ TESTS = \ test-034.vala \ test-035.vala \ test-036.vala \ + test-037.vala \ $(NULL) EXTRA_DIST = \ @@ -112,6 +113,7 @@ EXTRA_DIST = \ test-034.exp \ test-035.exp \ test-036.exp \ + test-037.exp \ \ testenchant.stamp \ testenchant.vala \ diff --git a/tests/test-037.exp b/tests/test-037.exp new file mode 100644 index 0000000..b0296a3 --- /dev/null +++ b/tests/test-037.exp @@ -0,0 +1 @@ +testing switch on strings: 1 2 3 4 5 6 7 diff --git a/tests/test-037.vala b/tests/test-037.vala new file mode 100644 index 0000000..af3940d --- /dev/null +++ b/tests/test-037.vala @@ -0,0 +1,46 @@ +using GLib; + +class Maman.Bar : Object { + static void main () { + // FIXME: figure out why "new string[]" is needed (again?) + var tokens = new string[] { "Hello", "World", "this", "is", "Vala", "GNOME", null }; + var t4 = " 5"; + + stdout.printf ("testing switch on strings:"); + + foreach(weak string t in tokens) { + switch (t) { + case "Hello": + stdout.printf (" 1"); + break; + + case "World": + stdout.printf (" 2"); + break; + + case "this": + stdout.printf (" 3"); + break; + + case ("is"): + stdout.printf (" 4"); + break; + + case tokens[4]: + stdout.printf (t4); + tokens[4] = "GNOME"; + t4 = " 6"; + break; + + default: + stdout.printf (" 7"); + break; + } + } + + tokens[4] = null; // FIXME: element access on array takes ownership + + stdout.printf ("\n"); + } +} + -- 2.7.4