public void GenerateCode(ProgramNode node, ICIL_CodeGenerator codeGenerator = null) { foreach (var cls in new[] { BuiltIn.Object, BuiltIn.IO, BuiltIn.String, BuiltIn.Bool, BuiltIn.Int }) { TypeTable.IsDefinedType($"{cls}", out var type); #region .TYPES CIL_Type cilType; IEnumerable <CIL_FunctionDeclaration> funtions; IEnumerable <CIL_Attribute> attributes; //var instance = type.Self.Holder ?? // (type.Self.Holder = codeGenerator.DefineVariable()); //codeGenerator.AddLocalVariable( // new CIL_LocalVariable((Variable)type.Self.Holder)); switch (cls) { case BuiltIn.Object: funtions = ((CoolType)type).GetMethods .Select(function => new CIL_FunctionDeclaration($"{function.ParentScope}_{function.Name}")); cilType = CIL_Factory.DefineType($"{cls}", funtion: funtions); break; case BuiltIn.IO: funtions = ((CoolType)type).GetMethods .Select(function => new CIL_FunctionDeclaration($"{function.ParentScope}_{function.Name}")); cilType = CIL_Factory.DefineType($"{cls}", $"{BuiltIn.Object}", funtion: funtions); break; case BuiltIn.String: attributes = new[] { new CIL_Attribute($"{Attribute.String_value}") }; funtions = ((CoolType)type).GetMethods .Select(function => new CIL_FunctionDeclaration($"{function.ParentScope}_{function.Name}")); cilType = CIL_Factory.DefineType($"{cls}", $"{BuiltIn.Object}", attributes, funtions); break; case BuiltIn.Int: case BuiltIn.Bool: attributes = new[] { new CIL_Attribute($"{cls}_value") }; cilType = CIL_Factory.DefineType($"{cls}", $"{BuiltIn.Object}", attributes); break; default: throw new ArgumentOutOfRangeException(); } CIL_Factory.AddType(cilType); #endregion } #region BFS GenerateCode var queue = new Queue <string>(); queue.Enqueue("Object"); queue.Enqueue("IO"); var classesList = new List <ClassNode>(); while (queue.Count != 0) { classesList.AddRange(node.ClassesList .Where(classNode => { var boolean = classNode.TypeParent == queue.Peek(); if (boolean) { queue.Enqueue(classNode.TypeClass); } return(boolean); })); queue.Dequeue(); } #endregion foreach (var cls in classesList) { TypeTable.IsDefinedType(cls.TypeClass, out var type); #region .Types var attributes = ((CoolType)type).GetAttributes .Select(attr => new CIL_Attribute($"{cls.TypeClass}_{attr.Name}")); var funtions = ((CoolType)type).GetMethods .Select(funtion => new CIL_FunctionDeclaration($"{funtion.ParentScope}_{funtion.Name}")); var cilType = CIL_Factory.DefineType(cls.TypeClass, cls.TypeParent, attributes, funtions); CIL_Factory.AddType(cilType); #endregion } foreach (var cls in classesList) { GenerateCode(cls); } #region .CODE #region Object CIL_Factory.AddFunction(CIL_FunctionBuilder.Object_copy); CIL_Factory.AddFunction(CIL_FunctionBuilder.Object_type_name); CIL_Factory.AddFunction(CIL_FunctionBuilder.Object_abort); #endregion #region IO CIL_Factory.AddFunction(CIL_FunctionBuilder.IO_out_string); CIL_Factory.AddFunction(CIL_FunctionBuilder.IO_out_int); CIL_Factory.AddFunction(CIL_FunctionBuilder.IO_in_string); CIL_Factory.AddFunction(CIL_FunctionBuilder.IO_in_int); #endregion #region String CIL_Factory.AddFunction(CIL_FunctionBuilder.String_concat); CIL_Factory.AddFunction(CIL_FunctionBuilder.String_length); CIL_Factory.AddFunction(CIL_FunctionBuilder.String_substring); #endregion #region Exceptions CIL_Factory.AddFunction(CIL_FunctionBuilder.ExecutionOfACaseStatementWithoutAMatchingBranchException); CIL_Factory.AddFunction(CIL_FunctionBuilder.CaseOnVoidException); CIL_Factory.AddFunction(CIL_FunctionBuilder.ArgumentOutOfRangeException); CIL_Factory.AddFunction(CIL_FunctionBuilder.DispatchOnVoidException); CIL_Factory.AddFunction(CIL_FunctionBuilder.DivideByZeroException); CIL_Factory.AddFunction(CIL_FunctionBuilder.NegativeLengthException); CIL_Factory.AddFunction(CIL_FunctionBuilder.SubstringOutOfRangeException); #endregion #endregion }
public void GenerateCode(ClassNode node, ICIL_CodeGenerator codeGenerator = null) { TypeTable.IsDefinedType(node.TypeClass, out var type); //Define init_function var initFunction = CIL_Factory.DefineFunction($"{node.TypeClass}_Init"); // Define Variable ('instance') var instance = type.Self.Holder ?? (type.Self.Holder = initFunction.CodeGenerator.DefineVariable()); if (node.TypeClass == "Main") { // Add Local Variable initFunction.CodeGenerator.AddLocalVariable( new CIL_LocalVariable((Variable)instance)); // Allocate Main initFunction.CodeGenerator.AddInstruction( new Allocate((Variable)instance, node.TypeClass)); } else { // Define argument //var argument = initFunction.CodeGenerator.DefineVariable(); //add Local Variable initFunction.CodeGenerator.AddLocalVariable( new CIL_LocalVariable((Variable)instance)); initFunction.CodeGenerator.AddArgument( new CIL_Argument((Variable)instance)); } if (node.TypeParent != $"{BuiltIn.Object}" && node.TypeParent != $"{BuiltIn.IO}") { // Set Param to invoke the Parent Init_function initFunction.CodeGenerator.AddInstruction( new Param((Variable)instance)); //Define the variable to hold the result call of the Parent's init_fuction of TypeClass var rVcall = initFunction.CodeGenerator.DefineVariable(); // add Local Variable initFunction.CodeGenerator.AddLocalVariable( new CIL_LocalVariable(rVcall)); //Call the Parent's init_function initFunction.CodeGenerator.AddInstruction( new Call(rVcall, $"{node.TypeParent}_Init")); } foreach (var feature in node.FeatureList.Features) { switch (feature) { case LocalOrFieldInit localOrFieldInit: GenerateCode(localOrFieldInit, initFunction.CodeGenerator); initFunction.CodeGenerator.AddInstruction( new SetAttr((Variable)instance, $"{node.TypeClass}_{localOrFieldInit.Name}", localOrFieldInit.Symbol.Holder)); break; case MethodNode methodNode: var function = CIL_Factory.DefineFunction($"{node.TypeClass}_{methodNode.FuncName}"); function.CodeGenerator .AddLocalVariable(new CIL_LocalVariable((Variable)instance)); function.CodeGenerator.AddArgument( new CIL_Argument((Variable)instance)); GenerateCode(methodNode, function.CodeGenerator); CIL_Factory.AddFunction(function); break; } } if (node.TypeClass == "Main") { var result = initFunction.CodeGenerator.DefineVariable(); // add Local Variable initFunction.CodeGenerator.AddLocalVariable( new CIL_LocalVariable(result)); // set Param to invoke the main function initFunction.CodeGenerator.AddInstruction( new Param((Variable)instance)); //Control is transferred to Main_main initFunction.CodeGenerator.AddInstruction( new Call(result, $"{node.TypeClass}_main")); } //Add the return instruction's initFunction.CodeGenerator.AddInstruction( new CIL_Return()); //Add InitFunction with the initialized code CIL_Factory.AddFunction(initFunction); }