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); }
/// <summary> /// Esta metodo annade todas los campos necesarios a la clase nested. Annade tambien un campo que es una referencia /// padre. /// </summary> /// <param name="code"></param> /// <param name="nested">El tipo nested</param> /// <param name="typeCodeInfo">la informacion asociada al tipo nested</param> /// <param name="container">El padre del tipo nested</param> private void PopulateNestedTypeWithVar(ILCode code, TypeBuilder nested, TypeCodeInfo typeCodeInfo, TypeBuilder container) { //annadir un field del tipo de mi padre typeCodeInfo.FieldNameOfParent = "parent"; FieldBuilder fieldRefPadreClass = nested.DefineField(typeCodeInfo.FieldNameOfParent, container, FieldAttributes.Public); //le annado a la clase TypeCodeInfo que ahora tiene un nuevo campo(la referencia al padre) typeCodeInfo.AddField(typeCodeInfo.FieldNameOfParent, fieldRefPadreClass); FunctionInfo funInfo = _functionDecl.CurrentScope.GetFunction(_functionDecl.FunctionId); foreach (var item in funInfo.VarsUsedForAnotherFunction) { if (item.IsParameterFunction) { Type fieldType = code.DefinedType[item.TypeInfo.CodeName]; FieldBuilder field = nested.DefineField(item.CodeName, fieldType, FieldAttributes.Public); code.DefinedField.Add(item.CodeName, field); //annadir el nuevo campo a la clase que me controlo los campos de un tipo nested typeCodeInfo.AddField(item.CodeName, field); } } }
/// <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; }
/// <summary> /// 转换模型 /// </summary> /// <param name="model"></param> /// <returns></returns> protected TypeCodeInfo ConvertToInfo(LxdmModel model) { if (model == null) { return(null); } TypeCodeInfo user = AutoMapper.Mapper.Map <LxdmModel, TypeCodeInfo>(model); return(user); }
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 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 }
public override Unit VisitVarDeclaration(VarDeclarationAST expr) { VarInfo varInfo = expr.CurrentScope.GetVarInfo(expr.Id); //nombre de la variable generado string varCodeName = varInfo.CodeName; // necesito el tipo de la variable. string typeCodeName = varInfo.TypeInfo.CodeName; Type varType = code.DefinedType[typeCodeName]; //aca hay que tener en cuenta que las variable que son usadas por otras funciones se declaran en la declaracion de //la funcion a la que pertenecen if (!varInfo.IsUsedForAnotherFunction) { if (!varInfo.IsParameterFunction) //no tengo en cuenta los parametro de funcion porque esos los declara la funcion { //generar la variable como local a la funcion ILGenerator il = code.Method.GetILGenerator(); LocalBuilder local = il.DeclareLocal(varType); // local.SetLocalSymInfo(varCodeName); //adicionarla a las varibles locales code.DefinedLocal.Add(varCodeName, local); } } else { if (!varInfo.IsParameterFunction) { string currentFunction = expr.CurrentScope.CurrentFunction.CodeName; TypeCodeInfo wrapper = code.GetWrapperAsociatteTo(currentFunction); FieldBuilder field = wrapper.Type.DefineField(varInfo.CodeName, varType, FieldAttributes.Public); //añadir el field a la clase ILCode code.DefinedField.Add(varInfo.CodeName, field); //añadida al wrapper wrapper.AddField(varCodeName, field); } } //generar la inicializacion de la variable code.OnBeginMethod += (theCode, e) => code_OnBeginMethod_var(expr, theCode, e); return(Unit.Create()); }
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 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); }
/// <summary> /// 自动转换映射 /// </summary> /// <param name="log"></param> /// <returns></returns> private LxdmModel ConvertToModel(TypeCodeInfo user) { LxdmModel model = AutoMapper.Mapper.Map <TypeCodeInfo, LxdmModel>(user); return(model); }