PageRenderTime 42ms CodeModel.GetById 18ms RepoModel.GetById 0ms app.codeStats 0ms

/src/sys/java/fanx/emit/FFacetEmit.java

https://bitbucket.org/bedlaczech/fan-1.0
Java | 310 lines | 236 code | 38 blank | 36 comment | 38 complexity | 22d70aa7df3a1c563b3c567c740d2539 MD5 | raw file
Possible License(s): CC-BY-SA-3.0
  1. //
  2. // Copyright (c) 2010, Brian Frank and Andy Frank
  3. // Licensed under the Academic Free License version 3.0
  4. //
  5. // History:
  6. // 10 Sep 10 Brian Frank Creation
  7. //
  8. package fanx.emit;
  9. import java.lang.Enum;
  10. import java.util.*;
  11. import java.util.Map.Entry;
  12. import fan.sys.*;
  13. import fan.sys.List;
  14. import fan.sys.Map;
  15. import fanx.fcode.*;
  16. import fanx.serial.*;
  17. import fanx.util.*;
  18. /**
  19. * FFacetEmit is used to emit Fantom facets as Java annotations.
  20. */
  21. class FFacetEmit
  22. implements FConst
  23. {
  24. //////////////////////////////////////////////////////////////////////////
  25. // Factories for Type, Field, and Methods
  26. //////////////////////////////////////////////////////////////////////////
  27. static void emitType(Emitter emit, FPod pod, FAttrs attrs)
  28. {
  29. FFacetEmit x = new FFacetEmit(emit, pod, attrs);
  30. if (x.num == 0) return;
  31. AttrEmit attr = emit.emitAttr("RuntimeVisibleAnnotations");
  32. x.doEmit(attr.info);
  33. }
  34. static void emitField(FieldEmit fe, FPod pod, FAttrs attrs)
  35. {
  36. FFacetEmit x = new FFacetEmit(fe.emit, pod, attrs);
  37. if (x.num == 0) return;
  38. AttrEmit attr = fe.emitAttr("RuntimeVisibleAnnotations");
  39. x.doEmit(attr.info);
  40. }
  41. static void emitMethod(MethodEmit me, FPod pod, FAttrs attrs)
  42. {
  43. FFacetEmit x = new FFacetEmit(me.emit, pod, attrs);
  44. if (x.num == 0) return;
  45. AttrEmit attr = me.emitAttr("RuntimeVisibleAnnotations");
  46. x.doEmit(attr.info);
  47. }
  48. //////////////////////////////////////////////////////////////////////////
  49. // Construction
  50. //////////////////////////////////////////////////////////////////////////
  51. private FFacetEmit(Emitter emit, FPod pod, FAttrs attrs)
  52. {
  53. this.emit = emit;
  54. this.pod = pod;
  55. this.facets = attrs.facets;
  56. this.num = computeNumJavaFacets();
  57. }
  58. private int computeNumJavaFacets()
  59. {
  60. if (facets == null) return 0;
  61. int num = 0;
  62. for (int i=0; i <facets.length; ++i)
  63. if (pod.typeRef(facets[i].type).isFFI()) num++;
  64. return num;
  65. }
  66. //////////////////////////////////////////////////////////////////////////
  67. // RuntimeVisibleAnnotation Generation
  68. //////////////////////////////////////////////////////////////////////////
  69. private void doEmit(Box info)
  70. {
  71. info.u2(num);
  72. try
  73. {
  74. for (int i=0; i <facets.length; ++i)
  75. {
  76. FAttrs.FFacet facet = facets[i];
  77. FTypeRef type = pod.typeRef(facet.type);
  78. if (type.isFFI()) encode(info, type, facet.val);
  79. }
  80. }
  81. catch (Exception e)
  82. {
  83. System.out.println("ERROR: Cannot emit annotations for " + emit.className);
  84. System.out.println(" Facet type: " + curType);
  85. e.printStackTrace();
  86. info.len = 0;
  87. info.u2(0);
  88. }
  89. }
  90. private void encode(Box info, FTypeRef type, String val)
  91. throws Exception
  92. {
  93. // reset type class
  94. this.curType = type;
  95. this.curClass = null;
  96. // parse value into name/value elements
  97. Elem[] elems = parseElems(val);
  98. // annotation type
  99. int cls = emit.cls(type.jname());
  100. info.u2(cls);
  101. info.u2(elems.length);
  102. for (int i=0; i<elems.length; ++i)
  103. {
  104. Elem elem = elems[i];
  105. info.u2(emit.utf(elem.name)); // element_name_index
  106. encodeVal(info, elem); // element_value_pairs
  107. }
  108. }
  109. private void encodeVal(Box info, Elem elem)
  110. throws Exception
  111. {
  112. Object v = elem.val;
  113. if (v instanceof String) { encodeStr(info, elem); return; }
  114. if (v instanceof Boolean) { encodeBool(info, elem); return; }
  115. if (v instanceof Long) { encodeInt(info, elem); return; }
  116. if (v instanceof Double) { encodeFloat(info, elem); return; }
  117. if (v instanceof Enum) { encodeEnum(info, elem); return; }
  118. if (v instanceof Type) { encodeType(info, elem); return; }
  119. if (v instanceof List) { encodeList(info, elem); return; }
  120. throw new RuntimeException("Unsupported annotation element type '" + curType + "." + elem.name + "': " + elem.val.getClass().getName());
  121. }
  122. private void encodeStr(Box info, Elem elem)
  123. {
  124. String val = (String)elem.val;
  125. info.u1('s');
  126. info.u2(emit.utf(val));
  127. }
  128. private void encodeBool(Box info, Elem elem)
  129. {
  130. Boolean val = (Boolean)elem.val;
  131. info.u1('Z');
  132. info.u2(emit.intConst(val.booleanValue() ? 1 : 0));
  133. }
  134. private void encodeInt(Box info, Elem elem)
  135. throws Exception
  136. {
  137. Long val = (Long)elem.val;
  138. Class type = elem.type();
  139. if (type == int.class)
  140. {
  141. info.u1('I');
  142. info.u2(emit.intConst(Integer.valueOf(val.intValue())));
  143. }
  144. else if (type == short.class)
  145. {
  146. info.u1('S');
  147. info.u2(emit.intConst(Integer.valueOf(val.intValue())));
  148. }
  149. else if (type == byte.class)
  150. {
  151. info.u1('B');
  152. info.u2(emit.intConst(Integer.valueOf(val.intValue())));
  153. }
  154. else
  155. {
  156. info.u1('J');
  157. info.u2(emit.longConst(val));
  158. }
  159. }
  160. private void encodeFloat(Box info, Elem elem)
  161. throws Exception
  162. {
  163. Double val = (Double)elem.val;
  164. Class type = elem.type();
  165. if (type == float.class)
  166. {
  167. info.u1('F');
  168. info.u2(emit.floatConst(Float.valueOf(val.floatValue())));
  169. }
  170. else
  171. {
  172. info.u1('D');
  173. info.u2(emit.doubleConst(val));
  174. }
  175. }
  176. private void encodeEnum(Box info, Elem elem)
  177. throws Exception
  178. {
  179. Enum e = (Enum)elem.val;
  180. info.u1('e');
  181. info.u2(emit.utf(e.getClass().getName()));
  182. info.u2(emit.utf(e.toString()));
  183. }
  184. private void encodeType(Box info, Elem elem)
  185. throws Exception
  186. {
  187. Type t = (Type)elem.val;
  188. info.u1('c');
  189. info.u2(emit.utf(FanUtil.toJavaMemberSig(t)));
  190. }
  191. private void encodeList(Box info, Elem elem)
  192. throws Exception
  193. {
  194. List list = (List)elem.val;
  195. Class of = elem.type().getComponentType();
  196. info.u1('[');
  197. info.u2(list.sz());
  198. for (int i=0; i<list.sz(); ++i)
  199. encodeVal(info, new Elem(elem.name, list.get(i), of));
  200. }
  201. //////////////////////////////////////////////////////////////////////////
  202. // Parsing
  203. //////////////////////////////////////////////////////////////////////////
  204. private Elem[] parseElems(String str)
  205. throws Exception
  206. {
  207. // empty string is a marker annotation
  208. if (str.length() == 0) return noElems;
  209. // Fantom compiler encodes FFI facets as map string name/value pairs
  210. Map map = (Map)ObjDecoder.decode(str);
  211. Elem[] acc = new Elem[map.sz()];
  212. int n = 0;
  213. Iterator it = map.pairsIterator();
  214. while (it.hasNext())
  215. {
  216. Entry e = (Entry)it.next();
  217. String name = (String)e.getKey();
  218. Object val = e.getValue();
  219. acc[n++] = new Elem(name, val);
  220. }
  221. return acc;
  222. }
  223. private Object parseElemVal(String name, String val)
  224. throws Exception
  225. {
  226. try
  227. {
  228. return ObjDecoder.decode(val);
  229. }
  230. catch (Exception e)
  231. {
  232. throw new Exception("Cannot parse " + curType + "." + name + " = " + val + "\n " + e, e);
  233. }
  234. }
  235. //////////////////////////////////////////////////////////////////////////
  236. // Utils
  237. //////////////////////////////////////////////////////////////////////////
  238. Class curClass()
  239. throws Exception
  240. {
  241. if (curClass == null)
  242. curClass = Env.cur().loadJavaClass(curType.jname().replace("/", "."));
  243. return curClass;
  244. }
  245. //////////////////////////////////////////////////////////////////////////
  246. // Elem
  247. //////////////////////////////////////////////////////////////////////////
  248. class Elem
  249. {
  250. Elem(String n, Object v) { name = n; val = v; }
  251. Elem(String n, Object v, Class t) { name = n; val = v; type = t; }
  252. Class type() throws Exception
  253. {
  254. if (type == null)
  255. type = curClass().getMethod(name, new Class[0]).getReturnType();
  256. return type;
  257. }
  258. String name;
  259. Object val;
  260. Class type;
  261. }
  262. //////////////////////////////////////////////////////////////////////////
  263. // Fields
  264. //////////////////////////////////////////////////////////////////////////
  265. static final Elem[] noElems = new Elem[0];
  266. private final Emitter emit; // class emitter
  267. private final FPod pod; // pod being emitted
  268. private final FAttrs.FFacet[] facets; // all the facets (java and non-java)
  269. private final int num; // num of Java annotations in facets
  270. private FTypeRef curType; // current facet type
  271. private Class curClass; // current facet class
  272. }