private void GenerateClassMethods(ITypeBuilder type, IReadOnlyList <MethodSyntaxNode> methods, CodeGenerationStore store, Dictionary <IMethodBuilder, MethodSyntaxNode> methodsDictionary, ref IMethodInfo?entryPoint) { var definedMethods = new List <IMethodInfo>(); store.Methods.Add(type, definedMethods); foreach (var method in methods) { var methodAttributes = MethodAttributes.Public; if (method.IsStatic) { methodAttributes |= MethodAttributes.Static; } var parameters = method.Parameters.Select(x => { var tpe = store.TypeDefLookup(x.Type); if (x.IsRef) { throw new RefTypeException("Ref types are not supported"); } typeChecker !.AssertTypeIsNotVoid(tpe); return(tpe); }).ToArray(); var arrType = typeof(int[]); var returnType = store.TypeDefLookup(method.ReturnType); var definedMethod = type.DefineMethod(method.Name, methodAttributes, returnType, parameters, method.IsEntryPoint); if (method.IsEntryPoint) { if (entryPoint != null) { throw new EntryPointException("Can only have 1 entry point"); } entryPoint = definedMethod; } definedMethods.Add(definedMethod); store.MethodParameters.Add(definedMethod, parameters); methodsDictionary.Add(definedMethod, method); int offset = 0; //if (!method.IsStatic) //{ // offset = 1; //} for (int i = 0; i < method.Parameters.Count; i++) { definedMethod.DefineParameter(i + 1 + offset, ParameterAttributes.None, method.Parameters[i].Name); } } }
// 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 IReadOnlyList <StatementSyntaxNode> GenerateClassFields(ITypeBuilder type, IReadOnlyList <FieldSyntaxNode> fields, CodeGenerationStore store, ISyntaxNode syntaxNode) { var definedFields = new List <IFieldInfo>(); var initExpressions = new List <StatementSyntaxNode>(); store.Fields.Add(type, definedFields); foreach (var field in fields) { var fieldType = store.TypeDefLookup(field.Type); typeChecker !.AssertTypeIsNotVoid(fieldType); var definedField = type.DefineField(field.Name, fieldType, FieldAttributes.Public); definedFields.Add(definedField); if (field.Expression != null) { initExpressions.Add(new ExpressionEqualsExpressionSyntaxNode(field, new VariableSyntaxNode(field, field.Name), field.Expression)); } } initExpressions.Add(new BaseClassConstructorSyntax(syntaxNode)); return(initExpressions); }
private IReadOnlyList <ConstructorSyntaxNode> GenerateClassConstructors(ITypeBuilder type, IReadOnlyList <ConstructorSyntaxNode> constructors, CodeGenerationStore store, IReadOnlyList <StatementSyntaxNode> fieldInitializers, Dictionary <IConstructorBuilder, ConstructorSyntaxNode> constructorsDictionary, ISyntaxNode parent) { var initialConstructors = new List <ConstructorSyntaxNode>(constructors); var mutatedConstructors = new List <ConstructorSyntaxNode>(); var definedConstructors = new List <IConstructorInfo>(); store.Constructors.Add(type, definedConstructors); if (constructors.Count == 0) { var statementList = new List <StatementSyntaxNode>(); initialConstructors.Add(new ConstructorSyntaxNode(parent, Array.Empty <ParameterDefinitionSyntaxNode>(), statementList)); } foreach (var constructor in initialConstructors) { var newStatements = new List <StatementSyntaxNode>(fieldInitializers); foreach (var toAdd in constructor.Statements) { newStatements.Add(toAdd); } var mutatedConstructor = constructor.MutateStatements(newStatements); mutatedConstructors.Add(mutatedConstructor); var methodAttributes = MethodAttributes.Public; var parameters = mutatedConstructor.Parameters.Select(x => { var tpe = store.TypeDefLookup(x.Type); if (x.IsRef) { throw new RefTypeException("Ref types are not supported"); } typeChecker !.AssertTypeIsNotVoid(tpe); return(tpe); }).ToArray(); var definedConstructor = type.DefineConstructor(methodAttributes, parameters); definedConstructors.Add(definedConstructor); store.ConstructorParameters.Add(definedConstructor, parameters); constructorsDictionary.Add(definedConstructor, mutatedConstructor); int offset = 0; for (int i = 0; i < mutatedConstructor.Parameters.Count; i++) { definedConstructor.DefineParameter(i + 1 + offset, ParameterAttributes.None, mutatedConstructor.Parameters[i].Name); } } return(mutatedConstructors); }