diff --git a/ChangeLog b/ChangeLog index 1e62c33..5d97c19 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,24 @@ +Sun Apr 12 16:37:16 2009 Minero Aoki + + * 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 * net/loveruby/cflat/compiler/Visitor.java: make all return types diff --git a/net/loveruby/cflat/ast/AbstractAssignNode.java b/net/loveruby/cflat/ast/AbstractAssignNode.java index cb9a1af..899908a 100644 --- a/net/loveruby/cflat/ast/AbstractAssignNode.java +++ b/net/loveruby/cflat/ast/AbstractAssignNode.java @@ -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(); } diff --git a/net/loveruby/cflat/ast/CondExprNode.java b/net/loveruby/cflat/ast/CondExprNode.java index e7a22ec..0c319de 100644 --- a/net/loveruby/cflat/ast/CondExprNode.java +++ b/net/loveruby/cflat/ast/CondExprNode.java @@ -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() { diff --git a/net/loveruby/cflat/compiler/CodeGenerator.java b/net/loveruby/cflat/compiler/CodeGenerator.java index c0a8c9f..ca7cd98 100644 --- a/net/loveruby/cflat/compiler/CodeGenerator.java +++ b/net/loveruby/cflat/compiler/CodeGenerator.java @@ -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 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; } diff --git a/net/loveruby/cflat/compiler/DereferenceChecker.java b/net/loveruby/cflat/compiler/DereferenceChecker.java index fcd12d2..dd48dd0 100644 --- a/net/loveruby/cflat/compiler/DereferenceChecker.java +++ b/net/loveruby/cflat/compiler/DereferenceChecker.java @@ -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 &"); diff --git a/net/loveruby/cflat/compiler/JumpResolver.java b/net/loveruby/cflat/compiler/JumpResolver.java index 642c5cb..c3c675d 100644 --- a/net/loveruby/cflat/compiler/JumpResolver.java +++ b/net/loveruby/cflat/compiler/JumpResolver.java @@ -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; } diff --git a/net/loveruby/cflat/compiler/LocalResolver.java b/net/loveruby/cflat/compiler/LocalResolver.java index 86eff9a..150b134 100644 --- a/net/loveruby/cflat/compiler/LocalResolver.java +++ b/net/loveruby/cflat/compiler/LocalResolver.java @@ -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(); diff --git a/net/loveruby/cflat/compiler/TypeChecker.java b/net/loveruby/cflat/compiler/TypeChecker.java index 6d95c32..9c076e0 100644 --- a/net/loveruby/cflat/compiler/TypeChecker.java +++ b/net/loveruby/cflat/compiler/TypeChecker.java @@ -4,7 +4,7 @@ import net.loveruby.cflat.type.*; import net.loveruby.cflat.exception.*; import java.util.*; -class TypeChecker implements ASTVisitor { +class TypeChecker extends Visitor { protected TypeTable typeTable; protected ErrorHandler errorHandler; private DefinedFunction currentFunction; @@ -15,14 +15,25 @@ class TypeChecker implements ASTVisitor { } // #@@} + 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 { } // #@@} - 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 { } } - 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 exprs = new ArrayList(); - for (ExprNode expr : node.values()) { - ExprNode e = checkExpr(expr); - mustBeInteger(e, "case"); - exprs.add(e); - } - node.setValues(exprs); - return null; - } - - public ReturnNode visit(ReturnNode node) { - if (node.expr() != null) { - node.setExpr(checkExpr(node.expr())); - } + 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 { 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 { 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.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.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 { * * 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 { // +, -, *, /, %, &, |, ^, <<, >> // #@@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 { // 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 { 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 { * * 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 args = node.arguments().iterator(); List newArgs = new ArrayList(); 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. diff --git a/net/loveruby/cflat/compiler/TypeResolver.java b/net/loveruby/cflat/compiler/TypeResolver.java index 2c44f6a..085a526 100644 --- a/net/loveruby/cflat/compiler/TypeResolver.java +++ b/net/loveruby/cflat/compiler/TypeResolver.java @@ -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; } diff --git a/net/loveruby/cflat/compiler/Visitor.java b/net/loveruby/cflat/compiler/Visitor.java index 680acdf..d1f923d 100644 --- a/net/loveruby/cflat/compiler/Visitor.java +++ b/net/loveruby/cflat/compiler/Visitor.java @@ -2,7 +2,8 @@ package net.loveruby.cflat.compiler; import net.loveruby.cflat.ast.*; import java.util.*; -abstract public class Visitor implements ASTVisitor { +// We do not use return value of methods. +abstract public class Visitor implements ASTVisitor { public Visitor() { } @@ -30,34 +31,34 @@ abstract public class Visitor implements ASTVisitor { // 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 { // 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 { 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 { 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 { 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 { // 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 { 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; } }