* net/loveruby/cflat/compiler/Visitor.java: make destructive again.

* net/loveruby/cflat/compiler/TypeResolver.java: ditto.
* net/loveruby/cflat/compiler/TypeChecker.java: ditto.
* net/loveruby/cflat/compiler/LocalResolver.java: ditto.
* net/loveruby/cflat/compiler/CodeGenerator.java: ditto.
* net/loveruby/cflat/compiler/DereferenceChecker.java: ditto.
* net/loveruby/cflat/compiler/JumpResolver.java: ditto.
* net/loveruby/cflat/ast/AbstractAssignNode.java: ditto.
* net/loveruby/cflat/ast/CondExprNode.java: ditto.


git-svn-id: file:///Users/aamine/c/gitwork/public/cbc/trunk@4133 1b9489fe-b721-0410-924e-b54b9192deb8
This commit is contained in:
Minero Aoki 2009-04-12 07:37:18 +00:00
parent d514300aef
commit f69902e1d7
10 changed files with 338 additions and 422 deletions

View File

@ -1,3 +1,24 @@
Sun Apr 12 16:37:16 2009 Minero Aoki <aamine@loveruby.net>
* net/loveruby/cflat/compiler/Visitor.java: make destructive
again.
* net/loveruby/cflat/compiler/TypeResolver.java: ditto.
* net/loveruby/cflat/compiler/TypeChecker.java: ditto.
* net/loveruby/cflat/compiler/LocalResolver.java: ditto.
* net/loveruby/cflat/compiler/CodeGenerator.java: ditto.
* net/loveruby/cflat/compiler/DereferenceChecker.java: ditto.
* net/loveruby/cflat/compiler/JumpResolver.java: ditto.
* net/loveruby/cflat/ast/AbstractAssignNode.java: ditto.
* net/loveruby/cflat/ast/CondExprNode.java: ditto.
Sun Apr 12 15:31:07 2009 Minero Aoki <aamine@loveruby.net>
* net/loveruby/cflat/compiler/Visitor.java: make all return types

View File

@ -18,10 +18,18 @@ abstract public class AbstractAssignNode extends ExprNode {
return lhs;
}
public void setLHS(ExprNode expr) {
this.lhs = expr;
}
public ExprNode rhs() {
return rhs;
}
public void setRHS(ExprNode expr) {
this.rhs = expr;
}
public Location location() {
return lhs.location();
}

View File

@ -27,14 +27,16 @@ public class CondExprNode extends ExprNode {
return thenExpr;
}
public void setThenExpr(ExprNode expr) {
this.thenExpr = expr;
}
public ExprNode elseExpr() {
return elseExpr;
}
public void setExprs(ExprNode cond, ExprNode thenExpr, ExprNode elseExpr) {
this.cond = cond;
this.thenExpr = thenExpr;
this.elseExpr = elseExpr;
public void setElseExpr(ExprNode expr) {
this.elseExpr = expr;
}
public Label elseLabel() {

View File

@ -710,7 +710,7 @@ public class CodeGenerator
* * Rewind stack by caller.
*/
// #@@range/compile_Funcall{
public FuncallNode visit(FuncallNode node) {
public Void visit(FuncallNode node) {
// compile function arguments from right to left.
ListIterator<ExprNode> args = node.finalArg();
while (args.hasPrevious()) {
@ -735,7 +735,7 @@ public class CodeGenerator
// #@@}
// #@@range/compile_Return{
public ReturnNode visit(ReturnNode node) {
public Void visit(ReturnNode node) {
if (node.expr() != null) {
compile(node.expr());
}
@ -749,7 +749,7 @@ public class CodeGenerator
//
// #@@range/compile_Block{
public BlockNode visit(BlockNode node) {
public Void visit(BlockNode node) {
for (DefinedVariable var : node.scope().localVariables()) {
if (var.initializer() != null) {
compile(var.initializer());
@ -772,7 +772,7 @@ public class CodeGenerator
}
// #@@}
public ExprStmtNode visit(ExprStmtNode node) {
public Void visit(ExprStmtNode node) {
compile(node.expr());
return null;
}
@ -784,7 +784,7 @@ public class CodeGenerator
// #@@}
// #@@range/compile_If{
public IfNode visit(IfNode node) {
public Void visit(IfNode node) {
compile(node.cond());
testCond(node.cond().type(), reg("ax"));
if (node.elseBody() != null) {
@ -805,7 +805,7 @@ public class CodeGenerator
// #@@}
// #@@range/compile_CondExpr{
public CondExprNode visit(CondExprNode node) {
public Void visit(CondExprNode node) {
compile(node.cond());
testCond(node.cond().type(), reg("ax"));
jz(node.elseLabel());
@ -819,7 +819,7 @@ public class CodeGenerator
// #@@}
// #@@range/compile_Switch{
public SwitchNode visit(SwitchNode node) {
public Void visit(SwitchNode node) {
compile(node.cond());
Type t = typeTable.signedInt();
for (CaseNode cn : node.cases()) {
@ -845,7 +845,7 @@ public class CodeGenerator
// #@@}
// #@@range/compile_Case{
public CaseNode visit(CaseNode node) {
public Void visit(CaseNode node) {
label(node.beginLabel());
compileStmt(node.body());
return null;
@ -853,7 +853,7 @@ public class CodeGenerator
// #@@}
// #@@range/compile_LogicalAnd{
public LogicalAndNode visit(LogicalAndNode node) {
public Void visit(LogicalAndNode node) {
compile(node.left());
testCond(node.left().type(), reg("ax"));
jz(node.endLabel());
@ -864,7 +864,7 @@ public class CodeGenerator
// #@@}
// #@@range/compile_LogicalOr{
public LogicalOrNode visit(LogicalOrNode node) {
public Void visit(LogicalOrNode node) {
compile(node.left());
testCond(node.left().type(), reg("ax"));
jnz(node.endLabel());
@ -875,7 +875,7 @@ public class CodeGenerator
// #@@}
// #@@range/compile_While{
public WhileNode visit(WhileNode node) {
public Void visit(WhileNode node) {
label(node.begLabel());
compile(node.cond());
testCond(node.cond().type(), reg("ax"));
@ -887,7 +887,7 @@ public class CodeGenerator
}
// #@@}
public DoWhileNode visit(DoWhileNode node) {
public Void visit(DoWhileNode node) {
label(node.begLabel());
compileStmt(node.body());
label(node.continueLabel());
@ -899,7 +899,7 @@ public class CodeGenerator
}
// #@@range/compile_For{
public ForNode visit(ForNode node) {
public Void visit(ForNode node) {
compileStmt(node.init());
label(node.begLabel());
compile(node.cond());
@ -915,21 +915,21 @@ public class CodeGenerator
// #@@}
// #@@range/compile_Break{
public BreakNode visit(BreakNode node) {
public Void visit(BreakNode node) {
jmp(node.targetLabel());
return null;
}
// #@@}
// #@@range/compile_Continue{
public ContinueNode visit(ContinueNode node) {
public Void visit(ContinueNode node) {
jmp(node.targetLabel());
return null;
}
// #@@}
// #@@range/compile_Label{
public LabelNode visit(LabelNode node) {
public Void visit(LabelNode node) {
label(node.label());
compileStmt(node.stmt());
return null;
@ -937,7 +937,7 @@ public class CodeGenerator
// #@@}
// #@@range/compile_Goto{
public GotoNode visit(GotoNode node) {
public Void visit(GotoNode node) {
jmp(node.targetLabel());
return null;
}
@ -962,7 +962,7 @@ public class CodeGenerator
// #@@}
// #@@range/compile_BinaryOp{
public BinaryOpNode visit(BinaryOpNode node) {
public Void visit(BinaryOpNode node) {
AsmOperand right = null;
if (!doesRequireRegister(node.operator()) && node.right().isConstant()){
compile(node.left());
@ -1084,7 +1084,7 @@ public class CodeGenerator
// #@@}
// #@@range/compile_UnaryOp{
public UnaryOpNode visit(UnaryOpNode node) {
public Void visit(UnaryOpNode node) {
compile(node.expr());
if (node.operator().equals("+")) {
;
@ -1105,7 +1105,7 @@ public class CodeGenerator
// #@@}
// #@@range/compile_PrefixOp{
public PrefixOpNode visit(PrefixOpNode node) {
public Void visit(PrefixOpNode node) {
if (node.expr().isConstantAddress()) {
load(node.expr().type(), node.expr().memref(), reg("ax"));
compileUnaryArithmetic(node, reg("ax"));
@ -1123,7 +1123,7 @@ public class CodeGenerator
// #@@}
// #@@range/compile_SuffixOp{
public SuffixOpNode visit(SuffixOpNode node) {
public Void visit(SuffixOpNode node) {
if (node.expr().isConstantAddress()) {
load(node.expr().type(), node.expr().memref(), reg("ax"));
mov(reg("ax"), reg("cx"));
@ -1159,7 +1159,7 @@ public class CodeGenerator
// #@@}
// #@@range/compile_Cast{
public CastNode visit(CastNode node) {
public Void 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.
@ -1180,7 +1180,7 @@ public class CodeGenerator
// #@@}
// #@@range/compile_SizeofExpr{
public SizeofExprNode visit(SizeofExprNode node) {
public Void visit(SizeofExprNode node) {
long val = node.expr().type().allocSize();
mov(node.type(), imm(val), reg("ax", node.type()));
return null;
@ -1188,7 +1188,7 @@ public class CodeGenerator
// #@@}
// #@@range/compile_SizeofType{
public SizeofTypeNode visit(SizeofTypeNode node) {
public Void visit(SizeofTypeNode node) {
long val = node.operand().allocSize();
mov(node.type(), imm(val), reg("ax", node.type()));
return null;
@ -1196,21 +1196,21 @@ public class CodeGenerator
// #@@}
// #@@range/compile_Variable{
public VariableNode visit(VariableNode node) {
public Void visit(VariableNode node) {
loadVariable(node, reg("ax"));
return null;
}
// #@@}
// #@@range/compile_IntegerLiteral{
public IntegerLiteralNode visit(IntegerLiteralNode node) {
public Void visit(IntegerLiteralNode node) {
loadConstant(node, reg("ax"));
return null;
}
// #@@}
// #@@range/compile_StringLiteral{
public StringLiteralNode visit(StringLiteralNode node) {
public Void visit(StringLiteralNode node) {
loadConstant(node, reg("ax"));
return null;
}
@ -1221,7 +1221,7 @@ public class CodeGenerator
//
// #@@range/compile_Assign{
public AssignNode visit(AssignNode node) {
public Void visit(AssignNode node) {
if (node.lhs().isConstantAddress() && node.lhs().memref() != null) {
compile(node.rhs());
save(node.type(), reg("ax"), node.lhs().memref());
@ -1245,7 +1245,7 @@ public class CodeGenerator
// #@@}
// #@@range/compile_OpAssign{
public OpAssignNode visit(OpAssignNode node) {
public Void visit(OpAssignNode node) {
if (node.lhs().isConstantAddress() && node.lhs().memref() != null) {
// const += ANY
compile(node.rhs());
@ -1291,7 +1291,7 @@ public class CodeGenerator
// #@@}
// #@@range/compile_Aref{
public ArefNode visit(ArefNode node) {
public Void visit(ArefNode node) {
compileLHS(node);
load(node.type(), mem(reg("ax")), reg("ax"));
return null;
@ -1299,7 +1299,7 @@ public class CodeGenerator
// #@@}
// #@@range/compile_Member{
public MemberNode visit(MemberNode node) {
public Void visit(MemberNode node) {
compileLHS(node.expr());
if (node.shouldEvaluatedToAddress()) {
add(imm(node.offset()), reg("ax"));
@ -1312,7 +1312,7 @@ public class CodeGenerator
// #@@}
// #@@range/compile_PtrMember{
public PtrMemberNode visit(PtrMemberNode node) {
public Void visit(PtrMemberNode node) {
compile(node.expr());
if (node.shouldEvaluatedToAddress()) {
add(imm(node.offset()), reg("ax"));
@ -1325,7 +1325,7 @@ public class CodeGenerator
// #@@}
// #@@range/compile_Dereference{
public DereferenceNode visit(DereferenceNode node) {
public Void visit(DereferenceNode node) {
compile(node.expr());
load(node.type(), mem(reg("ax")), reg("ax"));
return null;
@ -1333,7 +1333,7 @@ public class CodeGenerator
// #@@}
// #@@range/compile_Address{
public AddressNode visit(AddressNode node) {
public Void visit(AddressNode node) {
compileLHS(node.expr());
return null;
}

View File

@ -35,7 +35,7 @@ class DereferenceChecker extends Visitor {
// Statements
//
public BlockNode visit(BlockNode node) {
public Void visit(BlockNode node) {
for (DefinedVariable var : node.variables()) {
checkVariable(var);
}
@ -65,13 +65,13 @@ class DereferenceChecker extends Visitor {
// Assignment Expressions
//
public AssignNode visit(AssignNode node) {
public Void visit(AssignNode node) {
super.visit(node);
checkAssignment(node);
return null;
}
public OpAssignNode visit(OpAssignNode node) {
public Void visit(OpAssignNode node) {
super.visit(node);
checkAssignment(node);
return null;
@ -87,7 +87,7 @@ class DereferenceChecker extends Visitor {
// Expressions
//
public PrefixOpNode visit(PrefixOpNode node) {
public Void visit(PrefixOpNode node) {
super.visit(node);
if (! node.expr().isAssignable()) {
semanticError(node.expr(), "cannot increment/decrement");
@ -95,7 +95,7 @@ class DereferenceChecker extends Visitor {
return null;
}
public SuffixOpNode visit(SuffixOpNode node) {
public Void visit(SuffixOpNode node) {
super.visit(node);
if (! node.expr().isAssignable()) {
semanticError(node.expr(), "cannot increment/decrement");
@ -103,7 +103,7 @@ class DereferenceChecker extends Visitor {
return null;
}
public FuncallNode visit(FuncallNode node) {
public Void visit(FuncallNode node) {
super.visit(node);
if (! node.expr().isCallable()) {
semanticError(node, "calling object is not a function");
@ -111,7 +111,7 @@ class DereferenceChecker extends Visitor {
return null;
}
public ArefNode visit(ArefNode node) {
public Void visit(ArefNode node) {
super.visit(node);
if (! node.expr().isDereferable()) {
semanticError(node, "indexing non-array/pointer expression");
@ -119,13 +119,13 @@ class DereferenceChecker extends Visitor {
return null;
}
public MemberNode visit(MemberNode node) {
public Void visit(MemberNode node) {
super.visit(node);
checkMemberRef(node, node.expr().type(), node.member());
return null;
}
public PtrMemberNode visit(PtrMemberNode node) {
public Void visit(PtrMemberNode node) {
super.visit(node);
if (! node.expr().isDereferable()) {
undereferableError(node);
@ -146,7 +146,7 @@ class DereferenceChecker extends Visitor {
}
}
public DereferenceNode visit(DereferenceNode node) {
public Void visit(DereferenceNode node) {
super.visit(node);
if (! node.expr().isDereferable()) {
undereferableError(node);
@ -154,7 +154,7 @@ class DereferenceChecker extends Visitor {
return null;
}
public AddressNode visit(AddressNode node) {
public Void visit(AddressNode node) {
super.visit(node);
if (! node.expr().isAssignable()) {
semanticError(node, "invalid LHS expression for &");

View File

@ -39,7 +39,7 @@ public class JumpResolver extends Visitor {
n.accept(this);
}
public SwitchNode visit(SwitchNode node) {
public Void visit(SwitchNode node) {
resolve(node.cond());
breakTargetStack.add(node);
visitStmts(node.cases());
@ -48,7 +48,7 @@ public class JumpResolver extends Visitor {
}
// #@@range/_while{
public WhileNode visit(WhileNode node) {
public Void visit(WhileNode node) {
resolve(node.cond());
breakTargetStack.add(node);
continueTargetStack.add(node);
@ -59,7 +59,7 @@ public class JumpResolver extends Visitor {
}
// #@@}
public DoWhileNode visit(DoWhileNode node) {
public Void visit(DoWhileNode node) {
breakTargetStack.add(node);
continueTargetStack.add(node);
resolve(node.body());
@ -70,7 +70,7 @@ public class JumpResolver extends Visitor {
}
// #@@range/_for{
public ForNode visit(ForNode node) {
public Void visit(ForNode node) {
resolve(node.init());
resolve(node.cond());
breakTargetStack.add(node);
@ -84,7 +84,7 @@ public class JumpResolver extends Visitor {
// #@@}
// #@@range/_break{
public BreakNode visit(BreakNode node) {
public Void visit(BreakNode node) {
if (breakTargetStack.isEmpty()) {
errorHandler.error(node.location(),
"break from out of while/do-while/for/switch");
@ -97,7 +97,7 @@ public class JumpResolver extends Visitor {
// #@@}
// #@@range/_continue{
public ContinueNode visit(ContinueNode node) {
public Void visit(ContinueNode node) {
if (breakTargetStack.isEmpty()) {
errorHandler.error(node.location(),
"continue from out of while/do-while/for");
@ -109,7 +109,7 @@ public class JumpResolver extends Visitor {
}
// #@@}
public LabelNode visit(LabelNode node) {
public Void visit(LabelNode node) {
try {
Label label = currentFunction.defineLabel(node.name(),
node.location());
@ -121,12 +121,12 @@ public class JumpResolver extends Visitor {
return null;
}
public GotoNode visit(GotoNode node) {
public Void visit(GotoNode node) {
node.setTargetLabel(currentFunction.referLabel(node.target()));
return null;
}
public ReturnNode visit(ReturnNode node) {
public Void visit(ReturnNode node) {
node.setFunction(currentFunction);
return null;
}

View File

@ -70,7 +70,7 @@ public class LocalResolver extends Visitor {
// #@@}
// #@@range/BlockNode{
public BlockNode visit(BlockNode node) {
public Void visit(BlockNode node) {
pushScope(node.variables());
super.visit(node);
node.setScope(popScope());
@ -106,14 +106,14 @@ public class LocalResolver extends Visitor {
// #@@}
// #@@range/StringLiteralNode{
public StringLiteralNode visit(StringLiteralNode node) {
public Void visit(StringLiteralNode node) {
node.setEntry(constantTable.intern(node.value()));
return null;
}
// #@@}
// #@@range/VariableNode{
public VariableNode visit(VariableNode node) {
public Void visit(VariableNode node) {
try {
Entity ent = currentScope().get(node.name());
ent.refered();

View File

@ -4,7 +4,7 @@ import net.loveruby.cflat.type.*;
import net.loveruby.cflat.exception.*;
import java.util.*;
class TypeChecker implements ASTVisitor<Node, ExprNode> {
class TypeChecker extends Visitor {
protected TypeTable typeTable;
protected ErrorHandler errorHandler;
private DefinedFunction currentFunction;
@ -15,14 +15,25 @@ class TypeChecker implements ASTVisitor<Node, ExprNode> {
}
// #@@}
protected void check(StmtNode node) {
visitStmt(node);
}
protected void check(ExprNode node) {
visitExpr(node);
}
// #@@range/check_AST{
public void check(AST ast) throws SemanticException {
this.typeTable = ast.typeTable();
for (DefinedVariable var : ast.definedVariables()) {
visit(var);
checkVariable(var);
}
for (DefinedFunction f : ast.definedFunctions()) {
visit(f);
currentFunction = f;
checkReturnType(f);
checkParamTypes(f);
check(f.body());
}
if (errorHandler.errorOccured()) {
throw new SemanticException("compile failed.");
@ -30,38 +41,6 @@ class TypeChecker implements ASTVisitor<Node, ExprNode> {
}
// #@@}
public DefinedFunction visit(DefinedFunction f) {
currentFunction = 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());
@ -76,115 +55,74 @@ class TypeChecker implements ASTVisitor<Node, ExprNode> {
}
}
protected void checkStmt(StmtNode node) {
node.accept(this);
}
protected ExprNode checkExpr(ExprNode node) {
if (node == null) return null;
return node.accept(this);
}
//
// Declarations
// Statements
//
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) {
public Void visit(BlockNode node) {
for (DefinedVariable var : node.variables()) {
visit(var);
checkVariable(var);
}
for (StmtNode n : node.stmts()) {
checkStmt(n);
check(n);
}
return null;
}
public ExprStmtNode visit(ExprStmtNode node) {
ExprNode expr = checkExpr(node.expr());
if (isInvalidStatementType(expr.type())) {
error(expr, "invalid statement type: " + expr.type());
protected void checkVariable(DefinedVariable var) {
if (isInvalidVariableType(var.type())) {
error(var, "invalid variable type");
return;
}
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()));
}
}
public Void visit(ExprStmtNode node) {
check(node.expr());
if (isInvalidStatementType(node.expr().type())) {
error(node, "invalid statement type: " + node.expr().type());
return null;
}
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());
}
public Void visit(IfNode node) {
super.visit(node);
checkCond(node.cond());
return null;
}
public WhileNode visit(WhileNode node) {
node.setCond(checkCond(node.cond()));
checkStmt(node.body());
public Void visit(WhileNode node) {
super.visit(node);
checkCond(node.cond());
return null;
}
public DoWhileNode visit(DoWhileNode node) {
checkStmt(node.body());
node.setCond(checkCond(node.cond()));
public Void visit(ForNode node) {
super.visit(node);
checkCond(node.cond());
return null;
}
public ForNode visit(ForNode node) {
checkStmt(node.init());
node.setCond(checkCond(node.cond()));
checkStmt(node.incr());
checkStmt(node.body());
protected void checkCond(ExprNode cond) {
mustBeScalar(cond, "condition expression");
}
public Void visit(SwitchNode node) {
super.visit(node);
mustBeInteger(node.cond(), "condition expression");
return null;
}
protected ExprNode checkCond(ExprNode cond) {
ExprNode expr = checkExpr(cond);
mustBeScalar(expr, "condition expression");
return expr;
}
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 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()));
}
public Void visit(ReturnNode node) {
super.visit(node);
if (currentFunction.isVoid()) {
if (node.expr() != null) {
error(node, "returning value from void function");
@ -205,61 +143,45 @@ class TypeChecker implements ASTVisitor<Node, ExprNode> {
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 AssignNode visit(AssignNode node) {
return new AssignNode(checkLHS(node.lhs()), checkRHS(node.rhs()));
public Void visit(AssignNode node) {
super.visit(node);
if (! checkLHS(node.lhs())) return null;
if (! checkRHS(node.rhs())) return null;
node.setRHS(implicitCast(node.lhs().type(), node.rhs()));
return null;
}
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));
public Void visit(OpAssignNode node) {
super.visit(node);
if (! checkLHS(node.lhs())) return null;
if (! checkRHS(node.rhs())) return null;
if (node.operator().equals("+")
|| node.operator().equals("-")) {
if (node.lhs().type().isPointer()) {
if (! mustBeInteger(node.rhs(), node.operator())) return null;
node.setRHS(multiplyPtrBaseSize(node.rhs(), node.lhs()));
return null;
}
}
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());
if (! mustBeInteger(node.lhs(), node.operator())) return null;
if (! mustBeInteger(node.rhs(), node.operator())) return null;
Type l = integralPromotion(node.lhs().type());
Type r = integralPromotion(node.rhs().type());
Type opType = usualArithmeticConversion(l, r);
if (! opType.isCompatible(l)
&& ! isSafeIntegerCast(rhs, opType)) {
&& ! isSafeIntegerCast(node.rhs(), opType)) {
warn(node, "incompatible implicit cast from "
+ opType + " to " + l);
}
if (r.isSameType(opType)) {
return new OpAssignNode(lhs, node.operator(), rhs);
}
else { // cast RHS
return new OpAssignNode(lhs, node.operator(), new CastNode(opType, rhs));
if (! r.isSameType(opType)) {
// cast RHS
node.setRHS(new CastNode(opType, node.rhs()));
}
return null;
}
/** allow safe implicit cast from integer literal like:
@ -276,37 +198,48 @@ class TypeChecker implements ASTVisitor<Node, ExprNode> {
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 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);
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 null;
}
else if (t.type().isCompatible(e.type())) { // insert cast on thenExpr
node.setExprs(c, new CastNode(e.type(), t), e);
else if (t.isCompatible(e)) { // insert cast on thenBody
node.setThenExpr(new CastNode(e, node.thenExpr()));
}
else if (e.type().isCompatible(t.type())) { // insert cast on elseExpr
node.setExprs(c, t, new CastNode(t.type(), e));
else if (e.isCompatible(t)) { // insert cast on elseBody
node.setElseExpr(new CastNode(t, node.elseExpr()));
}
else {
invalidCastError(t, e.type(), t.type());
invalidCastError(node.thenExpr(), e, t);
}
return node;
return null;
}
// #@@range/BinaryOpNode{
public BinaryOpNode visit(BinaryOpNode node) {
node.setLeft(checkExpr(node.left()));
node.setRight(checkExpr(node.right()));
if (node.operator().equals("+")
|| node.operator().equals("-")) {
expectsSameIntegerOrPointerDiff(node);
return node;
public Void visit(BinaryOpNode node) {
super.visit(node);
if (node.operator().equals("+") || node.operator().equals("-")) {
Type t = expectsSameIntegerOrPointerDiff(node);
if (t != null) node.setType(t);
}
else if (node.operator().equals("*")
|| node.operator().equals("/")
@ -316,8 +249,8 @@ class TypeChecker implements ASTVisitor<Node, ExprNode> {
|| node.operator().equals("^")
|| node.operator().equals("<<")
|| node.operator().equals(">>")) {
expectsSameInteger(node);
return node;
Type t = expectsSameInteger(node);
if (t != null) node.setType(t);
}
else if (node.operator().equals("==")
|| node.operator().equals("!=")
@ -325,27 +258,28 @@ class TypeChecker implements ASTVisitor<Node, ExprNode> {
|| node.operator().equals("<=")
|| node.operator().equals(">")
|| node.operator().equals(">=")) {
expectsComparableScalars(node);
return node;
Type t = expectsComparableScalars(node);
if (t != null) node.setType(t);
}
else {
throw new Error("unknown binary operator: " + node.operator());
}
return null;
}
// #@@}
public LogicalAndNode visit(LogicalAndNode node) {
node.setLeft(checkExpr(node.left()));
node.setRight(checkExpr(node.right()));
expectsComparableScalars(node);
return node;
public Void visit(LogicalAndNode node) {
super.visit(node);
Type t = expectsComparableScalars(node);
if (t != null) node.setType(t);
return null;
}
public LogicalOrNode visit(LogicalOrNode 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);
return null;
}
/**
@ -357,31 +291,31 @@ class TypeChecker implements ASTVisitor<Node, ExprNode> {
* * integer - integer
* * pointer - integer
*/
protected void expectsSameIntegerOrPointerDiff(BinaryOpNode node) {
protected Type expectsSameIntegerOrPointerDiff(BinaryOpNode node) {
if (node.left().type().isDereferable()) {
if (node.left().type().baseType().isVoid()) {
wrongTypeError(node.left(), node.operator());
return;
return null;
}
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;
return null;
}
if (node.right().type().baseType().isVoid()) {
wrongTypeError(node.right(), node.operator());
return;
return null;
}
mustBeInteger(node.left(), node.operator());
node.setType(node.right().type());
node.setLeft(multiplyPtrBaseSize(node.left(), node.right()));
return node.right().type();
}
else {
expectsSameInteger(node);
return expectsSameInteger(node);
}
}
@ -417,28 +351,28 @@ class TypeChecker implements ASTVisitor<Node, ExprNode> {
// +, -, *, /, %, &, |, ^, <<, >>
// #@@range/expectsSameInteger{
protected void expectsSameInteger(BinaryOpNode bin) {
if (! mustBeInteger(bin.left(), bin.operator())) return;
if (! mustBeInteger(bin.right(), bin.operator())) return;
arithmeticImplicitCast(bin);
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 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;
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();
}
if (bin.right().type().isDereferable()) {
bin.setType(bin.right().type());
bin.setLeft(forcePointerType(bin.right(), bin.left()));
return;
if (node.right().type().isDereferable()) {
ExprNode left = forcePointerType(node.right(), node.left());
node.setLeft(left);
return node.right().type();
}
arithmeticImplicitCast(bin);
return arithmeticImplicitCast(node);
}
// cast slave node to master node.
@ -456,44 +390,46 @@ class TypeChecker implements ASTVisitor<Node, ExprNode> {
// Processes usual arithmetic conversion for binary operations.
// #@@range/arithmeticImplicitCast{
protected void arithmeticImplicitCast(BinaryOpNode bin) {
Type r = integralPromotion(bin.right().type());
Type l = integralPromotion(bin.left().type());
protected Type arithmeticImplicitCast(BinaryOpNode node) {
Type r = integralPromotion(node.right().type());
Type l = integralPromotion(node.left().type());
Type target = usualArithmeticConversion(l, r);
bin.setType(target);
if (! l.isSameType(target)) {
bin.setLeft(new CastNode(target, bin.left()));
// insert cast on left expr
node.setLeft(new CastNode(target, node.left()));
}
if (! r.isSameType(target)) {
bin.setRight(new CastNode(target, bin.right()));
// insert cast on right expr
node.setRight(new CastNode(target, node.right()));
}
return target;
}
// #@@}
// +, -, !, ~
public UnaryOpNode visit(UnaryOpNode un) {
ExprNode expr = checkExpr(un.expr());
if (un.operator().equals("!")) {
mustBeScalar(expr, un.operator());
public Void visit(UnaryOpNode node) {
super.visit(node);
if (node.operator().equals("!")) {
mustBeScalar(node.expr(), node.operator());
}
else {
mustBeInteger(expr, un.operator());
mustBeInteger(node.expr(), node.operator());
}
return new UnaryOpNode(un.operator(), expr);
return null;
}
// ++x, --x
public PrefixOpNode visit(PrefixOpNode pre) {
pre.setExpr(checkExpr(pre.expr()));
expectsScalarLHS(pre);
return pre;
public Void visit(PrefixOpNode node) {
super.visit(node);
expectsScalarLHS(node);
return null;
}
// x++, x--
public SuffixOpNode visit(SuffixOpNode suf) {
suf.setExpr(checkExpr(suf.expr()));
expectsScalarLHS(suf);
return suf;
public Void visit(SuffixOpNode node) {
super.visit(node);
expectsScalarLHS(node);
return null;
}
protected void expectsScalarLHS(UnaryArithmeticOpNode node) {
@ -508,7 +444,6 @@ class TypeChecker implements ASTVisitor<Node, ExprNode> {
else {
mustBeScalar(node.expr(), node.operator());
}
if (node.expr().type().isInteger()) {
Type opType = integralPromotion(node.expr().type());
if (! node.expr().type().isSameType(opType)) {
@ -536,102 +471,51 @@ class TypeChecker implements ASTVisitor<Node, ExprNode> {
* * ARG matches function prototype.
* * ARG is neither a struct nor an union.
*/
public FuncallNode visit(FuncallNode node) {
ExprNode expr = checkExpr(node.expr());
public Void visit(FuncallNode node) {
super.visit(node);
FunctionType type = node.functionType();
if (! type.acceptsArgc(node.numArgs())) {
error(node, "wrong number of argments: " + node.numArgs());
return node;
return null;
}
// 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 = checkRHS(args.next());
newArgs.add(isInvalidRHSType(arg.type()) ? arg : implicitCast(param, arg));
ExprNode arg = args.next();
newArgs.add(checkRHS(arg) ? implicitCast(param, arg) : arg);
}
while (args.hasNext()) {
newArgs.add(checkRHS(args.next()));
newArgs.add(args.next());
}
return new FuncallNode(expr, newArgs);
node.replaceArgs(newArgs);
return null;
}
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(ArefNode node) {
super.visit(node);
mustBeInteger(node.index(), "[]");
return null;
}
public CastNode visit(CastNode node) {
ExprNode expr = checkExpr(node.expr());
if (! expr.type().isCastableTo(node.type())) {
invalidCastError(node, expr.type(), node.type());
public Void visit(CastNode node) {
super.visit(node);
if (! node.expr().type().isCastableTo(node.type())) {
invalidCastError(node, 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;
return null;
}
//
// Utilities
//
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);
protected boolean checkRHS(ExprNode rhs) {
if (isInvalidRHSType(rhs.type())) {
error(rhs, "invalid RHS expression type: " + rhs.type());
return false;
}
return rhs;
return true;
}
// Processes forced-implicit-cast.

View File

@ -51,14 +51,14 @@ public class TypeResolver extends Visitor {
// #@@}
// #@@range/StructNode{
public StructNode visit(StructNode struct) {
public Void visit(StructNode struct) {
resolveCompositeType(struct);
return null;
}
// #@@}
// #@@range/UnionNode{
public UnionNode visit(UnionNode union) {
public Void visit(UnionNode union) {
resolveCompositeType(union);
return null;
}
@ -77,7 +77,7 @@ public class TypeResolver extends Visitor {
// #@@}
// #@@range/TypedefNode{
public TypedefNode visit(TypedefNode typedef) {
public Void visit(TypedefNode typedef) {
bindType(typedef.typeNode());
bindType(typedef.realTypeNode());
return null;
@ -85,27 +85,27 @@ public class TypeResolver extends Visitor {
// #@@}
// #@@range/DefinedVariable{
public DefinedVariable visit(DefinedVariable var) {
public Void visit(DefinedVariable var) {
bindType(var.typeNode());
super.visit(var); // resolve initializer
return null;
}
// #@@}
public UndefinedVariable visit(UndefinedVariable var) {
public Void visit(UndefinedVariable var) {
bindType(var.typeNode());
return null;
}
// #@@range/DefinedFunction{
public DefinedFunction visit(DefinedFunction func) {
public Void visit(DefinedFunction func) {
resolveFunctionHeader(func);
visitStmt(func.body());
return null;
}
// #@@}
public UndefinedFunction visit(UndefinedFunction func) {
public Void visit(UndefinedFunction func) {
resolveFunctionHeader(func);
return null;
}
@ -124,7 +124,7 @@ public class TypeResolver extends Visitor {
}
// #@@}
public AddressNode visit(AddressNode node) {
public Void visit(AddressNode node) {
super.visit(node);
// to avoid SemanticError which occurs when getting type of
// expr which is not assignable.
@ -144,31 +144,31 @@ public class TypeResolver extends Visitor {
return null;
}
public CastNode visit(CastNode node) {
public Void visit(CastNode node) {
bindType(node.typeNode());
super.visit(node);
return null;
}
public SizeofExprNode visit(SizeofExprNode node) {
public Void visit(SizeofExprNode node) {
bindType(node.typeNode());
super.visit(node);
return null;
}
public SizeofTypeNode visit(SizeofTypeNode node) {
public Void visit(SizeofTypeNode node) {
bindType(node.operandTypeNode());
bindType(node.typeNode());
super.visit(node);
return null;
}
public IntegerLiteralNode visit(IntegerLiteralNode node) {
public Void visit(IntegerLiteralNode node) {
bindType(node.typeNode());
return null;
}
public StringLiteralNode visit(StringLiteralNode node) {
public Void visit(StringLiteralNode node) {
bindType(node.typeNode());
return null;
}

View File

@ -2,7 +2,8 @@ package net.loveruby.cflat.compiler;
import net.loveruby.cflat.ast.*;
import java.util.*;
abstract public class Visitor implements ASTVisitor<Node, ExprNode> {
// We do not use return value of methods.
abstract public class Visitor implements ASTVisitor<Void, Void> {
public Visitor() {
}
@ -30,34 +31,34 @@ abstract public class Visitor implements ASTVisitor<Node, ExprNode> {
// Declarations
//
public DefinedVariable visit(DefinedVariable var) {
public Void visit(DefinedVariable var) {
if (var.hasInitializer()) {
visitExpr(var.initializer());
}
return null;
}
public UndefinedVariable visit(UndefinedVariable var) {
public Void visit(UndefinedVariable var) {
return null;
}
public DefinedFunction visit(DefinedFunction func) {
public Void visit(DefinedFunction func) {
return null;
}
public UndefinedFunction visit(UndefinedFunction func) {
public Void visit(UndefinedFunction func) {
return null;
}
public StructNode visit(StructNode struct) {
public Void visit(StructNode struct) {
return null;
}
public UnionNode visit(UnionNode union) {
public Void visit(UnionNode union) {
return null;
}
public TypedefNode visit(TypedefNode typedef) {
public Void visit(TypedefNode typedef) {
return null;
}
@ -65,7 +66,7 @@ abstract public class Visitor implements ASTVisitor<Node, ExprNode> {
// Statements
//
public BlockNode visit(BlockNode node) {
public Void visit(BlockNode node) {
for (DefinedVariable var : node.variables()) {
visit(var);
}
@ -73,12 +74,12 @@ abstract public class Visitor implements ASTVisitor<Node, ExprNode> {
return null;
}
public ExprStmtNode visit(ExprStmtNode node) {
public Void visit(ExprStmtNode node) {
visitExpr(node.expr());
return null;
}
public IfNode visit(IfNode n) {
public Void visit(IfNode n) {
visitExpr(n.cond());
visitStmt(n.thenBody());
if (n.elseBody() != null) {
@ -87,31 +88,31 @@ abstract public class Visitor implements ASTVisitor<Node, ExprNode> {
return null;
}
public SwitchNode visit(SwitchNode n) {
public Void visit(SwitchNode n) {
visitExpr(n.cond());
visitStmts(n.cases());
return null;
}
public CaseNode visit(CaseNode n) {
public Void visit(CaseNode n) {
visitExprs(n.values());
visitStmt(n.body());
return null;
}
public WhileNode visit(WhileNode n) {
public Void visit(WhileNode n) {
visitExpr(n.cond());
visitStmt(n.body());
return null;
}
public DoWhileNode visit(DoWhileNode n) {
public Void visit(DoWhileNode n) {
visitStmt(n.body());
visitExpr(n.cond());
return null;
}
public ForNode visit(ForNode n) {
public Void visit(ForNode n) {
visitStmt(n.init());
visitExpr(n.cond());
visitStmt(n.incr());
@ -119,24 +120,24 @@ abstract public class Visitor implements ASTVisitor<Node, ExprNode> {
return null;
}
public BreakNode visit(BreakNode n) {
public Void visit(BreakNode n) {
return null;
}
public ContinueNode visit(ContinueNode n) {
public Void visit(ContinueNode n) {
return null;
}
public GotoNode visit(GotoNode n) {
public Void visit(GotoNode n) {
return null;
}
public LabelNode visit(LabelNode n) {
public Void visit(LabelNode n) {
visitStmt(n.stmt());
return null;
}
public ReturnNode visit(ReturnNode n) {
public Void visit(ReturnNode n) {
if (n.expr() != null) {
visitExpr(n.expr());
}
@ -147,7 +148,7 @@ abstract public class Visitor implements ASTVisitor<Node, ExprNode> {
// Expressions
//
public CondExprNode visit(CondExprNode n) {
public Void visit(CondExprNode n) {
visitExpr(n.cond());
visitExpr(n.thenExpr());
if (n.elseExpr() != null) {
@ -156,106 +157,106 @@ abstract public class Visitor implements ASTVisitor<Node, ExprNode> {
return null;
}
public LogicalOrNode visit(LogicalOrNode node) {
public Void visit(LogicalOrNode node) {
visitExpr(node.left());
visitExpr(node.right());
return null;
}
public LogicalAndNode visit(LogicalAndNode node) {
public Void visit(LogicalAndNode node) {
visitExpr(node.left());
visitExpr(node.right());
return null;
}
public AssignNode visit(AssignNode n) {
public Void visit(AssignNode n) {
visitExpr(n.lhs());
visitExpr(n.rhs());
return null;
}
public OpAssignNode visit(OpAssignNode n) {
public Void visit(OpAssignNode n) {
visitExpr(n.lhs());
visitExpr(n.rhs());
return null;
}
public BinaryOpNode visit(BinaryOpNode n) {
public Void visit(BinaryOpNode n) {
visitExpr(n.left());
visitExpr(n.right());
return null;
}
public UnaryOpNode visit(UnaryOpNode node) {
public Void visit(UnaryOpNode node) {
visitExpr(node.expr());
return null;
}
public PrefixOpNode visit(PrefixOpNode node) {
public Void visit(PrefixOpNode node) {
visitExpr(node.expr());
return null;
}
public SuffixOpNode visit(SuffixOpNode node) {
public Void visit(SuffixOpNode node) {
visitExpr(node.expr());
return null;
}
public FuncallNode visit(FuncallNode node) {
public Void visit(FuncallNode node) {
visitExpr(node.expr());
visitExprs(node.arguments());
return null;
}
public ArefNode visit(ArefNode node) {
public Void visit(ArefNode node) {
visitExpr(node.expr());
visitExpr(node.index());
return null;
}
public MemberNode visit(MemberNode node) {
public Void visit(MemberNode node) {
visitExpr(node.expr());
return null;
}
public PtrMemberNode visit(PtrMemberNode node) {
public Void visit(PtrMemberNode node) {
visitExpr(node.expr());
return null;
}
public DereferenceNode visit(DereferenceNode node) {
public Void visit(DereferenceNode node) {
visitExpr(node.expr());
return null;
}
public ExprNode visit(AddressNode node) {
public Void visit(AddressNode node) {
visitExpr(node.expr());
return null;
}
public ExprNode visit(CastNode node) {
public Void visit(CastNode node) {
visitExpr(node.expr());
return null;
}
public ExprNode visit(SizeofExprNode node) {
public Void visit(SizeofExprNode node) {
visitExpr(node.expr());
return null;
}
public ExprNode visit(SizeofTypeNode node) {
public Void visit(SizeofTypeNode node) {
return null;
}
public ExprNode visit(VariableNode node) {
public Void visit(VariableNode node) {
return null;
}
public ExprNode visit(IntegerLiteralNode node) {
public Void visit(IntegerLiteralNode node) {
return null;
}
public ExprNode visit(StringLiteralNode node) {
public Void visit(StringLiteralNode node) {
return null;
}
}