Mercurial > projects > dang
view ast/Exp.d @ 98:7f9240d4ddc1 new_gen
Fixed tests - forgot some stuff in codegen.
author | Anders Johnsen <skabet@gmail.com> |
---|---|
date | Tue, 06 May 2008 21:55:29 +0200 |
parents | 438e6ed4cda1 |
children | 7ff4bc2accf2 189c049cbfcc |
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.Scope, sema.DType; enum ExpType { Binary, Negate, Deref, IntegerLit, MemberReference, Index, Identifier, ArrayIdentifier, PointerIdentifier, AssignExp, CallExp, CastExp, } class Exp { this(ExpType expType, SLoc loc) { this.expType = expType; this.loc = loc; } /// Get the type of the expression DType type() { return null; } /// 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); } 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; } 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; } Exp simplify() { if(auto t = type.asStruct) { 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).setType(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(SLoc op, Exp identifier, Exp exp) { super(ExpType.AssignExp, op); this.identifier = identifier; this.exp = exp; } Exp 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, Eq, Ne, Lt, Le, Gt, Ge, Add, Sub, Mul, Div, Mod, } 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; } 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; } Exp 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; } Exp 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; } Exp 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 = substitute(t, "_", ""); } char[] get() { return name; } Exp simplify() { return this; } override DType type() { return DType.Int; } override SourceRange sourceRange() { return range; } 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; } 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.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.isArray()) return type.asArray().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); } Exp 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); } Exp simplify() { castType.simplify; exp.simplify; return this; } override SourceRange sourceRange() { return SourceRange(loc) + exp.sourceRange; } Identifier castType; Exp exp; } 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 ArrayIdentifier : Identifier { this(Identifier arrayOf, IntegerLit size) { super(ExpType.ArrayIdentifier, arrayOf.loc); this.arrayOf = arrayOf; this.size = Integer.parse(size.get); this.name = arrayOf.name; } override DType type() { return arrayOf.type.getAsArray(size); } Identifier arrayOf; int size; 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 DType type() { if (myType !is null) return myType; myType = env.find(this).type; return myType; } this(char[] name) { super(ExpType.Identifier, SLoc.Invalid); this.name = name; } char[] get() { return name; } char[] getMangled() { DType t = type; if(name == "main") return "main"; return "_D"~name~t.mangle; } 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; } void setType(DType myType) { this.myType = myType; } char[] name; private DType myType; }