From 043859df0b4460d25de4ff7e11c81e355f51541e Mon Sep 17 00:00:00 2001 From: Minero Aoki Date: Sat, 4 Apr 2009 14:47:11 +0000 Subject: [PATCH] * net/loveruby/cflat/ast/ASTVisitor.java: #visit returns a node which has same type with the argument, to allow non-destructive AST rewriting. * net/loveruby/cflat/ast/*Node.java (#accept): ditto. * net/loveruby/cflat/compiler/Visitor.java: ditto. * net/loveruby/cflat/compiler/*.java: ditto. * net/loveruby/cflat/compiler/TypeChecker.java: make non-destructive. * net/loveruby/cflat/parser/Parser.jj: use StmtNode/ExprNode instead of Node. git-svn-id: file:///Users/aamine/c/gitwork/public/cbc/trunk@4130 1b9489fe-b721-0410-924e-b54b9192deb8 --- ChangeLog | 18 + net/loveruby/cflat/ast/AST.java | 2 +- net/loveruby/cflat/ast/ASTVisitor.java | 81 +-- .../cflat/ast/AbstractAssignNode.java | 4 - net/loveruby/cflat/ast/AddressNode.java | 8 +- net/loveruby/cflat/ast/ArefNode.java | 4 +- net/loveruby/cflat/ast/AssignNode.java | 4 +- net/loveruby/cflat/ast/BinaryOpNode.java | 4 +- net/loveruby/cflat/ast/BlockNode.java | 12 +- net/loveruby/cflat/ast/BreakNode.java | 4 +- net/loveruby/cflat/ast/CaseNode.java | 8 +- net/loveruby/cflat/ast/CastNode.java | 4 +- net/loveruby/cflat/ast/CondExprNode.java | 14 +- net/loveruby/cflat/ast/ContinueNode.java | 4 +- net/loveruby/cflat/ast/DefinedFunction.java | 4 +- net/loveruby/cflat/ast/DefinedVariable.java | 4 +- net/loveruby/cflat/ast/DereferenceNode.java | 4 +- net/loveruby/cflat/ast/DoWhileNode.java | 18 +- net/loveruby/cflat/ast/Entity.java | 2 + net/loveruby/cflat/ast/ExprNode.java | 2 + net/loveruby/cflat/ast/ExprStmtNode.java | 26 + net/loveruby/cflat/ast/ForNode.java | 28 +- net/loveruby/cflat/ast/FuncallNode.java | 4 +- net/loveruby/cflat/ast/GotoNode.java | 4 +- net/loveruby/cflat/ast/IfNode.java | 18 +- .../cflat/ast/IntegerLiteralNode.java | 4 +- net/loveruby/cflat/ast/LabelNode.java | 10 +- net/loveruby/cflat/ast/LogicalAndNode.java | 4 +- net/loveruby/cflat/ast/LogicalOrNode.java | 4 +- net/loveruby/cflat/ast/LoopNode.java | 12 +- net/loveruby/cflat/ast/MemberNode.java | 4 +- net/loveruby/cflat/ast/Node.java | 2 - net/loveruby/cflat/ast/OpAssignNode.java | 4 +- net/loveruby/cflat/ast/ParamSlots.java | 4 - net/loveruby/cflat/ast/PrefixOpNode.java | 4 +- net/loveruby/cflat/ast/PtrMemberNode.java | 4 +- net/loveruby/cflat/ast/ReturnNode.java | 4 +- net/loveruby/cflat/ast/SizeofExprNode.java | 8 +- net/loveruby/cflat/ast/SizeofTypeNode.java | 4 +- net/loveruby/cflat/ast/Slot.java | 4 - net/loveruby/cflat/ast/StmtNode.java | 2 + net/loveruby/cflat/ast/StringLiteralNode.java | 4 +- net/loveruby/cflat/ast/StructNode.java | 4 +- net/loveruby/cflat/ast/SuffixOpNode.java | 4 +- net/loveruby/cflat/ast/SwitchNode.java | 8 +- net/loveruby/cflat/ast/TypeDefinition.java | 1 + net/loveruby/cflat/ast/TypeNode.java | 2 +- net/loveruby/cflat/ast/TypedefNode.java | 4 +- .../cflat/ast/UnaryArithmeticOpNode.java | 4 + net/loveruby/cflat/ast/UnaryOpNode.java | 4 +- net/loveruby/cflat/ast/UndefinedFunction.java | 4 +- net/loveruby/cflat/ast/UndefinedVariable.java | 4 +- net/loveruby/cflat/ast/UnionNode.java | 4 +- net/loveruby/cflat/ast/VariableNode.java | 4 +- net/loveruby/cflat/ast/WhileNode.java | 18 +- .../cflat/compiler/CodeGenerator.java | 144 ++++-- .../cflat/compiler/DereferenceChecker.java | 43 +- net/loveruby/cflat/compiler/JumpResolver.java | 43 +- .../cflat/compiler/LocalResolver.java | 17 +- net/loveruby/cflat/compiler/TypeChecker.java | 483 +++++++++++------- net/loveruby/cflat/compiler/TypeResolver.java | 59 ++- net/loveruby/cflat/compiler/Visitor.java | 235 +++++---- net/loveruby/cflat/parser/Parser.jj | 31 +- 63 files changed, 912 insertions(+), 575 deletions(-) create mode 100644 net/loveruby/cflat/ast/ExprStmtNode.java diff --git a/ChangeLog b/ChangeLog index af6c600..b8ac370 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,21 @@ +Sat Apr 4 23:47:02 2009 Minero Aoki + + * net/loveruby/cflat/ast/ASTVisitor.java: #visit returns a node + which has same type with the argument, to allow non-destructive + AST rewriting. + + * net/loveruby/cflat/ast/*Node.java (#accept): ditto. + + * net/loveruby/cflat/compiler/Visitor.java: ditto. + + * net/loveruby/cflat/compiler/*.java: ditto. + + * net/loveruby/cflat/compiler/TypeChecker.java: make + non-destructive. + + * net/loveruby/cflat/parser/Parser.jj: use StmtNode/ExprNode + instead of Node. + Wed Dec 24 03:43:14 2008 Minero Aoki * lib/sizeof_jmpbuf.c: new analysis program. diff --git a/net/loveruby/cflat/ast/AST.java b/net/loveruby/cflat/ast/AST.java index 8ab7c3f..fe5ab95 100644 --- a/net/loveruby/cflat/ast/AST.java +++ b/net/loveruby/cflat/ast/AST.java @@ -110,7 +110,7 @@ public class AST extends Node { d.printNodeList("functions", definedFunctions()); } - public void accept(ASTVisitor visitor) { + public Node accept(ASTVisitor visitor) { throw new Error("must not happen: AST#accept called"); } } diff --git a/net/loveruby/cflat/ast/ASTVisitor.java b/net/loveruby/cflat/ast/ASTVisitor.java index 327a1ee..beaf81b 100644 --- a/net/loveruby/cflat/ast/ASTVisitor.java +++ b/net/loveruby/cflat/ast/ASTVisitor.java @@ -2,48 +2,49 @@ package net.loveruby.cflat.ast; public interface ASTVisitor { // Declarations - public void visit(DefinedVariable var); - public void visit(UndefinedVariable var); - public void visit(DefinedFunction func); - public void visit(UndefinedFunction func); - public void visit(StructNode struct); - public void visit(UnionNode union); - public void visit(TypedefNode typedef); + public DefinedVariable visit(DefinedVariable var); + public UndefinedVariable visit(UndefinedVariable var); + public DefinedFunction visit(DefinedFunction func); + public UndefinedFunction visit(UndefinedFunction func); + public StructNode visit(StructNode struct); + public UnionNode visit(UnionNode union); + public TypedefNode visit(TypedefNode typedef); // Statements - public void visit(BlockNode node); - public void visit(IfNode node); - public void visit(SwitchNode node); - public void visit(CaseNode node); - public void visit(WhileNode node); - public void visit(DoWhileNode node); - public void visit(ForNode node); - public void visit(BreakNode node); - public void visit(ContinueNode node); - public void visit(GotoNode node); - public void visit(LabelNode node); - public void visit(ReturnNode node); + public BlockNode visit(BlockNode node); + public ExprStmtNode visit(ExprStmtNode node); + public IfNode visit(IfNode node); + public SwitchNode visit(SwitchNode node); + public CaseNode visit(CaseNode node); + public WhileNode visit(WhileNode node); + public DoWhileNode visit(DoWhileNode node); + public ForNode visit(ForNode node); + public BreakNode visit(BreakNode node); + public ContinueNode visit(ContinueNode node); + public GotoNode visit(GotoNode node); + public LabelNode visit(LabelNode node); + public ReturnNode visit(ReturnNode node); // Expressions - public void visit(AssignNode node); - public void visit(OpAssignNode node); - public void visit(CondExprNode node); - public void visit(LogicalOrNode node); - public void visit(LogicalAndNode node); - public void visit(BinaryOpNode node); - public void visit(UnaryOpNode node); - public void visit(PrefixOpNode node); - public void visit(SuffixOpNode node); - public void visit(ArefNode node); - public void visit(MemberNode node); - public void visit(PtrMemberNode node); - public void visit(FuncallNode node); - public void visit(DereferenceNode node); - public void visit(AddressNode node); - public void visit(CastNode node); - public void visit(SizeofExprNode node); - public void visit(SizeofTypeNode node); - public void visit(VariableNode node); - public void visit(IntegerLiteralNode node); - public void visit(StringLiteralNode node); + public AssignNode visit(AssignNode node); + public OpAssignNode visit(OpAssignNode node); + public CondExprNode visit(CondExprNode node); + public LogicalOrNode visit(LogicalOrNode node); + public LogicalAndNode visit(LogicalAndNode node); + public BinaryOpNode visit(BinaryOpNode node); + public UnaryOpNode visit(UnaryOpNode node); + public PrefixOpNode visit(PrefixOpNode node); + public SuffixOpNode visit(SuffixOpNode node); + public ArefNode visit(ArefNode node); + public MemberNode visit(MemberNode node); + public PtrMemberNode visit(PtrMemberNode node); + public FuncallNode visit(FuncallNode node); + public DereferenceNode visit(DereferenceNode node); + public AddressNode visit(AddressNode node); + public CastNode visit(CastNode node); + public SizeofExprNode visit(SizeofExprNode node); + public SizeofTypeNode visit(SizeofTypeNode node); + public VariableNode visit(VariableNode node); + public IntegerLiteralNode visit(IntegerLiteralNode node); + public StringLiteralNode visit(StringLiteralNode node); } diff --git a/net/loveruby/cflat/ast/AbstractAssignNode.java b/net/loveruby/cflat/ast/AbstractAssignNode.java index b5ca543..cb9a1af 100644 --- a/net/loveruby/cflat/ast/AbstractAssignNode.java +++ b/net/loveruby/cflat/ast/AbstractAssignNode.java @@ -22,10 +22,6 @@ abstract public class AbstractAssignNode extends ExprNode { return rhs; } - public void setRHS(ExprNode node) { - this.rhs = node; - } - public Location location() { return lhs.location(); } diff --git a/net/loveruby/cflat/ast/AddressNode.java b/net/loveruby/cflat/ast/AddressNode.java index 56d10d6..ef8763b 100644 --- a/net/loveruby/cflat/ast/AddressNode.java +++ b/net/loveruby/cflat/ast/AddressNode.java @@ -8,6 +8,10 @@ public class AddressNode extends UnaryOpNode { super("&", n); } + public void setExpr(ExprNode expr) { + this.expr = expr; + } + public Type type() { if (type == null) throw new Error("type is null"); return type; @@ -20,7 +24,7 @@ public class AddressNode extends UnaryOpNode { this.type = type; } - public void accept(ASTVisitor visitor) { - visitor.visit(this); + public AddressNode accept(ASTVisitor visitor) { + return visitor.visit(this); } } diff --git a/net/loveruby/cflat/ast/ArefNode.java b/net/loveruby/cflat/ast/ArefNode.java index 5aade8a..2d6274a 100644 --- a/net/loveruby/cflat/ast/ArefNode.java +++ b/net/loveruby/cflat/ast/ArefNode.java @@ -60,8 +60,8 @@ public class ArefNode extends ExprNode { d.printMember("index", index); } - public void accept(ASTVisitor visitor) { - visitor.visit(this); + public ArefNode accept(ASTVisitor visitor) { + return visitor.visit(this); } public void acceptLHS(ASTLHSVisitor visitor) { diff --git a/net/loveruby/cflat/ast/AssignNode.java b/net/loveruby/cflat/ast/AssignNode.java index 5d07c2a..841835c 100644 --- a/net/loveruby/cflat/ast/AssignNode.java +++ b/net/loveruby/cflat/ast/AssignNode.java @@ -5,7 +5,7 @@ public class AssignNode extends AbstractAssignNode { super(lhs, rhs); } - public void accept(ASTVisitor visitor) { - visitor.visit(this); + public AssignNode accept(ASTVisitor visitor) { + return visitor.visit(this); } } diff --git a/net/loveruby/cflat/ast/BinaryOpNode.java b/net/loveruby/cflat/ast/BinaryOpNode.java index c1eecae..4759b11 100644 --- a/net/loveruby/cflat/ast/BinaryOpNode.java +++ b/net/loveruby/cflat/ast/BinaryOpNode.java @@ -53,7 +53,7 @@ public class BinaryOpNode extends ExprNode { d.printMember("right", right); } - public void accept(ASTVisitor visitor) { - visitor.visit(this); + public BinaryOpNode accept(ASTVisitor visitor) { + return visitor.visit(this); } } diff --git a/net/loveruby/cflat/ast/BlockNode.java b/net/loveruby/cflat/ast/BlockNode.java index 701bd40..cca8013 100644 --- a/net/loveruby/cflat/ast/BlockNode.java +++ b/net/loveruby/cflat/ast/BlockNode.java @@ -3,10 +3,10 @@ import java.util.*; public class BlockNode extends StmtNode { protected List variables; - protected List stmts; + protected List stmts; protected LocalScope scope; - public BlockNode(Location loc, List vars, List stmts) { + public BlockNode(Location loc, List vars, List stmts) { super(loc); this.variables = vars; this.stmts = stmts; @@ -16,11 +16,11 @@ public class BlockNode extends StmtNode { return variables; } - public List stmts() { + public List stmts() { return stmts; } - public Node tailStmt() { + public StmtNode tailStmt() { if (stmts.isEmpty()) return null; return stmts.get(stmts.size() - 1); } @@ -38,7 +38,7 @@ public class BlockNode extends StmtNode { d.printNodeList("stmts", stmts); } - public void accept(ASTVisitor visitor) { - visitor.visit(this); + public BlockNode accept(ASTVisitor visitor) { + return visitor.visit(this); } } diff --git a/net/loveruby/cflat/ast/BreakNode.java b/net/loveruby/cflat/ast/BreakNode.java index b2ebc5f..9cbf424 100644 --- a/net/loveruby/cflat/ast/BreakNode.java +++ b/net/loveruby/cflat/ast/BreakNode.java @@ -26,7 +26,7 @@ public class BreakNode extends StmtNode { protected void _dump(Dumper d) { } - public void accept(ASTVisitor visitor) { - visitor.visit(this); + public BreakNode accept(ASTVisitor visitor) { + return visitor.visit(this); } } diff --git a/net/loveruby/cflat/ast/CaseNode.java b/net/loveruby/cflat/ast/CaseNode.java index 763daed..c1e0c2b 100644 --- a/net/loveruby/cflat/ast/CaseNode.java +++ b/net/loveruby/cflat/ast/CaseNode.java @@ -18,6 +18,10 @@ public class CaseNode extends StmtNode { return values; } + public void setValues(List values) { + this.values = values; + } + public boolean isDefault() { return values.isEmpty(); } @@ -35,7 +39,7 @@ public class CaseNode extends StmtNode { d.printMember("body", body); } - public void accept(ASTVisitor visitor) { - visitor.visit(this); + public CaseNode accept(ASTVisitor visitor) { + return visitor.visit(this); } } diff --git a/net/loveruby/cflat/ast/CastNode.java b/net/loveruby/cflat/ast/CastNode.java index 55ac838..3cfd239 100644 --- a/net/loveruby/cflat/ast/CastNode.java +++ b/net/loveruby/cflat/ast/CastNode.java @@ -66,7 +66,7 @@ public class CastNode extends ExprNode { d.printMember("expr", expr); } - public void accept(ASTVisitor visitor) { - visitor.visit(this); + public CastNode accept(ASTVisitor visitor) { + return visitor.visit(this); } } diff --git a/net/loveruby/cflat/ast/CondExprNode.java b/net/loveruby/cflat/ast/CondExprNode.java index 77e24f3..0209d88 100644 --- a/net/loveruby/cflat/ast/CondExprNode.java +++ b/net/loveruby/cflat/ast/CondExprNode.java @@ -27,16 +27,14 @@ public class CondExprNode extends ExprNode { return thenExpr; } - public void setThenExpr(ExprNode node) { - thenExpr = node; - } - public ExprNode elseExpr() { return elseExpr; } - public void setElseExpr(ExprNode node) { - elseExpr = node; + public void setExprs(ExprNode cond, ExprNode thenExpr, ExprNode elseExpr) { + this.cond = cond; + this.thenExpr = thenExpr; + this.elseExpr = elseExpr; } public Label elseLabel() { @@ -57,7 +55,7 @@ public class CondExprNode extends ExprNode { d.printMember("elseExpr", elseExpr); } - public void accept(ASTVisitor visitor) { - visitor.visit(this); + public CondExprNode accept(ASTVisitor visitor) { + return visitor.visit(this); } } diff --git a/net/loveruby/cflat/ast/ContinueNode.java b/net/loveruby/cflat/ast/ContinueNode.java index d2ab64b..9b21f54 100644 --- a/net/loveruby/cflat/ast/ContinueNode.java +++ b/net/loveruby/cflat/ast/ContinueNode.java @@ -22,7 +22,7 @@ public class ContinueNode extends StmtNode { protected void _dump(Dumper d) { } - public void accept(ASTVisitor visitor) { - visitor.visit(this); + public ContinueNode accept(ASTVisitor visitor) { + return visitor.visit(this); } } diff --git a/net/loveruby/cflat/ast/DefinedFunction.java b/net/loveruby/cflat/ast/DefinedFunction.java index 97f5b22..7afbe0f 100644 --- a/net/loveruby/cflat/ast/DefinedFunction.java +++ b/net/loveruby/cflat/ast/DefinedFunction.java @@ -115,7 +115,7 @@ public class DefinedFunction extends Function { d.printMember("body", body); } - public void accept(ASTVisitor visitor) { - visitor.visit(this); + public DefinedFunction accept(ASTVisitor visitor) { + return visitor.visit(this); } } diff --git a/net/loveruby/cflat/ast/DefinedVariable.java b/net/loveruby/cflat/ast/DefinedVariable.java index dcfb7eb..6ac9d5b 100644 --- a/net/loveruby/cflat/ast/DefinedVariable.java +++ b/net/loveruby/cflat/ast/DefinedVariable.java @@ -50,7 +50,7 @@ public class DefinedVariable extends Variable { d.printMember("initializer", initializer); } - public void accept(ASTVisitor visitor) { - visitor.visit(this); + public DefinedVariable accept(ASTVisitor visitor) { + return visitor.visit(this); } } diff --git a/net/loveruby/cflat/ast/DereferenceNode.java b/net/loveruby/cflat/ast/DereferenceNode.java index 0559545..238d1a7 100644 --- a/net/loveruby/cflat/ast/DereferenceNode.java +++ b/net/loveruby/cflat/ast/DereferenceNode.java @@ -13,8 +13,8 @@ public class DereferenceNode extends UnaryOpNode { public boolean isAssignable() { return true; } public boolean isConstantAddress() { return false; } - public void accept(ASTVisitor visitor) { - visitor.visit(this); + public DereferenceNode accept(ASTVisitor visitor) { + return visitor.visit(this); } public void acceptLHS(ASTLHSVisitor visitor) { diff --git a/net/loveruby/cflat/ast/DoWhileNode.java b/net/loveruby/cflat/ast/DoWhileNode.java index 9bbab8a..789b25b 100644 --- a/net/loveruby/cflat/ast/DoWhileNode.java +++ b/net/loveruby/cflat/ast/DoWhileNode.java @@ -2,25 +2,19 @@ package net.loveruby.cflat.ast; import net.loveruby.cflat.asm.Label; public class DoWhileNode extends LoopNode { - protected ExprNode cond; - protected Node body; + protected StmtNode body; protected Label continueLabel; - public DoWhileNode(Location loc, Node body, ExprNode cond) { - super(loc); + public DoWhileNode(Location loc, StmtNode body, ExprNode cond) { + super(loc, cond); this.body = body; - this.cond = cond; this.continueLabel = new Label(); } - public Node body() { + public StmtNode body() { return body; } - public ExprNode cond() { - return cond; - } - public Label continueLabel() { return continueLabel; } @@ -30,7 +24,7 @@ public class DoWhileNode extends LoopNode { d.printMember("cond", cond); } - public void accept(ASTVisitor visitor) { - visitor.visit(this); + public DoWhileNode accept(ASTVisitor visitor) { + return visitor.visit(this); } } diff --git a/net/loveruby/cflat/ast/Entity.java b/net/loveruby/cflat/ast/Entity.java index 12d3254..5dfc6c1 100644 --- a/net/loveruby/cflat/ast/Entity.java +++ b/net/loveruby/cflat/ast/Entity.java @@ -89,4 +89,6 @@ abstract public class Entity extends Node { public Location location() { return typeNode.location(); } + + abstract public Entity accept(ASTVisitor visitor); } diff --git a/net/loveruby/cflat/ast/ExprNode.java b/net/loveruby/cflat/ast/ExprNode.java index 4ce0c5c..a8711a3 100644 --- a/net/loveruby/cflat/ast/ExprNode.java +++ b/net/loveruby/cflat/ast/ExprNode.java @@ -61,4 +61,6 @@ abstract public class ExprNode extends Node { public MemoryReference memref() { throw new Error("ExprNode#memref called"); } + + abstract public ExprNode accept(ASTVisitor visitor); } diff --git a/net/loveruby/cflat/ast/ExprStmtNode.java b/net/loveruby/cflat/ast/ExprStmtNode.java new file mode 100644 index 0000000..20abddf --- /dev/null +++ b/net/loveruby/cflat/ast/ExprStmtNode.java @@ -0,0 +1,26 @@ +package net.loveruby.cflat.ast; + +public class ExprStmtNode extends StmtNode { + protected ExprNode expr; + + public ExprStmtNode(Location loc, ExprNode expr) { + super(loc); + this.expr = expr; + } + + public ExprNode expr() { + return expr; + } + + public void setExpr(ExprNode expr) { + this.expr = expr; + } + + protected void _dump(Dumper d) { + d.printMember("expr", expr); + } + + public ExprStmtNode accept(ASTVisitor visitor) { + return visitor.visit(this); + } +} diff --git a/net/loveruby/cflat/ast/ForNode.java b/net/loveruby/cflat/ast/ForNode.java index 8a47660..ff73483 100644 --- a/net/loveruby/cflat/ast/ForNode.java +++ b/net/loveruby/cflat/ast/ForNode.java @@ -2,33 +2,29 @@ package net.loveruby.cflat.ast; import net.loveruby.cflat.asm.Label; public class ForNode extends LoopNode { - protected ExprNode init, cond, incr; - protected Node body; + protected StmtNode init; + protected StmtNode incr; + protected StmtNode body; protected Label continueLabel; public ForNode(Location loc, - ExprNode init, ExprNode cond, ExprNode incr, Node body) { - super(loc); - this.init = init; - this.cond = cond; - this.incr = incr; + ExprNode init, ExprNode cond, ExprNode incr, StmtNode body) { + super(loc, cond); + this.init = new ExprStmtNode(init.location(), init); + this.incr = new ExprStmtNode(incr.location(), incr); this.body = body; this.continueLabel = new Label(); } - public ExprNode init() { + public StmtNode init() { return init; } - public ExprNode cond() { - return cond; - } - - public ExprNode incr() { + public StmtNode incr() { return incr; } - public Node body() { + public StmtNode body() { return body; } @@ -43,7 +39,7 @@ public class ForNode extends LoopNode { d.printMember("body", body); } - public void accept(ASTVisitor visitor) { - visitor.visit(this); + public ForNode accept(ASTVisitor visitor) { + return visitor.visit(this); } } diff --git a/net/loveruby/cflat/ast/FuncallNode.java b/net/loveruby/cflat/ast/FuncallNode.java index 60b389c..f27bc68 100644 --- a/net/loveruby/cflat/ast/FuncallNode.java +++ b/net/loveruby/cflat/ast/FuncallNode.java @@ -77,7 +77,7 @@ public class FuncallNode extends ExprNode { d.printNodeList("arguments", arguments); } - public void accept(ASTVisitor visitor) { - visitor.visit(this); + public FuncallNode accept(ASTVisitor visitor) { + return visitor.visit(this); } } diff --git a/net/loveruby/cflat/ast/GotoNode.java b/net/loveruby/cflat/ast/GotoNode.java index f7eab2c..99561a6 100644 --- a/net/loveruby/cflat/ast/GotoNode.java +++ b/net/loveruby/cflat/ast/GotoNode.java @@ -27,7 +27,7 @@ public class GotoNode extends StmtNode { d.printMember("target", target); } - public void accept(ASTVisitor visitor) { - visitor.visit(this); + public GotoNode accept(ASTVisitor visitor) { + return visitor.visit(this); } } diff --git a/net/loveruby/cflat/ast/IfNode.java b/net/loveruby/cflat/ast/IfNode.java index b850df4..19ca12c 100644 --- a/net/loveruby/cflat/ast/IfNode.java +++ b/net/loveruby/cflat/ast/IfNode.java @@ -3,12 +3,12 @@ import net.loveruby.cflat.asm.Label; public class IfNode extends StmtNode { protected ExprNode cond; - protected Node thenBody; - protected Node elseBody; + protected StmtNode thenBody; + protected StmtNode elseBody; protected Label elseLabel; protected Label endLabel; - public IfNode(Location loc, ExprNode c, Node t, Node e) { + public IfNode(Location loc, ExprNode c, StmtNode t, StmtNode e) { super(loc); this.cond = c; this.thenBody = t; @@ -21,11 +21,15 @@ public class IfNode extends StmtNode { return cond; } - public Node thenBody() { + public void setCond(ExprNode cond) { + this.cond = cond; + } + + public StmtNode thenBody() { return thenBody; } - public Node elseBody() { + public StmtNode elseBody() { return elseBody; } @@ -43,7 +47,7 @@ public class IfNode extends StmtNode { d.printMember("elseBody", elseBody); } - public void accept(ASTVisitor visitor) { - visitor.visit(this); + public IfNode accept(ASTVisitor visitor) { + return visitor.visit(this); } } diff --git a/net/loveruby/cflat/ast/IntegerLiteralNode.java b/net/loveruby/cflat/ast/IntegerLiteralNode.java index e96d46b..c51ec2c 100644 --- a/net/loveruby/cflat/ast/IntegerLiteralNode.java +++ b/net/loveruby/cflat/ast/IntegerLiteralNode.java @@ -29,7 +29,7 @@ public class IntegerLiteralNode extends LiteralNode { d.printMember("value", value); } - public void accept(ASTVisitor visitor) { - visitor.visit(this); + public IntegerLiteralNode accept(ASTVisitor visitor) { + return visitor.visit(this); } } diff --git a/net/loveruby/cflat/ast/LabelNode.java b/net/loveruby/cflat/ast/LabelNode.java index 040dd89..8bca5fb 100644 --- a/net/loveruby/cflat/ast/LabelNode.java +++ b/net/loveruby/cflat/ast/LabelNode.java @@ -3,10 +3,10 @@ import net.loveruby.cflat.asm.Label; public class LabelNode extends StmtNode { protected String name; - protected Node stmt; + protected StmtNode stmt; protected Label label; - public LabelNode(Location loc, String name, Node stmt) { + public LabelNode(Location loc, String name, StmtNode stmt) { super(loc); this.name = name; this.stmt = stmt; @@ -16,7 +16,7 @@ public class LabelNode extends StmtNode { return name; } - public Node stmt() { + public StmtNode stmt() { return stmt; } @@ -34,7 +34,7 @@ public class LabelNode extends StmtNode { d.printMember("stmt", stmt); } - public void accept(ASTVisitor visitor) { - visitor.visit(this); + public LabelNode accept(ASTVisitor visitor) { + return visitor.visit(this); } } diff --git a/net/loveruby/cflat/ast/LogicalAndNode.java b/net/loveruby/cflat/ast/LogicalAndNode.java index f94c129..36deaa7 100644 --- a/net/loveruby/cflat/ast/LogicalAndNode.java +++ b/net/loveruby/cflat/ast/LogicalAndNode.java @@ -9,8 +9,8 @@ public class LogicalAndNode extends BinaryOpNode { this.endLabel = new Label(); } - public void accept(ASTVisitor visitor) { - visitor.visit(this); + public LogicalAndNode accept(ASTVisitor visitor) { + return visitor.visit(this); } public Label endLabel() { diff --git a/net/loveruby/cflat/ast/LogicalOrNode.java b/net/loveruby/cflat/ast/LogicalOrNode.java index ff531ce..c4d50a9 100644 --- a/net/loveruby/cflat/ast/LogicalOrNode.java +++ b/net/loveruby/cflat/ast/LogicalOrNode.java @@ -9,8 +9,8 @@ public class LogicalOrNode extends BinaryOpNode { this.endLabel = new Label(); } - public void accept(ASTVisitor visitor) { - visitor.visit(this); + public LogicalOrNode accept(ASTVisitor visitor) { + return visitor.visit(this); } public Label endLabel() { diff --git a/net/loveruby/cflat/ast/LoopNode.java b/net/loveruby/cflat/ast/LoopNode.java index feb3ec0..47bc3be 100644 --- a/net/loveruby/cflat/ast/LoopNode.java +++ b/net/loveruby/cflat/ast/LoopNode.java @@ -3,14 +3,24 @@ import net.loveruby.cflat.asm.Label; abstract public class LoopNode extends StmtNode implements BreakableStmt, ContinueableStmt { + protected ExprNode cond; protected Label begLabel, endLabel; - public LoopNode(Location loc) { + public LoopNode(Location loc, ExprNode cond) { super(loc); + this.cond = cond; this.begLabel = new Label(); this.endLabel = new Label(); } + public ExprNode cond() { + return cond; + } + + public void setCond(ExprNode cond) { + this.cond = cond; + } + public Label begLabel() { return begLabel; } diff --git a/net/loveruby/cflat/ast/MemberNode.java b/net/loveruby/cflat/ast/MemberNode.java index f3aff1e..8775e93 100644 --- a/net/loveruby/cflat/ast/MemberNode.java +++ b/net/loveruby/cflat/ast/MemberNode.java @@ -56,8 +56,8 @@ public class MemberNode extends ExprNode { d.printMember("member", member); } - public void accept(ASTVisitor visitor) { - visitor.visit(this); + public MemberNode accept(ASTVisitor visitor) { + return visitor.visit(this); } public void acceptLHS(ASTLHSVisitor visitor) { diff --git a/net/loveruby/cflat/ast/Node.java b/net/loveruby/cflat/ast/Node.java index 73de603..3f5ff4d 100644 --- a/net/loveruby/cflat/ast/Node.java +++ b/net/loveruby/cflat/ast/Node.java @@ -22,8 +22,6 @@ abstract public class Node { abstract protected void _dump(Dumper d); - abstract public void accept(ASTVisitor visitor); - public void acceptLHS(ASTLHSVisitor visitor) { throw new Error("wrong node for acceptLHS: " + getClass().getSimpleName()); } diff --git a/net/loveruby/cflat/ast/OpAssignNode.java b/net/loveruby/cflat/ast/OpAssignNode.java index 56bd5db..4d943c4 100644 --- a/net/loveruby/cflat/ast/OpAssignNode.java +++ b/net/loveruby/cflat/ast/OpAssignNode.java @@ -12,7 +12,7 @@ public class OpAssignNode extends AbstractAssignNode { return operator; } - public void accept(ASTVisitor visitor) { - visitor.visit(this); + public OpAssignNode accept(ASTVisitor visitor) { + return visitor.visit(this); } } diff --git a/net/loveruby/cflat/ast/ParamSlots.java b/net/loveruby/cflat/ast/ParamSlots.java index 6147de1..630102a 100644 --- a/net/loveruby/cflat/ast/ParamSlots.java +++ b/net/loveruby/cflat/ast/ParamSlots.java @@ -48,8 +48,4 @@ abstract public class ParamSlots extends Node { protected void _dump(Dumper d) { throw new Error("must not happen: ParamSlots#_dump"); } - - public void accept(ASTVisitor visitor) { - throw new Error("must not happen: ParamSlots#accept"); - } } diff --git a/net/loveruby/cflat/ast/PrefixOpNode.java b/net/loveruby/cflat/ast/PrefixOpNode.java index a138520..dbd6857 100644 --- a/net/loveruby/cflat/ast/PrefixOpNode.java +++ b/net/loveruby/cflat/ast/PrefixOpNode.java @@ -5,7 +5,7 @@ public class PrefixOpNode extends UnaryArithmeticOpNode { super(op, expr); } - public void accept(ASTVisitor visitor) { - visitor.visit(this); + public PrefixOpNode accept(ASTVisitor visitor) { + return visitor.visit(this); } } diff --git a/net/loveruby/cflat/ast/PtrMemberNode.java b/net/loveruby/cflat/ast/PtrMemberNode.java index 2ccec88..d34a71e 100644 --- a/net/loveruby/cflat/ast/PtrMemberNode.java +++ b/net/loveruby/cflat/ast/PtrMemberNode.java @@ -64,8 +64,8 @@ public class PtrMemberNode extends ExprNode { d.printMember("member", member); } - public void accept(ASTVisitor visitor) { - visitor.visit(this); + public PtrMemberNode accept(ASTVisitor visitor) { + return visitor.visit(this); } public void acceptLHS(ASTLHSVisitor visitor) { diff --git a/net/loveruby/cflat/ast/ReturnNode.java b/net/loveruby/cflat/ast/ReturnNode.java index d40d87b..db66f82 100644 --- a/net/loveruby/cflat/ast/ReturnNode.java +++ b/net/loveruby/cflat/ast/ReturnNode.java @@ -33,7 +33,7 @@ public class ReturnNode extends StmtNode { d.printMember("expr", expr); } - public void accept(ASTVisitor visitor) { - visitor.visit(this); + public ReturnNode accept(ASTVisitor visitor) { + return visitor.visit(this); } } diff --git a/net/loveruby/cflat/ast/SizeofExprNode.java b/net/loveruby/cflat/ast/SizeofExprNode.java index 4b30683..f8efbd8 100644 --- a/net/loveruby/cflat/ast/SizeofExprNode.java +++ b/net/loveruby/cflat/ast/SizeofExprNode.java @@ -14,6 +14,10 @@ public class SizeofExprNode extends ExprNode { return this.expr; } + public void setExpr(ExprNode expr) { + this.expr = expr; + } + public Type type() { return this.type.type(); } @@ -30,7 +34,7 @@ public class SizeofExprNode extends ExprNode { d.printMember("expr", expr); } - public void accept(ASTVisitor visitor) { - visitor.visit(this); + public SizeofExprNode accept(ASTVisitor visitor) { + return visitor.visit(this); } } diff --git a/net/loveruby/cflat/ast/SizeofTypeNode.java b/net/loveruby/cflat/ast/SizeofTypeNode.java index 2aac740..04c8f2a 100644 --- a/net/loveruby/cflat/ast/SizeofTypeNode.java +++ b/net/loveruby/cflat/ast/SizeofTypeNode.java @@ -34,7 +34,7 @@ public class SizeofTypeNode extends ExprNode { d.printMember("operand", type); } - public void accept(ASTVisitor visitor) { - visitor.visit(this); + public SizeofTypeNode accept(ASTVisitor visitor) { + return visitor.visit(this); } } diff --git a/net/loveruby/cflat/ast/Slot.java b/net/loveruby/cflat/ast/Slot.java index 05bc1a7..88aa908 100644 --- a/net/loveruby/cflat/ast/Slot.java +++ b/net/loveruby/cflat/ast/Slot.java @@ -56,8 +56,4 @@ public class Slot extends Node { d.printMember("name", name); d.printMember("typeNode", typeNode); } - - public void accept(ASTVisitor visitor) { - throw new Error("Slot#accept"); - } } diff --git a/net/loveruby/cflat/ast/StmtNode.java b/net/loveruby/cflat/ast/StmtNode.java index f86c879..c625626 100644 --- a/net/loveruby/cflat/ast/StmtNode.java +++ b/net/loveruby/cflat/ast/StmtNode.java @@ -10,4 +10,6 @@ abstract public class StmtNode extends Node { public Location location() { return location; } + + abstract public StmtNode accept(ASTVisitor visitor); } diff --git a/net/loveruby/cflat/ast/StringLiteralNode.java b/net/loveruby/cflat/ast/StringLiteralNode.java index f9e3cd9..3debeb6 100644 --- a/net/loveruby/cflat/ast/StringLiteralNode.java +++ b/net/loveruby/cflat/ast/StringLiteralNode.java @@ -51,7 +51,7 @@ public class StringLiteralNode extends LiteralNode { d.printMember("value", value); } - public void accept(ASTVisitor visitor) { - visitor.visit(this); + public StringLiteralNode accept(ASTVisitor visitor) { + return visitor.visit(this); } } diff --git a/net/loveruby/cflat/ast/StructNode.java b/net/loveruby/cflat/ast/StructNode.java index 85e5315..230010a 100644 --- a/net/loveruby/cflat/ast/StructNode.java +++ b/net/loveruby/cflat/ast/StructNode.java @@ -21,7 +21,7 @@ public class StructNode extends CompositeTypeDefinition { } // #@@} - public void accept(ASTVisitor visitor) { - visitor.visit(this); + public StructNode accept(ASTVisitor visitor) { + return visitor.visit(this); } } diff --git a/net/loveruby/cflat/ast/SuffixOpNode.java b/net/loveruby/cflat/ast/SuffixOpNode.java index b549ad7..4c40c8d 100644 --- a/net/loveruby/cflat/ast/SuffixOpNode.java +++ b/net/loveruby/cflat/ast/SuffixOpNode.java @@ -5,7 +5,7 @@ public class SuffixOpNode extends UnaryArithmeticOpNode { super(op, expr); } - public void accept(ASTVisitor visitor) { - visitor.visit(this); + public SuffixOpNode accept(ASTVisitor visitor) { + return visitor.visit(this); } } diff --git a/net/loveruby/cflat/ast/SwitchNode.java b/net/loveruby/cflat/ast/SwitchNode.java index 8f3cd65..817b4ee 100644 --- a/net/loveruby/cflat/ast/SwitchNode.java +++ b/net/loveruby/cflat/ast/SwitchNode.java @@ -18,6 +18,10 @@ public class SwitchNode extends StmtNode implements BreakableStmt { return cond; } + public void setCond(ExprNode cond) { + this.cond = cond; + } + public List cases() { return cases; } @@ -31,7 +35,7 @@ public class SwitchNode extends StmtNode implements BreakableStmt { d.printNodeList("cases", cases); } - public void accept(ASTVisitor visitor) { - visitor.visit(this); + public SwitchNode accept(ASTVisitor visitor) { + return visitor.visit(this); } } diff --git a/net/loveruby/cflat/ast/TypeDefinition.java b/net/loveruby/cflat/ast/TypeDefinition.java index fa49553..8df5b05 100644 --- a/net/loveruby/cflat/ast/TypeDefinition.java +++ b/net/loveruby/cflat/ast/TypeDefinition.java @@ -33,4 +33,5 @@ abstract public class TypeDefinition extends Node { } abstract public Type definingType(); + abstract public TypeDefinition accept(ASTVisitor visitor); } diff --git a/net/loveruby/cflat/ast/TypeNode.java b/net/loveruby/cflat/ast/TypeNode.java index f53bc2d..3609dae 100644 --- a/net/loveruby/cflat/ast/TypeNode.java +++ b/net/loveruby/cflat/ast/TypeNode.java @@ -42,7 +42,7 @@ public class TypeNode extends Node { d.printMember("type", type); } - public void accept(ASTVisitor visitor) { + public TypeNode accept(ASTVisitor visitor) { throw new Error("do not call TypeNode#accept"); } } diff --git a/net/loveruby/cflat/ast/TypedefNode.java b/net/loveruby/cflat/ast/TypedefNode.java index 9c778e7..fb5d79d 100644 --- a/net/loveruby/cflat/ast/TypedefNode.java +++ b/net/loveruby/cflat/ast/TypedefNode.java @@ -36,7 +36,7 @@ public class TypedefNode extends TypeDefinition { d.printMember("typeNode", typeNode); } - public void accept(ASTVisitor visitor) { - visitor.visit(this); + public TypedefNode accept(ASTVisitor visitor) { + return visitor.visit(this); } } diff --git a/net/loveruby/cflat/ast/UnaryArithmeticOpNode.java b/net/loveruby/cflat/ast/UnaryArithmeticOpNode.java index 468fc61..dece4fe 100644 --- a/net/loveruby/cflat/ast/UnaryArithmeticOpNode.java +++ b/net/loveruby/cflat/ast/UnaryArithmeticOpNode.java @@ -8,6 +8,10 @@ public class UnaryArithmeticOpNode extends UnaryOpNode { amount = 1; } + public void setExpr(ExprNode expr) { + this.expr = expr; + } + public long amount() { return this.amount; } diff --git a/net/loveruby/cflat/ast/UnaryOpNode.java b/net/loveruby/cflat/ast/UnaryOpNode.java index 6fc9f09..a7b890f 100644 --- a/net/loveruby/cflat/ast/UnaryOpNode.java +++ b/net/loveruby/cflat/ast/UnaryOpNode.java @@ -40,7 +40,7 @@ public class UnaryOpNode extends ExprNode { d.printMember("expr", expr); } - public void accept(ASTVisitor visitor) { - visitor.visit(this); + public UnaryOpNode accept(ASTVisitor visitor) { + return visitor.visit(this); } } diff --git a/net/loveruby/cflat/ast/UndefinedFunction.java b/net/loveruby/cflat/ast/UndefinedFunction.java index a995a47..433781b 100644 --- a/net/loveruby/cflat/ast/UndefinedFunction.java +++ b/net/loveruby/cflat/ast/UndefinedFunction.java @@ -25,7 +25,7 @@ public class UndefinedFunction extends Function { d.printMember("params", params); } - public void accept(ASTVisitor visitor) { - visitor.visit(this); + public UndefinedFunction accept(ASTVisitor visitor) { + return visitor.visit(this); } } diff --git a/net/loveruby/cflat/ast/UndefinedVariable.java b/net/loveruby/cflat/ast/UndefinedVariable.java index acdd4a9..240047e 100644 --- a/net/loveruby/cflat/ast/UndefinedVariable.java +++ b/net/loveruby/cflat/ast/UndefinedVariable.java @@ -16,7 +16,7 @@ public class UndefinedVariable extends Variable { d.printMember("typeNode", typeNode); } - public void accept(ASTVisitor visitor) { - visitor.visit(this); + public UndefinedVariable accept(ASTVisitor visitor) { + return visitor.visit(this); } } diff --git a/net/loveruby/cflat/ast/UnionNode.java b/net/loveruby/cflat/ast/UnionNode.java index 462361d..a5dd5a7 100644 --- a/net/loveruby/cflat/ast/UnionNode.java +++ b/net/loveruby/cflat/ast/UnionNode.java @@ -21,7 +21,7 @@ public class UnionNode extends CompositeTypeDefinition { } // #@@} - public void accept(ASTVisitor visitor) { - visitor.visit(this); + public UnionNode accept(ASTVisitor visitor) { + return visitor.visit(this); } } diff --git a/net/loveruby/cflat/ast/VariableNode.java b/net/loveruby/cflat/ast/VariableNode.java index 3f02638..e1d55dd 100644 --- a/net/loveruby/cflat/ast/VariableNode.java +++ b/net/loveruby/cflat/ast/VariableNode.java @@ -73,8 +73,8 @@ public class VariableNode extends ExprNode { d.printMember("name", name, isResolved()); } - public void accept(ASTVisitor visitor) { - visitor.visit(this); + public VariableNode accept(ASTVisitor visitor) { + return visitor.visit(this); } public void acceptLHS(ASTLHSVisitor visitor) { diff --git a/net/loveruby/cflat/ast/WhileNode.java b/net/loveruby/cflat/ast/WhileNode.java index 45f2672..dd2ce42 100644 --- a/net/loveruby/cflat/ast/WhileNode.java +++ b/net/loveruby/cflat/ast/WhileNode.java @@ -2,20 +2,14 @@ package net.loveruby.cflat.ast; import net.loveruby.cflat.asm.Label; public class WhileNode extends LoopNode { - protected ExprNode cond; - protected Node body; + protected StmtNode body; - public WhileNode(Location loc, ExprNode cond, Node body) { - super(loc); - this.cond = cond; + public WhileNode(Location loc, ExprNode cond, StmtNode body) { + super(loc, cond); this.body = body; } - public ExprNode cond() { - return cond; - } - - public Node body() { + public StmtNode body() { return body; } @@ -28,7 +22,7 @@ public class WhileNode extends LoopNode { d.printMember("body", body); } - public void accept(ASTVisitor visitor) { - visitor.visit(this); + public WhileNode accept(ASTVisitor visitor) { + return visitor.visit(this); } } diff --git a/net/loveruby/cflat/compiler/CodeGenerator.java b/net/loveruby/cflat/compiler/CodeGenerator.java index 2816799..c0a8c9f 100644 --- a/net/loveruby/cflat/compiler/CodeGenerator.java +++ b/net/loveruby/cflat/compiler/CodeGenerator.java @@ -455,7 +455,7 @@ public class CodeGenerator protected List compileStmts(DefinedFunction func) { pushAssembler(); currentFunction = func; - compile(func.body()); + compileStmt(func.body()); label(func.epilogueLabel()); currentFunction = null; return options.optimizer().optimize(popAssembler().assemblies()); @@ -477,20 +477,6 @@ public class CodeGenerator } // #@@} - // #@@range/compile{ - protected void compile(Node n) { - if (options.isVerboseAsm()) { - comment(n.getClass().getSimpleName() + " {"); - as.indentComment(); - } - n.accept(this); - if (options.isVerboseAsm()) { - as.unindentComment(); - comment("}"); - } - } - // #@@} - protected List usedCalleeSavedRegistersWithoutBP(AsmStatistics stats) { List result = new ArrayList(); for (Register reg : calleeSavedRegisters()) { @@ -724,7 +710,7 @@ public class CodeGenerator * * Rewind stack by caller. */ // #@@range/compile_Funcall{ - public void visit(FuncallNode node) { + public FuncallNode visit(FuncallNode node) { // compile function arguments from right to left. ListIterator args = node.finalArg(); while (args.hasPrevious()) { @@ -744,15 +730,17 @@ public class CodeGenerator // rewind stack // >4 bytes arguments are not supported. rewindStack(node.numArgs() * stackWordSize); + return null; } // #@@} // #@@range/compile_Return{ - public void visit(ReturnNode node) { + public ReturnNode visit(ReturnNode node) { if (node.expr() != null) { compile(node.expr()); } jmp(currentFunction.epilogueLabel()); + return null; } // #@@} @@ -761,28 +749,34 @@ public class CodeGenerator // // #@@range/compile_Block{ - public void visit(BlockNode node) { + public BlockNode visit(BlockNode node) { for (DefinedVariable var : node.scope().localVariables()) { if (var.initializer() != null) { compile(var.initializer()); save(var.type(), reg("ax"), var.memref()); } } - for (Node stmt : node.stmts()) { + for (StmtNode stmt : node.stmts()) { compileStmt(stmt); } + return null; } // #@@} // #@@range/compileStmt{ - protected void compileStmt(Node node) { + protected void compileStmt(StmtNode node) { if (options.isVerboseAsm()) { comment(node.location().numberedLine()); } - compile(node); + node.accept(this); } // #@@} + public ExprStmtNode visit(ExprStmtNode node) { + compile(node.expr()); + return null; + } + // #@@range/testCond{ private void testCond(Type t, Register reg) { test(t, reg.forType(t), reg.forType(t)); @@ -790,7 +784,7 @@ public class CodeGenerator // #@@} // #@@range/compile_If{ - public void visit(IfNode node) { + public IfNode visit(IfNode node) { compile(node.cond()); testCond(node.cond().type(), reg("ax")); if (node.elseBody() != null) { @@ -806,11 +800,12 @@ public class CodeGenerator compileStmt(node.thenBody()); label(node.endLabel()); } + return null; } // #@@} // #@@range/compile_CondExpr{ - public void visit(CondExprNode node) { + public CondExprNode visit(CondExprNode node) { compile(node.cond()); testCond(node.cond().type(), reg("ax")); jz(node.elseLabel()); @@ -819,11 +814,12 @@ public class CodeGenerator label(node.elseLabel()); compile(node.elseExpr()); label(node.endLabel()); + return null; } // #@@} // #@@range/compile_Switch{ - public void visit(SwitchNode node) { + public SwitchNode visit(SwitchNode node) { compile(node.cond()); Type t = typeTable.signedInt(); for (CaseNode cn : node.cases()) { @@ -841,41 +837,45 @@ public class CodeGenerator } jmp(node.endLabel()); for (CaseNode n : node.cases()) { - compile(n); + compileStmt(n); } label(node.endLabel()); + return null; } // #@@} // #@@range/compile_Case{ - public void visit(CaseNode node) { + public CaseNode visit(CaseNode node) { label(node.beginLabel()); - compile(node.body()); + compileStmt(node.body()); + return null; } // #@@} // #@@range/compile_LogicalAnd{ - public void visit(LogicalAndNode node) { + public LogicalAndNode visit(LogicalAndNode node) { compile(node.left()); testCond(node.left().type(), reg("ax")); jz(node.endLabel()); compile(node.right()); label(node.endLabel()); + return null; } // #@@} // #@@range/compile_LogicalOr{ - public void visit(LogicalOrNode node) { + public LogicalOrNode visit(LogicalOrNode node) { compile(node.left()); testCond(node.left().type(), reg("ax")); jnz(node.endLabel()); compile(node.right()); label(node.endLabel()); + return null; } // #@@} // #@@range/compile_While{ - public void visit(WhileNode node) { + public WhileNode visit(WhileNode node) { label(node.begLabel()); compile(node.cond()); testCond(node.cond().type(), reg("ax")); @@ -883,10 +883,11 @@ public class CodeGenerator compileStmt(node.body()); jmp(node.begLabel()); label(node.endLabel()); + return null; } // #@@} - public void visit(DoWhileNode node) { + public DoWhileNode visit(DoWhileNode node) { label(node.begLabel()); compileStmt(node.body()); label(node.continueLabel()); @@ -894,10 +895,11 @@ public class CodeGenerator testCond(node.cond().type(), reg("ax")); jnz(node.begLabel()); label(node.endLabel()); + return null; } // #@@range/compile_For{ - public void visit(ForNode node) { + public ForNode visit(ForNode node) { compileStmt(node.init()); label(node.begLabel()); compile(node.cond()); @@ -908,31 +910,36 @@ public class CodeGenerator compileStmt(node.incr()); jmp(node.begLabel()); label(node.endLabel()); + return null; } // #@@} // #@@range/compile_Break{ - public void visit(BreakNode node) { + public BreakNode visit(BreakNode node) { jmp(node.targetLabel()); + return null; } // #@@} // #@@range/compile_Continue{ - public void visit(ContinueNode node) { + public ContinueNode visit(ContinueNode node) { jmp(node.targetLabel()); + return null; } // #@@} // #@@range/compile_Label{ - public void visit(LabelNode node) { + public LabelNode visit(LabelNode node) { label(node.label()); compileStmt(node.stmt()); + return null; } // #@@} // #@@range/compile_Goto{ - public void visit(GotoNode node) { + public GotoNode visit(GotoNode node) { jmp(node.targetLabel()); + return null; } // #@@} @@ -940,8 +947,22 @@ public class CodeGenerator // Expressions // + // #@@range/compile{ + protected void compile(ExprNode n) { + if (options.isVerboseAsm()) { + comment(n.getClass().getSimpleName() + " {"); + as.indentComment(); + } + n.accept(this); + if (options.isVerboseAsm()) { + as.unindentComment(); + comment("}"); + } + } + // #@@} + // #@@range/compile_BinaryOp{ - public void visit(BinaryOpNode node) { + public BinaryOpNode visit(BinaryOpNode node) { AsmOperand right = null; if (!doesRequireRegister(node.operator()) && node.right().isConstant()){ compile(node.left()); @@ -960,6 +981,7 @@ public class CodeGenerator right = reg("cx", node.type()); } compileBinaryOp(node.operator(), node.type(), right); + return null; } // #@@} @@ -1062,7 +1084,7 @@ public class CodeGenerator // #@@} // #@@range/compile_UnaryOp{ - public void visit(UnaryOpNode node) { + public UnaryOpNode visit(UnaryOpNode node) { compile(node.expr()); if (node.operator().equals("+")) { ; @@ -1078,11 +1100,12 @@ public class CodeGenerator sete(al()); movzbl(al(), reg("ax")); } + return null; } // #@@} // #@@range/compile_PrefixOp{ - public void visit(PrefixOpNode node) { + public PrefixOpNode visit(PrefixOpNode node) { if (node.expr().isConstantAddress()) { load(node.expr().type(), node.expr().memref(), reg("ax")); compileUnaryArithmetic(node, reg("ax")); @@ -1095,11 +1118,12 @@ public class CodeGenerator compileUnaryArithmetic(node, reg("ax")); save(node.expr().type(), reg("ax"), mem(reg("cx"))); } + return null; } // #@@} // #@@range/compile_SuffixOp{ - public void visit(SuffixOpNode node) { + public SuffixOpNode visit(SuffixOpNode node) { if (node.expr().isConstantAddress()) { load(node.expr().type(), node.expr().memref(), reg("ax")); mov(reg("ax"), reg("cx")); @@ -1114,6 +1138,7 @@ public class CodeGenerator compileUnaryArithmetic(node, reg("dx")); save(node.expr().type(), reg("dx"), mem(reg("cx"))); } + return null; } // #@@} @@ -1134,7 +1159,7 @@ public class CodeGenerator // #@@} // #@@range/compile_Cast{ - public void visit(CastNode node) { + public CastNode visit(CastNode node) { compile(node.expr()); // We need not execute downcast because we can cast big value // to small value by just cutting off higer bits. @@ -1150,38 +1175,44 @@ public class CodeGenerator reg("ax").forType(src), reg("ax").forType(dest)); } } + return null; } // #@@} // #@@range/compile_SizeofExpr{ - public void visit(SizeofExprNode node) { + public SizeofExprNode visit(SizeofExprNode node) { long val = node.expr().type().allocSize(); mov(node.type(), imm(val), reg("ax", node.type())); + return null; } // #@@} // #@@range/compile_SizeofType{ - public void visit(SizeofTypeNode node) { + public SizeofTypeNode visit(SizeofTypeNode node) { long val = node.operand().allocSize(); mov(node.type(), imm(val), reg("ax", node.type())); + return null; } // #@@} // #@@range/compile_Variable{ - public void visit(VariableNode node) { + public VariableNode visit(VariableNode node) { loadVariable(node, reg("ax")); + return null; } // #@@} // #@@range/compile_IntegerLiteral{ - public void visit(IntegerLiteralNode node) { + public IntegerLiteralNode visit(IntegerLiteralNode node) { loadConstant(node, reg("ax")); + return null; } // #@@} // #@@range/compile_StringLiteral{ - public void visit(StringLiteralNode node) { + public StringLiteralNode visit(StringLiteralNode node) { loadConstant(node, reg("ax")); + return null; } // #@@} @@ -1190,7 +1221,7 @@ public class CodeGenerator // // #@@range/compile_Assign{ - public void visit(AssignNode node) { + public AssignNode visit(AssignNode node) { if (node.lhs().isConstantAddress() && node.lhs().memref() != null) { compile(node.rhs()); save(node.type(), reg("ax"), node.lhs().memref()); @@ -1209,11 +1240,12 @@ public class CodeGenerator pop(reg("ax")); save(node.type(), reg("ax"), mem(reg("cx"))); } + return null; } // #@@} // #@@range/compile_OpAssign{ - public void visit(OpAssignNode node) { + public OpAssignNode visit(OpAssignNode node) { if (node.lhs().isConstantAddress() && node.lhs().memref() != null) { // const += ANY compile(node.rhs()); @@ -1254,18 +1286,20 @@ public class CodeGenerator compileBinaryOp(node.operator(), node.type(), reg("cx")); save(node.type(), reg("ax"), mem(lhs)); } + return null; } // #@@} // #@@range/compile_Aref{ - public void visit(ArefNode node) { + public ArefNode visit(ArefNode node) { compileLHS(node); load(node.type(), mem(reg("ax")), reg("ax")); + return null; } // #@@} // #@@range/compile_Member{ - public void visit(MemberNode node) { + public MemberNode visit(MemberNode node) { compileLHS(node.expr()); if (node.shouldEvaluatedToAddress()) { add(imm(node.offset()), reg("ax")); @@ -1273,11 +1307,12 @@ public class CodeGenerator else { load(node.type(), mem(node.offset(), reg("ax")), reg("ax")); } + return null; } // #@@} // #@@range/compile_PtrMember{ - public void visit(PtrMemberNode node) { + public PtrMemberNode visit(PtrMemberNode node) { compile(node.expr()); if (node.shouldEvaluatedToAddress()) { add(imm(node.offset()), reg("ax")); @@ -1285,19 +1320,22 @@ public class CodeGenerator else { load(node.type(), mem(node.offset(), reg("ax")), reg("ax")); } + return null; } // #@@} // #@@range/compile_Dereference{ - public void visit(DereferenceNode node) { + public DereferenceNode visit(DereferenceNode node) { compile(node.expr()); load(node.type(), mem(reg("ax")), reg("ax")); + return null; } // #@@} // #@@range/compile_Address{ - public void visit(AddressNode node) { + public AddressNode visit(AddressNode node) { compileLHS(node.expr()); + return null; } // #@@} diff --git a/net/loveruby/cflat/compiler/DereferenceChecker.java b/net/loveruby/cflat/compiler/DereferenceChecker.java index 9c2c74b..fcd12d2 100644 --- a/net/loveruby/cflat/compiler/DereferenceChecker.java +++ b/net/loveruby/cflat/compiler/DereferenceChecker.java @@ -23,19 +23,23 @@ class DereferenceChecker extends Visitor { } } - protected void check(Node node) { - visitNode(node); + protected void check(StmtNode node) { + node.accept(this); + } + + protected void check(ExprNode node) { + node.accept(this); } // // Statements // - public void visit(BlockNode node) { + public BlockNode visit(BlockNode node) { for (DefinedVariable var : node.variables()) { checkVariable(var); } - for (Node stmt : node.stmts()) { + for (StmtNode stmt : node.stmts()) { try { check(stmt); } @@ -43,6 +47,7 @@ class DereferenceChecker extends Visitor { ; } } + return null; } protected void checkVariable(DefinedVariable var) { @@ -60,14 +65,16 @@ class DereferenceChecker extends Visitor { // Assignment Expressions // - public void visit(AssignNode node) { + public AssignNode visit(AssignNode node) { super.visit(node); checkAssignment(node); + return null; } - public void visit(OpAssignNode node) { + public OpAssignNode visit(OpAssignNode node) { super.visit(node); checkAssignment(node); + return null; } protected void checkAssignment(AbstractAssignNode node) { @@ -80,45 +87,51 @@ class DereferenceChecker extends Visitor { // Expressions // - public void visit(PrefixOpNode node) { + public PrefixOpNode visit(PrefixOpNode node) { super.visit(node); if (! node.expr().isAssignable()) { semanticError(node.expr(), "cannot increment/decrement"); } + return null; } - public void visit(SuffixOpNode node) { + public SuffixOpNode visit(SuffixOpNode node) { super.visit(node); if (! node.expr().isAssignable()) { semanticError(node.expr(), "cannot increment/decrement"); } + return null; } - public void visit(FuncallNode node) { + public FuncallNode visit(FuncallNode node) { super.visit(node); if (! node.expr().isCallable()) { semanticError(node, "calling object is not a function"); } + return null; } - public void visit(ArefNode node) { + public ArefNode visit(ArefNode node) { super.visit(node); if (! node.expr().isDereferable()) { semanticError(node, "indexing non-array/pointer expression"); } + return null; } - public void visit(MemberNode node) { + public MemberNode visit(MemberNode node) { super.visit(node); checkMemberRef(node, node.expr().type(), node.member()); + return null; } - public void visit(PtrMemberNode node) { + public PtrMemberNode visit(PtrMemberNode node) { super.visit(node); if (! node.expr().isDereferable()) { undereferableError(node); } checkMemberRef(node, node.dereferedType(), node.member()); + return null; } protected void checkMemberRef(Node node, Type t, String memb) { @@ -133,18 +146,20 @@ class DereferenceChecker extends Visitor { } } - public void visit(DereferenceNode node) { + public DereferenceNode visit(DereferenceNode node) { super.visit(node); if (! node.expr().isDereferable()) { undereferableError(node); } + return null; } - public void visit(AddressNode node) { + public AddressNode visit(AddressNode node) { super.visit(node); if (! node.expr().isAssignable()) { semanticError(node, "invalid LHS expression for &"); } + return null; } // diff --git a/net/loveruby/cflat/compiler/JumpResolver.java b/net/loveruby/cflat/compiler/JumpResolver.java index 0bc288a..642c5cb 100644 --- a/net/loveruby/cflat/compiler/JumpResolver.java +++ b/net/loveruby/cflat/compiler/JumpResolver.java @@ -31,39 +31,46 @@ public class JumpResolver extends Visitor { } // #@@} - protected void resolve(Node n) { - visitNode(n); + protected void resolve(StmtNode n) { + n.accept(this); } - public void visit(SwitchNode node) { + protected void resolve(ExprNode n) { + n.accept(this); + } + + public SwitchNode visit(SwitchNode node) { resolve(node.cond()); breakTargetStack.add(node); - visitNodeList(node.cases()); + visitStmts(node.cases()); breakTargetStack.removeLast(); + return null; } // #@@range/_while{ - public void visit(WhileNode node) { + public WhileNode visit(WhileNode node) { resolve(node.cond()); breakTargetStack.add(node); continueTargetStack.add(node); resolve(node.body()); continueTargetStack.removeLast(); breakTargetStack.removeLast(); + return null; } // #@@} - public void visit(DoWhileNode node) { + public DoWhileNode visit(DoWhileNode node) { breakTargetStack.add(node); continueTargetStack.add(node); resolve(node.body()); continueTargetStack.removeLast(); breakTargetStack.removeLast(); resolve(node.cond()); + return null; } // #@@range/_for{ - public void visit(ForNode node) { + public ForNode visit(ForNode node) { resolve(node.init()); resolve(node.cond()); breakTargetStack.add(node); @@ -72,34 +79,37 @@ public class JumpResolver extends Visitor { resolve(node.incr()); continueTargetStack.removeLast(); breakTargetStack.removeLast(); + return null; } // #@@} // #@@range/_break{ - public void visit(BreakNode node) { + public BreakNode visit(BreakNode node) { if (breakTargetStack.isEmpty()) { - errorHandler.error(node.location(), + errorHandler.error(node.location(), "break from out of while/do-while/for/switch"); - return; + return null; } BreakableStmt target = breakTargetStack.getLast(); node.setTargetLabel(target.endLabel()); + return null; } // #@@} // #@@range/_continue{ - public void visit(ContinueNode node) { + public ContinueNode visit(ContinueNode node) { if (breakTargetStack.isEmpty()) { errorHandler.error(node.location(), "continue from out of while/do-while/for"); - return; + return null; } ContinueableStmt target = continueTargetStack.getLast(); node.setTargetLabel(target.continueLabel()); + return null; } // #@@} - public void visit(LabelNode node) { + public LabelNode visit(LabelNode node) { try { Label label = currentFunction.defineLabel(node.name(), node.location()); @@ -108,13 +118,16 @@ public class JumpResolver extends Visitor { catch (SemanticException ex) { errorHandler.error(node.location(), ex.getMessage()); } + return null; } - public void visit(GotoNode node) { + public GotoNode visit(GotoNode node) { node.setTargetLabel(currentFunction.referLabel(node.target())); + return null; } - public void visit(ReturnNode node) { + public ReturnNode visit(ReturnNode node) { node.setFunction(currentFunction); + return null; } } diff --git a/net/loveruby/cflat/compiler/LocalResolver.java b/net/loveruby/cflat/compiler/LocalResolver.java index 68c96b5..86eff9a 100644 --- a/net/loveruby/cflat/compiler/LocalResolver.java +++ b/net/loveruby/cflat/compiler/LocalResolver.java @@ -15,8 +15,12 @@ public class LocalResolver extends Visitor { } // #@@} - protected void resolve(Node n) { - visitNode(n); + protected void resolve(StmtNode n) { + n.accept(this); + } + + protected void resolve(ExprNode n) { + n.accept(this); } // #@@range/resolve{ @@ -66,10 +70,11 @@ public class LocalResolver extends Visitor { // #@@} // #@@range/BlockNode{ - public void visit(BlockNode node) { + public BlockNode visit(BlockNode node) { pushScope(node.variables()); super.visit(node); node.setScope(popScope()); + return null; } // #@@} @@ -101,13 +106,14 @@ public class LocalResolver extends Visitor { // #@@} // #@@range/StringLiteralNode{ - public void visit(StringLiteralNode node) { + public StringLiteralNode visit(StringLiteralNode node) { node.setEntry(constantTable.intern(node.value())); + return null; } // #@@} // #@@range/VariableNode{ - public void visit(VariableNode node) { + public VariableNode visit(VariableNode node) { try { Entity ent = currentScope().get(node.name()); ent.refered(); @@ -116,6 +122,7 @@ public class LocalResolver extends Visitor { catch (SemanticException ex) { error(node, ex.getMessage()); } + return null; } // #@@} diff --git a/net/loveruby/cflat/compiler/TypeChecker.java b/net/loveruby/cflat/compiler/TypeChecker.java index 6b16bbd..881785d 100644 --- a/net/loveruby/cflat/compiler/TypeChecker.java +++ b/net/loveruby/cflat/compiler/TypeChecker.java @@ -4,7 +4,7 @@ import net.loveruby.cflat.type.*; import net.loveruby.cflat.exception.*; import java.util.*; -class TypeChecker extends Visitor { +class TypeChecker implements ASTVisitor { protected TypeTable typeTable; protected ErrorHandler errorHandler; @@ -14,20 +14,14 @@ class TypeChecker extends Visitor { } // #@@} - protected void check(Node node) { - visitNode(node); - } - // #@@range/check_AST{ public void check(AST ast) throws SemanticException { this.typeTable = ast.typeTable(); for (DefinedVariable var : ast.definedVariables()) { - checkVariable(var); + visit(var); } for (DefinedFunction f : ast.definedFunctions()) { - checkReturnType(f); - checkParamTypes(f); - check(f.body()); + visit(f); } if (errorHandler.errorOccured()) { throw new SemanticException("compile failed."); @@ -35,6 +29,37 @@ class TypeChecker extends Visitor { } // #@@} + public DefinedFunction visit(DefinedFunction f) { + checkReturnType(f); + checkParamTypes(f); + checkStmt(f.body()); + return null; + } + + public UndefinedFunction visit(UndefinedFunction var) { + throw new Error("must not happen: TypeChecker.visit:UndefinedFunction"); + } + + public DefinedVariable visit(DefinedVariable var) { + if (isInvalidVariableType(var.type())) { + error(var, "invalid variable type"); + return null; + } + if (var.hasInitializer()) { + if (isInvalidLHSType(var.type())) { + error(var, "invalid LHS type: " + var.type()); + return null; + } + var.setInitializer(implicitCast(var.type(), + checkExpr(var.initializer()))); + } + return null; + } + + public UndefinedVariable visit(UndefinedVariable var) { + throw new Error("must not happen: TypeChecker.visit:UndefinedVariable"); + } + protected void checkReturnType(DefinedFunction f) { if (isInvalidReturnType(f.returnType())) { error(f, "returns invalid type: " + f.returnType()); @@ -49,67 +74,115 @@ class TypeChecker extends Visitor { } } + protected void checkStmt(StmtNode node) { + node.accept(this); + } + + protected ExprNode checkExpr(ExprNode node) { + if (node == null) return null; + return node.accept(this); + } + // - // Statements + // Declarations // - public void visit(BlockNode node) { + public StructNode visit(StructNode node) { + return null; + } + + public UnionNode visit(UnionNode node) { + return null; + } + + public TypedefNode visit(TypedefNode node) { + return null; + } + + // + // Statements: replaces expr and returns null. + // + + public BlockNode visit(BlockNode node) { for (DefinedVariable var : node.variables()) { - checkVariable(var); + visit(var); } - for (Node n : node.stmts()) { - if (n instanceof ExprNode) { - ExprNode expr = (ExprNode)n; - if (isInvalidStatementType(expr.type())) { - error(expr, "invalid statement type: " + expr.type()); - return; - } - } - check(n); + for (StmtNode n : node.stmts()) { + checkStmt(n); } + return null; } - protected void checkVariable(DefinedVariable var) { - if (isInvalidVariableType(var.type())) { - error(var, "invalid variable type"); - return; + public ExprStmtNode visit(ExprStmtNode node) { + ExprNode expr = checkExpr(node.expr()); + if (isInvalidStatementType(expr.type())) { + error(expr, "invalid statement type: " + expr.type()); + return null; } - if (var.hasInitializer()) { - if (isInvalidLHSType(var.type())) { - error(var, "invalid LHS type: " + var.type()); - return; - } - check(var.initializer()); - var.setInitializer(implicitCast(var.type(), var.initializer())); + node.setExpr(expr); + return null; + } + + public IfNode visit(IfNode node) { + node.setCond(checkCond(node.cond())); + checkStmt(node.thenBody()); + if (node.elseBody() != null) { + checkStmt(node.elseBody()); } + return null; } - public void visit(IfNode node) { - super.visit(node); - checkCond(node.cond()); + public WhileNode visit(WhileNode node) { + node.setCond(checkCond(node.cond())); + checkStmt(node.body()); + return null; } - public void visit(WhileNode node) { - super.visit(node); - checkCond(node.cond()); + public DoWhileNode visit(DoWhileNode node) { + checkStmt(node.body()); + node.setCond(checkCond(node.cond())); + return null; } - public void visit(ForNode node) { - super.visit(node); - checkCond(node.cond()); + public ForNode visit(ForNode node) { + checkStmt(node.init()); + node.setCond(checkCond(node.cond())); + checkStmt(node.incr()); + checkStmt(node.body()); + return null; } - protected void checkCond(ExprNode cond) { - mustBeScalar(cond, "condition expression"); + protected ExprNode checkCond(ExprNode cond) { + ExprNode expr = checkExpr(cond); + mustBeScalar(expr, "condition expression"); + return expr; } - public void visit(SwitchNode node) { - super.visit(node); - mustBeInteger(node.cond(), "condition expression"); + public SwitchNode visit(SwitchNode node) { + ExprNode expr = checkExpr(node.cond()); + mustBeInteger(expr, "condition expression"); + node.setCond(expr); + for (CaseNode n : node.cases()) { + checkStmt(n); + } + return null; } - public void visit(ReturnNode node) { - super.visit(node); + public CaseNode visit(CaseNode node) { + List exprs = new ArrayList(); + for (ExprNode expr : node.values()) { + ExprNode e = checkExpr(expr); + mustBeInteger(e, "case"); + exprs.add(e); + } + node.setValues(exprs); + return null; + } + + public ReturnNode visit(ReturnNode node) { + if (node.expr() != null) { + node.setExpr(checkExpr(node.expr())); + } if (node.function().isVoid()) { if (node.expr() != null) { error(node, "returning value from void function"); @@ -118,53 +191,72 @@ class TypeChecker extends Visitor { else { // non-void function if (node.expr() == null) { error(node, "missing return value"); - return; + return null; } if (node.expr().type().isVoid()) { error(node, "returning void"); - return; + return null; } node.setExpr(implicitCast(node.function().returnType(), node.expr())); } + return null; + } + + public LabelNode visit(LabelNode node) { + checkStmt(node.stmt()); + return null; + } + + public GotoNode visit(GotoNode node) { + return null; + } + + public ContinueNode visit(ContinueNode node) { + return null; + } + + public BreakNode visit(BreakNode node) { + return null; } // // Assignment Expressions // - public void visit(AssignNode node) { - super.visit(node); - if (! checkLHS(node.lhs())) return; - if (! checkRHS(node.rhs())) return; - node.setRHS(implicitCast(node.lhs().type(), node.rhs())); + public AssignNode visit(AssignNode node) { + return new AssignNode(checkLHS(node.lhs()), checkRHS(node.rhs())); } - public void visit(OpAssignNode node) { - super.visit(node); - if (! checkLHS(node.lhs())) return; - if (! checkRHS(node.rhs())) return; - if (node.operator().equals("+") - || node.operator().equals("-")) { - if (node.lhs().type().isPointer()) { - if (! mustBeInteger(node.rhs(), node.operator())) return; - node.setRHS(multiplyPtrBaseSize(node.rhs(), node.lhs())); - return; + public OpAssignNode visit(OpAssignNode node) { + ExprNode lhs = checkLHS(node.lhs()); + ExprNode rhs = checkRHS(node.rhs()); + if (node.operator().equals("+") || node.operator().equals("-")) { + if (lhs.type().isPointer()) { + if (! mustBeInteger(rhs, node.operator())) { + return node; + } + return new OpAssignNode( + lhs, node.operator(), multiplyPtrBaseSize(rhs, lhs)); } } - if (! mustBeInteger(node.lhs(), node.operator())) return; - if (! mustBeInteger(node.rhs(), node.operator())) return; - Type l = integralPromotion(node.lhs().type()); - Type r = integralPromotion(node.rhs().type()); + if (!mustBeInteger(lhs, node.operator()) + || !mustBeInteger(rhs, node.operator())) { + return new OpAssignNode(lhs, node.operator(), rhs); + } + Type l = integralPromotion(lhs.type()); + Type r = integralPromotion(rhs.type()); Type opType = usualArithmeticConversion(l, r); if (! opType.isCompatible(l) - && ! isSafeIntegerCast(node.rhs(), opType)) { + && ! isSafeIntegerCast(rhs, opType)) { warn(node, "incompatible implicit cast from " + opType + " to " + l); } - if (! r.isSameType(opType)) { - // cast RHS - node.setRHS(new CastNode(opType, node.rhs())); + if (r.isSameType(opType)) { + return new OpAssignNode(lhs, node.operator(), rhs); + } + else { // cast RHS + return new OpAssignNode(lhs, node.operator(), new CastNode(opType, rhs)); } } @@ -182,48 +274,37 @@ class TypeChecker extends Visitor { return t.isInDomain(n.value()); } - protected boolean checkLHS(ExprNode lhs) { - if (lhs.isParameter()) { - // parameter is always assignable. - return true; - } - else if (isInvalidLHSType(lhs.type())) { - error(lhs, "invalid LHS expression type: " + lhs.type()); - return false; - } - return true; - } - // // Expressions // - public void visit(CondExprNode node) { - super.visit(node); - checkCond(node.cond()); - Type t = node.thenExpr().type(); - Type e = node.elseExpr().type(); - if (t.isSameType(e)) { - return; + public CondExprNode visit(CondExprNode node) { + ExprNode c = checkCond(node.cond()); + ExprNode t = checkExpr(node.thenExpr()); + ExprNode e = checkExpr(node.elseExpr()); + if (t.type().isSameType(e.type())) { + node.setExprs(c, t, e); } - else if (t.isCompatible(e)) { // insert cast on thenBody - node.setThenExpr(new CastNode(e, node.thenExpr())); + else if (t.type().isCompatible(e.type())) { // insert cast on thenExpr + node.setExprs(c, new CastNode(e.type(), t), e); } - else if (e.isCompatible(t)) { // insert cast on elseBody - node.setElseExpr(new CastNode(t, node.elseExpr())); + else if (e.type().isCompatible(t.type())) { // insert cast on elseExpr + node.setExprs(c, t, new CastNode(t.type(), e)); } else { - invalidCastError(node.thenExpr(), e, t); + invalidCastError(t, e.type(), t.type()); } + return node; } // #@@range/BinaryOpNode{ - public void visit(BinaryOpNode node) { - super.visit(node); + public BinaryOpNode visit(BinaryOpNode node) { + node.setLeft(checkExpr(node.left())); + node.setRight(checkExpr(node.right())); if (node.operator().equals("+") || node.operator().equals("-")) { - Type t = expectsSameIntegerOrPointerDiff(node); - if (t != null) node.setType(t); + expectsSameIntegerOrPointerDiff(node); + return node; } else if (node.operator().equals("*") || node.operator().equals("/") @@ -233,8 +314,8 @@ class TypeChecker extends Visitor { || node.operator().equals("^") || node.operator().equals("<<") || node.operator().equals(">>")) { - Type t = expectsSameInteger(node); - if (t != null) node.setType(t); + expectsSameInteger(node); + return node; } else if (node.operator().equals("==") || node.operator().equals("!=") @@ -242,8 +323,8 @@ class TypeChecker extends Visitor { || node.operator().equals("<=") || node.operator().equals(">") || node.operator().equals(">=")) { - Type t = expectsComparableScalars(node); - if (t != null) node.setType(t); + expectsComparableScalars(node); + return node; } else { throw new Error("unknown binary operator: " + node.operator()); @@ -251,16 +332,18 @@ class TypeChecker extends Visitor { } // #@@} - public void visit(LogicalAndNode node) { - super.visit(node); - Type t = expectsComparableScalars(node); - if (t != null) node.setType(t); + public LogicalAndNode visit(LogicalAndNode node) { + node.setLeft(checkExpr(node.left())); + node.setRight(checkExpr(node.right())); + expectsComparableScalars(node); + return node; } - public void visit(LogicalOrNode node) { - super.visit(node); - Type t = expectsComparableScalars(node); - if (t != null) node.setType(t); + public LogicalOrNode visit(LogicalOrNode node) { + node.setLeft(checkExpr(node.left())); + node.setRight(checkExpr(node.right())); + expectsComparableScalars(node); + return node; } /** @@ -272,31 +355,31 @@ class TypeChecker extends Visitor { * * integer - integer * * pointer - integer */ - protected Type expectsSameIntegerOrPointerDiff(BinaryOpNode node) { + protected void expectsSameIntegerOrPointerDiff(BinaryOpNode node) { if (node.left().type().isDereferable()) { if (node.left().type().baseType().isVoid()) { wrongTypeError(node.left(), node.operator()); - return null; + return; } mustBeInteger(node.right(), node.operator()); + node.setType(node.left().type()); node.setRight(multiplyPtrBaseSize(node.right(), node.left())); - return node.left().type(); } else if (node.right().type().isDereferable()) { if (node.operator().equals("-")) { error(node, "invalid operation integer-pointer"); - return null; + return; } if (node.right().type().baseType().isVoid()) { wrongTypeError(node.right(), node.operator()); - return null; + return; } mustBeInteger(node.left(), node.operator()); + node.setType(node.right().type()); node.setLeft(multiplyPtrBaseSize(node.left(), node.right())); - return node.right().type(); } else { - return expectsSameInteger(node); + expectsSameInteger(node); } } @@ -332,28 +415,28 @@ class TypeChecker extends Visitor { // +, -, *, /, %, &, |, ^, <<, >> // #@@range/expectsSameInteger{ - protected Type expectsSameInteger(BinaryOpNode node) { - if (! mustBeInteger(node.left(), node.operator())) return null; - if (! mustBeInteger(node.right(), node.operator())) return null; - return arithmeticImplicitCast(node); + protected void expectsSameInteger(BinaryOpNode bin) { + if (! mustBeInteger(bin.left(), bin.operator())) return; + if (! mustBeInteger(bin.right(), bin.operator())) return; + arithmeticImplicitCast(bin); } // #@@} // ==, !=, >, >=, <, <=, &&, || - protected Type expectsComparableScalars(BinaryOpNode node) { - if (! mustBeScalar(node.left(), node.operator())) return null; - if (! mustBeScalar(node.right(), node.operator())) return null; - if (node.left().type().isDereferable()) { - ExprNode right = forcePointerType(node.left(), node.right()); - node.setRight(right); - return node.left().type(); + protected void expectsComparableScalars(BinaryOpNode bin) { + if (! mustBeScalar(bin.left(), bin.operator())) return; + if (! mustBeScalar(bin.right(), bin.operator())) return; + if (bin.left().type().isDereferable()) { + bin.setType(bin.left().type()); + bin.setRight(forcePointerType(bin.left(), bin.right())); + return; } - if (node.right().type().isDereferable()) { - ExprNode left = forcePointerType(node.right(), node.left()); - node.setLeft(left); - return node.right().type(); + if (bin.right().type().isDereferable()) { + bin.setType(bin.right().type()); + bin.setLeft(forcePointerType(bin.right(), bin.left())); + return; } - return arithmeticImplicitCast(node); + arithmeticImplicitCast(bin); } // cast slave node to master node. @@ -371,43 +454,44 @@ class TypeChecker extends Visitor { // Processes usual arithmetic conversion for binary operations. // #@@range/arithmeticImplicitCast{ - protected Type arithmeticImplicitCast(BinaryOpNode node) { - Type r = integralPromotion(node.right().type()); - Type l = integralPromotion(node.left().type()); + protected void arithmeticImplicitCast(BinaryOpNode bin) { + Type r = integralPromotion(bin.right().type()); + Type l = integralPromotion(bin.left().type()); Type target = usualArithmeticConversion(l, r); + bin.setType(target); if (! l.isSameType(target)) { - // insert cast on left expr - node.setLeft(new CastNode(target, node.left())); + bin.setLeft(new CastNode(target, bin.left())); } if (! r.isSameType(target)) { - // insert cast on right expr - node.setRight(new CastNode(target, node.right())); + bin.setRight(new CastNode(target, bin.right())); } - return target; } // #@@} // +, -, !, ~ - public void visit(UnaryOpNode node) { - super.visit(node); - if (node.operator().equals("!")) { - mustBeScalar(node.expr(), node.operator()); + public UnaryOpNode visit(UnaryOpNode un) { + ExprNode expr = checkExpr(un.expr()); + if (un.operator().equals("!")) { + mustBeScalar(expr, un.operator()); } else { - mustBeInteger(node.expr(), node.operator()); + mustBeInteger(expr, un.operator()); } + return new UnaryOpNode(un.operator(), expr); } // ++x, --x - public void visit(PrefixOpNode node) { - super.visit(node); - expectsScalarLHS(node); + public PrefixOpNode visit(PrefixOpNode pre) { + pre.setExpr(checkExpr(pre.expr())); + expectsScalarLHS(pre); + return pre; } // x++, x-- - public void visit(SuffixOpNode node) { - super.visit(node); - expectsScalarLHS(node); + public SuffixOpNode visit(SuffixOpNode suf) { + suf.setExpr(checkExpr(suf.expr())); + expectsScalarLHS(suf); + return suf; } protected void expectsScalarLHS(UnaryArithmeticOpNode node) { @@ -422,6 +506,7 @@ class TypeChecker extends Visitor { else { mustBeScalar(node.expr(), node.operator()); } + if (node.expr().type().isInteger()) { Type opType = integralPromotion(node.expr().type()); if (! node.expr().type().isSameType(opType)) { @@ -449,48 +534,102 @@ class TypeChecker extends Visitor { * * ARG matches function prototype. * * ARG is neither a struct nor an union. */ - public void visit(FuncallNode node) { - super.visit(node); + public FuncallNode visit(FuncallNode node) { + ExprNode expr = checkExpr(node.expr()); FunctionType type = node.functionType(); if (! type.acceptsArgc(node.numArgs())) { error(node, "wrong number of argments: " + node.numArgs()); - return; + return node; } + // Check type of only mandatory parameters. Iterator args = node.arguments().iterator(); List newArgs = new ArrayList(); for (Type param : type.paramTypes()) { - ExprNode arg = args.next(); - newArgs.add(checkRHS(arg) ? implicitCast(param, arg) : arg); + ExprNode arg = checkRHS(args.next()); + newArgs.add(isInvalidRHSType(arg.type()) ? arg : implicitCast(param, arg)); } while (args.hasNext()) { - newArgs.add(args.next()); + newArgs.add(checkRHS(args.next())); } - node.replaceArgs(newArgs); + + return new FuncallNode(expr, newArgs); } - public void visit(ArefNode node) { - super.visit(node); - mustBeInteger(node.index(), "[]"); + public ArefNode visit(ArefNode node) { + ExprNode expr = checkExpr(node.expr()); + ExprNode index = checkExpr(node.index()); + mustBeInteger(index, "[]"); + return new ArefNode(expr, index); } - public void visit(CastNode node) { - super.visit(node); - if (! node.expr().type().isCastableTo(node.type())) { - invalidCastError(node, node.expr().type(), node.type()); + public CastNode visit(CastNode node) { + ExprNode expr = checkExpr(node.expr()); + if (! expr.type().isCastableTo(node.type())) { + invalidCastError(node, expr.type(), node.type()); } + return new CastNode(node.typeNode(), expr); + } + + public AddressNode visit(AddressNode node) { + node.setExpr(checkExpr(node.expr())); + return node; + } + + public DereferenceNode visit(DereferenceNode node) { + return new DereferenceNode(checkExpr(node.expr())); + } + + public MemberNode visit(MemberNode node) { + return new MemberNode(checkExpr(node.expr()), node.member()); + } + + public PtrMemberNode visit(PtrMemberNode node) { + return new PtrMemberNode(checkExpr(node.expr()), node.member()); + } + + public SizeofExprNode visit(SizeofExprNode node) { + node.setExpr(checkExpr(node.expr())); + return node; + } + + public SizeofTypeNode visit(SizeofTypeNode node) { + return node; + } + + public VariableNode visit(VariableNode node) { + return node; + } + + public IntegerLiteralNode visit(IntegerLiteralNode node) { + return node; + } + + public StringLiteralNode visit(StringLiteralNode node) { + return node; } // // Utilities // - protected boolean checkRHS(ExprNode rhs) { + protected ExprNode checkLHS(ExprNode expr) { + ExprNode lhs = checkExpr(expr); + if (lhs.isParameter()) { + ; // parameter is always assignable. + } + else if (isInvalidLHSType(lhs.type())) { + error(lhs, "invalid LHS expression type: " + lhs.type()); + } + return lhs; + } + + protected ExprNode checkRHS(ExprNode expr) { + ExprNode rhs = checkExpr(expr); if (isInvalidRHSType(rhs.type())) { error(rhs, "invalid RHS expression type: " + rhs.type()); - return false; } - return true; + return rhs; } // Processes forced-implicit-cast. diff --git a/net/loveruby/cflat/compiler/TypeResolver.java b/net/loveruby/cflat/compiler/TypeResolver.java index 258f302..2c44f6a 100644 --- a/net/loveruby/cflat/compiler/TypeResolver.java +++ b/net/loveruby/cflat/compiler/TypeResolver.java @@ -18,15 +18,15 @@ public class TypeResolver extends Visitor { public void resolve(AST ast) { this.typeTable = ast.typeTable(); defineTypes(ast.types()); - resolveNodeList(ast.types()); - resolveNodeList(ast.declarations()); - resolveNodeList(ast.entities()); - } - // #@@} - - // #@@range/resolveNodeList{ - protected void resolveNodeList(List nodes) { - visitNodeList(nodes); + for (TypeDefinition t : ast.types()) { + t.accept(this); + } + for (Entity d : ast.declarations()) { + d.accept(this); + } + for (Entity e : ast.entities()) { + e.accept(this); + } } // #@@} @@ -51,14 +51,16 @@ public class TypeResolver extends Visitor { // #@@} // #@@range/StructNode{ - public void visit(StructNode struct) { + public StructNode visit(StructNode struct) { resolveCompositeType(struct); + return null; } // #@@} // #@@range/UnionNode{ - public void visit(UnionNode union) { + public UnionNode visit(UnionNode union) { resolveCompositeType(union); + return null; } // #@@} @@ -75,32 +77,37 @@ public class TypeResolver extends Visitor { // #@@} // #@@range/TypedefNode{ - public void visit(TypedefNode typedef) { + public TypedefNode visit(TypedefNode typedef) { bindType(typedef.typeNode()); bindType(typedef.realTypeNode()); + return null; } // #@@} // #@@range/DefinedVariable{ - public void visit(DefinedVariable var) { + public DefinedVariable visit(DefinedVariable var) { bindType(var.typeNode()); super.visit(var); // resolve initializer + return null; } // #@@} - public void visit(UndefinedVariable var) { + public UndefinedVariable visit(UndefinedVariable var) { bindType(var.typeNode()); + return null; } // #@@range/DefinedFunction{ - public void visit(DefinedFunction func) { + public DefinedFunction visit(DefinedFunction func) { resolveFunctionHeader(func); - visitNode(func.body()); + visitStmt(func.body()); + return null; } // #@@} - public void visit(UndefinedFunction func) { + public UndefinedFunction visit(UndefinedFunction func) { resolveFunctionHeader(func); + return null; } // #@@range/resolveFunctionHeader{ @@ -117,7 +124,7 @@ public class TypeResolver extends Visitor { } // #@@} - public void visit(AddressNode node) { + public AddressNode visit(AddressNode node) { super.visit(node); // to avoid SemanticError which occurs when getting type of // expr which is not assignable. @@ -134,30 +141,36 @@ public class TypeResolver extends Visitor { Type t = typeTable.pointerTo(typeTable.voidType()); node.setType(t); } + return null; } - public void visit(CastNode node) { + public CastNode visit(CastNode node) { bindType(node.typeNode()); super.visit(node); + return null; } - public void visit(SizeofExprNode node) { + public SizeofExprNode visit(SizeofExprNode node) { bindType(node.typeNode()); super.visit(node); + return null; } - public void visit(SizeofTypeNode node) { + public SizeofTypeNode visit(SizeofTypeNode node) { bindType(node.operandTypeNode()); bindType(node.typeNode()); super.visit(node); + return null; } - public void visit(IntegerLiteralNode node) { + public IntegerLiteralNode visit(IntegerLiteralNode node) { bindType(node.typeNode()); + return null; } - public void visit(StringLiteralNode node) { + public StringLiteralNode visit(StringLiteralNode node) { bindType(node.typeNode()); + return null; } protected void error(Node node, String msg) { diff --git a/net/loveruby/cflat/compiler/Visitor.java b/net/loveruby/cflat/compiler/Visitor.java index 525661c..9466b6b 100644 --- a/net/loveruby/cflat/compiler/Visitor.java +++ b/net/loveruby/cflat/compiler/Visitor.java @@ -6,13 +6,23 @@ abstract public class Visitor implements ASTVisitor { public Visitor() { } - protected void visitNode(Node node) { - node.accept(this); + protected void visitStmt(StmtNode stmt) { + stmt.accept(this); } - protected void visitNodeList(List nodes) { - for (Node n : nodes) { - visitNode(n); + protected void visitStmts(List stmts) { + for (StmtNode s : stmts) { + visitStmt(s); + } + } + + protected void visitExpr(ExprNode expr) { + expr.accept(this); + } + + protected void visitExprs(List exprs) { + for (ExprNode e : exprs) { + visitExpr(e); } } @@ -20,187 +30,232 @@ abstract public class Visitor implements ASTVisitor { // Declarations // - public void visit(DefinedVariable var) { + public DefinedVariable visit(DefinedVariable var) { if (var.hasInitializer()) { - visitNode(var.initializer()); + visitExpr(var.initializer()); } + return null; } - public void visit(UndefinedVariable var) { + public UndefinedVariable visit(UndefinedVariable var) { + return null; } - public void visit(DefinedFunction func) { + public DefinedFunction visit(DefinedFunction func) { + return null; } - public void visit(UndefinedFunction func) { + public UndefinedFunction visit(UndefinedFunction func) { + return null; } - public void visit(StructNode struct) { + public StructNode visit(StructNode struct) { + return null; } - public void visit(UnionNode union) { + public UnionNode visit(UnionNode union) { + return null; } - public void visit(TypedefNode typedef) { + public TypedefNode visit(TypedefNode typedef) { + return null; } // // Statements // - public void visit(BlockNode node) { + public BlockNode visit(BlockNode node) { for (DefinedVariable var : node.variables()) { visit(var); } - visitNodeList(node.stmts()); + visitStmts(node.stmts()); + return null; } - public void visit(IfNode n) { - visitNode(n.cond()); - visitNode(n.thenBody()); + public ExprStmtNode visit(ExprStmtNode node) { + visitExpr(node.expr()); + return null; + } + + public IfNode visit(IfNode n) { + visitExpr(n.cond()); + visitStmt(n.thenBody()); if (n.elseBody() != null) { - visitNode(n.elseBody()); + visitStmt(n.elseBody()); } + return null; } - public void visit(SwitchNode n) { - visitNode(n.cond()); - visitNodeList(n.cases()); + public SwitchNode visit(SwitchNode n) { + visitExpr(n.cond()); + visitStmts(n.cases()); + return null; } - public void visit(CaseNode n) { - visitNodeList(n.values()); - visitNode(n.body()); + public CaseNode visit(CaseNode n) { + visitExprs(n.values()); + visitStmt(n.body()); + return null; } - public void visit(WhileNode n) { - visitNode(n.cond()); - visitNode(n.body()); + public WhileNode visit(WhileNode n) { + visitExpr(n.cond()); + visitStmt(n.body()); + return null; } - public void visit(DoWhileNode n) { - visitNode(n.body()); - visitNode(n.cond()); + public DoWhileNode visit(DoWhileNode n) { + visitStmt(n.body()); + visitExpr(n.cond()); + return null; } - public void visit(ForNode n) { - visitNode(n.init()); - visitNode(n.cond()); - visitNode(n.incr()); - visitNode(n.body()); + public ForNode visit(ForNode n) { + visitStmt(n.init()); + visitExpr(n.cond()); + visitStmt(n.incr()); + visitStmt(n.body()); + return null; } - public void visit(BreakNode n) { + public BreakNode visit(BreakNode n) { + return null; } - public void visit(ContinueNode n) { + public ContinueNode visit(ContinueNode n) { + return null; } - public void visit(GotoNode n) { + public GotoNode visit(GotoNode n) { + return null; } - public void visit(LabelNode n) { - visitNode(n.stmt()); + public LabelNode visit(LabelNode n) { + visitStmt(n.stmt()); + return null; } - public void visit(ReturnNode n) { + public ReturnNode visit(ReturnNode n) { if (n.expr() != null) { - visitNode(n.expr()); + visitExpr(n.expr()); } + return null; } // // Expressions // - public void visit(CondExprNode n) { - visitNode(n.cond()); - visitNode(n.thenExpr()); + public CondExprNode visit(CondExprNode n) { + visitExpr(n.cond()); + visitExpr(n.thenExpr()); if (n.elseExpr() != null) { - visitNode(n.elseExpr()); + visitExpr(n.elseExpr()); } + return null; } - public void visit(LogicalOrNode node) { - visitNode(node.left()); - visitNode(node.right()); + public LogicalOrNode visit(LogicalOrNode node) { + visitExpr(node.left()); + visitExpr(node.right()); + return null; } - public void visit(LogicalAndNode node) { - visitNode(node.left()); - visitNode(node.right()); + public LogicalAndNode visit(LogicalAndNode node) { + visitExpr(node.left()); + visitExpr(node.right()); + return null; } - public void visit(AssignNode n) { - visitNode(n.lhs()); - visitNode(n.rhs()); + public AssignNode visit(AssignNode n) { + visitExpr(n.lhs()); + visitExpr(n.rhs()); + return null; } - public void visit(OpAssignNode n) { - visitNode(n.lhs()); - visitNode(n.rhs()); + public OpAssignNode visit(OpAssignNode n) { + visitExpr(n.lhs()); + visitExpr(n.rhs()); + return null; } - public void visit(BinaryOpNode n) { - visitNode(n.left()); - visitNode(n.right()); + public BinaryOpNode visit(BinaryOpNode n) { + visitExpr(n.left()); + visitExpr(n.right()); + return null; } - public void visit(UnaryOpNode node) { - visitNode(node.expr()); + public UnaryOpNode visit(UnaryOpNode node) { + visitExpr(node.expr()); + return null; } - public void visit(PrefixOpNode node) { - visitNode(node.expr()); + public PrefixOpNode visit(PrefixOpNode node) { + visitExpr(node.expr()); + return null; } - public void visit(SuffixOpNode node) { - visitNode(node.expr()); + public SuffixOpNode visit(SuffixOpNode node) { + visitExpr(node.expr()); + return null; } - public void visit(FuncallNode node) { - visitNode(node.expr()); - visitNodeList(node.arguments()); + public FuncallNode visit(FuncallNode node) { + visitExpr(node.expr()); + visitExprs(node.arguments()); + return null; } - public void visit(ArefNode node) { - visitNode(node.expr()); - visitNode(node.index()); + public ArefNode visit(ArefNode node) { + visitExpr(node.expr()); + visitExpr(node.index()); + return null; } - public void visit(MemberNode node) { - visitNode(node.expr()); + public MemberNode visit(MemberNode node) { + visitExpr(node.expr()); + return null; } - public void visit(PtrMemberNode node) { - visitNode(node.expr()); + public PtrMemberNode visit(PtrMemberNode node) { + visitExpr(node.expr()); + return null; } - public void visit(DereferenceNode node) { - visitNode(node.expr()); + public DereferenceNode visit(DereferenceNode node) { + visitExpr(node.expr()); + return null; } - public void visit(AddressNode node) { - visitNode(node.expr()); + public AddressNode visit(AddressNode node) { + visitExpr(node.expr()); + return null; } - public void visit(CastNode node) { - visitNode(node.expr()); + public CastNode visit(CastNode node) { + visitExpr(node.expr()); + return null; } - public void visit(SizeofExprNode node) { - visitNode(node.expr()); + public SizeofExprNode visit(SizeofExprNode node) { + visitExpr(node.expr()); + return null; } - public void visit(SizeofTypeNode node) { + public SizeofTypeNode visit(SizeofTypeNode node) { + return null; } - public void visit(VariableNode node) { + public VariableNode visit(VariableNode node) { + return null; } - public void visit(IntegerLiteralNode node) { + public IntegerLiteralNode visit(IntegerLiteralNode node) { + return null; } - public void visit(StringLiteralNode node) { + public StringLiteralNode visit(StringLiteralNode node) { + return null; } } diff --git a/net/loveruby/cflat/parser/Parser.jj b/net/loveruby/cflat/parser/Parser.jj index 6b979ac..e15e5fa 100644 --- a/net/loveruby/cflat/parser/Parser.jj +++ b/net/loveruby/cflat/parser/Parser.jj @@ -587,7 +587,7 @@ BlockNode block(): { Token t; List vars; - List stmts; + List stmts; } { t="{" vars=defvar_list() stmts=stmts() "}" @@ -813,10 +813,10 @@ TypedefNode typedef(): // #@@} // #@@range/stmts{ -List stmts(): +List stmts(): { - List ss = new ArrayList(); - Node s; + List ss = new ArrayList(); + StmtNode s; } { (s=stmt() { if (s != null) ss.add(s); })* @@ -827,12 +827,15 @@ List stmts(): // #@@} // #@@range/stmt{ -Node stmt(): -{ Node n = null; } +StmtNode stmt(): +{ + StmtNode n = null; + ExprNode e = null; +} { ( ";" | LOOKAHEAD(2) n=labeled_stmt() - | n=expr() ";" + | e=expr() ";" { n = new ExprStmtNode(e.location(), e); } | n=block() | n=if_stmt() | n=while_stmt() @@ -853,7 +856,7 @@ Node stmt(): LabelNode labeled_stmt(): { Token t; - Node n; + StmtNode n; } { t= ":" n=stmt() @@ -867,7 +870,7 @@ IfNode if_stmt(): { Token t; ExprNode cond; - Node thenBody, elseBody = null; + StmtNode thenBody, elseBody = null; } { t= "(" cond=expr() ")" thenBody=stmt() @@ -883,7 +886,7 @@ WhileNode while_stmt(): { Token t; ExprNode cond; - Node body; + StmtNode body; } { t= "(" cond=expr() ")" body=stmt() @@ -897,7 +900,7 @@ DoWhileNode dowhile_stmt(): { Token t; ExprNode cond; - Node body; + StmtNode body; } { t= body=stmt() "(" cond=expr() ")" ";" @@ -910,7 +913,7 @@ ForNode for_stmt(): { Token t; ExprNode init = null, cond = null, incr = null; - Node body; + StmtNode body; } { t= "(" [init=expr()] ";" @@ -982,8 +985,8 @@ CaseNode default_clause(): BlockNode case_body(): { - LinkedList stmts = new LinkedList(); - Node s; + LinkedList stmts = new LinkedList(); + StmtNode s; } { (s=stmt() { if (s != null) stmts.add(s); })+