private void GenerateConstructors(GeneratedData toGenerate, CodeGenerationStore store) { foreach (var cls in toGenerate.Classes) { var type = cls.Key; var node = cls.Value; var fields = store.Fields[type].Select(x => (x, x.Name)) .ToDictionary(x => x.Name, x => x.x); foreach (IConstructorBuilder constructor in store.Constructors[type]) { var generator = constructor.GetILGenerator(); var parameters = toGenerate.Constructors[constructor].Parameters .Select((p, i) => (i, store.Types[p.Type], p.Name)) .ToDictionary(x => x.Name, x => ((short)x.i, x.Item2)); var methodInfo = new CurrentMethodInfo(type, typeChecker !.VoidType, false, parameters, fields); var generation = new ILGeneration(generator, store, methodInfo, delegateConstructorTypes !, baseConstructorInfo !, typeChecker !); GenerateMethod(generation, toGenerate.Constructors[constructor].Statements); } } }
private GeneratedData CreateTypesToGenerate(IReadOnlyList <ImmutableRootSyntaxNode> rootNodes, CodeGenerationStore store) { var toGenerate = new GeneratedData(); foreach (var rootNode in rootNodes) { foreach (var node in rootNode.Delegates) { var type = moduleBuilder.DefineType(node.Name, TypeAttributes.Public | TypeAttributes.Class | TypeAttributes.Sealed | TypeAttributes.AutoLayout, typeof(MulticastDelegate)); toGenerate.Delegates.Add(type, node); store.Types.Add(node.Name, type); } foreach (var node in rootNode.Classes) { var type = moduleBuilder.DefineType(node.Name, TypeAttributes.Public | TypeAttributes.Class | TypeAttributes.Sealed | TypeAttributes.AutoLayout); store.Types.Add(node.Name, type); toGenerate.Classes.Add(type, node); } } return(toGenerate); }
private void GenerateMethods(GeneratedData toGenerate, CodeGenerationStore store) { foreach (var cls in toGenerate.Classes) { var type = cls.Key; var node = cls.Value; var fields = store.Fields[type].Select(x => (x, x.Name)) .ToDictionary(x => x.Name, x => x.x); foreach (IMethodBuilder method in store.Methods[type]) { var generator = method.GetILGenerator(); int offset = method.IsStatic ? 0 : 1; var parameters = toGenerate.Methods[method].Parameters .Select((p, i) => (i + offset, store.Types[p.Type], p.Name)) .ToDictionary(x => x.Name, x => ((short)x.Item1, x.Item2)); var methodInfo = new CurrentMethodInfo(type, method.ReturnType, method.IsStatic, parameters, fields); var generation = new ILGeneration(generator, store, methodInfo, delegateConstructorTypes !, baseConstructorInfo !, typeChecker !); GenerateMethod(generation, toGenerate.Methods[method].Statements); } } }
// Generate all of our delegates. Delegates are easy, since the code generated for them is fixed, and all implemented // by the runtime. private void GenerateDelegates(GeneratedData toGenerate, CodeGenerationStore store) { foreach (var delegateToGenerate in toGenerate.Delegates) { var type = delegateToGenerate.Key; var syntaxNode = delegateToGenerate.Value; store.Fields.Add(type, Array.Empty <IFieldInfo>()); // Generate our constructor var constructor = type.DefineConstructor(MethodAttributes.Public | MethodAttributes.HideBySig | MethodAttributes.SpecialName | MethodAttributes.RTSpecialName, delegateConstructorTypes !); constructor.SetImplementationFlags(MethodImplAttributes.Runtime); store.Constructors.Add(type, new IConstructorInfo[] { constructor }); store.ConstructorParameters.Add(constructor, delegateConstructorTypes !); var parameterTypes = new IType[syntaxNode.Parameters.Count]; for (int i = 0; i < parameterTypes.Length; i++) { var paramType = store.TypeDefLookup(syntaxNode.Parameters[i].Type); if (syntaxNode.Parameters[i].IsRef) { throw new RefTypeException("Ref types are not supported"); } typeChecker !.AssertTypeIsNotVoid(paramType); parameterTypes[i] = paramType; } var returnType = store.TypeDefLookup(syntaxNode.ReturnType); // Generate the invoke method var method = type.DefineMethod("Invoke", MethodAttributes.Public | MethodAttributes.Virtual | MethodAttributes.HideBySig | MethodAttributes.NewSlot, returnType, parameterTypes, false); method.SetImplementationFlags(MethodImplAttributes.Runtime); for (int i = 0; i < parameterTypes.Length; i++) { method.DefineParameter(i + 1, ParameterAttributes.None, syntaxNode.Parameters[i].Name); } store.Methods.Add(type, new IMethodInfo[] { method }); store.MethodParameters.Add(method, parameterTypes); store.Delegates.Add((method.ReturnType, parameterTypes, type, constructor)); } }
private void GenerateClassPlaceholders(GeneratedData toGenerate, CodeGenerationStore store, ref IMethodInfo?entryPoint) { var patchedClasses = new Dictionary <ITypeBuilder, ImmutableClassSyntaxNode>(); foreach (var classToGenerate in toGenerate.Classes) { var type = classToGenerate.Key; var node = classToGenerate.Value; var fieldsToInitialize = GenerateClassFields(classToGenerate.Key, node.Fields, store, node); var patchedConstructors = GenerateClassConstructors(type, node.Constructors, store, fieldsToInitialize, toGenerate.Constructors, node); patchedClasses.Add(type, node.MutateConstructors(patchedConstructors)); GenerateClassMethods(type, node.Methods, store, toGenerate.Methods, ref entryPoint); } foreach (var patchedClass in patchedClasses) { toGenerate.Classes[patchedClass.Key] = patchedClass.Value; } ; }