本文整理汇总了C#中ILGen.EmitNull方法的典型用法代码示例。如果您正苦于以下问题:C# ILGen.EmitNull方法的具体用法?C# ILGen.EmitNull怎么用?C# ILGen.EmitNull使用的例子?那么恭喜您, 这里精选的方法代码示例或许可以为您提供帮助。您也可以进一步了解该方法所在类ILGen
的用法示例。
在下文中一共展示了ILGen.EmitNull方法的11个代码示例,这些例子默认根据受欢迎程度排序。您可以为喜欢或者感觉有用的代码点赞,您的评价将有助于系统推荐出更棒的C#代码示例。
示例1: Compile
public override Type Compile(Executive engine, ILGen il, LocalAccess locals, Type[] parameterTypes)
{
Label l_true = il.DefineLabel();
Label l_false = il.DefineLabel();
il.Emit(OpCodes.Brfalse_S, l_true);
il.EmitNull();
il.Emit(OpCodes.Br_S, l_false);
il.MarkLabel(l_true);
il.Emit(OpCodes.Ldsfld, typeof(RuntimeOps).GetField("True"));
il.MarkLabel(l_false);
return typeof(System.Object);
}
示例2: EmitGetVar
static void EmitGetVar(ILGen gen, FieldBuilder fb)
{
Label falseLabel = gen.DefineLabel();
Label endLabel = gen.DefineLabel();
gen.EmitFieldGet(fb); // gen.Emit(OpCodes.Ldsfld,fb);
gen.Emit(OpCodes.Dup);
gen.EmitCall(Method_Var_isBound); // gen.Emit(OpCodes.Call, Method_Var_IsBound);
gen.Emit(OpCodes.Brfalse_S,falseLabel);
gen.Emit(OpCodes.Call,Method_Var_get);
gen.Emit(OpCodes.Br_S,endLabel);
gen.MarkLabel(falseLabel);
gen.Emit(OpCodes.Pop);
gen.EmitNull(); // gen.Emit(OpCodes.Ldnull);
gen.MarkLabel(endLabel);
}
示例3: SaveToAssembly
/// <summary>
/// This takes an assembly name including extension and saves the provided ScriptCode objects into the assembly.
///
/// The provided script codes can constitute code from multiple languages. The assemblyName can be either a fully qualified
/// or a relative path. The DLR will simply save the assembly to the desired location. The assembly is created by the DLR and
/// if a file already exists than an exception is raised.
///
/// The DLR determines the internal format of the ScriptCode and the DLR can feel free to rev this as appropriate.
/// </summary>
public static void SaveToAssembly(string assemblyName, params SavableScriptCode[] codes) {
ContractUtils.RequiresNotNull(assemblyName, "assemblyName");
ContractUtils.RequiresNotNullItems(codes, "codes");
// break the assemblyName into it's dir/name/extension
string dir = Path.GetDirectoryName(assemblyName);
if (String.IsNullOrEmpty(dir)) {
dir = Environment.CurrentDirectory;
}
string name = Path.GetFileNameWithoutExtension(assemblyName);
string ext = Path.GetExtension(assemblyName);
// build the assembly & type gen that all the script codes will live in...
AssemblyGen ag = new AssemblyGen(new AssemblyName(name), dir, ext, /*emitSymbols*/false);
TypeBuilder tb = ag.DefinePublicType("DLRCachedCode", typeof(object), true);
TypeGen tg = new TypeGen(ag, tb);
var symbolDict = new Dictionary<SymbolId, FieldBuilder>();
// then compile all of the code
Dictionary<Type, List<CodeInfo>> langCtxBuilders = new Dictionary<Type, List<CodeInfo>>();
foreach (SavableScriptCode sc in codes) {
List<CodeInfo> builders;
if (!langCtxBuilders.TryGetValue(sc.LanguageContext.GetType(), out builders)) {
langCtxBuilders[sc.LanguageContext.GetType()] = builders = new List<CodeInfo>();
}
KeyValuePair<MethodBuilder, Type> compInfo = sc.CompileForSave(tg, symbolDict);
builders.Add(new CodeInfo(compInfo.Key, sc, compInfo.Value));
}
MethodBuilder mb = tb.DefineMethod(
"GetScriptCodeInfo",
MethodAttributes.SpecialName | MethodAttributes.Public | MethodAttributes.Static,
typeof(MutableTuple<Type[], Delegate[][], string[][], string[][]>),
Type.EmptyTypes);
ILGen ilgen = new ILGen(mb.GetILGenerator());
var langsWithBuilders = langCtxBuilders.ToArray();
// lang ctx array
ilgen.EmitArray(typeof(Type), langsWithBuilders.Length, (index) => {
ilgen.Emit(OpCodes.Ldtoken, langsWithBuilders[index].Key);
ilgen.EmitCall(typeof(Type).GetMethod("GetTypeFromHandle", new[] { typeof(RuntimeTypeHandle) }));
});
// builders array of array
ilgen.EmitArray(typeof(Delegate[]), langsWithBuilders.Length, (index) => {
List<CodeInfo> builders = langsWithBuilders[index].Value;
ilgen.EmitArray(typeof(Delegate), builders.Count, (innerIndex) => {
ilgen.EmitNull();
ilgen.Emit(OpCodes.Ldftn, builders[innerIndex].Builder);
ilgen.EmitNew(
builders[innerIndex].DelegateType,
new[] { typeof(object), typeof(IntPtr) }
);
});
});
// paths array of array
ilgen.EmitArray(typeof(string[]), langsWithBuilders.Length, (index) => {
List<CodeInfo> builders = langsWithBuilders[index].Value;
ilgen.EmitArray(typeof(string), builders.Count, (innerIndex) => {
ilgen.EmitString(builders[innerIndex].Code.SourceUnit.Path);
});
});
// 4th element in tuple - custom per-language data
ilgen.EmitArray(typeof(string[]), langsWithBuilders.Length, (index) => {
List<CodeInfo> builders = langsWithBuilders[index].Value;
ilgen.EmitArray(typeof(string), builders.Count, (innerIndex) => {
ICustomScriptCodeData data = builders[innerIndex].Code as ICustomScriptCodeData;
if (data != null) {
ilgen.EmitString(data.GetCustomScriptCodeData());
} else {
ilgen.Emit(OpCodes.Ldnull);
}
});
});
ilgen.EmitNew(
typeof(MutableTuple<Type[], Delegate[][], string[][], string[][]>),
new[] { typeof(Type[]), typeof(Delegate[][]), typeof(string[][]), typeof(string[][]) }
);
ilgen.Emit(OpCodes.Ret);
//.........这里部分代码省略.........
示例4: CompileStub
/***
* Current host interop uses reflection, which requires pre-existing classes
* Work around this by:
* Generate a stub class that has the same interfaces and fields as the class we are generating.
* Use it as a type hint for this, and bind the simple name of the class to this stub (in resolve etc)
* Unmunge the name (using a magic prefix) on any code gen for classes
*/
static Type CompileStub(Type super, NewInstanceExpr ret, Type[] interfaces, Object frm)
{
//GenContext context = Compiler.COMPILER_CONTEXT.get() as GenContext ?? Compiler.EvalContext;
//GenContext context = Compiler.COMPILER_CONTEXT.get() as GenContext ?? new GenContext("stub" + RT.nextID().ToString(), ".dll", ".", CompilerMode.Immediate);
GenContext context = Compiler.COMPILER_CONTEXT.get() as GenContext ?? new GenContext("stub" + RT.nextID().ToString(), ".dll", ".", false);
TypeBuilder tb = context.ModuleBuilder.DefineType(Compiler.COMPILE_STUB_PREFIX + "." + ret.InternalName, TypeAttributes.Public | TypeAttributes.Abstract, super, interfaces);
tb.DefineDefaultConstructor(MethodAttributes.Public);
// instance fields for closed-overs
for (ISeq s = RT.keys(ret.Closes); s != null; s = s.next())
{
LocalBinding lb = (LocalBinding)s.first();
FieldAttributes access = FieldAttributes.Public;
// TODO: FIgure out Volatile
if (!ret.IsVolatile(lb))
access |= FieldAttributes.InitOnly;
if (lb.PrimitiveType != null)
tb.DefineField(lb.Name, lb.PrimitiveType, access);
else
tb.DefineField(lb.Name, typeof(Object), access);
}
// ctor that takes closed-overs and does nothing
if (ret.CtorTypes().Length > 0)
{
ConstructorBuilder cb = tb.DefineConstructor(MethodAttributes.Public, CallingConventions.HasThis, ret.CtorTypes());
ILGen ilg = new ILGen(cb.GetILGenerator());
ilg.EmitLoadArg(0);
ilg.Emit(OpCodes.Call, super.GetConstructor(Type.EmptyTypes));
ilg.Emit(OpCodes.Ret);
if (ret._altCtorDrops > 0)
{
Type[] ctorTypes = ret.CtorTypes();
int newLen = ctorTypes.Length - ret._altCtorDrops;
if (newLen > 0)
{
Type[] altCtorTypes = new Type[newLen];
for (int i = 0; i < altCtorTypes.Length; i++)
altCtorTypes[i] = ctorTypes[i];
ConstructorBuilder cb2 = tb.DefineConstructor(MethodAttributes.Public, CallingConventions.HasThis, altCtorTypes);
ILGen ilg2 = new ILGen(cb2.GetILGenerator());
ilg2.EmitLoadArg(0);
for (int i = 0; i < newLen; i++)
ilg2.EmitLoadArg(i + 1);
for (int i = 0; i < ret._altCtorDrops; i++)
ilg2.EmitNull();
ilg2.Emit(OpCodes.Call, cb);
ilg2.Emit(OpCodes.Ret);
}
}
}
Type t = tb.CreateType();
Compiler.RegisterDuplicateType(t);
return t;
}
示例5: GenerateFieldOnlyConstructor
private ConstructorBuilder GenerateFieldOnlyConstructor(TypeBuilder fnTB, Type baseType)
{
Type[] ctorTypes = CtorTypes();
Type[] altCtorTypes = new Type[ctorTypes.Length - _altCtorDrops];
for (int i = 0; i < altCtorTypes.Length; i++)
altCtorTypes[i] = ctorTypes[i];
ConstructorBuilder cb = fnTB.DefineConstructor(MethodAttributes.Public, CallingConventions.HasThis, altCtorTypes);
ILGen gen = new ILGen(cb.GetILGenerator());
//Call full constructor
gen.EmitLoadArg(0); // gen.Emit(OpCodes.Ldarg_0);
for (int i = 0; i < altCtorTypes.Length; i++)
gen.EmitLoadArg(i + 1);
for (int i = 0; i < _altCtorDrops; i++)
gen.EmitNull();
gen.Emit(OpCodes.Call, _ctorInfo);
gen.Emit(OpCodes.Ret);
return cb;
}
示例6: GenerateNonMetaConstructor
private ConstructorBuilder GenerateNonMetaConstructor(TypeBuilder fnTB, Type baseType)
{
Type[] ctorTypes = CtorTypes();
Type[] noMetaCtorTypes = new Type[ctorTypes.Length - 1];
for (int i = 1; i < ctorTypes.Length; i++)
noMetaCtorTypes[i - 1] = ctorTypes[i];
ConstructorBuilder cb = fnTB.DefineConstructor(MethodAttributes.Public, CallingConventions.HasThis, noMetaCtorTypes);
ILGen gen = new ILGen(cb.GetILGenerator());
gen.EmitLoadArg(0);
gen.EmitNull(); // null meta
for (int i = 0; i < noMetaCtorTypes.Length; i++)
gen.EmitLoadArg(i + 1);
gen.Emit(OpCodes.Call, _ctorInfo);
gen.Emit(OpCodes.Ret);
return cb;
}
示例7: GenerateMetaFunctions
private void GenerateMetaFunctions(TypeBuilder fnTB)
{
// IPersistentMap meta()
MethodBuilder metaMB = fnTB.DefineMethod("meta", MethodAttributes.Public | MethodAttributes.Virtual | MethodAttributes.ReuseSlot, typeof(IPersistentMap), Type.EmptyTypes);
ILGen gen = new ILGen(metaMB.GetILGenerator());
if (SupportsMeta)
{
gen.EmitLoadArg(0);
gen.EmitFieldGet(_metaField);
}
else
gen.EmitNull();
gen.Emit(OpCodes.Ret);
// IObj withMeta(IPersistentMap)
MethodBuilder withMB = fnTB.DefineMethod("withMeta", MethodAttributes.Public | MethodAttributes.Virtual | MethodAttributes.ReuseSlot, typeof(IObj), new Type[] { typeof(IPersistentMap) });
gen = new ILGen(withMB.GetILGenerator());
if (SupportsMeta)
{
gen.EmitLoadArg(1); // meta arg
foreach (FieldBuilder fb in _closedOverFields)
{
gen.EmitLoadArg(0);
gen.EmitFieldGet(fb);
}
gen.EmitNew(_ctorInfo);
}
else
gen.EmitLoadArg(0); //this
gen.Emit(OpCodes.Ret);
}
示例8: CompileExpr
internal void CompileExpr(ILGen il, LocalAccess locals, Stack<Type> st, object lval)
{
if (lval == null)
{
il.EmitNull();
st.Push(typeof(System.Object));
}
else if (Lisp.IsNode(lval))
{
if (lval == Lisp.NIL || lval == Lisp.T)
{
if (lval == Lisp.NIL)
il.EmitNull();
else
il.Emit(OpCodes.Ldsfld, typeof(RuntimeOps).GetField("True"));
st.Push(typeof(System.Object));
}
else if (lval == Lisp.INST)
{
il.Emit(OpCodes.Ldarg_0);
il.EmitPropertyGet(typeof(CompiledLambda), "Engine");
st.Push(typeof(Executive));
}
else if (lval == Lisp.ARGV)
{
il.Emit(OpCodes.Ldarg_2);
st.Push(typeof(object[]));
}
else if (lval == Lisp.MPOOL)
{
il.Emit(OpCodes.Ldarg_3);
st.Push(typeof(MemoryPool));
}
else
{
LocalBuilder localVar = locals.GetLocal(lval);
if (localVar != null)
{
il.Emit(OpCodes.Ldloc, localVar);
st.Push(localVar.LocalType);
}
else
{
Type type = lval.GetType();
if (type == typeof(Integer))
{
il.EmitDecimal((Decimal)((Integer)lval));
il.EmitNew(typeof(Integer).GetConstructor(BindingFlags.Instance | BindingFlags.NonPublic, null,
new Type[] { typeof(Decimal) }, null));
}
else if (!il.TryEmitConstant(lval, type))
{
il.Emit(OpCodes.Ldarg_1);
il.EmitInt(locals.DefineConstant(lval));
il.Emit(OpCodes.Ldelem_Ref);
if (type.IsValueType)
il.EmitUnbox(type);
}
st.Push(type);
}
}
}
else if (Lisp.IsFunctor(lval))
{
object head = Lisp.Car(lval);
object[] args = Lisp.ToArray(Lisp.Cdr(lval));
ControlFormBase control;
if (m_control.TryGetValue(head, out control))
control.Compile(this, lval, il, locals, st, args);
else
{
foreach (object a in args)
CompileExpr(il, locals, st, a);
Type[] parameterTypes = new Type[args.Length];
for (int k = args.Length - 1; k >= 0; k--)
parameterTypes[k] = st.Pop();
FuncName name = new FuncName(head, parameterTypes);
FuncBase body = GetFunc(name, false);
if (body == null)
{
bool successed = false;
if (parameterTypes.Length == 2)
{
Type castType = ValueProxy.GetType(parameterTypes[0], parameterTypes[1]);
ValueConverter converter1 = FindConverter(parameterTypes[0], castType);
ValueConverter converter2 = FindConverter(parameterTypes[1], castType);
body = GetFunc(new FuncName(name.ID, new Type[] { castType, castType }), false);
if (body != null && converter1 != null && converter2 != null)
{
LocalBuilder localVar = il.DeclareLocal(parameterTypes[1]);
il.Emit(OpCodes.Stloc, localVar);
converter1.Compile(this, il, locals, parameterTypes[0]);
il.Emit(OpCodes.Ldloc, localVar);
il.FreeLocal(localVar);
converter2.Compile(this, il, locals, parameterTypes[1]);
successed = true;
}
}
if (!successed)
{
//.........这里部分代码省略.........
示例9: GenerateProxyMethod
private static void GenerateProxyMethod(
TypeBuilder proxyTB,
FieldBuilder mapField,
MethodInfo m,
HashSet<MethodBuilder> specialMethods)
{
MethodAttributes attribs = m.Attributes;
bool callBaseMethod;
if ( (attribs & MethodAttributes.Abstract) == MethodAttributes.Abstract )
{
attribs &= ~MethodAttributes.Abstract;
callBaseMethod = false;
}
else
{
callBaseMethod = true;
}
attribs &= ~MethodAttributes.NewSlot;
attribs |= MethodAttributes.Virtual | MethodAttributes.HideBySig | MethodAttributes.Public;
//Console.Write("Generating proxy method {0}(", m.Name);
//foreach (ParameterInfo p in m.GetParameters())
// Console.Write("{0}, ", p.ParameterType.FullName);
//Console.Write(") ");
//Console.WriteLine(attribs.ToString());
MethodBuilder proxym = proxyTB.DefineMethod(
m.Name,
attribs,
m.CallingConvention,
m.ReturnType,
m.GetParameters().Select<ParameterInfo, Type>(p => p.ParameterType).ToArray<Type>());
if (m.IsSpecialName)
specialMethods.Add(proxym);
ILGen gen = new ILGen(proxym.GetILGenerator());
Label elseLabel = gen.DefineLabel();
Label endLabel = gen.DefineLabel();
//// Print a little message, for debugging purposes
//gen.Emit(OpCodes.Ldstr, String.Format("Calling {0} / {1}", proxyTB.FullName, m.ToString()));
//gen.Emit(OpCodes.Call, typeof(Console).GetMethod("WriteLine",
// new Type[] { typeof(string) }));
//gen.Emit(OpCodes.Call, typeof(Console).GetMethod("get_Out"));
//gen.Emit(OpCodes.Call, typeof(System.IO.TextWriter).GetMethod("Flush"));
// Lookup method name in map
gen.EmitLoadArg(0); // gen.Emit(OpCodes.Ldarg_0);
gen.EmitFieldGet(mapField); // gen.Emit(OpCodes.Ldfld, mapField);
gen.EmitString(m.Name); // gen.Emit(OpCodes.Ldstr, m.Name);
gen.EmitCall(Method_RT_get); // gen.Emit(OpCodes.Call, Method_RT_get);
gen.Emit(OpCodes.Dup);
gen.EmitNull(); // gen.Emit(OpCodes.Ldnull);
gen.Emit(OpCodes.Beq_S, elseLabel);
// map entry found
ParameterInfo[] pinfos = m.GetParameters();
gen.Emit(OpCodes.Castclass, typeof(IFn));
gen.EmitLoadArg(0); // gen.Emit(OpCodes.Ldarg_0); // push implicit 'this' arg.
for (int i = 0; i < pinfos.Length; i++)
{
gen.EmitLoadArg(i + 1); // gen.Emit(OpCodes.Ldarg, i + 1);
if (m.GetParameters()[i].ParameterType.IsValueType)
gen.Emit(OpCodes.Box,pinfos[i].ParameterType);
}
int parmCount = pinfos.Length;
gen.EmitCall(GetIFnInvokeMethodInfo(parmCount+1)); // gen.Emit(OpCodes.Call, GetIFnInvokeMethodInfo(parmCount + 1));
if (m.ReturnType == typeof(void))
gen.Emit(OpCodes.Pop);
else
gen.Emit(OpCodes.Unbox_Any, m.ReturnType);
gen.Emit(OpCodes.Br_S,endLabel);
// map entry not found
gen.MarkLabel(elseLabel);
gen.Emit(OpCodes.Pop); // get rid of null leftover from the 'get'
if ( callBaseMethod )
{
gen.EmitLoadArg(0); // gen.Emit(OpCodes.Ldarg_0);
for (int i = 0; i < parmCount; i++)
gen.EmitLoadArg(i + 1); // gen.Emit(OpCodes.Ldarg, i + 1);
gen.Emit(OpCodes.Call, m); // gen.EmitCall(m) improperly emits a callvirt in some cases
}
else
{
gen.EmitString(m.Name); // gen.Emit(OpCodes.Ldstr, m.Name);
gen.EmitNew(CtorInfo_NotImplementedException_1); // gen.Emit(OpCodes.Newobj, CtorInfo_NotImplementedException_1);
gen.Emit(OpCodes.Throw);
}
gen.MarkLabel(endLabel);
//.........这里部分代码省略.........
示例10: DefineDelegateFieldAndOverride
static void DefineDelegateFieldAndOverride(TypeBuilder tb, int numArgs)
{
Type fieldType = FuncTypeHelpers.GetFFuncType(numArgs);
string fieldName = "_fn" + numArgs;
FieldBuilder fb = tb.DefineField(fieldName, fieldType, FieldAttributes.Public);
MethodBuilder mb = tb.DefineMethod("invoke", MethodAttributes.Public | MethodAttributes.HideBySig | MethodAttributes.Virtual, typeof(object), CreateObjectTypeArray(numArgs));
ILGen gen = new ILGen(mb.GetILGenerator());
Label eqLabel = gen.DefineLabel();
// this._fni == null ?
gen.EmitLoadArg(0); // gen.Emit(OpCodes.Ldarg_0);
gen.Emit(OpCodes.Ldfld, fb);
gen.EmitNull(); // gen.Emit(OpCodes.Ldnull);
gen.Emit(OpCodes.Beq, eqLabel);
//Not equal to Null, invoke it.
gen.EmitLoadArg(0); // gen.Emit(OpCodes.Ldarg_0);
gen.Emit(OpCodes.Ldfld, fb);
for (int i = 0; i < numArgs; i++)
gen.EmitLoadArg(i + 1); // gen.Emit(OpCodes.Ldarg, i + 1);
gen.EmitCall(fb.FieldType.GetMethod("Invoke")); // gen.Emit(OpCodes.Call, fb.FieldType.GetMethod("Invoke"));
gen.Emit(OpCodes.Ret);
gen.MarkLabel(eqLabel);
// Equal to Null: throw WrongArityException
gen.EmitLoadArg(0); // gen.Emit(OpCodes.Ldarg_0);
gen.EmitInt(numArgs);
gen.EmitCall(Method_AFn_WrongArityException); // gen.Emit(OpCodes.Call, Method_AFn_WrongArityException);
gen.Emit(OpCodes.Throw);
}
示例11: GenerateStatics
protected override void GenerateStatics(GenContext context)
{
if (IsDefType)
{
TypeBuilder tb = TypeBuilder;
// getBasis()
MethodBuilder mbg = tb.DefineMethod("getBasis", MethodAttributes.Public | MethodAttributes.Static, typeof(IPersistentVector), Type.EmptyTypes);
LambdaExpression lambda = Expression.Lambda(GenerateValue(_hintedFields));
lambda.CompileToMethod(mbg, context.IsDebuggable);
if (_fields.count() > _hintedFields.count())
{
// create(IPersistentMap)
MethodBuilder mbc = tb.DefineMethod("create", MethodAttributes.Public | MethodAttributes.Static, tb, new Type[] { typeof(IPersistentMap) });
ILGen gen = new ILGen(mbc.GetILGenerator());
LocalBuilder kwLocal = gen.DeclareLocal(typeof(Keyword));
List<LocalBuilder> locals = new List<LocalBuilder>();
for (ISeq s = RT.seq(_hintedFields); s != null; s = s.next())
{
string bName = ((Symbol)s.first()).Name;
Type t = Compiler.TagType(Compiler.TagOf(s.first()));
// local_kw = Keyword.intern(bname)
// local_i = arg_0.valAt(kw,null)
gen.EmitLoadArg(0);
gen.EmitString(bName);
gen.EmitCall(Compiler.Method_Keyword_intern_string);
gen.Emit(OpCodes.Dup);
gen.Emit(OpCodes.Stloc,kwLocal.LocalIndex);
gen.EmitNull();
gen.EmitCall(Compiler.Method_IPersistentMap_valAt2);
LocalBuilder lb = gen.DeclareLocal(t);
locals.Add(lb);
if ( t.IsPrimitive )
gen.EmitUnbox(t);
gen.Emit(OpCodes.Stloc, lb.LocalIndex);
// arg_0 = arg_0.without(local_kw);
gen.EmitLoadArg(0);
gen.Emit(OpCodes.Ldloc,kwLocal.LocalIndex);
gen.EmitCall(Compiler.Method_IPersistentMap_without);
gen.EmitStoreArg(0);
}
foreach (LocalBuilder lb in locals)
gen.Emit(OpCodes.Ldloc, lb.LocalIndex);
gen.EmitNull();
gen.EmitLoadArg(0);
gen.EmitCall(Compiler.Method_RT_seqOrElse);
gen.EmitNew(CtorInfo);
gen.Emit(OpCodes.Ret);
}
}
}