* 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
This commit is contained in:
Minero Aoki 2009-04-04 14:47:11 +00:00
parent c558b27a8e
commit 043859df0b
63 changed files with 912 additions and 575 deletions

View File

@ -1,3 +1,21 @@
Sat Apr 4 23:47:02 2009 Minero Aoki <aamine@loveruby.net>
* 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 <aamine@loveruby.net>
* lib/sizeof_jmpbuf.c: new analysis program.

View File

@ -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");
}
}

View File

@ -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);
}

View File

@ -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();
}

View File

@ -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);
}
}

View File

@ -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) {

View File

@ -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);
}
}

View File

@ -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);
}
}

View File

@ -3,10 +3,10 @@ import java.util.*;
public class BlockNode extends StmtNode {
protected List<DefinedVariable> variables;
protected List<Node> stmts;
protected List<StmtNode> stmts;
protected LocalScope scope;
public BlockNode(Location loc, List<DefinedVariable> vars, List<Node> stmts) {
public BlockNode(Location loc, List<DefinedVariable> vars, List<StmtNode> stmts) {
super(loc);
this.variables = vars;
this.stmts = stmts;
@ -16,11 +16,11 @@ public class BlockNode extends StmtNode {
return variables;
}
public List<Node> stmts() {
public List<StmtNode> 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);
}
}

View File

@ -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);
}
}

View File

@ -18,6 +18,10 @@ public class CaseNode extends StmtNode {
return values;
}
public void setValues(List<ExprNode> 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);
}
}

View File

@ -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);
}
}

View File

@ -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);
}
}

View File

@ -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);
}
}

View File

@ -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);
}
}

View File

@ -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);
}
}

View File

@ -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) {

View File

@ -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);
}
}

View File

@ -89,4 +89,6 @@ abstract public class Entity extends Node {
public Location location() {
return typeNode.location();
}
abstract public Entity accept(ASTVisitor visitor);
}

View File

@ -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);
}

View File

@ -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);
}
}

View File

@ -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);
}
}

View File

@ -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);
}
}

View File

@ -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);
}
}

View File

@ -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);
}
}

View File

@ -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);
}
}

View File

@ -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);
}
}

View File

@ -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() {

View File

@ -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() {

View File

@ -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;
}

View File

@ -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) {

View File

@ -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());
}

View File

@ -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);
}
}

View File

@ -48,8 +48,4 @@ abstract public class ParamSlots<T> 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");
}
}

View File

@ -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);
}
}

View File

@ -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) {

View File

@ -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);
}
}

View File

@ -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);
}
}

View File

@ -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);
}
}

View File

@ -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");
}
}

View File

@ -10,4 +10,6 @@ abstract public class StmtNode extends Node {
public Location location() {
return location;
}
abstract public StmtNode accept(ASTVisitor visitor);
}

View File

@ -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);
}
}

View File

@ -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);
}
}

View File

@ -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);
}
}

View File

@ -18,6 +18,10 @@ public class SwitchNode extends StmtNode implements BreakableStmt {
return cond;
}
public void setCond(ExprNode cond) {
this.cond = cond;
}
public List<CaseNode> 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);
}
}

View File

@ -33,4 +33,5 @@ abstract public class TypeDefinition extends Node {
}
abstract public Type definingType();
abstract public TypeDefinition accept(ASTVisitor visitor);
}

View File

@ -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");
}
}

View File

@ -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);
}
}

View File

@ -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;
}

View File

@ -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);
}
}

View File

@ -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);
}
}

View File

@ -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);
}
}

View File

@ -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);
}
}

View File

@ -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) {

View File

@ -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);
}
}

View File

@ -455,7 +455,7 @@ public class CodeGenerator
protected List<Assembly> 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<Register> usedCalleeSavedRegistersWithoutBP(AsmStatistics stats) {
List<Register> result = new ArrayList<Register>();
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<ExprNode> 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;
}
// #@@}

View File

@ -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;
}
//

View File

@ -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;
}
}

View File

@ -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;
}
// #@@}

View File

@ -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<ExprNode> exprs = new ArrayList<ExprNode>();
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<ExprNode> args = node.arguments().iterator();
List<ExprNode> newArgs = new ArrayList<ExprNode>();
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.

View File

@ -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<? extends Node> 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) {

View File

@ -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<? extends Node> nodes) {
for (Node n : nodes) {
visitNode(n);
protected void visitStmts(List<? extends StmtNode> stmts) {
for (StmtNode s : stmts) {
visitStmt(s);
}
}
protected void visitExpr(ExprNode expr) {
expr.accept(this);
}
protected void visitExprs(List<? extends ExprNode> 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;
}
}

View File

@ -587,7 +587,7 @@ BlockNode block():
{
Token t;
List<DefinedVariable> vars;
List<Node> stmts;
List<StmtNode> stmts;
}
{
t="{" vars=defvar_list() stmts=stmts() "}"
@ -813,10 +813,10 @@ TypedefNode typedef():
// #@@}
// #@@range/stmts{
List<Node> stmts():
List<StmtNode> stmts():
{
List<Node> ss = new ArrayList<Node>();
Node s;
List<StmtNode> ss = new ArrayList<StmtNode>();
StmtNode s;
}
{
(s=stmt() { if (s != null) ss.add(s); })*
@ -827,12 +827,15 @@ List<Node> 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=<IDENTIFIER> ":" n=stmt()
@ -867,7 +870,7 @@ IfNode if_stmt():
{
Token t;
ExprNode cond;
Node thenBody, elseBody = null;
StmtNode thenBody, elseBody = null;
}
{
t=<IF> "(" cond=expr() ")" thenBody=stmt()
@ -883,7 +886,7 @@ WhileNode while_stmt():
{
Token t;
ExprNode cond;
Node body;
StmtNode body;
}
{
t=<WHILE> "(" cond=expr() ")" body=stmt()
@ -897,7 +900,7 @@ DoWhileNode dowhile_stmt():
{
Token t;
ExprNode cond;
Node body;
StmtNode body;
}
{
t=<DO> body=stmt() <WHILE> "(" cond=expr() ")" ";"
@ -910,7 +913,7 @@ ForNode for_stmt():
{
Token t;
ExprNode init = null, cond = null, incr = null;
Node body;
StmtNode body;
}
{
t=<FOR> "(" [init=expr()] ";"
@ -982,8 +985,8 @@ CaseNode default_clause():
BlockNode case_body():
{
LinkedList<Node> stmts = new LinkedList<Node>();
Node s;
LinkedList<StmtNode> stmts = new LinkedList<StmtNode>();
StmtNode s;
}
{
(s=stmt() { if (s != null) stmts.add(s); })+