public void FunctionDeclaration(CParser.FunctionDeclaration FunctionDeclaration)
 {
     if (FunctionDeclaration.FunctionBody != null)
     {
         //Console.WriteLine(FunctionDeclaration.FunctionBody);
         Console.WriteLine("");
         Console.WriteLine("\t/// <summary>");
         Console.WriteLine("\t/// </summary>");
         foreach (var Parameter in FunctionDeclaration.CFunctionType.Parameters)
         {
             Console.WriteLine("\t/// <param name=\"{0}\"></param>", Parameter.Name);
         }
         if (ConvertCTypeToType(FunctionDeclaration.CFunctionType.Return) != typeof(void))
         {
             Console.WriteLine("\t/// <returns></returns>");
         }
         Console.WriteLine("\t[DllImport(DllName)]");
         string FunctionHeader = "";
         FunctionHeader += "static public";
         FunctionHeader += " " + ConvertCTypeToTypeString(FunctionDeclaration.CFunctionType.Return);
         FunctionHeader += " " + FunctionDeclaration.CFunctionType.Name;
         FunctionHeader += "(";
         FunctionHeader += String.Join(", ", FunctionDeclaration.CFunctionType.Parameters.Select(Item =>
         {
             return(ConvertCTypeToTypeString(Item.CType) + " " + Item.Name);
         }));
         FunctionHeader += ")";
         Console.WriteLine("\t{0};", FunctionHeader);
         //ConvertCTypeToType(FunctionDeclaration.CFunctionType.Return);
     }
 }
Beispiel #2
0
        public void FunctionDeclaration(CParser.FunctionDeclaration FunctionDeclaration)
        {
            PutDebugLine(FunctionDeclaration);

            var FunctionName      = FunctionDeclaration.CFunctionType.Name;
            var ReturnType        = ConvertCTypeToType(FunctionDeclaration.CFunctionType.Return);
            var ParameterTypes    = FunctionDeclaration.CFunctionType.Parameters.Select(Item => ConvertCTypeToType(Item.CType)).ToArray();
            var ParameterCSymbols = FunctionDeclaration.CFunctionType.Parameters;

            if (ParameterTypes.Length == 1 && ParameterTypes[0] == typeof(void))
            {
                ParameterTypes = new Type[0];
            }
            var FunctionReference = FunctionScope.Find(FunctionName);

            if (FunctionReference == null)
            {
                var CurrentMethodLazy = new Lazy <MethodInfo>(() =>
                {
                    var MethodBuilder = CurrentClass.DefineMethod(
                        FunctionName,
                        MethodAttributes.Static | MethodAttributes.Public, CallingConventions.Standard,
                        ReturnType,
                        ParameterTypes
                        );

                    for (int n = 0; n < ParameterCSymbols.Length; n++)
                    {
                        MethodBuilder.DefineParameter(n, ParameterAttributes.None, ParameterCSymbols[n].Name);
                    }

                    return(MethodBuilder);
                });

                FunctionReference = new FunctionReference(this, FunctionName, CurrentMethodLazy, new SafeMethodTypeInfo()
                {
                    IsStatic   = true,
                    ReturnType = ReturnType,
                    Parameters = ParameterTypes,
                })
                {
                    BodyFinalized = false,
                };

                FunctionScope.Push(FunctionName, FunctionReference);
            }

            // Just declaration
            if (FunctionDeclaration.FunctionBody == null)
            {
            }
            // Has function body.
            else
            {
                var CurrentMethod = (FunctionReference.MethodInfo as MethodBuilder);

                if (FunctionName == "main")
                {
                    //HasEntryPoint = true;

                    var StartupMethod = CurrentClass.DefineMethod(
                        "__startup",
                        MethodAttributes.Static | MethodAttributes.Public, CallingConventions.Standard,
                        typeof(int),
                        new Type[] { typeof(string[]) }
                        );

                    var StartupSafeILGenerator = new SafeILGenerator(StartupMethod.GetILGenerator(), CheckTypes: true, DoDebug: false, DoLog: false);
                    var ArgsArgument           = StartupSafeILGenerator.DeclareArgument(typeof(string[]), 0);

                    StartupSafeILGenerator.Push(CurrentClass);
                    StartupSafeILGenerator.Call((Func <RuntimeTypeHandle, Type>)Type.GetTypeFromHandle);
                    StartupSafeILGenerator.LoadArgument(ArgsArgument);
                    StartupSafeILGenerator.Call((Func <Type, string[], int>)CLibUtils.RunTypeMain);
                    //StartupSafeILGenerator.Call((Func<Type, string[], int>)CLibUtils.RunTypeMain);
                    StartupSafeILGenerator.Return(typeof(int));

                    EntryPoint = StartupMethod;
                    //EntryPoint = CurrentMethod;
                }

                var ILGenerator            = CurrentMethod.GetILGenerator();
                var CurrentSafeILGenerator = new SafeILGenerator(ILGenerator, CheckTypes: false, DoDebug: false, DoLog: true);

                AScope <VariableReference> .NewScope(ref this.VariableScope, () =>
                {
                    Scopable.RefScope(ref this.GotoContext, new LabelsContext(CurrentSafeILGenerator), () =>
                    {
                        Scopable.RefScope(ref this.CurrentMethod, CurrentMethod, () =>
                        {
                            Scopable.RefScope(ref this.SafeILGenerator, CurrentSafeILGenerator, () =>
                            {
                                // Set argument variables
                                ushort ArgumentIndex = 0;
                                foreach (var Parameter in FunctionDeclaration.CFunctionType.Parameters)
                                {
                                    var Argument = SafeILGenerator.DeclareArgument(ConvertCTypeToType(Parameter.CType), ArgumentIndex);
                                    this.VariableScope.Push(Parameter.Name, new VariableReference(Parameter.Name, Parameter.CType, Argument));
                                    ArgumentIndex++;
                                }

                                Traverse(FunctionDeclaration.FunctionBody);


                                if (FunctionDeclaration.FunctionBody.Statements.Length == 0 || !(FunctionDeclaration.FunctionBody.Statements.Last() is CParser.ReturnStatement))
                                //if (true)
                                {
                                    if (CurrentMethod.ReturnType != typeof(void))
                                    {
                                        SafeILGenerator.Push((int)0);
                                    }
                                    SafeILGenerator.Return(CurrentMethod.ReturnType);
                                }
                            });
#if SHOW_INSTRUCTIONS
                            Console.WriteLine("Code for '{0}':", FunctionName);
                            foreach (var Instruction in CurrentSafeILGenerator.GetEmittedInstructions())
                            {
                                Console.WriteLine("  {0}", Instruction);
                            }
#endif
                        });
                    });
                });

                FunctionReference.BodyFinalized = true;
            }
        }