protected override Void handleIf(IfStatementNode ifStatement, Void source)
        {
            var condition = ifStatement.Condition;

            this.ExpressionValidator.handleExpression(condition, context.TypeSystem.BooleanType, true);
            ValidationHelper.setBoxing(context, context.TypeSystem.BooleanType, condition);
            var cinfo = condition.getUserData(typeof(ExpressionInfo));

            if (cinfo == null || ValidationHelper.getType(context, condition) != context.TypeSystem.BooleanType)
            {
                throw context.error(CompileErrorId.NoImplicitConversion, condition,
                                    BytecodeHelper.getDisplayName(cinfo == null ? null : cinfo.Type),
                                    BytecodeHelper.getDisplayName(context.TypeSystem.BooleanType));
            }
            try {
                context.MemberResolver.enterScope();
                handleStatement(ifStatement.IfTrue, null);
            } finally {
                context.MemberResolver.leaveScope();
            }
            if (ifStatement.IfFalse != null)
            {
                try {
                    context.MemberResolver.enterScope();
                    handleStatement(ifStatement.IfFalse, null);
                } finally {
                    context.MemberResolver.leaveScope();
                }
            }
            return(null);
        }
        protected override Void handleYield(YieldStatementNode yieldStatement, Void source)
        {
            var returnType = context.CodeValidationContext.CurrentMethod.ReturnType;
            var value      = yieldStatement.Value;

            if (returnType == null)
            {
                if (value != null)
                {
                    this.ExpressionValidator.handleExpression(value, returnType, true);
                }
            }
            else
            {
                var elementType = BytecodeHelper.getIterableOrIteratorElementType(returnType);
                if (elementType == null)
                {
                    throw context.error(CompileErrorId.YieldOutsideIterator, yieldStatement);
                }
                if (value != null)
                {
                    this.ExpressionValidator.handleExpression(value, elementType, true);
                    ValidationHelper.setBoxing(context, elementType, value);
                    if (!ValidationHelper.isAssignable(context, elementType, value))
                    {
                        throw context.error(CompileErrorId.NoImplicitConversion, value,
                                            BytecodeHelper.getDisplayName(ValidationHelper.getType(context, value)),
                                            BytecodeHelper.getDisplayName(elementType));
                    }
                }
            }
            if (context.Iterables[context.CodeValidationContext.CurrentMethod] == null)
            {
                var prefix      = "_" + context.CodeValidationContext.CurrentMethod.Name + "_Iterable";
                int n           = context.CurrentType.NestedTypes.count(p => p.Name.startsWith(prefix));
                var typeBuilder = ((TypeBuilder)context.CurrentType).defineNestedType(prefix + n);
                typeBuilder.setSourceFile(PathHelper.getFileName(yieldStatement.Filename));
                typeBuilder.setSynthetic(true);
                typeBuilder.setSuper(true);
                context.Iterables[context.CodeValidationContext.CurrentMethod] = typeBuilder;
                context.TypeBuilders.add(typeBuilder);
                typeBuilder.setBaseType(context.TypeSystem.ObjectType);
            }
            return(null);
        }
        protected override Void handleReturn(ReturnStatementNode returnStatement, Void source)
        {
            var returnType = context.CodeValidationContext.CurrentMethod.ReturnType;

            if (returnType == null)
            {
                if (returnStatement.Value != null)
                {
                    this.ExpressionValidator.handleExpression(returnStatement.Value, null, true);
                    var rinfo = returnStatement.Value.getUserData(typeof(ExpressionInfo));
                    if (rinfo == null)
                    {
                        context.CodeValidationContext.LambdaReturnTypes.add(null);
                    }
                    else
                    {
                        context.CodeValidationContext.LambdaReturnTypes.add(ValidationHelper.getType(context, returnStatement.Value));
                    }
                }
            }
            else if (returnType == context.TypeSystem.VoidType)
            {
                if (returnStatement.Value != null)
                {
                    context.addError(CompileErrorId.ReturnVoid, returnStatement);
                }
            }
            else if (returnStatement.Value == null)
            {
                context.addError(CompileErrorId.ReturnNotVoid, returnStatement);
            }
            else
            {
                this.ExpressionValidator.handleExpression(returnStatement.Value, returnType, true);
                ValidationHelper.setBoxing(context, returnType, returnStatement.Value);
                if (!ValidationHelper.isAssignable(context, returnType, returnStatement.Value))
                {
                    var vinfo = returnStatement.Value.getUserData(typeof(ExpressionInfo));
                    context.addError(CompileErrorId.NoImplicitConversion, returnStatement.Value,
                                     BytecodeHelper.getDisplayName((vinfo == null) ? null : vinfo.Type),
                                     BytecodeHelper.getDisplayName(returnType));
                }
            }
            return(null);
        }
 protected override Void handleForeach(ForeachStatementNode foreachStatement, Void src)
 {
     try {
         context.MemberResolver.enterScope();
         var source = foreachStatement.Source;
         this.ExpressionValidator.handleExpression(source, null, true);
         var sinfo = source.getUserData(typeof(ExpressionInfo));
         if (sinfo == null)
         {
             throw context.error(CompileErrorId.NoImplicitConversion, source,
                                 "<null>", BytecodeHelper.getDisplayName(context.TypeSystem.getType("java/lang/Iterable")));
         }
         var      sourceType = ValidationHelper.getType(context, source);
         TypeInfo elementType;
         if (sourceType.IsArray)
         {
             elementType = sourceType.ElementType;
         }
         else
         {
             var iterableType = BytecodeHelper.getImplementedIterable(sourceType);
             if (iterableType == null)
             {
                 throw context.error(CompileErrorId.NoImplicitConversion, source,
                                     BytecodeHelper.getDisplayName(sourceType),
                                     BytecodeHelper.getDisplayName(context.TypeSystem.getType("java/lang/Iterable")));
             }
             foreachStatement.addOrReplaceUserData(iterableType);
             elementType = BytecodeHelper.getIterableOrIteratorElementType(iterableType);
         }
         var localName = context.getIdentifier(foreachStatement.NameOffset, foreachStatement.NameLength);
         if (context.MemberResolver.hasLocal(localName))
         {
             context.addError(CompileErrorId.VariableRedefinition, foreachStatement, localName);
         }
         var local = context.MemberResolver.defineLocal(localName,
                                                        ValidationHelper.getVariableType(context, elementType), context.CodeValidationContext.CurrentMethod);
         foreachStatement.addOrReplaceUserData(local);
         handleStatement(foreachStatement.Statement, null);
     } finally {
         context.MemberResolver.leaveScope();
     }
     return(null);
 }
 protected override Void handleUsing(UsingStatementNode usingStatement, Void source)
 {
     try {
         context.MemberResolver.enterScope();
         var resource = usingStatement.ResourceAcquisition;
         handleStatement(resource, null);
         if (resource.StatementKind == StatementKind.Expression)
         {
             var expr  = ((ExpressionStatementNode)resource).Expression;
             var einfo = expr.getUserData(typeof(ExpressionInfo));
             if (einfo == null ||
                 BytecodeHelper.getDisposeMethod(context.AnnotatedTypeSystem, ValidationHelper.getType(context, expr)) == null)
             {
                 context.addError(CompileErrorId.NoDisposeMethod, expr,
                                  BytecodeHelper.getDisplayName(einfo == null ? null : einfo.Type));
             }
         }
         else
         {
             foreach (var decl in ((LocalDeclarationStatementNode)resource).Declarators)
             {
                 if (decl.Value == null)
                 {
                     context.addError(CompileErrorId.UsingVariableUninitialized, decl);
                 }
                 else
                 {
                     var vinfo = decl.Value.getUserData(typeof(ExpressionInfo));
                     if (vinfo == null || BytecodeHelper.getDisposeMethod(context.AnnotatedTypeSystem,
                                                                          ValidationHelper.getType(context, decl.Value)) == null)
                     {
                         context.addError(CompileErrorId.NoDisposeMethod, decl.Value,
                                          BytecodeHelper.getDisplayName(vinfo == null ? null : vinfo.Type));
                     }
                 }
             }
         }
         handleStatement(usingStatement.Statement, null);
     } finally {
         context.MemberResolver.leaveScope();
     }
     return(null);
 }
        protected override Void handleThrow(ThrowStatementNode throwStatement, Void source)
        {
            var exception = throwStatement.Exception;

            if (exception != null)
            {
                this.ExpressionValidator.handleExpression(exception, null, true);
                var einfo = exception.getUserData(typeof(ExpressionInfo));
                if (einfo != null)
                {
                    if (!context.TypeSystem.getType("java/lang/Throwable").isAssignableFrom(ValidationHelper.getType(context, exception)))
                    {
                        throw context.error(CompileErrorId.NoImplicitConversion, exception,
                                            BytecodeHelper.getDisplayName(einfo.Type), "java.lang.Throwable");
                    }
                }
            }
            return(null);
        }
 protected override Void handleTry(TryStatementNode tryStatement, Void source)
 {
     handleStatement(tryStatement.Block, source);
     foreach (var node in tryStatement.CatchClauses)
     {
         try {
             context.MemberResolver.enterScope();
             if (node.ExceptionType != null)
             {
                 var etype = CompilerHelper.resolveTypeReference(context, context.CurrentType.PackageName, node.ExceptionType);
                 node.addOrReplaceUserData(etype);
                 if (etype.IsGenericParameter)
                 {
                     throw context.error(CompileErrorId.GenericParameterInCatch, node.ExceptionType,
                                         BytecodeHelper.getDisplayName(etype));
                 }
                 if (!context.TypeSystem.getType("java/lang/Throwable").isAssignableFrom(etype))
                 {
                     throw context.error(CompileErrorId.NoImplicitConversion, node.ExceptionType,
                                         BytecodeHelper.getDisplayName(etype), "java.lang.Throwable");
                 }
                 if (node.NameLength > 0)
                 {
                     var local = context.MemberResolver.defineLocal(context.getIdentifier(node.NameOffset, node.NameLength),
                                                                    etype, context.CodeValidationContext.CurrentMethod);
                     node.addOrReplaceUserData(local);
                 }
             }
             foreach (var s in node.Block.Statements)
             {
                 handleStatement(s, source);
             }
         } finally {
             context.MemberResolver.leaveScope();
         }
     }
     if (tryStatement.Finally != null)
     {
         handleStatement(tryStatement.Finally, source);
     }
     return(null);
 }
 protected override Void handleFor(ForStatementNode forStatement, Void source)
 {
     try {
         context.MemberResolver.enterScope();
         foreach (var s in forStatement.Initializer)
         {
             handleStatement(s, null);
         }
         var condition = forStatement.Condition;
         if (condition != null)
         {
             this.ExpressionValidator.handleExpression(condition, null, true);
             ValidationHelper.setBoxing(context, context.TypeSystem.BooleanType, condition);
             var info = condition.getUserData(typeof(ExpressionInfo));
             if (info == null || ValidationHelper.getType(context, condition) != context.TypeSystem.BooleanType)
             {
                 throw context.error(CompileErrorId.NoImplicitConversion, condition,
                                     BytecodeHelper.getDisplayName(info == null ? null : info.Type),
                                     BytecodeHelper.getDisplayName(context.TypeSystem.BooleanType));
             }
         }
         try {
             context.MemberResolver.enterScope();
             handleStatement(forStatement.Statement, source);
         } finally {
             context.MemberResolver.leaveScope();
         }
         foreach (var s in forStatement.Iterator)
         {
             handleStatement(s, source);
         }
     } finally {
         context.MemberResolver.leaveScope();
     }
     return(null);
 }
        static TypeInfo getType(CompilerContext context, ExpressionNode expression)
        {
            if (ValidationHelper.isMethod(expression))
            {
                throw context.error(CompileErrorId.UnexpectedMethodReference, expression);
            }
            var info = expression.getUserData(typeof(ExpressionInfo));

            if (info.Type != null)
            {
                return(info.Type);
            }
            else if (info.IsConstant)
            {
                context.ConstantBuilder.buildConstant(expression);
                return(info.Type);
            }
            else if (info.Members != null)
            {
                foreach (var member in info.Members)
                {
                    switch (member.MemberKind)
                    {
                    case Field:
                        var field = member.Field;
                        if (field.Value != null)
                        {
                            info.IsConstant = true;
                            info.Value      = field.Value;
                        }
                        info.Member = member;
                        info.Type   = member.Type;
                        if (!isInDeprecatedContext(context))
                        {
                            if (BytecodeHelper.isDeprecated(context.AnnotatedTypeSystem, field))
                            {
                                context.addWarning(CompileErrorId.DeprecatedField, expression,
                                                   BytecodeHelper.getDisplayName(field.DeclaringType), field.Name);
                            }
                        }
                        if (context.CodeValidationContext.IsInMethod && context.CodeValidationContext.IsInLambda)
                        {
                            if (!member.IsStatic && expression.ExpressionKind == ExpressionKind.SimpleName)
                            {
                                var typeBuilder = context.LambdaScopes[context.CodeValidationContext.RootMethod];
                                if (typeBuilder.getField("this$0") == null)
                                {
                                    typeBuilder.defineField("this$0", context.CurrentType);
                                }
                            }
                        }
                        return(member.Type);

                    case Type:
                        info.Member = member;
                        info.Type   = member.Type;
                        if (!isInDeprecatedContext(context))
                        {
                            if (BytecodeHelper.isDeprecated(context.AnnotatedTypeSystem, info.Type))
                            {
                                context.addWarning(CompileErrorId.DeprecatedType, expression,
                                                   BytecodeHelper.getDisplayName(info.Type));
                            }
                        }
                        return(member.Type);

                    case Indexer:
                    case Property:
                        info.Member = member;
                        info.Type   = member.Type;
                        if (!isInDeprecatedContext(context))
                        {
                            if (member.GetAccessor != null)
                            {
                                if (member.SetAccessor == null)
                                {
                                    if (BytecodeHelper.isDeprecated(context.AnnotatedTypeSystem, member.GetAccessor))
                                    {
                                        context.addWarning(CompileErrorId.DeprecatedProperty, expression,
                                                           BytecodeHelper.getDisplayName(member.DeclaringType), member.Name);
                                    }
                                }
                                else
                                {
                                    if (BytecodeHelper.isDeprecated(context.AnnotatedTypeSystem, member.GetAccessor) &&
                                        BytecodeHelper.isDeprecated(context.AnnotatedTypeSystem, member.SetAccessor))
                                    {
                                        context.addWarning(CompileErrorId.DeprecatedProperty, expression,
                                                           BytecodeHelper.getDisplayName(member.DeclaringType), member.Name);
                                    }
                                }
                            }
                            else if (member.SetAccessor != null)
                            {
                                if (BytecodeHelper.isDeprecated(context.AnnotatedTypeSystem, member.SetAccessor))
                                {
                                    context.addWarning(CompileErrorId.DeprecatedProperty, expression,
                                                       BytecodeHelper.getDisplayName(member.DeclaringType), member.Name);
                                }
                            }
                        }
                        if (context.CodeValidationContext.IsInMethod && context.CodeValidationContext.IsInLambda)
                        {
                            if (!member.IsStatic && expression.ExpressionKind == ExpressionKind.SimpleName)
                            {
                                var typeBuilder = context.LambdaScopes[context.CodeValidationContext.RootMethod];
                                if (typeBuilder.getField("this$0") == null)
                                {
                                    typeBuilder.defineField("this$0", context.CurrentType);
                                }
                            }
                        }
                        return(member.Type);

                    case Local:
                        if (context.CodeValidationContext.IsInMethod)
                        {
                            var currentMethod = context.CodeValidationContext.CurrentMethod;
                            var currentType   = (TypeBuilder)currentMethod.DeclaringType;
                            if (currentType.FullName.indexOf('#') == -1 && context.CodeValidationContext.IsInLambda)
                            {
                                if (currentMethod != member.Method)
                                {
                                    member.IsUsedFromLambda = true;
                                    var typeBuilder = context.LambdaScopes[context.CodeValidationContext.RootMethod];
                                    context.getLocalField(typeBuilder, (LocalMemberInfo)member);
                                }
                            }
                        }
                        info.Member = member;
                        info.Type   = member.Type;
                        return(member.Type);

                    default:
                        break;
                    }
                }
                if (info.ExtensionMethods != null && info.ExtensionMethods.any())
                {
                    return(info.Type = info.ExtensionMethods.first().Parameters.first().Type);
                }
            }
            throw new Exception("Internal error line " + (expression.getLine() + 1));
        }
        protected override Void handleSwitch(SwitchStatementNode switchStatement, Void source)
        {
            this.ExpressionValidator.handleExpression(switchStatement.Selector, null, true);
            var sinfo = switchStatement.Selector.getUserData(typeof(ExpressionInfo));

            if (sinfo == null)
            {
                throw context.error(CompileErrorId.IntegerStringOrEnumExpected, switchStatement.Selector);
            }
            var type = ValidationHelper.getType(context, switchStatement.getSelector());

            if (!type.IsNumeric && !type.IsEnum && type != context.TypeSystem.StringType)
            {
                throw context.error(CompileErrorId.IntegerStringOrEnumExpected, switchStatement.Selector);
            }
            var isString = false;

            switch (type.NumericTypeKind)
            {
            case Long:
            case Float:
            case Double:
                throw context.error(CompileErrorId.IntegerStringOrEnumExpected, switchStatement.Selector);

            default:
                ValidationHelper.setBoxing(context, context.TypeSystem.IntType, switchStatement.getSelector());
                break;

            case None:
                isString = !type.IsEnum;
                break;
            }
            var hasDefault = false;
            HashMap <String, Integer> enumOrdinals = null;
            HashSet <String>          cases        = null;

            if (type.IsEnum)
            {
                enumOrdinals = new HashMap <String, Integer>();
                cases        = new HashSet <String>();
                int i = 0;
                foreach (var f in type.Fields)
                {
                    if (f.IsEnum)
                    {
                        enumOrdinals[f.Name] = Integer.valueOf(i++);
                    }
                }
            }
            try {
                context.MemberResolver.enterScope();
                foreach (var section in switchStatement.Sections)
                {
                    if (section.CaseExpression == null)
                    {
                        if (hasDefault)
                        {
                            throw context.error(CompileErrorId.DuplicateCase, section);
                        }
                        hasDefault = true;
                    }
                    else
                    {
                        if (type.IsEnum)
                        {
                            if (section.CaseExpression.ExpressionKind != ExpressionKind.SimpleName)
                            {
                                throw context.error(CompileErrorId.EnumCaseNotIdentifier, section);
                            }
                            var name = (SimpleNameExpressionNode)section.CaseExpression;
                            var text = context.getIdentifier(name.NameOffset, name.NameLength);
                            if (!cases.add(text))
                            {
                                throw context.error(CompileErrorId.DuplicateCase, section);
                            }
                            if (!enumOrdinals.containsKey(text))
                            {
                                throw context.error(CompileErrorId.UnknownEnumMember, section, text, BytecodeHelper.getDisplayName(type));
                            }
                            name.addOrReplaceUserData(enumOrdinals.get(text));
                        }
                        else
                        {
                            this.ExpressionValidator.handleExpression(section.CaseExpression, type, true);
                            ValidationHelper.getType(context, section.CaseExpression);
                            var cinfo = section.CaseExpression.getUserData(typeof(ExpressionInfo));
                            if (cinfo == null)
                            {
                                if (!isString)
                                {
                                    throw context.error(CompileErrorId.UnexpectedNull, switchStatement);
                                }
                            }
                            else
                            {
                                if (!cinfo.IsConstant)
                                {
                                    throw context.error(CompileErrorId.ConstantValueExpected, section);
                                }
                                if (!type.isAssignableFrom(ValidationHelper.getType(context, section.CaseExpression)))
                                {
                                    context.addError(CompileErrorId.NoImplicitConversion, section.CaseExpression,
                                                     BytecodeHelper.getDisplayName(cinfo.Type),
                                                     BytecodeHelper.getDisplayName(type));
                                }
                            }
                        }
                    }
                    foreach (var s in section.Statements)
                    {
                        handleStatement(s, null);
                    }
                }
            } finally {
                context.MemberResolver.leaveScope();
            }
            return(null);
        }
 protected override Void handleLocalDeclaration(LocalDeclarationStatementNode localDeclaration, Void source)
 {
     if (localDeclaration.Type == null)
     {
         if (localDeclaration.Declarators.size() > 1)
         {
             context.addError(CompileErrorId.MultipleImplicitVariableDeclarators, localDeclaration);
         }
         var decl = localDeclaration.Declarators[0];
         if (decl.Value == null)
         {
             throw context.error(CompileErrorId.MissingImplicitVariableInitializer, localDeclaration);
         }
         if (decl.Value.ExpressionKind == ExpressionKind.ArrayInitializer)
         {
             throw context.error(CompileErrorId.ImplicitVariableWithArrayInitializer, localDeclaration);
         }
         this.ExpressionValidator.handleExpression(decl.Value, null, true);
         var info = decl.Value.getUserData(typeof(ExpressionInfo));
         if (info == null)
         {
             throw context.error(CompileErrorId.NullImplicitVariableInitializer, localDeclaration);
         }
         localDeclaration.addOrReplaceUserData(new ExpressionInfo(ValidationHelper.getType(context, decl.Value)));
         var name = context.getIdentifier(decl.NameOffset, decl.NameLength);
         if (context.MemberResolver.hasLocal(name))
         {
             context.addError(CompileErrorId.VariableRedefinition, decl, name);
         }
         var local = context.MemberResolver.defineLocal(name, ValidationHelper.getVariableType(context, info.Type),
                                                        context.CodeValidationContext.CurrentMethod);
         decl.addOrReplaceUserData(local);
     }
     else
     {
         var type = CompilerHelper.resolveTypeReference(context, context.CurrentType.PackageName, localDeclaration.Type);
         localDeclaration.addOrReplaceUserData(new ExpressionInfo(type));
         foreach (var decl in localDeclaration.Declarators)
         {
             var name = context.getIdentifier(decl.NameOffset, decl.NameLength);
             if (decl.Value != null)
             {
                 var isArrayInit = decl.Value.ExpressionKind == ExpressionKind.ArrayInitializer;
                 if (isArrayInit && !type.IsArray)
                 {
                     throw context.error(CompileErrorId.ArrayTypeExpected, decl);
                 }
                 this.ExpressionValidator.handleExpression(decl.Value, type, true);
                 ValidationHelper.setBoxing(context, type, decl.Value);
                 if (!ValidationHelper.isAssignable(context, type, decl.Value))
                 {
                     var vinfo = decl.Value.getUserData(typeof(ExpressionInfo));
                     var vtype = (vinfo == null) ? null : vinfo.Type;
                     context.addError(CompileErrorId.NoImplicitConversion, decl.Value,
                                      BytecodeHelper.getDisplayName(vtype),
                                      BytecodeHelper.getDisplayName(type));
                 }
                 if (isArrayInit)
                 {
                     ValidationHelper.setArrayInitializerTypes((ArrayInitializerExpressionNode)decl.Value, type);
                 }
             }
             if (context.MemberResolver.hasLocal(name))
             {
                 context.addError(CompileErrorId.VariableRedefinition, decl, name);
             }
             var local = context.MemberResolver.defineLocal(name, ValidationHelper.getVariableType(context, type),
                                                            context.CodeValidationContext.CurrentMethod);
             decl.addOrReplaceUserData(local);
         }
     }
     return(null);
 }