changeset 136:2be29b296081

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
author johnsen@johnsen-laptop
date Fri, 11 Jul 2008 21:47:57 +0200
parents 9869194de9b7
children efbf51d85f4d 927ae00bd9d2
files ast/Decl.d ast/Exp.d ast/Module.d basic/Attribute.d basic/Messages.d dang/compiler.d dsss.conf gen/CodeGen.d lexer/Keyword.d lexer/Lexer.d lexer/Token.d parser/Action.d parser/Parser.d sema/AstAction.d sema/DType.d sema/ScopeBuilder.d sema/ScopeCheck.d sema/Symbol.d sema/Visitor.d tests/parser/class_1.d tests/parser/class_2.d tests/parser/interface_1.d tests/sema/public_1.d tests/sema/scope_1.d tests/sema/scope_2.d
diffstat 25 files changed, 548 insertions(+), 65 deletions(-) [+]
line wrap: on
line diff
--- 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;
--- 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)
--- 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;
 }
 
--- 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;
 
--- 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.")
     ];
 }
 
--- 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)
--- 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
 
--- 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;
--- 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,
--- 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);
--- 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,
--- 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;
     }
--- 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);
                 
             }
--- 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)
--- 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;
--- 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);
     }
--- 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;
 }
 
--- 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;
 
--- 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);
 
--- /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;
+}
--- /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;
+}
--- /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
+{
+}
--- /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();
+}
--- /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;
+}
--- /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;
+}