diff --git a/ChangeLog b/ChangeLog index 833a4b6..de67508 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,44 @@ +Sat Jan 5 12:23:25 2008 Minero Aoki + + * 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 * net/loveruby/cflat/ast/Node.java: all nodes must contain diff --git a/net/loveruby/cflat/ast/DefinedFunction.java b/net/loveruby/cflat/ast/DefinedFunction.java index ec40d82..e07ab4c 100644 --- a/net/loveruby/cflat/ast/DefinedFunction.java +++ b/net/loveruby/cflat/ast/DefinedFunction.java @@ -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); } } } diff --git a/net/loveruby/cflat/ast/Scope.java b/net/loveruby/cflat/ast/Scope.java index 03a34bd..15ba4e4 100644 --- a/net/loveruby/cflat/ast/Scope.java +++ b/net/loveruby/cflat/ast/Scope.java @@ -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); } } } diff --git a/net/loveruby/cflat/ast/StructNode.java b/net/loveruby/cflat/ast/StructNode.java index 9f1406b..57f0d2e 100644 --- a/net/loveruby/cflat/ast/StructNode.java +++ b/net/loveruby/cflat/ast/StructNode.java @@ -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) { diff --git a/net/loveruby/cflat/ast/TypedefNode.java b/net/loveruby/cflat/ast/TypedefNode.java index 5ffe955..daefed3 100644 --- a/net/loveruby/cflat/ast/TypedefNode.java +++ b/net/loveruby/cflat/ast/TypedefNode.java @@ -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) { diff --git a/net/loveruby/cflat/ast/UnionNode.java b/net/loveruby/cflat/ast/UnionNode.java index 42fe006..9a0a51e 100644 --- a/net/loveruby/cflat/ast/UnionNode.java +++ b/net/loveruby/cflat/ast/UnionNode.java @@ -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) { diff --git a/net/loveruby/cflat/compiler/Compiler.java b/net/loveruby/cflat/compiler/Compiler.java index bcc0e23..988929c 100644 --- a/net/loveruby/cflat/compiler/Compiler.java +++ b/net/loveruby/cflat/compiler/Compiler.java @@ -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); } diff --git a/net/loveruby/cflat/compiler/ErrorHandler.java b/net/loveruby/cflat/compiler/ErrorHandler.java index 8d2e240..e25c2df 100644 --- a/net/loveruby/cflat/compiler/ErrorHandler.java +++ b/net/loveruby/cflat/compiler/ErrorHandler.java @@ -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++; diff --git a/net/loveruby/cflat/compiler/JumpResolver.java b/net/loveruby/cflat/compiler/JumpResolver.java index df7307a..b105601 100644 --- a/net/loveruby/cflat/compiler/JumpResolver.java +++ b/net/loveruby/cflat/compiler/JumpResolver.java @@ -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()); } } diff --git a/net/loveruby/cflat/compiler/LocalReferenceResolver.java b/net/loveruby/cflat/compiler/LocalReferenceResolver.java index 4a69f5f..6f2b39f 100644 --- a/net/loveruby/cflat/compiler/LocalReferenceResolver.java +++ b/net/loveruby/cflat/compiler/LocalReferenceResolver.java @@ -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); + } } diff --git a/net/loveruby/cflat/compiler/TypeChecker.java b/net/loveruby/cflat/compiler/TypeChecker.java index f3d1677..8beb98c 100644 --- a/net/loveruby/cflat/compiler/TypeChecker.java +++ b/net/loveruby/cflat/compiler/TypeChecker.java @@ -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); } } diff --git a/net/loveruby/cflat/compiler/TypeResolver.java b/net/loveruby/cflat/compiler/TypeResolver.java index 5a2d43a..fd50069 100644 --- a/net/loveruby/cflat/compiler/TypeResolver.java +++ b/net/loveruby/cflat/compiler/TypeResolver.java @@ -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) { diff --git a/net/loveruby/cflat/type/ComplexType.java b/net/loveruby/cflat/type/ComplexType.java index 69ab09f..4584540 100644 --- a/net/loveruby/cflat/type/ComplexType.java +++ b/net/loveruby/cflat/type/ComplexType.java @@ -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 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; - } } diff --git a/net/loveruby/cflat/type/NamedType.java b/net/loveruby/cflat/type/NamedType.java new file mode 100644 index 0000000..44a315e --- /dev/null +++ b/net/loveruby/cflat/type/NamedType.java @@ -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; + } +} diff --git a/net/loveruby/cflat/type/StructType.java b/net/loveruby/cflat/type/StructType.java index 952b98e..f255cf6 100644 --- a/net/loveruby/cflat/type/StructType.java +++ b/net/loveruby/cflat/type/StructType.java @@ -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; } diff --git a/net/loveruby/cflat/type/TypeTable.java b/net/loveruby/cflat/type/TypeTable.java index e52fc04..2e5d3a6 100644 --- a/net/loveruby/cflat/type/TypeTable.java +++ b/net/loveruby/cflat/type/TypeTable.java @@ -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) { diff --git a/net/loveruby/cflat/type/UnionType.java b/net/loveruby/cflat/type/UnionType.java index b80fab7..5b50ce7 100644 --- a/net/loveruby/cflat/type/UnionType.java +++ b/net/loveruby/cflat/type/UnionType.java @@ -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; } diff --git a/net/loveruby/cflat/type/UserType.java b/net/loveruby/cflat/type/UserType.java index e0aa389..20f29f1 100644 --- a/net/loveruby/cflat/type/UserType.java +++ b/net/loveruby/cflat/type/UserType.java @@ -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; }