private void CompileSuperCall(ByteCodeGenerator generator, PrimaryNode.TermConstructorCallExpression call)
        {
            var target = call.IsSuper
                ? (PrimaryNode)new PrimaryNode.TermSuperExpression()
                : (PrimaryNode)new PrimaryNode.TermThisExpression();

            new PrimaryCompiler(
                    new PrimaryNode.TermFieldExpression
                    {
                        Child = target,
                        SecondChild = new PrimaryNode.TermMethodExpression { Identifier = "<init>", Arguments = call.Arguments }
                    }
            ).Compile(generator);
        }
 public PrimaryCompiler(PrimaryNode node)
 {
     this.node = node;
 }
        private static Item TryInstance(ByteCodeGenerator generator, Type type, PrimaryNode.TermIdentifierExpression id)
        {
            if (type is Array)
            {
                if (id.Identifier == "length")
                {
                    generator.Emit(OpCodeValue.arraylength);
                    return new StackItem(generator, PrimativeTypes.Int);
                }
            }

            var definedType = type as DefinedType;
            if (definedType == null) return null;

            // try instance
            Field field = definedType.Fields.FirstOrDefault(x => x.Name == id.Identifier);
            if (field == null)
            {
                if (type is Class && ((Class)type).Super != null)
                {
                    definedType.Resolve(generator.Manager.Imports);

                    return TryInstance(generator, ((Class)type).Super, id);
                }

                return null;
            }

            bool nonVirtual = field.Modifiers.HasFlag(Modifier.Private);
            bool isStatic = field.Modifiers.HasFlag(Modifier.Static);

            return isStatic
                       ? new StaticItem(generator, field)
                       : (Item)new MemberItem(generator, field, nonVirtual);
        }
        private static LocalItem TryLocal(ByteCodeGenerator generator, PrimaryNode.TermIdentifierExpression id)
        {
            Variable localVariable = generator.GetVariable(id.Identifier);

            return localVariable != null ? new LocalItem(generator, localVariable) : null;
        }
        private static ClassItem TryClass(ByteCodeGenerator generator, PrimaryNode.TermIdentifierExpression id)
        {
            var c = ClassLocator.Find(id.Identifier, generator.Manager.Imports);

            return c == null ? null : new ClassItem(generator, c);
        }
        private static Item CompileMethod(ByteCodeGenerator generator, DefinedType parentType, PrimaryNode.TermMethodExpression id)
        {
            generator.Kill();
            var args = id.Arguments.Select(parameter => new TranslationCompiler(parameter).Compile(generator).Type).ToList();
            generator.Revive();

            var method = parentType.FindMethod(generator, id.Identifier, args);
            if (method == null) throw new InvalidOperationException();

            foreach (var arg in method.Parameters.Zip(id.Arguments, (dst, src) => new { dst, src }))
            {
                new TranslationCompiler(arg.src, arg.dst.Type).Compile(generator).Load();
            }

            var isSuper = false;
            if (generator.Method.DeclaringType is Class)
            {
                isSuper = parentType == ((Class)generator.Method.DeclaringType).Super;
            }

            var item = method.Modifiers.HasFlag(Modifier.Static)
               ? (Item)new StaticItem(generator, method)
               : new MemberItem(generator, method, method.Name == "<init>" || isSuper);

            return item.Invoke();
        }
        private static Item CompileIdentifier(ByteCodeGenerator generator, Item scope, PrimaryNode.TermIdentifierExpression id)
        {
            if (scope == null)
            {
                // try local, instance, static, super, etc...

                Item item = TryLocal(generator, id);
                if (item != null) return item;

                item = TryInstance(generator, generator.Method.DeclaringType, id);
                if (item != null)
                {
                    if (item is MemberItem)
                    {
                        new SelfItem(generator, generator.Method.DeclaringType, false).Load();
                    }

                    return item;
                }

                item = TryClass(generator, id);
                if (item != null) return item;
            }
            else if (scope is SelfItem)
            {
                var self = scope as SelfItem;

                if (self.IsSuper)
                {
                    // try super
                }
                else
                {
                    Item item = TryInstance(generator, generator.Method.DeclaringType, id);
                    if (item != null) return item;
                }
            }
            else if (scope is ClassItem)
            {
                var c = scope as ClassItem;

                Item item = TryInstance(generator, c.Type, id);
                if (item != null) return item;
            }
            else if (scope is LocalItem)
            {
                var c = scope as LocalItem;

                var item = TryInstance(generator, c.Type, id);
                if (item != null) return item;
            }

            throw new NotImplementedException();
        }
        private static Item CompileField(ByteCodeGenerator generator, Item scope, PrimaryNode.TermFieldExpression field)
        {
            var item = new PrimaryCompiler(field.Child).Compile(generator, scope);

            item.Load();
            return new PrimaryCompiler(field.SecondChild).Compile(generator, item);
        }
        private static Item CompileArray(ByteCodeGenerator generator, Item scope, PrimaryNode.TermArrayExpression array)
        {
            var item = new PrimaryCompiler(array.Child).Compile(generator, scope);
            item.Load();

            new ExpressionCompiler(array.Index).Compile(generator).Load();

            var result = item.Type as Array;

            return new IndexedItem(generator, result.ArrayType);
        }