Exemplo n.º 1
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;
            }
        }
Exemplo n.º 2
0
        public void VariableDeclaration(CParser.VariableDeclaration VariableDeclaration)
        {
            PutDebugLine(VariableDeclaration);

            var VariableName  = VariableDeclaration.Symbol.Name;
            var VariableCType = VariableDeclaration.Symbol.CType;

            //Console.WriteLine(VariableCType);

            // ??
            if (VariableCType == null)
            {
                Console.Error.WriteLine("Warning: Global variable '{0}' doesn't have type!!", VariableName);
                return;
            }

            var VariableType = ConvertCTypeToType(VariableCType);

            var IsExternVariable = (VariableCType.GetCSimpleType().Storage == CTypeStorage.Extern);
            var IsAlreadyDefined = (VariableScope.Find(VariableName) != null);


            if (IsAlreadyDefined)
            {
                if (!IsExternVariable)
                {
                    Console.Error.WriteLine("Warning: Global variable '{0}' already defined but not defined as external", VariableName);
                }
                return;
            }

            if (VariableName == null || VariableName.Length == 0)
            {
                Console.Error.WriteLine("Variable doesn't have name!");
                return;
            }
            if (VariableCType is CFunctionType)
            {
                Console.Error.WriteLine("Variable is not a function!");
                return;
            }
            if (VariableType == typeof(void))
            {
                Console.Error.WriteLine("Variable has void type!");
                return;
            }

            VariableReference Variable;
            bool GlobalScope;

            // Global Scope
            if (this.SafeILGenerator == null)
            {
                GlobalScope = true;

                var Field = CurrentClass.DefineField(VariableName, VariableType, FieldAttributes.Static | FieldAttributes.Public);
                Variable = new VariableReference(VariableDeclaration.Symbol.Name, VariableDeclaration.Symbol.CType, Field);
            }
            // Local Scope
            else
            {
                GlobalScope = false;

                var Local = this.SafeILGenerator.DeclareLocal(VariableType, VariableName);
                Variable = new VariableReference(VariableDeclaration.Symbol.Name, VariableDeclaration.Symbol.CType, Local);
            }

            this.VariableScope.Push(VariableName, Variable);

            Action Initialize = () =>
            {
                Variable.LoadAddress(SafeILGenerator);
                SafeILGenerator.InitObject(VariableType);

                Traverse(VariableDeclaration.InitialValue);
                SafeILGenerator.PopLeft();
            };

            if (GlobalScope)
            {
                Scopable.RefScope(ref SafeILGenerator, StaticInitializerSafeILGenerator, () =>
                {
                    Initialize();
                });
            }
            else
            {
                Initialize();
            }
        }