# HG changeset patch # User johnsen@johnsen-laptop # Date 1215805677 -7200 # Node ID 2be29b296081699912739f774351a35e8bd17714 # Parent 9869194de9b7b8094443f1e7ad2ce2d246302b1a Lots of changes: - Parsing classes and interfaces - Fixed some seg faults in sema - Supporting "private" to some extend - And a lot of other small fixes diff -r 9869194de9b7 -r 2be29b296081 ast/Decl.d --- a/ast/Decl.d Wed Jul 09 13:38:11 2008 +0200 +++ b/ast/Decl.d Fri Jul 11 21:47:57 2008 +0200 @@ -40,6 +40,19 @@ 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; diff -r 9869194de9b7 -r 2be29b296081 ast/Exp.d --- a/ast/Exp.d Wed Jul 09 13:38:11 2008 +0200 +++ b/ast/Exp.d Fri Jul 11 21:47:57 2008 +0200 @@ -25,6 +25,7 @@ Index, Identifier, ArrayIdentifier, + StaticArrayIdentifier, PointerIdentifier, AssignExp, CallExp, @@ -458,8 +459,8 @@ override DType type() { DType type = target.type(); - if (type.isArray()) - return type.asArray().arrayOf; + if (type.isStaticArray()) + return type.asStaticArray().arrayOf; else if (type.isPointer()) return type.asPointer().pointerOf; else assert(0, "Can only index pointers and arrays"); @@ -542,11 +543,11 @@ Identifier pointerOf; } -class ArrayIdentifier : Identifier +class StaticArrayIdentifier : Identifier { this(Identifier arrayOf, IntegerLit size) { - super(ExpType.ArrayIdentifier, arrayOf.loc); + super(ExpType.StaticArrayIdentifier, arrayOf.loc); this.arrayOf = arrayOf; this.size = Integer.parse(size.get); this.name = arrayOf.name; @@ -554,7 +555,7 @@ override DType type() { - return arrayOf.type.getAsArray(size); + return arrayOf.type.getAsStaticArray(size); } Identifier arrayOf; @@ -563,6 +564,25 @@ private DType myType; } +class ArrayIdentifier : Identifier +{ + this(Identifier arrayOf) + { + super(ExpType.ArrayIdentifier, arrayOf.loc); + this.arrayOf = arrayOf; + this.name = arrayOf.name; + } + + override DType type() + { + return arrayOf.type.getAsArray(); + } + + Identifier arrayOf; + + private DType myType; +} + class Identifier : Exp { this(SLoc loc, char[] name) diff -r 9869194de9b7 -r 2be29b296081 ast/Module.d --- a/ast/Module.d Wed Jul 09 13:38:11 2008 +0200 +++ b/ast/Module.d Fri Jul 11 21:47:57 2008 +0200 @@ -21,5 +21,6 @@ char[] moduleName; Scope env; Symbol symbol; + bool outputModule = true; } diff -r 9869194de9b7 -r 2be29b296081 basic/Attribute.d --- a/basic/Attribute.d Wed Jul 09 13:38:11 2008 +0200 +++ b/basic/Attribute.d Fri Jul 11 21:47:57 2008 +0200 @@ -1,5 +1,10 @@ module basic.Attribute; +import tango.core.BitManip; +import Integer = tango.text.convert.Integer; + +import tango.io.Stdout; + enum Protection : uint { Private = 1<<0, @@ -15,7 +20,33 @@ void setProtection(Protection p) { att &= 0xFFFFFFE0; - att |= ~p; + 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 setStatic() { att &= ~Static; } @@ -26,6 +57,11 @@ void setDepracted() { att &= ~Depracted; } void setAuto() { att &= ~Auto; } + char[] toString() + { + return Integer.toString(att); + } + private: uint att; diff -r 9869194de9b7 -r 2be29b296081 basic/Messages.d --- a/basic/Messages.d Wed Jul 09 13:38:11 2008 +0200 +++ b/basic/Messages.d Fri Jul 11 21:47:57 2008 +0200 @@ -32,6 +32,7 @@ UndefinedIdentifier, UndefinedType, MissingMember, + CannotRedeclare, // Strings InvalidStrPrefix, @@ -48,6 +49,9 @@ FloatingInvalidEnd, FloatingBadLocation, FloatingDotInE, + + // Protection + CannotAccessPrivate, } enum MessageType @@ -96,6 +100,7 @@ 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'"), // literals InvalidStrPrefix : E(Err, "Invalid string literal prefix"), @@ -111,7 +116,8 @@ 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") + FloatingDotInE : E(Err, "There cannot be a dot in the exponent of a floating literal"), + CannotAccessPrivate : E(Err, "Cannot access private member.") ]; } diff -r 9869194de9b7 -r 2be29b296081 dang/compiler.d --- a/dang/compiler.d Wed Jul 09 13:38:11 2008 +0200 +++ b/dang/compiler.d Fri Jul 11 21:47:57 2008 +0200 @@ -5,6 +5,7 @@ tango.core.Memory, tango.sys.Process, tango.time.StopWatch, + tango.text.Util, tango.io.FileConduit, tango.io.FilePath; @@ -30,8 +31,13 @@ sema.TypeCheck; import tango.stdc.posix.unistd; +import tango.stdc.stdlib; import Opt = dang.OptParse; + +class NullAction : Action +{ +} void checkFiles(char[][] *files) { @@ -64,7 +70,7 @@ if (fileInStack) continue; - validFiles ~= file; + validFiles ~= path.toString(); } *files = validFiles; @@ -86,6 +92,7 @@ Signal!(Lexer) preParse; Signal!(Module[], SourceManager) postParse; + Signal!(Module[], SourceManager) postSema; preStart.attach(&checkFiles); @@ -113,6 +120,9 @@ argParse.addOption(["-c"], "what-to-do", Opt.Action.StoreConst, "compile") .help("Compile to .o or executeable"); + argParse.addOption(["--syntax-only"], + "what-to-do", Opt.Action.StoreConst, "parse") + .help("Only parse the file(s) and output parseing errors."); argParse.addOption( ["-O","--optimize"], { @@ -142,10 +152,12 @@ auto what = options["what-to-do"]; if (what == "" || what == "gen-llvm") - postParse.attach( + postSema.attach( (Module[] modules, SourceManager sm) { foreach(m ; modules) { + if (!m.outputModule) + continue; StopWatch w; w.start; auto llvmGen = new CodeGen(); auto file = new FileConduit(m.moduleName~".bc", FileConduit.WriteCreate); @@ -154,14 +166,16 @@ } }); else if (what == "compile") - postParse.attach( + postSema.attach( (Module[] modules, SourceManager sm) { foreach(m ; modules) { + if (!m.outputModule) + continue; StopWatch w; w.start; auto llvmGen = new CodeGen(); auto llc = new Process("llc","-o=-"); - auto gcc = new Process("gcc","-c","-o","out.o","-x","assembler","-"); + auto gcc = new Process("gcc","-c","-o",m.moduleName~".o","-x","assembler","-"); llc.execute(); int i = dup(llc.stdin.fileHandle); llc.stdin.detach; @@ -175,8 +189,17 @@ } }); + else if (what == "parse") + preParse.attach( + (Lexer lexer) { + auto parser = new Parser(messages); + auto action = new NullAction(); + parser.parse(src_mgr, lexer, action); + messages.checkErrors(ExitLevel.Parser); + exit(0); + }); else if (what == "dot") - postParse.attach( + postSema.attach( (Module[] m, SourceManager sm) { StopWatch w; w.start; // auto print = new DotPrinter(); @@ -184,12 +207,13 @@ timings ~= Measurement("Generating dot output", w.stop); }); else if (what == "code") - postParse.attach( + postSema.attach( (Module[] modules, SourceManager sm) { StopWatch w; w.start; auto print = new AstPrinter(sm); foreach ( m ; modules ) - print.print(m); + if (m.outputModule) + print.print(m); timings ~= Measurement("Converting AST to text", w.stop); }); StopWatch total; @@ -242,6 +266,44 @@ } (new LiteralInterpreter(messages)).visit(modules); + messages.checkErrors; + postParse(modules, src_mgr); + + class ModuleLoader : Visitor!(void) + { + Module[] visit(Module[] modules, MessageHandler messages, SourceManager src_mgr) + { + this.modules = modules; + this.messages = messages; + this.src_mgr = src_mgr; + super.visit(modules); + return this.modules; + } + + override void visitImportDecl(ImportDecl decl) + { + char[] path = replace!(char)(decl.get,'.','/')~".d"; + + auto start = src_mgr.addFile(path); + auto lexer = new Lexer(start, src_mgr, messages); + + auto parser = new Parser(messages); + auto action = new AstAction(src_mgr); + + Module m = cast(Module)parser.parse(src_mgr, lexer, action); + modules ~= m; + m.outputModule = false; + // decl.env.mHandle.add(m); + messages.checkErrors(ExitLevel.Parser); + } + + Module[] modules; + SourceManager src_mgr; + MessageHandler messages; + } + + modules = (new ModuleLoader()).visit(modules, messages, src_mgr); + messages.checkErrors; (new ScopeBuilder).visit(modules); StopWatch watch2; @@ -261,7 +323,7 @@ decl.simplify(); timings ~= Measurement("Total", total.stop); - postParse(modules, src_mgr); + postSema(modules, src_mgr); if (options.flag("time")) foreach (m; timings) diff -r 9869194de9b7 -r 2be29b296081 dsss.conf --- a/dsss.conf Wed Jul 09 13:38:11 2008 +0200 +++ b/dsss.conf Fri Jul 11 21:47:57 2008 +0200 @@ -1,7 +1,11 @@ [lexer] +buildflags = -version=Tango [parser] +buildflags = -version=Tango [ast] +buildflags = -version=Tango [gen] +buildflags = -version=Tango [dang/compiler.d] @@ -9,8 +13,12 @@ buildflags = -llstdc++ \ -llLLVMSystem -llLLVMSupport -llLLVMCore -llLLVMBitWriter -llLLVMBitReader -llLLVMAnalysis -llLLVMTarget \ -llLLVMTransformUtils -llLLVMScalarOpts -llLLVMipa -llLLVMipo \ - -llLLVMInstrumentation -llllvm-c-ext -lldl + -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 9869194de9b7 -r 2be29b296081 gen/CodeGen.d --- a/gen/CodeGen.d Wed Jul 09 13:38:11 2008 +0200 +++ b/gen/CodeGen.d Fri Jul 11 21:47:57 2008 +0200 @@ -661,7 +661,7 @@ gep_indices[1] = index.value; Value res; auto target = genLValue(indexExp.target).getAddress(); - if (type.isArray()) + 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"); @@ -889,7 +889,7 @@ type_map[t] = res; return res; } - else if (auto f = t.asArray) + else if (auto f = t.asStaticArray) { Type res = ArrayType.Get(llvm(f.arrayOf), f.size); type_map[t] = res; diff -r 9869194de9b7 -r 2be29b296081 lexer/Keyword.d --- a/lexer/Keyword.d Wed Jul 09 13:38:11 2008 +0200 +++ b/lexer/Keyword.d Fri Jul 11 21:47:57 2008 +0200 @@ -63,7 +63,7 @@ // attributse "public" : Tok.Public, - "private" : Tok.Public, + "private" : Tok.Private, "protected" : Tok.Protected, "package" : Tok.Package, "export" : Tok.Export, diff -r 9869194de9b7 -r 2be29b296081 lexer/Lexer.d --- a/lexer/Lexer.d Wed Jul 09 13:38:11 2008 +0200 +++ b/lexer/Lexer.d Fri Jul 11 21:47:57 2008 +0200 @@ -84,7 +84,7 @@ { case CharType.EOF: SLoc loc; - return Token(Tok.EOF, loc, 0); + return Token(Tok.EOF, loc + 1, 0); case CharType.Whitespace: position += 1; @@ -249,7 +249,7 @@ return this.next; } } - messages.report(UnexpectedEOFBlock,Loc(position)); + messages.report(UnexpectedEOFBlock,Loc(position)).fatal(ExitLevel.Lexer); case '+': position += 2; @@ -274,7 +274,9 @@ if(nesting == 0) return this.next; } - messages.report(UnexpectedEOFBlock,Loc(position)); + messages.report( + UnexpectedEOFBlock, + Loc(position)).fatal(ExitLevel.Lexer); default: return Token(Tok.Slash, Loc(position - 1), 1); diff -r 9869194de9b7 -r 2be29b296081 lexer/Token.d --- a/lexer/Token.d Wed Jul 09 13:38:11 2008 +0200 +++ b/lexer/Token.d Fri Jul 11 21:47:57 2008 +0200 @@ -76,6 +76,14 @@ } /** + 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() @@ -191,7 +199,7 @@ Module, Import, /* Attributes */ - Public, Private, Package, Protected, Export, + Public, Private, Package, Export, Protected, Static, Final, Const, diff -r 9869194de9b7 -r 2be29b296081 parser/Action.d --- a/parser/Action.d Wed Jul 09 13:38:11 2008 +0200 +++ b/parser/Action.d Fri Jul 11 21:47:57 2008 +0200 @@ -52,11 +52,11 @@ Id id; } -class ArrayId : Id +class StaticArrayId : Id { - public static ArrayId opCall(Id id, Object number) + public static StaticArrayId opCall(Id id, Object number) { - auto a = new ArrayId(); + auto a = new StaticArrayId(); a.id = id; a.number = number; return a; @@ -163,7 +163,23 @@ /** Add a struct member to a struct. */ - void actOnStructMember(DeclT st_decl, DeclT m_decl) //ref Id type, ref Id name, ExprT init) + void actOnStructMember(DeclT st_decl, DeclT m_decl) + { + return null; + } + + /** + Add a class member to a struct. + */ + void actOnClassMember(DeclT st_decl, DeclT m_decl) + { + return null; + } + + /** + Add a class member to a struct. + */ + void actOnClassBaseClass(DeclT st_decl, ref Id name) { return null; } @@ -182,7 +198,7 @@ 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) + DeclT actOnStartOfFunctionDef(ref Id type, ref Id name, Attribute att) { return null; } diff -r 9869194de9b7 -r 2be29b296081 parser/Parser.d --- a/parser/Parser.d Wed Jul 09 13:38:11 2008 +0200 +++ b/parser/Parser.d Fri Jul 11 21:47:57 2008 +0200 @@ -154,7 +154,7 @@ return action.actOnDeclarator(type, iden, exp, att); } else if (next.type == Tok.OpenParentheses) - return parseFunc(type, iden); + return parseFunc(type, iden, att); else messages.report(UnexpectedTok, next.location).arg(next.getType); return null; @@ -176,6 +176,20 @@ return parseStruct(type, iden, att); } + else if (t.type == Tok.Class) + { + Id type = Id(lexer.next); + Id iden = Id(require(Tok.Identifier)); + + return parseClass(type, iden, att); + } + else if (t.type == Tok.Interface) + { + Id type = Id(lexer.next); + Id iden = Id(require(Tok.Identifier)); + + return parseClass(type, iden, att); + } messages.report(UnexpectedTok, t.location) .arg(t.getType) .arg(Tok.Identifier) @@ -263,6 +277,100 @@ } /** + Parse interface + */ + Decl parseInterface(Id type, Id iden, Attribute att) + { + auto decl = action.actOnDeclarator(type, iden, null, att); + + if (lexer.peek.type == Tok.Colon) + // SuperInterfaces + { + lexer.next; // Remove colon. + + Token identifier; + + // The identifier + identifier = require(Tok.Identifier); + + // FIXME: Register Interface here + + // We should now have an optional list of items, each starting ',' + while (lexer.peek.type == Tok.Comma) + { + lexer.next; // Remove comma + + // The identifier + identifier = require(Tok.Identifier); + + // FIXME: Register Interface here + } + } + + require(Tok.OpenBrace); + + Attribute a; + while(lexer.peek.isBasicType || lexer.peek.isIdentifier || lexer.peek.isAttribute) + { + auto m_decl = parseDecl(&a); + action.actOnStructMember(decl, m_decl); + } + + require(Tok.CloseBrace); + + return decl; + } + + /** + Parse class + */ + Decl parseClass(Id type, Id iden, Attribute att) + { + auto decl = action.actOnDeclarator(type, iden, null, att); + + if (lexer.peek.type == Tok.Colon) + // BaseClassList - Super class and interfaces(in that order) + { + lexer.next; // Remove colon. + + Token protection, identifier; + + // First we expect an optional protection level. + if (lexer.peek.isBaseClassProtection) + protection = lexer.next; + // Then the identifier + identifier = require(Tok.Identifier); + + // FIXME: Register Interface here + + // We should now have an optional list of items, each starting ',' + while (lexer.peek.type == Tok.Comma) + { + lexer.next; // Remove comma + + // First we expect an optional protection level. + if (lexer.peek.isBaseClassProtection) + protection = lexer.next; + // Then the identifier + identifier = require(Tok.Identifier); + } + } + + require(Tok.OpenBrace); + + Attribute a; + while(lexer.peek.isBasicType || lexer.peek.isIdentifier || lexer.peek.isAttribute) + { + auto m_decl = parseDecl(&a); + action.actOnStructMember(decl, m_decl); // FIXME: Should call actOnClassMember + } + + require(Tok.CloseBrace); + + return decl; + } + + /** Parse struct */ Decl parseStruct(Id type, Id iden, Attribute att) @@ -417,9 +525,9 @@ /** Parses a function/method given the already parsed return type and name */ - Decl parseFunc(ref Id type, ref Id name) + Decl parseFunc(ref Id type, ref Id name, Attribute att) { - Decl func = action.actOnStartOfFunctionDef(type, name); + Decl func = action.actOnStartOfFunctionDef(type, name, att); parseFuncArgs(func); if(lexer.peek.type == Tok.Seperator) @@ -543,7 +651,10 @@ { lexer.next; if(lexer.peek.type == Tok.Integer) - currentType = ArrayId(currentType, action.actOnNumericConstant(require(Tok.Integer))); + currentType = StaticArrayId( + currentType, + action.actOnNumericConstant( + require(Tok.Integer))); require(Tok.CloseBracket); } diff -r 9869194de9b7 -r 2be29b296081 sema/AstAction.d --- a/sema/AstAction.d Wed Jul 09 13:38:11 2008 +0200 +++ b/sema/AstAction.d Fri Jul 11 21:47:57 2008 +0200 @@ -31,8 +31,8 @@ { if(auto t = cast(PointerId)type) return new PointerIdentifier(handleType(t.id)); - if(auto t = cast(ArrayId)type) - return new ArrayIdentifier(handleType(t.id), cast(IntegerLit)t.number); + if(auto t = cast(StaticArrayId)type) + return new StaticArrayIdentifier(handleType(t.id), cast(IntegerLit)t.number); else return identifierFromTok(type.tok); } @@ -108,9 +108,11 @@ return new MemberReference(op, exp, id); } - override DeclT actOnStartOfFunctionDef(ref Id type, ref Id name) + override DeclT actOnStartOfFunctionDef(ref Id type, ref Id name, Attribute att) { - return new FuncDecl(identifierFromTok(type.tok), identifierFromTok(name.tok)); + auto res = new FuncDecl(identifierFromTok(type.tok), identifierFromTok(name.tok)); + res.att = att; + return res; } override void addFuncArg(DeclT func, Id type, Id name) diff -r 9869194de9b7 -r 2be29b296081 sema/DType.d --- a/sema/DType.d Wed Jul 09 13:38:11 2008 +0200 +++ b/sema/DType.d Fri Jul 11 21:47:57 2008 +0200 @@ -31,6 +31,11 @@ /// Return a DStruct if this is one, otherwise return null DStruct asStruct() { 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 @@ -129,14 +134,23 @@ /** Get a type representing a static array of this type with length 'size' */ - DArray getAsArray(int size) + DStaticArray getAsStaticArray(int size) { - if(size in myArray) - return myArray[size]; - myArray[size] = new DArray(this, size); - return myArray[size]; + if(size in myStaticArray) + return myStaticArray[size]; + myStaticArray[size] = new DStaticArray(this, size); + return myStaticArray[size]; } - private DArray[int] myArray; + private DStaticArray[int] myStaticArray; + + DArray getAsArray() + { + if(myArray !is null) + return myArray; + myArray = new DArray(this); + return myArray; + } + private DArray myArray; static DInteger Bool, @@ -335,7 +349,7 @@ } } -class DArray : DType +class DStaticArray : DType { this(DType arrayOf, int size, DType actual = null) { @@ -344,8 +358,8 @@ this.size = size; } - override bool isArray() { return true; } - override DArray asArray() { return this; } + override bool isStaticArray() { return true; } + override DStaticArray asStaticArray() { return this; } int byteSize() { return arrayOf.byteSize * size; } @@ -358,6 +372,27 @@ 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 char[] mangle() + { + return "G"~arrayOf.mangle; // FIXME: Need correct mangling + } + + DType arrayOf; +} + class DPointer : DType { this(DType pointerOf, DType actual = null) @@ -389,6 +424,11 @@ override bool isFunction() { return true; } override DFunction asFunction() { return this; } + override bool hasImplicitConversionTo(DType that) + { + return returnType.hasImplicitConversionTo(that); + } + override char[] mangle() { char[] res; diff -r 9869194de9b7 -r 2be29b296081 sema/ScopeBuilder.d --- a/sema/ScopeBuilder.d Wed Jul 09 13:38:11 2008 +0200 +++ b/sema/ScopeBuilder.d Fri Jul 11 21:47:57 2008 +0200 @@ -40,7 +40,10 @@ inFunctionBodyStack.pop(); - d.sym = current.symbol.createMember(d.identifier.get, d.type); + d.sym = current.symbol.createMember( + d.identifier.get, + d.type, + d.env.find(d.identifier)); } override void visitVarDecl(VarDecl d) @@ -52,7 +55,11 @@ visitExp(d.init); DType t = typeOf(d.varType, d.env); - d.sym = current.symbol.createAlias(d.identifier.get,d.env.find(d.varType).sym); + d.sym = current.symbol.createAlias( + d.identifier.get, + d.env.find(d.varType).sym, + d.env.find(d.identifier)); + d.sym.type = t; } override void visitStructDecl(StructDecl s) @@ -69,8 +76,8 @@ { if(auto i = cast(PointerIdentifier)id) return (typeOf(i.pointerOf, sc)).getPointerTo(); - else if(auto i = cast(ArrayIdentifier)id) - return typeOf(i.arrayOf, sc).getAsArray(i.size); + else if(auto i = cast(StaticArrayIdentifier)id) + return typeOf(i.arrayOf, sc).getAsStaticArray(i.size); return sc.findType(id); } @@ -94,7 +101,10 @@ override void visitStructDecl(StructDecl s) { auto st = s.env.findType(s.identifier).asStruct; - s.sym = current.symbol.createMember(s.identifier.get, st); + s.sym = current.symbol.createMember( + s.identifier.get, + st, + s.env.find(s.identifier)); foreach (decl; s.decls) { @@ -118,8 +128,8 @@ { if(auto i = cast(PointerIdentifier)id) return (typeOf(i.pointerOf, sc)).getPointerTo(); - else if(auto i = cast(ArrayIdentifier)id) - return typeOf(i.arrayOf, sc).getAsArray(i.size); + else if(auto i = cast(StaticArrayIdentifier)id) + return typeOf(i.arrayOf, sc).getAsStaticArray(i.size); return sc.findType(id); } @@ -157,10 +167,11 @@ private void registerBasicTypeTo(char[] n, DType t, Scope sc, Module m) { sc.types[n] = t; - auto sym = m.symbol.createMember(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, decl); @@ -228,11 +239,11 @@ override void visitFuncDecl(FuncDecl d) { current().put(d.identifier, d); + d.env = current(); auto sc = push(); visitExp(d.returnType); visitExp(d.identifier); - d.env = current(); sc.parentFunction = d; foreach (arg; d.funcArgs) visitDecl(arg); @@ -271,6 +282,7 @@ sc.types[s.identifier.get] = type; sc = push(); + Stdout(sc).newline; super.visitStructDecl(s); pop(sc); } diff -r 9869194de9b7 -r 2be29b296081 sema/ScopeCheck.d --- a/sema/ScopeCheck.d Wed Jul 09 13:38:11 2008 +0200 +++ b/sema/ScopeCheck.d Fri Jul 11 21:47:57 2008 +0200 @@ -2,9 +2,11 @@ import sema.Visitor, sema.Symbol, + sema.Scope, sema.DType; -import basic.Message; +import basic.Message, + basic.Attribute; import tango.io.Stdout; @@ -31,6 +33,18 @@ 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) !is null) + if (d.env.parentFunction !is null) + while( d.env.parentFunction.env !is env) + { + if (d.env.enclosing.find(d.identifier).env == env) + messages.report(CannotRedeclare, d.identifier.loc) + .arg(d.identifier.get); + env = env.enclosing; + } + visitExp(d.identifier); if (d.init) visitExp(d.init); @@ -40,8 +54,10 @@ { visitExp(f.identifier); + inFunction = true; foreach (stmt; f.statements) visitStmt(stmt); + inFunction = false; } override void visitImportDecl(ImportDecl) { } @@ -71,6 +87,8 @@ .arg(st.type.name) .arg(target.get) .arg(child.get); + else + internalCheckProtection(res, child); return res; case ExpType.MemberReference: @@ -86,11 +104,57 @@ .arg(s.type.name) .arg(s.getFQN) .arg(child.get); + else + internalCheckProtection(res, child); return res; } } + override void visitExp(Exp exp) + { + if (exp.expType == ExpType.Identifier && inFunction + && exp.env.find(cast(Identifier)exp) !is null) + { + if (exp.env.findType(cast(Identifier)exp) is null) + internalCheckProtection( + exp.env.find(cast(Identifier)exp).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); @@ -98,5 +162,6 @@ int[char[]] types; MessageHandler messages; + bool inFunction; } diff -r 9869194de9b7 -r 2be29b296081 sema/Symbol.d --- a/sema/Symbol.d Wed Jul 09 13:38:11 2008 +0200 +++ b/sema/Symbol.d Fri Jul 11 21:47:57 2008 +0200 @@ -5,6 +5,8 @@ import sema.DType; +import ast.Decl; + /// class Symbol { @@ -49,6 +51,14 @@ return null; } + /** + Get the members of the symbol + **/ + Symbol[] getMembers() + { + return actual.contained; + } + void dump() { Stdout("Symbol: "); @@ -61,9 +71,10 @@ } /// Create a member with the given name and type - Symbol createMember(char[] member, DType type) + Symbol createMember(char[] member, DType type, Decl decl) { auto res = new Symbol(member, type, this); + res.decl = decl; actual.contained ~= res; return res; } @@ -73,15 +84,23 @@ The target symbol can be a member of another symbol **/ - Symbol createAlias(char[] aliasedName, Symbol target) + 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; private: // Helper for getMangledFQN - gets the FQN without _D and the type @@ -114,11 +133,6 @@ private: char[] name; - // 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; // All the symbols contained within this symbol Symbol[] contained; diff -r 9869194de9b7 -r 2be29b296081 sema/Visitor.d --- a/sema/Visitor.d Wed Jul 09 13:38:11 2008 +0200 +++ b/sema/Visitor.d Fri Jul 11 21:47:57 2008 +0200 @@ -95,8 +95,8 @@ return visitIdentifier(cast(Identifier)exp); case ExpType.PointerIdentifier: return visitPointerIdentifier(cast(PointerIdentifier)exp); - case ExpType.ArrayIdentifier: - return visitArrayIdentifier(cast(ArrayIdentifier)exp); + case ExpType.StaticArrayIdentifier: + return visitStaticArrayIdentifier(cast(StaticArrayIdentifier)exp); case ExpType.StringExp: return visitStringExp(cast(StringExp)exp); case ExpType.Index: @@ -342,7 +342,7 @@ return ExpT.init; } - ExpT visitArrayIdentifier(ArrayIdentifier exp) + ExpT visitStaticArrayIdentifier(StaticArrayIdentifier exp) { visitExp(exp.arrayOf); diff -r 9869194de9b7 -r 2be29b296081 tests/parser/class_1.d --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tests/parser/class_1.d Fri Jul 11 21:47:57 2008 +0200 @@ -0,0 +1,5 @@ + +class A +{ + int af; +} diff -r 9869194de9b7 -r 2be29b296081 tests/parser/class_2.d --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tests/parser/class_2.d Fri Jul 11 21:47:57 2008 +0200 @@ -0,0 +1,15 @@ + +class A +{ + int a; +} + +class B +{ + int b; +} + +class C : A, B +{ + int c; +} diff -r 9869194de9b7 -r 2be29b296081 tests/parser/interface_1.d --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tests/parser/interface_1.d Fri Jul 11 21:47:57 2008 +0200 @@ -0,0 +1,7 @@ +interface A +{ +} + +interface B : A +{ +} diff -r 9869194de9b7 -r 2be29b296081 tests/sema/public_1.d --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tests/sema/public_1.d Fri Jul 11 21:47:57 2008 +0200 @@ -0,0 +1,27 @@ +//fail + +public struct A +{ +//static: + public void foo() + { + bar(); + } + + private void bar() + { + } + final int i; +} + +private void bar() +{ +} + +void main() +{ + A a; + a.foo(); + a.bar(); + bar(); +} diff -r 9869194de9b7 -r 2be29b296081 tests/sema/scope_1.d --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tests/sema/scope_1.d Fri Jul 11 21:47:57 2008 +0200 @@ -0,0 +1,7 @@ +//fail + +void main() +{ + int x; + int x; +} diff -r 9869194de9b7 -r 2be29b296081 tests/sema/scope_2.d --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tests/sema/scope_2.d Fri Jul 11 21:47:57 2008 +0200 @@ -0,0 +1,6 @@ +//fail + +void main() +{ + x = 5; +}