//перевод тела функции private void ConvertFunctionBody(ICommonFunctionNode func, MethInfo mi, bool conv_first_stmt) { //if (is_in_unit && helper.IsUsed(func)==false) return; num_scope++; TypeBuilder tmp_type = cur_type; if (mi.disp != null) cur_type = mi.disp.tb; MethodBuilder tmp = cur_meth; cur_meth = (MethodBuilder)mi.mi; ILGenerator tmp_il = il; il = cur_meth.GetILGenerator(); smi.Push(mi); funcs.Add(func); if (conv_first_stmt) ConvertBody(func.function_code);//переводим тело else { ConvertStatementsListWithoutFirstStatement(func.function_code as IStatementsListNode); OptMakeExitLabel(); } //ivan for debug if (save_debug_info) { AddSpecialDebugVariables(); } //\ivan for debug if (cur_meth.ReturnType == TypeFactory.VoidType) il.Emit(OpCodes.Ret); //восстановление значений cur_meth = tmp; cur_type = tmp_type; il = tmp_il; smi.Pop(); funcs.RemoveAt(funcs.Count - 1); num_scope--; }
//процедура получения типов параметров процедуры private Type[] GetParamTypes(ICommonFunctionNode func) { Type[] tt = null; int num = 0; IParameterNode[] parameters = func.parameters; if (funcs.Count > 0) { tt = new Type[parameters.Length + 1]; tt[num++] = cur_type.DeclaringType; } else tt = new Type[parameters.Length]; for (int i = 0; i < parameters.Length; i++) { //этот тип уже был определен, поэтому получаем его с помощью хелпера Type tp = helper.GetTypeReference(parameters[i].type).tp; if (parameters[i].parameter_type == parameter_type.value) tt[i + num] = tp; else { //если var-параметр, то прибавляем & //(ssyy) 12.04.2008. Это полная ерунда. Написал нормально. tt[i + num] = tp.MakeByRefType(); } } return tt; }
//перевод заголовка функции private void ConvertFunctionHeader(ICommonFunctionNode func) { //if (is_in_unit && helper.IsUsed(func)==false) return; num_scope++; //увеличиваем глубину обл. видимости TypeBuilder tb = null, tmp_type = cur_type; Frame frm = null; bool nested = false; //func.functions_nodes.Length > 0 - имеет вложенные //funcs.Count > 0 - сама вложенная if (func.functions_nodes.Length > 0 || funcs.Count > 0) { nested = true; frm = MakeAuxType(func);//создаем запись активации tb = frm.tb; cur_type = tb; } else tb = cur_type; MethodAttributes attrs = MethodAttributes.Public | MethodAttributes.Static; //определяем саму процедуру/функцию MethodBuilder methb = null; methb = tb.DefineMethod(func.name, attrs); if (func.is_generic_function) { int count = func.generic_params.Count; string[] names = new string[count]; for (int i = 0; i < count; i++) { names[i] = func.generic_params[i].name; } methb.DefineGenericParameters(names); Type[] genargs = methb.GetGenericArguments(); for (int i = 0; i < count; i++) { helper.AddExistingType(func.generic_params[i], genargs[i]); } foreach (ICommonTypeNode par in func.generic_params) { converting_generic_param = par; ConvertTypeHeaderInSpecialOrder(par); } ConvertTypeInstancesInFunction(func); } Type ret_type = null; //получаем тип возвр. значения if (func.return_value_type == null) ret_type = TypeFactory.VoidType; else ret_type = helper.GetTypeReference(func.return_value_type).tp; //получаем типы параметров Type[] param_types = GetParamTypes(func); methb.SetParameters(param_types); methb.SetReturnType(ret_type); MethInfo mi = null; if (smi.Count != 0) //добавляем вложенную процедуру, привязывая ее к верхней процедуре mi = helper.AddMethod(func, methb, smi.Peek()); else mi = helper.AddMethod(func, methb); mi.num_scope = num_scope; mi.disp = frm;//тип - запись активации smi.Push(mi); ParameterBuilder pb = null; int num = 0; ILGenerator tmp_il = il; il = methb.GetILGenerator(); if (save_debug_info) { if (func.function_code is IStatementsListNode) MarkSequencePoint(((IStatementsListNode)func.function_code).LeftLogicalBracketLocation); else MarkSequencePoint(func.function_code.Location); } //if (ret_type != typeof(void)) mi.ret_val = il.DeclareLocal(ret_type); //если функция вложенная, то добавляем фиктивный параметр //ссылку на верхнюю запись активации if (funcs.Count > 0) { mi.nested = true;//это вложенная процедура methb.DefineParameter(1, ParameterAttributes.None, "$up$"); num = 1; } //все нелокальные параметры будем хранить в нестатических полях //записи активации. В начале функции инициализируем эти поля //параметрами IParameterNode[] parameters = func.parameters; FieldBuilder[] fba = new FieldBuilder[parameters.Length]; for (int i = 0; i < parameters.Length; i++) { object default_value = null; if (parameters[i].default_value != null) { default_value = helper.GetConstantForExpression(parameters[i].default_value); } ParameterAttributes pa = ParameterAttributes.None; //if (func.parameters[i].parameter_type == parameter_type.var) // pa = ParameterAttributes.Retval; if (default_value != null) pa |= ParameterAttributes.Optional; pb = methb.DefineParameter(i + num + 1, pa, parameters[i].name); if (parameters[i].is_params) pb.SetCustomAttribute(TypeFactory.ParamArrayAttributeConstructor, new byte[] { 0x1, 0x0, 0x0, 0x0 }); if (default_value != null) pb.SetConstant(default_value); if (func.functions_nodes.Length > 0) { FieldBuilder fb = null; //если параметр передается по значению, то все нормально if (parameters[i].parameter_type == parameter_type.value) fb = frm.tb.DefineField(parameters[i].name, param_types[i + num], FieldAttributes.Public); else { //иначе параметр передается по ссылке //тогда вместо типа параметра тип& используем тип* //например System.Int32& - System.Int32* (unmanaged pointer) //Type pt = param_types[i + num].Module.GetType(param_types[i + num].FullName.Substring(0, param_types[i + num].FullName.IndexOf('&')) + "*"); ////это означает, что тип определен в генерируемой сборке //if (pt == null) mb.GetType(param_types[i + num].FullName.Substring(0, param_types[i + num].FullName.IndexOf('&')) + "*"); Type pt = param_types[i + num].GetElementType().MakePointerType(); //определяем поле для параметра fb = frm.tb.DefineField(parameters[i].name, pt, FieldAttributes.Public); } //добавляем как глобальный параметр helper.AddGlobalParameter(parameters[i], fb).meth = smi.Peek(); fba[i] = fb; } else { //если проца не содержит вложенных, то все хорошо helper.AddParameter(parameters[i], pb).meth = smi.Peek(); } } if (func is ICommonNamespaceFunctionNode && (func as ICommonNamespaceFunctionNode).ConnectedToType != null) { if (!marked_with_extension_attribute.ContainsKey(cur_unit_type)) { cur_unit_type.SetCustomAttribute(TypeFactory.ExtensionAttributeType.GetConstructor(new Type[0]), new byte[0]); marked_with_extension_attribute[cur_unit_type] = cur_unit_type; } methb.SetCustomAttribute(TypeFactory.ExtensionAttributeType.GetConstructor(new Type[0]), new byte[0]); } if (func.functions_nodes.Length > 0 || funcs.Count > 0) { //определяем переменную, хранящую ссылку на запись активации данной процедуры LocalBuilder frame = il.DeclareLocal(cur_type); mi.frame = frame; if (doc != null) frame.SetLocalSymInfo("$disp$"); if (funcs.Count > 0) { //если она вложенная, то конструктору зап. акт. передаем ссылку на верх. з. а. il.Emit(OpCodes.Ldarg_0); //создаем запись активации il.Emit(OpCodes.Newobj, frm.cb); il.Emit(OpCodes.Stloc, frame); } else { //в противном случае просто создаем з. а. il.Emit(OpCodes.Newobj, frm.cb); il.Emit(OpCodes.Stloc_0, frame); } if (func.functions_nodes.Length > 0) for (int j = 0; j < fba.Length; j++) { //сохраняем нелокальные параметры в полях il.Emit(OpCodes.Ldloc_0); parameters = func.parameters; if (parameters[j].parameter_type == parameter_type.value) { if (funcs.Count > 0) il.Emit(OpCodes.Ldarg_S, (byte)(j + 1)); else il.Emit(OpCodes.Ldarg_S, (byte)j); } else { if (funcs.Count > 0) il.Emit(OpCodes.Ldarga_S, (byte)(j + 1)); else il.Emit(OpCodes.Ldarg_S, (byte)j); } il.Emit(OpCodes.Stfld, fba[j]); } } funcs.Add(func); //здесь наверное дублирование MethodBuilder tmp = cur_meth; cur_meth = methb; ConvertCommonFunctionConstantDefinitions(func.constants); //если функция не содержит вложенных процедур, то //переводим переменные как локальные if (func.functions_nodes.Length > 0) ConvertNonLocalVariables(func.var_definition_nodes, frm.mb); /*if (func.functions_nodes.Length == 0) ConvertLocalVariables(func.var_definition_nodes); else //иначе как нелокальные ConvertNonLocalVariables(func.var_definition_nodes, frm.mb);*/ //переводим заголовки вложенных функций ConvertNestedFunctionHeaders(func.functions_nodes); //переводим тела вложенных функций //foreach (ICommonNestedInFunctionFunctionNode f in func.functions_nodes) // ConvertFunctionBody(f); if (frm != null) frm.mb.GetILGenerator().Emit(OpCodes.Ret); //восстанавливаем текущие значения cur_type = tmp_type; num_scope--; smi.Pop(); funcs.RemoveAt(funcs.Count - 1); }
//перевод тела процедуры //(ssyy) По-моему, это вызывается только для вложенных процедур. private void ConvertFunctionBody(ICommonFunctionNode func) { //if (is_in_unit && helper.IsUsed(func)==false) return; num_scope++; MakeAttribute(func); IStatementsListNode sl = (IStatementsListNode)func.function_code; IStatementNode[] statements = sl.statements; if (sl.statements.Length > 0 && (statements[0] is IPInvokeStatementNode || (statements[0] is IExternalStatementNode))) { num_scope--; return; } MethInfo mi = helper.GetMethod(func); TypeBuilder tmp_type = cur_type; if (mi.disp != null) cur_type = mi.disp.tb; MethodBuilder tmp = cur_meth; cur_meth = (MethodBuilder)mi.mi; ILGenerator tmp_il = il; il = cur_meth.GetILGenerator(); smi.Push(mi); funcs.Add(func); if (func.functions_nodes.Length == 0) ConvertLocalVariables(func.var_definition_nodes); /*else //иначе как нелокальные ConvertNonLocalVariables(func.var_definition_nodes, mi.disp.mb);*/ foreach (ICommonNestedInFunctionFunctionNode f in func.functions_nodes) ConvertFunctionBody(f); //перевод тела ConvertBody(func.function_code); //ivan for debug if (save_debug_info) { AddSpecialDebugVariables(); } //\ivan for debug //if (cur_meth.ReturnType == typeof(void)) if (func.return_value_type == null || func.return_value_type == SystemLibrary.SystemLibrary.void_type) il.Emit(OpCodes.Ret); cur_meth = tmp; cur_type = tmp_type; il = tmp_il; smi.Pop(); funcs.RemoveAt(funcs.Count - 1); num_scope--; }
//перевод тел функций private void ConvertFunctionsBodies(ICommonFunctionNode[] funcs) { for (int i = 0; i < funcs.Length; i++) { IStatementsListNode sl = (IStatementsListNode)funcs[i].function_code; /*if (sl.statements.Length > 0 && (sl.statements[0] is IExternalStatementNode)) { continue; }*/ ConvertFunctionBody(funcs[i]); } }
//создание записи активации для влож. процедур private Frame MakeAuxType(ICommonFunctionNode func) { TypeBuilder tb = cur_type.DefineNestedType("$" + func.name + "$" + uid++, TypeAttributes.NestedPublic); //определяем поле - ссылку на верхнюю запись активации FieldBuilder fb = tb.DefineField("$parent$", tb.DeclaringType.IsValueType ? tb.DeclaringType.MakePointerType() : tb.DeclaringType, FieldAttributes.Public); //конструктор в кач-ве параметра, которого передается ссылка на верх. з/а ConstructorBuilder cb = null; //определяем метод для инициализации MethodBuilder mb = tb.DefineMethod("$Init$", MethodAttributes.Private, TypeFactory.VoidType, Type.EmptyTypes); if (funcs.Count > 0) { cb = tb.DefineConstructor(MethodAttributes.Public, CallingConventions.HasThis, new Type[1] { tb.DeclaringType.IsValueType ? tb.DeclaringType.MakeByRefType() : tb.DeclaringType }); cb.DefineParameter(1, ParameterAttributes.None, "$parent$"); } else cb = tb.DefineConstructor(MethodAttributes.Public, CallingConventions.HasThis, Type.EmptyTypes); ILGenerator il = cb.GetILGenerator(); //сохраняем ссылку на верхнюю запись активации if (func is ICommonNestedInFunctionFunctionNode) { il.Emit(OpCodes.Ldarg_0); il.Emit(OpCodes.Ldarg_1); il.Emit(OpCodes.Stfld, fb); } //вызываем метод $Init$ il.Emit(OpCodes.Ldarg_0); il.Emit(OpCodes.Call, mb); il.Emit(OpCodes.Ret); types.Add(tb); //создаем кадр записи активации Frame frm = new Frame(); frm.cb = cb; frm.mb = mb; frm.tb = tb; frm.parent = fb; return frm; }
public void ConvertTypeInstancesInFunction(ICommonFunctionNode func) { List<IGenericTypeInstance> insts; bool flag = instances_in_functions.TryGetValue(func, out insts); if (!flag) return; foreach (IGenericTypeInstance igi in insts) { ConvertTypeHeaderInSpecialOrder(igi); } }
public static string build_name_with_possible_generic(ICommonFunctionNode f, bool use_lt) { StringBuilder sb = new StringBuilder(); sb.Append(f.name); if (f.generic_params != null) { if (use_lt) sb.Append("<"); else sb.Append("<"); for (int i = 0; i < f.generic_params.Count; i++) { sb.Append(f.generic_params[i].name); if (i < f.generic_params.Count - 1) sb.Append(','); } if (use_lt) sb.Append(">"); else sb.Append(">"); } return sb.ToString(); }
private void AddTypeInstanceToFunction(ICommonFunctionNode func, IGenericTypeInstance gti) { List<IGenericTypeInstance> instances; //if (func == null) // SSM 3.07.16 Это решает проблему с оставшимся после перевода в сем. дерево узлом IEnumerable<UnknownType>, но очень грубо - пробую найти ошибку раньше // return; bool found = instances_in_functions.TryGetValue(func, out instances); if (!found) { instances = new List<IGenericTypeInstance>(); instances_in_functions.Add(func, instances); } if (!instances.Contains(gti)) { instances.Add(gti); } }
private void MakeAttribute(ICommonFunctionNode func) { MethodBuilder mb = helper.GetMethod(func).mi as MethodBuilder; IAttributeNode[] attrs = func.Attributes; for (int i = 0; i < attrs.Length; i++) { CustomAttributeBuilder cab = new CustomAttributeBuilder ((attrs[i].AttributeConstructor is ICompiledConstructorNode) ? (attrs[i].AttributeConstructor as ICompiledConstructorNode).constructor_info : helper.GetConstructor(attrs[i].AttributeConstructor).cnstr, get_constants(attrs[i].Arguments), get_named_properties(attrs[i].PropertyNames), get_constants(attrs[i].PropertyInitializers), get_named_fields(attrs[i].FieldNames), get_constants(attrs[i].FieldInitializers)); mb.SetCustomAttribute(cab); } foreach (IParameterNode pn in func.parameters) { ParamInfo pi = helper.GetParameter(pn); if (pi == null) continue; ParameterBuilder pb = pi.pb; attrs = pn.Attributes; for (int i = 0; i < attrs.Length; i++) { CustomAttributeBuilder cab = new CustomAttributeBuilder ((attrs[i].AttributeConstructor is ICompiledConstructorNode) ? (attrs[i].AttributeConstructor as ICompiledConstructorNode).constructor_info : helper.GetConstructor(attrs[i].AttributeConstructor).cnstr, get_constants(attrs[i].Arguments), get_named_properties(attrs[i].PropertyNames), get_constants(attrs[i].PropertyInitializers), get_named_fields(attrs[i].FieldNames), get_constants(attrs[i].FieldInitializers)); pb.SetCustomAttribute(cab); } } }
public void visit(ICommonFunctionNode value) { string s = value.GetType().ToString() + "."; prepare_string_node(value.name, s + "name"); prepare_collection(value.constants, s + "constants", "constants", value.constants.Length); prepare_node(value.function_code, s + "function_code"); prepare_collection(value.functions_nodes, s + "function_nodes", "function_nodes", value.functions_nodes.Length); prepare_string_node(value.node_kind.ToString(), s + "node_kind"); prepare_string_node(value.node_location_kind.ToString(), s + "node_location_kind"); prepare_collection(value.parameters, s + "parameters", "parameters", value.parameters.Length); prepare_string_node(value.return_value_type.ToString(), s + "return_value_type"); //prepare_node(value.return_variable, s + "return_variable"); prepare_up_link_node(value.return_variable.name, s + "return_variable", value.return_variable); prepare_string_node(value.SpecialFunctionKind.ToString(), s + "SpecialFunctionKind"); prepare_collection(value.var_definition_nodes, s + "var_definition_nodes", "var_definition_nodes", value.var_definition_nodes.Length); }
public virtual void visit(ICommonFunctionNode value) { }
public void visit(ICommonFunctionNode value) { throw new System.NotSupportedException(value.GetType().ToString()); }
private void AddTypeInstanceToFunction(ICommonFunctionNode func, IGenericTypeInstance gti) { List<IGenericTypeInstance> instances; bool found = instances_in_functions.TryGetValue(func, out instances); if (!found) { instances = new List<IGenericTypeInstance>(); instances_in_functions.Add(func, instances); } if (!instances.Contains(gti)) { instances.Add(gti); } }
public void ConvertTypeInstancesMembersInFunction(ICommonFunctionNode func) { List<IGenericTypeInstance> insts; bool flag = instances_in_functions.TryGetValue(func, out insts); if (!flag) return; foreach (IGenericTypeInstance igi in insts) { ConvertGenericInstanceTypeMembers(igi); } }
public static string get_simple_meth_header(ICommonFunctionNode f) { StringBuilder sb = new StringBuilder(); string hdr = HelpUtils.extract_user_defined_header(f.Documentation); if (!string.IsNullOrEmpty(hdr)) { sb.Append(hdr); return sb.ToString(); } sb.Append(f.name); sb.Append(get_generic_string(f.generic_params)); if (f.parameters.Length > 0) { sb.Append('('); for (int i = 0; i < f.parameters.Length; i++) { sb.Append(get_type_text(f.parameters[i].type)); if (i < f.parameters.Length - 1) sb.Append(", "); } sb.Append(')'); } return sb.ToString(); }