view ast/Exp.d @ 195:4e1a7265d620

Made a BuildTypes pass, to give all exp's a type.
author Anders Johnsen <skabet@gmail.com>
date Tue, 29 Jul 2008 15:50:24 +0200
parents 08f68d684047
children
line wrap: on
line source

module ast.Exp;

import tango.text.Util,
       Integer = tango.text.convert.Integer;
import tango.io.Stdout;

import ast.Decl,
       ast.Stmt;

import lexer.Token;

import sema.Scope,
       sema.Symbol,
       sema.DType;

import basic.LiteralParsing;

enum ExpType
{
    Binary,
    Negate,
    Deref,
    AddressOfExp,
    IntegerLit,
    MemberReference,
    Index,
    Identifier,
    AssignExp,
    CallExp,
    CastExp,
    StringExp,
    NewExp,
    NullExp,
    ArrayLiteralExp,

    IdentifierTypeExp,
    ArrayTypeExp,
    StaticArrayTypeExp,
    PointerTypeExp,
    FunctionTypeExp,
}

abstract class Exp
{
    this(ExpType expType, SLoc loc)
    {
        this.expType = expType;
        this.loc = loc;
    }

    /**
      Get the fully qualified name for the expression (if it can be resolved to
      one) - otherwise null is returned
     **/
    char[] getFQN() { return null; }

    /// The same as getFQN, except that the name is mangled
    char[] getMangledFQN() { return null; }

    /**
      Try to get the symbol the expression represents.

      Returns null for most expressions as they don't represent any symbol.
      Identifiers and member references can have a sensible value.
     **/
    Symbol getSymbol() { return null; }

    /// Get the type of the expression
    DType type;

    /// Indicates which type the expression is - to avoid a lot of casts
    ExpType expType;

    /// The environment of the expression
    Scope env;

    int stmtIndex;

    /**
      The "main" location of the expression.
      What exactly this represents varies but for most things its the start
      while for a binary expression its the operator.
     **/
    SourceLocation loc;

    /// Return the starting location of this expression
    SourceLocation startLoc() { return loc; }

    /// Get the full extents of the expression
    SourceRange sourceRange() { return SourceRange(loc, loc + 1); }

    /// Do some simplifications
    Exp simplify() { return this; }
}

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

    DType callerType()
    {
        DFunction f = new DFunction(new Identifier("function"));
        f.returnType = type;
        foreach (a ; args)
            f.params ~= a.type;
            
        return f;
    }

    override CallExp simplify()
    {
        foreach (ref arg; args)
            arg = arg.simplify();
        exp = exp.simplify();
        return this;
    }

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

    override SourceRange sourceRange()
    {
        SourceRange res = exp.sourceRange;
        if (args.length > 0)
            res = res + args[$ - 1].sourceRange;
        return res;
    }
}

class AssignExp : BinaryExp
{
    this(SLoc op_loc, Operator op, Exp identifier, Exp exp)
    {
        super(ExpType.AssignExp, op_loc, op, identifier, exp);
        this.identifier = identifier;
        this.exp = exp;
    }

    override AssignExp simplify()
    {
        identifier = identifier.simplify();
        exp = exp.simplify();

        return this;
    }

    override SourceRange sourceRange()
    {
        return identifier.sourceRange + exp.sourceRange;
    }

    Exp identifier;
    Exp exp;
}

class BinaryExp : Exp
{
    public enum Operator
    {
        Assign,
        AddAssign,
        SubAssign,
        MulAssign,
        DivAssign,
        ModAssign,

        Eq, Ne,

        Lt, Le,
        Gt, Ge,

        Add, Sub,
        Mul, Div, Mod,

        LeftShift, RightShift, UnsignedRightShift,

        And, Or, Xor,
    }

    char[][] getOp = ["=","+=","-=","*=","/=","%=","==","!=","<","<=",">",">=","+","-","*","/","%","<<",">>",">>>"];

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

    protected this(ExpType e, SLoc op_loc, Operator op, Exp left, Exp right)
    {
        super(e, op_loc);
        this.op = op;
        this.left = left;
        this.right = right;
    }

    override SLoc startLoc() { return left.startLoc(); }

    override SourceRange sourceRange()
    {
        return left.sourceRange + right.sourceRange;
    }

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

    override BinaryExp simplify()
    {
        left = left.simplify();
        right = right.simplify();
        return this;
    }

    Operator op;
    Exp left, right;
}

class NegateExp : Exp
{
    this(SLoc op, Exp exp)
    {
        super(ExpType.Negate, op);
        this.exp = exp;
    }

    override NegateExp simplify()
    {
        exp = exp.simplify();
        return this;
    }

    override SourceRange sourceRange()
    {
        return SourceRange(loc) + exp.sourceRange;
    }

    public Exp exp;
}

class DerefExp : Exp
{
    this(SLoc op, Exp exp)
    {
        super(ExpType.Deref, op);
        this.exp = exp;
    }

    override DerefExp simplify()
    {
        exp = exp.simplify();
        return this;
    }

    override SourceRange sourceRange()
    {
        return SourceRange(loc) + exp.sourceRange;
    }

    public Exp exp;
}

class AddressOfExp : Exp
{
    this(SLoc op, Exp exp)
    {
        super(ExpType.AddressOfExp, op);
        this.exp = exp;
    }

    override AddressOfExp simplify()
    {
        exp = exp.simplify();
        return this;
    }

    override SourceRange sourceRange()
    {
        return SourceRange(loc) + exp.sourceRange;
    }

    public Exp exp;
}

class IntegerLit : Exp
{
    this(SLoc loc, char[] t)
    {
        super(ExpType.IntegerLit, loc);
        range = SourceRange(loc, loc + t.length);
        this.name = t;
    }

    char[] get()
    {
        return name;
    }

    override IntegerLit simplify()
    {
        return this;
    }

    override SourceRange sourceRange()
    {
        return range;
    }

    Number number;

    char[] name;
    private SourceRange range;
}

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

    override char[] getFQN()
    {
        return getSymbol().getFQN();
    }

    override char[] getMangledFQN()
    {
        return target.type.mangle() ~ child.getMangledFQN();
    }

    override Symbol getSymbol()
    {
        auto s = target.getSymbol();
        if (s !is null)
            return s.findMembers(child.get)[0];
        return null;
    }

    override MemberReference simplify()
    {
        target = target.simplify();
        return this;
    }

    override SLoc startLoc() { return target.startLoc(); }

    override SourceRange sourceRange()
    {
        return target.sourceRange + child.sourceRange;
    }

    Identifier child;
    Exp target;
}

class IndexExp : Exp
{
    this(Exp target, SLoc left_bracket, Exp index, SLoc right_bracket)
    {
        super(ExpType.Index, target.startLoc);
        this.target = target;
        this.left_bracket = left_bracket;
        this.index = index;
        this.right_bracket = right_bracket;
    }

    override SourceRange sourceRange()
    {
        return target.sourceRange + SourceRange(right_bracket);
    }

    override IndexExp simplify()
    {
        target = target.simplify();
        index = index.simplify();
        return this;
    }

    Exp target;
    Exp index;
    SLoc left_bracket, right_bracket;
}

class CastExp : Exp
{
    this(SLoc loc, Identifier castType, Exp exp)
    {
        super(ExpType.CastExp, loc);
        this.castType = castType;
        this.exp = exp;
    }

    override CastExp simplify()
    {
        castType = castType.simplify();
        exp = exp.simplify();
        return this;
    }

    override SourceRange sourceRange()
    {
        return SourceRange(loc) + exp.sourceRange;
    }

    Identifier castType;
    Exp exp;
}

class StringExp : Exp
{
    this(SLoc loc, char[] str)
    {
        super(ExpType.StringExp, loc);
        this.str = str;
    }

    char[] str;
    String data;
}

class NewExp : Exp
{
    this(Identifier newType, Exp[] a_args, Exp[] c_args)
    {
        super(ExpType.NewExp, newType.loc);
        this.newType = newType;
        this.a_args = a_args;
        this.c_args = c_args;
    }

    Exp[] a_args, c_args;
    Identifier newType;
    Symbol callSym;
}

class NullExp : Exp
{
    this(SLoc loc)
    {
        super(ExpType.NullExp, loc);
    }
}

class Identifier : Exp
{
    this(SLoc loc, char[] name)
    {
        super(ExpType.Identifier, loc);
        this.name = name;
    }

    protected this(ExpType t, SLoc loc)
    {
        super(t, loc);
    }

    override char[] getFQN()
    {
        return name;
    }

    override char[] getMangledFQN()
    {
        return Integer.toString(name.length) ~ name;
    }

    override Symbol getSymbol()
    {
        if (!env)
            return null;
        if (auto decl = env.find(this.get))
            if(decl.length)
                return decl[$-1].sym;
        return null;
    }

    this(char[] name)
    {
        super(ExpType.Identifier, SLoc.Invalid);
        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;
    }

    override Identifier simplify()
    {
        return this;
    }

    override SourceRange sourceRange()
    {
        return SourceRange(loc, loc + name.length);
    }

    char[] name;
}

class IdentifierTypeExp : Identifier
{
    this(SLoc loc, char[] name)
    {
        super(ExpType.IdentifierTypeExp, loc);
        this.name = name;
    }

    protected this(ExpType t, SLoc loc)
    {
        super(t, loc);
    }
}

class PointerTypeExp : IdentifierTypeExp
{
    this(IdentifierTypeExp pointerOf)
    {
        super(ExpType.PointerTypeExp, pointerOf.loc);
        this.pointerOf = pointerOf;
        this.name = pointerOf.name;
    }

    Identifier pointerOf;
}

class StaticArrayTypeExp : IdentifierTypeExp
{
    this(IdentifierTypeExp arrayOf, IntegerLit size)
    {
        super(ExpType.StaticArrayTypeExp, arrayOf.loc);
        this.arrayOf = arrayOf;
        this.size = Integer.parse(size.get);
        this.name = arrayOf.name;
    }

    Identifier arrayOf;
    int size;
}

class ArrayTypeExp : IdentifierTypeExp
{
    this(IdentifierTypeExp arrayOf)
    {
        super(ExpType.ArrayTypeExp, arrayOf.loc);
        this.arrayOf = arrayOf;
        this.name = arrayOf.name;
    }

    Identifier arrayOf;
}

class FunctionTypeExp : IdentifierTypeExp
{
    this(IdentifierTypeExp returnType, VarDecl[] decls)
    {
        super(ExpType.FunctionTypeExp, returnType.loc);
        this.returnType = returnType;
        this.decls = decls;
    }

    VarDecl[] decls;
    IdentifierTypeExp returnType;
}

class ArrayLiteralExp : Exp
{
    this(Exp[] exps, SLoc begin, SLoc end)
    {
        super(ExpType.ArrayLiteralExp, begin);
        this.exps = exps;
        this.begin = begin;
        this.end = end;
    }

    Exp[] exps;
    SLoc begin, end;
}