private static object doTrap(object self, string name, List args, Type type) { Slot slot = type.slot(name, true); if (slot is Method) { Method m = (Method)slot; return(m.m_func.callOn(self, args)); } else { Field f = (Field)slot; int argSize = (args == null) ? 0 : args.sz(); if (argSize == 0) { return(FanUtil.box(f.get(self))); } if (argSize == 1) { object val = args.get(0); f.set(self, val); return(FanUtil.box(val)); } throw ArgErr.make("Invalid number of args to get or set field '" + name + "'").val; } }
////////////////////////////////////////////////////////////////////////// // Stub ////////////////////////////////////////////////////////////////////////// public static void stub(string podName, DirectoryInfo outDir, bool verbose) { writeLine(" .NET Stub [" + podName + "]"); string fanHome = SysProps.getProperty("fan.home"); string podPath = fanHome + "\\lib\\fan\\" + podName + ".pod"; string target = new FileInfo(outDir + "\\" + podName + ".dll").FullName; if (verbose) { writeLine(" <- " + podPath); Pod pod = Pod.doFind(podName, true, null); List list = pod.types(); string pre = "Fan." + FanUtil.upper(podName) + "."; for (int i = 0; i < list.sz(); i++) { writeLine(" " + pre + (list.get(i) as Type).name()); } writeLine(" -> " + target); } FStore store = new FStore(new ZipFile(podPath)); FPod fpod = new FPod(podName, store); fpod.read(); FTypeEmit.emitPod(fpod, false, target); }
/// <summary> /// .NET type name: Fan.Sys.Duration, System.Boolean /// </summary> public string nname() { if (m_nname == null) { m_nname = FanUtil.toDotnetTypeName(podName, typeName, isNullable()); } return(m_nname); }
public void verifySplitQName() { verifyQName(FanUtil.splitQName("Fan"), null, "Fan"); verifyQName(FanUtil.splitQName("Fan.Sys"), "Fan", "Sys"); verifyQName(FanUtil.splitQName("Fan.Sys.Boolean"), "Fan.Sys", "Boolean"); verifyQName(FanUtil.splitQName("Fan.Sys.Boolean.Foo"), "Fan.Sys.Boolean", "Foo"); verifyQName(FanUtil.splitQName("Fan.Sys.Foo/Val"), "Fan.Sys.Foo", "Val"); verifyQName(FanUtil.splitQName("Fan.Sys.Foo<Bar>"), "Fan.Sys.Foo", "Bar"); }
/// <summary> /// Emit a mixin router from a class to the mixin body methods. /// </summary> public void emitMixinRouter(Method m) { string parent = FanUtil.toDotnetTypeName(m.parent()); string name = FanUtil.toDotnetMethodName(m.name()); string ret = FanUtil.toDotnetTypeName(m.inheritedReturns()); string[] parTypes = new string[] { parent }; List pars = m.@params(); int paramCount = pars.sz(); // find first param with default value int firstDefault = paramCount; for (int i = 0; i < paramCount; i++) { if (((Param)pars.get(i)).hasDefault()) { firstDefault = i; break; } } // generate routers for (int i = firstDefault; i <= paramCount; i++) { string[] myParams = new string[i]; string[] myParamNames = new string[i]; string[] implParams = new string[i + 1]; implParams[0] = parent; for (int j = 0; j < i; j++) { Param param = (Param)m.@params().get(j); Type pt = param.type(); string s = FanUtil.toDotnetTypeName(pt); myParams[j] = s; myParamNames[j] = param.name(); implParams[j + 1] = s; } // CLR requires public virtual PERWAPI.MethAttr attr = PERWAPI.MethAttr.Public | PERWAPI.MethAttr.Virtual; PERWAPI.CILInstructions code = emitter.emitMethod(name, ret, myParamNames, myParams, attr, new string[0], new string[0]); code.Inst(PERWAPI.Op.ldarg_0); // push this for (int p = 0; p < i; p++) { // push args Param param = (Param)m.@params().get(p); FCodeEmit.loadVar(code, FanUtil.toDotnetStackType(param.type()), p + 1); } PERWAPI.Method meth = emitter.findMethod(parent + "_", name, implParams, ret); code.MethInst(PERWAPI.MethodOp.call, meth); code.Inst(PERWAPI.Op.ret); } }
////////////////////////////////////////////////////////////////////////// // Management ////////////////////////////////////////////////////////////////////////// public static Type of(object obj) { if (obj is FanObj) { return(((FanObj)obj).@typeof()); } else { return(FanUtil.toFanType(obj.GetType(), true)); } }
public void verifyUpper() { verify(FanUtil.upper("foo"), "Foo"); verify(FanUtil.upper("Foo"), "Foo"); verify(FanUtil.upper("fooBar"), "FooBar"); verify(FanUtil.upper("FooBar"), "FooBar"); verify(FanUtil.upper("alpha.beta.gamma"), "Alpha.Beta.Gamma"); verify(FanUtil.upper("Alpha.Beta.gamma"), "Alpha.Beta.Gamma"); verify(FanUtil.upper("Alpha.beta.Gamma"), "Alpha.Beta.Gamma"); verify(FanUtil.upper("alpha.Beta.Gamma"), "Alpha.Beta.Gamma"); }
public static Type @typeof(object self) { if (self is FanObj) { return(((FanObj)self).@typeof()); } else { return(FanUtil.toFanType(self.GetType(), true)); } }
public void verifyGetPodName() { verify(FanUtil.getPodName("Fan.Sys.Foo"), "sys"); verify(FanUtil.getPodName("Fan.Sys.Foo.Bar"), "sys"); verify(FanUtil.getPodName("Fan.Sys.Foo.Bar.Car"), "sys"); verify(FanUtil.getPodName("Fan.Sys.Foo/Val"), "sys"); verify(FanUtil.getPodName("Fan.SysTest.Foo"), "sysTest"); verifyFail(FanUtil.getPodName("Fan.Sys"), "sys"); verifyFail(FanUtil.getPodName("Fan.Sys.Foo"), "Sys"); verifyFail(FanUtil.getPodName("Fan.Sys.Foo"), "andy"); }
public static object toImmutable(object self) { if (self is FanObj) { return(((FanObj)self).toImmutable()); } else if (FanUtil.isDotnetImmutable(self.GetType())) { return(self); } throw NotImmutableErr.make(self.GetType().ToString()).val; }
public System.Type emit() { if (m_type == null) { if (Debug) { Console.WriteLine("-- emit: " + m_qname); } // make sure we have reflected to setup slots reflect(); // if sys class, just load it by name string podName = m_pod.m_name; if (podName == "sys") { try { m_dotnetRepr = FanUtil.isDotnetRepresentation(this); m_type = System.Type.GetType(FanUtil.toDotnetImplTypeName(podName, m_name)); } catch (Exception e) { Err.dumpStack(e); throw Err.make("Cannot load precompiled class: " + m_qname, e).val; } } // otherwise we need to emit it else { try { System.Type[] types = FTypeEmit.emitAndLoad(m_ftype); this.m_type = types[0]; if (types.Length > 1) { this.m_auxType = types[1]; } } catch (Exception e) { Err.dumpStack(e); throw Err.make("Cannot emit: " + m_qname, e).val; } } // we are done with our ftype now, gc it this.m_ftype = null; } return(m_type); }
////////////////////////////////////////////////////////////////////////// // Load ////////////////////////////////////////////////////////////////////////// public static System.Type load(System.Reflection.Assembly assembly, FPod pod) { System.Type type = null; string name = FanUtil.toDotnetTypeName(pod.m_podName, "$Pod", false); //if (Sys.usePrecompiledOnly) // type = System.Type.GetType(name); //else type = assembly.GetType(name); initFields(pod, type); return(type); }
public FCodeEmit(FTypeEmit parent, FBuf fcode, CILInstructions code, Reg[] regs, FTypeRef ret) { this.pod = parent.pod; this.emitter = parent.emitter; this.parent = parent; this.buf = fcode.m_buf; this.len = fcode.m_len; this.code = code; this.podClass = FanUtil.toDotnetTypeName(pod.m_podName, "$Pod", false); this.jumps = new Jumps(code); this.regs = regs; this.ret = ret; }
public static bool isImmutable(object self) { if (self is FanObj) { return(((FanObj)self).isImmutable()); } else if (self == null) { return(true); } else { return(FanUtil.isDotnetImmutable(self.GetType())); } }
////////////////////////////////////////////////////////////////////////// // Methods ////////////////////////////////////////////////////////////////////////// /// <summary> /// Define a new class to emit for this assembly. This class /// becomes the 'current' class, where subsequent EmitMethod /// and EmitField calls will popuate this class. /// </summary> public void emitClass(string baseQName, string qname, string[] interfaces, TypeAttr attr) { string[] s = FanUtil.splitQName(qname); className = qname; // first check if this type was already stubbed out classDef = (ClassDef)types[qname]; if (classDef == null) { // if not, we need to create it if (qname.IndexOf("/") != -1) { // Nested class PERWAPI.ClassDef cdef = (PERWAPI.ClassDef)findType(s[0]); classDef = cdef.AddNestedClass(attr, s[1]); } else { // Normal class classDef = peFile.AddClass(attr, s[0], s[1]); } } else { // if stubbed out, make sure we define the type correctly classDef.SetAttribute(attr); } // base class if (baseQName == null) { classDef.SuperType = null; } else { classDef.SuperType = findType(baseQName) as PERWAPI.Class; } // interfaces for (int i = 0; i < interfaces.Length; i++) { classDef.AddImplementedInterface(findType(interfaces[i]) as PERWAPI.Class); } types[qname] = classDef; }
/// <summary> /// Map a fcode field signature to a .NET field emit signature. /// </summary> public NField nfield(int index, bool mixin) { if (m_nfields == null) { m_nfields = new NField[m_fieldRefs.size()]; } NField nfield = m_nfields[index]; if (nfield == null) { int[] v = fieldRef(index).val; nfield = new NField(); nfield.parentType = FanUtil.toDotnetImplTypeName(nname(v[0])); nfield.fieldName = "m_" + name(v[1]); nfield.fieldType = nname(v[2]); m_nfields[index] = nfield; } return(nfield); }
////////////////////////////////////////////////////////////////////////// // Constructor ////////////////////////////////////////////////////////////////////////// /// <summary> /// Constructor. /// </summary> public FMethodEmit(FTypeEmit emit, FMethod method) { this.emitter = emit.emitter; this.emit = emit; this.method = method; this.code = method.m_code; this.name = FanUtil.toDotnetMethodName(method.m_name); this.paramLen = method.m_paramCount; this.isStatic = (method.m_flags & FConst.Static) != 0; this.isInternal = false; //(method.m_flags & FConst.Internal) != 0; this.isPrivate = (method.m_flags & FConst.Private) != 0; this.isAbstract = (method.m_flags & FConst.Abstract) != 0; this.isVirtual = (method.m_flags & FConst.Virtual) != 0; this.isOverride = (method.m_flags & FConst.Override) != 0; this.isCtor = (method.m_flags & FConst.Ctor) != 0; this.isNative = (method.m_flags & FConst.Native) != 0; this.isHide = false; // only used for make/make_ this.ret = emit.pod.typeRef(method.m_inheritedRet); this.selfName = emit.selfName; }
////////////////////////////////////////////////////////////////////////// // Emit ////////////////////////////////////////////////////////////////////////// public static void emit(Emitter emitter, FPod pod) { //FPodEmit emit = new FPodEmit(pod); TypeAttr tattr = TypeAttr.Public | TypeAttr.Sealed; FieldAttr fattr = FieldAttr.Public | FieldAttr.Static; emitter.emitClass("System.Object", FanUtil.toDotnetTypeName(pod.m_podName, "$Pod", false), new string[0], tattr); pod.readLiterals(); // generate constant fields other types will reference, we don't // initialize them, rather we do that later via reflection for (int i = 0; i < pod.m_literals.m_ints.size(); i++) { emitter.emitField("I" + i, "System.Int64", fattr); } for (int i = 0; i < pod.m_literals.m_floats.size(); i++) { emitter.emitField("F" + i, "System.Double", fattr); } for (int i = 0; i < pod.m_literals.m_decimals.size(); i++) { emitter.emitField("D" + i, "Fan.Sys.BigDecimal", fattr); } for (int i = 0; i < pod.m_literals.m_strs.size(); i++) { emitter.emitField("S" + i, "System.String", fattr); } for (int i = 0; i < pod.m_literals.m_durations.size(); i++) { emitter.emitField("Dur" + i, "Fan.Sys.Duration", fattr); } for (int i = 0; i < pod.m_literals.m_uris.size(); i++) { emitter.emitField("U" + i, "Fan.Sys.Uri", fattr); } }
public virtual object get(object instance) { m_parent.finish(); if (m_getter != null) { return(m_getter.invoke(instance, Method.noArgs)); } try { return(FanUtil.box(m_reflect.GetValue(instance))); } catch (Exception e) { if (m_reflect == null) { throw Err.make("Field not mapped to System.Reflection.FieldInfo correctly").val; } throw Err.make(e).val; } }
/// <summary> /// Map a fcode method signature to a .NET method emit signature. /// </summary> public NMethod ncall(int index, int opcode) { if (m_ncalls == null) { m_ncalls = new NMethod[m_methodRefs.size()]; } NMethod x = m_ncalls[index]; if (x == null || opcode == FConst.CallNonVirtual) // don't use cache on nonvirt (see below) { int[] m = methodRef(index).val; string type = nname(m[0]); string mName = name(m[1]); // if the type signature is java/lang then we route // to static methods on FanObj, FanFloat, etc string impl = FanUtil.toDotnetImplTypeName(type); bool explicitSelf = false; bool isStatic = false; if (type != impl) { explicitSelf = opcode == FConst.CallVirtual; isStatic = explicitSelf; } else { // if no object method than ok to use cache if (x != null) { return(x); } } // equals => Equals if (!explicitSelf) { mName = FanUtil.toDotnetMethodName(mName); } string[] pars; if (explicitSelf) { pars = new string[m.Length - 2]; pars[0] = type; for (int i = 1; i < pars.Length; i++) { pars[i] = nname(m[i + 2]); } } else { pars = new string[m.Length - 3]; for (int i = 0; i < pars.Length; i++) { pars[i] = nname(m[i + 3]); } } string ret = nname(m[2]); if (opcode == FConst.CallNew) { ret = type; // factory } // Handle static mixin calls if (opcode == FConst.CallMixinStatic) { impl += "_"; } x = new NMethod(); x.parentType = impl; x.methodName = mName; x.returnType = ret; x.paramTypes = pars; x.isStatic = isStatic; // we don't cache nonvirtuals on Obj b/c of conflicting signatures: // - CallVirtual: Obj.toStr => static FanObj.toStr(Object) // - CallNonVirtual: Obj.toStr => FanObj.toStr() if (type == impl || opcode != FConst.CallNonVirtual) { m_ncalls[index] = x; } } return(x); }
internal object invoke(object instance, object[] args) { if (m_reflect == null) { m_parent.finish(); } try { // zero index is full signature up to using max defaults int index = m_params.sz() - args.Length; if (m_parent.dotnetRepr() && isInstance()) { index++; } if (index < 0) { index = 0; } MethodInfo m = m_reflect[index]; //System.Console.WriteLine(">>> " + m_reflect.Length + "/" + index); //System.Console.WriteLine(m_reflect[index]); //System.Console.WriteLine("---"); //for (int i=0; i<m_reflect.Length; i++) // System.Console.WriteLine(m_reflect[i]); // TODO - not sure how this should work entirely yet, but we need // to be responsible for "boxing" Fantom wrappers and primitives // box the parameters ParameterInfo[] pars = m.GetParameters(); for (int i = 0; i < args.Length; i++) { System.Type pt = pars[i].ParameterType; if (pt == boolPrimitive && args[i] is Fan.Sys.Boolean) { args[i] = (args[i] as Fan.Sys.Boolean).booleanValue(); } else if (pt == doublePrimitive && args[i] is Fan.Sys.Double) { args[i] = (args[i] as Fan.Sys.Double).doubleValue(); } else if (pt == longPrimitive && args[i] is Fan.Sys.Long) { args[i] = (args[i] as Fan.Sys.Long).longValue(); } } // invoke method object ret = m.Invoke(instance, args); // box the return value return(FanUtil.box(ret)); } catch (ArgumentException e) { throw ArgErr.make(e).val; } catch (TargetInvocationException e) { Err err = Err.make(e.InnerException); err.m_stack = e.InnerException.StackTrace; throw err.val; } catch (Exception e) { if (m_reflect == null) { throw Err.make("Method not mapped to System.Reflection.MethodInfo correctly " + m_qname).val; } /* * System.Console.WriteLine("ERROR: " + signature()); * System.Console.WriteLine(" instance: " + instance); * System.Console.WriteLine(" args: " + (args == null ? "null" : ""+args.Length)); * for (int i=0; args != null && i<args.Length; ++i) * System.Console.WriteLine(" args[" + i + "] = " + args[i]); * Err.dumpStack(e); */ throw Err.make("Cannot call '" + this + "': " + e).val; } }
////////////////////////////////////////////////////////////////////////// // Util ////////////////////////////////////////////////////////////////////////// /// <summary> /// Find the Type instance for this fully qualified type name. /// </summary> internal PERWAPI.Type findType(string qname) { // Always convert voids to native if (qname == "Fan.Sys.Void") { qname = "System.Void"; } PERWAPI.Type type = (PERWAPI.Type)types[qname]; if (type == null) { string aname = FanUtil.getPodName(qname); if (aname == null) { aname = "mscorlib"; } if (qname.StartsWith("Fanx.")) { aname = "sys"; // hack for support classes } if (qname.EndsWith("Peer")) { aname += "Native_"; // TODO } // first check if this is a type in this pod that // hasn't been defined yet if (aname == assemblyName) { // stub out type - fill get filled in later (we hope) string[] sn = FanUtil.splitQName(qname); ClassDef stub = null; if (qname.IndexOf("/") != -1) { // Nested class PERWAPI.ClassDef cdef = (PERWAPI.ClassDef)findType(sn[0]); stub = cdef.AddNestedClass(PERWAPI.TypeAttr.NestedPublic, sn[1]); } else { // Normal class stub = peFile.AddClass(PERWAPI.TypeAttr.Public, sn[0], sn[1]); } types[qname] = stub; return(stub); } AssemblyRef aref = (AssemblyRef)assemblies[aname]; if (aref == null) { aref = peFile.MakeExternAssembly(aname); assemblies[aname] = aref; } string[] s = FanUtil.splitQName(qname); if (qname.IndexOf("/") != -1) { // Nested class PERWAPI.ClassRef cref = (PERWAPI.ClassRef)findType(s[0]); type = cref.AddNestedClass(s[1]); } /* * else if (qname.IndexOf("<") != -1) * { * // Generic type * //if (type == null) type = aref.AddClass(s[0], s[1]); * PERWAPI.ClassRef cref = (PERWAPI.ClassRef)findType(s[0]); * cref.SetGenericParams(new GenericParam[] { cref.GetGenericParam(0) }); * type = cref; * } */ else { // Normal class, get/add type type = aref.GetClass(s[0], s[1]); if (type == null) { type = aref.AddClass(s[0], s[1]); } } types[qname] = type; } return(type); }
private void finishMethod(MethodInfo m, bool staticOnly) { m_finishing = m.Name; string name = FanUtil.toFanMethodName(m.Name); Slot s = slot(name, false); if (s == null) { return; } if (s.parent() != this) { return; } if (staticOnly && !s.isStatic()) { return; } if (s is Method) { Method method = (Method)s; // alloc System.Reflection.MethodInfo[] array big enough // to handle all the versions with default parameters if (method.m_reflect == null) { int n = 1; for (int j = method.@params().sz() - 1; j >= 0; j--) { if (((Param)method.@params().get(j)).hasDefault()) { n++; } else { break; } } method.m_reflect = new MethodInfo[n]; } // get parameters, if sys we need to skip the // methods that use non-Fantom signatures ParameterInfo[] pars = m.GetParameters(); int numParams = pars.Length; if (m_pod == Sys.m_sysPod) { if (!checkAllFan(pars)) { return; } if (m_dotnetRepr) { bool dotnetStatic = m.IsStatic; if (!dotnetStatic) { return; } if (!method.isStatic() && !method.isCtor()) { --numParams; } } } // zero index is full signature up to using max defaults method.m_reflect[method.@params().sz() - numParams] = m; } else { Field field = (Field)s; if (m.ReturnType.ToString() == "System.Void") { field.m_setter.m_reflect = new MethodInfo[] { m } } ; else { field.m_getter.m_reflect = new MethodInfo[] { m } }; } } bool checkAllFan(ParameterInfo[] pars) { for (int i = 0; i < pars.Length; i++) { System.Type p = pars[i].ParameterType; if (!p.FullName.StartsWith("Fan.") && FanUtil.toFanType(p, false) == null) { return(false); } } return(true); }