# HG changeset patch # User Anders Johnsen # Date 1218378470 -7200 # Node ID 55ea834c867555ff741a0025444f14d2b6579e0f # Parent d442ce39917c06f9abc1dc0401b9c0c31a967ae7 Removed everything... diff -r d442ce39917c -r 55ea834c8675 LICENSE --- a/LICENSE Sun Aug 10 16:23:09 2008 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,25 +0,0 @@ -* Copyright (c) 2008, Anders Johnsen & Anders Halager -* All rights reserved. -* Redistribution and use in source and binary forms, with or without -* modification, are permitted provided that the following conditions are met: -* -* * Redistributions of source code must retain the above copyright -* notice, this list of conditions and the following disclaimer. -* * Redistributions in binary form must reproduce the above copyright -* notice, this list of conditions and the following disclaimer in the -* documentation and/or other materials provided with the distribution. -* * Neither the name of the nor the -* names of its contributors may be used to endorse or promote products -* derived from this software without specific prior written permission. -* -* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND ANY -* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -* DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY -* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND -* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - diff -r d442ce39917c -r 55ea834c8675 ast/Decl.d --- a/ast/Decl.d Sun Aug 10 16:23:09 2008 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,323 +0,0 @@ -module ast.Decl; - -import ast.Exp, - ast.Stmt; - -import lexer.Token; - -import tango.io.Stdout; - -import sema.Scope, - sema.Symbol, - sema.DType, - sema.VC, - basic.SmallArray, - basic.Attribute; - -enum DeclType -{ - VarDecl, - DummyDecl, - ImportDecl, - FuncDecl, - StructDecl, - ClassDecl, - InterfaceDecl, - AliasDecl, -} - -class Decl -{ - this(DeclType declType) - { - this.declType = declType; - } - - void simplify() - { - } - - void verify(VC vc) - { - } - - DType type() - { - if (sym !is null) - return sym.type; - return null; - } - - Identifier getIdentifier() - { - switch(declType) - { - case DeclType.VarDecl: - return (cast(VarDecl)this).identifier; - case DeclType.FuncDecl: - return (cast(FuncDecl)this).identifier; - default: - assert(0, "Invalid DeclType for getting a identifier"); - } - } - - DeclType declType; - Scope env; - Symbol sym; - Attribute att; -} - -class DummyDecl : Decl -{ - this() - { - super(DeclType.DummyDecl); - } -} - -class VarDecl : Decl -{ - this(IdentifierTypeExp type, Identifier identifier, - Exp e = null) - { - super(DeclType.VarDecl); - this.varType = type; - this.identifier = identifier; - this.init = e; - } - - override DType type() - { - return env.findType(varType.get); - } - - Identifier varType, identifier; - Exp init; -} - -class ImportDecl : Decl -{ - this() - { - super(DeclType.ImportDecl); - } - - char[] get() - { - char[] res; - foreach(i ; packages) - res ~= i.get ~ "."; - res ~= name.get; - return res; - } - - bool isStatic = false; - - Identifier[] packages; - Identifier name; - Identifier aliasedName; - - Identifier[2][] explicitSymbols; -} - -class FuncDecl : Decl -{ - this(IdentifierTypeExp type, Identifier identifier) - { - super(DeclType.FuncDecl); - this.returnType = type; - this.identifier = identifier; - } - - void addParam(IdentifierTypeExp type, Identifier name = null) - { - funcArgs ~= new VarDecl(type, name, null); - } - - void setBody(CompoundStatement stmts) - { - statements = stmts.statements; - emptyFunction = false; - } - - void simplify() - { - /* - if(auto t = env.find(identifier).type.asFunction()) - { - if(auto s = cast(DStruct)t.returnType) - { - VarDecl[] funcArgs; - auto i = new Identifier("ret.val"); - i.env = env; - i.env.add(i); - i.env.find(i).setType( s ); - auto var = new VarDecl(returnType, i); - var.env = env; - funcArgs ~= var; - funcArgs ~= this.funcArgs; - this.funcArgs = funcArgs; - t.returnType = DType.Void; - this.returnType = new Identifier("void"); - env.find(identifier).setType(t); - sret = true; - - myType = null; - } - } - */ - - foreach (funcArg; funcArgs) - funcArg.simplify(); - foreach (stmt; statements) - stmt.simplify(); - } - - override void verify(VC vc) - { - foreach (stmt; statements) - stmt.verify(vc); - } - - override DFunction type() - { - if (myType !is null) - return myType; - - auto t = new DFunction(identifier); - if ( identifier.get == "this" ) - t.returnType = DType.Void; - else - t.returnType = env.findType(returnType.get); - SmallArray!(DType) array; - foreach (a; funcArgs) - array ~= a.type(); - t.params = array.safe(); - t.firstParamIsReturnValue = this.sret; - myType = t; - return myType; - } - - Identifier returnType, identifier; - VarDecl[] funcArgs; - Stmt[] statements; - bool sret = false; - bool emptyFunction = true; - private DFunction myType; -} - -class StructDecl : Decl -{ - this(Identifier identifier) - { - super(DeclType.StructDecl); - this.identifier = identifier; - } - - void addMember(Decl decl) - { - decls ~= decl; - } - - void simplify() - { - } - - override void verify(VC vc) - { - foreach (decl; decls) - decl.verify(vc); - } - - override DType type() - { - return env.findType(identifier.get); - } - - Identifier identifier; - Decl[] decls; - private DType myType; -} - -class ClassDecl : Decl -{ - this(Identifier identifier) - { - super(DeclType.ClassDecl); - this.identifier = identifier; - - auto name = new Identifier(identifier.loc, "__vptr"); - auto type = new IdentifierTypeExp(identifier.loc, "byte"); - auto p_type = new PointerTypeExp(type); - decls ~= new VarDecl(p_type, name, null); - } - - void addMember(Decl decl) - { - decls ~= decl; - } - - void addBaseClass(Identifier identifier) - { - baseClasses ~= identifier; - } - - void simplify() - { - } - - override DType type() - { - return env.findType(identifier.get); - } - - Identifier identifier; - Identifier[] baseClasses; - Decl[] decls; - private DType myType; -} - -class InterfaceDecl : Decl -{ - this(Identifier identifier) - { - super(DeclType.InterfaceDecl); - this.identifier = identifier; - } - - void addMember(Decl decl) - { - decls ~= decl; - } - - void addBaseClass(Identifier identifier) - { - baseClasses ~= identifier; - } - - void simplify() - { - } - - override DType type() - { - return env.findType(identifier.get); - } - - Identifier identifier; - Identifier[] baseClasses; - Decl[] decls; - private DType myType; -} - -class AliasDecl : Decl -{ - this(Decl decl) - { - super(DeclType.AliasDecl); - this.decl = decl; - } - - Decl decl; -} - diff -r d442ce39917c -r 55ea834c8675 ast/Exp.d --- a/ast/Exp.d Sun Aug 10 16:23:09 2008 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,612 +0,0 @@ -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; -} - diff -r d442ce39917c -r 55ea834c8675 ast/Module.d --- a/ast/Module.d Sun Aug 10 16:23:09 2008 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,65 +0,0 @@ -module ast.Module; - -import sema.Scope, - sema.VC, - sema.Symbol; - -import ast.Decl; - -class Module -{ - this(char[] moduleName) - { - this.moduleName = moduleName; - } - - void addDecl(Decl decl) - { - if(!decl) - return; - switch(decl.declType) - { - case DeclType.FuncDecl: - functions ~= cast(FuncDecl)decl; - break; - case DeclType.VarDecl: - vars ~= cast(VarDecl)decl; - break; - case DeclType.StructDecl: - structs ~= cast(StructDecl)decl; - break; - case DeclType.ClassDecl: - classes ~= cast(ClassDecl)decl; - break; - case DeclType.InterfaceDecl: - interfaces ~= cast(InterfaceDecl)decl; - break; - case DeclType.AliasDecl: - aliases ~= cast(AliasDecl)decl; - break; - default: - assert(0, "DeclType not implemented"); - } - decls ~= decl; - } - - void verify(VC vc) - { - foreach (decl; decls) - decl.verify(vc); - } - - VarDecl[] vars; - FuncDecl[] functions; - StructDecl[] structs; - ClassDecl[] classes; - InterfaceDecl[] interfaces; - AliasDecl[] aliases; - Decl[] decls; - - char[] moduleName; - Scope env; - Symbol symbol; - bool outputModule = true; -} - diff -r d442ce39917c -r 55ea834c8675 ast/Stmt.d --- a/ast/Stmt.d Sun Aug 10 16:23:09 2008 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,292 +0,0 @@ -module ast.Stmt; - -import Array = tango.core.Array, - Integer = tango.text.convert.Integer, - tango.io.Stdout; - -import ast.Exp, - ast.Decl; - -import sema.Scope, - sema.VC, - basic.Message, - basic.SourceLocation; - -enum StmtType -{ - Stmt, - Compound, - Decl, - Exp, - Return, - If, - While, - For, - Switch, -} - -abstract class Stmt -{ - this(StmtType stmtType = StmtType.Stmt) - { - this.stmtType = stmtType; - } - - void simplify() - { - } - - void verify(VC vc) {} - - /// The "main" location of the expression. - SourceLocation loc; - - /// Return the starting location of this statement - SourceLocation startLoc() { return loc; } - - /// Get the full extents of the expression - SourceRange sourceRange() { return SourceRange(loc, loc + 1); } - - StmtType stmtType; - Scope env; - int stmtIndex; -} - -class CompoundStatement : Stmt -{ - this(Stmt[] stmts) - { - super(StmtType.Compound); - this.statements = stmts; - } - - override void simplify() - { - foreach (stmt; statements ) - stmt.simplify(); - } - - Stmt[] statements; -} - -class ReturnStmt : Stmt -{ - this() - { - super(StmtType.Return); - } - - // Needed? - override void simplify() - { - FuncDecl f = env.parentFunction; - if (exp) - exp = exp.simplify(); - if (f !is null && f.sret) - { - auto i = new Identifier("ret.val"); - i.env = f.env; - auto ass = new AssignExp(SLoc.Invalid, BinaryExp.Operator.Assign, i, exp); - ass.env = f.env; - auto assStmt = new ExpStmt(ass); - assStmt.env = f.env; - - Stmt[] stmts; - foreach(index, stmt ; f.statements) - { - if(stmtIndex == index) - stmts ~= assStmt; - - stmts ~= stmt; - } - f.statements = stmts; - exp = null; - } - } - - public Exp exp; -} - -class DeclStmt : Stmt -{ - this(Decl decl) - { - super(StmtType.Decl); - this.decl = decl; - } - - override void simplify() - { - decl.simplify(); - } - - public Decl decl; -} - -class ExpStmt : Stmt -{ - this(Exp exp) - { - super(StmtType.Exp); - this.exp = exp; - } - - override void simplify() - { - exp = exp.simplify(); - } - - public Exp exp; -} - -class IfStmt : Stmt -{ - this(Exp cond, Stmt then, Stmt el = null) - { - super(StmtType.If); - this.cond = cond; - this.then_body = then; - this.else_body = el; - } - - override void simplify() - { - cond = cond.simplify(); - then_body.simplify(); - if (else_body) - else_body.simplify(); - } - - Exp cond; - Stmt then_body; - Stmt else_body; -} - -class WhileStmt : Stmt -{ - this(Exp cond, Stmt stmts) - { - super(StmtType.While); - this.cond = cond; - this.whileBody = stmts; - } - - override void simplify() - { - cond = cond.simplify(); - whileBody.simplify(); - } - - Exp cond; - Stmt whileBody; -} - -class ForStmt : Stmt -{ - this(Stmt init, Exp cond, Exp incre, Stmt stmts) - { - super(StmtType.For); - this.init = init; - this.cond = cond; - this.incre = incre; - this.forBody = stmts; - } - - override void simplify() - { - if (cond) - cond = cond.simplify(); - forBody.simplify(); - } - - Exp cond, incre; - Stmt init, forBody; -} - -class SwitchStmt : Stmt -{ - this(SourceLocation loc, Exp target) - { - super(StmtType.Switch); - cond = target; - this.loc = loc; - } - - void addCase(SourceLocation _case, Exp[] values, Stmt[] stmts) - { - cases ~= Case(_case, values, stmts); - } - - void setDefault(SourceLocation _default, Stmt[] stmts) - { - if (defaultBlock !is null) - extraDefaultBlocks = true; - - defaultBlock = stmts; - defaultLoc = _default; - if (cases.length > 0) - cases[$ - 1].followedByDefault = true; - } - - override void simplify() - { - cond = cond.simplify(); - foreach ( stmt ; defaultBlock ) - stmt.simplify(); - foreach ( c ; cases ) - foreach ( stmt ; c.stmts ) - stmt.simplify(); - } - - override void verify(VC vc) - { - if (extraDefaultBlocks) - vc.msg.report(MultipleDefaults, defaultLoc); - - if (cases.length == 0) - return; - - scope long[] all_values; - foreach (ref Case; cases) - { - long[] new_values; - foreach (exp; Case.values) - if (auto lit = cast(IntegerLit)exp) - new_values ~= Integer.parse(lit.get); - else - // We flag all non-literals and ignore them - vc.msg.report(InvalidCaseValue, exp.loc); - Case.values_converted = new_values; - all_values ~= new_values; - } - - Array.sort(all_values); - char[][] overlapping; - size_t i = 0; - while ((i = Array.findAdj(all_values)) < all_values.length - && all_values.length > 0) - { - overlapping ~= Integer.toString(all_values[i]); - auto similar = Array.count(all_values, all_values[i]); - all_values = all_values[i + similar .. $]; - } - if (overlapping.length > 0) - vc.msg.report(OverlappingCases, loc).arg(overlapping); - } - - Exp cond; - Case[] cases; - Stmt[] defaultBlock; - private bool extraDefaultBlocks = false; - private SourceLocation defaultLoc; - - struct Case - { - SourceLocation caseLoc; - Exp[] values; - Stmt[] stmts; - long[] values_converted; - bool followedByDefault = false; - } -} - diff -r d442ce39917c -r 55ea834c8675 basic/Attribute.d --- a/basic/Attribute.d Sun Aug 10 16:23:09 2008 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,128 +0,0 @@ -module basic.Attribute; - -import tango.core.BitManip; -import Integer = tango.text.convert.Integer; - -import tango.io.Stdout; - -enum Protection : uint -{ - Private = 1<<0, - Public = 1<<1, - Package = 1<<2, - Protected = 1<<3, - Export = 1<<4, -} - -enum Extern : uint -{ - C = 1<<12, - CPlusPlus = 1<<13, - D = 1<<14, - Windows = 1<<15, - Pascal = 1<<16, - System = 1<<17, -} - -struct Attribute -{ - - void setProtection(Protection p) - { - att &= 0xFFFFFFE0; - att |= p; - } - - Protection getProtection() - { - Protection p = Protection.Public; - switch(bsf(0xF0000000 | att)) - { - case 0: - p = Protection.Private; - break; - case 1: - p = Protection.Public; - break; - case 2: - p = Protection.Package; - break; - case 3: - p = Protection.Protected; - break; - case 4: - p = Protection.Export; - break; - default: - break; - } - return p; - } - - void setExtern(Extern e) - { - att &= 0xFF7C0FFF; - att |= e; - } - - Extern getExtern() - { - Extern e = Extern.D; - switch(bsf(0xF0000000 | att >> 12)) - { - case 0: - e = Extern.C; - break; - case 1: - e = Extern.CPlusPlus; - break; - case 2: - e = Extern.D; - break; - case 3: - e = Extern.Windows; - break; - case 4: - e = Extern.Pascal; - break; - case 5: - e = Extern.System; - break; - default: - break; - } - return e; - } - - void setStatic() { att |= Static; } - bool getStatic() { return att & Static ? true : false; } - void setFinal() { att |= Final; } - bool getFinal() { return att & Final ? true : false; } - void setConst() { att |= Const; } - bool getConst() { return att & Const ? true : false; } - void setAbstract() { att |= Abstract; } - bool getAbstract() { return att & Abstract ? true : false; } - void setOverride() { att |= Override; } - bool getOverride() { return att & Override ? true : false; } - void setDeprecated(){ att |= Deprecated; } - bool getDeprecated(){ return att & Deprecated ? true : false; } - void setAuto() { att |= Auto; } - bool getAuto() { return att & Auto ? true : false; } - - char[] toString() - { - return Integer.toString(att); - } - -private: - uint att; - - - static const uint Static = 1<<5; - static const uint Final = 1<<6; - static const uint Const = 1<<7; - static const uint Abstract = 1<<8; - static const uint Override = 1<<9; - static const uint Deprecated = 1<<10; - static const uint Auto = 1<<11; -} diff -r d442ce39917c -r 55ea834c8675 basic/LiteralParsing.d --- a/basic/LiteralParsing.d Sun Aug 10 16:23:09 2008 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,900 +0,0 @@ -module basic.LiteralParsing; - -import basic.SourceLocation, - basic.Message, - basic.conv; - -import tango.io.Stdout, - tango.core.BitManip, - Integer = tango.text.convert.Integer, - Utf = tango.text.convert.Utf, - tango.text.Util; - -enum StringType -{ - Char, - WChar, - DChar -} - -enum NumberType -{ - Int, - UInt, - Long, - ULong, - Float, - Double, - Real -} - -struct String -{ - StringType type; - ubyte[] data; -} - -struct Number -{ - NumberType type; - ulong integer; - real floating; -} - -private struct EscapeReturn -{ - ubyte[] data; - int length; -} - -private struct NumberReturn -{ - char[] data; - int length; -} - -Number parseNumber(char[] str, SourceLocation loc, MessageHandler messages) -{ - Number num; - - switch(str[0]) - { - case '0': - case '1': - case '2': - case '3': - case '4': - case '5': - case '6': - case '7': - case '8': - case '9': - if(str.contains('.') || str.contains('e') || str.contains('E')) - { - auto n = parseRealNumber(str, loc, messages); - - try - { - num.floating = toReal(n.data); - num.type = NumberType.Double; - } - catch(Exception e) - { - num.floating = real.init; - messages.report(FloatingToLarge, loc, loc + n.length - 1); - } - - if(num.floating > double.max) - num.type = NumberType.Real; - } - else - { - auto n = parseDecimalDigits(str, loc, messages); - - try - { - num.integer = toUlong(n.data); - } - catch(Exception e) - { - num.integer = 0; - messages.report(IntegerToLarge, loc, loc + n.length - 1); - } - - if(num.integer > uint.max) - num.type = NumberType.Long; - if(num.integer > long.max) - num.type = NumberType.ULong; - } - break; - default: - messages.report(InvalidStartInteger, loc, loc+1); - } - -// printNumber(str, num); - return num; -} - -NumberReturn parseDecimalDigits(char[] str, SourceLocation loc, MessageHandler messages) -{ - int i = 0; - - char[] number; - - bool end; - while(!end) - { - switch(str[i]) - { - case '0': - case '1': - case '2': - case '3': - case '4': - case '5': - case '6': - case '7': - case '8': - case '9': - number ~= str[i]; - break; - case '_': - break; - default: - end = true; - } - i++; - if(str.length == i) - { - end = true; - i++; - } - } - - NumberReturn res; - res.length = i - 1; - res.data = number; - - return res; -} - -NumberReturn parseRealNumber(char[] str, SourceLocation loc, MessageHandler messages) -{ - int i = 0; - - bool dot, e; - char[] number; - - NumberReturn num; - - bool end; - while(!end) - { - switch(str[i]) - { - case '0': - case '1': - case '2': - case '3': - case '4': - case '5': - case '6': - case '7': - case '8': - case '9': - case '_': - auto n = parseDecimalDigits(str[i..$], loc, messages); - number ~= n.data; - i += n.length; - break; - case '.': - if(e) - messages.report(FloatingDotInE, loc + i, loc + i + 1); - else if(dot) - messages.report(OnlyOneDotFloating, loc + i, loc + i + 1); - else - { - dot = true; - number ~= str[i]; - } - i++; - break; - case 'e': - case 'E': - if(e) - messages.report(OnlyOneEFloating, loc + i, loc + i + 1); - else - { - e = true; - number ~= str[i]; - } - i++; - break; - case '+': - case '-': - if (number[$-1] != 'e' && - number[$-1] != 'E') - messages.report(FloatingBadLocation, loc + i, loc + i + 1) - .arg(str[i]); - else - number ~= str[i]; - i++; - break; - default: - end = true; - } - if(str.length == i) - end = true; - } - - if (number[$-1] == '+' || - number[$-1] == '-' || - number[$-1] == 'e' || - number[$-1] == 'E') - { - messages.report(FloatingInvalidEnd, loc + i - 1, loc + i); - return num; - } - - num.data = number; - num.length = i; - - return num; -} - - -void printNumber(char[] str, Number num) -{ - Stdout(str)(" have become").newline; - switch(num.type) - { - case NumberType.Int: - Stdout(num.integer)(" of type ")("int"); - break; - case NumberType.UInt: - Stdout(num.integer)(" of type ")("uint"); - break; - case NumberType.Long: - Stdout(num.integer)(" of type ")("long"); - break; - case NumberType.ULong: - Stdout(num.integer)(" of type ")("ulong"); - break; - case NumberType.Float: - Stdout(num.floating)(" of type ")("float"); - break; - case NumberType.Double: - Stdout(num.floating)(" of type ")("double"); - break; - case NumberType.Real: - Stdout(num.floating)(" of type ")("real"); - break; - } - Stdout().newline; -} - - -String parseString(char[] str, SourceLocation loc, MessageHandler messages) -{ - String strBuf; - strBuf.data.length = str.length; - strBuf.data.length = 0; - - switch(str[0]) - { - case 'r': - strBuf = parseWysiwygString(str[1..$], strBuf); - break; - case '`': - strBuf = parseWysiwygString(str, strBuf); - break; - case '"': - strBuf = parseDoubleQuotedString(str, strBuf, loc, messages); - break; - case 'x': - strBuf = parseHexString(str[1..$], strBuf, loc + 1, messages); - break; - default: - messages.report(InvalidStrPrefix, loc, loc + 1); - - } - -// printString(str, strBuf); - - return strBuf; -} - -String parseHexString(char[] str, String strBuf, - SourceLocation loc, MessageHandler messages) -{ - int i = 1; // first char is " - char[] hex = "0123456789abcdefABCDEF"; - char[] whitespace = "\r\n "; - char[] hexBuf; - - while(str[i] != '"') - { - if(hex.contains(str[i])) - { - hexBuf ~= str[i]; - if(hexBuf.length == 2) - { - strBuf.data ~= Integer.toInt(hexBuf, 16); - hexBuf.length = 0; - } - } - else if(!whitespace.contains(str[i])) - messages.report(InvalidHexStrChar, loc + i, loc + i + 1); - - i++; - } - - - - return strBuf; -} -// - -String parseDoubleQuotedString(char[] str, String strBuf, - SourceLocation loc, MessageHandler messages) -{ - int i = 1; // first char is " - - while(str[i] != '"') - { - switch(str[i]) - { - case '\\': // EscapeSequence - EscapeReturn res = parseEscapeSequence(str[i..$], loc + i, messages); - strBuf.data ~= res.data; - i += res.length; - break; - default: - strBuf.data ~= str[i]; - i++; - } - if(i >= str.length) - break; - } - - if(str.length > i + 1) // Then we have a postfix. Lexer makes sure this is c, w or d. - switch(str[i+1]) - { - case 'c': - break; - case 'w': - strBuf.data = cast(ubyte[])Utf.toString16(cast(char[])strBuf.data); - strBuf.type = StringType.WChar; - break; - case 'd': - strBuf.data = cast(ubyte[])Utf.toString32(cast(char[])strBuf.data); - strBuf.type = StringType.DChar; - break; - } - - - return strBuf; -} - -EscapeReturn parseEscapeSequence(char[] str, - SourceLocation loc, MessageHandler messages) -{ - EscapeReturn res; - - switch(str[1]) - { - case '\'': - res.length = 2; - res.data ~= '\''; - break; - case '"': - res.length = 2; - res.data ~= '\"'; - break; - case '?': - res.length = 2; - res.data ~= '\?'; - break; - case '\\': - res.length = 2; - res.data ~= '\\'; - break; - case 'a': - res.length = 2; - res.data ~= '\a'; - break; - case 'b': - res.length = 2; - res.data ~= '\b'; - break; - case 'f': - res.length = 2; - res.data ~= '\f'; - break; - case 'n': - res.length = 2; - res.data ~= '\n'; - break; - case 'r': - res.length = 2; - res.data ~= '\r'; - break; - case 't': - res.length = 2; - res.data ~= '\t'; - break; - case 'v': - res.length = 2; - res.data ~= '\v'; - break; - case 'x': - char[] hex = "0123456789abcdefABCDEF"; - char[] hexBuf; - if(str.length - 1 >= 4) - { - for(int i = 2; i < 4; i++) - if(hex.contains(str[i])) - hexBuf ~= str[i]; - else - messages.report(StringHexInvalid, loc + i, loc + i + 1) - .arg(Integer.toString(i-1)) - .arg(Integer.toString(2)); - res.length = 4; - } - else - { - messages.report(StringShortEscape, loc, loc + str.length); - res.length = str.length - 1; - } - res.data ~= cast(ubyte)Integer.toInt(hexBuf, 16); - break; - case 'u': - char[] hex = "0123456789abcdefABCDEF"; - char[] hexBuf; - if(str.length - 1 >= 6) - { - for(int i = 2; i < 6; i++) - if(hex.contains(str[i])) - hexBuf ~= str[i]; - else - messages.report(StringHexInvalid, loc + i, loc + i + 1) - .arg(Integer.toString(i-1)) - .arg(Integer.toString(6)); - res.length = 6; - } - else - { - messages.report(StringShortEscape, loc, loc + str.length); - res.length = str.length - 1; - } - uint i = Integer.toLong(hexBuf, 16); - if(!isValidUtf8(i)) - messages.report(InvalidUtf8Hex, loc, loc+6); - else - res.data ~= parseToUtf8(i); - break; - case 'U': - char[] hex = "0123456789abcdefABCDEF"; - char[] hexBuf; - if(str.length - 1 >= 10) - { - for(int i = 2; i < 10; i++) - if(hex.contains(str[i])) - hexBuf ~= str[i]; - else - messages.report(StringHexInvalid, loc + i, loc + i + 1) - .arg(Integer.toString(i-1)) - .arg(Integer.toString(10)); - res.length = 10; - } - else - { - messages.report(StringShortEscape, loc, loc + str.length); - res.length = str.length - 1; - } - uint i = Integer.toLong(hexBuf, 16); - if(!isValidUtf8(i)) - messages.report(InvalidUtf8Hex, loc, loc+10); - else - res.data ~= parseToUtf8(i); - break; - case '0': - case '1': - case '2': - case '3': - case '4': - case '5': - case '6': - case '7': - char[] oct = "01234567"; - char[] octBuf; - octBuf ~= str[1]; - res.length = 2; - for(int i = 2; i < 4; i++) - if(oct.contains(str[i])) - { - octBuf ~= str[i]; - res.length += 1; - } - else - break; - - uint i = Integer.toLong(octBuf, 8); - res.data ~= i; - break; - case '&': - int i = 2; - char[] s; - while(str[i] != ';') - { - if(str[i] == '"') - { - messages.report(NoCharEntityEnd, loc+i, loc+i+1); - res.length = 2; - break; - } - s ~= str[i]; - i++; - } - - if ( s in characterEntities ) - { - res.data ~= parseToUtf8(characterEntities[s]); - } - else - messages.report(InvalidCharEntity, loc + 2, loc + i); - - res.length = i + 1; // remember the ; - - break; - default: - messages.report(InvalidStrEscape, loc, loc + 2); - res.length += 2; - } - - return res; -} - -String parseWysiwygString(char[] str, String strBuf) -{ - char start = str[0]; - - int i = 1; - - while(str[i] != start) - { - strBuf.data ~= cast(ubyte)str[i]; - i++; - } - return strBuf; -} - -ubyte[] parseToUtf8(uint i) -{ - if(i <= 0x00007F) - return [cast(ubyte)i]; - else if(i <= 0x0007FF) - { - ubyte a = (i << 26) >> 26; - bts(cast(uint*)&a, 7); - ubyte b = (i << 19) >> 25; - bts(cast(uint*)&b, 7); - bts(cast(uint*)&b, 6); - return [b,a]; - } - else if(i <= 0x00FFFF) - { - ubyte a = (i << 26) >> 26; - bts(cast(uint*)&a, 7); - ubyte b = (i << 20) >> 26; - bts(cast(uint*)&b, 7); - ubyte c = (i << 16) >> 28; - bts(cast(uint*)&c, 7); - bts(cast(uint*)&c, 6); - bts(cast(uint*)&c, 5); - return [c,b,a]; - } - else if(i <= 0x10FFFF) - { - ubyte a = (i << 26) >> 26; - bts(cast(uint*)&a, 7); - ubyte b = (i << 20) >> 26; - bts(cast(uint*)&b, 7); - ubyte c = (i << 14) >> 26; - bts(cast(uint*)&c, 7); - ubyte d = (i << 11) >> 29; - bts(cast(uint*)&d, 7); - bts(cast(uint*)&d, 6); - bts(cast(uint*)&d, 5); - bts(cast(uint*)&d, 4); - return [d,c,b,a]; - } -} - -bool isValidUtf8(uint i) -{ - if(i <= 0x10FFFF) - return true; - return false; -} - -void printString(char[] str, String strBuf) -{ - char[] s; - switch(strBuf.type) - { - case StringType.Char: - Stdout(str)(" have become").newline() - (cast(char[])strBuf.data).newline; - break; - case StringType.WChar: - Stdout(str)(" have become").newline() - (cast(wchar[])strBuf.data).newline; - break; - case StringType.DChar: - Stdout(str)(" have become").newline() - (cast(dchar[])strBuf.data).newline; - break; - } -} - -static ushort[char[]] characterEntities; - -static this() -{ - characterEntities = - [ - "quot"[]: 34, - "amp": 38, - "lt": 60, - "gt": 62, - "OElig": 338, - "oelig": 339, - "Scaron": 352, - "scaron": 353, - "Yuml": 376, - "circ": 710, - "tilde": 732, - "ensp": 8194, - "emsp": 8195, - "thinsp": 8201, - "zwnj": 8204, - "zwj": 8205, - "lrm": 8206, - "rlm": 8207, - "ndash": 8211, - "mdash": 8212, - "lsquo": 8216, - "rsquo": 8217, - "sbquo": 8218, - "ldquo": 8220, - "rdquo": 8221, - "bdquo": 8222, - "dagger": 8224, - "Dagger": 8225, - "permil": 8240, - "lsaquo": 8249, - "rsaquo": 8250, - "euro": 8364, - "nbsp": 160, - "iexcl": 161, - "cent": 162, - "pound": 163, - "curren": 164, - "yen": 165, - "brvbar": 166, - "sect": 167, - "uml": 168, - "copy": 169, - "ordf": 170, - "laquo": 171, - "not": 172, - "shy": 173, - "reg": 174, - "macr": 175, - "deg": 176, - "plusmn": 177, - "sup2": 178, - "sup3": 179, - "acute": 180, - "micro": 181, - "para": 182, - "middot": 183, - "cedil": 184, - "sup1": 185, - "ordm": 186, - "raquo": 187, - "frac14": 188, - "frac12": 189, - "frac34": 190, - "iquest": 191, - "Agrave": 192, - "Aacute": 193, - "Acirc": 194, - "Atilde": 195, - "Auml": 196, - "Aring": 197, - "AElig": 198, - "Ccedil": 199, - "Egrave": 200, - "Eacute": 201, - "Ecirc": 202, - "Euml": 203, - "Igrave": 204, - "Iacute": 205, - "Icirc": 206, - "Iuml": 207, - "ETH": 208, - "Ntilde": 209, - "Ograve": 210, - "Oacute": 211, - "Ocirc": 212, - "Otilde": 213, - "Ouml": 214, - "times": 215, - "Oslash": 216, - "Ugrave": 217, - "Uacute": 218, - "Ucirc": 219, - "Uuml": 220, - "Yacute": 221, - "THORN": 222, - "szlig": 223, - "agrave": 224, - "aacute": 225, - "acirc": 226, - "atilde": 227, - "auml": 228, - "aring": 229, - "aelig": 230, - "ccedil": 231, - "egrave": 232, - "eacute": 233, - "ecirc": 234, - "euml": 235, - "igrave": 236, - "iacute": 237, - "icirc": 238, - "iuml": 239, - "eth": 240, - "ntilde": 241, - "ograve": 242, - "oacute": 243, - "ocirc": 244, - "otilde": 245, - "ouml": 246, - "divide": 247, - "oslash": 248, - "ugrave": 249, - "uacute": 250, - "ucirc": 251, - "uuml": 252, - "yacute": 253, - "thorn": 254, - "yuml": 255, - "fnof": 402, - "Alpha": 913, - "Beta": 914, - "Gamma": 915, - "Delta": 916, - "Epsilon": 917, - "Zeta": 918, - "Eta": 919, - "Theta": 920, - "Iota": 921, - "Kappa": 922, - "Lambda": 923, - "Mu": 924, - "Nu": 925, - "Xi": 926, - "Omicron": 927, - "Pi": 928, - "Rho": 929, - "Sigma": 931, - "Tau": 932, - "Upsilon": 933, - "Phi": 934, - "Chi": 935, - "Psi": 936, - "Omega": 937, - "alpha": 945, - "beta": 946, - "gamma": 947, - "delta": 948, - "epsilon": 949, - "zeta": 950, - "eta": 951, - "theta": 952, - "iota": 953, - "kappa": 954, - "lambda": 955, - "mu": 956, - "nu": 957, - "xi": 958, - "omicron": 959, - "pi": 960, - "rho": 961, - "sigmaf": 962, - "sigma": 963, - "tau": 964, - "upsilon": 965, - "phi": 966, - "chi": 967, - "psi": 968, - "omega": 969, - "thetasym": 977, - "upsih": 978, - "piv": 982, - "bull": 8226, - "hellip": 8230, - "prime": 8242, - "Prime": 8243, - "oline": 8254, - "frasl": 8260, - "weierp": 8472, - "image": 8465, - "real": 8476, - "trade": 8482, - "alefsym": 8501, - "larr": 8592, - "uarr": 8593, - "rarr": 8594, - "darr": 8595, - "harr": 8596, - "crarr": 8629, - "lArr": 8656, - "uArr": 8657, - "rArr": 8658, - "dArr": 8659, - "hArr": 8660, - "forall": 8704, - "part": 8706, - "exist": 8707, - "empty": 8709, - "nabla": 8711, - "isin": 8712, - "notin": 8713, - "ni": 8715, - "prod": 8719, - "sum": 8721, - "minus": 8722, - "lowast": 8727, - "radic": 8730, - "prop": 8733, - "infin": 8734, - "ang": 8736, - "and": 8743, - "or": 8744, - "cap": 8745, - "cup": 8746, - "int": 8747, - "there4": 8756, - "sim": 8764, - "cong": 8773, - "asymp": 8776, - "ne": 8800, - "equiv": 8801, - "le": 8804, - "ge": 8805, - "sub": 8834, - "sup": 8835, - "nsub": 8836, - "sube": 8838, - "supe": 8839, - "oplus": 8853, - "otimes": 8855, - "perp": 8869, - "sdot": 8901, - "lceil": 8968, - "rceil": 8969, - "lfloor": 8970, - "rfloor": 8971, - "lang": 9001, - "rang": 9002, - "loz": 9674, - "spades": 9824, - "clubs": 9827, - "hearts": 9829, - "diams": 9830 - ]; -} diff -r d442ce39917c -r 55ea834c8675 basic/Message.d --- a/basic/Message.d Sun Aug 10 16:23:09 2008 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,229 +0,0 @@ -module basic.Message; - -import tango.core.Exception, - Array = tango.core.Array, - tango.io.Stdout, - tango.text.Util; - -import tango.stdc.stdlib; - -import llvm.type; - -import lexer.Token, - lexer.Lexer, - sema.DType; - -import basic.SourceLocation, - basic.SourceManager; - -public import basic.Messages; - -enum ExitLevel -{ - Normal = 1, - Lexer = 2, - Parser = 3, - Semantic = 3, -} - -class MessageHandler -{ -public: - - this(SourceManager src_mgr) - { - this.src_mgr = src_mgr; - } - - Message report(uint opcode, SLoc location) - { - Message m = new Message(opcode, location, src_mgr, this); - messages ~= m; - return m; - } - - Message report(uint opcode, SourceRange[] ranges, SourceLocation[] locs) - { - Message m = new Message(opcode, ranges, locs, src_mgr, this); - messages ~= m; - return m; - } - - Message report(uint opcode, SLoc location1, SLoc location2, SLoc location3 = SLoc.Invalid) - { - Message m = new Message(opcode, [SourceRange(location1, location2)][], [location3][], src_mgr, this); - messages ~= m; - return m; - } - - void checkErrors(ExitLevel exitlevel = ExitLevel.Normal) - { - if(messages.length == 0) - return; - - if(warnings) - checkWarnings; - foreach(m ; messages) - if(m.type == MessageType.Error) - { - Stdout(m).newline; - } - - exit(exitlevel); - } - - void checkWarnings() - { - foreach(m ; messages) - if(m.type == MessageType.Warning) - { - Stdout(m).newline; - } - } - - void showWarnings(bool value) - { - warnings = value; - } - -private: - Message[] messages; - SourceManager src_mgr; - bool warnings; -} - -class Message -{ - - this(int opcode, SLoc location, SourceManager src_mgr, MessageHandler msg_handler) - { - this.src_mgr = src_mgr; - this.interests ~= location; - args ~= Messages[opcode].message; - this.type = Messages[opcode].type; - this.msg_handler = msg_handler; - } - - this(int opcode, SourceRange[] locs, SLoc[] interests, - SourceManager src_mgr, MessageHandler msg_handler) - in - { - assert(locs.length + interests.length, "Atleast one location is requiret for a mark"); - } - body - { - this.src_mgr = src_mgr; - this.locs = locs; - this.interests = interests; - args ~= Messages[opcode].message; - this.type = Messages[opcode].type; - this.msg_handler = msg_handler; - haveEnd = true; - } - - char[] toString() - { - char[256] tmp = void; - char[] msg = layout(tmp, args); - - SLoc location; - if (interests.length) - location = interests[0]; - else - location = locs[0].begin; - - int len = 0; - if(!haveEnd) - { - Lexer l = new Lexer(interests[0], src_mgr, new MessageHandler(src_mgr)); - - Token t = l.next; - len = t.length; - } -// else - // len = end - location; - - if (src_mgr.getRawData(location).length > 0) - msg = src_mgr.getLocationAsString(location) ~ ": " ~ msg; - else - msg = msg.dup; - - - char[] line = src_mgr.getLine(location); - char[] marks = line.dup; - marks[] = ' '; - - foreach (s ; locs) - { - size_t p = src_mgr.getColumn(s.begin); - marks[p .. p + (s.end-s.begin)] = interests.length ? '~' : '^'; - } - - foreach (interest ; interests) - { - size_t i = src_mgr.getColumn(interest); - marks[i] = '^'; - } - - msg ~= "\n "; - msg ~= line; - msg ~= "\n "; - msg ~= marks; - - return msg; - } - - Message arg(char[] s) - { - if (args.length > 10) - throw new Exception("Sorry, errors only support up to 10 args"); - args ~= s; - return this; - } - - Message arg(char[][] s) - { - char[] res = s[0 .. $ - 1].join(", "); - if (s.length > 1) - res ~= " and "; - res ~= s[$ - 1]; - return arg(res); - } - - Message arg(char c) - { - return arg([c]); - } - - Message arg(DType[] types) - { - char[][] res; - foreach (type; types) - res ~= type.name(); - return arg(res); - } - - Message fatal(ExitLevel exitlevel = ExitLevel.Normal) - { - msg_handler.checkErrors(exitlevel); - return this; - } - - /* - Message loc(SLoc loc) - { - location = loc; - return this; - } - */ - - MessageType type; -private: - char[][] args; - SourceRange[] locs; - SLoc[] interests; - bool haveEnd; - SourceManager src_mgr; - MessageHandler msg_handler; - Token t; -} diff -r d442ce39917c -r 55ea834c8675 basic/Messages.d --- a/basic/Messages.d Sun Aug 10 16:23:09 2008 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,154 +0,0 @@ -module basic.Messages; - -enum : uint -{ - // Lex - InvalidSymbol, - InvalidIlligaleType, - UnexpectedEOFBlock, - OnlyOneDotFloating, - OnlyOneEFloating, - - // Parse - UnexpectedTokMulti, - UnexpectedTokSingle, - UnexpectedTok, - CaseValueMustBeInt, - UnexpectedBeginStmt, - UnexpectedTokType, - ExpectedIdAfterDot, - ExpectedExp, - ExpectedCastType, - InvalidDeclType, - InvalidType, - UnexpectedLinkType, - // - imports/module - ExpectedIdAfterPackage, - RenameMustBeSingleIdent, - UnexpectedEOF, - - - // sema - CannotFindModule, - InvalidImplicitCast, - UndefinedIdentifier, - UndefinedType, - MissingMember, - CannotRedeclare, - // - switch - MultipleDefaults, - OverlappingCases, - InvalidCaseValue, - NoConstructor, - NoMachingCon, - CandidateNr, - NoMethodByName, - NoMachingMethod, - CannotReassignSArray, - CanOnlyDerefPointers, - CannotCallMethod, - - // Strings - InvalidStrPrefix, - InvalidStrEscape, - InvalidUtf8Hex, - InvalidHexStrChar, - InvalidCharEntity, - NoCharEntityEnd, - StringShortEscape, - StringHexInvalid, - InvalidStartInteger, - IntegerToLarge, - FloatingToLarge, - FloatingInvalidEnd, - FloatingBadLocation, - FloatingDotInE, - - // Protection - CannotAccessPrivate, -} - -enum MessageType -{ - Warning, - Error, -} - -MessageEntry[uint] Messages; - -struct MessageEntry -{ - MessageType type; - char[] message; -} - -private alias MessageType.Error Err; -private alias MessageType.Warning War; -private alias MessageEntry E; -static this() -{ - Messages = [ - // lexing - UnexpectedEOFBlock : E(Err, "Unexpected end of file. Unclosed comment block"), - InvalidSymbol : E(Err, "Read invalid symbol: '%0'"), - OnlyOneDotFloating : E(Err, "Only one '.' is allowed in an floating number"), - OnlyOneEFloating : E(Err, "Only one E is allowed in an floating number"), - - // parsing - UnexpectedTokMulti : E(Err, "Unexpected token, got %0 expected one of %1"), - UnexpectedTokSingle : E(Err, "Unexpected token, got %0 expected %1"), - UnexpectedTok : E(Err, "Unexpected token %0"), - CaseValueMustBeInt : E(Err, "Cases can only be integer literals"), - UnexpectedBeginStmt : E(Err, "Unexpected begining of statement."), - UnexpectedTokType : E(Err, "Unexpected token in Type parsing. Got %0"), - ExpectedIdAfterDot : E(Err, "Expected identifier after '.'"), - ExpectedExp : E(Err, "Expected expression"), - ExpectedCastType : E(Err, "Expected cast type"), - InvalidDeclType : E(Err, "Invalid declaration type"), - InvalidType : E(Err, "Invalid type"), - ExpectedIdAfterPackage : E(Err, "Identifier expected following package"), - UnexpectedLinkType : E(Err, "Invalid linkage type. Only C, C++, D, Windows, Pascal and System is allowed"), - UnexpectedEOF : E(Err, "Unexpected EOF after '%0'"), - - // sema - CannotFindModule : E(Err, "Cannot find module '%0'"), - InvalidImplicitCast : E(Err, "Cannot make implicit cast between '%0' and '%1'"), - UndefinedIdentifier : E(Err, "Undefined identifier '%0'"), - UndefinedType : E(Err, "Undefined type '%0'"), - MissingMember : E(Err, "%0 %1 has no member %2"), - CannotRedeclare : E(Err, "Cannot redeclare '%0'"), - NoConstructor : E(Err, "No constructor avaible"), - NoMachingCon : E(Err, "No maching constructor. Candidates are:"), - CandidateNr : E(Err, "Candidate number %0"), - NoMethodByName : E(Err, "No method with that name"), - NoMachingMethod : E(Err, "No maching method. Candidates are:"), - // - switch - MultipleDefaults - : E(Err, "Switch statements can't have multiple defaults"), - OverlappingCases - : E(Err, "Can't have multiple cases with the same value." - " Values appearing in multiple cases: %0"), - InvalidCaseValue : E(Err, "Case values must be integers"), - CannotReassignSArray: E(Err, "Cannot reassign static arrays"), - CanOnlyDerefPointers: E(Err, "Can only deref pointers, not '%0'"), - CannotCallMethod : E(Err, "Cannot call a method of type '%0' with '%1'"), - - // literals - InvalidStrPrefix : E(Err, "Invalid string literal prefix"), - InvalidStrEscape : E(Err, "Invalid escape sequence"), - InvalidUtf8Hex : E(Err, "Invalid Utf8 hex char"), - NoCharEntityEnd : E(Err, "Character entity have no end, insert ';'"), - InvalidCharEntity : E(Err, "Invalid character entity"), - InvalidHexStrChar : E(Err, "Invalid character in hex string"), - StringShortEscape : E(Err, "String literal is to short for escape sequence"), - StringHexInvalid : E(Err, "Hex escape sequence have invalid digit at position %0 of %1"), - InvalidStartInteger : E(Err, "Invalid begining of number"), - IntegerToLarge : E(Err, "Integer is to large. Max size is 18446744073709551615"), - FloatingToLarge : E(Err, "Floating literal is to large"), - FloatingInvalidEnd : E(Err, "Floating literal have wrong ending"), - FloatingBadLocation : E(Err, "Bad location for '%0' in floting literal"), - FloatingDotInE : E(Err, "There cannot be a dot in the exponent of a floating literal"), - CannotAccessPrivate : E(Err, "Cannot access private member.") - ]; -} - diff -r d442ce39917c -r 55ea834c8675 basic/SmallArray.d --- a/basic/SmallArray.d Sun Aug 10 16:23:09 2008 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,119 +0,0 @@ -module basic.SmallArray; - -/** - This struct acts like a normal dynamic array, with one difference. - A size is given, which is how many elements are preallocated on the stack. - - Example: - -------- - SmallArray!(float, 4) array; - array ~= 1.0; - array ~= 2.0; - array ~= 3.0; - float[] three_floats = array[0 .. 3]; - // The slice gives a reference to the stack, remember to .dup - array ~= 4.0; - // not using the heap yet, but after the next line all values will have been - // copied to the heap. - array ~= 5.0; - -------- - - Compared to a normal dynamic array there is 8 bytes overhead (on 32 bit cpus) - and ofcourse size * T.sizeof bytes for the stack allocated array. - */ -struct SmallArray(T, ubyte size = 8) -{ - T[] opSlice(size_t low, size_t high) - { - assert(high <= len && low <= high, "Array index out of range"); - return ptr[low .. high]; - } - - T[] opSlice() - { - return ptr[0 .. len]; - } - alias opSlice unsafe; - - T[] safe() - { - if (len <= size) - return static_array[0 .. len].dup; - return array[0 .. len]; - } - - T[] opSliceAssign(T val, size_t low, size_t high) - { - assert(high <= len && low <= high, "Array index out of range"); - return ptr[low .. high] = val; - } - - T[] opSliceAssign(T val) - { - return ptr[0 .. len] = val; - } - - T opIndex(size_t index) - { - assert(index < len, "Array index out of range"); - return ptr[index]; - } - - T opIndexAssign(T val, size_t index) - { - assert(index < len, "Array index out of range"); - return ptr[index] = val; - } - - void opCatAssign(T val) - { - if (len < size) - static_array[len] = val; - else if (len == size) - { - T[] tmp = static_array[].dup; - array = tmp; - array ~= val; - } - else - array ~= val; - - ++len; - if (len <= size) - ptr = static_array.ptr; - else - ptr = array.ptr; - } - alias opCatAssign push; - - T pop() - { - assert(len > 0, "Can't remove from an empty array"); - return ptr[--len]; - } - - T peek() - { - assert(len > 0, "Array is empty"); - return ptr[len - 1]; - } - - size_t length() { return len; } - - static SmallArray opCall() - { - SmallArray array; - array.ptr = array.static_array.ptr; - return array; - } - -private: - T* ptr; - size_t len; - union - { - T[] array; - T[size] static_array; - } -} - diff -r d442ce39917c -r 55ea834c8675 basic/SourceLocation.d --- a/basic/SourceLocation.d Sun Aug 10 16:23:09 2008 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,157 +0,0 @@ -module basic.SourceLocation; - -import Integer = tango.text.convert.Integer; - -/// Shorter alias for SourceLocation -public alias SourceLocation SLoc; - -/// SourceLocation points to a place in some buffer -struct SourceLocation -{ - /// Returns true, if the location is from a real file - bool isReal() { return (val & 0x80_00_00_00) == 0; } - /// Returns true, if the location is not from a real file - bool isVirtual() { return (val & 0x80_00_00_00) != 0; } - - /// Check if this location is invalid or not - bool isValid() { return val != uint.max; } - /// ditto - bool isInvalid() { return val == uint.max; } - - /** - Extracts the file id. - - Warning: In release mode this may return junk, if the loc is not from a - file - **/ - uint fileID() { - assert(isValid, "Location is invalid"); - assert(isReal, "You can only extract fileID from a real location"); - // Here we can rely on two facts, first that the high bit is zero - // since its a real position, second that FileOffset is saved in the - // high end, so all we need is some shifting - return val >> Bits.FileOffset; - } - - /** - Extracts the offset into the "file". (actually in to the referenced - chunk) - - Warning: In release mode this may return junk, if the loc is not from a - file - **/ - uint fileOffset() { - assert(isValid, "Location is invalid"); - assert(isReal, "You can only extract fileOffset from real locations"); - // FileOffset is stored in the lower bits, so all that is needed is a - // binary and with all ones in the lower bits. - return val & (1 << Bits.FileOffset) - 1; - } - - /// Get a new location, placed n bytes after the given location - SourceLocation opAdd(int n) - { - SourceLocation res = *this; - res.val += n; - return res; - } - - /// Get a new location, placed n bytes before the given location - SourceLocation opSub(int n) - { - SourceLocation res = *this; - res.val -= n; - return res; - } - - /// Get the length between two location - int opSub(SourceLocation loc) - { - return val - loc.val; - } - - /// Creates a SourceLocation from a File ID - static SourceLocation fromFileID(uint fileID) - { - assert(fileID < Bits.MaxFileID, "To large fileID"); - SourceLocation res; - res.val = fileID << Bits.FileOffset; - return res; - } - - char[] toString() - { - return Integer.toString(val); - } - /** - Used for invalid/unknown locations. (also the default value, but this is - more explicit) - **/ - static const SourceLocation Invalid = {val: uint.max}; - -private: - /** - A SourceLocation consists of 1 bit, indicating real or virtual, meaning - if the location points to a file(real), a string mixin or has been - affected by #line(virtual). That information is saved in the most - significant bit. - The rest depends on which type we are dealing with. - Real: - 13 bits for a file identifier - 18 bits for offset into that "file" (one file may be split) - Virtual: - Unknown for now. Likely skewed toward more ids and some meta data - An invalid location is uint.max, this might happen by accident but its - unlikely. - **/ - uint val = uint.max; - - /** - This enum contains some constants that are useful for manipulating - SourceLocation's, like the size of various “members” of val. - **/ - static enum Bits { - /// Number of bits used for the offset into file buffers - FileOffset = 18, - /// Number of bits used to identify which file buffer this is from - FileID = 31 - FileOffset, - - /// Indicates how much can be indexed within one block(2^FileOffset) - MaxFileOffset = 1 << FileOffset, - MaxFileID = 1 << FileID, - } -} - -/// A simple pair used to describe a range in a buffer and not just a point. -struct SourceRange -{ - SourceLocation begin, end; - - static SourceRange opCall(SourceLocation loc) - { - return SourceRange(loc, loc + 1); - } - - static SourceRange opCall(SourceLocation begin, SourceLocation end) - { - SourceRange res; - res.begin = begin; - res.end = end; - return res; - } - - bool isValid() { return begin.isValid && end.isValid; } - bool isInvalid() { return begin.isInvalid || end.isInvalid; } - - bool isReal() { return begin.isReal && end.isReal; } - - /// Get a new range spanning both ranges - SourceRange opAdd(SourceRange that) - { - assert(this.isValid && that.isValid, "Invalid range"); - return SourceRange( - this.begin.val < that.begin.val? this.begin : that.begin, - this.end.val > that.end.val? this.end : that.end); - } -} - diff -r d442ce39917c -r 55ea834c8675 basic/SourceManager.d --- a/basic/SourceManager.d Sun Aug 10 16:23:09 2008 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,284 +0,0 @@ -module basic.SourceManager; - -import tango.core.Memory : GC; -import tango.io.UnicodeFile; -import tango.io.Stdout; -import tango.text.convert.Layout; - -public import basic.SourceLocation; - -private alias char[] string; - -/** - SourceManager is used to handle input files, by loading them in in chunks - that can be referenced elsewhere. - - It will also help extract the line/col of locations and convert between - real and virtual locations - **/ -class SourceManager -{ - this() - { - layout = new Layout!(char); - } - - /** - Will load in the file belonging to the filename - - filename = The file to load. Theres some assumptions about this file. - 1. The file has a BOM or is valid utf-8 - 2. The file is not empty, unreadable, a folder etc. - **/ - SourceLocation addFile(string filename) - { - scope file = new UnicodeFile!(char)(filename, Encoding.UTF_8); - auto file_data = file.read(); - return createCheckpoints(file_data, filename); - } - - /** - Returns a string slice containing the part of the file after loc (a - pointer might be better, it allows negative indexing) - **/ - string getRawData(SourceLocation loc) - { - CP cp = checkpoints[loc.fileID]; - auto length = cp.data_end - cp.data.ptr; - return cp.data.ptr[loc.fileOffset .. length]; - } - - /** - Extracts the line number of the given location - O("file size") if cache isn't built, O(log "lines in file") else - **/ - uint getLineNumber(SourceLocation loc) - { - assert(loc.isValid, "Location is invalid"); - assert(loc.isReal, "Virtual locations not supported yet"); - assert(loc.fileID < checkpoints.length, "Non-existent location"); - - CP* cp = &checkpoints[loc.fileID]; - auto cache = &linecache[cp.meta_index]; - if (!cache.isCached) - cache.build(cp.data_start[0 .. cp.data_end - cp.data_start]); - return cache.lineOf(getFileOffset(loc)); - } - - /** - Extracts the full byte offset into a file, at which a location - is pointing. - **/ - uint getFileOffset(SourceLocation loc) - { - return loc.fileOffset - + checkpoints[loc.fileID].part * loc.Bits.MaxFileOffset; - } - - /** - Extracts a string containing the entire line loc appears in. - **/ - string getLine(SourceLocation loc) - { - // The line is extracted by getting two pointers to the exact location - // and decreasing one until the nearest newline while the other ptr is - // increased to the nearest newline. - CP* cp = &checkpoints[loc.fileID]; - char* ptr = cp.data.ptr + loc.fileOffset; - char* ptr_lo = ptr; - while (cp.inRange(ptr_lo) && *ptr_lo != '\n' && *ptr_lo != '\r') - --ptr_lo; - while (cp.inRange(ptr) && *ptr != '\n' && *ptr != '\r') - ++ptr; - return ptr_lo[1 .. ptr - ptr_lo]; - } - - /** - Gets the column of where the loc appears. - **/ - int getColumn(SourceLocation loc) - { - // Use same approach as getLine - - CP* cp = &checkpoints[loc.fileID]; - char* ptr = cp.data.ptr + loc.fileOffset; - char* ptr_lo = ptr; - while (cp.inRange(ptr_lo) && *ptr_lo != '\n' && *ptr_lo != '\r') - --ptr_lo; - return cast(int)ptr - cast(int)ptr_lo - 1; - } - - /** - Get the original source text of a SourceRange - **/ - string getText(SourceRange loc) - { - assert(loc.isValid, "Range is invalid"); - assert(loc.isReal, "Virtual locations not supported yet"); - auto begin = getFileOffset(loc.begin); - auto end = getFileOffset(loc.end); - return checkpoints[loc.begin.fileID].data_start[begin .. end]; - } - - /** - Get the original source text - **/ - string getText(SourceLocation loc, size_t length) - { - return getText(SourceRange(loc, loc + length)); - } - - /** - Convert a location into a string. Something like "file(line)" - **/ - string getLocationAsString(SourceLocation loc) - { - assert(loc.isValid, "Location is invalid"); - return layout.convert("{}({})", - checkpoints[loc.fileID].filename, - getLineNumber(loc)); - } - string getLocationAsString(SourceRange loc) - { - return layout.convert("{}({}:{})", - checkpoints[loc.begin.fileID].filename, - getFileOffset(loc.begin), - getFileOffset(loc.end)); - } - - /** - Get the file name of a loc. - **/ - string getFile(SourceLocation loc) - { - return checkpoints[loc.fileID].filename; - } - -private: - synchronized - SourceLocation createCheckpoints(string data, string source_file) - { - // The line-cache is added, but not built, - // getLineNumber makes sure it is called when needed. - linecache ~= FileLineCache(); - uint meta_index = linecache.length - 1; - - // SourceLocation's can only index relatively short buffers, therefore - // the file is split into several checkpoints. - uint checkpoint_counter = 0; - char* data_start = data.ptr; - char* data_end = data.ptr + data.length; - while (data.length > 0) - { - uint to_take = min(data.length, SourceLocation.Bits.MaxFileOffset); - checkpoints ~= - CP(source_file, - data_start, - data_end, - data[0 .. to_take], - checkpoint_counter++, - meta_index); - data = data[to_take .. $]; - } - checkpoint_counter = checkpoints.length - checkpoint_counter; - return SourceLocation.fromFileID(checkpoint_counter); - } - - /// Contains the read/generated data. - CP[] checkpoints; - /// Cache used to speed up finding of line-starts. - FileLineCache[] linecache; - /// Used for formatting locations as strings. - Layout!(char) layout; - - // These really should be magically available everywhere and templated. - int min(int a, int b) { return a < b? a : b; } - int max(int a, int b) { return a >= b? a : b; } - - // A Check Point is used to store a file in multiple parts, to overcome - // the limitation of SourceLocation only having a rather limited amount of - // bits to index any one file. - struct CP - { - // read-only - char[] filename; - // ditto - char* data_start; - char* data_end; - // ditto - char[] data; - // ditto - uint part = 0; - // ditto - uint meta_index = 0; - - bool inRange(char* p) - { - return p >= data_start && p < data_end; - } - } - - struct FileLineCache - { - /// Contains the offset of the i'th line on index i - uint[] line_starts; - - /// Indicates weather the cache has been built or not - bool isCached = false; - - /** - This method does a binary search to find the line that contains the - given offset. - **/ - uint lineOf(uint offset) - { - size_t beg = 0, - end = line_starts.length, - mid = end >> 1; - - while( beg < end ) - { - if( line_starts[mid] <= offset ) - beg = mid + 1; - else - end = mid; - mid = beg + ( end - beg ) / 2; - } - return mid; - } - - /** - Builds the cache data - always make sure this has been called before - calling lineOf. - **/ - void build(char[] data) - { - // j starts at 1, because we need an additional place in the array - // to indicate that line 1 starts at index 0. - size_t j = 1; - char* it = data.ptr, end = data.ptr + data.length; - for (; it != end; ++it) - if (*it == '\n') - ++j; - // Allocate without initialization. Saves a bit of time - line_starts.length = j; - line_starts[0] = 0; - - // Go over the data again, writing the line starts in our new array - j = 1; - for (size_t i = 0; i < data.length; i++) - { - if (data[i] == '\n') - line_starts[j++] = i; - else if (data[i] == '\r') - { - line_starts[j++] = i; - i += cast(size_t)(data[i+1] == '\n'); - } - } - - isCached = true; - } - } -} - diff -r d442ce39917c -r 55ea834c8675 basic/conv.d --- a/basic/conv.d Sun Aug 10 16:23:09 2008 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,464 +0,0 @@ - -// Written in the D programming language. - -/* - * Copyright (C) 2002-2006 by Digital Mars, www.digitalmars.com - * Written by Walter Bright - * Some parts contributed by David L. Davis - * - * This software is provided 'as-is', without any express or implied - * warranty. In no event will the authors be held liable for any damages - * arising from the use of this software. - * - * Permission is granted to anyone to use this software for any purpose, - * including commercial applications, and to alter it and redistribute it - * freely, subject to the following restrictions: - * - * o The origin of this software must not be misrepresented; you must not - * claim that you wrote the original software. If you use this software - * in a product, an acknowledgment in the product documentation would be - * appreciated but is not required. - * o Altered source versions must be plainly marked as such, and must not - * be misrepresented as being the original software. - * o This notice may not be removed or altered from any source - * distribution. - */ - -/*********** - * Conversion building blocks. These differ from the C equivalents - * atoi() and atol() by - * checking for overflow and not allowing whitespace. - * - * For conversion to signed types, the grammar recognized is: - *
-$(I Integer):
-    $(I Sign UnsignedInteger)
-    $(I UnsignedInteger)
-
-$(I Sign):
-    $(B +)
-    $(B -)
- * 
- * For conversion to signed types, the grammar recognized is: - *
-$(I UnsignedInteger):
-    $(I DecimalDigit)
-    $(I DecimalDigit) $(I UnsignedInteger)
- * 
- * Macros: - * WIKI=Phobos/StdConv - */ - - -/************************* - Changed to be used next to tango. - - Unittests removed. - *************************/ - -module basic.conv; - -private import tango.text.Util; // for atof(), toString() -private import tango.stdc.stringz; -private import tango.stdc.ctype; -private import tango.stdc.stdlib; -private import tango.stdc.errno; -//private import std.c.stdlib; -//private import std.math; // for fabs(), isnan() - -private -{ - extern (C) int getErrno(); - extern (C) int setErrno(int); -} - -//debug=conv; // uncomment to turn on debugging printf's - -/* ************* Exceptions *************** */ - -/** - * Thrown on conversion errors, which happens on deviation from the grammar. - */ -class ConvError : Exception -{ - this(char[] s) - { - super("conversion " ~ s); - } -} - -private void conv_error(char[] s) -{ - throw new ConvError(s); -} - -/** - * Thrown on conversion overflow errors. - */ -class ConvOverflowError : Exception -{ - this(char[] s) - { - super("Error: overflow " ~ s); - } -} - -private void conv_overflow(char[] s) -{ - throw new ConvOverflowError(s); -} - -/*************************************************************** - * Convert character string to the return type. - */ - -int toInt(char[] s) -{ - int length = s.length; - - if (!length) - goto Lerr; - - int sign = 0; - int v = 0; - - for (int i = 0; i < length; i++) - { - char c = s[i]; - if (c >= '0' && c <= '9') - { - if (v < int.max/10 || (v == int.max/10 && c + sign <= '7')) - v = v * 10 + (c - '0'); - else - goto Loverflow; - } - else if (c == '-' && i == 0) - { - sign = -1; - if (length == 1) - goto Lerr; - } - else if (c == '+' && i == 0) - { - if (length == 1) - goto Lerr; - } - else - goto Lerr; - } - if (sign == -1) - { - if (cast(uint)v > 0x80000000) - goto Loverflow; - v = -v; - } - else - { - if (cast(uint)v > 0x7FFFFFFF) - goto Loverflow; - } - return v; - -Loverflow: - conv_overflow(s); - -Lerr: - conv_error(s); - return 0; -} - -/******************************************************* - * ditto - */ - -uint toUint(char[] s) -{ - int length = s.length; - - if (!length) - goto Lerr; - - uint v = 0; - - for (int i = 0; i < length; i++) - { - char c = s[i]; - if (c >= '0' && c <= '9') - { - if (v < uint.max/10 || (v == uint.max/10 && c <= '5')) - v = v * 10 + (c - '0'); - else - goto Loverflow; - } - else - goto Lerr; - } - return v; - -Loverflow: - conv_overflow(s); - -Lerr: - conv_error(s); - return 0; -} - -/******************************************************* - * ditto - */ - -long toLong(char[] s) -{ - int length = s.length; - - if (!length) - goto Lerr; - - int sign = 0; - long v = 0; - - for (int i = 0; i < length; i++) - { - char c = s[i]; - if (c >= '0' && c <= '9') - { - if (v < long.max/10 || (v == long.max/10 && c + sign <= '7')) - v = v * 10 + (c - '0'); - else - goto Loverflow; - } - else if (c == '-' && i == 0) - { - sign = -1; - if (length == 1) - goto Lerr; - } - else if (c == '+' && i == 0) - { - if (length == 1) - goto Lerr; - } - else - goto Lerr; - } - if (sign == -1) - { - if (cast(ulong)v > 0x8000000000000000) - goto Loverflow; - v = -v; - } - else - { - if (cast(ulong)v > 0x7FFFFFFFFFFFFFFF) - goto Loverflow; - } - return v; - -Loverflow: - conv_overflow(s); - -Lerr: - conv_error(s); - return 0; -} - -/******************************************************* - * ditto - */ - -ulong toUlong(char[] s) -{ - int length = s.length; - - if (!length) - goto Lerr; - - ulong v = 0; - - for (int i = 0; i < length; i++) - { - char c = s[i]; - if (c >= '0' && c <= '9') - { - if (v < ulong.max/10 || (v == ulong.max/10 && c <= '5')) - v = v * 10 + (c - '0'); - else - goto Loverflow; - } - else - goto Lerr; - } - return v; - -Loverflow: - conv_overflow(s); - -Lerr: - conv_error(s); - return 0; -} - -/******************************************************* - * ditto - */ - -short toShort(char[] s) -{ - int v = toInt(s); - - if (v != cast(short)v) - goto Loverflow; - - return cast(short)v; - -Loverflow: - conv_overflow(s); - return 0; -} - -/******************************************************* - * ditto - */ - -ushort toUshort(char[] s) -{ - uint v = toUint(s); - - if (v != cast(ushort)v) - goto Loverflow; - - return cast(ushort)v; - -Loverflow: - conv_overflow(s); - return 0; -} - -/******************************************************* - * ditto - */ - -byte toByte(char[] s) -{ - int v = toInt(s); - - if (v != cast(byte)v) - goto Loverflow; - - return cast(byte)v; - -Loverflow: - conv_overflow(s); - return 0; -} - -/******************************************************* - * ditto - */ - -ubyte toUbyte(char[] s) -{ - uint v = toUint(s); - - if (v != cast(ubyte)v) - goto Loverflow; - - return cast(ubyte)v; - -Loverflow: - conv_overflow(s); - return 0; -} - -/******************************************************* - * ditto - */ - -float toFloat(in char[] s) -{ - float f; - char* endptr; - char* sz; - - //writefln("toFloat('%s')", s); - sz = toStringz(s); - if (tango.stdc.ctype.isspace(*sz)) - goto Lerr; - - // BUG: should set __locale_decpoint to "." for DMC - - setErrno(0); - f = strtof(sz, &endptr); - if (getErrno() == ERANGE) - goto Lerr; - if (endptr && (endptr == sz || *endptr != 0)) - goto Lerr; - - return f; - - Lerr: - conv_error(s ~ " not representable as a float"); - assert(0); -} - -/******************************************************* - * ditto - */ - -double toDouble(in char[] s) -{ - double f; - char* endptr; - char* sz; - - //writefln("toDouble('%s')", s); - sz = toStringz(s); - if (tango.stdc.ctype.isspace(*sz)) - goto Lerr; - - // BUG: should set __locale_decpoint to "." for DMC - - setErrno(0); - f = strtod(sz, &endptr); - if (getErrno() == ERANGE) - goto Lerr; - if (endptr && (endptr == sz || *endptr != 0)) - goto Lerr; - - return f; - - Lerr: - conv_error(s ~ " not representable as a double"); - assert(0); -} - -/******************************************************* - * ditto - */ -real toReal(in char[] s) -{ - real f; - char* endptr; - char* sz; - - //writefln("toReal('%s')", s); - sz = toStringz(s); - if (tango.stdc.ctype.isspace(*sz)) - goto Lerr; - - // BUG: should set __locale_decpoint to "." for DMC - - setErrno(0); - f = strtold(sz, &endptr); - if (getErrno() == ERANGE) - goto Lerr; - if (endptr && (endptr == sz || *endptr != 0)) - goto Lerr; - - return f; - - Lerr: - conv_error(s ~ " not representable as a real"); - assert(0); -} - diff -r d442ce39917c -r 55ea834c8675 dsss.conf --- a/dsss.conf Sun Aug 10 16:23:09 2008 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,24 +0,0 @@ -[lexer] -buildflags = -version=Tango -[parser] -buildflags = -version=Tango -[ast] -buildflags = -version=Tango -[gen] -buildflags = -version=Tango - - -[dang/compiler.d] -Target = Dang -buildflags = -llstdc++ \ - -llLLVMSystem -llLLVMSupport -llLLVMCore -llLLVMBitWriter -llLLVMBitReader -llLLVMAnalysis -llLLVMTarget \ - -llLLVMTransformUtils -llLLVMScalarOpts -llLLVMipa -llLLVMipo \ - -llLLVMInstrumentation -llllvm-c-ext -lldl -version=Tango - -[tests/run.d] -Target = tests/run -buildflags = -llllvm-c-ext -llstdc++ \ - -llLLVMCore -llLLVMBitWriter -llLLVMBitReader -llLLVMAnalysis -llLLVMTarget \ - -llLLVMTransformUtils -llLLVMScalarOpts -llLLVMipa -llLLVMipo \ - -llLLVMInstrumentation -llLLVMSystem -llLLVMSupport -version=Tango - diff -r d442ce39917c -r 55ea834c8675 gen/CodeGen.d --- a/gen/CodeGen.d Sun Aug 10 16:23:09 2008 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,1198 +0,0 @@ -module gen.CodeGen; - -import tango.io.Stdout, - Int = tango.text.convert.Integer; -import tango.core.Array : find, partition; - -import llvm.llvm; - -import ast.Decl, - ast.Stmt, - ast.Exp, - ast.Module : DModule = Module; - -import basic.SmallArray, - basic.Attribute, - basic.LiteralParsing; - -import lexer.Token; - -import sema.Scope, - sema.Visitor; - -/** - Wrapper for Values representing rvalues (things you can only read from) - **/ -private struct RValue -{ - /** - Returns true if this is a simple value, like an int or a pointer. - This is basicly anything except a struct, which will contain a Value that - is a pointer to the struct. - **/ - bool isSimple() { return simple; } - /// Opposite of isSimple - bool isAggregate() { return !simple; } - - Value value; - private bool simple = true; -} - -/** - Wrapper for Values representing lvalues (things you can write to) - **/ -private struct LValue -{ - Value getAddress() { return value; } - private Value value; -} - -class CodeGen -{ -public: - this() - { - b = new Builder; - ZeroIndex = ConstantInt.GetU(Type.Int32, 0); - - table = new SimpleSymbolTable(); - - createBasicTypes(); - } - - /** - Generate a new module. - **/ - /* - Find all function decls and add the functions to the llvm module, so - they can be referenced. - - Make sure all var-decls are located before functions, so we wont get - problems when referencing the global vars. - - Generate the actual llvm code needed for all decls - - Optimize if requested - - Write to filehandle (can be a file or stdout) - */ - void gen(DModule mod, uint handle, bool optimize, bool inline) - { - this.mod = mod; - // create module - m = new .llvm.llvm.Module("main_module"); - scope(exit) m.dispose(); - - table.enterScope; - - BytePtr = PointerType.Get(Type.Int8); - auto temp = FunctionType.Get( - Type.Void, - [BytePtr, BytePtr, Type.Int32, Type.Int32]); - llvm_memcpy = m.addFunction(temp, "llvm.memcpy.i32"); - - auto registerFunc = - (FuncDecl fd) - { - Type[] param_types; - foreach (i, p; fd.type.params) - { - if (auto st = p.asStruct()) - { - Type pointer = PointerType.Get(llvm(st)); - param_types ~= pointer; - } - else if (auto ar = p.asArray()) - { - Type pointer = PointerType.Get(llvm(ar)); - param_types ~= pointer; - } - else - param_types ~= llvm(p); - } - auto ret_t = fd.type.returnType; - if(auto st = cast(DStruct)ret_t) - ret_t = DType.Void; - else if(auto f = cast(DFunction)ret_t) - ret_t = f.returnType; - auto func_t = FunctionType.Get(llvm(ret_t), param_types); - auto llfunc = m.addFunction(func_t, symbolName(fd)); - - foreach (i, p; fd.funcArgs) - { - if(i == 0 && fd.sret) - llfunc.addParamAttr(0, ParamAttr.StructRet); - - DType t = fd.type.params[i]; - if (auto st = t.asStruct) - { - if (i == 0 && fd.sret) - continue; - llfunc.addParamAttr(i, ParamAttr.ByVal); - } - else if (auto ar = t.asArray) - { - llfunc.addParamAttr(i, ParamAttr.ByVal); - } - } - }; - auto visitor = new VisitFuncDecls(registerFunc); - visitor.visit([mod]); - // Before beginning we move all top level var-decls to the start - // and then we generate the var-decls first - // partition is NOT required to be stable, but that should not create - // any problems. - partition(mod.decls, (Decl d) { return d.declType == DeclType.VarDecl; }); - - foreach (decl; mod.decls) - genRootDecl(decl); - - table.leaveScope; - -// debug m.verify(); - - if(optimize) - m.optimize(inline); - - m.writeBitcodeToFileHandle(handle); - } - -private: - /** - Generate a single top-level Decl - **/ - void genRootDecl(Decl decl) - { - switch(decl.declType) - { - case DeclType.FuncDecl: - FuncDecl funcDecl = cast(FuncDecl)decl; - - // Empty function - declare; - if(funcDecl.emptyFunction) - return; - - llvm(funcDecl.type); - auto llfunc = m.getNamedFunction(symbolName(funcDecl)); - auto func_tp = cast(PointerType)llfunc.type; - auto func_t = cast(FunctionType)func_tp.elementType(); - auto ret_t = func_t.returnType(); - - - auto bb = llfunc.appendBasicBlock("entry"); - b.positionAtEnd(bb); - - table.enterScope; - foreach (i, v; funcDecl.funcArgs) - { - llfunc.getParam(i).name = v.identifier.get; - auto name = v.identifier.get; - if (!cast(PointerType)llfunc.getParam(i).type) - { - auto AI = b.buildAlloca(llfunc.getParam(i).type, name); - // Value va = b.buildLoad(val, name); - b.buildStore(llfunc.getParam(i), AI); - table[name] = AI; - } - else - table[name] = llfunc.getParam(i); - } - - foreach (stmt; funcDecl.statements) - genStmt(stmt); - - // if the function didn't end with a return, we automatically - // add one (return 0 as default) - if (b.getInsertBlock().terminated() is false) - if (ret_t is Type.Void) - b.buildRetVoid(); - else - b.buildRet(ConstantInt.GetS(ret_t, 0)); - - table.leaveScope; - break; - - case DeclType.VarDecl: - auto varDecl = cast(VarDecl)decl; - auto id = varDecl.identifier; - Type t = llvm(id.type); - GlobalVariable g = m.addGlobal(t, id.get); - g.initializer = Constant.GetNull(t); - table[varDecl.identifier.get] = g; - break; - - case DeclType.StructDecl: - auto sdecl = cast(StructDecl)decl; - foreach (d; sdecl.decls) - { - auto func = cast(FuncDecl)d; - if (func is null) - continue; - genRootDecl(func); - } - break; - - case DeclType.ClassDecl: - auto cdecl = cast(ClassDecl)decl; - SmallArray!(Constant) functions; - foreach (d; cdecl.decls) - { - auto func = cast(FuncDecl)d; - if (func is null) - continue; - genRootDecl(func); - auto llvm_f = m.getNamedFunction(symbolName(func)); - functions ~= Constant.GetBitCast(llvm_f, BytePtr); - } - auto class_vtbl = ConstantArray.Get(BytePtr, functions.unsafe()); - auto gv = m.addGlobal(class_vtbl, cdecl.identifier.get ~ "_vtable"); - gv.linkage = Linkage.Weak; - gv.globalConstant = true; - break; - - default: - break; - } - } - - /** - Generate a single local Decl - **/ - void genDecl(Decl decl) - { - switch(decl.declType) - { - case DeclType.VarDecl: - auto varDecl = cast(VarDecl)decl; - auto id = varDecl.identifier; - auto name = id.get; - auto AI = b.buildAlloca(llvm(id.type), name); - table[name] = AI; - if (varDecl.init) - { - LValue dst = genLValue(varDecl.identifier); - RValue src = genExpression(varDecl.init); - storeThroughLValue(dst, src, id.type); - } - break; - - case DeclType.FuncDecl, - DeclType.StructDecl, - DeclType.ClassDecl: - genRootDecl(decl); - break; - - default: - break; - } - } - - // Remove - do it right (basic/Messages.d) - struct PE - { - static char[] NoImplicitConversion = - "Can't find an implicit conversion between %0 and %1"; - static char[] VoidRetInNonVoidFunc = - "Only void functions can return without an expression"; - } - - /** - Generate a single expression. - - This is the most general way of generating expressions and therefore - returns an RValue. - **/ - RValue genExpression(Exp exp) - { - switch(exp.expType) - { - case ExpType.Binary: - return RValue(genBinExp(cast(BinaryExp)exp)); - case ExpType.IntegerLit: - auto integerLit = cast(IntegerLit)exp; - switch(integerLit.number.type) - { - case NumberType.Int: - return RValue(ConstantInt.GetS(Type.Int32, integerLit.number.integer)); - case NumberType.Long: - return RValue(ConstantInt.GetS(Type.Int64, integerLit.number.integer)); - case NumberType.ULong: - return RValue(ConstantInt.GetS(Type.Int64, integerLit.number.integer)); - case NumberType.Float: - return RValue(ConstantReal.Get(Type.Float, integerLit.number.floating)); - case NumberType.Double: - return RValue(ConstantReal.Get(Type.Double, integerLit.number.floating)); - case NumberType.Real: - return RValue(ConstantReal.Get(Type.X86_FP80, integerLit.number.floating)); - } - case ExpType.StringExp, - ExpType.ArrayLiteralExp: - return loadLValue(genLValue(exp)); - case ExpType.Negate: - auto negateExp = cast(NegateExp)exp; - auto target = genExpression(negateExp.exp); - return RValue(b.buildNeg(target.value, "neg")); - case ExpType.Deref: - auto derefExp = cast(DerefExp)exp; - auto target = genExpression(derefExp.exp); - return RValue(b.buildLoad(target.value, "deref")); - case ExpType.AddressOfExp: - auto addrExp = cast(AddressOfExp)exp; - auto target = genLValue(addrExp.exp); - return RValue(target.getAddress()); - case ExpType.AssignExp: - auto AE = cast(AssignExp)exp; - LValue dst = genLValue(AE.identifier); - RValue src = genExpression(AE.exp); - storeThroughLValue(dst, src, AE.exp.type); - return src; - case ExpType.Index: - auto indexExp = cast(IndexExp)exp; - return loadLValue(genLValue(exp)); - case ExpType.NewExp: - auto newExp = cast(NewExp)exp; - DClass type = newExp.newType.type.asClass(); - auto llvm_type = cast(PointerType)llvm(type); - auto pointer = b.buildMalloc(llvm_type.elementType(), "new"); - scope args = new Value[newExp.c_args.length]; - foreach (i, arg; newExp.c_args) - args[i] = genExpression(arg).value; - auto f = m.getNamedFunction(newExp.callSym.getMangledFQN()); - b.buildCall(f, args, ""); - return RValue(pointer); - case ExpType.CallExp: - auto callExp = cast(CallExp)exp; - // BUG: Might not be a simple identifier, a.foo(x) is also a - // valid call - or foo(x)(y) for that matter. - - // if type of exp is DFunction - safe to call getSymbol and FQN - // if function ptr: do something else - // if delegate do a third thing - // if struct/class check for opCall - DType type = callExp.exp.type; - assert (type.isCallable(), "Can only call functions"); - scope args = new Value[callExp.args.length]; - foreach (i, arg; callExp.args) - args[i] = genExpression(arg).value; - DFunction ftype = type.asCallable(); - Type llvm_ftype = llvm(ftype); - Value f = null; - if (callExp.callSym is null) - { - // Do a virtual function call - f = genLValue(callExp.exp).getAddress(); - f = b.buildLoad(f, "func_pointer"); - f = b.buildBitCast( - f, - PointerType.Get(llvm_ftype), - ftype.name); - } - else - { - auto sym = callExp.callSym; - f = m.getNamedFunction(sym.getMangledFQN()); - } - bool isVoid = ftype.returnType is DType.Void; - auto r = b.buildCall(f, args, isVoid? "" : "call"); - return RValue(r); - case ExpType.CastExp: - auto castExp = cast(CastExp)exp; - exp = castExp.exp; - auto value = genExpression(exp); - - if (!exp.type.hasImplicitConversionTo(castExp.type)) - assert(0, "Invalid cast"); - - return genTypeCast(value, exp.type, castExp.type); - - case ExpType.Identifier: - auto id = cast(Identifier)exp; - auto type = id.type; - if (type.isStruct() - || type.isArray() - || type.isClass()) - return RValue(table.find(id.get)); - else if (type.isFunction()) - { - auto func_name = id.getSymbol().getMangledFQN(); - return RValue(m.getNamedFunction(func_name)); - } - else if (type.isCallable()) - return RValue(genLValue(id).getAddress()); - else - return RValue(b.buildLoad(table.find(id.get), id.get)); - case ExpType.MemberReference: - return loadLValue(genLValue(exp)); - } - assert(0, "Reached end of switch in genExpression"); - return RValue(null); - } - - /** - Generate a binary expression. - - Currently only works for signed and unsigned integers, but is almost - ready for floats and should be expanded to everything else. - **/ - Value genBinExp(BinaryExp e) - { - auto left = genExpression(e.left).value; - auto right = genExpression(e.right).value; - DType t_a = e.left.type; - DType t_b = e.right.type; - - Value res; - // TODO: do usual type promotions on a and b - // TODO: support floats - if (t_a.isArithmetic() && t_b.isArithmetic()) - { - Operation op = t_a.getOperationWith(op2op(e.op), t_b); - assert(op.isBuiltin(), - "numbers should only use builtin ops"); - alias BuiltinOperation BO; - BO val = op.builtinOp(); - // map val to buildAdd or similar - switch (val) { - case BO.Add: res = b.buildAdd(left, right, "add"); break; - case BO.Sub: res = b.buildSub(left, right, "sub"); break; - case BO.Mul: res = b.buildMul(left, right, "mul"); break; - case BO.SDiv: res = b.buildSDiv(left, right, "div"); break; - case BO.UDiv: res = b.buildUDiv(left, right, "div"); break; - case BO.FDiv: res = b.buildFDiv(left, right, "div"); break; - case BO.SRem: res = b.buildSRem(left, right, "rem"); break; - case BO.URem: res = b.buildURem(left, right, "rem"); break; - case BO.FRem: res = b.buildFRem(left, right, "rem"); break; - - case BO.Shl: res = b.buildShl(left, right, "shl"); break; - case BO.LShr: res = b.buildLShr(left, right, "lshr"); break; - case BO.AShr: res = b.buildAShr(left, right, "ashr"); break; - - case BO.And: res = b.buildAnd(left, right, "and"); break; - case BO.Or: res = b.buildOr (left, right, "or"); break; - case BO.Xor: res = b.buildXor(left, right, "xor"); break; - - default: - LLVMPred pred = predFromBI(val); - if (t_a.isReal()) - if (val == BO.Eq) - pred = LLVMPred.Real(RealPredicate.OEQ); - else if (val == BO.Ne) - pred = LLVMPred.Real(RealPredicate.ONE); - IntPredicate ip = pred.intPred; - RealPredicate rp = pred.realPred; - assert(pred.isValid, "Not a predicate"); - if (pred.isReal) - res = b.buildFCmp(rp, left, right, "cmp"); - else - res = b.buildICmp(ip, left, right, "cmp"); - break; - } - } - else - /* - if left has op for right's type: - a_op = left.op(right) - if right has usable op_r: - b_op_r = right.op_r(left) - if a_op or b_op_r is set, choose the best one - else if op is commutative - if left has usable op_r - a_op_r = left.op_r(right) - if right has usable op - b_op = right.op(left) - choose best one from a_op_r and b_op - else error - */ - assert(0, "Not integers?"); - - return res; - } - - /** - Generates one statement - **/ - // This should be split into specific methods - one per Stmt type? - void genStmt(Stmt stmt) - { - switch(stmt.stmtType) - { - case StmtType.Compound: - auto stmts = cast(CompoundStatement)stmt; - foreach (s; stmts.statements) - genStmt(s); - break; - case StmtType.Return: - auto ret = cast(ReturnStmt)stmt; - DFunction type = stmt.env.parentFunction().type(); - Type t = llvm(type.returnType); - if (ret.exp is null) - if (t is Type.Void) - { - b.buildRetVoid(); - return; - } - else - assert(0, PE.VoidRetInNonVoidFunc); - - RValue v = genExpression(ret.exp); - b.buildRet(v.value); - break; - case StmtType.Decl: - auto declStmt = cast(DeclStmt)stmt; - genDecl(declStmt.decl); - break; - case StmtType.Exp: - auto expStmt = cast(ExpStmt)stmt; - genExpression(expStmt.exp); - break; - case StmtType.If: - auto ifStmt = cast(IfStmt)stmt; - Value cond = genExpression(ifStmt.cond).value; - if (cond.type !is Type.Int1) - { - Value False = ConstantInt.GetS(cond.type, 0); - cond = b.buildICmp(IntPredicate.NE, cond, False, ".cond"); - } - auto func_name = symbolName(stmt.env.parentFunction()); - Function func = m.getNamedFunction(func_name); - bool has_else = (ifStmt.else_body !is null); - - auto thenBB = func.appendBasicBlock("then"); - auto elseBB = has_else? func.appendBasicBlock("else") : null; - auto mergeBB = func.appendBasicBlock("merge"); - - b.buildCondBr(cond, thenBB, has_else? elseBB : mergeBB); - b.positionAtEnd(thenBB); - genStmt(ifStmt.then_body); - thenBB = b.getInsertBlock(); - if (b.getInsertBlock().terminated() is false) - b.buildBr(mergeBB); - - if (has_else) - { - b.positionAtEnd(elseBB); - genStmt(ifStmt.else_body); - elseBB = b.getInsertBlock(); - if (elseBB.terminated() is false) - b.buildBr(mergeBB); - } - - b.positionAtEnd(mergeBB); - break; - case StmtType.While: - auto wStmt = cast(WhileStmt)stmt; - genLoop(stmt.env, wStmt.cond, false, wStmt.whileBody); - break; - /+ - case StmtType.DoWhile: - auto wStmt = cast(DoWhileStmt)stmt; - genLoop(stmt.env, wStmt.cond, true, wStmt.whileBody); - break; - +/ - case StmtType.For: - auto fStmt = cast(ForStmt)stmt; - Stmt[] stmts; - if(fStmt.init) - genStmt(fStmt.init); - ExpStmt inc; - if(fStmt.incre) - stmts ~= new ExpStmt(fStmt.incre); - Exp cond; - if(fStmt.cond) - cond = fStmt.cond; - else - { - auto i = new IntegerLit(fStmt.loc,"1"); - i.number.type = NumberType.Int; - i.number.integer = 1; - cond = i; - } - stmts ~= fStmt.forBody; - genLoop(stmt.env, cond, false, stmts); - break; - case StmtType.Switch: - auto sw = cast(SwitchStmt)stmt; - Value cond = genExpression(sw.cond).value; - - auto fc = stmt.env.parentFunction(); - Function func = m.getNamedFunction(symbolName(fc)); - - BasicBlock oldBB = b.getInsertBlock(); - BasicBlock defBB; - BasicBlock endBB = func.appendBasicBlock("sw.end"); - if (sw.defaultBlock) - { - defBB = Function.InsertBasicBlock(endBB, "sw.def"); - b.positionAtEnd(defBB); - foreach (case_statement; sw.defaultBlock) - genStmt(case_statement); - if (!defBB.terminated()) - b.buildBr(endBB); - b.positionAtEnd(oldBB); - } - else - defBB = endBB; - auto SI = b.buildSwitch(cond, defBB, sw.cases.length); - foreach (c; sw.cases) - { - BasicBlock prevBB; - foreach (i, val; c.values) - { - auto BB = Function.InsertBasicBlock(defBB, "sw.bb"); - SI.addCase(ConstantInt.GetS(cond.type, c.values_converted[i]), BB); - - if (i + 1 == c.values.length) - { - b.positionAtEnd(BB); - foreach (case_statement; c.stmts) - genStmt(case_statement); - if (!BB.terminated()) - b.buildBr(c.followedByDefault? defBB : endBB); - } - - if (prevBB !is null && !prevBB.terminated()) - { - b.positionAtEnd(prevBB); - b.buildBr(BB); - } - prevBB = BB; - } - } - b.positionAtEnd(endBB); - break; - } - } - - /** - Generate a loop. - - Loops while cond is true, executing all statements in stmts every time. - - If skipFirstCond is set, the condition is skipped the first time around, - like in a do-while loop. - **/ - void genLoop(Scope env, Exp cond, bool skipFirstCond, Stmt[] stmts...) - { - auto fd = env.parentFunction(); - Function func = m.getNamedFunction(symbolName(fd)); - - auto condBB = func.appendBasicBlock("cond"); - auto bodyBB = func.appendBasicBlock("body"); - auto doneBB = func.appendBasicBlock("done"); - - b.buildBr(skipFirstCond? bodyBB : condBB); - b.positionAtEnd(condBB); - - Value cond_v = genExpression(cond).value; - if (cond_v.type !is Type.Int1) - { - Value False = ConstantInt.GetS(cond_v.type, 0); - cond_v = b.buildICmp(IntPredicate.NE, cond_v, False, ".cond"); - } - b.buildCondBr(cond_v, bodyBB, doneBB); - - b.positionAtEnd(bodyBB); - foreach (stmt; stmts) - genStmt(stmt); - if (b.getInsertBlock().terminated() is false) - b.buildBr(condBB); - - b.positionAtEnd(doneBB); - } - - /* - Get the address of an expression - allowing us to modify something in - memory or on the stack. - */ - LValue genLValue(Exp exp) - { - switch(exp.expType) - { - case ExpType.Identifier: - auto id = cast(Identifier)exp; - Value v = table.find(id.get); - if (v is null) - v = m.getNamedFunction(id.getSymbol().getMangledFQN()); - return LValue(v); - case ExpType.StringExp: - auto stringExp = cast(StringExp)exp; - char[] data = cast(char[])stringExp.data.data; - auto string_constant = ConstantArray.GetString(data, true); - auto gv = m.addGlobal(string_constant, "string"); - gv.linkage = Linkage.Internal; - gv.globalConstant = true; - return LValue(gv); - case ExpType.ArrayLiteralExp: - auto arrayLiteralExp = cast(ArrayLiteralExp)exp; - SmallArray!(Constant) constants; - foreach (e; arrayLiteralExp.exps) - constants ~= cast(Constant)genExpression(e).value; - auto array_constant = - ConstantArray.Get(constants[0].type, constants[]); - auto gv = m.addGlobal(array_constant, "array"); - gv.linkage = Linkage.Internal; - gv.globalConstant = true; - return LValue(gv); - case ExpType.AddressOfExp: - assert(0, "&&x wont work, &x isn't an LValue"); - case ExpType.Deref: - // LValue(*x): load(x) - // RValue(*x): load(load(x)) - // This way *x = *x + 1 will work - // We need an ekstra load, because we get an i32** rather than - // i32* since stuff is alloc'd - auto DE = cast(DerefExp)exp; - return LValue(genExpression(DE.exp).value); - case ExpType.Index: - auto indexExp = cast(IndexExp)exp; - auto type = indexExp.target.type; - auto index = genExpression(indexExp.index); - Value[2] gep_indices; - gep_indices[0] = ZeroIndex; - gep_indices[1] = index.value; - Value res; - auto target = genLValue(indexExp.target).getAddress(); - if (type.isStaticArray()) - res = b.buildGEP(target, gep_indices[0 .. 2], "index"); - else if (type.isPointer()) - res = b.buildGEP(target, gep_indices[1 .. 2], "index"); - else assert(0, "Can only index pointers and arrays"); - return LValue(res); - case ExpType.MemberReference: - auto mem = cast(MemberReference)exp; - switch (mem.target.expType) - { - case ExpType.Identifier: - auto id = cast(Identifier)mem.target; - auto child = mem.child; - Value v = table.find(id.get); - DType t = id.type; - if (auto st = t.asStruct) - { - int i = st.indexOf(child.get); - if (i == -1) - { - auto fname = mem.getSymbol.getMangledFQN(); - auto f = m.getNamedFunction(fname); - return LValue(f); - } - - Value[2] vals; - vals[0] = ZeroIndex; - vals[1] = ConstantInt.GetU(IntegerType.Int32, i); - - Value val = b.buildGEP(v, vals, id.get~"."~child.get); - return LValue(val); - } - else if (auto ct = t.asClass) - { - int i = ct.indexOf(child.get); - Value[2] vals; - vals[0] = ZeroIndex; - // A normal member - if (i != -1) - { - vals[1] = ConstantInt.GetU(IntegerType.Int32, i); - Value val = b.buildGEP(v, vals, id.get~"."~child.get); - return LValue(val); - } - // A method - else - { - vals[1] = ZeroIndex; - //vals[1] = ConstantInt.GetU(IntegerType.Int32, 1); - auto vtbl_name = ct.name ~ "_vtable"; - auto vtbl = m.getNamedGlobal(vtbl_name); - v = vtbl; - } - - Value val = b.buildGEP(v, vals, id.get~"."~child.get); - return LValue(val); - } - else - assert(0, "Can only access members in classes " - "and structs"); - - case ExpType.MemberReference: - auto addr = genLValue(mem.target).getAddress(); - auto child = mem.child; - DStruct t = mem.target.type.asStruct(); - - int i = t.indexOf(child.get); - - Value[2] vals; - vals[0] = ZeroIndex; - vals[1] = ConstantInt.GetU(IntegerType.Int32, i); - - Value val = b.buildGEP(addr, vals, "."~child.get); - return LValue(val); - } - break; - } - assert(0, "Reached end of switch in getPointer"); - return LValue(null); - } - - /** - Store into an lvalue from a rvalue. Both are assumed to have type t. - **/ - void storeThroughLValue(LValue dst, RValue src, DType t) - { - Value to = dst.getAddress(); - Value from = src.value; - - auto a = cast(PointerType)to.type; - assert(a !is null, "Can only store through pointers"); - - if (auto st = t.asStruct()) - genMemcpy(to, from, t); - else - b.buildStore(from, to); - } - - /** - Copy from src into dst. The values are assumed to have the same size, - and the amount of bytes to copy is taken from t. - **/ - void genMemcpy(Value dst, Value src, DType t, int alignment = 16) - { - Value from = b.buildBitCast(src, BytePtr, ".copy_from"); - Value to = b.buildBitCast(dst, BytePtr, ".copy_to"); - Value[4] args; - args[0] = to; - args[1] = from; - args[2] = ConstantInt.GetS(Type.Int32, t.byteSize()); - args[3] = ConstantInt.GetS(Type.Int32, alignment); - b.buildCall(llvm_memcpy, args[], null); - } - - /** - Generate the statements necessary to convert V, from type 'from' to type - 'to'. - **/ - RValue genTypeCast(RValue V, DType from, DType to) - { - Value delegate(Value, Type, char[]) extend, trunc; - if(auto ito = to.asInteger()) - { - extend = ito.unsigned? &b.buildZExt : &b.buildSExt; - trunc = &b.buildTrunc; - if(auto rfrom = from.isReal()) - { - extend = ito.unsigned? &b.buildFPToUI : &b.buildFPToSI; - trunc = extend; - } - } - else if (auto rto = to.asReal()) - { - extend = &b.buildFPExt; - trunc = &b.buildFPTrunc; - if(auto ifrom = from.isInteger()) - { - extend = rto.unsigned? &b.buildUIToFP : &b.buildSIToFP; - trunc = extend; - } - } - else - assert(0, "implicit cast need implimentation"); - - Value res; - if (from.byteSize() < to.byteSize()) - res = extend(V.value, llvm(to), "ext"); - else - res = trunc(V.value, llvm(to), "trunc"); - return RValue(res); - } - - /** - Given the address of something, load it into an alloc. - **/ - RValue loadLValue(LValue addr, char[] name = null) - { - Value val = addr.getAddress(); - if (name is null) - name = val.name.length > 0? val.name : "load"; - - auto res = b.buildLoad(val, name); - return RValue(res); - } - - /// Get the mangled name of a function - char[] symbolName(FuncDecl f) - { - if (f.att.getExtern == Extern.D) - return f.sym.getMangledFQN(); - return f.sym.getName; - } - - char[] symbolName(Exp f) - { - if (f.getSymbol.decl.att.getExtern == Extern.D) - return f.getSymbol.getMangledFQN(); - return f.getSymbol.getName; - } - - /** - Get the LLVM Type corresponding to a DType. - - Currently using the built-in associative array - not sure if it works - well when the hashes are so uniform. - - Other possibilities would be to find a hash-function that works on - something as small as 4 bytes or to create a sparse array perhaps. - */ - Type llvm(DType t) - { - if (auto llvm_t = t in type_map) - return *llvm_t; - return llvmCreateNew(t); - } - - // Create an LLVM type and insert it into the type map, and return the - // result - Type llvmCreateNew(DType t) - { - if (auto i = cast(DInteger)t) - { - Type res = IntegerType.Get(i.byteSize() * 8); - type_map[t] = res; - return res; - } - else if (auto s = t.asStruct) - { - SmallArray!(Type, 8) members; - DType[] array; - array.length = s.members.length; - - foreach (m; s.members) - array[m.index] = m.type; - - foreach (m; array) - members ~= llvm(m); - - Type res = StructType.Get(members.unsafe()); - type_map[t] = res; - m.addTypeName("struct." ~ s.name, res); - return res; - } - else if (auto c = t.asClass) - { - SmallArray!(Type) members; - if (c.members.length > 0) - { - DType[] array; - array.length = c.members.length; - - foreach (m; c.members) - array[m.index] = m.type; - - foreach (m; array) - members ~= llvm(m); - } - else members ~= Type.Int32; - - Type res = StructType.Get(members.unsafe()); - res = PointerType.Get(res); - type_map[t] = res; - m.addTypeName("class." ~ c.name, res); - return res; - } - else if (auto f = t.asFunction) - { - // We should never have a function returning structs, because of - // the simplify step - assert(f.returnType.isStruct() == false, "Can't return structs"); - Type ret_t = llvm(f.returnType); - - SmallArray!(Type, 8) params; - foreach(param; f.params) - if (param.isStruct) - params ~= PointerType.Get(llvm(param)); - else if (param.isArray) - params ~= PointerType.Get(llvm(param)); - else - params ~= llvm(param); - - Type res = FunctionType.Get(ret_t, params.unsafe()); - type_map[t] = res; - return res; - } - else if (auto f = t.asPointer) - { - Type res = PointerType.Get(llvm(f.pointerOf)); - type_map[t] = res; - return res; - } - else if (auto f = t.asStaticArray) - { - Type res = ArrayType.Get(llvm(f.arrayOf), f.size); - type_map[t] = res; - return res; - } - assert(0, "Only integers, structs and functions are supported"); - } - - // Might as well insert all the basic types from the start - void createBasicTypes() - { - type_map[DType.Void] = Type.Void; - - type_map[DType.Bool] = Type.Int1; - type_map[DType.Byte] = Type.Int8; - type_map[DType.UByte] = Type.Int8; - type_map[DType.Short] = Type.Int16; - type_map[DType.UShort] = Type.Int16; - type_map[DType.Int] = Type.Int32; - type_map[DType.UInt] = Type.Int32; - type_map[DType.Long] = Type.Int64; - type_map[DType.ULong] = Type.Int64; - - type_map[DType.Float] = Type.Float; - type_map[DType.Double] = Type.Double; - type_map[DType.Real] = Type.X86_FP80; - - type_map[DType.Char] = Type.Int8; - type_map[DType.WChar] = Type.Int16; - type_map[DType.DChar] = Type.Int32; - } - -private: - - // llvm stuff - DModule mod; - .llvm.llvm.Module m; - Builder b; - Function llvm_memcpy; - ConstantInt ZeroIndex; - Type BytePtr; - Type[DType] type_map; - - SimpleSymbolTable table; -} - -private Operator op2op(BinaryExp.Operator op) -{ - alias BinaryExp.Operator O; - Operator res; - switch (op) { - case O.Add: res = Operator.Add; break; - case O.Sub: res = Operator.Sub; break; - case O.Mul: res = Operator.Mul; break; - case O.Div: res = Operator.Div; break; - case O.LeftShift: res = Operator.Shl; break; - case O.RightShift: res = Operator.AShr; break; - case O.UnsignedRightShift: res = Operator.LShr; break; - - case O.And: res = Operator.And; break; - case O.Or: res = Operator.Or; break; - case O.Xor: res = Operator.Xor; break; - - case O.Eq: res = Operator.Eq; break; - case O.Ne: res = Operator.Ne; break; - case O.Lt: res = Operator.Lt; break; - case O.Le: res = Operator.Le; break; - case O.Gt: res = Operator.Gt; break; - case O.Ge: res = Operator.Ge; break; - } - return res; -} - -private struct LLVMPred -{ - bool isValid = false; - bool isReal; - union { - IntPredicate intPred; - RealPredicate realPred; - } - - static LLVMPred Int(IntPredicate p) - { - LLVMPred res; - res.isValid = true; - res.isReal = false; - res.intPred = p; - return res; - } - static LLVMPred Real(RealPredicate p) - { - LLVMPred res; - res.isValid = true; - res.isReal = true; - res.realPred = p; - return res; - } -} -private LLVMPred predFromBI(BuiltinOperation op) -{ - alias BuiltinOperation O; - LLVMPred pred; - switch (op) { - case O.Eq: pred = LLVMPred.Int(IntPredicate.EQ); break; - case O.Ne: pred = LLVMPred.Int(IntPredicate.NE); break; - - case O.SLt: pred = LLVMPred.Int(IntPredicate.SLT); break; - case O.ULt: pred = LLVMPred.Int(IntPredicate.ULT); break; - case O.FLt: pred = LLVMPred.Real(RealPredicate.OLT); break; - - case O.SLe: pred = LLVMPred.Int(IntPredicate.SLE); break; - case O.ULe: pred = LLVMPred.Int(IntPredicate.ULE); break; - case O.FLe: pred = LLVMPred.Real(RealPredicate.OLE); break; - - case O.SGt: pred = LLVMPred.Int(IntPredicate.SGT); break; - case O.UGt: pred = LLVMPred.Int(IntPredicate.UGT); break; - case O.FGt: pred = LLVMPred.Real(RealPredicate.OGT); break; - - case O.SGe: pred = LLVMPred.Int(IntPredicate.SGE); break; - case O.UGe: pred = LLVMPred.Int(IntPredicate.UGE); break; - case O.FGe: pred = LLVMPred.Real(RealPredicate.OGE); break; - }; - return pred; -} - -private class VisitFuncDecls : Visitor!(void) -{ - void delegate(FuncDecl) dg; - this(void delegate(FuncDecl funcDecl) dg) - { - this.dg = dg; - } - - override void visitFuncDecl(FuncDecl fd) - { - dg(fd); - } -} - -private class SimpleSymbolTable -{ - Value[char[]][] namedValues; - - void enterScope() - { - namedValues ~= cast(Value[char[]])["__dollar":null]; - } - - void leaveScope() - { - namedValues.length = namedValues.length - 1; - } - - Value put(Value val, char[] key) - { - namedValues[$ - 1][key] = val; - return val; - } - - Value find(char[] key) - { - foreach_reverse (map; namedValues) - if(auto val_ptr = key in map) - return *val_ptr; - return null; - } - - alias find opIndex; - alias put opIndexAssign; -} - diff -r d442ce39917c -r 55ea834c8675 lexer/Keyword.d --- a/lexer/Keyword.d Sun Aug 10 16:23:09 2008 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,98 +0,0 @@ -module lexer.Keyword; - -import lexer.Token; - -/** - A list of keywords in an associative array that link a string - representation of the keyword to a Tok - */ -Tok[char[]] keywords; - -static this () -{ - keywords = - [ - // types - "byte"[] : Tok.Byte, - "ubyte" : Tok.Ubyte, - "short" : Tok.Short, - "ushort" : Tok.Ushort, - "int" : Tok.Int, - "uint" : Tok.Uint, - "long" : Tok.Long, - "ulong" : Tok.Ulong, - - "char" : Tok.Char, - "wchar" : Tok.Wchar, - "dchar" : Tok.Dchar, - - "bool" : Tok.Bool, - - "float" : Tok.Float, - "double" : Tok.Double, - - "void" : Tok.Void, - - // type related - "struct" : Tok.Struct, - "function" : Tok.Function, - "delegate" : Tok.Delegate, - "class" : Tok.Class, - "interface" : Tok.Interface, - "union" : Tok.Union, - "typedef" : Tok.Typedef, - "typeid" : Tok.Typeid, - "typeof" : Tok.Typeof, - "sizeof" : Tok.Sizeof, - "alias" : Tok.Alias, - "this" : Tok.This, - "new" : Tok.New, - "null" : Tok.Null, -// "super" : Tok.Super, - - // control flow - "if" : Tok.If, - "else" : Tok.Else, - "while" : Tok.While, - "for" : Tok.For, - "switch" : Tok.Switch, - "case" : Tok.Case, - "default" : Tok.Default, - "break" : Tok.Break, - "return" : Tok.Return, - "cast" : Tok.Cast, - - // modules - "module" : Tok.Module, - "import" : Tok.Import, - - // attributse - "public" : Tok.Public, - "private" : Tok.Private, - "protected" : Tok.Protected, - "package" : Tok.Package, - "export" : Tok.Export, - "static" : Tok.Static, - "final" : Tok.Final, - "const" : Tok.Const, - "abstract" : Tok.Abstract, - "override" : Tok.Override, - "deprecated": Tok.Deprecated, - "auto" : Tok.Auto, - "extern" : Tok.Extern, - - // exceptions - "assert" : Tok.Assert, - "throw" : Tok.Throw, - "try" : Tok.Try, - "catch" : Tok.Catch, - "finally" : Tok.Finally, - - // functions - "in" : Tok.In, - "out" : Tok.Out, - "body" : Tok.Body, - - "asm" : Tok.Asm - ]; -} diff -r d442ce39917c -r 55ea834c8675 lexer/Lexer.d --- a/lexer/Lexer.d Sun Aug 10 16:23:09 2008 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,500 +0,0 @@ -module lexer.Lexer; - -import basic.Message, - basic.SourceManager; - -import lexer.Token, - lexer.Keyword; - -import tango.io.Stdout; - -/** - The Lexer class will supply you with methods to tokenize a D file. Supply the - Lexer with a DataSource and you can 'peek' and 'next' Tokens from the file. - - For more info about Tokens, look up the lexer.Token module. -*/ -class Lexer -{ -public: - - /** - Create a new Lexer. - */ - this(SourceLocation start, SourceManager src_mgr, MessageHandler messages) - { - this.messages = messages; - sm = src_mgr; - start_loc = start; - position = 0; - source = sm.getRawData(start_loc); - - - charTable.length = 256; - foreach (c; "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ_") - charTable[c] = CharType.Letter; - - foreach (c; "0123456789") - charTable[c] = CharType.Number; - - foreach (c; "(){}[];:.,=!<>+-*/%&\"`") - charTable[c] = CharType.Symbol; - - foreach (c; " \n") - charTable[c] = CharType.Whitespace; - - foreach (c; "'\\") - charTable[c] = CharType.Other; - - symbolFunctions.length = 256; - - symbolFunctions['('] = &openParentheses; - symbolFunctions[')'] = &closeParentheses; - symbolFunctions['{'] = &openBrace; - symbolFunctions['}'] = &closeBrace; - symbolFunctions['['] = &openBracket; - symbolFunctions[']'] = &closeBracket; - symbolFunctions[';'] = &seperator; - symbolFunctions[':'] = : - symbolFunctions['.'] = ˙ - symbolFunctions[','] = , - symbolFunctions['='] = &eq; - symbolFunctions['!'] = ≠ - symbolFunctions['<'] = ≤ - symbolFunctions['>'] = ≥ - symbolFunctions['+'] = + - symbolFunctions['-'] = − - symbolFunctions['*'] = ☆ - symbolFunctions['/'] = &slash; - symbolFunctions['%'] = &percent; - symbolFunctions['&'] = ∧ - symbolFunctions['"'] = &string; - symbolFunctions['`'] = &string; - - last = Token(Tok.EOF, SLoc() + 1, 0); - } - - /** - Get the next token from the source. This method will move the - internal position forward to the next Token. - - return: A Token - Token.type is TokType.EOF if there is - no more tokens in the file. - */ - Token next() - { - Token res; - switch (getNextChar) - { - case CharType.EOF: - return Token(Tok.EOF, last.location, 0); - - case CharType.Whitespace: - position += 1; - res = this.next; - break; - - case CharType.Symbol: - res = lexSymbol; - break; - - case CharType.Letter: - res = lexLetter; - break; - - case CharType.Number: - res = lexNumber; - break; - case CharType.Other: - messages.report(UnexpectedTok, Loc(position)).fatal(ExitLevel.Lexer); - } - if (res.type != Tok.EOF) - last = res; - return res; - } - - /** - Get the next token from the source. This method will NOT move the - internal position forward, and thereby having no side-effects. - - return: A Token - Token.type is TokType.EOF if there is - no more tokens in the file. - */ - Token peek(int skip = 0) - { - int oldPosition = this.position; - while (skip-- > 0) - this.next; - Token t = this.next; - this.position = oldPosition; - return t; - } - - Token last; -private: - - Token eq() - { - if(source[position] == '=') - return Token(Tok.Eq, Loc(position++ - 1), 2); - return Token(Tok.Assign, Loc(position - 1), 1); - } - Token openBrace() - { - return Token(Tok.OpenBrace, Loc(position - 1), 1); - } - Token closeBrace() - { - return Token(Tok.CloseBrace, Loc(position - 1), 1); - } - Token openParentheses() - { - return Token(Tok.OpenParentheses, Loc(position - 1), 1); - } - Token closeParentheses() - { - return Token(Tok.CloseParentheses, Loc(position - 1), 1); - } - Token openBracket() - { - return Token(Tok.OpenBracket, Loc(position - 1), 1); - } - Token closeBracket() - { - return Token(Tok.CloseBracket, Loc(position - 1), 1); - } - Token seperator() - { - return Token(Tok.Seperator, Loc(position - 1), 1); - } - Token colon() - { - return Token(Tok.Colon, Loc(position - 1), 1); - } - Token dot() - { - int pos = 0; - while(getNextChar(0) == CharType.Number || - this.source[position + pos + 1] == '_') - { - if(getNextChar(0) == CharType.Number) - { - position--; - return lexNumber(); - } - pos++; - } - return Token(Tok.Dot, Loc(position - 1), 1); - } - Token comma() - { - return Token(Tok.Comma, Loc(position - 1), 1); - } - Token ne() - { - if(source[position] == '=') - return Token(Tok.Ne, Loc(position++ - 1), 2); - return Token(Tok.Not, Loc(position - 1), 1); - } - Token le() - { - if(source[position] == '=') - return Token(Tok.Le, Loc(position++ - 1), 2); - if(source[position] == '<') - return Token(Tok.LeftShift, Loc(position++ - 1), 2); - return Token(Tok.Lt, Loc(position - 1), 1); - } - Token ge() - { - if(source[position] == '=') - return Token(Tok.Ge, Loc(position++ - 1), 2); - if(source[position] == '>') - if(source[position+1] == '>') - { - position += 2; - return Token(Tok.UnsignedRightShift, Loc(position - 1), 3); - } - else - return Token(Tok.RightShift, Loc(position++ - 1), 2); - return Token(Tok.Gt, Loc(position - 1), 1); - } - Token plus() - { - if(source[position] == '=') - return Token(Tok.PlusAssign, Loc(position++ - 1), 2); - return Token(Tok.Plus, Loc(position - 1), 1); - } - Token minus() - { - if(source[position] == '=') - return Token(Tok.MinusAssign, Loc(position++ - 1), 2); - return Token(Tok.Minus, Loc(position - 1), 1); - } - Token star() - { - if(source[position] == '=') - return Token(Tok.StarAssign, Loc(position++ - 1), 2); - return Token(Tok.Star, Loc(position - 1), 1); - } - Token slash() - { - int p = position; - switch(source[position]) - { - case '=': - return Token(Tok.SlashAssign, Loc(position++ - 1), 2); - case '/': - while(getNextChar != CharType.EOF) - { - if(source[position++] == '\n') - return this.next; - } - return Token(Tok.EOF, Loc(position), 0); - - case '*': - position += 2; - while(getNextChar != CharType.EOF) - { - ++position; - if(source[position-2] == '*') - if(source[position-1] == '/') - { - return this.next; - } - } - messages.report(UnexpectedEOFBlock,Loc(p)).fatal(ExitLevel.Lexer); - - case '+': - position += 2; - int nesting = 1; - while(getNextChar != CharType.EOF) - { - ++position; - if(source[position-2] == '+') - if(source[position-1] == '/') - { - position++; - nesting--; - } - - if(source[position-2] == '/') - if(source[position-1] == '+') - { - nesting++; - position++; - } - - if(nesting == 0) - return this.next; - } - messages.report( - UnexpectedEOFBlock, - Loc(p)).fatal(ExitLevel.Lexer); - - default: - return Token(Tok.Slash, Loc(position - 1), 1); - } - } - Token and() - { - return Token(Tok.And, Loc(position - 1), 1); - } - Token percent() - { - if(source[position] == '=') - return Token(Tok.PercentAssign, Loc(position++ - 1), 2); - return Token(Tok.Percent, Loc(position - 1), 1); - } - - Token string() - { - --position; - int start = position; - if(getNextChar() == CharType.Letter) - position++; - char end = '`'; - switch(source[position]) - { - case '"': - if(position > 0) - if(source[position-1] == 'r') - { - end = '"'; - goto string_wys; - } - ++position; - while(getNextChar != CharType.EOF) - { - ++position; - if (source[position-1] == '"' ) - { - if(getNextChar != CharType.EOF) - if (source[position] == 'c' || - source[position] == 'w' || - source[position] == 'd') - position++; - - return Token(Tok.String, Loc(start), position - start); - } - else if (source[position-1] == '\\') - position++; - } - break; - case '`': -string_wys: - ++position; - while(getNextChar != CharType.EOF) - { - ++position; - if (source[position-1] == end ) - return Token(Tok.String, Loc(start), position - start); - } - break; - } - messages.report(UnexpectedEOFBlock, Loc(position)).fatal(ExitLevel.Lexer); - } - - Token lexNumber () - { - bool sign; - - int i = 0; - - - bool end = false; - while(!end) - { - switch(getNextChar(i)) - { - case CharType.Number: - break; - case CharType.Symbol: - if(this.source[position+i] == '.') - { - break; - } - if (this.source[position+i] == '+' || - this.source[position+i] == '-') - { - if (source[position+i-1] == 'e' || - source[position+i-1] == 'E') - break; - } - end = true; - continue; - case CharType.Letter: - if(this.source[position+i] == '_') - break; - if (this.source[position+i] == 'e' || - this.source[position+i] == 'E') - { - break; - } - end = true; - continue; - - default: - end = true; - continue; - } - i++; - } - - while(source[position+i] == 'u' || - source[position+i] == 'U' || - source[position+i] == 'L') - i += 1; - - - - position += i; - - return Token(Tok.Integer, Loc(position - i), i); - } - - Token lexSymbol () - { - Token t = symbolFunctions[source[position++]](); - - return t; - } - - Token lexLetter () - { - int i = 0; - bool hasNumber = false; - if (source[position+1] == '"' || - source[position+1] == '`') - { - ++position; - return string; - } - while (getNextChar(++i) == CharType.Letter || - getNextChar(i) == CharType.Number) - { - if (getNextChar(i) == CharType.Number) - { - hasNumber = true; - } - } - - Token t = Token(Tok.Identifier, Loc(), i); - - if (!hasNumber) - { - char[] str = source[position .. position + i]; - if(str in keywords) - t.type = keywords[str]; - } - - position += i; - - return t; - } - - CharType getNextChar(int offset = 0) - { - if (position + offset >= this.source.length) - return CharType.EOF; - - char current = source[position + offset]; - - CharType c = charTable[current]; - - if(c == CharType.INVALID) - messages.report(InvalidSymbol, Loc()) - .arg(Integer.toString(cast(int)current)) - .fatal(ExitLevel.Lexer); - - return c; - - } - - private final SourceLocation Loc(int pos = -1) - { - if (pos < 0) - return start_loc + position; - return start_loc + pos; - } - - SourceManager sm; - SourceLocation start_loc; - int position; - char[] source; - MessageHandler messages; - CharType[] charTable; - Token delegate()[] symbolFunctions; -} - -enum CharType : ubyte -{ - INVALID, - Letter, - Number, - Symbol, - Whitespace, - Other, - - EOF -} - diff -r d442ce39917c -r 55ea834c8675 lexer/Token.d --- a/lexer/Token.d Sun Aug 10 16:23:09 2008 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,328 +0,0 @@ -module lexer.Token; - -public -import basic.SourceLocation, - basic.SourceManager; - -import Integer = tango.text.convert.Integer; - -/** - The Token struct will be used through the Lexer, Parser and other - modules as a location into source. - - The Token should always be optimized for size to limit unnecessary - memory usage. - */ -struct Token -{ - Tok type; - SLoc location; - uint length; - - /** - Create a new token with a Tok type, Location in source and a - length of how many chars the Token span in the source - */ - static Token opCall (Tok type, SLoc location, uint length) - { - Token t; - t.type = type; - t.location = location; - t.length = length; - return t; - } - - /** - Get the type of the Token as a string - */ - char[] get (SourceManager sm) - { - if (isIdentifier) - return sm.getText(asRange); - return typeToString[this.type]; - } - - /** - A human readable dump of a Token - */ - char[] toString () - { - return typeToString[this.type]; - } - - /// Get the range of this token - SourceRange asRange() { return SourceRange(location, location + length); } - - /** - Returns true if the type of this token is a basic type (int, float, ...). - Void is included, although a void in it self is not really a type. - */ - bool isBasicType() - { - return type >= Tok.Byte && type <= Tok.Void; - } - - /** - Returns true for all the various assignments (=, +=, *= ...) - */ - bool isAssignment() - { - return type >= Tok.Assign && type <= Tok.PercentAssign; - } - - /** - Returns true for all attributes( public, static, private...) - */ - bool isAttribute() - { - return type >= Tok.Public && type <= Tok.Extern; - } - - /** - Returns true for all attributes( public, static, private...) - */ - bool isBaseClassProtection() - { - return type >= Tok.Public && type <= Tok.Export; - } - - /** - just a shortcut to avoid `token.type == tok.Switch`. - */ - bool isSwitch() - { - return type == Tok.Switch; - } - - /** - just a shortcut to avoid `token.type == tok.While`. - */ - bool isWhile() - { - return type == Tok.While; - } - - /** - just a shortcut to avoid `token.type == tok.For`. - */ - bool isFor() - { - return type == Tok.For; - } - - /** - just a shortcut to avoid `token.type == tok.If`. - */ - bool isIf() - { - return type == Tok.If; - } - - /** - just a shortcut to avoid `token.type == tok.Return`. - */ - bool isReturn() - { - return type == Tok.Return; - } - - /** - Just a shortcut to avoid `token.type == Tok.Identifier`. - */ - bool isIdentifier() - { - return type == Tok.Identifier; - } -} - -/** - Tok is short for TokenType. This enum list is to supply the Token - with a type. - - This enum is used to switch over "many" places. - */ -enum Tok : ushort -{ - /* Non-code related tokens */ - EOF, - - /* Basic types */ - Identifier, - Integer, - String, - - /* Basic operators */ - Assign, - PlusAssign, - MinusAssign, - StarAssign, - SlashAssign, - PercentAssign, - Plus, - Minus, - Star, - Slash, - Percent, - LeftShift, RightShift, UnsignedRightShift, - Comma, - And, - - /* Symbols */ - OpenParentheses, - CloseParentheses, - OpenBrace, - CloseBrace, - OpenBracket, - CloseBracket, - Seperator, - Colon, - Dot, - - /* Comparator operators */ - Eq, Ne, - Lt, Gt, - Le, Ge, - - Not, - - - /* Keywords */ - Byte, Ubyte, - Short, Ushort, - Int, Uint, - Long, Ulong, - - Char, Wchar, Dchar, - - Float, Double, - - Bool, - - Void, - - Struct, Function, Delegate, Class, This, - Interface, Union, Typedef, Typeid, - Typeof, Sizeof, Alias, - - If, Else, - While, - For, - Switch, Case, Default, Break, - Return, Cast, - - Module, Import, - - New, Null, - - /* Attributes */ - Public, Private, Package, Export, Protected, - Static, - Final, - Const, - Abstract, - Override, - Deprecated, - Auto, - Extern, - - Align, - - Asm, - - In, Out, Body, - - Assert, Throw, Try, Catch, Finally, - - - - -} - -/** - An associative array to supply a Tok to String function. - - Keep always this list updated when adding a new Tok. - */ -public char[][Tok] typeToString; - -static this() -{ - typeToString = - [ - Tok.EOF:"EOF"[], - Tok.Identifier:"identifier", - Tok.Byte:"byte", - Tok.Short:"short", - Tok.Int:"int", - Tok.Long:"long", - Tok.Char:"char", - Tok.Wchar:"wchar", - Tok.Dchar:"dchar", - Tok.Bool:"bool", - Tok.Void:"void", - Tok.Function:"function", - Tok.Eq:"==", - Tok.Ne:"!=", - Tok.Lt:"<", - Tok.Le:"<=", - Tok.Gt:">", - Tok.Ge:">=", - Tok.OpenParentheses:"(", - Tok.CloseParentheses:")", - Tok.OpenBrace:"{", - Tok.CloseBrace:"}", - Tok.OpenBracket:"[", - Tok.CloseBracket:"]", - Tok.Dot:"-", - Tok.Assign:"=", - Tok.Plus:"+", - Tok.PlusAssign:"+=", - Tok.Minus:"-", - Tok.MinusAssign:"-=", - Tok.Star:"*", - Tok.StarAssign:"*=", - Tok.Slash:"/", - Tok.SlashAssign:"/=", - Tok.Percent:"%", - Tok.PercentAssign:"%=", - Tok.LeftShift:"<<", - Tok.RightShift:">>", - Tok.UnsignedRightShift:">>>", - Tok.Integer:"int", - Tok.If:"if", - Tok.While:"while", - Tok.For:"for", - Tok.Switch:"switch", - Tok.Case:"case", - Tok.Default:"default", - Tok.Comma:",", - Tok.Return:"return", - Tok.Struct:"struct", - Tok.Class:"class", - Tok.This:"this", - Tok.Colon:":", - Tok.Seperator:";", - Tok.And:"&", - Tok.Cast:"cast", - Tok.Module:"module", - Tok.Import:"import", - Tok.String:"String", - Tok.Public:"public", - Tok.Private:"private", - Tok.Protected:"protected", - Tok.Package:"package", - Tok.Export:"export", - Tok.Static:"static", - Tok.Final:"finale", - Tok.Public:"public", - Tok.Const:"const", - Tok.Abstract:"abstract", - Tok.Override:"override", - Tok.Deprecated:"deprecated", - Tok.Auto:"auto", - Tok.Extern:"extern", - Tok.New:"new", - Tok.Null:"null", - Tok.Alias:"alias" - ]; -} diff -r d442ce39917c -r 55ea834c8675 llvm.patch --- a/llvm.patch Sun Aug 10 16:23:09 2008 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,156 +0,0 @@ -diff -Naur -X exclude llvmbindings/llvm/llvm.d llvmbindings_ny/llvm/llvm.d ---- llvmbindings/llvm/llvm.d 2008-07-23 00:11:36.000000000 +0200 -+++ llvmbindings_ny/llvm/llvm.d 2008-07-22 23:51:15.000000000 +0200 -@@ -44,6 +44,8 @@ - alias LLVMVisibility Visibility; - /// - alias LLVMValueKind ValueKind; -+/// -+public alias LLVMParamAttr ParamAttr; - - /// - class Module -@@ -837,6 +839,20 @@ - return getValueOf(v); - } - /// -+ void addParamAttr(uint idx, ParamAttr PA) -+ { -+ auto v = LLVMGetParam(value, idx); -+ assert(v !is null); -+ LLVMAddParamAttr(v, PA); -+ } -+ /// -+ void removeParamAttr(uint idx, ParamAttr PA) -+ { -+ auto v = LLVMGetParam(value, idx); -+ assert(v !is null); -+ LLVMRemoveParamAttr(v, PA); -+ } -+ /// - uint intrinsicID() - { - return LLVMGetIntrinsicID(value); -diff -Naur -X exclude llvmbindings/llvm/type.d llvmbindings_ny/llvm/type.d ---- llvmbindings/llvm/type.d 2008-07-23 00:11:36.000000000 +0200 -+++ llvmbindings_ny/llvm/type.d 2008-07-23 00:07:46.000000000 +0200 -@@ -111,7 +111,7 @@ - Type refineAbstractType(Type to) { - assert(isAbstract()); - -- LLVMRefineAbstractType(type, to.type); -+ //LLVMRefineAbstractType(type, to.type); - - // Either type will do. Go through the registry to try to use the - // "canonical" Type object for the type. -diff -Naur -X exclude llvmbindings/llvm.patch llvmbindings_ny/llvm.patch ---- llvmbindings/llvm.patch 1970-01-01 01:00:00.000000000 +0100 -+++ llvmbindings_ny/llvm.patch 2008-07-22 23:45:58.000000000 +0200 -@@ -0,0 +1,107 @@ -+Index: llvm/c/Core.d -+=================================================================== -+--- llvm/c/Core.d (revision 170) -++++ llvm/c/Core.d (working copy) -+@@ -82,6 +82,20 @@ -+ */ -+ typedef LLVM_OpaqueMemoryBuffer* LLVMMemoryBufferRef; -+ -++enum LLVMParamAttr { -++ ZExt = 1<<0, -++ SExt = 1<<1, -++ NoReturn = 1<<2, -++ InReg = 1<<3, -++ StructRet = 1<<4, -++ NoUnwind = 1<<5, -++ NoAlias = 1<<6, -++ ByVal = 1<<7, -++ Nest = 1<<8, -++ ReadNone = 1<<9, -++ ReadOnly = 1<<10 -++} -++ -+ enum LLVMTypeKind { -+ Void, /**< type with no size */ -+ Float, /**< 32 bit floating point type */ -+@@ -388,6 +402,14 @@ -+ /*const*/ char *LLVMGetCollector(LLVMValueRef Fn); -+ void LLVMSetCollector(LLVMValueRef Fn, /*const*/ char *Coll); -+ -++void LLVMAddParamAttr(LLVMValueRef Arg, LLVMParamAttr Attr); -++void LLVMRemoveParamAttr(LLVMValueRef Arg, LLVMParamAttr Attr); -++void LLVMSetParamAlignment(LLVMValueRef Arg, uint Align); -++void LLVMAddInstrParamAttr(LLVMValueRef Inst, uint Index, LLVMParamAttr Attr); -++void LLVMRemoveInstrParamAttr(LLVMValueRef Inst, uint Index, LLVMParamAttr Attr); -++void LLVMSetInstrParamAlignment(LLVMValueRef Inst, uint Index, uint Align); -++ -++ -+ /* Operations on basic blocks */ -+ LLVMValueRef LLVMBasicBlockAsValue(LLVMBasicBlockRef Bb); -+ int LLVMValueIsBasicBlock(LLVMValueRef Val); -+Index: llvm/llvm.d -+=================================================================== -+--- llvm/llvm.d (revision 170) -++++ llvm/llvm.d (working copy) -+@@ -43,6 +43,8 @@ -+ alias LLVMVisibility Visibility; -+ /// -+ alias LLVMValueKind ValueKind; -++/// -++public alias LLVMParamAttr ParamAttr; -+ -+ /// -+ class Module -+@@ -836,6 +838,20 @@ -+ return getValueOf(v); -+ } -+ /// -++ void addParamAttr(uint idx, ParamAttr PA) -++ { -++ auto v = LLVMGetParam(value, idx); -++ assert(v !is null); -++ LLVMAddParamAttr(v, PA); -++ } -++ /// -++ void removeParamAttr(uint idx, ParamAttr PA) -++ { -++ auto v = LLVMGetParam(value, idx); -++ assert(v !is null); -++ LLVMRemoveParamAttr(v, PA); -++ } -++ /// -+ uint intrinsicID() -+ { -+ return LLVMGetIntrinsicID(value); -+Index: llvm-fix.cpp -+=================================================================== -+--- llvm-fix.cpp (revision 170) -++++ llvm-fix.cpp (working copy) -+@@ -29,10 +29,10 @@ -+ APN.convert(SemanticsForType(unwrap(RealTy)), APFloat::rmNearestTiesToEven); -+ return wrap(ConstantFP::get(unwrap(RealTy), APN)); -+ } -+- -++/* -+ LLVMValueRef LLVMConstRealOfString(LLVMTypeRef RealTy, const char *Text) { -+ return wrap(ConstantFP::get(unwrap(RealTy), -+ APFloat(SemanticsForType(unwrap(RealTy)), Text))); -+ } -+- -++*/ -+ } -+Index: llvm-ext.cpp -+=================================================================== -+--- llvm-ext.cpp (revision 170) -++++ llvm-ext.cpp (working copy) -+@@ -80,9 +80,11 @@ -+ LLVMTargetDataRef LLVMGetTargetDataFromModule(LLVMModuleRef M) { -+ return wrap(new TargetData(unwrap(M))); -+ } -++/* -+ void LLVMDisposeTargetData(LLVMTargetDataRef TD) { -+ delete unwrap(TD); -+ } -++*/ -+ -+ // we need to be able to query the ABI size of a type as an integer -+ size_t LLVMGetABITypeSize(LLVMTargetDataRef TD, LLVMTypeRef T) { diff -r d442ce39917c -r 55ea834c8675 parser/Action.d --- a/parser/Action.d Sun Aug 10 16:23:09 2008 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,454 +0,0 @@ -module parser.Action; - -import lexer.Token; - -import basic.Attribute; - -/** - Used to indicate what type of operator is used in a given binary expression - (and unary expressions?) - */ -public enum Operator -{ - Assign, - AddAssign, - SubAssign, - MulAssign, - DivAssign, - ModAssign, - - Eq, Ne, - - Lt, Le, - Gt, Ge, - - Add, Sub, - Mul, Div, Mod, - - LeftShift, RightShift, UnsignedRightShift, -} - - -class Id -{ - public static Id opCall(Token tok) - { - auto id = new Id(); - id.tok = tok; - return id; - } - Token tok; -} - -class PointerTypeId : Id -{ - public static PointerTypeId opCall(Id id) - { - auto p = new PointerTypeId(); - p.id = id; - return p; - } - - Id id; -} - -class StaticArrayTypeId : Id -{ - public static StaticArrayTypeId opCall(Id id, Object number) - { - auto a = new StaticArrayTypeId(); - a.id = id; - a.number = number; - return a; - } - - Id id; - Object number; -} - -class FunctionTypeId : Id -{ - public static FunctionTypeId opCall(Id id, DeclT[] decls) - { - auto f = new FunctionTypeId(); - f.id = id; - f.decls = decls; - return f; - } - - Id id; - DeclT[] decls; -} - -/** - Represents a fully qualified name, with some packages and a final identifier. - The identifier should always be set, but packages may have length 0. - **/ -struct ModuleName -{ - Id id; - Id[] packages; - - /// Get the full ranged spanned by packages and identifier - SourceRange asRange() - { - SourceRange r = id.tok.asRange(); - foreach (identifier; packages) - r = r + identifier.tok.asRange(); - return r; - } -} - - /** - A few aliases to indicate what methods should be dealing with the same - types. - Not typesafe, and not using typedef because users would need a lot of - casts (and base type would be void*, so no possibility to synchronize, - print etc.) - */ -alias Object ExprT; -alias Object StmtT; /// ditto -alias Object DeclT; /// ditto -alias Object ModuleT; /// ditto - -/** - All methods are optional. - -Warning: Interface is not stable yet. Use the `override` keyword in all classes - inheriting from this to get warning if the interface changes. - */ -abstract class Action -{ - - - // -- Modules -- - - ModuleT actOnModule(ref Token _module, char[] name) - { - return null; - } - - /** - This action is called when a file does not start with a module - declaration - in which case there is no Token available. - - Instead a SLoc to the start of the file is given. - */ - ModuleT actOnImplicitModule(SourceLocation fileStart, char[] name) - { - return null; - } - - void actOnModuleDecl(ModuleT m, DeclT d) - { - } - - // -- Declarations -- - - /** - Called for an import statement, that may be renamed. Id name is null, - there is no rename. - - If there are selective imports, its handled in add - */ - DeclT actOnImport(ref Token _import, ref ModuleName target, Id* name) - { - return null; - } - - /** - */ - void addSelectiveImport(DeclT _import, ref Id target, Id* name) - { - } - - /** - Either we should have one case that handles a lot of things, or we should - have a lot of separate cases. - As an example, this method could handle the params in `int f(int, int)` - as well as handling `int x` at both top-level, in classes and in methods. - - The other solution is an addParamToFunc or similar. - */ - DeclT actOnDeclarator(ref Id type, ref Id name, ExprT init, Attribute att) - { - return null; - } - - DeclT actOnAliasDecl(DeclT decl, Attribute att) - { - return null; - } - - /** - Add a struct member to a struct. - */ - void actOnStructMember(DeclT st_decl, DeclT m_decl) - { - return null; - } - - /** - Add a class member to a struct. - */ - void actOnClassMember(DeclT cl_decl, DeclT m_decl) - { - return null; - } - - /** - Add a class member to a struct. - */ - void actOnClassBaseClass(DeclT cl_decl, ref Id name) - { - return null; - } - - /** - Add a class member to a struct. - */ - void actOnInterfaceMember(DeclT if_decl, DeclT m_decl) - { - return null; - } - - /** - Add a class member to a struct. - */ - void actOnInterfaceBaseClass(DeclT if_decl, ref Id name) - { - return null; - } - - /** - Add an initialization expression to a previously created decl. - - Used for default values on function params and for values to local - variables. - */ - void addInitToDeclarator(DeclT decl, ExprT exp) - { - } - - /** - Called at the start of a function, doesn't get a lot of info - that is - added later on, through addFuncArg and actOnEndOfFunction. - */ - DeclT actOnStartOfFunctionDef(ref Id type, ref Id name, Attribute att) - { - return null; - } - - /** - Add a new parameter to the function func. - */ - void addFuncArg(DeclT func, Id type, Id name) - { - } - - /** - Finish off the function, by giving it the body (a single statement, so - you probably want some sort of compound statement) - */ - DeclT actOnEndOfFunction(DeclT func, StmtT stmts) - { - return func; - } - - // -- Statements -- - - /** - Called after parsing a function/while/for/whatever body. - - Note that stmts is to be considered temporary, it might point into the - stack and needs to be copied before saving. - */ - StmtT actOnCompoundStmt(ref Token left, ref Token right, StmtT[] stmts) - { - return null; - } - - /** - An expression was used as a statement - this includes assignments, - function calls. - - Additionally the D spec dictates that expressions with no effect are not - legal as statements, but the parser can't test for this so it has to be - done in the later stages. - */ - StmtT actOnExprStmt(ExprT exp) - { - return null; - } - - /** - Called after parsing return statements. - - loc is the return token. - */ - StmtT actOnReturnStmt(ref Token loc, ExprT exp) - { - return null; - } - - /** - */ - StmtT actOnIfStmt(ref Token ifTok, ExprT cond, StmtT thenBody, - ref Token elseTok, StmtT elseBody) - { - return null; - } - - /** - */ - StmtT actOnWhileStmt(ref Token whileTok, ExprT cond, StmtT whileBody) - { - return null; - } - - /** - */ - StmtT actOnForStmt(ref Token forTok, StmtT init, ExprT cond, ExprT incre, StmtT forBody) - { - return null; - } - - /** - */ - StmtT actOnDeclStmt(DeclT decl) - { - return null; - } - - StmtT actOnStartOfSwitchStmt(Token _switch, ExprT exp) - { - return null; - } - - void actOnCaseStmt(StmtT stmt, Token _case, ExprT[] exps, StmtT[] stmts) - { - } - - void actOnDefaultStmt(StmtT stmt, Token _default, StmtT[] stmts) - { - } - - StmtT actOnFinishSwitchStmt(StmtT sw) - { - return sw; - } - - // -- Expressions -- - - /** - A single numerical constant -- this can be absolutely any kind of number. - Integers, floats, hex, octal, binary, imaginary and so on. - */ - ExprT actOnNumericConstant(Token op) - { - return null; - } - - /** - This is called when identifiers are used in expressions. - */ - ExprT actOnIdentifierExp(Id id) - { - return null; - } - - /** - This is called when strings are used in expression - */ - ExprT actOnStringExp(Token t) - { - return null; - } - - /** - Unary operator. - */ - ExprT actOnUnaryOp(Token op, ExprT operand) - { - return null; - } - - /** - Binary operator. - */ - ExprT actOnBinaryOp(SLoc op_loc, Operator op, ExprT l, ExprT r) - { - return null; - } - - /** - Called when using the 'dot' operator. - The left hand side can be any expression, but its only possible to look - up an identifier. - */ - ExprT actOnMemberReference(ExprT lhs, SourceLocation op, Id member) - { - return null; - } - - /** - Called when function calls are encountered. - - Note that args is temporary and might point into the stack. Remember to - copy before saving a reference to it. - */ - ExprT actOnCallExpr(ExprT func, ref Token left_paren, ExprT[] args, - ref Token right_paren) - { - return null; - } - - /** - Called when function calls are encountered. - */ - ExprT actOnIndexExpr(ExprT array, ref Token left_bracket, ExprT index, - ref Token right_bracket) - { - return null; - } - - /** - Cast expression. - */ - ExprT actOnCastExpr(ref Token _cast, Id type, ExprT exp) - { - return null; - } - - /** - New expression. - */ - ExprT actOnNewExpr(ref Id type, ExprT[] a_args, ExprT[] c_args) - { - return null; - } - - /** - Array Literal expression. - */ - ExprT actOnArrayLiteralExpr(ExprT[] exps, SLoc start, SLoc end) - { - return null; - } - - /** - Null expression. - */ - ExprT actOnNullExpr(SLoc pos) - { - return null; - } -} - -/** - Doesn't do anything at all - can be used for benchmarking the parser. - */ -class NullAction : Action -{ -} - diff -r d442ce39917c -r 55ea834c8675 parser/Parser.d --- a/parser/Parser.d Sun Aug 10 16:23:09 2008 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,1189 +0,0 @@ -module parser.Parser; - -import lexer.Lexer, - lexer.Token; - -import parser.Action; - -import basic.Message, - basic.Attribute; - -import basic.SmallArray, - basic.SourceManager; - -import tango.io.Stdout, - Integer = tango.text.convert.Integer; - -class Parser -{ - Action action; - MessageHandler messages; - alias Object Exp; - alias Object Stmt; - alias Object Decl; - alias Object Module; - - this(MessageHandler messages) - { - this.messages = messages; - } - - Module parse(SourceManager sm, Lexer lexer, Action act) - { - this.sm = sm; - this.lexer = lexer; - this.action = act; - - Module m; - if (peek.type == Tok.Module) - { - Token _module = next(); - ModuleName name = parseModuleName(); - m = action.actOnModule(_module, sm.getText(name.asRange())); - require(Tok.Seperator); - } - else - { - SLoc loc = peek.location; - m = action.actOnImplicitModule(loc, sm.getFile(loc)); - } - - auto nes = parseAttributeInit; - while( !isa(Tok.EOF) ) - { - while ( peek.isAttribute ) - nes ~= parseAttribute(nes[$-1]); - - foreach (d; parseDeclDef(nes[$-1].a)) - action.actOnModuleDecl(m, d); - - nes = parseAttributeScope(nes); - } - - return m; - } - -private: - Decl[] parseDeclDef(Attribute a) - { - if ( isa (Tok.Import) ) - return parseImports(); - - return [parseDecl(a)]; - } - - Decl parseDecl(Attribute att) - { - switch(peek.type) - { - case Tok.Struct: - Id type = Id(next()); - Id iden = Id(require(Tok.Identifier)); - return parseStruct(type, iden, att); - - case Tok.Class: - Id type = Id(next()); - Id iden = Id(require(Tok.Identifier)); - return parseClass(type, iden, att); - - case Tok.Interface: - Id type = Id(next()); - Id iden = Id(require(Tok.Identifier)); - return parseInterface(type, iden, att); - - case Tok.Alias: - next(); - auto decl = parseDecl(Attribute()); - return action.actOnAliasDecl(decl, att); - - case Tok.Identifier: - Id type = parseType; - Id iden = Id(require(Tok.Identifier)); - - switch(peek.type) - { - case Tok.Seperator: - Token sep = next(); - return action.actOnDeclarator(type, iden, null, att); - - case Tok.Assign: - Token assign = next(); - Exp exp = parseExpression(); - require(Tok.Seperator); - return action.actOnDeclarator(type, iden, exp, att); - - case Tok.OpenParentheses: - return parseFunc(type, iden, att); - - default: - auto n1 = next(); - isEOF(type.tok); - messages.report(UnexpectedTok, n1.location).arg(n1.get(sm)); - return action.actOnDeclarator(type, iden, null, att); - } - messages.report(InvalidDeclType, peek.location) - .arg(sm.getText(peek.asRange)); - - default: - if (peek.isBasicType) - goto case Tok.Identifier; - - messages.report(UnexpectedTok, peek.location) - .arg(sm.getText(peek.asRange)); - - next(); - return null; - } - messages.report(UnexpectedTok, peek.location) - .arg(peek.get(sm)) - .arg(Tok.Identifier) - .fatal(ExitLevel.Parser); - } - - Extern parseLinkageType() - { - Extern e = Extern.D; - if(peek(1).type != Tok.OpenParentheses) - return e; - - next(); next(); - - Token t = require(Tok.Identifier); - - switch(sm.getText(t.asRange)) - { - case "C": - if (peek(0).type == Tok.Plus && - peek(1).type == Tok.Plus) - e = Extern.CPlusPlus; - else - e = Extern.C; - break; - case "D": - break; - case "Windows": - e = Extern.Windows; - break; - case "Pascal": - e = Extern.Pascal; - break; - case "System": - e = Extern.System; - break; - default: - messages.report(UnexpectedLinkType, t.location); - } - - if (!isa(Tok.CloseParentheses)) - messages.report(UnexpectedTokSingle, peek.location); - - return e; - } - - /** - Parse a series of imports belonging to a single import token. - */ - Decl[] parseImports() - { - Token _import = require(Tok.Import); - SmallArray!(Decl) res; - void addToRes(Decl d) { res ~= d; } - - bool done = false; - while (!done && !isa(Tok.Seperator)) - { - ModuleName mod = parseModuleName(); - Token tok = peek; - switch (tok.type) - { - case Tok.Comma: - // import A, B.C; - // parse another module-name - next(); - res ~= action.actOnImport(_import, mod, null); - break; - case Tok.Assign: - // import B = A.A; - // ^- must be a single identifier - // renamed import - if (mod.packages.length != 0) - { - SLoc loc = mod.packages[0].tok.location; - messages.report(RenameMustBeSingleIdent, loc); - } - //if (isStatic) - // error("Static imports cannot be renamed"); - next(); - Id name = mod.id; - mod = parseModuleName(); - // create from mod and rename to `name` - res ~= action.actOnImport(_import, mod, &name); - break; - case Tok.Colon: - // import A : a; - // selective imports, potentially import A : print = a - next(); - Decl d = action.actOnImport(_import, mod, null); - // do-while on a comma: - // add explicit symbol - do - { - Id sym = parseIdentifier(); - Id dummy; - Id* name = null; - if (skip(Tok.Assign)) - { - dummy = sym; - name = &dummy; - sym = parseIdentifier(); - } - action.addSelectiveImport(d, sym, name); - - } while (skip(Tok.Comma)); - require(Tok.Seperator); - res ~= d; - return res.safe(); - case Tok.Seperator: - done = true; - break; - default: - goto Lerror; - } - res ~= action.actOnImport(_import, mod, null); - } - - require(Tok.Seperator); - return res.safe(); -Lerror: - while (!isa (Tok.Seperator)) - next(); - return res.safe(); - } - - /** - Parse interface - */ - Decl parseInterface(Id type, Id iden, Attribute att) - { - auto decl = action.actOnDeclarator(type, iden, null, att); - - if (peek.type == Tok.Colon) - // SuperInterfaces - { - next(); // Remove colon. - - Id identifier; - - // The identifier - identifier = Id(require(Tok.Identifier)); - - action.actOnInterfaceBaseClass(decl, identifier); - - // We should now have an optional list of items, each starting ',' - while (peek.type == Tok.Comma) - { - next(); // Remove comma - - // The identifier - identifier = Id(require(Tok.Identifier)); - - action.actOnInterfaceBaseClass(decl, identifier); - } - } - - require(Tok.OpenBrace); - - auto nes = parseAttributeInit; - while( !isa(Tok.EOF) && !isa(Tok.CloseBrace) ) - { - while ( peek.isAttribute ) - nes ~= parseAttribute(nes[$-1]); - - auto m_decl = parseDecl(nes[$-1].a); - action.actOnInterfaceMember(decl, m_decl); - - nes = parseAttributeScope(nes); - } - - require(Tok.CloseBrace); - - return decl; - } - - /** - Parse class - */ - Decl parseClass(Id type, Id iden, Attribute att) - { - auto decl = action.actOnDeclarator(type, iden, null, att); - - if (peek.type == Tok.Colon) - // BaseClassList - Super class and interfaces(in that order) - { - next(); // Remove colon. - - Token protection; - Id identifier; - - // First we expect an optional protection level. - if (peek.isBaseClassProtection) - protection = next(); - // Then the identifier - identifier = Id(require(Tok.Identifier)); - - action.actOnClassBaseClass(decl, identifier); - - // We should now have an optional list of items, each starting ',' - while (peek.type == Tok.Comma) - { - next(); // Remove comma - - // First we expect an optional protection level. - if (peek.isBaseClassProtection) - protection = next(); - // Then the identifier - identifier = Id(require(Tok.Identifier)); - - action.actOnClassBaseClass(decl, identifier); - } - } - - require(Tok.OpenBrace); - - auto nes = parseAttributeInit; - while( !isa(Tok.EOF) && !isa(Tok.CloseBrace) ) - { - while ( peek.isAttribute ) - nes ~= parseAttribute(nes[$-1]); - - switch(peek.type) - { - case Tok.This: - auto id = Id(next); - auto m_decl = parseFunc(iden, id, nes[$-1].a); - action.actOnClassMember(decl, m_decl); - break; - - default: - auto m_decl = parseDecl(nes[$-1].a); - action.actOnClassMember(decl, m_decl); - } - - nes = parseAttributeScope(nes); - } - - require(Tok.CloseBrace); - - return decl; - } - - /** - Parse struct - */ - Decl parseStruct(Id type, Id iden, Attribute att) - { - auto decl = action.actOnDeclarator(type, iden, null, att); - - require(Tok.OpenBrace); - - auto nes = parseAttributeInit; - while( !isa(Tok.EOF) && !isa(Tok.CloseBrace) ) - { - while ( peek.isAttribute ) - nes ~= parseAttribute(nes[$-1]); - - auto m_decl = parseDecl(nes[$-1].a); - action.actOnStructMember(decl, m_decl); - - nes = parseAttributeScope(nes); - } - - require(Tok.CloseBrace); - - return decl; - } - - Att[] parseAttributeInit() - { - Att[] nes; - nes ~= Att(); - nes[0].nested = Scope; - return nes; - } - - Att[] parseAttributeScope(Att[] nes) - { - while ( nes[$-1].nested == Single ) - nes.length = nes.length - 1; - - while ( isa(Tok.CloseBrace) && nes.length > 1) - { - while ( nes.length > 1 ) - { - if( nes[$-1].nested == Scope ) - { - nes.length = nes.length - 1; - next(); - break; - } - nes.length = nes.length - 1; - } - } - - return nes; - } - - Att parseAttribute(Att last) - { - Att _parseAttribute(Att last) - { - Att a = last; - a.nested = Single; - - switch(peek.type) - { - case Tok.Public: - a.a.setProtection(Protection.Public); - break; - case Tok.Private: - a.a.setProtection(Protection.Private); - break; - case Tok.Package: - a.a.setProtection(Protection.Package); - break; - case Tok.Protected: - a.a.setProtection(Protection.Protected); - break; - case Tok.Export: - a.a.setProtection(Protection.Export); - break; - case Tok.Static: - a.a.setStatic; - break; - case Tok.Final: - a.a.setFinal; - break; - case Tok.Const: - a.a.setConst; - break; - case Tok.Abstract: - a.a.setAbstract; - break; - case Tok.Override: - a.a.setOverride; - break; - case Tok.Deprecated: - a.a.setDeprecated; - break; - case Tok.Auto: - a.a.setAuto; - break; - case Tok.Extern: - Extern e = parseLinkageType; - a.a.setExtern(e); - break; - } - next(); - - return a; - } - - Att a = _parseAttribute(last); - - while (peek.isAttribute) - { - a = parseAttribute(a); - } - - if (peek.type == Tok.Colon) - { - a.nested = All; - next(); - } - else if (peek.type == Tok.OpenBrace) - { - a.nested = Scope; - next(); - } - - return a; - } - - enum : uint - { - Single, - Scope, - All - } - - struct Att - { - Attribute a; - uint nested; - } - - /** - Parse statements. - - This is the place to attack! - */ - Stmt parseStatement() - { - switch (peek.type) - { - case Tok.Return: - Token ret = next(); - Exp exp; - if (peek.type != Tok.Seperator) - exp = parseExpression(); - require(Tok.Seperator); - return action.actOnReturnStmt(ret, exp); - - case Tok.If: - Token _if = next(); - - require(Tok.OpenParentheses); - Exp cond = parseExpression(); - require(Tok.CloseParentheses); - - Stmt thenB = parseSingleOrCompoundStatement(); - - // if there is no else part we use the if as token, to have - // something than can be passed along - Token _else = _if; - Stmt elseB; - if (peek.type == Tok.Else) - { - _else = next(); - elseB = parseSingleOrCompoundStatement(); - } - return action.actOnIfStmt(_if, cond, thenB, _else, elseB); - - case Tok.While: - Token _while = next(); - require(Tok.OpenParentheses); - Exp cond = parseExpression(); - require(Tok.CloseParentheses); - Stmt bodyStmt = parseSingleOrCompoundStatement(); - return action.actOnWhileStmt(_while, cond, bodyStmt); - - case Tok.For: - Token _for = next(); - require(Tok.OpenParentheses); - Stmt init; - if ( isa(Tok.Seperator)) - require(Tok.Seperator); - else - init = parseStatement(); - - Exp cond; - if ( !isa(Tok.Seperator)) - cond = parseExpression(); - require(Tok.Seperator); - - Exp incre; - if ( !isa(Tok.CloseParentheses)) - incre = parseExpression(); - require(Tok.CloseParentheses); - - Stmt bodyStmt = parseSingleOrCompoundStatement(); - return action.actOnForStmt(_for, init, cond, incre, bodyStmt); - - case Tok.Switch: - auto t = next(); - require(Tok.OpenParentheses); - auto target = parseExpression(); - auto res = action.actOnStartOfSwitchStmt(t, target); - require(Tok.CloseParentheses); - require(Tok.OpenBrace); - while (true) - { - Stmt[] statements; - if (isa(Tok.Default)) - { - Token _default = next(); - require(Tok.Colon); - statements.length = 0; - while (peek.type != Tok.Case - && peek.type != Tok.Default - && peek.type != Tok.CloseBrace) - statements ~= parseStatement(); - action.actOnDefaultStmt(res, _default, statements); - continue; - } - - Token _case = peek; - if (_case.type != Tok.Case) - break; - next(); - - Exp[] literals; - do - { - Exp e = parseExpression(); - literals ~= e; - } - while (skip(Tok.Comma)); - require(Tok.Colon); - - while (peek.type != Tok.Case - && peek.type != Tok.Default - && peek.type != Tok.CloseBrace) - statements ~= parseStatement(); - - action.actOnCaseStmt(res, _case, literals, statements); - - if (peek.type == Tok.CloseBrace) - break; - } - require(Tok.CloseBrace); - return res; - - case Tok.Star: - auto exp = parseExpression(); - require(Tok.Seperator); - return action.actOnExprStmt(exp); - - case Tok.Identifier: - // If it's a '*' it must be a method. Otherwise it won't give - // any sense. - - if (isa(Tok.Function, 1) || - isa(Tok.Identifier, 1) || - isa(Tok.Star, 1)) - { - Attribute a; - return action.actOnDeclStmt(parseDecl(a)); - } - - if (isa(Tok.OpenBracket, 1)) - { - int i = 1; - while (isa(Tok.OpenBracket, i) || - isa(Tok.Star, i) || - isa(Tok.Identifier, i)) - { - if (isa(Tok.Identifier, i)) - return action.actOnDeclStmt(parseDecl(Attribute())); - - i++; - if (isa(Tok.Star,i-1)) - continue; - // Must be OpenBracket here.. - - if (isa(Tok.Integer, i)) - i++; - else - if (isa(Tok.CloseBracket, i)) - return action.actOnDeclStmt(parseDecl(Attribute())); - else - i++; - - if (!isa(Tok.CloseBracket, i)) - break; - i++; - } - if (isa(Tok.Function, i)) - return action.actOnDeclStmt(parseDecl(Attribute())); - } - - // Expression: a.b, a = b, a(b) etc. - Exp exp = parseExpression(); - require(Tok.Seperator); - return action.actOnExprStmt(exp); - - case Tok.Void: // And all basic types - return action.actOnDeclStmt(parseVarDecl()); - - default: - if (peek.isBasicType) - goto case Tok.Void; - - messages.report(UnexpectedBeginStmt, peek.location).arg(peek.get(sm)); - require(Tok.Seperator); - return null; - } - } - - Decl parseVarDecl() - { - // manually hardcoded to only support "type id [= exp];" - // as that is the only thing the codegen understands - Id type = parseType(); - Id id = Id(next()); - Exp init; - if (skip(Tok.Assign)) - init = parseExpression(); - require(Tok.Seperator); - Attribute att; - Decl d = action.actOnDeclarator(type, id, init, att); - return d; - } - - /** - Parses a function/method given the already parsed return type and name - */ - Decl parseFunc(ref Id type, ref Id name, Attribute att) - { - Decl func = action.actOnStartOfFunctionDef(type, name, att); - parseFuncArgs(func); - - if(peek.type == Tok.Seperator) - { - next(); - return func; - } - Stmt stmt = parseCompoundStatement(); - - return action.actOnEndOfFunction(func, stmt); - } - - /** - Parse the function arguments, assumes current token is (. - - Both the intitial paren and the ending paren is consumed. - */ - void parseFuncArgs(Decl func) - { - require(Tok.OpenParentheses); // Remove the "(" token. - - while(peek.type != Tok.CloseParentheses) - { - auto t = parseType(); - Id i; - if(peek.type == Tok.Identifier) - i = parseIdentifier(); - action.addFuncArg(func, t, i); - - if(peek.type == Tok.Comma) - next(); - } - - require(Tok.CloseParentheses); // Remove the ")" - } - - /** - Parse either a block, or a single statement as allowed after if, while - and for. - */ - Stmt parseSingleOrCompoundStatement() - { - if (peek.type == Tok.OpenBrace) - return parseCompoundStatement(); - return parseStatement(); - } - - /** - Parses a function-body or similar, expects an opening brace to be the - current token. - - Will consume both the starting { and ending } - */ - Stmt parseCompoundStatement() - { - Token lbrace = require(Tok.OpenBrace); - SmallArray!(Stmt, 32) stmts; // Try to use the stack only - while ( !isa(Tok.CloseBrace) && !isa(Tok.EOF) ) - stmts ~= parseStatement(); - Token rbrace = require(Tok.CloseBrace); - return action.actOnCompoundStmt(lbrace, rbrace, stmts.unsafe()); - } - - Id parseIdentifier() - { - Token tok = next(); - - if (tok.type is Tok.Identifier) - return Id(tok); - - messages.report(UnexpectedTokSingle, tok.location) - .arg(tok.get(sm)) - .arg(Tok.Identifier); - } - - ModuleName parseModuleName() - { - auto id = parseIdentifier(); - ModuleName mod; - while (skip(Tok.Dot)) - { - mod.packages ~= id; - if (peek.type != Tok.Identifier) { - messages.report(ExpectedIdAfterPackage, peek.location); - goto Lerror; - } - id = parseIdentifier(); - } - mod.id = id; - return mod; -Lerror: - while (!skip(Tok.Seperator)) - next(); - return mod; - } - - - /** - Parse a type - this includes pointer and array(at some point) types. - */ - Id parseType() - { - Token type = next(); - - Id currentType; - - if ( !(type.isBasicType || type.type == Tok.Identifier) ) - messages.report(InvalidType, type.location); - - currentType = Id(type); - - while(true) - { - switch(peek.type) - { - case Tok.Star: - currentType = PointerTypeId(currentType); - next(); - break; - case Tok.OpenBracket: - next(); - if (isa(Tok.Integer)) - currentType = StaticArrayTypeId( - currentType, - action.actOnNumericConstant( - require(Tok.Integer))); - require(Tok.CloseBracket); - break; - case Tok.Function: - next(); - - - require(Tok.OpenParentheses); // Remove the "(" token. - - DeclT[] decls; - - while(peek.type != Tok.CloseParentheses) - { - auto t = parseType(); - Id i; - if(peek.type == Tok.Identifier) - i = parseIdentifier(); - - // Act on function type param - decls ~= action.actOnDeclarator(t, i, null, Attribute()); - - if(peek.type == Tok.Comma) - next(); - } - - currentType = FunctionTypeId(currentType, decls); - - require(Tok.CloseParentheses); // Remove the ")" - break; - default: - goto end; - } - } -end: - return currentType; - } - -private: - // -- Expression parsing -- // - Exp parsePostfixExp(Exp target) - { - switch(peek.type) - { - case Tok.Dot: - switch(peek(1).type) - { - case Tok.Identifier: - Token op = next(); - Id member = Id(next()); - Exp exp = action.actOnMemberReference(target, op.location, member); - return parsePostfixExp(exp); - default: - Token t = peek(1); - messages.report(ExpectedIdAfterDot, t.location); - } - case Tok.OpenBracket: - Token open = next(); - Exp index = parseExpression(); - Token close = require(Tok.CloseBracket); - return action.actOnIndexExpr(target, open, index, close); - default: - return target; - } - } - - Exp parseExpression(int p = 0) - { - auto exp = P(); - Token n = peek(); - BinOp* op = null; - while ((op = binary(n.type)) != null && op.prec >= p) - { - next(); - int q = op.leftAssoc? 1 + op.prec : op.prec; - auto exp2 = parseExpression(q); - exp = action.actOnBinaryOp(n.location, op.operator, exp, exp2); - n = peek(); - } - - return exp; - } - - Exp P() - { - Token n = next(); - if (auto op = unary(n.type)) - return action.actOnUnaryOp(n, parseExpression(op.prec)); - else if (n.type == Tok.OpenParentheses) - { - auto e = parseExpression(0); - require(Tok.CloseParentheses); - return e; - } - else if (n.type == Tok.Identifier) - { - Exp value = action.actOnIdentifierExp(Id(n)); - Exp iden = parsePostfixExp(value); - switch(peek.type) - { - case Tok.OpenParentheses: - Token lp = next(); - SmallArray!(Exp, 8) args; - while(peek.type != Tok.CloseParentheses) - { - if(peek.type == Tok.Comma) - next(); - args ~= parseExpression(); - } - - Token rp = next(); - return action.actOnCallExpr(iden, lp, args.unsafe(), rp); - - default: - return iden; - } - } - else if (n.type == Tok.Null) - return action.actOnNullExpr(n.location); - else if (n.type == Tok.Cast) - return parseCast(n); - else if (n.type == Tok.Integer) - return action.actOnNumericConstant(n); - else if (n.type == Tok.String) - return action.actOnStringExp(n); - else if (n.type == Tok.OpenBracket) - { - // Array literals - Exp[] exps; - exps ~= parseExpression(); - - while (isa(Tok.Comma)) - { - next(); - - if (isa(Tok.CloseBracket)) - break; - exps ~= parseExpression(); - } - scope e = require(Tok.CloseBracket); - return action.actOnArrayLiteralExpr(exps, n.location, e.location); - } - else if (n.type == Tok.New) - { - Exp[] allocator_args; - Exp[] constructor_args; - - if ( isa(Tok.OpenParentheses)) - { - next(); // Remove OpenParentheses - - if ( !isa(Tok.CloseParentheses ) ) - { - allocator_args ~= parseExpression; - - while ( isa(Tok.Comma) ) - { - next(); // Remove Comma - - allocator_args ~= parseExpression; - } - } - require(Tok.CloseParentheses); - } - - auto type = parseType; - - if ( isa(Tok.OpenParentheses)) - { - next(); // Remove OpenParentheses - - if ( !isa(Tok.CloseParentheses ) ) - { - constructor_args ~= parseExpression; - - while ( isa(Tok.Comma) ) - { - next(); // Remove Comma - - constructor_args ~= parseExpression; - } - } - require(Tok.CloseParentheses); - } - return action.actOnNewExpr(type, allocator_args, constructor_args); - } - - messages.report(ExpectedExp, n.location) - .fatal(ExitLevel.Parser); - return null; - } - - Exp parseCast(ref Token _cast) - { - require(Tok.OpenParentheses); - auto n = next(); - if(!n.isBasicType && !n.isIdentifier) - messages.report(ExpectedCastType, n.location); - - require(Tok.CloseParentheses); - auto exp = P(); - return action.actOnCastExpr(_cast, Id(n), exp); - } - - struct UnOp - { - Tok tokenType; - int prec; - } - - static const UnOp[] _unary = - [ - {Tok.Minus, 4}, - {Tok.Star, 4}, - {Tok.And, 4} - ]; - UnOp* unary(Tok t) - { - foreach (ref op; _unary) - if (op.tokenType == t) - return &op; - return null; - } - - struct BinOp - { - Tok tokenType; - int prec; - bool leftAssoc; - Operator operator; - } - - static const BinOp[] _binary = - [ - {Tok.Assign, 1, false, Operator.Assign}, - {Tok.PlusAssign, 1, false, Operator.AddAssign}, - {Tok.MinusAssign, 1, false, Operator.SubAssign}, - {Tok.StarAssign, 1, false, Operator.MulAssign}, - {Tok.SlashAssign, 1, false, Operator.DivAssign}, - {Tok.PercentAssign, 1, false, Operator.ModAssign}, - - // =, += etc. 1 - // (need special-case for the ternary operator at this level) - // ||, 2 - // &&, 3 - // |, 4 - // &, 5 - // ^, 6 - // ==, !=, is, !is, 7 - // <, <= etc, 7 - // in, 7 - // <<, >>, >>>, 8 - // +, -, ~, 9 - // *, /, %, 10 - // unary operators here - - {Tok.Eq, 2, true, Operator.Eq}, - {Tok.Ne, 2, true, Operator.Ne}, - - {Tok.Lt, 2, true, Operator.Lt}, - {Tok.Le, 2, true, Operator.Le}, - {Tok.Gt, 2, true, Operator.Gt}, - {Tok.Ge, 2, true, Operator.Ge}, - - {Tok.Plus, 3, true, Operator.Add}, - {Tok.Minus, 3, true, Operator.Sub}, - - {Tok.Star, 5, true, Operator.Mul}, - {Tok.Slash, 5, true, Operator.Div}, - {Tok.Percent, 5, true, Operator.Mod}, - - {Tok.LeftShift, 8, true, Operator.LeftShift}, - {Tok.RightShift, 8, true, Operator.RightShift}, - {Tok.UnsignedRightShift, 8, true, Operator.UnsignedRightShift} - ]; - BinOp* binary(Tok t) - { - foreach (ref op; _binary) - if (op.tokenType == t) - return &op; - return null; - } - -private: - - Token require(Tok t) - { - if (!isa(t)) - if(isa(Tok.EOF)) - messages.report(UnexpectedEOF, - [lexer.last.asRange][], []) - .arg(lexer.last.get(sm)) - .fatal(ExitLevel.Parser); - else - messages.report(UnexpectedTokSingle, peek.location) - .arg(peek.get(sm)) - .arg(typeToString[t]); - return next(); - } - - bool skip(Tok t) - { - if (peek().type != t) - return false; - next(); - return true; - } - - bool isa(Tok t, int i = 0) - { - return peek(i).type == t; - } - - bool isEOF(Token t) - { - if (isa(Tok.EOF)) - messages.report(UnexpectedEOF, - [t.asRange][], []) - .arg(t.get(sm)) - .fatal(ExitLevel.Parser); - return false; - } - - Token next() - { - return lexer.next; - } - - Token peek(int i = 0) - { - return lexer.peek(i); - } - - Lexer lexer; - SourceManager sm; -} - diff -r d442ce39917c -r 55ea834c8675 sema/AstAction.d --- a/sema/AstAction.d Sun Aug 10 16:23:09 2008 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,328 +0,0 @@ -module sema.AstAction; - -import Integer = tango.text.convert.Integer, - tango.io.Stdout; - -import lexer.Token; - -import basic.SourceManager, - basic.Attribute; - -import ast.Module, - ast.Exp, - ast.Stmt, - ast.Decl; - -public -import parser.Action; - -/** - This class implements the default actions for Dang, by building up an AST - with the data needed in a compiler. - */ -class AstAction : Action -{ - this(SourceManager sm) - { - this.sm = sm; - } - private SourceManager sm; - - private IdentifierTypeExp handleType(Id type) - { - if(auto t = cast(PointerTypeId)type) - return new PointerTypeExp(handleType(t.id)); - if(auto t = cast(StaticArrayTypeId)type) - return new StaticArrayTypeExp(handleType(t.id), cast(IntegerLit)t.number); - if(auto t = cast(FunctionTypeId)type) - return new FunctionTypeExp(handleType(t.id), cast(VarDecl[])t.decls); - - return new IdentifierTypeExp(type.tok.location, sm.getText(type.tok.asRange)); - } - - private Identifier identifierFromTok(Token t) - { - return new Identifier(t.location, sm.getText(t.asRange)); - } -override -{ - ModuleT actOnModule(ref Token _module, char[] name) - { - return new Module(name); - } - - ModuleT actOnImplicitModule(SLoc startLoc, char[] name) - { - return new Module(name); - } - - void actOnModuleDecl(ModuleT m, DeclT d) - { - (cast(Module)m).addDecl(cast(Decl)d); - } - - // -- Declarations -- - DeclT actOnImport(ref Token _, ref ModuleName target, Id* name) - { - auto res = new ImportDecl; - Identifier[] packages = new Identifier[target.packages.length]; - foreach (i, v; target.packages) - packages[i] = identifierFromTok(v.tok); - res.packages = packages; - - res.name = identifierFromTok(target.id.tok); - if (name !is null) - res.aliasedName = identifierFromTok(name.tok); - return res; - } - - void addSelectiveImport(DeclT _import, ref Id target, Id* name) - { - auto d = cast(ImportDecl)_import; - Identifier t = identifierFromTok(target.tok); - Identifier n = t; - if (name !is null) - n = identifierFromTok(name.tok); - d.explicitSymbols ~= [t, n]; - } - - DeclT actOnDeclarator(ref Id type, ref Id id, ExprT init, Attribute att) - { - Decl d; - Exp exp = cast(Exp)init; - if (type.tok.type == Tok.Struct) - d = new StructDecl(identifierFromTok(id.tok)); - else if (type.tok.type == Tok.Class) - d = new ClassDecl(identifierFromTok(id.tok)); - else if (type.tok.type == Tok.Interface) - d = new InterfaceDecl(identifierFromTok(id.tok)); - else - d = new VarDecl(handleType(type), id ? identifierFromTok(id.tok) : null, exp); - - d.att = att; - return d; - } - - DeclT actOnAliasDecl(DeclT decl, Attribute att) - { - auto a = new AliasDecl(cast(Decl)decl); - a.att = att; - return a; - } - - void actOnStructMember(DeclT st_decl, DeclT m_decl) //ref Id type, ref Id name, ExprT init) - { - StructDecl st = cast(StructDecl)st_decl; - st.addMember(cast(Decl)m_decl); - } - - void actOnClassMember(DeclT cl_decl, DeclT m_decl) - { - ClassDecl cl = cast(ClassDecl)cl_decl; - cl.addMember(cast(Decl)m_decl); - } - - void actOnClassBaseClass(DeclT cl_decl, ref Id name) - { - ClassDecl cl = cast(ClassDecl)cl_decl; - cl.addBaseClass(identifierFromTok(name.tok)); - } - - void actOnInterfaceMember(DeclT if_decl, DeclT m_decl) - { - InterfaceDecl inf = cast(InterfaceDecl)if_decl; - inf.addMember(cast(Decl)m_decl); - } - - void actOnInterfaceBaseClass(DeclT if_decl, ref Id name) - { - InterfaceDecl inf = cast(InterfaceDecl)if_decl; - inf.addBaseClass(identifierFromTok(name.tok)); - } - - ExprT actOnMemberReference(ExprT lhs, SLoc op, Id member) - { - Exp exp = cast(Exp)lhs; - Identifier id = identifierFromTok(member.tok); - return new MemberReference(op, exp, id); - } - - DeclT actOnStartOfFunctionDef(ref Id type, ref Id name, Attribute att) - { - auto res = new FuncDecl(handleType(type), identifierFromTok(name.tok)); - res.att = att; - return res; - } - - void addFuncArg(DeclT func, Id type, Id name) - { - FuncDecl fd = cast(FuncDecl)func; - if(name) - fd.addParam(handleType(type), identifierFromTok(name.tok)); - else - fd.addParam(handleType(type)); - } - - DeclT actOnEndOfFunction(DeclT func, StmtT stmts) - { - FuncDecl fd = cast(FuncDecl)func; - fd.setBody(cast(CompoundStatement)stmts); - return fd; - } - - // -- Statements -- - StmtT actOnCompoundStmt(ref Token l, ref Token r, StmtT[] stmts) - { - Stmt[] statements = cast(Stmt[])stmts; - return new CompoundStatement(statements.dup); - } - - StmtT actOnExprStmt(ExprT exp) - { - return new ExpStmt(cast(Exp)exp); - } - - StmtT actOnReturnStmt(ref Token loc, ExprT exp) - { - Exp e = cast(Exp)exp; - auto res = new ReturnStmt; - res.exp = e; - return res; - } - - StmtT actOnIfStmt(ref Token ifTok, ExprT cond, StmtT thenBody, - ref Token elseTok, StmtT elseBody) - { - Exp c = cast(Exp)cond; - Stmt t = cast(Stmt)thenBody; - Stmt e = cast(Stmt)elseBody; - return new IfStmt(c, t, e); - } - - StmtT actOnWhileStmt(ref Token tok, ExprT cond, StmtT whileBody) - { - Exp c = cast(Exp)cond; - Stmt b = cast(Stmt)whileBody; - return new WhileStmt(c, b); - } - - StmtT actOnForStmt(ref Token tok, StmtT init, ExprT cond, ExprT incre, StmtT forBody) - { - Stmt i = cast(Stmt)init; - Exp c = cast(Exp)cond; - Exp inc = cast(Exp)incre; - Stmt b = cast(Stmt)forBody; - return new ForStmt(i, c, inc, b); - } - - StmtT actOnDeclStmt(DeclT decl) - { - Decl d = cast(Decl)decl; - return new DeclStmt(d); - } - - StmtT actOnStartOfSwitchStmt(Token _switch, ExprT exp) - { - return new SwitchStmt(_switch.location, cast(Exp)exp); - } - - void actOnCaseStmt(StmtT stmt, Token _case, ExprT[] exps, StmtT[] stmts) - { - auto sw = cast(SwitchStmt)stmt; - sw.addCase(_case.location, cast(Exp[])exps, cast(Stmt[])stmts); - } - - void actOnDefaultStmt(StmtT stmt, Token _default, StmtT[] stmts) - { - auto sw = cast(SwitchStmt)stmt; - sw.setDefault(_default.location, cast(Stmt[])stmts); - } - - // -- Expressions -- - ExprT actOnNumericConstant(Token c) - { - return new IntegerLit(c.location, sm.getText(c.asRange)); - } - - ExprT actOnStringExp(Token s) - { - return new StringExp(s.location, sm.getText(s.asRange)); - } - - ExprT actOnIdentifierExp(Id id) - { - return identifierFromTok(id.tok); - } - - ExprT actOnBinaryOp(SLoc op_loc, Operator op, ExprT l, ExprT r) - { - Exp left = cast(Exp)l; - Exp right = cast(Exp)r; - switch(op) - { - case Operator.Assign: - case Operator.AddAssign: - case Operator.SubAssign: - case Operator.MulAssign: - case Operator.DivAssign: - case Operator.ModAssign: - return new AssignExp(op_loc, cast(BinaryExp.Operator)op, left, right); - default: - BinaryExp.Operator bin_op = cast(BinaryExp.Operator)op; - return new BinaryExp(op_loc, bin_op, left, right); - } - } - - ExprT actOnUnaryOp(Token op, ExprT operand) - { - Exp target = cast(Exp)operand; - if (op.type == Tok.Minus) - return new NegateExp(op.location, target); - if (op.type == Tok.Star) - return new DerefExp(op.location, target); - if (op.type == Tok.And) - return new AddressOfExp(op.location, target); - assert(0, "Only valid unary expressions are -x and *x"); - } - - ExprT actOnCallExpr(ExprT fn, ref Token, ExprT[] args, ref Token) - { - Exp f = cast(Exp)fn; - Exp[] arguments = cast(Exp[])args.dup; - return new CallExp(f, arguments); - } - - ExprT actOnCastExpr(ref Token _cast, Id id, ExprT exp) - { - Exp target = cast(Exp)exp; - Identifier target_type = identifierFromTok(id.tok); - return new CastExp(_cast.location, target_type, target); - } - - ExprT actOnIndexExpr(ExprT arr, ref Token lb, ExprT index, ref Token rb) - { - Exp target = cast(Exp)arr; - Exp idx = cast(Exp)index; - return new IndexExp(target, lb.location, idx, rb.location); - } - - ExprT actOnNewExpr(ref Id type, ExprT[] a_args, ExprT[] c_args) - { - auto id = identifierFromTok(type.tok); - Exp[] _a_args = cast(Exp[])a_args; - Exp[] _c_args = cast(Exp[])c_args; - return new NewExp(id, _a_args, _c_args); - } - - ExprT actOnArrayLiteralExpr(ExprT[] exps, SLoc start, SLoc end) - { - return new ArrayLiteralExp(cast(Exp[])exps, start, end); - } - - ExprT actOnNullExpr(SLoc pos) - { - return new NullExp(pos); - } -} -} - diff -r d442ce39917c -r 55ea834c8675 sema/BuildScopes.d --- a/sema/BuildScopes.d Sun Aug 10 16:23:09 2008 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,265 +0,0 @@ -module sema.BuildScopes; - -import tango.io.Stdout, - tango.core.Array : find; - -import sema.Scope; - -import sema.Visitor; - -/** - Add scopes to everything, and add all identifiers that correspond to types. - Types/Symbols are added by ForwardReference. - **/ -class BuildScopes : Visitor!(void) -{ - static ModuleHandler mHandle; - - static this() - { - mHandle = new ModuleHandler; - } - - override void visit(Module[] modules) - { - foreach(m ; modules) - visitModule(m); - } - - private void registerBasicTypeTo(char[] n, DType t, Scope sc, Module m) - { - sc.types[n] = t; - auto id = new Identifier(n); - id.env = sc; - auto decl = new DummyDecl(); - auto sym = m.symbol.createMember(n, t, decl); - sym.decl = decl; - decl.sym = sym; - decl.env = sc; - sc.put(id.get, decl); - } - - override void visitModule(Module m) - { - auto root = new Scope; - table ~= root; - - m.symbol = new Symbol; - - registerBasicTypeTo("void", DType.Void, root, m); - registerBasicTypeTo("bool", DType.Bool, root, m); - registerBasicTypeTo("byte", DType.Byte, root, m); - registerBasicTypeTo("ubyte", DType.UByte, root, m); - registerBasicTypeTo("short", DType.Short, root, m); - registerBasicTypeTo("ushort", DType.UShort, root, m); - registerBasicTypeTo("int", DType.Int, root, m); - registerBasicTypeTo("uint", DType.UInt, root, m); - registerBasicTypeTo("long", DType.Long, root, m); - registerBasicTypeTo("ulong", DType.ULong, root, m); - - registerBasicTypeTo("char", DType.Char, root, m); - registerBasicTypeTo("wchar", DType.WChar, root, m); - registerBasicTypeTo("dchar", DType.DChar, root, m); - - registerBasicTypeTo("float", DType.Float, root, m); - registerBasicTypeTo("double", DType.Double, root, m); - registerBasicTypeTo("real", DType.Real, root, m); - - current().inModule = m; - current().mHandle = mHandle; - mHandle.add(m); - m.env = current(); - super.visitModule(m); - } - - override void visitDecl(Decl d) - { - d.env = current(); - super.visitDecl(d); - } - - override void visitImportDecl(ImportDecl i) - { - i.env.imports ~= i; - super.visitImportDecl(i); - } - - override void visitStmt(Stmt s) - { - s.env = current(); - s.stmtIndex = s.env.stmtIndex; - super.visitStmt(s); - } - - override void visitExp(Exp e) - { - e.env = current(); - e.stmtIndex = e.env.stmtIndex; - super.visitExp(e); - } - - override void visitFuncDecl(FuncDecl d) - { - current().put(d.identifier.get, d); - d.env = current(); - auto sc = push(); - - visitExp(d.returnType); - visitExp(d.identifier); - sc.parentFunction = d; - foreach (arg; d.funcArgs) - visitDecl(arg); - foreach (stmt; d.statements) - { - sc.currentStmtIndex++; - visitStmt(stmt); - } - pop(sc); - } - - override void visitVarDecl(VarDecl d) - { - if (d.init) - visitExp(d.init); - - if (need_push > 0 && current().parentFunction !is null) { - push(); - --need_push; - } - - if(d.identifier) - { - auto sc = current(); - sc.put(d.identifier.get, d); - d.env = sc; - visitExp(d.varType); - visitExp(d.identifier); - } - } - - override void visitStructDecl(StructDecl s) - { - auto sc = current(); - sc.put(s.identifier.get, s); - s.env = sc; - auto type = new DStruct(s.identifier); - - sc.types[s.identifier.get] = type; - - sc = push(); - super.visitStructDecl(s); - pop(sc); - } - - override void visitClassDecl(ClassDecl s) - { - auto sc = current(); - sc.put(s.identifier.get, s); - s.env = sc; - auto type = new DClass(s.identifier); - - sc.types[s.identifier.get] = type; - - sc = push(); - super.visitClassDecl(s); - pop(sc); - } - - override void visitInterfaceDecl(InterfaceDecl s) - { - auto sc = current(); - sc.put(s.identifier.get, s); - s.env = sc; - auto type = new DInterface(s.identifier); - - sc.types[s.identifier.get] = type; - - sc = push(); - super.visitInterfaceDecl(s); - pop(sc); - } - - override void visitAliasDecl(AliasDecl a) - { - a.env = current(); -// auto decl = cast(VarDecl)a.decl; -// auto sc = current(); -// super.visitDecl(a.decl); - } - - override void visitDeclStmt(DeclStmt d) - { - ++need_push; - super.visitDeclStmt(d); - } - private uint need_push = 0; - - override void visitIfStmt(IfStmt s) - { - s.env = current(); - visitExp(s.cond); - auto sc = push(); - visitStmt(s.then_body); - pop(sc); - - if (s.else_body !is null) - { - sc = push(); - visitStmt(s.else_body); - pop(sc); - } - } - - override void visitWhileStmt(WhileStmt s) - { - s.env = current(); - auto sc = push(); - super.visitWhileStmt(s); - pop(sc); - } - - override void visitForStmt(ForStmt s) - { - s.env = current(); - auto sc = push(); - super.visitForStmt(s); - pop(sc); - } - - override void visitCompoundStmt(CompoundStatement s) - { - s.env = current(); - auto sc = push(); - super.visitCompoundStmt(s); - pop(sc); - } - -private: - Scope[] table; - - Scope push() - { - auto sc = new Scope(current()); - table ~= sc; - return sc; - } - - Scope pop(Scope sc = null) - { - if (sc !is null) - { - table.length = table.find(sc); - return sc; - } - - auto res = table[$ - 1]; - table.length = table.length - 1; - return res; - } - - Scope current() - { - return table[$ - 1]; - } -} - diff -r d442ce39917c -r 55ea834c8675 sema/BuildSymbols.d --- a/sema/BuildSymbols.d Sun Aug 10 16:23:09 2008 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,247 +0,0 @@ -module sema.BuildSymbols; - -import tango.io.Stdout, - tango.core.Array : find; - -import sema.Scope, - sema.Symbol; - -import sema.Visitor, - basic.SmallArray; - -class SymbolFactory -{ - void put(Symbol symbol, DType type) - { - types[type] = symbol; - } - - Symbol get(Symbol owner, DType type, Identifier i, Decl decl) - { - if (type in types) - return owner.createAlias(i.get, types[type], decl); - else - return owner.createMember(i.get, type, decl); - } - - Symbol[DType] types; -} - -class BuildSymbols : Visitor!(void) -{ - this() - { - this.sf = new SymbolFactory; - } - - override void visit(Module[] modules) - { -// (new BuildSymbolTypes(sf)).visit(modules); - this.modules = modules; - inFunctionBodyStack.push(false); - foreach (mod; modules) - { - current = mod; - foreach (decl; mod.decls) - visitDecl(decl); - } - } - - override void visitFuncDecl(FuncDecl d) - { - - visitExp(d.returnType); - visitExp(d.identifier); - - d.sym = current.symbol.createMember( - d.identifier.get, - d.type, - d); - - auto old = current.symbol; - current.symbol = d.sym; - - foreach (arg; d.funcArgs) - visitDecl(arg); - - inFunctionBodyStack.push(true); - - foreach (stmt; d.statements) - visitStmt(stmt); - - inFunctionBodyStack.pop(); - - current.symbol = old; - - } - - override void visitVarDecl(VarDecl d) - { - visitExp(d.varType); - if(d.identifier) - visitExp(d.identifier); - - if (d.init) - visitExp(d.init); - - if(d.identifier) - { - DType t = typeOf(d.varType, d.env); - d.sym = sf.get(current.symbol, t, d.identifier, d); - d.sym.type = t; - } - } - - override void visitAliasDecl(AliasDecl a) - { - auto decl = cast(VarDecl)a.decl; - - if (a.env.findType(decl.varType.get)) // Alias "type" is a type. - { - auto t = typeOf(decl.varType, a.env); - a.sym = sf.get(current.symbol, t, - decl.identifier, a); - a.env.types[decl.identifier.get] = t; - } - else if(auto aliasOf = a.env.find(decl.varType.get)[0]) - { - a.env.put(decl.identifier.get, aliasOf); - a.sym = current.symbol.createAlias( - decl.identifier.get, - aliasOf.sym, - a); - } - decl.env = a.env; - } - - - override void visitStructDecl(StructDecl s) - { - auto st = s.env.findType(s.identifier.get).asStruct; - s.sym = current.symbol.createMember( - s.identifier.get, - st, - s.env.find(s.identifier.get)[0]); - sf.put(s.sym, st); - - foreach (decl; s.decls) - { - DType type; - char[] name; - if (auto varDecl = cast(VarDecl)decl) - { - type = typeOf(varDecl.varType, varDecl.env); - name = varDecl.identifier.get; - st.addMember(type, name); - } - /* - else if (auto fd = cast(FuncDecl)decl) - { - type = fd.type; - name = fd.identifier.get; - }*/ - } - auto old = current.symbol; - current.symbol = s.sym; - inFunctionBodyStack.push(false); - super.visitStructDecl(s); - inFunctionBodyStack.pop(); - current.symbol = old; - } - - override void visitClassDecl(ClassDecl s) - { - auto st = s.env.findType(s.identifier.get).asClass; - s.sym = current.symbol.createMember( - s.identifier.get, - st, - s.env.find(s.identifier.get)[0]); - - sf.put(s.sym, st); - - foreach (decl; s.decls) - { - DType type; - char[] name; - if (auto varDecl = cast(VarDecl)decl) - { - type = typeOf(varDecl.varType, varDecl.env); - name = varDecl.identifier.get; - st.addMember(type, name); - } - /* - else if (auto fd = cast(FuncDecl)decl) - { - type = fd.type; - name = fd.identifier.get; - }*/ - } - auto old = current.symbol; - current.symbol = s.sym; - inFunctionBodyStack.push(false); - super.visitClassDecl(s); - inFunctionBodyStack.pop(); - current.symbol = old; - } - - override void visitInterfaceDecl(InterfaceDecl s) - { - auto st = s.env.findType(s.identifier.get).asInterface; - s.sym = current.symbol.createMember( - s.identifier.get, - st, - s.env.find(s.identifier.get)[0]); - sf.put(s.sym, st); - - foreach (decl; s.decls) - { - DType type; - char[] name; - if (auto varDecl = cast(VarDecl)decl) - { - type = typeOf(varDecl.varType, varDecl.env); - name = varDecl.identifier.get; - st.addMember(type, name); - } - /* - else if (auto fd = cast(FuncDecl)decl) - { - type = fd.type; - name = fd.identifier.get; - }*/ - } - auto old = current.symbol; - current.symbol = s.sym; - inFunctionBodyStack.push(false); - super.visitInterfaceDecl(s); - inFunctionBodyStack.pop(); - current.symbol = old; - } - - override void visitFunctionTypeExp(FunctionTypeExp f) - { - } - - DType typeOf(Identifier id, Scope sc) - { - if(auto i = cast(PointerTypeExp)id) - return (typeOf(i.pointerOf, sc)).getPointerTo(); - else if(auto i = cast(StaticArrayTypeExp)id) - return typeOf(i.arrayOf, sc).getAsStaticArray(i.size); - else if(auto i = cast(FunctionTypeExp)id) - { - auto d = new DFunction(id); - d.returnType = typeOf(i.returnType, sc); - foreach (decl ; i.decls) - d.params ~= typeOf(decl.varType, sc); - return d.getPointerTo; - } - return sc.findType(id.get); - } - - Module[] modules; - Module current; - SmallArray!(bool) inFunctionBodyStack; - SymbolFactory sf; -} - diff -r d442ce39917c -r 55ea834c8675 sema/BuildTypes.d --- a/sema/BuildTypes.d Sun Aug 10 16:23:09 2008 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,221 +0,0 @@ -module sema.BuildTypes; - -import basic.LiteralParsing, - basic.Message; - -import sema.Visitor, - sema.Symbol, - sema.DType; - -import tango.io.Stdout; - - -class BuildTypes : Visitor!(void) -{ - this(MessageHandler messages) - { - this.messages = messages; - } - - override void visitCallExp(CallExp exp) - { - super.visitCallExp(exp); - DFunction f = exp.exp.type.asCallable(); - assert(f !is null, "Can only call functions"); - exp.type = f.returnType; - } - - override void visitAssignExp(AssignExp exp) - { - super.visitAssignExp(exp); - exp.type = exp.identifier.type; - } - - override void visitBinaryExp(BinaryExp exp) - { - super.visitBinaryExp(exp); - if (exp.op == BinaryExp.Operator.Eq || - exp.op == BinaryExp.Operator.Ne || - exp.op == BinaryExp.Operator.Lt || - exp.op == BinaryExp.Operator.Le || - exp.op == BinaryExp.Operator.Gt || - exp.op == BinaryExp.Operator.Ge) - { - exp.type = DType.Bool; - return; - } - - DType l = exp.left.type; - DType r = exp.right.type; - if (l.isSame(r)) - exp.type = l; - else if (l.hasImplicitConversionTo(r)) - exp.type = r; - else if (r.hasImplicitConversionTo(l)) - exp.type = l; - else - exp.type = DType.Int; //FIXME: Throw error here. - } - - override void visitNegateExp(NegateExp exp) - { - super.visitNegateExp(exp); - exp.type = exp.exp.type; - } - - override void visitDerefExp(DerefExp exp) - { - super.visitDerefExp(exp); - exp.type = exp.exp.type.asPointer().pointerOf; - } - - override void visitAddressOfExp(AddressOfExp exp) - { - super.visitAddressOfExp(exp); - exp.type = exp.exp.type.getPointerTo; - } - - override void visitIntegerLit(IntegerLit exp) - { - super.visitIntegerLit(exp); - switch(exp.number.type) - { - case NumberType.Int: - exp.type = DType.Int; - break; - case NumberType.Long: - exp.type = DType.Long; - break; - case NumberType.ULong: - exp.type = DType.ULong; - break; - case NumberType.Double: - exp.type = DType.Double; - break; - case NumberType.Real: - exp.type = DType.Real; - break; - } - } - - override void visitMemberReference(MemberReference exp) - { - super.visitMemberReference(exp); - if ( exp.target.type.isStruct ) - { - Symbol st = exp.target.getSymbol; - if (auto t = st.findMembers(exp.child.name)) - exp.type = t[0].type; -// else assert(0, "Referencing non-existant member"); - } - else if ( exp.target.type.isClass ) - { - Symbol cl = exp.target.getSymbol; - if (auto t = cl.findMembers(exp.child.name)) - exp.type = t[0].type; -// else assert(0, "Referencing non-existant member"); - } - else - assert(0, "Only structs and classes have members"); - // no error reporting here - } - - override void visitIndexExp(IndexExp exp) - { - super.visitIndexExp(exp); - DType type = exp.target.type; - if (type.isStaticArray()) - exp.type = type.asStaticArray().arrayOf; - else if (type.isPointer()) - exp.type = type.asPointer().pointerOf; - else assert(0, "Can only index pointers and arrays"); - } - - override void visitCastExp(CastExp exp) - { - super.visitCastExp(exp); - exp.type = exp.env.findType(exp.castType.get); - } - - override void visitStringExp(StringExp exp) - { - super.visitStringExp(exp); - switch (exp.data.type) - { - case StringType.Char: - exp.type = DType.Char.getAsStaticArray(exp.data.data.length); - break; - case StringType.WChar: - exp.type = DType.WChar.getAsStaticArray(exp.data.data.length/2); - break; - case StringType.DChar: - exp.type = DType.DChar.getAsStaticArray(exp.data.data.length/4); - break; - } - } - - override void visitNewExp(NewExp exp) - { - super.visitNewExp(exp); - exp.type = exp.env.findType(exp.newType.get); - } - - override void visitNullExp(NullExp exp) - { - super.visitNullExp(exp); - exp.type = new DPointer(DType.Int); - } - - override void visitIdentifier(Identifier exp) - { - super.visitIdentifier(exp); - if (auto sym = exp.getSymbol) - exp.type = sym.type; - else - exp.type = DType.Int; - } - -/* override void visitIdentifierTypeExp(IdentifierTypeExp exp) - { - if (auto sym = exp.getSymbol) - exp.type = sym.type; - else - exp.type = DType.Int; - }*/ - - override void visitPointerTypeExp(PointerTypeExp exp) - { - super.visitPointerTypeExp(exp); - exp.type = exp.pointerOf.type.getPointerTo(); - } - - override void visitStaticArrayTypeExp(StaticArrayTypeExp exp) - { - super.visitStaticArrayTypeExp(exp); - exp.type = exp.arrayOf.type.getAsStaticArray(exp.size); - } - -/* override void visitArrayTypeExp(ArrayTypeExp exp) - { - exp.type = arrayOf.type.getAsArray(); - }*/ - - override void visitFunctionTypeExp(FunctionTypeExp exp) - { - super.visitFunctionTypeExp(exp); - auto t = new DFunction(exp.returnType); - t.returnType = exp.returnType.type; - foreach (decl ; exp.decls) - t.params ~= decl.varType.type; - - exp.type = t.getPointerTo; - } - - override void visitArrayLiteralExp(ArrayLiteralExp exp) - { - super.visitArrayLiteralExp(exp); - exp.type = exp.exps[0].type.getAsStaticArray(exp.exps.length); - } - - MessageHandler messages; -} diff -r d442ce39917c -r 55ea834c8675 sema/CheckScopes.d --- a/sema/CheckScopes.d Sun Aug 10 16:23:09 2008 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,158 +0,0 @@ -module sema.CheckScopes; - -import sema.Visitor, - sema.Symbol, - sema.Scope, - sema.DType; - -import basic.Message, - basic.Attribute; - -import tango.io.Stdout; - -class CheckScopes : Visitor!(void) -{ - - this(MessageHandler messages) - { - this.messages = messages; - } - - override void visitIdentifier(Identifier i) - { - auto symbol = i.env.find(i.get); - - if(symbol is null) - messages.report(UndefinedIdentifier, i.loc) - .arg(i.get); - } - - override void visitVarDecl(VarDecl d) - { - if(d.identifier.get is null) - messages.report(UndefinedType, d.varType.loc) - .arg(d.varType.get); - - auto env = d.env; - if (d.env.enclosing) - if (d.env.enclosing.find(d.identifier.get) !is null) - if (d.env.parentFunction !is null) - while( d.env.parentFunction.env !is env) - { - if (d.env.enclosing.find(d.identifier.get)[0].env == env) - messages.report(CannotRedeclare, d.identifier.loc) - .arg(d.identifier.get); - env = env.enclosing; - } - - visitExp(d.identifier); - if (d.init) - visitExp(d.init); - } - - override void visitFuncDecl(FuncDecl f) - { - visitExp(f.identifier); - - inFunction = true; - foreach (stmt; f.statements) - visitStmt(stmt); - inFunction = false; - } - - override void visitImportDecl(ImportDecl) { } - - override void visitCastExp(CastExp exp) - { - visitExp(exp.exp); - } - - override void visitMemberReference(MemberReference m) - { - internalVisitMemberRef(m); - } - - private Symbol internalVisitMemberRef(MemberReference m) - { - Symbol visitRef(MemberReference m, Identifier target, Symbol st) - { - auto child = m.child; - auto res = st.findMembers(child.get); - - if(!res.length) - messages.report(MissingMember, m.loc) - .arg(st.type.name) - .arg(target.get) - .arg(child.get); - else - internalCheckProtection(res[0], child); - - return res.length ? res[0] : null; - } - switch(m.target.expType) - { - case ExpType.Identifier: - return visitRef(m, cast(Identifier)m.target, - (cast(Identifier)m.target).getSymbol); - case ExpType.MemberReference: - Symbol s = internalVisitMemberRef(cast(MemberReference)m.target); - if(!s) - return null; - return visitRef(m, cast(Identifier)m.target, s); - } - } - - override void visitExp(Exp exp) - { - if (exp.expType == ExpType.Identifier && inFunction - && exp.env.find((cast(Identifier)exp).get) !is null) - { - if (exp.env.findType((cast(Identifier)exp).get) is null) - internalCheckProtection( - exp.env.find((cast(Identifier)exp).get)[0].sym, - cast(Identifier)exp); - } - - super.visitExp(exp); - } - - private void internalCheckProtection(Symbol sym, Identifier iden) - { - if (isChildOf(sym.decl.env, iden.env)) - return; - - switch(sym.decl.att.getProtection) - { - case Protection.Private: -/* if (iden.env.inModule == sym.decl.getIdentifier.env.inModule - && sym.decl.getIdentifier.env.enclosing == iden.env.inModule) - {} - else*/ - messages.report(CannotAccessPrivate, iden.loc); - return; - default: - return; - } - } - - private bool isChildOf(Scope parent, Scope child) - { - if (child is parent) - return true; - - if (child.enclosing !is null) - return isChildOf(parent, child.enclosing); - - return false; - } - - private bool isType(char[] s) - { - return (s in types? true : false); - } - - int[char[]] types; - MessageHandler messages; - bool inFunction; -} - diff -r d442ce39917c -r 55ea834c8675 sema/CheckTypes.d --- a/sema/CheckTypes.d Sun Aug 10 16:23:09 2008 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,490 +0,0 @@ -module sema.CheckTypes; - -import sema.Visitor, - sema.Symbol, - sema.DType; - -import tango.io.Stdout, - Integer = tango.text.convert.Integer; - -import basic.SourceLocation, - basic.Message; - -class CheckTypes : Visitor!(void) -{ - this(MessageHandler messages) - { - this.messages = messages; - } - - override void visitBinaryExp(BinaryExp exp) - { - super.visitBinaryExp(exp); - - if(!exp.left.type.isSame(exp.right.type)) - { - if (!exp.right.type.hasImplicitConversionTo(exp.left.type) && - !exp.left.type.hasImplicitConversionTo(exp.right.type)) - messages.report(InvalidImplicitCast, exp.loc) - .arg(exp.right.type.toString) - .arg(exp.left.type.toString); - else - { - CastExp castExp; - if(exp.left.type.isReal && exp.right.type.isReal) - if(exp.left.type.byteSize > exp.right.type.byteSize) - castExp = new CastExp( - SLoc.Invalid, - new Identifier(exp.left.type.name), - exp.right); - else - castExp = new CastExp( - SLoc.Invalid, - new Identifier(exp.right.type.name), - exp.left); - else if(exp.left.type.isReal || exp.right.type.isReal) - if(exp.left.type.isReal) - castExp = new CastExp( - SLoc.Invalid, - new Identifier(exp.left.type.name), - exp.right); - else - castExp = new CastExp( - SLoc.Invalid, - new Identifier(exp.right.type.name), - exp.left); - else - if(exp.left.type.byteSize > exp.right.type.byteSize) - castExp = new CastExp( - SLoc.Invalid, - new Identifier(exp.left.type.name), - exp.right); - else if(exp.left.type.byteSize < exp.right.type.byteSize) - castExp = new CastExp( - SLoc.Invalid, - new Identifier(exp.right.type.name), - exp.left); - else - castExp = new CastExp( - SLoc.Invalid, - new Identifier(exp.left.type.name), - exp.right); - - - if(castExp) - { - castExp.env = exp.env; - if(castExp.exp == exp.right) - { - exp.type = castExp.type = exp.left.type; - exp.right = castExp; - } - else - { - exp.type = castExp.type = exp.right.type; - exp.left = castExp; - } - - } - } - } - if (exp.op >= BinaryExp.Operator.LeftShift && - exp.op <= BinaryExp.Operator.UnsignedRightShift) - {} // FIXME: When we have const-system we need to check for - // right site being larger then the bitsize of the - // left - } - - override void visitDerefExp(DerefExp exp) - { - if (!exp.exp.type.isPointer) - { - messages.report(CanOnlyDerefPointers, - [exp.exp.sourceRange][], - [exp.loc]) - .arg(exp.exp.type.toString); - - exp.type = DType.Int; - } - } - - override void visitCallExp(CallExp exp) - { - super.visitCallExp(exp); - - if (auto iden = cast(MemberReference)exp.exp) - { - Symbol[] internalVisitMemberRef(MemberReference m) - { - Symbol[] visitRef(MemberReference m, Identifier target, Symbol st) - { - auto child = m.child; - auto res = st.findMembers(child.get); - return res; - } - switch(m.target.expType) - { - case ExpType.Identifier: - return visitRef(m, cast(Identifier)m.target, - (cast(Identifier)m.target).getSymbol); - case ExpType.MemberReference: - Symbol[] s = internalVisitMemberRef(cast(MemberReference)m.target); - if(s.length) - return s; - return visitRef(m, cast(Identifier)m.target, s[0]); - } - } - - Exp[] newArgs; - - DFunction function_type; - if (iden.type.isFunction()) - { - Symbol[] methods = internalVisitMemberRef(iden); - - if (!methods.length) - { - messages.report(NoMethodByName, iden.loc); - return; - } - - Symbol sel = getBestMatch(exp.args, methods); - exp.callSym = sel; - if (sel) - function_type = sel.type.asFunction(); - else - { - messages.report(NoMachingMethod, exp.loc); - foreach ( i, s ; methods ) - { - messages.report(CandidateNr, - (cast(FuncDecl)s.decl).identifier.loc) - .arg(Integer.toString(i+1)); - } - } - } - else if (iden.type.isCallable) - function_type = iden.type.asCallable(); - else assert(0, "Should not happen"); - - foreach (i, arg; exp.args) - { - auto argType = function_type.params[i]; - auto expType = arg.type; - if (argType.isSame(expType)) - { - if (!expType.hasImplicitConversionTo(argType)) - messages.report(InvalidImplicitCast, exp.loc) - .arg(expType.toString) - .arg(argType.toString); - - auto castExp = new CastExp( - SLoc.Invalid, - new Identifier(argType.name), - arg); - castExp.env = iden.env; - castExp.type = argType; - newArgs ~= castExp; - } - else - newArgs ~= arg; - } - exp.args = newArgs; - } - else if (auto iden = cast(Identifier)exp.exp) - { - Exp[] newArgs; - - DFunction function_type; - if (iden.type.isFunction()) - { - Symbol[] methods; - - foreach (decl ; iden.env.find(iden.get)) - methods ~= decl.sym; - - if (!methods.length) - { - messages.report(NoMethodByName, iden.loc); - return; - } - - Symbol sel = getBestMatch(exp.args, methods); - exp.callSym = sel; - if (sel) - function_type = sel.type.asFunction(); - else - { - messages.report(NoMachingMethod, exp.loc); - foreach ( i, s ; methods ) - { - messages.report(CandidateNr, - (cast(FuncDecl)s.decl).identifier.loc) - .arg(Integer.toString(i+1)); - } - } - } - else if (iden.type.isCallable) - { - function_type = iden.type.asCallable(); - if (exp.args.length != function_type.params.length) - { - messages.report(CannotCallMethod, exp.loc) - .arg(iden.type.toString) - .arg(exp.callerType.toString); - } - } - else assert(0, "Should not happen"); - - foreach (i, arg; exp.args) - { - auto argType = function_type.params[i]; - auto expType = arg.type; - if (!argType.isSame(expType)) - { - if (!expType.hasImplicitConversionTo(argType)) - messages.report(InvalidImplicitCast, exp.loc) - .arg(expType.toString) - .arg(argType.toString); - - auto castExp = new CastExp( - SLoc.Invalid, - new Identifier(argType.name), - arg); - castExp.env = iden.env; - castExp.type = argType; - newArgs ~= castExp; - } - else - newArgs ~= arg; - } - exp.args = newArgs; - } - else - { - Exp[] newArgs; - - foreach(i, arg; exp.args) - { - auto argType = exp.exp.type.asFunction.params[i]; - auto expType = arg.type; - if(!argType.isSame(expType)) - { - if(!expType.hasImplicitConversionTo(argType)) - messages.report(InvalidImplicitCast, exp.loc) - .arg(expType.toString) - .arg(argType.toString); - - auto castExp = new CastExp( - SLoc.Invalid, - new Identifier(argType.name), - arg); - castExp.env = exp.exp.env; - castExp.type = argType; - newArgs ~= castExp; - } - else - newArgs ~= arg; - } - - exp.args = newArgs; - } - } - - override void visitNewExp(NewExp exp) - { - super.visitNewExp(exp); - - Exp[] newArgs; - - Symbol[] methods = exp.newType.getSymbol.findFunctionMembers("this"); - - if (!methods.length) - { - messages.report(NoConstructor, exp.newType.loc); - return; - } - - Symbol sel = getBestMatch(exp.c_args, methods); - - if (sel) - { - foreach (i, arg; exp.c_args) - { - auto argType = sel.type.asFunction.params[i]; - auto expType = arg.type; - if (!argType.isSame(expType)) - { - if (!expType.hasImplicitConversionTo(argType)) - messages.report(InvalidImplicitCast, exp.loc) - .arg(expType.toString) - .arg(argType.toString); - - auto castExp = new CastExp( - SLoc.Invalid, - new Identifier(argType.name), - arg); - castExp.env = exp.newType.env; - castExp.type = argType; - newArgs ~= castExp; - } - else - newArgs ~= arg; - } - exp.c_args = newArgs; - exp.callSym = sel; - } - else - { - messages.report(NoMachingCon, exp.newType.loc); - foreach ( i, s ; methods ) - { - messages.report(CandidateNr, - (cast(FuncDecl)s.decl).identifier.loc) - .arg(Integer.toString(i+1)); - } - } - } - - override void visitAssignExp(AssignExp exp) - { - super.visitAssignExp(exp); - - auto identifierType = exp.identifier.type; - auto expType = exp.exp.type; - - if(!identifierType.isSame(expType)) - { - if(!expType.hasImplicitConversionTo(identifierType)) - messages.report(InvalidImplicitCast, - [exp.identifier.sourceRange, exp.exp.sourceRange][], - [exp.loc]) - .arg(expType.toString) - .arg(identifierType.toString); - - auto castExp = new CastExp( - SLoc.Invalid, - new Identifier(identifierType.name), - exp.exp); - castExp.env = exp.exp.env; - exp.type = castExp.type = identifierType; - exp.exp = castExp; - } - - if (expType.isStaticArray) - messages.report(CannotReassignSArray, - [exp.identifier.sourceRange, exp.exp.sourceRange][], - [exp.loc]); - } - - override void visitReturnStmt(ReturnStmt stmt) - { - super.visitReturnStmt(stmt); - - if(stmt.exp) - { - auto returnType = stmt.env.parentFunction.type.asFunction.returnType; - auto expType = stmt.exp.type; - if(!expType) - return; - if(!returnType.isSame(expType)) - { - if(!expType.hasImplicitConversionTo(returnType)) - messages.report(InvalidImplicitCast, stmt.exp.loc) - .arg(expType.toString) - .arg(returnType.toString); - - auto castExp = new CastExp( - SLoc.Invalid, - new Identifier(returnType.name), - stmt.exp); - castExp.env = stmt.exp.env; - castExp.type = returnType; - stmt.exp = castExp; - } - } - } - - override void visitVarDecl(VarDecl decl) - { - super.visitVarDecl(decl); - - if(decl.init) - { - auto varType = decl.identifier.type; - auto expType = decl.init.type; - if(!varType.isSame(expType)) - { - if(!expType.hasImplicitConversionTo(varType)) - messages.report(InvalidImplicitCast, decl.init.loc) - .arg(expType.toString) - .arg(varType.toString); - - auto castExp = new CastExp( - SLoc.Invalid, - new Identifier(varType.name), - decl.init); - castExp.env = decl.init.env; - castExp.type = varType; - decl.init = castExp; - } - } - } - - private Symbol getBestMatch(Exp[] arg_list , Symbol[] available) - in - { - foreach (a ; available) - assert(a.type.isFunction, "A non-function found in available-list."); - } - body - { - assert(available.length, "No available methods in symbol-list."); - - Symbol[] possible; - Symbol perfect; - - bool per, work; - foreach (s ; available) - { - if (s.type.asFunction.params.length < arg_list.length) - continue; - - per = true; - work = true; - - foreach (i, arg; arg_list) - { - auto argType = s.type.asFunction.params[i]; - auto expType = arg.type; - if (argType.isSame(expType)) - { - per = false; - if( !expType.hasImplicitConversionTo(argType) ) - { - work = false; - break; - } - } - } - - foreach (a ; (cast(FuncDecl)s.decl).funcArgs[arg_list.length..$]) - if (a.init is null) - work = false; - - if (work) - if (per) - return s; - else - possible ~= s; - } - - if (possible.length) - return possible[0]; - - return null; - } - - MessageHandler messages; -} - diff -r d442ce39917c -r 55ea834c8675 sema/DType.d --- a/sema/DType.d Sun Aug 10 16:23:09 2008 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,725 +0,0 @@ -module sema.DType; - -import lexer.Token, - ast.Exp; - -public -import sema.Operation; - -/// -class DType -{ - private char[] id; - private SourceLocation loc; - public DType actual; - - this(Identifier id, DType actual = null) - { - this.id = id.name; - this.loc = id.startLoc(); - this.actual = actual is null? this : actual; - } - - this(char[] id, DType actual = null) - { - this.id = id; - this.actual = actual is null? this : actual; - } - - /// Is this type a DStruct - bool isStruct() { return false; } - /// Return a DStruct if this is one, otherwise return null - DStruct asStruct() { return null; } - - /// Is this type a DClass - bool isClass() { return false; } - /// Return a DClass if this is one, otherwise return null - DClass asClass() { return null; } - - /// Is this type a DInterface - bool isInterface() { return false; } - /// Return a DInterface if this is one, otherwise return null - DInterface asInterface() { return null; } - - /// Is this type a DStaticArray - bool isStaticArray() { return false; } - /// Return a DStaticArray if this is one, otherwise return null - DStaticArray asStaticArray() { return null; } - - /// Is this type a DArray - bool isArray() { return false; } - /// Return a DArray if this is one, otherwise return null - DArray asArray() { return null; } - - /// Is this type a DPointer - bool isPointer() { return false; } - /// Return a DPointer if this is one, otherwise return null - DPointer asPointer() { return null; } - - /// Is this type a DFunction - bool isFunction() { return false; } - /// Return a DFunction if this is one, otherwise return null - DFunction asFunction() { return null; } - - /// Is this type a DFunction or a pointer to one - bool isCallable() { return false; } - /// Return a DFunction if this one is available - DFunction asCallable() { return null; } - - /// Returns true for integers, reals and complex numbers - bool isArithmetic() { return false; } - - /// Is this type a DInteger - bool isInteger() { return false; } - /// Return a DInteger if this is one, otherwise return null - DInteger asInteger() { return null; } - - /// Is this type a DReal - bool isReal() { return false; } - /// Return a DReal if this is one, otherwise return null - DReal asReal() { return null; } - - int opEquals(Object o) - { - if (auto t = cast(DType)o) - return this.actual is t.actual; - return 0; - } - - int opCmp(Object o) - { - if (auto t = cast(DType)o) - return cast(void*)this.actual - cast(void*)t.actual; - return 0; - } - - /** - Hashing is done by casting the reference to a void* and taking that - value, but this gives a bad distribution of hash-values. - - Multiple DType's allocated close to each other will only have a - difference in the lower bits of their hashes. - */ - hash_t toHash() - { - return cast(hash_t)(cast(void*)this); - } - - char[] toString() - { - return id; - } - - char[] name() { return id; } - SourceLocation getLoc() { return loc; } - int byteSize() { return 0; } - - /** - Can this type legally be converted to that type with no casts? - True for short -> int etc. - */ - bool hasImplicitConversionTo(DType that) { return false; } - - /** - Get an Operation describing how to use the supplied operator on the two - types given. - */ - Operation getOperationWith(Operator op, DType other) - { - Operation res; - return res; - } - - /** - Get a type representing a pointer to this type (from int to int*) - */ - DPointer getPointerTo() - { - if(myPointer !is null) - return myPointer; - myPointer = new DPointer(this); - return myPointer; - } - private DPointer myPointer; - - /** - Mangle the DType following the specs at http://digitalmars.com/d/1.0/abi.html - **/ - char[] mangle() - { - /// expects to be void - return "v"; - } - - /** - Get a type representing a static array of this type with length 'size' - */ - DStaticArray getAsStaticArray(int size) - { - if(size in myStaticArray) - return myStaticArray[size]; - myStaticArray[size] = new DStaticArray(this, size); - return myStaticArray[size]; - } - private DStaticArray[int] myStaticArray; - - DArray getAsArray() - { - if(myArray !is null) - return myArray; - myArray = new DArray(this); - return myArray; - } - private DArray myArray; - - bool isSame(DType d) - { - return d is this; - } - - static DInteger - Bool, - Byte, UByte, Short, UShort, - Int, UInt, Long, ULong, - Char, WChar, DChar; - - static DReal Float, Double, Real; - - // Ignore - we dont support complex numbers yet - static DReal CFloat, CDouble, CReal; - - static DType Void; - - static this() - { - Void = new DType("void"); - - Bool = new DInteger("bool", 1, true); - Byte = new DInteger("byte", 8, false); - UByte = new DInteger("ubyte", 8, true); - Short = new DInteger("short", 16, false); - UShort = new DInteger("ushort", 16, true); - Int = new DInteger("int", 32, false); - UInt = new DInteger("uint", 32, true); - Long = new DInteger("long", 64, false); - ULong = new DInteger("ulong", 64, true); - - Float = new DReal("float", 32); - Double = new DReal("double", 64); - Real = new DReal("real", 80); - - Char = new DInteger("char", 8, true); - WChar = new DInteger("wchar", 16, true); - DChar = new DInteger("dchar", 32, true); - } -} - -/** - Class to represent the built-in numerical types, from byte to long, reals and - complex numbers. - - Should not actually use this, but DInteger, DReal or DComplex. - */ -class DArithmetic : DType -{ - private static char[][DArithmetic] mangle_types; - - static this() - { - mangle_types = - [ - cast(DArithmetic) - Bool : "b", - Byte : "g", - UByte : "h", - Short : "s", - UShort : "t", - Int : "i", - UInt : "k", - Long : "l", - ULong : "m", - - Float : "f", - Double : "d", - Real : "e", - - /* - CFloat : "q", - CDouble : "r", - CReal : "c", - */ - - Char : "a", - WChar : "u", - DChar : "w" - ]; - } - - this(char[] name, int bits, bool unsigned) - { - super(name, null); - this.bits = bits; - this.unsigned = unsigned; - } - - override int byteSize() { return bits / 8; } - - bool isArithmetic() { return true; } - - override Operation getOperationWith(Operator op, DType that) - { - Operation operation; - if (this is that) - operation = Operation.builtin(op, unsigned, isReal()); - return operation; - } - - override char[] mangle() - { - return mangle_types[this]; - } - - int bits; - bool unsigned; -} - -class DInteger : DArithmetic -{ - this(char[] name, int bits, bool unsigned) - { - super(name, bits, unsigned); - } - - override bool hasImplicitConversionTo(DType that) - { - if (that.isInteger() || that.isReal()) - return true; - return false; - } - - override bool isInteger() { return true; } - override DInteger asInteger() { return this; } -} - -class DReal : DArithmetic -{ - this(char[] name, int bits) - { - super(name, bits, false); - } - - override bool hasImplicitConversionTo(DType that) - { - if (that.isInteger() || that.isReal()) - return true; - return false; - } - - override bool isReal() { return true; } - override DReal asReal() { return this; } -} - -class DStruct : DType -{ - this(Identifier id, DType actual = null) - { - super(id, actual); - } - - int byteSize() { return bytes_total; } - - override bool isStruct() { return true; } - override DStruct asStruct() { return this; } - - void addMember(DType type, char[] name) - { - auto s = DStructMember(type, members.length); - members[name] = s; - - bytes_total += type.byteSize(); - } - - int indexOf(char[] name) - { - if(name in members) - return members[name].index; - - return -1; - } - - DType typeOf(char[] name) - { - if (auto res = name in members) - return res.type; - return null; - } - - DStructMember[char[]] members; - private int bytes_total; - - override char[] mangle() - { - return "S"~Integer.toString(name.length)~name; - } - - override bool isSame(DType d) - { - if (d is this) - return true; - - if (!d.isStruct) - return false; - - auto s = d.asStruct; - - return id == s.id; - } - - struct DStructMember - { - DType type; - int index; - - char[] toString() - { - return type.toString(); - } - } -} - -class DClass : DType -{ - this(Identifier id, DType actual = null) - { - super(id, actual); - } - - int byteSize() { return bytes_total; } - - override bool isClass() { return true; } - override DClass asClass() { return this; } - - void addMember(DType type, char[] name) - { - auto s = DClassMember(type, members.length); - members[name] = s; - - bytes_total += type.byteSize(); - } - - int indexOf(char[] name) - { - if(name in members) - return members[name].index; - - return -1; - } - - DType typeOf(char[] name) - { - if (auto res = name in members) - return res.type; - return null; - } - - DClassMember[char[]] members; - private int bytes_total; - - override char[] mangle() - { - return "S"~Integer.toString(name.length)~name; - } - - override bool isSame(DType d) - { - if (d is this) - return true; - - if (!d.isClass) - return false; - - auto c = d.asClass; - - return id == c.id; - } - - struct DClassMember - { - DType type; - int index; - - char[] toString() - { - return type.toString(); - } - } -} - -class DInterface : DType -{ - this(Identifier id, DType actual = null) - { - super(id, actual); - } - - int byteSize() { return bytes_total; } - - override bool isInterface() { return true; } - override DInterface asInterface() { return this; } - - void addMember(DType type, char[] name) - { - auto s = DInterfaceMember(type, members.length); - members[name] = s; - - bytes_total += type.byteSize(); - } - - int indexOf(char[] name) - { - if(name in members) - return members[name].index; - - return -1; - } - - DType typeOf(char[] name) - { - if (auto res = name in members) - return res.type; - return null; - } - - override bool isSame(DType d) - { - if (d is this) - return true; - - if (!d.isInterface) - return false; - - auto i = d.asInterface; - - return id == i.id; - } - - DInterfaceMember[char[]] members; - private int bytes_total; - - override char[] mangle() - { - return "S"~Integer.toString(name.length)~name; - } - - struct DInterfaceMember - { - DType type; - int index; - - char[] toString() - { - return type.toString(); - } - } -} - -class DStaticArray : DType -{ - this(DType arrayOf, int size, DType actual = null) - { - super(arrayOf.id ~ "[" ~ Integer.toString(size) ~ "]", actual); - this.arrayOf = arrayOf; - this.size = size; - } - - override bool isStaticArray() { return true; } - override DStaticArray asStaticArray() { return this; } - - int byteSize() { return arrayOf.byteSize * size; } - - override bool isSame(DType d) - { - if (d is this) - return true; - - if (!d.isArray) - return false; - - auto a = d.asStaticArray; - - if (size != a.size) - return false; - - return arrayOf.isSame(a.arrayOf); - } - - char[] toString() - { - return arrayOf.toString~"["~Integer.toString(size)~"]"; - } - - - override char[] mangle() - { - return "G"~Integer.toString(size)~arrayOf.mangle; - } - - DType arrayOf; - const int size; -} - -class DArray : DType -{ - this(DType arrayOf, DType actual = null) - { - super(id, actual); - this.arrayOf = arrayOf; - } - - override bool isArray() { return true; } - override DArray asArray() { return this; } - - int byteSize() { return 8; } // FIXME: Size is a pointer + on size. (platform depend) - - override bool isSame(DType d) - { - if (d is this) - return true; - - if (!d.isArray) - return false; - - auto a = d.asArray; - - return arrayOf.isSame(a.arrayOf); - } - - override char[] mangle() - { - return "G"~arrayOf.mangle; // FIXME: Need correct mangling - } - - DType arrayOf; -} - -class DPointer : DType -{ - this(DType pointerOf, DType actual = null) - { - super(id, actual); - this.pointerOf = pointerOf; - } - - override bool isPointer() { return true; } - override DPointer asPointer() { return this; } - bool isCallable() { return pointerOf.isFunction(); } - DFunction asCallable() { return pointerOf.asFunction(); } - - int byteSize() { return DType.Int.byteSize; } - - override bool isSame(DType d) - { - if (d is this) - return true; - - if (!d.isPointer) - return false; - - auto p = d.asPointer; - - return pointerOf.isSame(p.pointerOf); - } - - char[] toString() - { - if (!pointerOf.isFunction) - return pointerOf.toString~"*"; - - auto f = pointerOf.asFunction; - - char[] res = f.returnType.toString~" function("; - - foreach (i, p ; f.params) - res ~= i ? ", "~p.toString : p.toString; - - return res ~ ")"; - } - - override char[] mangle() - { - return "P"~pointerOf.mangle; - } - - DType pointerOf; -} - -class DFunction : DType -{ - this(Identifier id, DType actual = null) - { - super(id, actual); - } - - override bool isFunction() { return true; } - override DFunction asFunction() { return this; } - bool isCallable() { return true; } - DFunction asCallable() { return this; } - - override bool hasImplicitConversionTo(DType that) - { - return returnType.hasImplicitConversionTo(that); - } - - override char[] mangle() - { - char[] res; - - res ~= "F"; - - foreach(param ; params) - res ~= param.mangle; - - res ~= "Z"; - res ~= returnType.mangle; - - return res; - } - - char[] toString() - { - char[] res = returnType.toString~" ("; - - foreach (i, p ; params) - res ~= i ? ", "~p.toString : p.toString; - - return res ~ ")"; - } - - override bool isSame(DType f) - { - if (f is this) - return true; - - if (!f.isFunction) - return false; - - auto func = f.asFunction; - - if (returnType != func.returnType) - return false; - - if (params.length != func.params.length) - return false; - - foreach (i, p ; params) - if (!p.isSame(func.params[0])) - return false; - - return true; - } - - DType[] params; - DType returnType; - bool firstParamIsReturnValue = false; -} - diff -r d442ce39917c -r 55ea834c8675 sema/LiteralInterpreter.d --- a/sema/LiteralInterpreter.d Sun Aug 10 16:23:09 2008 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,33 +0,0 @@ -module sema.LiteralInterpreter; - -import sema.Visitor; - -import basic.LiteralParsing, - basic.Message; - -class LiteralInterpreter : Visitor!(void) -{ - this(MessageHandler messages) - { - this.messages = messages; - } - - void visit(Module[] modules) - { - super.visit(modules); - messages.checkErrors(); - } - - void visitStringExp(StringExp exp) - { - auto str = parseString(exp.str, exp.loc, messages); - exp.data = str; - } - - void visitIntegerLit(IntegerLit exp) - { - exp.number = parseNumber(exp.name, exp.loc, messages); - } - - MessageHandler messages; -} diff -r d442ce39917c -r 55ea834c8675 sema/ObjectOriented.d --- a/sema/ObjectOriented.d Sun Aug 10 16:23:09 2008 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,64 +0,0 @@ -module sema.ObjectOriented; - -import sema.Visitor, - sema.Symbol, - sema.DType; - -import tango.io.Stdout, - Array = tango.core.Array; - -import basic.SourceLocation, - basic.Message; - -class ObjectOriented : Visitor!(void) -{ - this(MessageHandler messages) - { - this.messages = messages; - } - - override void visit(Module[] m) - { - super.visit(m); - - ClassDecl[] visitBaseClass(ClassDecl current, ClassDecl[] visited) - { - visited ~= current; - foreach (d ; current.baseClasses) - if (d.type.isClass) - if(Array.find(visited, - (cast(ClassDecl)d.getSymbol.decl)) - visited.length) - assert(0,"Circulair base class"); - else - return visitBaseClass((cast(ClassDecl)d.getSymbol.decl), visited); - return visited; - } - - while (classes.length) - { - ClassDecl current = classes[$-1]; - ClassDecl[] visited; - visited = visitBaseClass(current, visited); - foreach (v; visited) - classes.length = Array.remove(classes, v); - } - } - - override void visitClassDecl(ClassDecl decl) - { - classes ~= decl; - } - - ClassDecl[] classNoBase; - ClassDecl[] classes; - MessageHandler messages; -} - -class FindClassNoBase : Visitor!(void) -{ - override void visitClassDecl(ClassDecl decl) - { - } - - ClassDecl[] classes; -} diff -r d442ce39917c -r 55ea834c8675 sema/Operation.d --- a/sema/Operation.d Sun Aug 10 16:23:09 2008 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,137 +0,0 @@ -module sema.Operation; - -/// Operators -public enum Operator -{ - Add, Sub, Mul, Div, Rem, - Shl, LShr, AShr, - And, Or, Xor, - - Eq, Ne, - Lt, Le, - Gt, Ge, -} - -/** - Enum for the basic builtin operations. - - S for signed, U for unsigned and F for floating point. - **/ -public enum BuiltinOperation -{ - Add, Sub, Mul, SDiv, UDiv, FDiv, SRem, URem, FRem, - - // FShr is a dummy element to avoid special case for signed >> unsigned - Shl, LShr, AShr, FShr, - And, Or, Xor, - - Eq, Ne, - SLt, ULt, FLt, SLe, ULe, FLe, - SGt, UGt, FGt, SGe, UGe, FGe, - - None -} - -/** - Returns true if the operation has an unsigned variant. - - Will only be true for the S version, so SDiv gives true, UDiv or FDiv dont. - **/ -private bool hasUnsignedVariant(BuiltinOperation op) -{ - alias BuiltinOperation O; - return op is O.SDiv - || op is O.SRem - || op is O.SLt - || op is O.SLe - || op is O.SGt - || op is O.SGe; -} - -/// Same as hasUnsignedVariant, but for float variants -private bool hasFloatVariant(BuiltinOperation op) -{ - alias BuiltinOperation O; - return op is O.SDiv - || op is O.SRem - || op is O.SLt - || op is O.SLe - || op is O.SGt - || op is O.SGe; -} - -private BuiltinOperation OpToBI(Operator op) -{ - // This is dependent on the definition of Operator - // Maps from an Operator to the first appropiate BuiltinOperation - static const BuiltinOperation[] map = - [ - BuiltinOperation.Add, - BuiltinOperation.Sub, - BuiltinOperation.Mul, - BuiltinOperation.SDiv, - BuiltinOperation.SRem, - - BuiltinOperation.Shl, - BuiltinOperation.LShr, - BuiltinOperation.AShr, - BuiltinOperation.And, - BuiltinOperation.Or, - BuiltinOperation.Xor, - - BuiltinOperation.Eq, - BuiltinOperation.Ne, - BuiltinOperation.SLt, - BuiltinOperation.SLe, - BuiltinOperation.SGt, - BuiltinOperation.SGe, - - ]; - if (op >= Operator.Add && op <= Operator.Ge) - return map[op]; - - return BuiltinOperation.None; -} - -/** - Represents an operation on to values of (potentionally) different types. - - Can be either some built-in thing (addition of floats, int etc) or a user - defined operation (a method in a struct/class). - **/ -struct Operation -{ - /// Returns true if the operation is legal - bool isPossible() { return is_valid; } - - /// True for <, <=, ==, !=, >, >= - bool isComparison() { return false; } - - /// Built in operations like adding ints or floats - bool isBuiltin() { return is_bi; } - - /// Get the builtin operation - only valid if isBuiltin() returns true - BuiltinOperation builtinOp() { return bi_op; }; - - /// Create builtin operation - static Operation builtin(Operator op, bool unsigned, bool fp) - { - assert(!(unsigned && fp), "Can't be both unsigned and a float"); - Operation res; - res.is_valid = true; - res.is_bi = true; - res.bi_op = OpToBI(op); - - if (unsigned && hasUnsignedVariant(res.bi_op)) - res.bi_op += 1; - if (fp && hasFloatVariant(res.bi_op)) - res.bi_op += 2; - return res; - } - -private: - bool is_valid = false; - bool is_bi; - BuiltinOperation bi_op; -} - diff -r d442ce39917c -r 55ea834c8675 sema/Scope.d --- a/sema/Scope.d Sun Aug 10 16:23:09 2008 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,156 +0,0 @@ -module sema.Scope; - -import tango.io.Stdout; - -import lexer.Token, - ast.Module, - ast.Decl; - -public -import sema.DType, - sema.Symbol; - -class Scope -{ - this() {} - this(Scope enclosing) - { - this.enclosing = enclosing; - this.func = enclosing.func; - this.inModule = enclosing.inModule; - this.mHandle = enclosing.mHandle; - } - - Scope enclosing; - ModuleHandler mHandle; - Module inModule; - Scope[] imported; - - ImportDecl[] imports; - - void put(char[] id, Decl d) - { - symbols[id] ~= d; - } - - Decl[] find(char[] id) - { - if(id is "") - return null; - else if (auto sym = id in symbols) - { - return *sym; - } - else if (enclosing !is null) - { - auto res = enclosing.find(id) ~ mHandle.find(getImports, id); - return res; - } - return []; - } - - ImportDecl[] getImports() - { - if(enclosing) - return enclosing.getImports ~ imports; - return imports; - } - - DType findType(char[] id) - { - if (auto type = id in types) - return *type; - if (enclosing !is null) - { - auto type = enclosing.findType(id); - if(type is null) - return mHandle.findType(getImports, id); - return type; - } - return null; - } - - FuncDecl parentFunction() - { - if (func !is null) - return func; - else if (enclosing !is null) - return enclosing.parentFunction(); - else - return null; - } - - int stmtIndex() - { - if (currentStmtIndex != -1) - return currentStmtIndex; - else if (enclosing !is null) - return enclosing.stmtIndex(); - else - return -1; - } - - int opEquals(Object o) - { - return this is o; - } - - char[] toString() - { - if (func) - return Stdout.layout.convert("{}: {}", func.identifier.get, symbols.length); - return Stdout.layout.convert("root: {}", symbols.length); - } - - FuncDecl parentFunction(FuncDecl f) - { - func = f; - return f; - } - DType[char[]] types; - int currentStmtIndex = -1; -private: - Decl[][char[]] symbols; - FuncDecl func; -} - -class ModuleHandler -{ - void add(Module m) - { - modules[m.moduleName] = m; - } - void add(Module m, char[] file) - { - fileToModule[file] = m.moduleName; - add(m); - } - - DType findType(ImportDecl[] imports, char[] type) - { - foreach(i ; imports) - if(i.get in modules) - { - auto t = modules[i.get].env.findType(type); - if(t !is null) - return t; - } - return null; - } - - Decl[] find(ImportDecl[] imports, char[] id) - { - foreach(i ; imports) - if(i.get in modules) - { - auto t = modules[i.get].env.find(id); - if(t !is null) - return t; - } - return []; - } - - char[][char[]] fileToModule; - Module[char[]] modules; -} - diff -r d442ce39917c -r 55ea834c8675 sema/Symbol.d --- a/sema/Symbol.d Sun Aug 10 16:23:09 2008 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,166 +0,0 @@ -module sema.Symbol; - -import tango.text.convert.Integer : format; -import tango.io.Stdout; - -import sema.DType; - -import ast.Decl; - -/// -class Symbol -{ - /// Create a root symbol - representing a module - this() { actual = this; } - - /// Get a simple human readable name (bar) - char[] getName() { return name; } - - /// Get a human readable name (foo.bar) - char[] getFQN() - { - char[] prefix; - if (parent !is null && parent.name !is null) - prefix ~= parent.getFQN() ~ "."; - return prefix ~ name; - } - - /// Get a machine readable name (_D3foo3barFZi) - char[] getMangledFQN() - { - char[] n = `_D`; - Symbol p = parent; - while (p !is null) { - n ~= p.internalFQN(); - p = p.parent; - } - n ~= internalFQN(); - n ~= type.mangle(); - return n; - } - - /** - Try to find a contained symbol with the given name - **/ - Symbol[] findMembers(char[] member) - { - Symbol[] res; - foreach (possible; actual.contained) - if (possible.name == member) - res ~= possible; - - if (!res.length && actual.type.isClass) - { - foreach (base ; (cast(ClassDecl)actual.decl).baseClasses) - if (base.type.isClass) - res ~= base.getSymbol.findMembers(member); - } - return res; - } - - /** - Try to find a contained symbol with the given name, who's type is a DFunction - **/ - Symbol[] findFunctionMembers(char[] member) - { - Symbol[] res; - foreach (possible; actual.contained) - if (possible.name == member && possible.type.isFunction) - res ~= possible; - return res; - } - - /** - Get the members of the symbol - **/ - Symbol[] getMembers() - { - return actual.contained; - } - - void dump() - { - Stdout("Symbol: "); - Symbol p = parent; - while (p !is null) { - Stdout.format("{}.", p.name); - p = p.parent; - } - Stdout.formatln("{}", name); - } - - /// Create a member with the given name and type - Symbol createMember(char[] member, DType type, Decl decl) - { - auto res = new Symbol(member, type, this); - res.decl = decl; - actual.contained ~= res; - return res; - } - - /** - Create an alias of another symbol with the given name. - - The target symbol can be a member of another symbol - **/ - Symbol createAlias(char[] aliasedName, Symbol target, Decl decl) - { - auto res = new Symbol(aliasedName, target, this); - res.decl = decl; - actual.contained ~= res; - return res; - } - - // The type of this symbol - DType type; - // The declaration of this symbol - Decl decl; - // If the symbol is an alias, this will point to the actual symbol - Symbol actual; - // If this symbol is contained within a struct or similar this will point - // to that symbol - Symbol parent; - - char[] toString() - { - return getMangledFQN; - } - -private: - // Helper for getMangledFQN - gets the FQN without _D and the type - char[] internalFQN() - { - if (actual.name !is null && actual.name.length > 0) - { - char[32] len; - return format(len, actual.name.length) ~ actual.name; - } - return ""; - } - - this(char[] name, Symbol actual, Symbol parent) - { - this.name = name; - this.actual = actual; - this.parent = parent; - this.type = actual.type; - } - - this(char[] name, DType type, Symbol parent) - { - this.name = name; - this.actual = this; - this.parent = parent; - this.type = type; - } - -private: - char[] name; - - // All the symbols contained within this symbol - Symbol[] contained; - - // The module that contains this symbol (root of the parent-chain) - // DModule mod; -} - diff -r d442ce39917c -r 55ea834c8675 sema/VC.d --- a/sema/VC.d Sun Aug 10 16:23:09 2008 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,14 +0,0 @@ -module sema.VC; - -import basic.Message; - -/** - VC is short for verification context. - - This class holds various things that are neccesary to verify validity - of the AST. -**/ -class VC -{ - MessageHandler msg; -} diff -r d442ce39917c -r 55ea834c8675 sema/Visitor.d --- a/sema/Visitor.d Sun Aug 10 16:23:09 2008 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,509 +0,0 @@ -module sema.Visitor; - -import tango.io.Stdout; - -public -import ast.Module, - ast.Decl, - ast.Stmt, - ast.Exp; - -import lexer.Token; - -class Visitor(FinalT = int, ModuleT = FinalT, DeclT = ModuleT, StmtT = DeclT, ExpT = StmtT) -{ -public: - FinalT visit(Module[] modules) - { - foreach(m ; modules) - visitModule(m); - static if (is(FinalT == void)) - return; - else - return FinalT.init; - } - - ModuleT visitModule(Module m) - { - foreach (decl; m.decls) - visitDecl(decl); - static if (is(ModuleT == void)) - return; - else - return ModuleT.init; - } - - DeclT visitDecl(Decl decl) - { - switch(decl.declType) - { - case DeclType.FuncDecl: - return visitFuncDecl(cast(FuncDecl)decl); - case DeclType.VarDecl: - return visitVarDecl(cast(VarDecl)decl); - case DeclType.ImportDecl: - return visitImportDecl(cast(ImportDecl)decl); - case DeclType.StructDecl: - return visitStructDecl(cast(StructDecl)decl); - case DeclType.ClassDecl: - return visitClassDecl(cast(ClassDecl)decl); - case DeclType.InterfaceDecl: - return visitInterfaceDecl(cast(InterfaceDecl)decl); - case DeclType.AliasDecl: - return visitAliasDecl(cast(AliasDecl)decl); - default: - throw new Exception("Unknown declaration type"); - } - } - - StmtT visitStmt(Stmt stmt) - { - switch(stmt.stmtType) - { - case StmtType.Return: - return visitReturnStmt(cast(ReturnStmt)stmt); - case StmtType.Compound: - return visitCompoundStmt(cast(CompoundStatement)stmt); - case StmtType.Decl: - return visitDeclStmt(cast(DeclStmt)stmt); - case StmtType.Exp: - return visitExpStmt(cast(ExpStmt)stmt); - case StmtType.If: - return visitIfStmt(cast(IfStmt)stmt); - case StmtType.While: - return visitWhileStmt(cast(WhileStmt)stmt); - case StmtType.For: - return visitForStmt(cast(ForStmt)stmt); - case StmtType.Switch: - return visitSwitchStmt(cast(SwitchStmt)stmt); - default: - throw new Exception("Unknown statement type"); - } - } - - ExpT visitExp(Exp exp) - { - switch(exp.expType) - { - case ExpType.Binary: - return visitBinaryExp(cast(BinaryExp)exp); - case ExpType.IntegerLit: - return visitIntegerLit(cast(IntegerLit)exp); - case ExpType.Negate: - return visitNegateExp(cast(NegateExp)exp); - case ExpType.Deref: - return visitDerefExp(cast(DerefExp)exp); - case ExpType.AddressOfExp: - return visitAddressOfExp(cast(AddressOfExp)exp); - case ExpType.AssignExp: - return visitAssignExp(cast(AssignExp)exp); - case ExpType.CallExp: - return visitCallExp(cast(CallExp)exp); - case ExpType.CastExp: - return visitCastExp(cast(CastExp)exp); - case ExpType.Identifier: - return visitIdentifier(cast(Identifier)exp); - case ExpType.IdentifierTypeExp: - return visitIdentifier(cast(Identifier)exp); - case ExpType.PointerTypeExp: - return visitPointerTypeExp(cast(PointerTypeExp)exp); - case ExpType.StaticArrayTypeExp: - return visitStaticArrayTypeExp(cast(StaticArrayTypeExp)exp); - case ExpType.FunctionTypeExp: - return visitFunctionTypeExp(cast(FunctionTypeExp)exp); - case ExpType.StringExp: - return visitStringExp(cast(StringExp)exp); - case ExpType.Index: - return visitIndexExp(cast(IndexExp)exp); - case ExpType.MemberReference: - return visitMemberReference(cast(MemberReference)exp); - case ExpType.NewExp: - return visitNewExp(cast(NewExp)exp); - case ExpType.ArrayLiteralExp: - return visitArrayLiteralExp(cast(ArrayLiteralExp)exp); - case ExpType.NullExp: - return visitNullExp(cast(NullExp)exp); - default: - throw new Exception("Unknown expression type"); - } - } - - // Declarations: - DeclT visitVarDecl(VarDecl d) - { - visitExp(d.varType); - if(d.identifier) - visitExp(d.identifier); - if (d.init) - visitExp(d.init); - - static if (is(DeclT == void)) - return; - else - return DeclT.init; - } - - DeclT visitImportDecl(ImportDecl d) - { - visitIdentifier(d.name); - visitIdentifier(d.aliasedName); - foreach (id; d.packages) - visitIdentifier(id); - foreach (ids; d.explicitSymbols) - { - visitIdentifier(ids[0]); - visitIdentifier(ids[1]); - } - - static if (is(DeclT == void)) - return; - else - return DeclT.init; - } - - DeclT visitFuncDecl(FuncDecl f) - { - visitExp(f.returnType); - visitExp(f.identifier); - foreach (arg; f.funcArgs) - visitDecl(arg); - foreach (stmt; f.statements) - visitStmt(stmt); - - static if (is(DeclT == void)) - return; - else - return DeclT.init; - } - - DeclT visitStructDecl(StructDecl s) - { - visitExp(s.identifier); - - foreach (arg; s.decls) - visitDecl(arg); - - static if (is(DeclT == void)) - return; - else - return DeclT.init; - } - - DeclT visitClassDecl(ClassDecl s) - { - visitExp(s.identifier); - - foreach (arg; s.decls) - visitDecl(arg); - - foreach (arg; s.baseClasses) - visitExp(arg); - - static if (is(DeclT == void)) - return; - else - return DeclT.init; - } - - DeclT visitInterfaceDecl(InterfaceDecl s) - { - visitExp(s.identifier); - - foreach (arg; s.decls) - visitDecl(arg); - - foreach (arg; s.baseClasses) - visitExp(arg); - - static if (is(DeclT == void)) - return; - else - return DeclT.init; - } - - DeclT visitAliasDecl(AliasDecl a) - { - static if (is(DeclT == void)) - return; - else - return DeclT.init; - } - - // Statements: - StmtT visitReturnStmt(ReturnStmt s) - { - if (s.exp) - visitExp(s.exp); - static if (is(StmtT == void)) - return; - else - return StmtT.init; - } - - StmtT visitDeclStmt(DeclStmt d) - { - visitDecl(d.decl); - static if (is(StmtT == void)) - return; - else - return StmtT.init; - } - - StmtT visitCompoundStmt(CompoundStatement c) - { - foreach (stmt; c.statements) - visitStmt(stmt); - static if (is(StmtT == void)) - return; - else - return StmtT.init; - } - - StmtT visitIfStmt(IfStmt s) - { - visitExp(s.cond); - visitStmt(s.then_body); - if (s.else_body !is null) - visitStmt(s.else_body); - static if (is(StmtT == void)) - return; - else - return StmtT.init; - } - - StmtT visitWhileStmt(WhileStmt s) - { - visitExp(s.cond); - visitStmt(s.whileBody); - static if (is(StmtT == void)) - return; - else - return StmtT.init; - } - - StmtT visitForStmt(ForStmt s) - { - if(s.init) - visitStmt(s.init); - if(s.cond) - visitExp(s.cond); - if(s.incre) - visitExp(s.incre); - visitStmt(s.forBody); - static if (is(StmtT == void)) - return; - else - return StmtT.init; - } - - StmtT visitSwitchStmt(SwitchStmt s) - { - visitExp(s.cond); - foreach(stmt; s.defaultBlock) - visitStmt(stmt); - foreach (c; s.cases) - { - foreach(lit; c.values) - visitExp(lit); - foreach(stmt; c.stmts) - visitStmt(stmt); - } - static if (is(StmtT == void)) - return; - else - return StmtT.init; - } - - StmtT visitExpStmt(ExpStmt s) - { - visitExp(s.exp); - static if (is(StmtT == void)) - return; - else - return StmtT.init; - } - - // Expressions: - ExpT visitAssignExp(AssignExp exp) - { - visitExp(exp.identifier); - visitExp(exp.exp); - static if (is(ExpT == void)) - return; - else - return ExpT.init; - } - - ExpT visitBinaryExp(BinaryExp exp) - { - visitExp(exp.left); - visitExp(exp.right); - static if (is(ExpT == void)) - return; - else - return ExpT.init; - } - - ExpT visitCallExp(CallExp exp) - { - visitExp(exp.exp); - foreach (arg; exp.args) - visitExp(arg); - static if (is(ExpT == void)) - return; - else - return ExpT.init; - } - - ExpT visitCastExp(CastExp exp) - { - visitExp(exp.castType); - visitExp(exp.exp); - static if (is(ExpT == void)) - return; - else - return ExpT.init; - } - - ExpT visitNegateExp(NegateExp exp) - { - visitExp(exp.exp); - static if (is(ExpT == void)) - return; - else - return ExpT.init; - } - - ExpT visitDerefExp(DerefExp exp) - { - visitExp(exp.exp); - static if (is(ExpT == void)) - return; - else - return ExpT.init; - } - - ExpT visitAddressOfExp(AddressOfExp exp) - { - visitExp(exp.exp); - static if (is(ExpT == void)) - return; - else - return ExpT.init; - } - - ExpT visitIntegerLit(IntegerLit exp) - { - static if (is(ExpT == void)) - return; - else - return ExpT.init; - } - - ExpT visitStringExp(StringExp exp) - { - static if (is(ExpT == void)) - return; - else - return ExpT.init; - } - - ExpT visitIdentifier(Identifier exp) - { - static if (is(ExpT == void)) - return; - else - return ExpT.init; - } - - ExpT visitPointerTypeExp(PointerTypeExp exp) - { - visitExp(exp.pointerOf); - - static if (is(ExpT == void)) - return; - else - return ExpT.init; - } - - ExpT visitStaticArrayTypeExp(StaticArrayTypeExp exp) - { - visitExp(exp.arrayOf); - - static if (is(ExpT == void)) - return; - else - return ExpT.init; - } - - ExpT visitFunctionTypeExp(FunctionTypeExp exp) - { - visitExp(exp.returnType); - - foreach (decl ; exp.decls) - visitDecl(decl); - - static if (is(ExpT == void)) - return; - else - return ExpT.init; - } - - ExpT visitIndexExp(IndexExp exp) - { - visitExp(exp.target); - visitExp(exp.index); - - static if (is(ExpT == void)) - return; - else - return ExpT.init; - } - - ExpT visitMemberReference(MemberReference mem) - { - visitExp(mem.target); - visitExp(mem.child); - - static if (is(ExpT == void)) - return; - else - return ExpT.init; - } - - ExpT visitNewExp(NewExp n) - { - visitExp(n.newType); - - foreach( a ; n.a_args ) - visitExp(a); - - foreach( c ; n.c_args ) - visitExp(c); - - static if (is(ExpT == void)) - return; - else - return ExpT.init; - } - - ExpT visitArrayLiteralExp(ArrayLiteralExp a) - { - foreach( e ; a.exps ) - visitExp(e); - - static if (is(ExpT == void)) - return; - else - return ExpT.init; - } - - ExpT visitNullExp(NullExp n) - { - static if (is(ExpT == void)) - return; - else - return ExpT.init; - } -} - diff -r d442ce39917c -r 55ea834c8675 tools/AstPrinter.d --- a/tools/AstPrinter.d Sun Aug 10 16:23:09 2008 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,376 +0,0 @@ -module tools.AstPrinter; - -import tango.io.Stdout; - -import ast.Module, - ast.Decl, - ast.Stmt, - ast.Exp; - -import basic.SourceManager, - basic.Attribute; - -class AstPrinter -{ - const char[] tabType = " "; // 4 spaces - - this(SourceManager sm) - { - - this.sm = sm; - } - - void print(Module m) - { - printBeginLine("module "); - print(m.moduleName); - printEndLine(";"); - printEndLine(); - foreach(decl ; m.decls) - { - printDecl(decl); - } - printEndLine(); - } - - void printDecl(Decl decl, bool printAtt = true) - { - switch(decl.declType) - { - case DeclType.FuncDecl: - auto funcDecl = cast(FuncDecl)decl; - printBeginLine(); - if (printAtt) printAttribute(decl.att); - if (funcDecl.identifier.get != "this") - { - printIdentifier(funcDecl.returnType); - space; - } - printIdentifier(funcDecl.identifier); - printFuncArgs(funcDecl); - printOpenBrace(); - foreach(stmt ; funcDecl.statements) - printStatement(stmt); - printCloseBrace(); - break; - - case DeclType.VarDecl: - auto varDecl = cast(VarDecl)decl; - printBeginLine(); - if(printAtt) printAttribute(decl.att); - printExp(varDecl.varType); - space; - printExp(varDecl.identifier); - if(varDecl.init) - { - print(" = "); - printExp(varDecl.init); - } - printEndLine(";"); - break; - - case DeclType.StructDecl: - auto structDecl = cast(StructDecl)decl; - if(printAtt) printAttribute(decl.att); - printBeginLine("struct "); - printIdentifier(structDecl.identifier); - printEndLine; - printOpenBrace; - foreach( var ; structDecl.decls) - printDecl(var); - printCloseBrace; - break; - - case DeclType.ClassDecl: - auto classDecl = cast(ClassDecl)decl; - if(printAtt) printAttribute(decl.att); - printBeginLine("class "); - printIdentifier(classDecl.identifier); - foreach(i, iden ; classDecl.baseClasses ) - { - print(i ? " : " : ", "); - printIdentifier(iden); - } - printEndLine; - printOpenBrace; - foreach( var ; classDecl.decls) - printDecl(var); - printCloseBrace; - break; - - case DeclType.InterfaceDecl: - auto interfaceDecl = cast(InterfaceDecl)decl; - if(printAtt) printAttribute(decl.att); - printBeginLine("interface "); - printIdentifier(interfaceDecl.identifier); - foreach(i, iden ; interfaceDecl.baseClasses ) - { - print(i ? " : " : ", "); - printIdentifier(iden); - } - printEndLine; - printOpenBrace; - foreach( var ; interfaceDecl.decls) - printDecl(var); - printCloseBrace; - break; - - case DeclType.ImportDecl: - auto i = cast(ImportDecl)decl; - if(printAtt) printAttribute(decl.att); - printBeginLine("import "); - printEndLine(i.get); - break; - } -// printEndLine(); - } - - void printStatement(Stmt stmt) - { - switch(stmt.stmtType) - { - case StmtType.Return: - auto ret = cast(ReturnStmt)stmt; - printBeginLine("return"); - if(ret.exp) - { - space; - printExp(ret.exp); - } - printEndLine(";"); - break; - case StmtType.If: - auto i = cast(IfStmt)stmt; - printBeginLine("if"); - print(" ("); - printExp(i.cond); - printEndLine(" )"); - printOpenBrace; - printStatement(i.then_body); - printCloseBrace; - if (i.else_body) - { - printBeginLine("else"); - printEndLine(); - printOpenBrace; - printStatement(i.else_body); - printCloseBrace; - } - break; - case StmtType.Decl: - auto declStmt = cast(DeclStmt)stmt; - printDecl(declStmt.decl, false); - break; - case StmtType.Exp: - auto expStmt = cast(ExpStmt)stmt; - printBeginLine(); - printExp(expStmt.exp); - printEndLine(";"); - break; - - } - } - - void printExp(Exp exp) - { - switch(exp.expType) - { - case ExpType.Binary: - auto binaryExp = cast(BinaryExp)exp; - print("("); - printExp(binaryExp.left); - print(" " ~ binaryExp.getOp[binaryExp.op] ~ " "); - printExp(binaryExp.right); - print(")"); - break; - case ExpType.IntegerLit: - auto integetLit = cast(IntegerLit)exp; - print(integetLit.get); - break; - case ExpType.Negate: - auto negateExp = cast(NegateExp)exp; - print("-"); - printExp(negateExp.exp); - break; - case ExpType.Deref: - auto derefExp = cast(DerefExp)exp; - print("*"); - printExp(derefExp.exp); - break; - case ExpType.AssignExp: - auto assignExp = cast(AssignExp)exp; - printExp(assignExp.identifier); - print(" "); - print(assignExp.getOp[assignExp.op]); - print(" "); - printExp(assignExp.exp); - break; - case ExpType.MemberReference: - auto mrExp = cast(MemberReference)exp; - printExp(mrExp.target); - print("."); - printIdentifier(mrExp.child); - break; - case ExpType.Identifier: - auto iden = cast(Identifier)exp; - printIdentifier(iden); - break; - case ExpType.IdentifierTypeExp: - auto iden = cast(Identifier)exp; - printIdentifier(iden); - break; - case ExpType.PointerTypeExp: - auto iden = cast(PointerTypeExp)exp; - printExp(iden.pointerOf); - print("*"); - break; - case ExpType.CallExp: - auto callExp = cast(CallExp)exp; - printExp(callExp.exp); - print("("); - foreach(i, e; callExp.args) - { - printExp(e); - if(i+1 < callExp.args.length) - print(", "); - } - print(")"); - break; - case ExpType.CastExp: - auto castExp = cast(CastExp)exp; - print("cast"); - print("("); - printExp(castExp.castType); - print(")"); - printExp(castExp.exp); - break; - case ExpType.NewExp: - auto newExp = cast(NewExp)exp; - print("new "); - if(newExp.a_args.length) - { - foreach( i, a ; newExp.a_args ) - { - print(i ? ", " : "("); - printExp(a); - } - print(")"); - } - printExp(newExp.newType); - print("("); - foreach( i, c ; newExp.c_args ) - { - print(i ? ", " : ""); - printExp(c); - } - print(")"); - break; - } - - } - - void printFuncArgs(FuncDecl decl) - { - print("("); - - foreach(i, d; decl.funcArgs) - { - printIdentifier(d.varType); - if(i == 0 && decl.sret) - print("*"); - space; - printIdentifier(d.identifier); - if(i+1 < decl.funcArgs.length) - print(","); - } - - printEndLine(")"); - } - - void printIdentifier(Identifier identifier) - { - print(identifier.get); - } - - void printOpenBrace() - { - printEndLine(tabIndex~"{"); - tabIndex ~= tabType; - } - - void printCloseBrace() - { - tabIndex = tabIndex[0 .. $-tabType.length]; - printEndLine(tabIndex~"}"); - } - - void printAttribute(Attribute a) - { - switch(a.getExtern) - { - case Extern.C: - print("extern(C) "); - break; - case Extern.CPlusPlus: - print("extern(C++) "); - break; - case Extern.D: - break; - } - switch(a.getProtection) - { - case Protection.Public: - print("public "); - break; - case Protection.Private: - print("private "); - break; - case Protection.Package: - print("package "); - break; - case Protection.Protected: - print("protected "); - break; - case Protection.Export: - print("export "); - break; - } - if ( a.getStatic ) - print("static "); - if ( a.getFinal ) - print("final "); - if ( a.getConst ) - print("const "); - if ( a.getAbstract ) - print("abstract "); - if ( a.getOverride ) - print("override "); - if ( a.getDeprecated ) - print("deprecated "); - if ( a.getAuto ) - print("auto "); - } - - void printBeginLine(char[] line = "") - { - Stdout(tabIndex~line); - } - - void printEndLine(char[] line = "") - { - Stdout(line).newline; - } - - void print(char[] line) - { - Stdout(line); - } - - void space() - { - print(" "); - } -private: - SourceManager sm; - char[] tabIndex; -} diff -r d442ce39917c -r 55ea834c8675 tools/DotPrinter.d --- a/tools/DotPrinter.d Sun Aug 10 16:23:09 2008 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,163 +0,0 @@ -module tools.DotPrinter; - -import tango.io.Stdout, - Int = tango.text.convert.Integer; - -import ast.Module, - ast.Decl, - ast.Stmt, - ast.Exp; - -class DotPrinter -{ - this() - { - } - - private char[][void*] identifiers; - private int current_id = 0; - - void print(Module m) - { - Stdout("digraph {").newline; - foreach(decl ; m.decls) - { - printDecl(decl); - } - Stdout("}").newline; - } - - void printDecl(Decl decl) - { - switch(decl.declType) - { - case DeclType.FuncDecl: - FuncDecl funcDecl = cast(FuncDecl)decl; - - //printIdentifier(funcDecl.identifier); - //printFuncArgs(funcDecl.funcArgs); - Stdout(dotId(decl))(` [label="function`); - Stdout(`\n name: `)(text(funcDecl.identifier)); - Stdout(`\n return type: `)(text(funcDecl.returnType)); - Stdout(`", shape=box, fillcolor=lightblue, style=filled]`); - Stdout.newline; - //Stdout(`"`); - foreach(stmt ; funcDecl.statements) - printStatement(dotId(decl), stmt); - break; - - case DeclType.VarDecl: - VarDecl varDecl = cast(VarDecl)decl; - - //printIdentifier(funcDecl.identifier); - //printFuncArgs(funcDecl.funcArgs); - Stdout(dotId(decl))(` [label="var`); - Stdout(`\n name: `)(text(varDecl.identifier)); - Stdout(`\n type: `)(text(varDecl.varType)); - Stdout(`"]`).newline; - - if (varDecl.init !is null) - printExpression(dotId(decl), varDecl.init); - break; - } - } - - void printStatement(char[] parent, Stmt stmt) - { - auto id = dotId(stmt); - switch (stmt.stmtType) - { - case StmtType.Stmt: - Stdout(id)(` [label="Statement"]`).newline; - Stdout(parent)(` -> `)(id).newline; - break; - - case StmtType.Decl: - Stdout(id)(` [label="Decl"]`).newline; - Stdout(parent)(` -> `)(id).newline; - auto decl = (cast(DeclStmt)stmt).decl; - printDecl(decl); - Stdout(id)(` -> `)(dotId(decl)).newline; - break; - - case StmtType.Return: - Stdout(id)(` [label="Return"]`).newline; - Stdout(parent)(` -> `)(id).newline; - printExpression(id, (cast(ReturnStmt)stmt).exp); - break; - - case StmtType.Exp: - Stdout(parent)(` -> `)(id).newline; - printExpression(id, (cast(ExpStmt)stmt).exp); - break; - } - } - - void printExpression(char[] parent, Exp exp) - { - auto id = dotId(exp); - - switch(exp.expType) - { - case ExpType.Binary: - auto bin = cast(BinaryExp)exp; - Stdout(id)(` [label="`)(bin.op)(`"]`).newline; - printExpression(id, bin.left); - printExpression(id, bin.right); - break; - - case ExpType.Negate: - auto neg = cast(NegateExp)exp; - Stdout(id)(` [label="Negate"]`).newline; - printExpression(id, neg.exp); - break; - - case ExpType.IntegerLit: - auto e = cast(IntegerLit)exp; - Stdout(id)(` [label="`)(text(e.get))(`"]`).newline; - break; - - case ExpType.Identifier: - auto e = cast(Identifier)exp; - Stdout(id)(` [label="`)(text(e))(`"]`).newline; - break; - - case ExpType.AssignExp: - auto ass = cast(AssignExp)exp; - Stdout(parent)(` [label="Assign"]`).newline; -// Stdout(id)(` [label="`)(text(ass.identifier))(`"]`).newline; - printExpression(parent, ass.exp); - break; - - case ExpType.CallExp: - break; - } - Stdout(parent)(` -> `)(id).newline; - } - - char[] dotId(Decl d) { return dotId(cast(void*)d); } - char[] dotId(Stmt s) { return dotId(cast(void*)s); } - char[] dotId(Exp e) { return dotId(cast(void*)e); } - - char[] dotId(void* o) - { - auto id = o in identifiers; - if (id is null) - { - ++current_id; - identifiers[o] = Int.toString(current_id); - id = o in identifiers; - } - return *id; - } - - char[] text(Identifier identifier) - { - return identifier.get; - } - char[] text(char[] t) - { - return t; - } -} -