예제 #1
0
        public override Unit VisitVar(VarAST ast)
        {
            ILGenerator il = code.Method.GetILGenerator();

            //buscar la variable
            VarInfo varInfo = ast.CurrentScope.GetVarInfo(ast.VarId);
            string  currentFunctionCodeName = ast.CurrentScope.CurrentFunction.CodeName;

            if (ast.IsForeignVar) //se entra aca cuando la variable pertenece a otra funcion que no es la actual .
            {
                //carga el respectivo campo de la clase contenedora.
                //como mis metodos son de instancia y las varibles tambien tengo que cargar el parametro 0
                il.Emit(OpCodes.Ldarg_0);
                //ahora viene cargar la variable de verdad.
                TypeCodeInfo typeCodeInfo =
                    code.GetWrapperAsociatteTo(ast.CurrentScope.CurrentFunction.FunctionParent.CodeName);
                while (typeCodeInfo != null && !typeCodeInfo.ContainFieldInLevel1(varInfo.CodeName))
                {
                    //cargo el campo que representa al padre del tipo actual
                    il.Emit(OpCodes.Ldfld, typeCodeInfo.GetField(typeCodeInfo.FieldNameOfParent));
                    typeCodeInfo = typeCodeInfo.Parent;
                }
                il.Emit(OpCodes.Ldfld, typeCodeInfo.GetField(varInfo.CodeName));
            }
            else
            {
                if (varInfo.IsLocalVariable)
                {
                    il.Emit(OpCodes.Ldloc, code.DefinedLocal[varInfo.CodeName].LocalIndex);
                }
                else if (varInfo.IsParameterFunction)
                {
                    il.Emit(OpCodes.Ldarg, varInfo.ParameterNumber + 1);
                }
                else // tengo que acceder a la variable a travez de la instancia que tengo como varible local.
                {
                    TypeCodeInfo typeCodeInfo = code.GetWrapperAsociatteTo(currentFunctionCodeName);
                    //cargar esta variable local donde estan todas las variables que son usadas por  los demas metodos.
                    il.Emit(OpCodes.Ldloc_0);
                    il.Emit(OpCodes.Ldfld, typeCodeInfo.GetField(varInfo.CodeName));
                }
            }

            //ver si debo dejar el valor en la pila.
            if (!code.PushOnStack)
            {
                il.Emit(OpCodes.Pop);
            }
            return(Unit.Create());
        }
예제 #2
0
        /// <summary>
        /// Devuelve true si el llamado es a una funcion hija.Es decir definidas a partir de la funcion actual
        /// </summary>
        /// <param name="code"></param>
        /// <returns></returns>
        private bool IsCallToMethodChild(ILCode code)
        {
            string       funCodeName  = _functionInvocation.CurrentScope.CurrentFunction.CodeName;
            TypeCodeInfo typeCodeInfo = code.GetWrapperAsociatteTo(funCodeName);

            return(typeCodeInfo.ContainMethodInLevel1(FunctionCodeName()));
        }
예제 #3
0
        /// <summary>
        /// Devuelve true si el llamado es a una funcion definida al mismo nivel del la funcion actual
        /// </summary>
        /// <param name="code"></param>
        /// <returns></returns>
        private bool IsCallRecursiveOrMethodBrother(ILCode code)
        {
            string       funParentCodeName = _functionInvocation.CurrentScope.CurrentFunction.FunctionParent.CodeName;
            TypeCodeInfo typeCodeInfo      = code.GetWrapperAsociatteTo(funParentCodeName);

            return(typeCodeInfo.ContainMethodInLevel1(FunctionCodeName()));
        }
예제 #4
0
        public override void GenerateCode(ILCode code, ExpressionAst rightExpr)
        {
            ILGenerator il = code.Method.GetILGenerator();

            //buscar la variable
            VarInfo varInfo = _varAst.CurrentScope.GetVarInfo(_varAst.VarId);

            //--->

            bool pushOnStack = code.PushOnStack;

            code.PushOnStack = true;

            if (_varAst.IsForeignVar)
            //aqui se entra cuando se usa una variable se usa en una funcion que no fue quien la declaro
            {
                string currentParentFunctionCodeName = _varAst.CurrentScope.CurrentFunction.FunctionParent.CodeName;
                //carga el respectivo campo de la clase contenedora.
                //como mis metodos son de instancia y las varibles tambien tengo que cargar el parametro 0
                il.Emit(OpCodes.Ldarg_0);
                //ahora viene cargar la variable de verdad.
                TypeCodeInfo typeCodeInfo = code.GetWrapperAsociatteTo(currentParentFunctionCodeName);
                while (!typeCodeInfo.ContainFieldInLevel1(varInfo.CodeName))
                {
                    //cargo el campo que representa al padre del tipo actual
                    string parentInstanceName = typeCodeInfo.FieldNameOfParent;
                    il.Emit(OpCodes.Ldfld, typeCodeInfo.GetField(parentInstanceName));
                    typeCodeInfo = typeCodeInfo.Parent;
                }
                //pongo el valor que quiero asignar en la pila
                rightExpr.Accept(CodeGenerator);
                //lo asigno.
                il.Emit(OpCodes.Stfld, typeCodeInfo.GetField(varInfo.CodeName));
            }
            else
            {
                if (varInfo.IsLocalVariable)
                {
                    rightExpr.Accept(CodeGenerator);
                    il.Emit(OpCodes.Stloc, code.DefinedLocal[varInfo.CodeName].LocalIndex);
                }
                else if (varInfo.IsParameterFunction)
                {
                    rightExpr.Accept(CodeGenerator);
                    il.Emit(OpCodes.Starg, varInfo.ParameterNumber + 1);
                }
                else // tengo que acceder a la variable a travez de la instancia que tengo como varible local.
                {
                    //se asume que el wrapper siempre esta como primera variable del metodo.
                    il.Emit(OpCodes.Ldloc_0);
                    rightExpr.Accept(CodeGenerator);
                    il.Emit(OpCodes.Stfld, code.DefinedField[varInfo.CodeName]);
                }
            }
            code.PushOnStack = pushOnStack;
        }
        public MethodBuilder GenerateInstanceMethodWithClassWrapper(ILCode code)
        {
            MethodBuilder mBuilder = GetMethod(code);

            //este es el nombre de la clase que contiene a este funcion
            string parentWrapper = string.Format("Tg_{0}", FunctionParentCodeName());
            //obtengo el tipo de la clase que contiene a esta funcion
            var container = (TypeBuilder)code.DefinedType[parentWrapper];

            //generar la clase wrapper a mis variables
            string      currentWrapper = string.Format("Tg_{0}", FunctionCodeName());
            TypeBuilder typeNested     = container.DefineNestedType(currentWrapper,
                                                                    TypeAttributes.NestedPublic);

            //annadir a la clase code el tipo.
            code.DefinedType.Add(typeNested.Name, typeNested);
            //asociar el wrapper con la funcion que lo creo
            code.AsociatteMethodToWrapper(mBuilder.Name, currentWrapper);

            //tengo que asociar este tipo con su padre.
            TypeCodeInfo typeCodeInfo = code.GetWrapperAsociatteTo(FunctionCodeName());

            typeCodeInfo.Parent = code.GetWrapperAsociatteTo(FunctionParentCodeName());

            //annadir esta funcion al padre.
            //Tener en cuenta cuando se llame la funcion antes de ser declarada
            if (!typeCodeInfo.Parent.ContainMethodInLevel1(mBuilder.Name))
            {
                typeCodeInfo.Parent.AddMethod(mBuilder.Name, mBuilder);
            }

            PopulateNestedTypeWithVar(code, typeNested, typeCodeInfo, container);

            //crear la instancia de esta clase dentro de mi codigo.
            ILGenerator il = mBuilder.GetILGenerator();

            il.DeclareLocal(typeNested);
            //No annado la variable local al ILCode porque siempre sera la primera de todas.

            return(mBuilder);
        }
예제 #6
0
        private void GenerateCodeForCallMethodParent(ILCode code)
        {
            ILGenerator il = code.Method.GetILGenerator();

            string       parentOfCurrentFunction = _functionInvocation.CurrentScope.CurrentFunction.FunctionParent.CodeName;
            TypeCodeInfo parentWrapper           = code.GetWrapperAsociatteTo(parentOfCurrentFunction);

            il.Emit(OpCodes.Ldarg_0);
            while (parentWrapper != null && !parentWrapper.ContainMethodInLevel1(FunctionCodeName()))
            {
                il.Emit(OpCodes.Ldfld, parentWrapper.GetField(parentWrapper.FieldNameOfParent));
                parentWrapper = parentWrapper.Parent;
            }
            //lo proximo seria llamar al metodo
        }
예제 #7
0
        private MethodBuilder GetMethod(string funCodeName, ILCode code)
        {
            //si esta definida la uso
            if (code.DefinedMethod.ContainsKey(funCodeName))
            {
                return(code.DefinedMethod[funCodeName]);
            }

            //sino no  esta definida creo su signatura.
            //este es el nombre de la clase que contiene a este funcion
            string parentWrapper = string.Format("Tg_{0}", FunctionParentCodeName());
            //obtengo el tipo de la clase
            var container = (TypeBuilder)code.DefinedType[parentWrapper];

            Type returnType;

            Type[] parameterTypes;
            //creo los paremtros de la funcion
            bool isFunction = !string.IsNullOrEmpty(ReturnTypeId());

            //creando los parametros y el tipo de retorno
            CreateParams(code, isFunction, out returnType, out parameterTypes);

            //creo la funcion como un metodo de instancia.
            MethodBuilder mBuilder = container.DefineMethod(FunctionCodeName(), MethodAttributes.Public, returnType,
                                                            parameterTypes);

            //adiciono la nueva funcion que he declarado
            code.DefinedMethod.Add(mBuilder.Name, mBuilder);

            //Tener en cuenta cuando se llame la funcion antes de ser declarada ,hay que annadir el metodo a su padre
            string       currentFunctionParent = _functionInvocation.CurrentScope.CurrentFunction.FunctionParent.CodeName;
            TypeCodeInfo typeCodeInfo          = code.GetWrapperAsociatteTo(currentFunctionParent);

            typeCodeInfo.AddMethod(mBuilder.Name, mBuilder);
            //typcodeindo

            return(mBuilder);
        }
예제 #8
0
        private static TypeBuilder AddFunctionMainToCode(ILCode code, MethodBuilder main)
        {
            code.DefinedMethod.Add(MainFunction, main);
            //crear lo que sera el wrapper a esta funcion
            string      currentWrapper = string.Format("Tg_{0}", MainFunction);
            TypeBuilder typeNested     = code.Type.DefineNestedType(currentWrapper,
                                                                    TypeAttributes.NestedPublic);

            //crear en la variable de instancia de la clase contenedora,pues el Let asume que la tiene creada.
            ILGenerator il = main.GetILGenerator();

            il.DeclareLocal(typeNested);

            //annadir a la clase code el tipo.
            code.DefinedType.Add(typeNested.Name, typeNested);
            //asociar el tipo wrapper al metodo
            code.AsociatteMethodToWrapper(MainFunction, currentWrapper);

            code.GetWrapperAsociatteTo(MainFunction);
            //PopulateNestedTypeWithVar(code, typeNested, typeCodeInfo);

            return(typeNested);
        }