From b99c2c277d83964d3783cf45c657deeca99d7f0c Mon Sep 17 00:00:00 2001 From: Minero Aoki Date: Sun, 31 Aug 2008 16:49:26 +0000 Subject: [PATCH] * net/loveruby/cflat/parser/Parser.jj: pass location node to the CaseNode explicitly. * net/loveruby/cflat/ast/CaseNode.java: default clause does not have value, we cannot extract location node from values. Receive a location node as a first argument explicitly. * net/loveruby/cflat/compiler/CodeGenerator.java: must define end label. * net/loveruby/cflat/compiler/CodeGenerator.java: implement default clause. * test: test switch stmt. git-svn-id: file:///Users/aamine/c/gitwork/public/cbc/trunk@3990 1b9489fe-b721-0410-924e-b54b9192deb8 --- ChangeLog | 17 +++++++++++++ net/loveruby/cflat/ast/CaseNode.java | 8 +++++-- .../cflat/compiler/CodeGenerator.java | 19 ++++++++++----- net/loveruby/cflat/parser/Parser.jj | 5 ++-- test/switch.cb | 24 +++++++++++++++++++ 5 files changed, 63 insertions(+), 10 deletions(-) create mode 100644 test/switch.cb diff --git a/ChangeLog b/ChangeLog index f49d17d..51c0d7b 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,20 @@ +Mon Sep 1 01:49:23 2008 Minero Aoki + + * net/loveruby/cflat/parser/Parser.jj: pass location node to the + CaseNode explicitly. + + * net/loveruby/cflat/ast/CaseNode.java: default clause does not + have value, we cannot extract location node from values. Receive + a location node as a first argument explicitly. + + * net/loveruby/cflat/compiler/CodeGenerator.java: must define end + label. + + * net/loveruby/cflat/compiler/CodeGenerator.java: implement + default clause. + + * test: test switch stmt. + Mon Sep 1 01:26:20 2008 Minero Aoki * net/loveruby/cflat/compiler/CodeGenerator.java: static function diff --git a/net/loveruby/cflat/ast/CaseNode.java b/net/loveruby/cflat/ast/CaseNode.java index 888c7f8..ee36c93 100644 --- a/net/loveruby/cflat/ast/CaseNode.java +++ b/net/loveruby/cflat/ast/CaseNode.java @@ -8,8 +8,8 @@ public class CaseNode extends StmtNode { protected List values; // List protected BlockNode body; - public CaseNode(LabelPool pool, List values, BlockNode body) { - super(((Node)values.get(0)).location()); + public CaseNode(Location loc, LabelPool pool, List values, BlockNode body) { + super(loc); this.pool = pool; this.values = values; this.body = body; @@ -20,6 +20,10 @@ public class CaseNode extends StmtNode { return values.iterator(); } + public boolean isDefault() { + return values.isEmpty(); + } + public BlockNode body() { return body; } diff --git a/net/loveruby/cflat/compiler/CodeGenerator.java b/net/loveruby/cflat/compiler/CodeGenerator.java index f95e55c..25a8436 100644 --- a/net/loveruby/cflat/compiler/CodeGenerator.java +++ b/net/loveruby/cflat/compiler/CodeGenerator.java @@ -457,18 +457,25 @@ static public void p(String s) { System.err.println(s); } Iterator cases = node.cases(); while (cases.hasNext()) { CaseNode caseNode = (CaseNode)cases.next(); - Iterator values = caseNode.values(); - while (values.hasNext()) { - IntegerLiteralNode ival = (IntegerLiteralNode)values.next(); - mov(imm(ival.value()), reg("cx")); - cmp(t, reg("cx", t), reg("ax", t)); - je(caseNode.beginLabel()); + if (! caseNode.isDefault()) { + Iterator values = caseNode.values(); + while (values.hasNext()) { + IntegerLiteralNode ival = (IntegerLiteralNode)values.next(); + mov(imm(ival.value()), reg("cx")); + cmp(t, reg("cx", t), reg("ax", t)); + je(caseNode.beginLabel()); + } + } + else { + jmp(caseNode.beginLabel()); } } + jmp(node.endLabel()); cases = node.cases(); while (cases.hasNext()) { compile((CaseNode)cases.next()); } + label(node.endLabel()); } public void visit(CaseNode node) { diff --git a/net/loveruby/cflat/parser/Parser.jj b/net/loveruby/cflat/parser/Parser.jj index c3fd04b..f0cfb24 100644 --- a/net/loveruby/cflat/parser/Parser.jj +++ b/net/loveruby/cflat/parser/Parser.jj @@ -955,7 +955,7 @@ CaseNode case_clause(): { values=cases() body=case_body() { - return new CaseNode(labelPool, values, body); + return new CaseNode(body.location(), labelPool, values, body); } } @@ -976,7 +976,8 @@ CaseNode default_clause(): { ":" body=case_body() { - return new CaseNode(labelPool, new ArrayList(), body); + return new CaseNode(body.location(), labelPool, + new ArrayList(), body); } } diff --git a/test/switch.cb b/test/switch.cb new file mode 100644 index 0000000..c37221b --- /dev/null +++ b/test/switch.cb @@ -0,0 +1,24 @@ +import stdio; + +int +main(int argc, char **argv) +{ + switch (argc) { + case 1: + case 2: + puts("1 or 2"); + break; + case 3: + case 4: + puts("3 or 4"); + break; + case 5: + case 6: + puts("5 or 6"); + break; + default: + puts("other"); + break; + } + return 0; +}