view ast/Exp.d @ 59:1d6f4ad38a91 new_gen

Make most of the tests pass again Still have two bugs, one is that type conversion has been diabled for return statements, the other is at line ~540 of CodeGen.d, were the following error is emitted: Can't find an implicit conversion between { i32 } and i32
author Anders Halager <halager@gmail.com>
date Tue, 29 Apr 2008 00:31:56 +0200
parents fc62c5296a1c
children 2451f0904bf6
line wrap: on
line source

module ast.Exp;

import tango.text.Util : jhash;
import tango.io.Stdout;

import ast.Decl,
       ast.Stmt;

import lexer.Token;

import sema.SymbolTable,
       sema.DType;

enum ExpType
{
    Binary,
    Negate,
    IntegerLit,
    MemberReference,
    ArrayLookup,
    Identifier,
    AssignExp,
    CallExp,
}

class Exp
{
    this(ExpType expType) 
    {
        this.expType = expType;
    }

    DType type() { return null; }

    ExpType expType;
    Scope env;
    int stmtIndex;

    Exp simplify()
    {
        return this;
    }
}

class CallExp : Exp
{
    this(Exp exp, Exp[] args)
    {
        super(ExpType.CallExp);
        this.exp = exp;
        this.args = args;
    }

    override DType type()
    {
        DFunction f = cast(DFunction)exp.type();
        assert(f !is null, "Can only call functions");
        return f.return_type;
    }

    Exp exp;
    Exp[] args;
    bool sret = false;


    Exp simplify()
    {
        DFunction func_t = cast(DFunction)exp.type();
        assert(func_t !is null, "Calling on something that isn't a function");
        if (cast(DStruct)func_t.return_type is null)
            return this;

        auto call = cast(Identifier)exp;
        FuncDecl f = env.parentFunction;
        auto i = new Identifier("temp.var");
        i.env = f.env;
        f.env.add(i);
        f.env.find(i).type = f.env.find(call).type;
        auto var = new VarDecl(f.type, i, null);
        Exp[] args; 
        args ~= i;
        args ~= this.args;
        auto callExp = new CallExp(exp, args);
        callExp.env = f.env;
//        auto ass = new AssignExp(i, callExp);
        var.env = f.env;
//        ass.env = f.env;
        auto stmtVar = new DeclStmt(var);
        auto stmtCall = new ExpStmt(callExp);
        Stmt[] stmts;
        foreach( index, s ; f.statements)
        {
            if(stmtIndex == index)
            {
                stmts ~= stmtVar;
                stmts ~= stmtCall;
            }
            stmts ~= s;
        }
        f.statements = stmts;
        callExp.sret = true;

        return i;
    }
}

class AssignExp : Exp
{
    this(Exp identifier, Exp exp)
    {
        super(ExpType.AssignExp);
        this.identifier = identifier;
        this.exp = exp;
    }
    Exp simplify()
    {
        identifier = identifier.simplify;
        exp = exp.simplify;

        return this;
    }

    override DType type() { return identifier.type(); }

    Exp identifier;
    Exp exp;
}

class BinaryExp : Exp
{
    public enum Operator
    {
        Assign,

        Eq, Ne,

        Lt, Le,
        Gt, Ge,

        Add, Sub,
        Mul, Div, Mod,
    }

    this(Operator op, Exp left, Exp right)
    {
        super(ExpType.Binary);
        this.op = op;
        this.left = left;
        this.right = right;
    }

    override DType type()
    {
        if (myType)
            return myType;

        DType l = left.type;
        DType r = right.type;
        if (l is r)
            myType = l;
        else if (l.hasImplicitConversionTo(r))
            myType = r;
        else if (r.hasImplicitConversionTo(l))
            myType = l;
        else
            return null;
    }

    char[] resultType()
    {
        if (op >= Operator.Eq && op <= Operator.Ge)
            return "bool";
        return null;
    }
    Exp simplify()
    {
        left = left.simplify;
        right = right.simplify;
        return this;
    }

    Operator op;
    Exp left, right;
    private DType myType;
}

class NegateExp : Exp
{
    this(Exp exp)
    {
        super(ExpType.Negate);
        this.exp = exp;
    }
    Exp simplify()
    {
        exp = exp.simplify;
        return this;
    }

    override DType type() { return exp.type(); }

    public Exp exp;
}

class IntegerLit : Exp
{
    this(Token t)
    {
        super(ExpType.IntegerLit);
        this.token = t;
    }
    Exp simplify()
    {
        return this;
    }

    override DType type() { return DType.Int; }

    Token token;
}

class MemberReference : Exp
{
    this(Exp target, Identifier child)
    {
        super(ExpType.MemberReference);
        this.target = target;
        this.child = child;
    }
    Exp simplify()
    {
        target = target.simplify;
        return this;
    }

    override DType type()
    {
        if (myType)
            return myType;

        DStruct st = cast(DStruct)target.type;
        assert(st, "Only structs have members");
        if (auto t = st.typeOf(child.token.get))
            myType = t;
        // no error reporting here
        else assert(0, "Referencing non-existant member");
    }

    Identifier child;
    Exp target;
    private DType myType;
}

class ArrayLookup : Exp
{
    this(Exp target, IntegerLit pos)
    {
        super(ExpType.ArrayLookup);
        this.target = target;
        this.pos = pos;
    }

    override DType type() { return target.type(); }

    Exp simplify()
    {
        target = target.simplify;
        pos.simplify;
        return this;
    }

    Exp target;
    IntegerLit pos;
}

class Identifier : Exp
{
    this(Token t)
    {
        super(ExpType.Identifier);
        this.token = t;
        name = t.get;
    }

    override DType type()
    {
        if (myType !is null)
            return myType;
        myType = env.find(this).type;
        return myType;
    }

    this(char[] name)
    {
        super(ExpType.Identifier);
        this.name = name;
    }

    char[] get()
    {
        return name;
    }

    hash_t toHash()
    {
        return jhash(name);
    }

    int opCmp(Object o)
    {
        if (auto id = cast(Identifier)o)
            return typeid(char[]).compare(&name, &id.name);
        return 0;
    }

    int opEquals(Object o)
    {
        if (auto id = cast(Identifier)o)
            return typeid(char[]).equals(&name, &id.name);
        return 0;
    }

    Exp simplify()
    {
        return this;
    }

    Token token;
    char[] name;
    private DType myType;
}