PageRenderTime 47ms CodeModel.GetById 23ms RepoModel.GetById 0ms app.codeStats 0ms

/src/sys/java/fan/sys/Type.java

https://bitbucket.org/bedlaczech/fan-1.0
Java | 363 lines | 203 code | 64 blank | 96 comment | 84 complexity | b88e45570189e7cbe2e8f13220c58152 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. // 2 Dec 05 Brian Frank Creation
  7. //
  8. package fan.sys;
  9. import java.io.*;
  10. import java.lang.reflect.*;
  11. import java.util.ArrayList;
  12. import java.util.HashMap;
  13. import java.util.Iterator;
  14. import java.util.Map.Entry;
  15. import fanx.fcode.*;
  16. import fanx.emit.*;
  17. import fanx.serial.*;
  18. import fanx.util.*;
  19. /**
  20. * Type models sys::Type. Implementation classes are:
  21. * - ClassType
  22. * - GenericType (ListType, MapType, FuncType)
  23. * - NullableType
  24. */
  25. public abstract class Type
  26. extends FanObj
  27. implements Literal
  28. {
  29. //////////////////////////////////////////////////////////////////////////
  30. // Management
  31. //////////////////////////////////////////////////////////////////////////
  32. public static Type of(Object obj)
  33. {
  34. if (obj instanceof FanObj)
  35. return ((FanObj)obj).typeof();
  36. else
  37. return FanUtil.toFanType(obj.getClass(), true);
  38. }
  39. public static Type find(String sig) { return TypeParser.load(sig, true, null); }
  40. public static Type find(String sig, boolean checked) { return TypeParser.load(sig, checked, null); }
  41. //////////////////////////////////////////////////////////////////////////
  42. // Naming
  43. //////////////////////////////////////////////////////////////////////////
  44. public Type typeof() { return Sys.TypeType; }
  45. public String podName() { return pod().name(); }
  46. public abstract Pod pod();
  47. public abstract String name();
  48. public abstract String qname();
  49. public abstract String signature();
  50. //////////////////////////////////////////////////////////////////////////
  51. // Flags
  52. //////////////////////////////////////////////////////////////////////////
  53. public final boolean isAbstract() { return (flags() & FConst.Abstract) != 0; }
  54. public final boolean isClass() { return (flags() & (FConst.Enum|FConst.Mixin)) == 0; }
  55. public final boolean isConst() { return (flags() & FConst.Const) != 0; }
  56. public final boolean isEnum() { return (flags() & FConst.Enum) != 0; }
  57. public final boolean isFacet() { return (flags() & FConst.Facet) != 0; }
  58. public final boolean isFinal() { return (flags() & FConst.Final) != 0; }
  59. public final boolean isInternal() { return (flags() & FConst.Internal) != 0; }
  60. public final boolean isMixin() { return (flags() & FConst.Mixin) != 0; }
  61. public final boolean isNative() { return (flags() & FConst.Native) != 0; }
  62. public final boolean isPublic() { return (flags() & FConst.Public) != 0; }
  63. public final boolean isSynthetic() { return (flags() & FConst.Synthetic) != 0; }
  64. abstract int flags();
  65. public Object trap(String name, List args)
  66. {
  67. // private undocumented access
  68. if (name.equals("flags")) return Long.valueOf(flags());
  69. if (name.equals("toClass")) return toClass();
  70. if (name.equals("finish")) { finish(); return this; }
  71. return super.trap(name, args);
  72. }
  73. //////////////////////////////////////////////////////////////////////////
  74. // Value Types
  75. //////////////////////////////////////////////////////////////////////////
  76. public boolean isVal()
  77. {
  78. return this == Sys.BoolType || this == Sys.IntType || this == Sys.FloatType;
  79. }
  80. //////////////////////////////////////////////////////////////////////////
  81. // Nullable
  82. //////////////////////////////////////////////////////////////////////////
  83. public boolean isNullable() { return false; }
  84. public Type toNonNullable() { return this; }
  85. public abstract Type toNullable();
  86. //////////////////////////////////////////////////////////////////////////
  87. // Generics
  88. //////////////////////////////////////////////////////////////////////////
  89. /**
  90. * A generic type means that one or more of my slots contain signatures
  91. * using a generic parameter (such as V or K). Fantom supports three built-in
  92. * generic types: List, Map, and Func. A generic instance (such as Str[])
  93. * is NOT a generic type (all of its generic parameters have been filled in).
  94. * User defined generic types are not supported in Fan.
  95. */
  96. public boolean isGenericType()
  97. {
  98. return this == Sys.ListType || this == Sys.MapType || this == Sys.FuncType;
  99. }
  100. /**
  101. * A generic instance is a type which has "instantiated" a generic type
  102. * and replaced all the generic parameter types with generic argument
  103. * types. The type Str[] is a generic instance of the generic type
  104. * List (V is replaced with Str). A generic instance always has a signature
  105. * which different from the qname.
  106. */
  107. public boolean isGenericInstance()
  108. {
  109. return false;
  110. }
  111. /**
  112. * Return if this type is a generic parameter (such as V or K) in a
  113. * generic type (List, Map, or Method). Generic parameters serve
  114. * as place holders for the parameterization of the generic type.
  115. * Fantom has a predefined set of generic parameters which are always
  116. * defined in the sys pod with a one character name.
  117. */
  118. public boolean isGenericParameter()
  119. {
  120. return pod() == Sys.sysPod && name().length() == 1;
  121. }
  122. /*
  123. * If this type is a generic parameter (V, L, etc), then return
  124. * the actual type used in the Java method. For example V is Obj,
  125. * and L is List. This is the type we actually use when constructing
  126. * a signature for the invoke opcode.
  127. */
  128. public Type getRawType()
  129. {
  130. if (!isGenericParameter()) return this;
  131. if (this == Sys.LType) return Sys.ListType;
  132. if (this == Sys.MType) return Sys.MapType;
  133. if (this instanceof ListType) return Sys.ListType;
  134. if (this instanceof MapType) return Sys.MapType;
  135. if (this instanceof FuncType) return Sys.FuncType;
  136. return Sys.ObjType;
  137. }
  138. public final boolean isGeneric()
  139. {
  140. return isGenericType();
  141. }
  142. public Map params()
  143. {
  144. if (noParams == null) noParams = Sys.emptyStrTypeMap;
  145. return (Map)noParams;
  146. }
  147. public Type parameterize(Map params)
  148. {
  149. if (this == Sys.ListType)
  150. {
  151. Type v = (Type)params.get("V");
  152. if (v == null) throw ArgErr.make("List.parameterize - V undefined");
  153. return v.toListOf();
  154. }
  155. if (this == Sys.MapType)
  156. {
  157. Type v = (Type)params.get("V");
  158. Type k = (Type)params.get("K");
  159. if (v == null) throw ArgErr.make("Map.parameterize - V undefined");
  160. if (k == null) throw ArgErr.make("Map.parameterize - K undefined");
  161. return new MapType(k, v);
  162. }
  163. if (this == Sys.FuncType)
  164. {
  165. Type r = (Type)params.get("R");
  166. if (r == null) throw ArgErr.make("Map.parameterize - R undefined");
  167. ArrayList p = new ArrayList();
  168. for (int i='A'; i<='H'; ++i)
  169. {
  170. Type x = (Type)params.get(FanStr.ascii[i]);
  171. if (x == null) break;
  172. p.add(x);
  173. }
  174. return new FuncType((Type[])p.toArray(new Type[p.size()]), r);
  175. }
  176. throw UnsupportedErr.make("not generic: " + this);
  177. }
  178. public final synchronized Type toListOf()
  179. {
  180. if (listOf == null) listOf = new ListType(this);
  181. return listOf;
  182. }
  183. public final List emptyList()
  184. {
  185. if (emptyList == null) emptyList = (List)new List(this, 0).toImmutable();
  186. return emptyList;
  187. }
  188. //////////////////////////////////////////////////////////////////////////
  189. // Slots
  190. //////////////////////////////////////////////////////////////////////////
  191. public abstract List fields();
  192. public abstract List methods();
  193. public abstract List slots();
  194. public final Field field(String name) { return field(name, true); }
  195. public Field field(String name, boolean checked) { return (Field)slot(name, checked); }
  196. public final Method method(String name) { return method(name, true); }
  197. public Method method(String name, boolean checked) { return (Method)slot(name, checked); }
  198. public final Slot slot(String name) { return slot(name, true); }
  199. public abstract Slot slot(String name, boolean checked);
  200. public final Object make() { return make(null); }
  201. public Object make(List args)
  202. {
  203. Method make = method("make", false);
  204. if (make != null && make.isPublic())
  205. {
  206. int numArgs = args == null ? 0 : args.sz();
  207. List params = make.params();
  208. if ((numArgs == params.sz()) ||
  209. (numArgs < params.sz() && ((Param)params.get(numArgs)).hasDefault()))
  210. return make.func.callList(args);
  211. }
  212. Slot defVal = slot("defVal", false);
  213. if (defVal != null && defVal.isPublic())
  214. {
  215. if (defVal instanceof Field) return ((Field)defVal).get(null);
  216. if (defVal instanceof Method) return ((Method)defVal).func.callList(null);
  217. }
  218. throw Err.make("Type missing 'make' or 'defVal' slots: " + this);
  219. }
  220. //////////////////////////////////////////////////////////////////////////
  221. // Inheritance
  222. //////////////////////////////////////////////////////////////////////////
  223. public abstract Type base();
  224. public abstract List mixins();
  225. public abstract List inheritance();
  226. public final boolean fits(Type type) { return is(type); }
  227. public abstract boolean is(Type type);
  228. /**
  229. * Given a list of objects, compute the most specific type which they all
  230. * share,or at worst return sys::Obj?. This method does not take into
  231. * account interfaces, only extends class inheritance.
  232. */
  233. public static Type common(Object[] objs, int n)
  234. {
  235. if (objs.length == 0) return Sys.ObjType.toNullable();
  236. boolean nullable = false;
  237. Type best = null;
  238. for (int i=0; i<n; ++i)
  239. {
  240. Object obj = objs[i];
  241. if (obj == null) { nullable = true; continue; }
  242. Type t = typeof(obj);
  243. if (best == null) { best = t; continue; }
  244. while (!t.is(best))
  245. {
  246. best = best.base();
  247. if (best == null) return nullable ? Sys.ObjType.toNullable() : Sys.ObjType;
  248. }
  249. }
  250. if (best == null) best = Sys.ObjType;
  251. return nullable ? best.toNullable() : best;
  252. }
  253. //////////////////////////////////////////////////////////////////////////
  254. // Facets
  255. //////////////////////////////////////////////////////////////////////////
  256. public abstract List facets();
  257. public final Facet facet(Type t) { return facet(t, true); }
  258. public abstract Facet facet(Type t, boolean c);
  259. public final boolean hasFacet(Type t) { return facet(t, false) != null; }
  260. //////////////////////////////////////////////////////////////////////////
  261. // Documentation
  262. //////////////////////////////////////////////////////////////////////////
  263. public abstract String doc();
  264. //////////////////////////////////////////////////////////////////////////
  265. // Conversion
  266. //////////////////////////////////////////////////////////////////////////
  267. public String toStr() { return signature(); }
  268. public String toLocale() { return signature(); }
  269. public void encode(ObjEncoder out)
  270. {
  271. out.w(signature()).w("#");
  272. }
  273. //////////////////////////////////////////////////////////////////////////
  274. // Reflection
  275. //////////////////////////////////////////////////////////////////////////
  276. protected Type reflect() { return this; }
  277. public void finish() {}
  278. /**
  279. * Return if this is a JavaType which represents a Java
  280. * class imported into the Fantom type system via the Java FFI.
  281. */
  282. public final boolean isJava() { return this instanceof JavaType; }
  283. /**
  284. * Return if the Fantom Type is represented as a Java class
  285. * such as sys::Int as java.lang.Long.
  286. */
  287. public abstract boolean javaRepr();
  288. /**
  289. * Get the Java class which represents this type.
  290. */
  291. public abstract Class toClass();
  292. //////////////////////////////////////////////////////////////////////////
  293. // Fields
  294. //////////////////////////////////////////////////////////////////////////
  295. static final boolean Debug = false;
  296. static Object noParams;
  297. Type listOf; // cached value of toListOf()
  298. List emptyList; // cached value of emptyList()
  299. }