mirror of https://github.com/aamine/cbc
* 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:
parent
c558b27a8e
commit
043859df0b
18
ChangeLog
18
ChangeLog
|
@ -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.
|
||||
|
|
|
@ -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");
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -89,4 +89,6 @@ abstract public class Entity extends Node {
|
|||
public Location location() {
|
||||
return typeNode.location();
|
||||
}
|
||||
|
||||
abstract public Entity accept(ASTVisitor visitor);
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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() {
|
||||
|
|
|
@ -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() {
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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());
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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");
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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");
|
||||
}
|
||||
}
|
||||
|
|
|
@ -10,4 +10,6 @@ abstract public class StmtNode extends Node {
|
|||
public Location location() {
|
||||
return location;
|
||||
}
|
||||
|
||||
abstract public StmtNode accept(ASTVisitor visitor);
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -33,4 +33,5 @@ abstract public class TypeDefinition extends Node {
|
|||
}
|
||||
|
||||
abstract public Type definingType();
|
||||
abstract public TypeDefinition accept(ASTVisitor visitor);
|
||||
}
|
||||
|
|
|
@ -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");
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
// #@@}
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
//
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
// #@@}
|
||||
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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); })+
|
||||
|
|
Loading…
Reference in New Issue