Commit 15f4c8e7 authored by Mathias Hasselmann's avatar Mathias Hasselmann Committed by Mathias Hasselmann
Browse files

support strings in switch statements, fixes bug 473462

2007-09-04 Mathias Hasselmann <mathias.hasselmann@gmx.de>

	* gobject/valacodegenerator.vala: support strings in switch
	statements, fixes bug 473462

svn path=/trunk/; revision=581
parent c7229010
2007-09-04 Mathias Hasselmann <mathias.hasselmann@gmx.de>
* gobject/valacodegenerator.vala: support strings in switch
statements, fixes bug 473462
2007-09-04 Jürg Billeter <j@bitron.ch>
* vala/valacodenode.vala, ccode/valaccodebreakstatement.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<Statement> 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) {
......
......@@ -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 \
......
testing switch on strings: 1 2 3 4 5 6 7
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");
}
}
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