* net/loveruby/cflat/compiler/Compiler.java: show error location.

* net/loveruby/cflat/compiler/TypeResolver.java: ditto.
* net/loveruby/cflat/compiler/TypeChecker.java: ditto.
* net/loveruby/cflat/compiler/ErrorHandler.java: ditto.
* net/loveruby/cflat/compiler/LocalReferenceResolver.java: ditto.
* net/loveruby/cflat/compiler/JumpResolver.java: ditto.
* net/loveruby/cflat/type/TypeTable.java: ditto.
* net/loveruby/cflat/ast/Scope.java: ditto.
* net/loveruby/cflat/type/NamedType.java: introduce new common superclass of ComplexType and UserType.
* net/loveruby/cflat/type/ComplexType.java: inherit NamedType.
* net/loveruby/cflat/type/UserType.java: inherit NamedType.
* net/loveruby/cflat/type/StructType.java: memoise defined location.
* net/loveruby/cflat/type/UnionType.java: ditto.
* net/loveruby/cflat/ast/DefinedFunction.java: ditto.
* net/loveruby/cflat/type/TypeTable.java: change define* methods interface to pass all definition informations.
* net/loveruby/cflat/ast/StructNode.java: follow it.
* net/loveruby/cflat/ast/UnionNode.java: follow it.
* net/loveruby/cflat/ast/TypedefNode.java: follow it.


git-svn-id: file:///Users/aamine/c/gitwork/public/cbc/trunk@3801 1b9489fe-b721-0410-924e-b54b9192deb8
This commit is contained in:
Minero Aoki 2008-01-05 03:23:27 +00:00
parent 879738ba62
commit 8bc055ed4e
18 changed files with 214 additions and 112 deletions

View File

@ -1,3 +1,44 @@
Sat Jan 5 12:23:25 2008 Minero Aoki <aamine@loveruby.net>
* net/loveruby/cflat/compiler/Compiler.java: show error location.
* net/loveruby/cflat/compiler/TypeResolver.java: ditto.
* net/loveruby/cflat/compiler/TypeChecker.java: ditto.
* net/loveruby/cflat/compiler/ErrorHandler.java: ditto.
* net/loveruby/cflat/compiler/LocalReferenceResolver.java: ditto.
* net/loveruby/cflat/compiler/JumpResolver.java: ditto.
* net/loveruby/cflat/type/TypeTable.java: ditto.
* net/loveruby/cflat/ast/Scope.java: ditto.
* net/loveruby/cflat/type/NamedType.java: introduce new common
superclass of ComplexType and UserType.
* net/loveruby/cflat/type/ComplexType.java: inherit NamedType.
* net/loveruby/cflat/type/UserType.java: inherit NamedType.
* net/loveruby/cflat/type/StructType.java: memoise defined
location.
* net/loveruby/cflat/type/UnionType.java: ditto.
* net/loveruby/cflat/ast/DefinedFunction.java: ditto.
* net/loveruby/cflat/type/TypeTable.java: change define* methods
interface to pass all definition informations.
* net/loveruby/cflat/ast/StructNode.java: follow it.
* net/loveruby/cflat/ast/UnionNode.java: follow it.
* net/loveruby/cflat/ast/TypedefNode.java: follow it.
Sat Jan 5 10:34:24 2008 Minero Aoki <aamine@loveruby.net>
* net/loveruby/cflat/ast/Node.java: all nodes must contain

View File

@ -59,6 +59,7 @@ public class DefinedFunction extends Function {
public Label label;
public long numRefered;
public boolean isDefined;
public Location location;
public JumpEntry(Label label) {
this.label = label;
@ -67,13 +68,15 @@ public class DefinedFunction extends Function {
}
}
public Label defineLabel(String name) throws SemanticException {
public Label defineLabel(String name, Location loc)
throws SemanticException {
JumpEntry ent = getJumpEntry(name);
if (ent.isDefined) {
throw new SemanticException(
"duplicated jump labels in " + name + "(): " + name);
}
ent.isDefined = true;
ent.location = loc;
return ent.label;
}
@ -99,11 +102,12 @@ public class DefinedFunction extends Function {
String labelName = (String)ent.getKey();
JumpEntry jump = (JumpEntry)ent.getValue();
if (!jump.isDefined) {
handler.error("undefined label in function " +
name + ": " + labelName);
handler.error(jump.location,
name + ": undefined label: " + labelName);
}
if (jump.numRefered == 0) {
handler.warn("useless label: " + labelName);
handler.warn(jump.location,
name + ": useless label: " + labelName);
}
}
}

View File

@ -152,18 +152,18 @@ public class Scope {
return result;
}
public void checkReferences(ErrorHandler handler) {
public void checkReferences(ErrorHandler h) {
Iterator ents = entities.iterator();
while (ents.hasNext()) {
Entity ent = (Entity)ents.next();
if (ent.isDefined() && ent.isPrivate() && !ent.isRefered()) {
handler.warn("unused variable: " + ent.name());
h.warn(ent.location(), "unused variable: " + ent.name());
}
}
Iterator cs = children.iterator();
while (cs.hasNext()) {
Scope s = (Scope)cs.next();
s.checkReferences(handler);
s.checkReferences(h);
}
}
}

View File

@ -16,7 +16,7 @@ public class StructNode extends ComplexTypeDefinition {
}
public void defineIn(TypeTable table) {
table.defineStruct((StructTypeRef)typeRef(), members());
table.defineStruct(this);
}
public void accept(ASTVisitor visitor) {

View File

@ -2,16 +2,31 @@ package net.loveruby.cflat.ast;
import net.loveruby.cflat.type.*;
public class TypedefNode extends TypeDefinition {
public TypedefNode(Location loc, TypeRef ref, String name) {
super(loc, ref, name);
protected TypeNode real;
public TypedefNode(Location loc, TypeRef real, String name) {
super(loc, new UserTypeRef(name), name);
this.real = new TypeNode(real);
}
public boolean isUserType() {
return true;
}
public TypeNode realTypeNode() {
return real;
}
public Type realType() {
return real.type();
}
public TypeRef realTypeRef() {
return real.typeRef();
}
public void defineIn(TypeTable table) {
table.defineUserType(new UserTypeRef(name()), typeNode());
table.defineUserType(this);
}
protected void _dump(Dumper d) {

View File

@ -16,7 +16,7 @@ public class UnionNode extends ComplexTypeDefinition {
}
public void defineIn(TypeTable table) {
table.defineUnion((UnionTypeRef)typeRef(), members());
table.defineUnion(this);
}
public void accept(ASTVisitor visitor) {

View File

@ -111,17 +111,23 @@ public class Compiler {
}
public void compileFile(String path) throws CompileException {
TypeTable typeTable = TypeTable.ilp32();
AST ast = parseFile(path);
JumpResolver.resolve(ast, errorHandler);
LocalReferenceResolver.resolve(ast, errorHandler);
TypeResolver.resolve(ast, typeTable, errorHandler);
TypeChecker.check(ast, typeTable, errorHandler);
TypeTable typeTable = TypeTable.ilp32();
semanticAnalysis(ast, typeTable);
String asm = CodeGenerator.generate(ast, typeTable, errorHandler);
writeFile(asmFileName(path), asm);
assemble(asmFileName(path));
}
public void semanticAnalysis(AST ast, TypeTable typeTable)
throws SemanticException {
JumpResolver.resolve(ast, errorHandler);
LocalReferenceResolver.resolve(ast, errorHandler);
TypeResolver.resolve(ast, typeTable, errorHandler);
typeTable.semanticCheck(errorHandler);
TypeChecker.check(ast, typeTable, errorHandler);
}
public AST parseFile(String path) throws CompileException {
return Parser.parseFile(new File(path), loader, errorHandler);
}

View File

@ -1,4 +1,5 @@
package net.loveruby.cflat.compiler;
import net.loveruby.cflat.ast.Location;
import java.io.*;
public class ErrorHandler {
@ -17,11 +18,19 @@ public class ErrorHandler {
this.stream = new PrintStream(stream);
}
public void error(Location loc, String msg) {
error(loc.toString() + ": " + msg);
}
public void error(String msg) {
stream.println(programId + ": error: " + msg);
nError++;
}
public void warn(Location loc, String msg) {
warn(loc.toString() + ": " + msg);
}
public void warn(String msg) {
stream.println(programId + ": warning: " + msg);
nWarning++;

View File

@ -29,7 +29,7 @@ public class JumpResolver extends Visitor {
currentFunction.checkJumpLinks(errorHandler);
}
if (errorHandler.errorOccured()) {
throw new SemanticException("semantic error");
throw new SemanticException("compile failed.");
}
}
@ -90,7 +90,7 @@ public class JumpResolver extends Visitor {
node.setTargetLabel(currentBreakTarget().endLabel());
}
catch (SemanticException ex) {
errorHandler.error(ex.getMessage());
errorHandler.error(node.location(), ex.getMessage());
}
}
@ -99,17 +99,18 @@ public class JumpResolver extends Visitor {
node.setTargetLabel(currentContinueTarget().continueLabel());
}
catch (SemanticException ex) {
errorHandler.error(ex.getMessage());
errorHandler.error(node.location(), ex.getMessage());
}
}
public void visit(LabelNode node) {
try {
Label label = currentFunction.defineLabel(node.name());
Label label = currentFunction.defineLabel(node.name(),
node.location());
node.setLabel(label);
}
catch (SemanticException ex) {
errorHandler.error(ex.getMessage());
errorHandler.error(node.location(), ex.getMessage());
}
}

View File

@ -9,13 +9,13 @@ public class LocalReferenceResolver extends Visitor {
new LocalReferenceResolver(handler).resolveAST(ast);
}
protected ErrorHandler handler;
protected ErrorHandler errorHandler;
protected ToplevelScope toplevel;
protected LinkedList scopeStack;
protected ConstantTable constantTable;
public LocalReferenceResolver(ErrorHandler handler) {
this.handler = handler;
public LocalReferenceResolver(ErrorHandler h) {
this.errorHandler = h;
}
public void resolveAST(AST ast) throws SemanticException {
@ -28,9 +28,9 @@ public class LocalReferenceResolver extends Visitor {
defineToplevelEntities(ast.entities());
resolveGvarInitializers(ast.variables());
resolveFunctions(ast.functions());
toplevel.checkReferences(handler);
if (handler.errorOccured()) {
throw new SemanticException("compile error");
toplevel.checkReferences(errorHandler);
if (errorHandler.errorOccured()) {
throw new SemanticException("compile failed.");
}
}
@ -69,7 +69,7 @@ public class LocalReferenceResolver extends Visitor {
while (params.hasNext()) {
Parameter param = (Parameter)params.next();
if (frame.isDefinedLocally(param.name())) {
handler.error("duplicated parameter: " + param.name());
error(param, "duplicated parameter: " + param.name());
}
else {
frame.allocateVariable(param);
@ -121,7 +121,11 @@ public class LocalReferenceResolver extends Visitor {
node.setEntity(ent);
}
catch (SemanticException ex) {
handler.error(ex.getMessage());
error(node, ex.getMessage());
}
}
protected void error(Node node, String message) {
errorHandler.error(node.location(), message);
}
}

View File

@ -42,7 +42,7 @@ class TypeChecker extends Visitor {
protected void checkReturnType(DefinedFunction f) {
if (isInvalidReturnType(f.returnType())) {
errorHandler.error("returns invalid type: " + f.returnType());
error(f, "returns invalid type: " + f.returnType());
return;
}
}
@ -52,7 +52,7 @@ class TypeChecker extends Visitor {
while (params.hasNext()) {
Parameter param = (Parameter)params.next();
if (isInvalidParameterType(param.type())) {
errorHandler.error("invalid parameter type: " + param.type());
error(param, "invalid parameter type: " + param.type());
}
}
}
@ -77,13 +77,13 @@ class TypeChecker extends Visitor {
protected void checkVariable(DefinedVariable var) {
if (isInvalidVariableType(var.type())) {
errorHandler.error("invalid variable type");
error(var, "invalid variable type");
return;
}
if (var.hasInitializer()) {
try {
if (isInvalidLHSType(var.type())) {
errorHandler.error("invalid LHS type: " + var.type());
error(var, "invalid LHS type: " + var.type());
return;
}
check(var.initializer());
@ -118,7 +118,7 @@ class TypeChecker extends Visitor {
protected void checkCondExpr(ExprNode cond) {
Type t = cond.type();
if (!t.isInteger() && !t.isPointer()) {
notIntegerError(t);
notIntegerError(cond, t);
return;
}
}
@ -132,12 +132,12 @@ class TypeChecker extends Visitor {
super.visit(node);
if (node.function().isVoid()) {
if (node.expr() != null) {
errorHandler.error("returning value from void function");
error(node, "returning value from void function");
}
}
else { // non-void function
if (node.expr() == null) {
errorHandler.error("missing return value");
error(node, "missing return value");
return;
}
insertImplicitCast(node);
@ -154,7 +154,7 @@ class TypeChecker extends Visitor {
node.setExpr(newCastNode(retType, node.expr()));
}
else {
errorHandler.error("returning incompatible value: " + exprType);
error(node, "returning incompatible value: " + exprType);
}
}
@ -210,11 +210,11 @@ class TypeChecker extends Visitor {
check(node.lhs());
check(node.rhs());
if (! node.lhs().isAssignable()) {
errorHandler.error("invalid lhs expression");
error(node, "invalid lhs expression");
return;
}
if (isInvalidLHSType(node.lhs().type())) {
errorHandler.error("invalid lhs type");
error(node, "invalid lhs type");
return;
}
node.setRHS(checkRHSType(node.rhs(), node.lhs().type()));
@ -223,7 +223,7 @@ class TypeChecker extends Visitor {
protected ExprNode checkRHSType(ExprNode rhs, Type l) {
Type r = rhs.type();
if (isInvalidRHSType(r)) {
errorHandler.error("invalid rhs type: " + r);
error(rhs, "invalid rhs type: " + r);
return rhs;
}
if (l.isSameType(r)) {
@ -231,12 +231,12 @@ class TypeChecker extends Visitor {
}
else if (r.isCastableTo(l)) { // insert cast on RHS
if (! r.isCompatible(l)) {
errorHandler.warn("implicit cast from " + r + " to " + l);
warn(rhs, "implicit cast from " + r + " to " + l);
}
return newCastNode(l, rhs);
}
else {
incompatibleTypeError(l, r);
incompatibleTypeError(rhs, l, r);
return rhs;
}
}
@ -281,7 +281,7 @@ class TypeChecker extends Visitor {
node.setElseExpr(newCastNode(t, node.elseExpr()));
}
else {
incompatibleTypeError(e, t);
incompatibleTypeError(node.thenExpr(), e, t);
}
}
@ -435,7 +435,7 @@ class TypeChecker extends Visitor {
node.setLeft(newCastNode(r.type(), l));
}
else {
incompatibleTypeError(l.type(), r.type());
incompatibleTypeError(node, l.type(), r.type());
}
}
@ -476,12 +476,12 @@ class TypeChecker extends Visitor {
public void visit(FuncallNode node) {
check(node.expr());
if (! node.expr().isCallable()) {
errorHandler.error("calling object is not a function");
error(node, "calling object is not a function");
return;
}
FunctionType type = node.functionType();
if (! type.acceptsArgc(node.numArgs())) {
errorHandler.error("wrong number of argments: " + node.numArgs());
error(node, "wrong number of argments: " + node.numArgs());
return;
}
// Check type of only mandatory parameters.
@ -509,7 +509,7 @@ class TypeChecker extends Visitor {
public void visit(ArefNode node) {
check(node.expr());
if (! node.expr().isDereferable()) {
errorHandler.error("is not indexable: " + node.expr().type());
error(node, "is not indexable: " + node.expr().type());
return;
}
check(node.index());
@ -518,27 +518,26 @@ class TypeChecker extends Visitor {
public void visit(MemberNode node) {
check(node.expr());
checkMemberRef(node.expr().type(), node.name());
checkMemberRef(node, node.expr().type(), node.name());
}
public void visit(PtrMemberNode node) {
check(node.expr());
if (! node.expr().isDereferable()) {
undereferableError(node.expr().type());
undereferableError(node, node.expr().type());
return;
}
checkMemberRef(node.dereferedType(), node.name());
checkMemberRef(node, node.dereferedType(), node.name());
}
protected void checkMemberRef(Type t, String memb) {
protected void checkMemberRef(Node node, Type t, String memb) {
if (! t.isComplexType()) {
errorHandler.error("is not struct/union: " + t);
error(node, "is not struct/union: " + t);
return;
}
ComplexType type = t.getComplexType();
if (! type.hasMember(memb)) {
errorHandler.error(type.toString()
+ " does not have member " + memb);
error(node, type.toString() + " does not have member " + memb);
return;
}
}
@ -546,7 +545,7 @@ class TypeChecker extends Visitor {
public void visit(DereferenceNode node) {
super.visit(node);
if (! node.expr().isDereferable()) {
undereferableError(node.expr().type());
undereferableError(node, node.expr().type());
return;
}
}
@ -556,14 +555,14 @@ class TypeChecker extends Visitor {
Type t = typeTable.pointerTo(node.expr().type());
node.setType(t);
if (! node.expr().isAssignable()) {
errorHandler.error("invalid LHS expression for &");
error(node, "invalid LHS expression for &");
}
}
public void visit(CastNode node) {
check(node.expr());
if (! node.expr().type().isCastableTo(node.type())) {
incompatibleTypeError(node.expr().type(), node.type());
incompatibleTypeError(node, node.expr().type(), node.type());
}
}
@ -577,24 +576,32 @@ class TypeChecker extends Visitor {
protected void mustBeInteger(ExprNode node) {
if (node.type().isInteger()) return;
notIntegerError(node.type());
notIntegerError(node, node.type());
}
protected void mustBeScalar(ExprNode node) {
if (node.type().isInteger()) return;
if (node.type().isPointer()) return;
notIntegerError(node.type());
notIntegerError(node, node.type());
}
protected void incompatibleTypeError(Type l, Type r) {
errorHandler.error("incompatible type: " + l + " and " + r);
protected void incompatibleTypeError(Node n, Type l, Type r) {
error(n, "incompatible type: " + l + " and " + r);
}
protected void notIntegerError(Type type) {
errorHandler.error("non-integer argument for unary op: " + type);
protected void notIntegerError(Node n, Type type) {
error(n, "non-integer argument for unary op: " + type);
}
protected void undereferableError(Type type) {
errorHandler.error("dereferencing non-pointer expression: " + type);
protected void undereferableError(Node n, Type type) {
error(n, "dereferencing non-pointer expression: " + type);
}
protected void warn(Node n, String msg) {
errorHandler.warn(n.location(), msg);
}
protected void error(Node n, String msg) {
errorHandler.error(n.location(), msg);
}
}

View File

@ -22,7 +22,6 @@ public class TypeResolver extends Visitor {
resolveDeclarations(ast.types());
resolveDeclarations(ast.declarations());
resolveDeclarations(ast.entities());
typeTable.semanticCheck(errorHandler);
}
private void defineTypes(Iterator deftypes) {
@ -64,6 +63,7 @@ public class TypeResolver extends Visitor {
public void visit(TypedefNode typedef) {
bindType(typedef.typeNode());
bindType(typedef.realTypeNode());
}
public void visit(VariableNode n) {

View File

@ -1,30 +1,25 @@
package net.loveruby.cflat.type;
import net.loveruby.cflat.ast.Slot;
import net.loveruby.cflat.type.*;
import net.loveruby.cflat.ast.Location;
import net.loveruby.cflat.exception.*;
import java.util.*;
abstract public class ComplexType extends Type {
protected String name;
abstract public class ComplexType extends NamedType {
protected List members; // List<Slot>
protected long size;
protected boolean isRecursiveChecked;
public ComplexType(String n, List membs) {
name = n;
members = membs;
size = Type.sizeUnknown;
isRecursiveChecked = false;
public ComplexType(String name, List membs, Location loc) {
super(name, loc);
this.members = membs;
this.size = Type.sizeUnknown;
this.isRecursiveChecked = false;
}
public boolean isComplexType() {
return true;
}
public String name() {
return name;
}
public long size() {
if (size == Type.sizeUnknown) {
computeOffsets();
@ -78,12 +73,4 @@ abstract public class ComplexType extends Type {
}
return null;
}
public boolean isRecursiveChecked() {
return isRecursiveChecked;
}
public void recursiveChecked() {
isRecursiveChecked = true;
}
}

View File

@ -0,0 +1,22 @@
package net.loveruby.cflat.type;
import net.loveruby.cflat.ast.Location;
import net.loveruby.cflat.exception.*;
import java.util.*;
abstract public class NamedType extends Type {
protected String name;
protected Location location;
public NamedType(String name, Location loc) {
this.name = name;
this.location = loc;
}
public String name() {
return name;
}
public Location location() {
return location;
}
}

View File

@ -1,10 +1,11 @@
package net.loveruby.cflat.type;
import net.loveruby.cflat.ast.Slot;
import net.loveruby.cflat.ast.Location;
import java.util.*;
public class StructType extends ComplexType {
public StructType(String name, List membs) {
super(name, membs);
public StructType(String name, List membs, Location loc) {
super(name, membs, loc);
}
public boolean isStruct() { return true; }

View File

@ -121,16 +121,25 @@ public class TypeTable {
t.defineIn(this);
}
public void defineStruct(StructTypeRef ref, List membs) {
table.put(ref, new StructType(ref.name(), membs));
public void defineStruct(StructNode node) {
Type type = new StructType(node.name(),
node.members(),
node.location());
table.put(node.typeRef(), type);
}
public void defineUnion(UnionTypeRef ref, List membs) {
table.put(ref, new UnionType(ref.name(), membs));
public void defineUnion(UnionNode node) {
Type type = new UnionType(node.name(),
node.members(),
node.location());
table.put(node.typeRef(), type);
}
public void defineUserType(UserTypeRef ref, TypeNode real) {
table.put(ref, new UserType(ref.name(), real));
public void defineUserType(TypedefNode node) {
Type type = new UserType(node.name(),
node.realTypeNode(),
node.location());
table.put(node.typeRef(), type);
}
public PointerType pointerTo(Type baseType) {
@ -150,6 +159,7 @@ public class TypeTable {
checkRecursiveDefinition((ComplexType)t, h);
}
else if (t instanceof ArrayType) {
// FIXME: check on the fly
checkVoidMembers((ArrayType)t, h);
}
else if (t instanceof UserType) {
@ -169,7 +179,7 @@ public class TypeTable {
while (membs.hasNext()) {
Slot memb = (Slot)membs.next();
if (memb.type().isVoid()) {
h.error("struct/union cannot contain void");
h.error(t.location(), "struct/union cannot contain void");
}
}
}
@ -180,7 +190,8 @@ public class TypeTable {
while (membs.hasNext()) {
Slot memb = (Slot)membs.next();
if (seen.containsKey(memb.name())) {
h.error(t.toString() + " has duplicated member: "
h.error(t.location(),
t.toString() + " has duplicated member: "
+ memb.name());
}
seen.put(memb.name(), memb);
@ -197,7 +208,8 @@ public class TypeTable {
protected void _checkRecursiveDefinition(Type t, Map seen,
ErrorHandler h) {
if (seen.get(t) == checking) {
h.error("recursive type definition: " + t);
h.error(((NamedType)t).location(),
"recursive type definition: " + t);
return;
}
else if (seen.get(t) == checked) {

View File

@ -1,10 +1,11 @@
package net.loveruby.cflat.type;
import net.loveruby.cflat.ast.Slot;
import net.loveruby.cflat.ast.Location;
import java.util.*;
public class UnionType extends ComplexType {
public UnionType(String name, List membs) {
super(name, membs);
public UnionType(String name, List membs, Location loc) {
super(name, membs, loc);
}
public boolean isUnion() { return true; }

View File

@ -1,27 +1,19 @@
package net.loveruby.cflat.type;
import net.loveruby.cflat.ast.TypeNode;
import net.loveruby.cflat.ast.Location;
public class UserType extends Type {
protected String name;
public class UserType extends NamedType {
protected TypeNode real;
public UserType(String name, TypeNode real) {
this.name = name;
public UserType(String name, TypeNode real, Location loc) {
super(name, loc);
this.real = real;
}
public String name() {
return name;
}
public Type realType() {
return real.type();
}
public TypeNode typeNode() {
return real;
}
public String toString() {
return name;
}