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(); }