r4865@macbookpro: aamine | 2009-05-18 03:02:28 +0900

* net/loveruby/cflat/parser/Parser.jj: change function pointer syntax: int(*)(int,int) -> int(int,int)*.  Function type is int(int,int).
 * net/loveruby/cflat/parser/Parser.jj: function returns function type, not pointer to function.
 * net/loveruby/cflat/compiler/TypeResolver.java: resolve all function headers first, then resolve bodies.
 * net/loveruby/cflat/compiler/TypeResolver.java: generate a pointer for array-type expression.
 * net/loveruby/cflat/compiler/TypeResolver.java: isDereferable -> isPointer.
 * net/loveruby/cflat/compiler/TypeChecker.java: ditto.
 * net/loveruby/cflat/compiler/DereferenceChecker.java: ditto.
 * net/loveruby/cflat/compiler/IRGenerator.java: ditto.
 * net/loveruby/cflat/compiler/IRGenerator.java: shouldEvaluatedToAddress -> isLoadable (check arrays and functions, not only arrays).
 * net/loveruby/cflat/type/Type.java: remove #isDereferable.
 * net/loveruby/cflat/type/UserType.java: ditto.
 * net/loveruby/cflat/type/ArrayType.java: is not a scalar.
 * net/loveruby/cflat/type/ArrayType.java: is not dereferable itself.
 * net/loveruby/cflat/type/PointerType.java: is incompatible with arrays.
 * net/loveruby/cflat/type/IntegerType.java: ditto.
 * net/loveruby/cflat/type/FunctionType.java: is callable.
 * net/loveruby/cflat/type/ParamTypeRefs.java: x[] -> x* for param types.
 * net/loveruby/cflat/type/TypeTable.java: new method #getParamType.
 * net/loveruby/cflat/ast/ExprNode.java: new method #isLvalue.
 * net/loveruby/cflat/ast/ExprNode.java: new method #isAssignable.
 * net/loveruby/cflat/ast/ExprNode.java: new method #isLoadable.
 * net/loveruby/cflat/ast/CastNode.java: delegate them.
 * net/loveruby/cflat/ast/LHSNode.java: new super class of LHS nodes.
 * net/loveruby/cflat/ast/VariableNode.java: ditto.
 * net/loveruby/cflat/ast/DereferenceNode.java: ditto.
 * net/loveruby/cflat/ast/ArefNode.java: ditto.
 * net/loveruby/cflat/ast/MemberNode.java: ditto.
 * net/loveruby/cflat/ast/PtrMemberNode.java: ditto.
 * net/loveruby/cflat/entity/Entity.java: remove #cannotLoad.
 * net/loveruby/cflat/entity/Function.java: ditto.
 * net/loveruby/cflat/entity/Variable.java: ditto.
 * net/loveruby/cflat/entity/Constant.java: ditto.
 * net/loveruby/cflat/ir/Addr.java: is not LHS node now.
 


git-svn-id: file:///Users/aamine/c/gitwork/public/cbc/trunk@4220 1b9489fe-b721-0410-924e-b54b9192deb8
This commit is contained in:
Minero Aoki 2009-05-17 18:35:02 +00:00
parent ced081c9c3
commit 3b29c039bd
35 changed files with 339 additions and 236 deletions

View File

@ -1,3 +1,84 @@
Mon May 18 03:01:22 2009 Minero Aoki <aamine@loveruby.net>
* net/loveruby/cflat/parser/Parser.jj: change function pointer
syntax: int(*)(int,int) -> int(int,int)*. Function type is
int(int,int).
* net/loveruby/cflat/parser/Parser.jj: function returns function
type, not pointer to function.
* net/loveruby/cflat/compiler/TypeResolver.java: resolve all
function headers first, then resolve bodies.
* net/loveruby/cflat/compiler/TypeResolver.java: generate a
pointer for array-type expression.
* net/loveruby/cflat/compiler/TypeResolver.java: isDereferable ->
isPointer.
* net/loveruby/cflat/compiler/TypeChecker.java: ditto.
* net/loveruby/cflat/compiler/DereferenceChecker.java: ditto.
* net/loveruby/cflat/compiler/IRGenerator.java: ditto.
* net/loveruby/cflat/compiler/IRGenerator.java:
shouldEvaluatedToAddress -> isLoadable (check arrays and
functions, not only arrays).
* net/loveruby/cflat/type/Type.java: remove #isDereferable.
* net/loveruby/cflat/type/UserType.java: ditto.
* net/loveruby/cflat/type/ArrayType.java: is not a scalar.
* net/loveruby/cflat/type/ArrayType.java: is not dereferable
itself.
* net/loveruby/cflat/type/PointerType.java: is incompatible with
arrays.
* net/loveruby/cflat/type/IntegerType.java: ditto.
* net/loveruby/cflat/type/FunctionType.java: is callable.
* net/loveruby/cflat/type/ParamTypeRefs.java: x[] -> x* for param
types.
* net/loveruby/cflat/type/TypeTable.java: new method
#getParamType.
* net/loveruby/cflat/ast/ExprNode.java: new method #isLvalue.
* net/loveruby/cflat/ast/ExprNode.java: new method #isAssignable.
* net/loveruby/cflat/ast/ExprNode.java: new method #isLoadable.
* net/loveruby/cflat/ast/CastNode.java: delegate them.
* net/loveruby/cflat/ast/LHSNode.java: new super class of LHS
nodes.
* net/loveruby/cflat/ast/VariableNode.java: ditto.
* net/loveruby/cflat/ast/DereferenceNode.java: ditto.
* net/loveruby/cflat/ast/ArefNode.java: ditto.
* net/loveruby/cflat/ast/MemberNode.java: ditto.
* net/loveruby/cflat/ast/PtrMemberNode.java: ditto.
* net/loveruby/cflat/entity/Entity.java: remove #cannotLoad.
* net/loveruby/cflat/entity/Function.java: ditto.
* net/loveruby/cflat/entity/Variable.java: ditto.
* net/loveruby/cflat/entity/Constant.java: ditto.
* net/loveruby/cflat/ir/Addr.java: is not LHS node now.
Sun May 17 16:37:26 2009 Minero Aoki <aamine@loveruby.net>
* import/dlfcn.hb: new declaration file dlfcn.hb.

View File

@ -1,35 +1,22 @@
package net.loveruby.cflat.ast;
import net.loveruby.cflat.type.*;
public class ArefNode extends ExprNode {
protected ExprNode expr, index;
public class ArefNode extends LHSNode {
private ExprNode expr, index;
public ArefNode(ExprNode expr, ExprNode index) {
this.expr = expr;
this.index = index;
}
public Type type() {
return expr.type().baseType();
}
public ExprNode expr() {
return expr;
}
public ExprNode index() {
return index;
}
public boolean isAssignable() {
return true;
}
public ExprNode expr() { return expr; }
public ExprNode index() { return index; }
// isMultiDimension a[x][y][z] = true.
// isMultiDimension a[x][y] = true.
// isMultiDimension a[x] = false.
public boolean isMultiDimension() {
return (expr instanceof ArefNode) && !expr.type().isPointer();
return (expr instanceof ArefNode) && !expr.origType().isPointer();
}
// Returns base expression of (multi-dimension) array.
@ -40,17 +27,19 @@ public class ArefNode extends ExprNode {
// element size of this (multi-dimension) array
public long elementSize() {
return type().allocSize();
return origType().allocSize();
}
public long length() {
return ((ArrayType)expr.type()).length();
return ((ArrayType)expr.origType()).length();
}
public boolean isConstantAddress() {
return false;
protected Type origType() {
return expr.origType().baseType();
}
public boolean isConstantAddress() { return false; }
public Location location() {
return expr.location();
}

View File

@ -26,9 +26,8 @@ public class CastNode extends ExprNode {
return expr;
}
public boolean shouldEvaluatedToAddress() {
return expr.shouldEvaluatedToAddress();
}
public boolean isLvalue() { return expr.isLvalue(); }
public boolean isAssignable() { return expr.isAssignable(); }
public boolean isEffectiveCast() {
return type().size() > expr.type().size();

View File

@ -1,18 +1,35 @@
package net.loveruby.cflat.ast;
import net.loveruby.cflat.type.*;
public class DereferenceNode extends UnaryOpNode {
public DereferenceNode(ExprNode n) {
super("*", n);
public class DereferenceNode extends LHSNode {
private ExprNode expr;
public DereferenceNode(ExprNode expr) {
this.expr = expr;
}
public Type type() {
return expr().type().baseType();
protected Type origType() {
return expr.type().baseType();
}
public ExprNode expr() {
return expr;
}
public void setExpr(ExprNode expr) {
this.expr = expr;
}
public boolean isAssignable() { return true; }
public boolean isConstantAddress() { return false; }
public Location location() {
return expr.location();
}
protected void _dump(Dumper d) {
d.printMember("expr", expr);
}
public <S,E> E accept(ASTVisitor<S,E> visitor) {
return visitor.visit(this);
}

View File

@ -8,10 +8,16 @@ abstract public class ExprNode extends Node {
}
abstract public Type type();
protected Type origType() { return type(); }
public boolean isConstant() {
return false;
}
public long allocSize() { return type().allocSize(); }
public boolean isConstant() { return false; }
public boolean isParameter() { return false; }
public boolean isLvalue() { return false; }
public boolean isAssignable() { return false; }
public boolean isLoadable() { return false; }
public boolean isCallable() {
try {
@ -22,10 +28,10 @@ abstract public class ExprNode extends Node {
}
}
// #@@range/isDereferable{
public boolean isDereferable() {
// #@@range/isPointer{
public boolean isPointer() {
try {
return type().isDereferable();
return type().isPointer();
}
catch (SemanticError err) {
return false;
@ -33,18 +39,6 @@ abstract public class ExprNode extends Node {
}
// #@@}
public boolean isAssignable() {
return false;
}
public boolean isParameter() {
return false;
}
public boolean shouldEvaluatedToAddress() {
return type().isArray();
}
// used by IRGenerator
public boolean isConstantAddress() {
return false;

View File

@ -0,0 +1,28 @@
package net.loveruby.cflat.ast;
import net.loveruby.cflat.type.Type;
abstract public class LHSNode extends ExprNode {
protected Type type, origType;
public Type type() {
return type != null ? type : origType();
}
public void setType(Type t) {
this.type = t;
}
abstract protected Type origType();
public long allocSize() { return origType().allocSize(); }
public boolean isLvalue() { return true; }
public boolean isAssignable() { return isLoadable(); }
public boolean isLoadable() {
Type t = origType();
return !t.isArray() && !t.isFunction();
}
abstract public boolean isConstantAddress();
}

View File

@ -3,19 +3,15 @@ import net.loveruby.cflat.type.Type;
import net.loveruby.cflat.type.CompositeType;
import net.loveruby.cflat.exception.*;
public class MemberNode extends ExprNode {
protected ExprNode expr;
protected String member;
public class MemberNode extends LHSNode {
private ExprNode expr;
private String member;
public MemberNode(ExprNode expr, String member) {
this.expr = expr;
this.member = member;
}
public Type type() {
return baseType().memberType(member);
}
public CompositeType baseType() {
try {
return expr.type().getCompositeType();
@ -37,15 +33,11 @@ public class MemberNode extends ExprNode {
return baseType().memberOffset(member);
}
// #@@range/isAssignable{
public boolean isAssignable() {
return true;
protected Type origType() {
return baseType().memberType(member);
}
// #@@}
public boolean isConstantAddress() {
return false;
}
public boolean isConstantAddress() { return false; }
public Location location() {
return expr.location();

View File

@ -4,7 +4,7 @@ import net.loveruby.cflat.type.CompositeType;
import net.loveruby.cflat.type.PointerType;
import net.loveruby.cflat.exception.*;
public class PtrMemberNode extends ExprNode {
public class PtrMemberNode extends LHSNode {
public ExprNode expr;
public String member;
@ -13,10 +13,6 @@ public class PtrMemberNode extends ExprNode {
this.member = member;
}
public Type type() {
return dereferedCompositeType().memberType(member);
}
public CompositeType dereferedCompositeType() {
try {
PointerType pt = expr.type().getPointerType();
@ -45,18 +41,16 @@ public class PtrMemberNode extends ExprNode {
return member;
}
public boolean isAssignable() {
return true;
}
public boolean isConstantAddress() {
return false;
}
public long offset() {
return dereferedCompositeType().memberOffset(member);
}
protected Type origType() {
return dereferedCompositeType().memberType(member);
}
public boolean isConstantAddress() { return false; }
public Location location() {
return expr.location();
}

View File

@ -2,8 +2,8 @@ package net.loveruby.cflat.ast;
import net.loveruby.cflat.type.*;
public class TypeNode extends Node {
protected TypeRef typeRef;
protected Type type;
TypeRef typeRef;
Type type;
public TypeNode(TypeRef ref) {
super();
@ -24,12 +24,16 @@ public class TypeNode extends Node {
}
public void setType(Type t) {
if (isResolved()) throw new Error("TypeNode#setType called twice");
if (type != null) {
throw new Error("TypeNode#setType called twice");
}
type = t;
}
public Type type() {
if (type == null) throw new Error("TypeNode not resolved");
if (type == null) {
throw new Error("TypeNode not resolved: " + typeRef);
}
return type;
}

View File

@ -3,13 +3,12 @@ import net.loveruby.cflat.type.Type;
import net.loveruby.cflat.entity.Entity;
import net.loveruby.cflat.entity.DefinedVariable;
public class VariableNode extends ExprNode {
protected Location location;
protected String name;
protected Entity entity;
public class VariableNode extends LHSNode {
private Location location;
private String name;
private Entity entity;
public VariableNode(Location loc, String name) {
super();
this.location = loc;
this.name = name;
}
@ -38,35 +37,28 @@ public class VariableNode extends ExprNode {
entity = ent;
}
public Type type() {
return entity().type();
}
public TypeNode typeNode() {
return entity().typeNode();
}
public boolean isAssignable() {
return true;
}
public boolean isParameter() {
return entity().isParameter();
}
public boolean shouldEvaluatedToAddress() {
return entity().cannotLoad();
protected Type origType() {
return entity().type();
}
public boolean isConstantAddress() {
return true;
}
public boolean isConstantAddress() { return true; }
public Location location() {
return location;
}
protected void _dump(Dumper d) {
if (type != null) {
d.printMember("type", type);
}
d.printMember("name", name, isResolved());
}

View File

@ -129,11 +129,11 @@ public class Compiler {
new LocalResolver(errorHandler).resolve(ast);
new TypeResolver(errorHandler).resolve(ast, typeTable);
typeTable.semanticCheck(errorHandler);
new DereferenceChecker(errorHandler).check(ast);
if (opts.mode() == CompilerMode.DumpReference) {
ast.dump();
return ast;
}
new DereferenceChecker(errorHandler).check(ast);
new TypeChecker(errorHandler).check(ast, typeTable);
return ast;
}

View File

@ -100,7 +100,7 @@ class DereferenceChecker extends Visitor {
return null;
}
protected void checkAssignment(AbstractAssignNode node) {
private void checkAssignment(AbstractAssignNode node) {
if (! node.lhs().isAssignable()) {
semanticError(node, "invalid lhs expression");
}
@ -136,7 +136,7 @@ class DereferenceChecker extends Visitor {
public Void visit(ArefNode node) {
super.visit(node);
if (! node.expr().isDereferable()) {
if (! node.expr().isPointer()) {
semanticError(node, "indexing non-array/pointer expression");
}
return null;
@ -150,7 +150,7 @@ class DereferenceChecker extends Visitor {
public Void visit(PtrMemberNode node) {
super.visit(node);
if (! node.expr().isDereferable()) {
if (! node.expr().isPointer()) {
undereferableError(node);
}
checkMemberRef(node, node.dereferedType(), node.member());
@ -172,7 +172,7 @@ class DereferenceChecker extends Visitor {
// #@@range/DereferenceNode{
public Void visit(DereferenceNode node) {
super.visit(node);
if (! node.expr().isDereferable()) {
if (! node.expr().isPointer()) {
undereferableError(node);
}
return null;
@ -182,8 +182,8 @@ class DereferenceChecker extends Visitor {
// #@@range/AddressNode{
public Void visit(AddressNode node) {
super.visit(node);
if (! node.expr().isAssignable()) {
semanticError(node, "invalid LHS expression for &");
if (! node.expr().isLvalue()) {
semanticError(node, "invalid expression for &");
}
return null;
}
@ -197,6 +197,14 @@ class DereferenceChecker extends Visitor {
return null;
}
public Void visit(CastNode node) {
super.visit(node);
if (node.type().isArray()) {
semanticError(node, "cast specifies array type");
}
return null;
}
//
// Utilities
//

View File

@ -482,7 +482,7 @@ class IRGenerator implements ASTVisitor<Void, Expr> {
switch (op) {
case ADD:
case SUB:
if (lhsType.isDereferable()) {
if (lhsType.isPointer()) {
return new Bin(rhs.type(), Op.MUL,
rhs, ptrDiff(lhsType.baseType().size()));
}
@ -565,11 +565,11 @@ class IRGenerator implements ASTVisitor<Void, Expr> {
Expr right = transformExpr(node.right());
Expr left = transformExpr(node.left());
if (node.operator().equals("+") || node.operator().equals("-")) {
if (node.left().type().isDereferable()) {
if (node.left().type().isPointer()) {
right = new Bin(ptrDiffType(), Op.MUL,
right, ptrDiff(node.left().type().baseType().size()));
}
else if (node.right().type().isDereferable()) {
else if (node.right().type().isPointer()) {
left = new Bin(ptrDiffType(), Op.MUL,
left, ptrDiff(node.right().type().baseType().size()));
}
@ -626,9 +626,7 @@ class IRGenerator implements ASTVisitor<Void, Expr> {
Expr addr = new Bin(pointer(), Op.ADD,
addressOf(transformExpr(node.expr())),
intValue(node.offset()));
return node.shouldEvaluatedToAddress()
? addr
: deref(addr, node.type());
return node.isLoadable() ? deref(addr, node.type()) : addr;
}
// #@@}
@ -636,7 +634,7 @@ class IRGenerator implements ASTVisitor<Void, Expr> {
Expr addr = new Bin(pointer(), Op.ADD,
transformExpr(node.expr()),
intValue(node.offset()));
return node.shouldEvaluatedToAddress() ? addr : deref(addr, node.type());
return node.isLoadable() ? deref(addr, node.type()) : addr;
}
public Expr visit(DereferenceNode node) {
@ -645,12 +643,7 @@ class IRGenerator implements ASTVisitor<Void, Expr> {
public Expr visit(AddressNode node) {
Expr e = transformExpr(node.expr());
if (node.expr().shouldEvaluatedToAddress()) {
return e;
}
else {
return addressOf(e);
}
return node.expr().isLoadable() ? addressOf(e) : e;
}
public Expr visit(CastNode node) {
@ -669,7 +662,7 @@ class IRGenerator implements ASTVisitor<Void, Expr> {
}
public Expr visit(SizeofExprNode node) {
return intValue(node.expr().type().allocSize());
return intValue(node.expr().allocSize());
}
public Expr visit(SizeofTypeNode node) {
@ -681,7 +674,7 @@ class IRGenerator implements ASTVisitor<Void, Expr> {
return transformExpr(node.entity().value());
}
Var var = new Var(varType(node.type()), node.entity());
return node.shouldEvaluatedToAddress() ? addressOf(var) : var;
return node.isLoadable() ? var : addressOf(var);
}
public Expr visit(IntegerLiteralNode node) {

View File

@ -164,7 +164,7 @@ class TypeChecker extends Visitor {
if (! checkLHS(node.lhs())) return null;
if (! checkRHS(node.rhs())) return null;
if (node.operator().equals("+") || node.operator().equals("-")) {
if (node.lhs().type().isDereferable()) {
if (node.lhs().type().isPointer()) {
mustBeInteger(node.rhs(), node.operator());
node.setRHS(integralPromotedExpr(node.rhs()));
return null;
@ -290,7 +290,7 @@ class TypeChecker extends Visitor {
* * pointer - integer
*/
protected void expectsSameIntegerOrPointerDiff(BinaryOpNode node) {
if (node.left().type().isDereferable()) {
if (node.left().type().isPointer()) {
if (node.left().type().baseType().isVoid()) {
wrongTypeError(node.left(), node.operator());
return;
@ -300,7 +300,7 @@ class TypeChecker extends Visitor {
node.setRight(integralPromotedExpr(node.right()));
node.setType(node.left().type());
}
else if (node.right().type().isDereferable()) {
else if (node.right().type().isPointer()) {
if (node.operator().equals("-")) {
error(node, "invalid operation integer-pointer");
return;
@ -342,13 +342,13 @@ class TypeChecker extends Visitor {
protected void expectsComparableScalars(BinaryOpNode node) {
if (! mustBeScalar(node.left(), node.operator())) return;
if (! mustBeScalar(node.right(), node.operator())) return;
if (node.left().type().isDereferable()) {
if (node.left().type().isPointer()) {
ExprNode right = forcePointerType(node.left(), node.right());
node.setRight(right);
node.setType(node.left().type());
return;
}
if (node.right().type().isDereferable()) {
if (node.right().type().isPointer()) {
ExprNode left = forcePointerType(node.right(), node.left());
node.setLeft(left);
node.setType(node.right().type());
@ -433,7 +433,7 @@ class TypeChecker extends Visitor {
}
node.setAmount(1);
}
else if (node.expr().type().isDereferable()) {
else if (node.expr().type().isPointer()) {
if (node.expr().type().baseType().isVoid()) {
// We cannot increment/decrement void*
wrongTypeError(node.expr(), node.operator());

View File

@ -31,6 +31,18 @@ public class TypeResolver extends Visitor
for (Entity e : ast.entities()) {
e.accept(this);
}
for (DefinedVariable var : ast.definedVariables()) {
if (var.hasInitializer()) {
visitExpr(var.initializer());
}
}
for (Constant c : ast.constants()) {
visitExpr(c.value());
}
for (DefinedFunction f : ast.definedFunctions()) {
visitStmt(f.body());
}
// #@@}
}
// #@@}
@ -100,9 +112,6 @@ public class TypeResolver extends Visitor
// #@@range/DefinedVariable{
public Void visit(DefinedVariable var) {
bindType(var.typeNode());
if (var.hasInitializer()) {
visitExpr(var.initializer());
}
return null;
}
// #@@}
@ -114,14 +123,12 @@ public class TypeResolver extends Visitor
public Void visit(Constant c) {
bindType(c.typeNode());
visitExpr(c.value());
return null;
}
// #@@range/DefinedFunction{
public Void visit(DefinedFunction func) {
resolveFunctionHeader(func);
visitStmt(func.body());
return null;
}
// #@@}
@ -135,11 +142,8 @@ public class TypeResolver extends Visitor
protected void resolveFunctionHeader(Function func) {
bindType(func.typeNode());
for (Parameter param : func.parameters()) {
Type t = typeTable.get(param.typeNode().typeRef());
// arrays must be converted to pointers in a function parameter.
if (t.isArray()) {
t = typeTable.pointerTo(t.getArrayType().baseType());
}
Type t = typeTable.getParamType(param.typeNode().typeRef());
param.typeNode().setType(t);
}
}
@ -151,7 +155,12 @@ public class TypeResolver extends Visitor
public Void visit(BlockNode node) {
for (DefinedVariable var : node.variables()) {
var.accept(this);
bindType(var.typeNode());
}
for (DefinedVariable var : node.variables()) {
if (var.hasInitializer()) {
visitExpr(var.initializer());
}
}
visitStmts(node.stmts());
return null;
@ -159,11 +168,10 @@ public class TypeResolver extends Visitor
public Void visit(AddressNode node) {
super.visit(node);
// to avoid SemanticError which occurs when getting type of
// expr which is not assignable.
try {
Type base = node.expr().type();
if (node.expr().shouldEvaluatedToAddress()) {
if (! node.expr().isLoadable()) {
// node.expr.type is already pointer.
node.setType(base);
}
else {
@ -177,6 +185,54 @@ public class TypeResolver extends Visitor
return null;
}
public Void visit(DereferenceNode node) {
super.visit(node);
handleImplicitAddress(node);
return null;
}
public Void visit(MemberNode node) {
super.visit(node);
handleImplicitAddress(node);
return null;
}
public Void visit(PtrMemberNode node) {
super.visit(node);
handleImplicitAddress(node);
return null;
}
public Void visit(ArefNode node) {
super.visit(node);
handleImplicitAddress(node);
return null;
}
public Void visit(VariableNode node) {
super.visit(node);
handleImplicitAddress(node);
return null;
}
private void handleImplicitAddress(LHSNode node) {
try {
if (! node.isLoadable()) {
Type t = node.type();
if (t.isArray()) {
// int[4] ary; ary; should generate int*
node.setType(typeTable.pointerTo(t.baseType()));
}
else {
node.setType(typeTable.pointerTo(t));
}
}
}
catch (SemanticError err) {
// #isLoadable may cause SemanticError, ignore it
}
}
public Void visit(CastNode node) {
bindType(node.typeNode());
super.visit(node);

View File

@ -12,7 +12,7 @@ public class Constant extends Entity {
this.value = value;
}
public boolean cannotLoad() { return false; }
public boolean isAssignable() { return false; }
public boolean isDefined() { return true; }
public boolean isInitialized() { return true; }
public boolean isConstant() { return true; }

View File

@ -70,8 +70,6 @@ abstract public class Entity
return (nRefered > 0);
}
abstract public boolean cannotLoad();
public void setMemref(MemoryReference mem) {
this.memref = mem;
}

View File

@ -14,27 +14,19 @@ abstract public class Function extends Entity {
super(priv, t, name);
}
public boolean isFunction() { return true; }
public boolean isInitialized() { return true; }
abstract public boolean isDefined();
abstract public List<Parameter> parameters();
public FunctionType functionType() {
return type().getPointerType().baseType().getFunctionType();
}
public Type returnType() {
return functionType().returnType();
return type().getFunctionType().returnType();
}
public boolean isVoid() {
return returnType().isVoid();
}
public boolean cannotLoad() {
return true;
}
public void setCallingSymbol(Symbol sym) {
if (this.callingSymbol != null) {
throw new Error("must not happen: Function#callingSymbol was set again");

View File

@ -6,8 +6,4 @@ abstract public class Variable extends Entity {
public Variable(boolean priv, TypeNode type, String name) {
super(priv, type, name);
}
public boolean cannotLoad() {
return type().isArray();
}
}

View File

@ -24,10 +24,6 @@ public class Addr extends Expr {
return entity.memref();
}
public Addr addressNode(Type type) {
return this;
}
public Entity getEntityForce() {
return entity;
}

View File

@ -536,18 +536,16 @@ Constant defconst():
DefinedFunction defun():
{
boolean priv;
TypeRef ref;
TypeRef ret;
String n;
Params ps;
BlockNode body;
}
{
priv=storage() ref=typeref() n=name() "(" ps=params() ")" body=block()
priv=storage() ret=typeref() n=name() "(" ps=params() ")" body=block()
{
ParamTypeRefs paramref = ps.parametersTypeRef();
TypeNode t = new TypeNode(new PointerTypeRef(
new FunctionTypeRef(ref, paramref)));
return new DefinedFunction(priv, t, n, ps, body);
TypeRef t = new FunctionTypeRef(ret, ps.parametersTypeRef());
return new DefinedFunction(priv, new TypeNode(t), n, ps, body);
}
}
// #@@}
@ -692,17 +690,15 @@ Slot slot():
// #@@range/funcdecl{
UndefinedFunction funcdecl():
{
TypeRef ref;
TypeRef ret;
String n;
Params ps;
}
{
<EXTERN> ref=typeref() n=name() "(" ps=params() ")" ";"
<EXTERN> ret=typeref() n=name() "(" ps=params() ")" ";"
{
ParamTypeRefs paramref = ps.parametersTypeRef();
TypeNode t = new TypeNode(new PointerTypeRef(
new FunctionTypeRef(ref, paramref)));
return new UndefinedFunction(t, n, ps);
TypeRef t = new FunctionTypeRef(ret, ps.parametersTypeRef());
return new UndefinedFunction(new TypeNode(t), n, ps);
}
}
// #@@}
@ -749,9 +745,9 @@ TypeRef typeref():
{
ref = new PointerTypeRef(ref);
}
| "(" "*" ")" "(" params=param_typerefs() ")"
| "(" params=param_typerefs() ")"
{
ref = new PointerTypeRef(new FunctionTypeRef(ref, params));
ref = new FunctionTypeRef(ref, params);
}
)*
{

View File

@ -17,8 +17,7 @@ public class ArrayType extends Type {
}
public boolean isArray() { return true; }
public boolean isDereferable() { return true; }
public boolean isScalar() { return true; }
public boolean isScalar() { return false; }
public boolean isSigned() { return false; }
public boolean isAllocatedArray() {
@ -66,12 +65,12 @@ public class ArrayType extends Type {
public boolean isSameType(Type other) {
// length is not important
if (! other.isDereferable()) return false;
if (!other.isPointer() && !other.isArray()) return false;
return baseType.isSameType(other.baseType());
}
public boolean isCompatible(Type target) {
if (! target.isDereferable()) return false;
if (!target.isPointer() && !target.isArray()) return false;
if (target.baseType().isVoid()) {
return true;
}
@ -80,7 +79,7 @@ public class ArrayType extends Type {
}
public boolean isCastableTo(Type target) {
return target.isDereferable();
return target.isPointer() || target.isArray();
}
public String toString() {

View File

@ -12,6 +12,7 @@ public class FunctionType extends Type {
}
public boolean isFunction() { return true; }
public boolean isCallable() { return true; }
public boolean isSameType(Type other) {
if (! other.isFunction()) return false;
@ -68,7 +69,7 @@ public class FunctionType extends Type {
String sep = "";
StringBuffer buf = new StringBuffer();
buf.append(returnType.toString());
buf.append(" (*)(");
buf.append("(");
for (Type t : paramTypes.types()) {
buf.append(sep);
buf.append(t.toString());

View File

@ -42,7 +42,7 @@ public class IntegerType extends Type {
}
public boolean isCastableTo(Type target) {
return (target.isInteger() || target.isDereferable());
return (target.isInteger() || target.isPointer());
}
public long size() {

View File

@ -19,7 +19,7 @@ public class ParamTypeRefs extends ParamSlots<TypeRef> {
public ParamTypes internTypes(TypeTable table) {
List<Type> types = new ArrayList<Type>();
for (TypeRef ref : paramDescriptors) {
types.add(table.get(ref));
types.add(table.getParamType(ref));
}
return new ParamTypes(location, types, vararg);
}

View File

@ -12,9 +12,6 @@ public class PointerType extends Type {
public boolean isPointer() { return true; }
public boolean isScalar() { return true; }
public boolean isSigned() { return false; }
// #@@range/isDereferable{
public boolean isDereferable() { return true; }
// #@@}
public boolean isCallable() { return baseType.isFunction(); }
public long size() {
@ -31,12 +28,12 @@ public class PointerType extends Type {
}
public boolean isSameType(Type other) {
if (! other.isDereferable()) return false;
if (!other.isPointer()) return false;
return baseType.isSameType(other.baseType());
}
public boolean isCompatible(Type other) {
if (! other.isDereferable()) return false;
if (!other.isPointer()) return false;
if (baseType.isVoid()) {
return true;
}
@ -47,7 +44,7 @@ public class PointerType extends Type {
}
public boolean isCastableTo(Type other) {
return other.isDereferable() || other.isInteger();
return other.isPointer() || other.isInteger();
}
public String toString() {

View File

@ -24,7 +24,6 @@ public abstract class Type {
public boolean isFunction() { return false; }
// Ability methods (unary)
public boolean isDereferable() { return false; }
public boolean isAllocatedArray() { return false; }
public boolean isIncompleteArray() { return false; }
public boolean isScalar() { return false; }

View File

@ -90,6 +90,12 @@ public class TypeTable {
return type;
}
// array is really a pointer on parameters.
public Type getParamType(TypeRef ref) {
Type t = get(ref);
return t.isArray() ? pointerTo(t.baseType()) : t;
}
public int intSize() {
return this.intSize;
}

View File

@ -39,7 +39,6 @@ public class UserType extends NamedType {
public boolean isUserType() { return true; }
public boolean isFunction() { return realType().isFunction(); }
public boolean isDereferable() { return realType().isDereferable(); }
public boolean isCallable() { return realType().isCallable(); }
public boolean isScalar() { return realType().isScalar(); }

View File

@ -1,11 +1,28 @@
import stdio;
int
main(int argc, char **argv)
main(int argc, char** argv)
{
int (*)(char*) f;
int (char*, ...)* f;
f = puts;
f = printf;
f("OK");
f = &printf;
f(";OK");
f = myputs;
f(";OK");
f = &myputs;
f(";OK");
puts("");
return 0;
}
static int
myputs(char *s, ...)
{
return printf("%s", s);
}

View File

@ -1,13 +0,0 @@
import stdio;
void myputs(char* str) { puts(str); }
int
main(int argc, char **argv)
{
void (*)(char*) f;
f = myputs;
f("OK");
return 0;
}

View File

@ -1,11 +0,0 @@
import stdio;
int
main(int argc, char **argv)
{
int (*)(char*) f;
f = &puts;
f("OK");
return 0;
}

View File

@ -1,13 +0,0 @@
import stdio;
void myputs(char* str) { puts(str); }
int
main(int argc, char **argv)
{
void (*)(char*) f;
f = &myputs;
f("OK");
return 0;
}

View File

@ -98,7 +98,7 @@ test_10_assign() {
assert_out "3;4;3;12;4;1;1;7;5;1;4;e;H;76;75;1;3;6;82;81" ./opassign
assert_out "0;1;2;2;3;3;4;5;5" ./inc
assert_out "4;3;2;2;1;1;0" ./dec
assert_compile_success textwrite.cb
assert_compile_error textwrite.cb
}
test_12_if() {
@ -244,10 +244,7 @@ test_25_block() {
}
test_26_funcptr() {
assert_out "OK" ./funcptr
assert_out "OK" ./funcptr2
assert_out "OK" ./funcptr3
assert_out "OK" ./funcptr4
assert_out "OK;OK;OK;OK" ./funcptr
assert_compile_error defun-semcheck.cb
assert_compile_error defun-semcheck2.cb
assert_compile_error defun-semcheck3.cb

View File

@ -22,7 +22,7 @@ typedef struct s struct_s;
typedef union u union_u;
typedef int[8] ints8;
typedef int* intptr;
typedef int (*)(char*) msgfunc;
typedef int (char*)* msgfunc;
typedef sint sint2;
int