mirror of https://github.com/aamine/cbc
* 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:
parent
d514300aef
commit
f69902e1d7
21
ChangeLog
21
ChangeLog
|
@ -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
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
|
|
@ -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() {
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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 &");
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue