PageRenderTime 37ms CodeModel.GetById 11ms RepoModel.GetById 1ms app.codeStats 0ms

/src/sys/dotnet/fan/sys/Type.cs

https://bitbucket.org/bedlaczech/fan-1.0
C# | 357 lines | 192 code | 62 blank | 103 comment | 79 complexity | 1de9a66a162f29fb1e87be879c598ebd MD5 | raw file
Possible License(s): CC-BY-SA-3.0
  1. //
  2. // Copyright (c) 2006, Brian Frank and Andy Frank
  3. // Licensed under the Academic Free License version 3.0
  4. //
  5. // History:
  6. // 14 Sep 06 Andy Frank Creation
  7. //
  8. using System.Collections;
  9. using System.Runtime.CompilerServices;
  10. using Fanx.Emit;
  11. using Fanx.Fcode;
  12. using Fanx.Serial;
  13. using Fanx.Util;
  14. namespace Fan.Sys
  15. {
  16. /// <summary>
  17. /// Type models a static type definition for an Obj class. A Type lifecycle:
  18. ///
  19. /// 1) Hollow: in this state we know basic identity of the type, and
  20. /// it's inheritance hierarchy. A type is setup to be hollow during
  21. /// Pod.load().
  22. /// 2) Reflected: in this state we read all the slot definitions from the
  23. /// fcode to populate the slot tables used to for reflection. At this
  24. /// point clients can discover the signatures of the Type.
  25. /// 3) Emitted: the final state of loading a Type is to emit to a Java
  26. /// class called "fan.{pod}.{type}". Once emitted we can instantiate
  27. /// the type or call it's methods.
  28. /// 4) Finished: once we have reflected the slots into memory and emitted
  29. /// the Java class, the last stage is to bind the all the java.lang.reflect
  30. /// representations to the Slots for dynamic dispatch. We delay this
  31. /// until needed by Method or Field for a reflection invocation
  32. ///
  33. /// Type models sys::Type. Implementation classes are:
  34. /// - ClassType
  35. /// - GenericType (ListType, MapType, FuncType)
  36. /// - NullableType
  37. /// </summary>
  38. public abstract class Type : FanObj, Literal
  39. {
  40. //////////////////////////////////////////////////////////////////////////
  41. // Management
  42. //////////////////////////////////////////////////////////////////////////
  43. public static Type of(object obj)
  44. {
  45. if (obj is FanObj)
  46. return ((FanObj)obj).@typeof();
  47. else
  48. return FanUtil.toFanType(obj.GetType(), true);
  49. }
  50. public static Type find(string sig) { return TypeParser.load(sig, true, null); }
  51. public static Type find(string sig, bool check) { return TypeParser.load(sig, check, null); }
  52. //////////////////////////////////////////////////////////////////////////
  53. // Naming
  54. //////////////////////////////////////////////////////////////////////////
  55. public override Type @typeof() { return Sys.TypeType; }
  56. public abstract Pod pod();
  57. public abstract string name();
  58. public abstract string qname();
  59. public abstract string signature();
  60. //////////////////////////////////////////////////////////////////////////
  61. // Flags
  62. //////////////////////////////////////////////////////////////////////////
  63. public bool isAbstract() { return (flags() & FConst.Abstract) != 0; }
  64. public bool isClass() { return (flags() & (FConst.Enum|FConst.Mixin)) == 0; }
  65. public bool isConst() { return (flags() & FConst.Const) != 0; }
  66. public bool isEnum() { return (flags() & FConst.Enum) != 0; }
  67. public bool isFacet() { return (flags() & FConst.Facet) != 0; }
  68. public bool isFinal() { return (flags() & FConst.Final) != 0; }
  69. public bool isInternal() { return (flags() & FConst.Internal) != 0; }
  70. public bool isMixin() { return (flags() & FConst.Mixin) != 0; }
  71. public bool isPublic() { return (flags() & FConst.Public) != 0; }
  72. public bool isSynthetic() { return (flags() & FConst.Synthetic) != 0; }
  73. internal abstract int flags();
  74. public override object trap(string name, List args)
  75. {
  76. // private undocumented access
  77. if (name == "flags") return Long.valueOf(flags());
  78. return base.trap(name, args);
  79. }
  80. //////////////////////////////////////////////////////////////////////////
  81. // Value Types
  82. //////////////////////////////////////////////////////////////////////////
  83. public virtual bool isVal()
  84. {
  85. return this == Sys.BoolType || this == Sys.IntType || this == Sys.FloatType;
  86. }
  87. //////////////////////////////////////////////////////////////////////////
  88. // Nullable
  89. //////////////////////////////////////////////////////////////////////////
  90. public virtual bool isNullable() { return false; }
  91. public virtual Type toNonNullable() { return this; }
  92. public abstract Type toNullable();
  93. //////////////////////////////////////////////////////////////////////////
  94. // Generics
  95. //////////////////////////////////////////////////////////////////////////
  96. /// <summary>
  97. /// A generic type means that one or more of my slots contain signatures
  98. /// using a generic parameter (such as V or K). Fantom supports three built-in
  99. /// generic types: List, Map, and Method. A generic instance (such as string[])
  100. /// is NOT a generic type (all of its generic parameters have been filled in).
  101. /// User defined generic types are not supported in Fan.
  102. /// </summary>
  103. public virtual bool isGenericType()
  104. {
  105. return this == Sys.ListType || this == Sys.MapType || this == Sys.FuncType;
  106. }
  107. /// <summary>
  108. /// A generic instance is a type which has "instantiated" a generic type
  109. /// and replaced all the generic parameter types with generic argument
  110. /// types. The type string[] is a generic instance of the generic type
  111. /// List (V is replaced with string). A generic instance always has a signature
  112. /// which different from the qname.
  113. /// </summary>
  114. public virtual bool isGenericInstance()
  115. {
  116. return false;
  117. }
  118. /// <summary>
  119. /// Return if this type is a generic parameter (such as V or K) in a
  120. /// generic type (List, Map, or Method). Generic parameters serve
  121. /// as place holders for the parameterization of the generic type.
  122. /// Fantom has a predefined set of generic parameters which are always
  123. /// defined in the sys pod with a one character name.
  124. /// </summary>
  125. public virtual bool isGenericParameter()
  126. {
  127. return pod() == Sys.m_sysPod && name().Length == 1;
  128. }
  129. /// <summary>
  130. /// If this type is a generic parameter (V, L, etc), then return
  131. /// the actual type used in the Java method. For example V is Obj,
  132. /// and L is List. This is the type we actually use when constructing
  133. /// a signature for the invoke opcode.
  134. /// </summary>
  135. public virtual Type getRawType()
  136. {
  137. if (!isGenericParameter()) return this;
  138. if (this == Sys.LType) return Sys.ListType;
  139. if (this == Sys.MType) return Sys.MapType;
  140. if (this is ListType) return Sys.ListType;
  141. if (this is MapType) return Sys.MapType;
  142. if (this is FuncType) return Sys.FuncType;
  143. return Sys.ObjType;
  144. }
  145. public bool isGeneric()
  146. {
  147. return isGenericType();
  148. }
  149. public virtual Map @params()
  150. {
  151. if (noParams == null)
  152. noParams = new Map(Sys.StrType, Sys.TypeType).ro();
  153. return (Map)noParams;
  154. }
  155. public virtual Type parameterize(Map pars)
  156. {
  157. if (this == Sys.ListType)
  158. {
  159. Type v = (Type)pars.get(FanStr.m_ascii['V']);
  160. if (v == null) throw ArgErr.make("List.parameterize - V undefined").val;
  161. return v.toListOf();
  162. }
  163. if (this == Sys.MapType)
  164. {
  165. Type v = (Type)pars.get(FanStr.m_ascii['V']);
  166. Type k = (Type)pars.get(FanStr.m_ascii['K']);
  167. if (v == null) throw ArgErr.make("Map.parameterize - V undefined").val;
  168. if (k == null) throw ArgErr.make("Map.parameterize - K undefined").val;
  169. return new MapType(k, v);
  170. }
  171. if (this == Sys.FuncType)
  172. {
  173. Type r = (Type)pars.get(FanStr.m_ascii['R']);
  174. if (r == null) throw ArgErr.make("Map.parameterize - R undefined").val;
  175. ArrayList p = new ArrayList();
  176. for (int i='A'; i<='H'; ++i)
  177. {
  178. Type x = (Type)pars.get(FanStr.m_ascii[i]);
  179. if (x == null) break;
  180. p.Add(x);
  181. }
  182. return new FuncType((Type[])p.ToArray(System.Type.GetType("Fan.Sys.Type")), r);
  183. }
  184. throw UnsupportedErr.make("not generic: " + this).val;
  185. }
  186. [MethodImpl(MethodImplOptions.Synchronized)]
  187. public Type toListOf()
  188. {
  189. if (m_listOf == null) m_listOf = new ListType(this);
  190. return m_listOf;
  191. }
  192. public List emptyList()
  193. {
  194. if (m_emptyList == null) m_emptyList = (List)new List(this, 0).toImmutable();
  195. return m_emptyList;
  196. }
  197. //////////////////////////////////////////////////////////////////////////
  198. // Slots
  199. //////////////////////////////////////////////////////////////////////////
  200. public abstract List fields();
  201. public abstract List methods();
  202. public abstract List slots();
  203. public Field field(string name) { return (Field)slot(name, true); }
  204. public Field field(string name, bool check) { return (Field)slot(name, check); }
  205. public Method method(string name) { return (Method)slot(name, true); }
  206. public Method method(string name, bool check) { return (Method)slot(name, check); }
  207. public Slot slot(string name) { return slot(name, true); }
  208. public abstract Slot slot(string name, bool check);
  209. public object make() { return make(null); }
  210. public virtual object make(List args)
  211. {
  212. Method make = method("make", false);
  213. if (make != null && make.isPublic())
  214. {
  215. int numArgs = args == null ? 0 : args.sz();
  216. List p = make.@params();
  217. if ((numArgs == p.sz()) ||
  218. (numArgs < p.sz() && ((Param)p.get(numArgs)).hasDefault()))
  219. return make.m_func.callList(args);
  220. }
  221. Slot defVal = slot("defVal", false);
  222. if (defVal is Field) return ((Field)defVal).get(null);
  223. if (defVal is Method) return ((Method)defVal).m_func.callList(null);
  224. throw Err.make("Type missing 'make' or 'defVal' slots: " + this).val;
  225. }
  226. //////////////////////////////////////////////////////////////////////////
  227. // Inheritance
  228. //////////////////////////////////////////////////////////////////////////
  229. public abstract Type @base();
  230. public abstract List mixins();
  231. public abstract List inheritance();
  232. public bool fits(Type type) { return @is(type); }
  233. public abstract bool @is(Type type);
  234. /// <summary>
  235. /// Given a list of objects, compute the most specific type which they all
  236. /// share,or at worst return sys::Obj. This method does not take into
  237. /// account interfaces, only extends class inheritance.
  238. /// </summary>
  239. public static Type common(object[] objs, int n)
  240. {
  241. if (objs.Length == 0) return Sys.ObjType.toNullable();
  242. bool nullable = false;
  243. Type best = null;
  244. for (int i=0; i<n; ++i)
  245. {
  246. object obj = objs[i];
  247. if (obj == null) { nullable = true; continue; }
  248. Type t = @typeof(obj);
  249. if (best == null) { best = t; continue; }
  250. while (!t.@is(best))
  251. {
  252. best = best.@base();
  253. if (best == null) return nullable ? Sys.ObjType.toNullable() : Sys.ObjType;
  254. }
  255. }
  256. if (best == null) best = Sys.ObjType;
  257. return nullable ? best.toNullable() : best;
  258. }
  259. //////////////////////////////////////////////////////////////////////////
  260. // Facets
  261. //////////////////////////////////////////////////////////////////////////
  262. public abstract List facets();
  263. public Facet facet(Type t) { return facet(t, true); }
  264. public abstract Facet facet(Type t, bool c);
  265. public bool hasFacet(Type t) { return facet(t, false) != null; }
  266. //////////////////////////////////////////////////////////////////////////
  267. // Documentation
  268. //////////////////////////////////////////////////////////////////////////
  269. public abstract string doc();
  270. //////////////////////////////////////////////////////////////////////////
  271. // Conversion
  272. //////////////////////////////////////////////////////////////////////////
  273. public override string toStr() { return signature(); }
  274. public string toLocale() { return signature(); }
  275. public void encode(ObjEncoder @out)
  276. {
  277. @out.w(signature()).w("#");
  278. }
  279. //////////////////////////////////////////////////////////////////////////
  280. // Reflection
  281. //////////////////////////////////////////////////////////////////////////
  282. // TODO - needs to be public, since we need to
  283. // call this from FTypeEmit for now
  284. public /*protected*/ virtual Type reflect() { return this; }
  285. public virtual void finish() {}
  286. public abstract bool dotnetRepr();
  287. //////////////////////////////////////////////////////////////////////////
  288. // Fields
  289. //////////////////////////////////////////////////////////////////////////
  290. internal static readonly bool Debug = false;
  291. internal static object noParams;
  292. Type m_listOf; // cached value of toListOf()
  293. List m_emptyList; // cached value of emptyList()
  294. }
  295. }