Mercurial > projects > dang
view ast/Exp.d @ 79:81813366ef92 new_gen
branch merge
author | Anders Halager <halager@gmail.com> |
---|---|
date | Fri, 02 May 2008 16:39:04 +0200 |
parents | ad956143dcdc 13eea2c4e60d |
children | 682e20aa224f |
line wrap: on
line source
module ast.Exp; import tango.text.Util; import tango.io.Stdout; import ast.Decl, ast.Stmt; import lexer.Token; import sema.SymbolTable, sema.DType; enum ExpType { Binary, Negate, Deref, IntegerLit, MemberReference, ArrayReference, Identifier, ArrayIdentifier, PointerIdentifier, AssignExp, CallExp, CastExp, } 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.returnType; } Exp exp; Exp[] args; bool sret = false; Exp simplify() { if(auto t = cast(DStruct)type) { 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.returnType 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 = t; auto ty = new Identifier(t.name); auto var = new VarDecl(ty, i, null); Exp[] args; args ~= i; args ~= this.args; auto callExp = new CallExp(exp, args); callExp.env = f.env; var.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; } return this; } } 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, } char[][] getOp = ["=","==","!=","<","<=",">",">=","+","-","*","/","%"]; 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; 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; } 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 DerefExp : Exp { this(Exp exp) { super(ExpType.Deref); 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; this.name = substitute(t.get,"_",""); } char[] get() { return name; } Exp simplify() { return this; } override DType type() { return DType.Int; } Token token; char[] name; } 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"); return myType; } Identifier child; Exp target; private DType myType; } class ArrayReference : Exp { this(Exp target, IntegerLit pos) { super(ExpType.ArrayReference); 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 CastExp : Exp { this(Identifier castType, Exp exp) { super(ExpType.CastExp); this.castType = castType; this.exp = exp; } override DType type() { return env.findType(this.castType); } Exp simplify() { castType.simplify; exp.simplify; return this; } Identifier castType; Exp exp; } class PointerIdentifier : Identifier { this(Identifier pointerOf) { super(ExpType.PointerIdentifier); this.pointerOf = pointerOf; this.name = pointerOf.name; } override DType type() { if (myType !is null) return myType; myType = new DPointer(pointerOf.type); return myType; } Identifier pointerOf; private DType myType; } class ArrayIdentifier : Identifier { this(Identifier arrayOf) { super(ExpType.ArrayIdentifier); this.arrayOf = arrayOf; } override DType type() { if (myType !is null) return myType; myType = new DArray(arrayOf.type); return myType; } Identifier arrayOf; private DType myType; } class Identifier : Exp { this(Token t) { super(ExpType.Identifier); this.token = t; name = t.get; } protected this(ExpType t) { super(t); } 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; }