private void defineClassDestructor(DestructorDeclarationNode destructorDeclaration, TypeBuilder typeBuilder) {
     if (typeBuilder.IsEnum) {
         // TODO: error
     }
     var methodBuilder = (MethodBuilder)typeBuilder.getMethod("finalize", Query.empty<TypeInfo>());
     if (methodBuilder != null) {
         context.addError(CompileErrorId.AlreadyDefinedDestructor, destructorDeclaration,
                 BytecodeHelper.getDisplayName(typeBuilder));
     }
     var name = context.getIdentifier(destructorDeclaration.NameOffset, destructorDeclaration.NameLength);
     if (!name.equals(typeBuilder.Name)) {
         context.addError(CompileErrorId.InvalidDestructorName, destructorDeclaration, name);
     }
     methodBuilder = typeBuilder.defineMethod("finalize");
     methodBuilder.setReturnType(context.TypeSystem.VoidType);
     methodBuilder.setProtected(true);
     destructorDeclaration.addUserData(methodBuilder);
 }
 private void defineInterfaceMethod(MethodDeclarationNode methodDeclaration, TypeBuilder typeBuilder) {
     var packageName = typeBuilder.PackageName;
     var name = context.getIdentifier(methodDeclaration.NameOffset, methodDeclaration.NameLength);
     var methodBuilder = lookupMethod(typeBuilder, methodDeclaration.TypeParameters, methodDeclaration.Parameters, name);
     if (methodBuilder != null) {
         context.addError(CompileErrorId.AlreadyDefinedMethod, methodDeclaration,
                 BytecodeHelper.getDisplayName(typeBuilder), name);
     }
     methodBuilder = typeBuilder.defineMethod(context.getIdentifier(methodDeclaration.NameOffset, methodDeclaration.NameLength));
     methodDeclaration.addUserData(methodBuilder);
     setTypeParameters(methodBuilder, methodDeclaration.TypeParameters, methodDeclaration);
     context.MemberResolver.enterMethod(methodBuilder);
     try {
         methodBuilder.setPublic(true);
         methodBuilder.setAbstract(true);
         methodBuilder.setReturnType(CompilerHelper.resolveTypeReference(context, packageName, methodDeclaration.ReturnType));
         foreach (var p in methodDeclaration.Parameters) {
             var pb = methodBuilder.addParameter(CompilerHelper.resolveTypeReference(context, packageName, p.Type));
             pb.setName(context.getIdentifier(p.NameOffset, p.NameLength));
             if (p.Modifier == ParameterModifier.Params) {
                 methodBuilder.setVarargs(true);
             }
         }
         setMethodConstraints(methodDeclaration.ConstraintsClauses, methodBuilder);
     } finally {
         context.MemberResolver.leaveMethod();
     }
 }
        private void defineClassConstructor(ConstructorDeclarationNode constructorDeclaration, TypeBuilder typeBuilder) {
            var name = context.getIdentifier(constructorDeclaration.NameOffset, constructorDeclaration.NameLength);
            if (!name.equals(typeBuilder.Name)) {
                context.addError(CompileErrorId.MethodWithoutReturnType, constructorDeclaration, name);
            }
            if (constructorDeclaration.Modifiers.contains(Modifier.Static)) {
                // TODO: check that modifiers.size() == 1
                var clinit = (MethodBuilder)typeBuilder.getMethod("<clinit>", Query.empty<TypeInfo>());
                if (clinit != null) {
                    context.addError(CompileErrorId.AlreadyDefinedStaticInitializer, constructorDeclaration,
                        BytecodeHelper.getDisplayName(typeBuilder));
                }
                clinit = typeBuilder.defineMethod("<clinit>");
                clinit.setStatic(true);
                clinit.setReturnType(context.TypeSystem.VoidType);
                constructorDeclaration.addUserData(clinit);
            } else {
				if (typeBuilder.IsEnum) {
					// TODO: check if the contructor is private
				}
                var methodBuilder = lookupMethod(typeBuilder, constructorDeclaration.TypeParameters, constructorDeclaration.Parameters, "<init>");
                if (methodBuilder != null) {
                    context.addError(CompileErrorId.AlreadyDefinedConstructor, constructorDeclaration,
                            BytecodeHelper.getDisplayName(typeBuilder));
                }
                methodBuilder = typeBuilder.defineMethod("<init>");
                methodBuilder.setReturnType(context.TypeSystem.VoidType);
                constructorDeclaration.addUserData(methodBuilder);
                setTypeParameters(methodBuilder, constructorDeclaration.getTypeParameters(), constructorDeclaration);
                context.MemberResolver.enterMethod(methodBuilder);
                try {
                    setConstructorModifiers(constructorDeclaration, methodBuilder);
                    if (typeBuilder.IsEnum) {
                        var pb = methodBuilder.addParameter(context.TypeSystem.StringType);
                        pb.setName("name$0");
                        pb = methodBuilder.addParameter(context.TypeSystem.IntType);
                        pb.setName("ordinal$0");
                    }
                    foreach (var p in constructorDeclaration.Parameters) {
                        var t = CompilerHelper.resolveTypeReference(context, typeBuilder.PackageName, p.Type);
                        var pb = methodBuilder.addParameter(t);
                        pb.setName(context.getIdentifier(p.NameOffset, p.NameLength));
                        if (p.Modifier == ParameterModifier.Params) {
                            methodBuilder.setVarargs(true);
                        }
                    }
                    setMethodConstraints(constructorDeclaration.ConstraintsClauses, methodBuilder);
                } finally {
                    context.MemberResolver.leaveMethod();
                }
            }
        }
 private void defineTypeProperty(PropertyDeclarationNode propertyDeclaration, TypeBuilder typeBuilder) {
     var isInterface = typeBuilder.IsInterface;
     var name = context.getIdentifier(propertyDeclaration.NameOffset, propertyDeclaration.NameLength);
     foreach (var meth in typeBuilder.Methods) {
         foreach (var ann in meth.Annotations) {
             if (BytecodeHelper.isPropertyGet(ann)) {
                 if (BytecodeHelper.getPropertyGetName(meth, ann).equals(name)) {
                     context.addError(CompileErrorId.AlreadyDefinedProperty, propertyDeclaration,
                         BytecodeHelper.getDisplayName(typeBuilder), name);
                 }
             } else if (BytecodeHelper.isPropertySet(ann)) {
                 if (BytecodeHelper.getPropertySetName(meth, ann).equals(name)) {
                     context.addError(CompileErrorId.AlreadyDefinedProperty, propertyDeclaration,
                         BytecodeHelper.getDisplayName(typeBuilder), name);
                 }
             }
         }
     }
     var type = CompilerHelper.resolveTypeReference(context, typeBuilder.PackageName, propertyDeclaration.Type);
     var get = propertyDeclaration.GetAccessor;
     var set = propertyDeclaration.SetAccessor;
     if (!isInterface) {
         checkAccessors(propertyDeclaration.Modifiers, get, set, propertyDeclaration);
     }
     if (get != null) {
         var methodName = "get" + name;
         if (type.IsBoolean) {
             if (name.length() > 2 && name.startsWith("Is") && Character.isUpperCase(name[2])) {
                 methodName = Character.toLowerCase(name[0]) + name.substring(1);
             }
         }
         var methodBuilder = typeBuilder.defineMethod(methodName);
         get.addUserData(methodBuilder);
         if (isInterface) {
             methodBuilder.setAbstract(true);
             methodBuilder.setPublic(true);
         } else {
             setPropertyOrIndexerModifiers(get, propertyDeclaration.getModifiers(), methodBuilder);
         }
         methodBuilder.setReturnType(type);
         methodBuilder.addAnnotation(context.getType("stab/lang/PropertyGet", get), false);
     }
     if (set != null) {
         var methodBuilder = typeBuilder.defineMethod("set" + name);
         set.addUserData(methodBuilder);
         if (isInterface) {
             methodBuilder.setAbstract(true);
             methodBuilder.setPublic(true);
         } else {
             setPropertyOrIndexerModifiers(set, propertyDeclaration.getModifiers(), methodBuilder);
         }
         methodBuilder.setReturnType(context.TypeSystem.VoidType);
         var paramBuilder = methodBuilder.addParameter(type);
         paramBuilder.setName("value");
         methodBuilder.addAnnotation(context.getType("stab/lang/PropertySet", set), false);
     }
 }
 private void defineTypeIndexer(IndexerDeclarationNode indexerDeclaration, TypeBuilder typeBuilder) {
     var isInterface = typeBuilder.IsInterface;
     var type = CompilerHelper.resolveTypeReference(context, typeBuilder.PackageName, indexerDeclaration.Type);
     var get = indexerDeclaration.GetAccessor;
     var set = indexerDeclaration.SetAccessor;
     if (!isInterface) {
         checkAccessors(indexerDeclaration.Modifiers, get, set, indexerDeclaration);
     }
     
     var paramTypes = new TypeInfo[indexerDeclaration.Parameters.size()];
     var paramNames = new String[sizeof(paramTypes)];
     var isVarargs = false;
     int i = 0;
     foreach (var p in indexerDeclaration.Parameters) {
         paramTypes[i] = CompilerHelper.resolveTypeReference(context, typeBuilder.PackageName, p.Type);
         paramNames[i] = context.getIdentifier(p.NameOffset, p.NameLength);
         if (p.Modifier == ParameterModifier.Params) {
             if (i < indexerDeclaration.Parameters.size() - 1) {
                 context.addError(CompileErrorId.ParamsNotLast, p);
             }
             if (!paramTypes[i].IsArray) {
                 context.addError(CompileErrorId.ParamsNotArray, p);
             }
             isVarargs = true;
         }
         i++;
     }
     foreach (var meth in typeBuilder.Methods) {
         foreach (var ann in meth.Annotations) {
             if (BytecodeHelper.isIndexerGet(ann)) {
                 // TODO: check the parameter types for redefinition
             } else if (BytecodeHelper.isIndexerSet(ann)) {
                 // TODO: check the parameter types for redefinition
             }
         }
     }
     if (get != null) {
         var methodBuilder = typeBuilder.defineMethod("getItem");
         methodBuilder.setVarargs(isVarargs);
         get.addUserData(methodBuilder);
         if (isInterface) {
             methodBuilder.setAbstract(true);
             methodBuilder.setPublic(true);
         } else {
             setPropertyOrIndexerModifiers(get, indexerDeclaration.getModifiers(), methodBuilder);
         }
         methodBuilder.setReturnType(type);
         methodBuilder.addAnnotation(context.getType("stab/lang/IndexerGet", get), false);
         for (i = 0; i < sizeof(paramTypes); i++) {
             var paramBuilder = methodBuilder.addParameter(paramTypes[i]);
             paramBuilder.setName(paramNames[i]);
         }
     }
     if (set != null) {
         var methodBuilder = typeBuilder.defineMethod("setItem");
         methodBuilder.setVarargs(isVarargs);
         set.addUserData(methodBuilder);
         if (isInterface) {
             methodBuilder.setAbstract(true);
             methodBuilder.setPublic(true);
         } else {
             setPropertyOrIndexerModifiers(set, indexerDeclaration.getModifiers(), methodBuilder);
         }
         methodBuilder.setReturnType(context.TypeSystem.VoidType);
         for (i = 0; i < sizeof(paramTypes); i++) {
             var paramBuilder = methodBuilder.addParameter(paramTypes[i]);
             paramBuilder.setName(paramNames[i]);
             if (paramNames[i].equals("value")) {
                 throw context.error(CompileErrorId.ValueParameterConflict, set);
             }
         }
         var paramBuilder = methodBuilder.addParameter(type);
         paramBuilder.setName("value");
         methodBuilder.addAnnotation(context.getType("stab/lang/IndexerSet", set), false);
     }
 }
 private void defineClassMethod(MethodDeclarationNode methodDeclaration, bool partial, TypeBuilder typeBuilder) {
     var name = context.getIdentifier(methodDeclaration.NameOffset, methodDeclaration.NameLength);
     if (name.equals("finalize") && methodDeclaration.Parameters.size() == 0) {
         context.addError(CompileErrorId.FinalizeMethodOverride, methodDeclaration);
     }
     if (methodDeclaration.IsPartial) {
         if (!partial) {
             context.addError(CompileErrorId.PartialMethodWithinPartialClass, methodDeclaration);
         }
         if (methodDeclaration.ReturnType != context.TypeSystem.VoidType) {
             context.addError(CompileErrorId.PartialMethodNotVoid, methodDeclaration);
         }
     }
     var methodBuilder = lookupMethod(typeBuilder, methodDeclaration.TypeParameters, methodDeclaration.Parameters, name);
     if (methodBuilder != null) {
         if (!methodDeclaration.IsPartial) {
             context.addError(CompileErrorId.AlreadyDefinedMethod, methodDeclaration, BytecodeHelper.getDisplayName(typeBuilder), name);
             return;
         }
         var partialInfo = partialTypes[typeBuilder.FullName];
         if (!partialInfo.partialMethods.containsKey(methodBuilder)) {
             context.addError(CompileErrorId.AlreadyDefinedMethod, methodDeclaration, BytecodeHelper.getDisplayName(typeBuilder), name);
         }
         var partialMethodInfo = partialInfo.partialMethods[methodBuilder];
         if (methodDeclaration.Body == null) {
             if (partialMethodInfo.definingPart != null) {
                 context.addError(CompileErrorId.MultiplePartialDefiningDeclarations, methodDeclaration);
             }
             partialMethodInfo.definingPart = methodDeclaration;
         } else {
             if (partialMethodInfo.implementingPart != null) {
                 context.addError(CompileErrorId.MultiplePartialImplementingDeclarations, methodDeclaration);
             }
             partialMethodInfo.implementingPart = methodDeclaration;
         }
         setPartialMethodModifiers(methodDeclaration, methodBuilder);
         setMethodConstraints(methodDeclaration.ConstraintsClauses, methodBuilder);
         methodDeclaration.addUserData(methodBuilder);
     } else {
         methodBuilder = typeBuilder.defineMethod(name);
         methodDeclaration.addUserData(methodBuilder);
         setTypeParameters(methodBuilder, methodDeclaration.TypeParameters, methodDeclaration);
         context.MemberResolver.enterMethod(methodBuilder);
         try {
             setMethodModifiers(methodDeclaration, methodBuilder);
             var returnType = CompilerHelper.resolveTypeReference(context, typeBuilder.PackageName, methodDeclaration.ReturnType);
             methodBuilder.setReturnType(returnType);
             var i = 0;
             foreach (var parameter in methodDeclaration.Parameters) {
                 var type = CompilerHelper.resolveTypeReference(context, typeBuilder.PackageName, parameter.Type);
                 var paramBuilder = methodBuilder.addParameter(type);
                 paramBuilder.setName(context.getIdentifier(parameter.NameOffset, parameter.NameLength));
                 if (parameter.Modifier == ParameterModifier.Params) {
                     if (i < methodDeclaration.Parameters.size() - 1) {
                         context.addError(CompileErrorId.ParamsNotLast, parameter);
                     }
                     if (!type.IsArray) {
                         context.addError(CompileErrorId.ParamsNotArray, parameter);
                     }
                     methodBuilder.setVarargs(true);
                 } else if (parameter.Modifier == ParameterModifier.This) {
                     if (!methodBuilder.IsStatic) {
                         context.addError(CompileErrorId.ThisParameterNotStatic, parameter);
                     }
                     if (i > 0) {
                         context.addError(CompileErrorId.ThisNotFirst, parameter);
                     }
                     methodBuilder.addAnnotation(context.getType("stab/lang/ExtensionMethod", parameter), false);
                 }
                 i++;
             }
             setMethodConstraints(methodDeclaration.ConstraintsClauses, methodBuilder);
             if (methodDeclaration.IsPartial) {
                 var partialInfo = partialTypes[typeBuilder.getFullName()];
                 var partialMethodInfo = new PartialMethodInfo();
                 if (methodDeclaration.Body == null) {
                     partialMethodInfo.definingPart = methodDeclaration;
                 } else {
                     partialMethodInfo.implementingPart = methodDeclaration;
                 }
                 partialInfo.partialMethods[methodBuilder] = partialMethodInfo;
             }
         } finally {
             context.MemberResolver.leaveMethod();
         }
     }
 }
		private static void declareType(TypeInfo type, Library targetTypeSystem, TypeBuilder clone, Scope<String, TypeInfo> genericArgs) {
			if (type.IsSynthetic) {
				return;
			}
			
			genericArgs.enterScope();
			foreach (var ga in clone.GenericArguments) {
				genericArgs.declareBinding(ga.FullName, ga);
			}
	
			clone.setBaseType(getType(targetTypeSystem, type.BaseType, genericArgs));
			
			foreach (var t in type.Interfaces) {
				clone.addInterface(getType(targetTypeSystem, t, genericArgs));
			}
	
			foreach (var av in type.Annotations) {
				var avb = clone.addAnnotation(getType(targetTypeSystem, av.Type, genericArgs), av.IsRuntimeVisible);
				cloneAnnotationValue(av, targetTypeSystem, avb, genericArgs);
			}
			
			foreach (var f in type.Fields.where(p => !p.IsSynthetic && !p.IsPrivate)) {
				var fb = clone.defineField(f.Name, getType(targetTypeSystem, f.Type, genericArgs));
				fb.setEnum(f.IsEnum);
				fb.setFinal(f.IsFinal);
				fb.setProtected(f.IsProtected);
				fb.setPublic(f.IsPublic);
				fb.setStatic(f.IsStatic);
				fb.setTransient(f.IsTransient);
				fb.setVolatile(f.IsVolatile);
				
				fb.setValue(f.Value);
				
				foreach (var av in f.getAnnotations()) {
					var avb = fb.addAnnotation(getType(targetTypeSystem, av.Type, genericArgs), av.IsRuntimeVisible);
					cloneAnnotationValue(av, targetTypeSystem, avb, genericArgs);
				}
			}
	
			foreach (var m in type.Methods.where(p => !p.IsSynthetic && !p.IsPrivate)) {
				var mb = clone.defineMethod(m.Name);
				mb.setAbstract(m.IsAbstract);
				mb.setBridge(m.IsBridge);
				mb.setFinal(m.IsFinal);
				mb.setNative(m.IsNative);
				mb.setProtected(m.IsProtected);
				mb.setPublic(m.IsPublic);
				mb.setStatic(m.IsStatic);
				mb.setStrict(m.IsStrict);
				mb.setSynchronized(m.IsSynchronized);
				mb.setVarargs(m.IsVarargs);
				
				foreach (var av in m.Annotations) {
					var avb = mb.addAnnotation(getType(targetTypeSystem, av.Type, genericArgs), av.IsRuntimeVisible);
					cloneAnnotationValue(av, targetTypeSystem, avb, genericArgs);
				}
				
				genericArgs.enterScope();
				foreach (var ga in m.GenericArguments) {
					var t = mb.addGenericArgument(ga.FullName);
					genericArgs.declareBinding(t.FullName, t);
				}
				
				mb.setReturnType(getType(targetTypeSystem, m.ReturnType, genericArgs));
				foreach (var p in m.Parameters) {
					var pb = mb.addParameter(getType(targetTypeSystem, p.Type, genericArgs));
					pb.setName(p.Name);
				}
				genericArgs.leaveScope();
			}
			
			foreach (var nt in type.NestedTypes) {
				declareType(nt, targetTypeSystem, (TypeBuilder)clone.getNestedType(nt.Name), genericArgs);
			}
			
			genericArgs.leaveScope();
		}