From da69c6fcc5e41a5e711b7b05faaa6c37392cbeef Mon Sep 17 00:00:00 2001 From: =?utf8?q?J=C3=BCrg=20Billeter?= Date: Thu, 10 Aug 2006 15:30:52 +0000 Subject: [PATCH] support switch statements add has_default_label () and get_statements () MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit 2006-08-10 Jürg Billeter * vala/valacodegenerator.vala: support switch statements * vala/valaswitchsection.vala: add has_default_label () and get_statements () methods * vala/valaswitchstatement.vala: add get_sections () method * ccode/valaccodedostatement.vala * ccode/Makefile.am: update * tests/test-020.vala: test switch statements * tests/Makefile.am: update svn path=/trunk/; revision=97 --- vala/ChangeLog | 11 ++++++ vala/ccode/Makefile.am | 4 ++ vala/ccode/valaccodedostatement.vala | 62 +++++++++++++++++++++++++++++++ vala/tests/Makefile.am | 1 + vala/tests/test-020.vala | 53 +++++++++++++++++++++++++++ vala/vala/valacodegenerator.vala | 71 ++++++++++++++++++++++++++++++++++++ vala/vala/valaswitchsection.vala | 19 ++++++++++ vala/vala/valaswitchstatement.vala | 9 +++++ 8 files changed, 230 insertions(+) create mode 100644 vala/ccode/valaccodedostatement.vala create mode 100644 vala/tests/test-020.vala diff --git a/vala/ChangeLog b/vala/ChangeLog index f4748a6..85c7b05 100644 --- a/vala/ChangeLog +++ b/vala/ChangeLog @@ -1,5 +1,16 @@ 2006-08-10 Jürg Billeter + * vala/valacodegenerator.vala: support switch statements + * vala/valaswitchsection.vala: add has_default_label () and + get_statements () methods + * vala/valaswitchstatement.vala: add get_sections () method + * ccode/valaccodedostatement.vala + * ccode/Makefile.am: update + * tests/test-020.vala: test switch statements + * tests/Makefile.am: update + +2006-08-10 Jürg Billeter + * vala/valasemanticanalyzer.vala, vala/valacodegenerator.vala: use Invokable * vala/valainvokable.vala diff --git a/vala/ccode/Makefile.am b/vala/ccode/Makefile.am index a41023e..6adb826 100644 --- a/vala/ccode/Makefile.am +++ b/vala/ccode/Makefile.am @@ -54,6 +54,9 @@ libvalaccode_la_SOURCES = \ valaccodedeclarator.c \ valaccodedeclarator.h \ valaccodedeclarator.vala \ + valaccodedostatement.c \ + valaccodedostatement.h \ + valaccodedostatement.vala \ valaccodeemptystatement.c \ valaccodeemptystatement.h \ valaccodeemptystatement.vala \ @@ -168,6 +171,7 @@ ccodeinclude_HEADERS = \ valaccodecontinuestatement.h \ valaccodedeclaration.h \ valaccodedeclarator.h \ + valaccodedostatement.h \ valaccodeemptystatement.h \ valaccodeenum.h \ valaccodeexpression.h \ diff --git a/vala/ccode/valaccodedostatement.vala b/vala/ccode/valaccodedostatement.vala new file mode 100644 index 0000000..b0bc335 --- /dev/null +++ b/vala/ccode/valaccodedostatement.vala @@ -0,0 +1,62 @@ +/* valaccodedostatement.vala + * + * Copyright (C) 2006 Jürg Billeter + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Author: + * Jürg Billeter + */ + +using GLib; + +/** + * Represents a do iteration statement in the C code. + */ +public class Vala.CCodeDoStatement : CCodeStatement { + /** + * The loop body. + */ + public CCodeStatement body { get; set; } + + /** + * The loop condition. + */ + public CCodeExpression! condition { get; set construct; } + + public construct (CCodeStatement stmt, CCodeExpression! cond) { + body = stmt; + condition = cond; + } + + public override void write (CCodeWriter! writer) { + writer.write_indent (); + writer.write_string ("do"); + + /* while shouldn't be on a separate line */ + if (body is CCodeBlock) { + var cblock = (CCodeBlock) body; + cblock.suppress_newline = true; + } + + body.write (writer); + + writer.write_string (" while ("); + + condition.write (writer); + + writer.write_string (");"); + } +} diff --git a/vala/tests/Makefile.am b/vala/tests/Makefile.am index 1e4cf97..9909987 100644 --- a/vala/tests/Makefile.am +++ b/vala/tests/Makefile.am @@ -20,4 +20,5 @@ EXTRA_DIST = \ test-017.vala \ test-018.vala \ test-019.vala \ + test-020.vala \ $(NULL) diff --git a/vala/tests/test-020.vala b/vala/tests/test-020.vala new file mode 100644 index 0000000..f11cee8 --- /dev/null +++ b/vala/tests/test-020.vala @@ -0,0 +1,53 @@ +using GLib; + +class Maman.Foo { + public void run () { + stdout.printf (" 2"); + + switch (23) { + case 23: + stdout.printf (" 3"); + break; + default: + stdout.printf (" BAD"); + break; + } + + switch (inc ()) { + case 0: + stdout.printf (" 4"); + break; + default: + stdout.printf (" BAD"); + break; + } + + switch (42) { + case 0: + stdout.printf (" BAD"); + break; + default: + stdout.printf (" 5"); + break; + } + + stdout.printf (" 6"); + } + + public int inc () { + return counter++; + } + + static int main (int argc, string[] argv) { + stdout.printf ("Switch statement: 1"); + + var foo = new Foo (); + foo.run (); + + stdout.printf (" 7\n"); + + return 0; + } + + private int counter = 0; +} diff --git a/vala/vala/valacodegenerator.vala b/vala/vala/valacodegenerator.vala index bf05988..bb00d79 100644 --- a/vala/vala/valacodegenerator.vala +++ b/vala/vala/valacodegenerator.vala @@ -1511,6 +1511,77 @@ public class Vala.CodeGenerator : CodeVisitor { create_temp_decl (stmt, stmt.condition.temp_vars); } + public override void visit_switch_statement (SwitchStatement! stmt) { + // we need a temporary variable to save the property value + var temp_decl = get_temp_variable_declarator (stmt.expression.static_type); + stmt.expression.temp_vars.prepend (temp_decl); + + var ctemp = new CCodeIdentifier (temp_decl.name); + + var cinit = new CCodeAssignment (ctemp, (CCodeExpression) stmt.expression.ccodenode); + + var cswitchblock = new CCodeFragment (); + cswitchblock.append (new CCodeExpressionStatement (cinit)); + stmt.ccodenode = cswitchblock; + + create_temp_decl (stmt, stmt.expression.temp_vars); + + List default_statements = null; + + // generate nested if statements + CCodeStatement ctopstmt = null; + ref 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; + } else { + cor = new CCodeBinaryExpression (CCodeBinaryOperator.OR, cor, ccmp); + } + } + + var cblock = new CCodeBlock (); + foreach (Statement body_stmt in section.get_statements ()) { + cblock.add_statement ((CCodeStatement) body_stmt.ccodenode); + } + + 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) { + var cblock = new CCodeBlock (); + foreach (Statement body_stmt in default_statements) { + cblock.add_statement ((CCodeStatement) body_stmt.ccodenode); + } + + var cdo = new CCodeDoStatement (cblock, new CCodeConstant ("0")); + + if (coldif == null) { + // there is only one section and that section + // contains a default label + ctopstmt = cdo; + } else { + coldif.false_statement = cdo; + } + } + + cswitchblock.append (ctopstmt); + } + public override void visit_while_statement (WhileStatement! stmt) { stmt.ccodenode = new CCodeWhileStatement ((CCodeExpression) stmt.condition.ccodenode, (CCodeStatement) stmt.body.ccodenode); diff --git a/vala/vala/valaswitchsection.vala b/vala/vala/valaswitchsection.vala index 84ba31a..4899ebf 100644 --- a/vala/vala/valaswitchsection.vala +++ b/vala/vala/valaswitchsection.vala @@ -57,6 +57,16 @@ public class Vala.SwitchSection : CodeNode { return labels.copy (); } + public bool has_default_label () { + foreach (SwitchLabel label in labels) { + if (label.expression == null) { + return true; + } + } + + return false; + } + /** * Appends the specified statement to this switch section. * @@ -66,6 +76,15 @@ public class Vala.SwitchSection : CodeNode { statement_list.append (stmt); } + /** + * Returns a copy of the list of statements. + * + * @return statement list + */ + public ref List get_statements () { + return statement_list.copy (); + } + public override void accept (CodeVisitor! visitor) { foreach (SwitchLabel label in labels) { label.accept (visitor); diff --git a/vala/vala/valaswitchstatement.vala b/vala/vala/valaswitchstatement.vala index dacaece..5955b29 100644 --- a/vala/vala/valaswitchstatement.vala +++ b/vala/vala/valaswitchstatement.vala @@ -54,6 +54,15 @@ public class Vala.SwitchStatement : Statement { sections.append (section); } + /** + * Returns a copy of the list of switch sections. + * + * @return section list + */ + public ref List get_sections () { + return sections.copy (); + } + public override void accept (CodeVisitor! visitor) { expression.accept (visitor); -- 2.7.4