Mercurial > projects > dang
view ast/Exp.d @ 154:0ea5d2f3e96b
Parsing "this" as constructor. Also removed regex from the test run program(seg fault - dmd???)
author | Anders Johnsen <skabet@gmail.com> |
---|---|
date | Mon, 21 Jul 2008 21:45:54 +0200 |
parents | a14ac9e5c858 |
children | 57b0b4464a0b |
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, IntegerLit, MemberReference, Index, Identifier, ArrayIdentifier, StaticArrayIdentifier, PointerIdentifier, AssignExp, CallExp, CastExp, StringExp, } 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 abstract DType type(); /// Indicates which type the expression is - to avoid a lot of casts ExpType expType; /// The environment of the expression Scope env; Symbol symbol; 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; } override DType type() { DFunction f = cast(DFunction)exp.type(); assert(f !is null, "Can only call functions"); return f.returnType; } override CallExp simplify() { foreach (ref arg; args) arg = arg.simplify(); exp = exp.simplify(); return this; } Exp exp; Exp[] args; 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; } override DType type() { return identifier.type(); } 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 DType type() { if (myType) return myType; if (op == Operator.Eq || op == Operator.Ne || op == Operator.Lt || op == Operator.Le || op == Operator.Gt || op == Operator.Ge) { myType = DType.Bool; 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; return myType; } 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; private DType myType; } class NegateExp : Exp { this(SLoc op, Exp exp) { super(ExpType.Negate, op); this.exp = exp; } override NegateExp simplify() { exp = exp.simplify(); return this; } override DType type() { return exp.type(); } 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 DType type() { return exp.type().asPointer().pointerOf; } 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 DType type() { switch(number.type) { case NumberType.Int: return DType.Int; case NumberType.Long: return DType.Long; case NumberType.ULong: return DType.ULong; case NumberType.Double: return DType.Double; case NumberType.Real: return DType.Real; } } 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.findMember(child.get); return null; } override MemberReference 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.name)) myType = t; // no error reporting here else assert(0, "Referencing non-existant member"); return myType; } override SLoc startLoc() { return target.startLoc(); } override SourceRange sourceRange() { return target.sourceRange + child.sourceRange; } Identifier child; Exp target; private DType myType; } 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 DType type() { DType type = target.type(); if (type.isStaticArray()) return type.asStaticArray().arrayOf; else if (type.isPointer()) return type.asPointer().pointerOf; else assert(0, "Can only index pointers and arrays"); } 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 DType type() { return env.findType(this.castType.get); } 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; } override DType type() { return null; } char[] str; } class PointerIdentifier : Identifier { this(Identifier pointerOf) { super(ExpType.PointerIdentifier, pointerOf.loc); this.pointerOf = pointerOf; this.name = pointerOf.name; } override DType type() { return pointerOf.type.getPointerTo(); } Identifier pointerOf; } class StaticArrayIdentifier : Identifier { this(Identifier arrayOf, IntegerLit size) { super(ExpType.StaticArrayIdentifier, arrayOf.loc); this.arrayOf = arrayOf; this.size = Integer.parse(size.get); this.name = arrayOf.name; } override DType type() { return arrayOf.type.getAsStaticArray(size); } Identifier arrayOf; int size; private DType myType; } class ArrayIdentifier : Identifier { this(Identifier arrayOf) { super(ExpType.ArrayIdentifier, arrayOf.loc); this.arrayOf = arrayOf; this.name = arrayOf.name; } override DType type() { return arrayOf.type.getAsArray(); } Identifier arrayOf; private DType myType; } 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 (auto decl = env.find(this.get)) return decl.sym; else return null; } override DType type() { if (myType !is null) return myType; else if (auto sym = getSymbol) myType = sym.type; else myType = DType.Int; return myType; } 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; } void setType(DType myType) { this.myType = myType; } char[] name; private DType myType; }