* net/loveruby/cflat/compiler/Compiler.java: create TypeTable here.

* net/loveruby/cflat/compiler/CodeGenerator.java: accepts TypeTable and ErrorHandler.
* net/loveruby/cflat/compiler/TypeResolver.java: ditto.
* net/loveruby/cflat/compiler/TypeChecker.java: ditto.
* net/loveruby/cflat/compiler/TypeChecker.java: set type of AddressNode.
* net/loveruby/cflat/compiler/TypeChecker.java: warn incompatible cast.
* net/loveruby/cflat/compiler/ErrorHandler.java: modify message (error -> warning).
* net/loveruby/cflat/parser/Parser.jj: rename variable: handler -> errorHandler.
* net/loveruby/cflat/ast/AST.java: do not contain TypeTable.
* net/loveruby/cflat/ast/ComplexTypeDefinition.java: new method #type.
* net/loveruby/cflat/ast/StructNode.java: ditto.
* net/loveruby/cflat/ast/UnionNode.java: ditto.
* net/loveruby/cflat/ast/AddressNode.java: receive Type from TypeChcker.
* net/loveruby/cflat/type/TypeTable.java: new method #pointerTo.
* net/loveruby/cflat/type/IntegerType.java (isCompatible): check if self is compatible with other side (be able to cast to other implicitly).
* net/loveruby/cflat/type/IntegerType.java (isCastableTo): allow explicit cast if type of type is same (integer/pointer).
* net/loveruby/cflat/type/PointerType.java: implement #equals.


git-svn-id: file:///Users/aamine/c/gitwork/public/cbc/trunk@3763 1b9489fe-b721-0410-924e-b54b9192deb8
This commit is contained in:
Minero Aoki 2008-01-01 14:21:26 +00:00
parent 5fc167d2e5
commit 1e4ac4dabf
15 changed files with 156 additions and 62 deletions

View File

@ -1,3 +1,50 @@
Tue Jan 1 23:21:22 2008 Minero Aoki <aamine@loveruby.net>
* net/loveruby/cflat/compiler/Compiler.java: create TypeTable
here.
* net/loveruby/cflat/compiler/CodeGenerator.java: accepts
TypeTable and ErrorHandler.
* net/loveruby/cflat/compiler/TypeResolver.java: ditto.
* net/loveruby/cflat/compiler/TypeChecker.java: ditto.
* net/loveruby/cflat/compiler/TypeChecker.java: set type of
AddressNode.
* net/loveruby/cflat/compiler/TypeChecker.java: warn incompatible
cast.
* net/loveruby/cflat/compiler/ErrorHandler.java: modify message
(error -> warning).
* net/loveruby/cflat/parser/Parser.jj: rename variable: handler ->
errorHandler.
* net/loveruby/cflat/ast/AST.java: do not contain TypeTable.
* net/loveruby/cflat/ast/ComplexTypeDefinition.java: new method
#type.
* net/loveruby/cflat/ast/StructNode.java: ditto.
* net/loveruby/cflat/ast/UnionNode.java: ditto.
* net/loveruby/cflat/ast/AddressNode.java: receive Type from
TypeChcker.
* net/loveruby/cflat/type/TypeTable.java: new method #pointerTo.
* net/loveruby/cflat/type/IntegerType.java (isCompatible): check
if self is compatible with other side (be able to cast to other
implicitly).
* net/loveruby/cflat/type/IntegerType.java (isCastableTo): allow
explicit cast if type of type is same (integer/pointer).
* net/loveruby/cflat/type/PointerType.java: implement #equals.
Tue Jan 1 21:56:19 2008 Minero Aoki <aamine@loveruby.net>
* net/loveruby/cflat/compiler/Compiler.java: invoke TypeChecker.

View File

@ -1,6 +1,5 @@
package net.loveruby.cflat.ast;
import net.loveruby.cflat.parser.Token;
import net.loveruby.cflat.type.TypeTable;
import java.util.*;
public class AST extends Node {
@ -9,7 +8,6 @@ public class AST extends Node {
protected Token firstToken;
protected ToplevelScope scope;
protected TypeTable typeTable;
protected ConstantTable constantTable;
public AST(String fname, Declarations decls, Token t) {
@ -18,7 +16,6 @@ public class AST extends Node {
declarations = decls;
firstToken = t;
scope = new ToplevelScope();
typeTable = TypeTable.ilp32(); // FIXME: platform dependent
constantTable = new ConstantTable();
}
@ -73,10 +70,6 @@ public class AST extends Node {
return scope;
}
public TypeTable typeTable() {
return typeTable;
}
public ConstantTable constantTable() {
return constantTable;
}

View File

@ -1,10 +1,24 @@
package net.loveruby.cflat.ast;
import net.loveruby.cflat.type.*;
public class AddressNode extends UnaryOpNode {
protected Type type;
public AddressNode(Node n) {
super(n);
}
public Type type() {
if (type == null) throw new Error("type is null");
return type;
}
/** This method is called in TypeChecker. */
public void setType(Type type) {
if (this.type != null) throw new Error("type set twice");
this.type = type;
}
public void accept(ASTVisitor visitor) {
visitor.visit(this);
}

View File

@ -16,6 +16,8 @@ abstract public class ComplexTypeDefinition extends TypeDefinition {
return true;
}
abstract public String type();
public List members() {
return members;
}

View File

@ -7,6 +7,10 @@ public class StructNode extends ComplexTypeDefinition {
super(ref, name, membs);
}
public String type() {
return "struct";
}
public TypeRef typeRef() {
return super.typeRef();
}

View File

@ -7,6 +7,10 @@ public class UnionNode extends ComplexTypeDefinition {
super(ref, name, membs);
}
public String type() {
return "union";
}
public TypeRef typeRef() {
return (UnionTypeRef)super.typeRef();
}

View File

@ -5,22 +5,26 @@ import net.loveruby.cflat.asm.*;
import java.util.*;
public class CodeGenerator implements ASTVisitor {
static public String generate(AST ast) {
return new CodeGenerator(new Assembler()).generateAssembly(ast);
static public String generate(AST ast, TypeTable typeTable,
ErrorHandler errorHandler) {
CodeGenerator gen = new CodeGenerator(new Assembler(), errorHandler);
return gen.generateAssembly(ast, typeTable);
}
protected Assembler as;
protected DefinedFunction currentFunction;
protected TypeTable typeTable;
protected ErrorHandler errorHandler;
public CodeGenerator(Assembler as) {
public CodeGenerator(Assembler as, ErrorHandler errorHandler) {
this.as = as;
this.errorHandler = errorHandler;
}
static public void p(String s) { System.err.println(s); }
/** Compiles "ast" and generates assembly code. */
public String generateAssembly(AST ast) {
typeTable = ast.typeTable();
public String generateAssembly(AST ast, TypeTable typeTable) {
typeTable = typeTable;
allocateGlobalVariables(ast.globalVariables());
allocateCommonSymbols(ast.commonSymbols());

View File

@ -1,6 +1,7 @@
package net.loveruby.cflat.compiler;
import net.loveruby.cflat.parser.*;
import net.loveruby.cflat.ast.*;
import net.loveruby.cflat.type.*;
import net.loveruby.cflat.exception.*;
import java.util.*;
import java.io.*;
@ -11,17 +12,20 @@ public class Compiler {
}
static final private String programId = "cbc";
protected TypeTable typeTable;
protected LibraryLoader loader;
protected ErrorHandler handler;
protected ErrorHandler errorHandler;
public Compiler() {
typeTable = TypeTable.ilp32();
loader = new LibraryLoader();
handler = new ErrorHandler(programId);
errorHandler = new ErrorHandler(programId);
}
public Compiler(LibraryLoader ld, ErrorHandler h) {
public Compiler(TypeTable table, LibraryLoader ld, ErrorHandler h) {
typeTable = table;
loader = ld;
handler = h;
errorHandler = h;
}
public void commandMain(String[] args) {
@ -54,7 +58,7 @@ public class Compiler {
}
private void errorExit(String msg) {
handler.error(msg);
errorHandler.error(msg);
System.exit(1);
}
@ -73,18 +77,19 @@ public class Compiler {
}
public void compileFile(String path) throws CompileException {
TypeTable typeTable = TypeTable.ilp32();
AST ast = parseFile(path);
JumpResolver.resolve(ast, handler);
LocalReferenceResolver.resolve(ast, handler);
TypeResolver.resolve(ast);
TypeChecker.check(ast, handler);
String asm = CodeGenerator.generate(ast);
JumpResolver.resolve(ast, errorHandler);
LocalReferenceResolver.resolve(ast, errorHandler);
TypeResolver.resolve(ast, typeTable, errorHandler);
TypeChecker.check(ast, typeTable, errorHandler);
String asm = CodeGenerator.generate(ast, typeTable, errorHandler);
writeFile(asmFileName(path), asm);
assemble(asmFileName(path));
}
public AST parseFile(String path) throws CompileException {
return Parser.parseFile(new File(path), loader, handler);
return Parser.parseFile(new File(path), loader, errorHandler);
}
public void assemble(String path) throws IPCException {
@ -97,17 +102,17 @@ public class Compiler {
Process proc = Runtime.getRuntime().exec(cmd);
proc.waitFor();
if (proc.exitValue() != 0) {
handler.error("gcc failed (assemble); status " +
errorHandler.error("gcc failed (assemble); status " +
proc.exitValue());
throw new IPCException("compile error");
}
}
catch (InterruptedException ex) {
handler.error("gcc interrupted: " + ex.getMessage());
errorHandler.error("gcc interrupted: " + ex.getMessage());
throw new IPCException("compile error");
}
catch (IOException ex) {
handler.error(ex.getMessage());
errorHandler.error(ex.getMessage());
throw new IPCException("compile error");
}
}
@ -125,11 +130,11 @@ public class Compiler {
}
}
catch (FileNotFoundException ex) {
handler.error("file not found: " + path);
errorHandler.error("file not found: " + path);
throw new FileException("file error");
}
catch (IOException ex) {
handler.error("IO error" + ex.getMessage());
errorHandler.error("IO error" + ex.getMessage());
throw new FileException("file error");
}
}

View File

@ -23,7 +23,7 @@ public class ErrorHandler {
}
public void warn(String msg) {
stream.println(programId + ": error: " + msg);
stream.println(programId + ": warning: " + msg);
nWarning++;
}

View File

@ -5,14 +5,16 @@ import net.loveruby.cflat.exception.*;
import java.util.*;
class TypeChecker extends Visitor {
static public void check(AST ast, ErrorHandler handler)
throws SemanticException {
new TypeChecker(handler).visit(ast);
static public void check(AST ast, TypeTable typeTable,
ErrorHandler handler) throws SemanticException {
new TypeChecker(typeTable, handler).visit(ast);
}
protected TypeTable typeTable;
protected ErrorHandler handler;
public TypeChecker(ErrorHandler handler) {
public TypeChecker(TypeTable typeTable, ErrorHandler handler) {
this.typeTable = typeTable;
this.handler = handler;
}
@ -272,6 +274,7 @@ class TypeChecker extends Visitor {
super.visit(node);
// FIXME: check types
// FIXME: check if callable
// FIXME: check argument types
}
public void visit(ArefNode node) {
@ -297,6 +300,8 @@ class TypeChecker extends Visitor {
public void visit(AddressNode node) {
super.visit(node);
Type t = typeTable.pointerTo(node.expr().type());
node.setType(t);
// FIXME: what is "assignable"??
}
@ -305,6 +310,11 @@ class TypeChecker extends Visitor {
if (! node.expr().type().isCastableTo(node.type())) {
incompatibleTypeError(node.expr().type(), node.type());
}
else if (! node.expr().type().isCompatible(node.type())) {
handler.warn("incompatible cast from " +
node.expr().type().textize() +
" to " + node.type().textize());
}
}
//

View File

@ -4,15 +4,20 @@ import net.loveruby.cflat.type.*;
import java.util.*;
public class TypeResolver extends Visitor implements DefinitionVisitor {
static public void resolve(AST ast) {
new TypeResolver().resolveProgram(ast);
static public void resolve(AST ast, TypeTable typeTable,
ErrorHandler errorHandler) {
new TypeResolver(typeTable, errorHandler).resolveProgram(ast);
}
protected TypeTable typeTable;
protected ErrorHandler errorHandler;
public TypeResolver(TypeTable typeTable, ErrorHandler errorHandler) {
this.typeTable = typeTable;
this.errorHandler = errorHandler;
}
public void resolveProgram(AST ast) {
typeTable = ast.typeTable();
//importLibraries(ast.importLibraryNames());
defineTypes(ast.types());
resolveDeclarations(ast.types());
resolveDeclarations(ast.declarations());
@ -48,7 +53,7 @@ public class TypeResolver extends Visitor implements DefinitionVisitor {
public void resolveComplexType(ComplexTypeDefinition def) {
ComplexType ct = (ComplexType)typeTable.get(def.typeNode().typeRef());
if (ct == null) {
throw new Error("FATAL: cannot intern Struct/Union");
throw new Error("cannot intern struct/union: " + def.name());
}
Iterator membs = ct.members();
while (membs.hasNext()) {

View File

@ -15,24 +15,21 @@ import java.util.*;
import java.io.*;
public class Parser {
static public AST parseFile(File file,
LibraryLoader loader, ErrorHandler handler)
throws CompileException {
return newFileParser(file, loader, handler).parse();
static public AST parseFile(File file, LibraryLoader loader,
ErrorHandler errorHandler) throws CompileException {
return newFileParser(file, loader, errorHandler).parse();
}
static public Declarations parseDeclFile(File file,
LibraryLoader loader, ErrorHandler handler)
throws CompileException {
return newFileParser(file, loader, handler).parseDecls();
static public Declarations parseDeclFile(File file, LibraryLoader loader,
ErrorHandler errorHandler) throws CompileException {
return newFileParser(file, loader, errorHandler).parseDecls();
}
static public Parser newFileParser(File file,
LibraryLoader loader, ErrorHandler handler)
throws FileException {
static public Parser newFileParser(File file, LibraryLoader loader,
ErrorHandler errorHandler) throws FileException {
try {
return new Parser(newReader(new FileInputStream(file)),
file.getPath(), loader, handler);
file.getPath(), loader, errorHandler);
}
catch (FileNotFoundException ex) {
throw new FileException(ex.getMessage());
@ -54,14 +51,14 @@ public class Parser {
protected LabelPool labelPool;
protected Set knownTypedefs;
protected LibraryLoader loader;
protected ErrorHandler handler;
protected ErrorHandler errorHandler;
public Parser(Reader s, String name,
LibraryLoader loader, ErrorHandler handler) {
LibraryLoader loader, ErrorHandler errorHandler) {
this(s);
this.sourceName = name;
this.loader = loader;
this.handler = handler;
this.errorHandler = errorHandler;
this.labelPool = new LabelPool();
this.knownTypedefs = new HashSet();
}
@ -71,11 +68,11 @@ public class Parser {
return compilation_unit();
}
catch (TokenMgrError err) {
handler.error(err.getMessage());
errorHandler.error(err.getMessage());
throw new SyntaxException(err.getMessage());
}
catch (ParseException ex) {
handler.error(ex.getMessage());
errorHandler.error(ex.getMessage());
throw new SyntaxException(ex.getMessage());
}
}
@ -85,11 +82,11 @@ public class Parser {
return declaration_file();
}
catch (TokenMgrError ex) {
handler.error(ex.getMessage());
errorHandler.error(ex.getMessage());
throw new SyntaxException(ex.getMessage());
}
catch (ParseException ex) {
handler.error(ex.getMessage());
errorHandler.error(ex.getMessage());
throw new SyntaxException(ex.getMessage());
}
}
@ -332,7 +329,7 @@ Declarations import_stmts():
(libid=import_stmt()
{
try {
Declarations decls = loader.loadLibrary(libid, handler);
Declarations decls = loader.loadLibrary(libid, errorHandler);
if (decls != null) {
impdecls.add(decls);
Iterator types = decls.typedefs().iterator();
@ -343,7 +340,7 @@ Declarations import_stmts():
}
}
catch (CompileException ex) {
handler.error(ex.getMessage());
errorHandler.error(ex.getMessage());
throw new ParseException("compile error");
}
}

View File

@ -32,11 +32,10 @@ public class IntegerType extends Type {
}
public boolean isCompatible(Type other) {
return (other.isInteger() && other.size() <= size);
return (other.isInteger() && size <= other.size());
}
public boolean isCastableTo(Type target) {
return (target.isInteger() && target.size() >= size)
|| (target.isPointer() && target.size() >= size);
return (target.isInteger() || target.isPointer());
}
}

View File

@ -39,6 +39,12 @@ public class PointerType extends Type {
//public boolean isArray() { return true; }
public boolean equals(Object other) {
if (! (other instanceof PointerType)) return false;
PointerType otherptr = (PointerType)other;
return this.base.equals(otherptr.base());
}
public String textize() {
return base.textize() + "*";
}

View File

@ -130,6 +130,10 @@ public class TypeTable {
table.put(ref, new UserType(ref.name(), real));
}
public PointerType pointerTo(Type base) {
return new PointerType(pointerSize, base);
}
public void semanticCheck() {
Iterator types = table.values().iterator();
while (types.hasNext()) {