mirror of https://github.com/aamine/cbc
* 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:
parent
879738ba62
commit
8bc055ed4e
41
ChangeLog
41
ChangeLog
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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) {
|
||||
|
|
|
|||
|
|
@ -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) {
|
||||
|
|
|
|||
|
|
@ -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) {
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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++;
|
||||
|
|
|
|||
|
|
@ -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());
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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) {
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
@ -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; }
|
||||
|
|
|
|||
|
|
@ -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) {
|
||||
|
|
|
|||
|
|
@ -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; }
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue