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 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()); }
private void CreateInstanceOfWrapper(LetExpressionAST let) { string currentFunctionCodeName = let.CurrentScope.CurrentFunction.CodeName; TypeCodeInfo typeCodeInfo = code.GetWrapperAsociatteTo(currentFunctionCodeName); ILGenerator il = code.Method.GetILGenerator(); //crear la instancia del objeto que contiene las variable mias que son usadas por otras funciones il.Emit(OpCodes.Newobj, typeCodeInfo.DefaultConstructor()); il.Emit(OpCodes.Stloc_0); //asignarle la instancia de mi clase a esta objeto para que tenga la referencia a su padre. //locaL_0.parent = this. if (let.CurrentScope.CurrentFunction.FunctionName != "main$") { FieldBuilder parent = typeCodeInfo.GetField("parent"); il.Emit(OpCodes.Ldloc_0); //cargar el this il.Emit(OpCodes.Ldarg_0); il.Emit(OpCodes.Stfld, parent); //darle los valores de las variables a los campos de esta clase. InitilizateFieldFromParameters(let); } //obligo a que se lanze el evento que estan esperando los que inicializa las varialbles code.ThrowEventForFunction(currentFunctionCodeName); }
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 }