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()); }
/// <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())); }
/// <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())); }
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); }
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 }
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); }
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); }