PageRenderTime 47ms CodeModel.GetById 22ms RepoModel.GetById 1ms app.codeStats 0ms

/src/sys/dotnet/fan/sys/Func.cs

https://bitbucket.org/bedlaczech/fan-1.0
C# | 403 lines | 322 code | 47 blank | 34 comment | 21 complexity | 06aa2d14a37bd9aeaf4e95a5a1e203ed 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. // 23 Jul 07 Andy Frank Creation
  7. //
  8. namespace Fan.Sys
  9. {
  10. /// <summary>
  11. /// Func models an executable subroutine.
  12. /// </summary>
  13. public abstract class Func : FanObj
  14. {
  15. //////////////////////////////////////////////////////////////////////////
  16. // Methods
  17. //////////////////////////////////////////////////////////////////////////
  18. public override Type @typeof() { return Sys.FuncType; }
  19. public abstract Type returns();
  20. public abstract long arity();
  21. public abstract List @params();
  22. public override abstract bool isImmutable();
  23. public abstract Method method();
  24. public abstract object callList(List args);
  25. public abstract object callOn(object target, List args);
  26. public abstract object call();
  27. public abstract object call(object a);
  28. public abstract object call(object a, object b);
  29. public abstract object call(object a, object b, object c);
  30. public abstract object call(object a, object b, object c, object d);
  31. public abstract object call(object a, object b, object c, object d, object e);
  32. public abstract object call(object a, object b, object c, object d, object e, object f);
  33. public abstract object call(object a, object b, object c, object d, object e, object f, object g);
  34. public abstract object call(object a, object b, object c, object d, object e, object f, object g, object h);
  35. public override object toImmutable()
  36. {
  37. if (isImmutable()) return this;
  38. throw NotImmutableErr.make().val;
  39. }
  40. // Hooks used by compiler to generate runtime const field checks for it-blocks
  41. public virtual void enterCtor(object o) {}
  42. public virtual void exitCtor() {}
  43. public virtual void checkInCtor(object o) {}
  44. //////////////////////////////////////////////////////////////////////////
  45. // Indirect
  46. //////////////////////////////////////////////////////////////////////////
  47. public static readonly int MaxIndirectParams = 8; // max callX()
  48. /// <summary>
  49. /// Indirect is the base class for the IndirectX classes, which are
  50. /// used as the common base classes for closures and general purpose
  51. /// functions. An Indirect method takes a funcType for it's type,
  52. /// and also extends Func for the callList() implementations.
  53. /// </summary>
  54. public abstract class Indirect : Func
  55. {
  56. protected Indirect(FuncType type) { this.m_type = type; }
  57. public string name() { return GetType().Name; }
  58. public override Type @typeof() { return m_type; }
  59. public override string toStr() { return m_type.signature(); }
  60. public override bool isImmutable() { return false; }
  61. public override Method method() { return null; }
  62. public Err.Val tooFewArgs(int given) { return Err.make("Too few arguments: " + given + " < " + m_type.m_params.Length).val; }
  63. public override Type returns() { return m_type.m_ret; }
  64. public override long arity() { return m_type.m_params.Length; }
  65. public override List @params()
  66. {
  67. // lazily build params list
  68. if (m_params == null) m_params = m_type.toMethodParams().ro();
  69. return m_params;
  70. }
  71. public override object callOn(object obj, List args)
  72. {
  73. List flat = args.dup();
  74. flat.insert(0, obj);
  75. return callList(flat);
  76. }
  77. FuncType m_type;
  78. private List m_params;
  79. }
  80. public abstract class Indirect0 : Indirect
  81. {
  82. protected Indirect0(FuncType type) : base(type) {}
  83. protected Indirect0() : base(type0) {}
  84. public override object callList(List args) { return call(); }
  85. public override abstract object call();
  86. public override object call(object a) { return call(); }
  87. public override object call(object a, object b) { return call(); }
  88. public override object call(object a, object b, object c) { return call(); }
  89. public override object call(object a, object b, object c, object d) { return call(); }
  90. public override object call(object a, object b, object c, object d, object e) { return call(); }
  91. public override object call(object a, object b, object c, object d, object e, object f) { return call(); }
  92. public override object call(object a, object b, object c, object d, object e, object f, object g) { return call(); }
  93. public override object call(object a, object b, object c, object d, object e, object f, object g, object h) { return call(); }
  94. }
  95. public abstract class Indirect1 : Indirect
  96. {
  97. protected Indirect1(FuncType type) : base(type) {}
  98. protected Indirect1() : base(type1) {}
  99. public override object callList(List args) { return call(args.get(0)); }
  100. public override object call() { throw tooFewArgs(0); }
  101. public override abstract object call(object a);
  102. public override object call(object a, object b) { return call(a); }
  103. public override object call(object a, object b, object c) { return call(a); }
  104. public override object call(object a, object b, object c, object d) { return call(a); }
  105. public override object call(object a, object b, object c, object d, object e) { return call(a); }
  106. public override object call(object a, object b, object c, object d, object e, object f) { return call(a); }
  107. public override object call(object a, object b, object c, object d, object e, object f, object g) { return call(a); }
  108. public override object call(object a, object b, object c, object d, object e, object f, object g, object h) { return call(a); }
  109. public override void enterCtor(object o) { this.m_inCtor = o; }
  110. public override void exitCtor() { this.m_inCtor = null; }
  111. public override void checkInCtor(object it)
  112. {
  113. if (it == m_inCtor) return;
  114. string msg = it == null ? "null" : FanObj.@typeof(it).qname();
  115. throw ConstErr.make(msg).val;
  116. }
  117. internal object m_inCtor;
  118. }
  119. public abstract class Indirect2 : Indirect
  120. {
  121. protected Indirect2(FuncType type) : base(type) {}
  122. protected Indirect2() : base(type2) {}
  123. public override object callList(List args) { return call(args.get(0), args.get(1)); }
  124. public override object call() { throw tooFewArgs(0); }
  125. public override object call(object a) { throw tooFewArgs(1); }
  126. public override abstract object call(object a, object b);
  127. public override object call(object a, object b, object c) { return call(a, b); }
  128. public override object call(object a, object b, object c, object d) { return call(a, b); }
  129. public override object call(object a, object b, object c, object d, object e) { return call(a, b); }
  130. public override object call(object a, object b, object c, object d, object e, object f) { return call(a, b); }
  131. public override object call(object a, object b, object c, object d, object e, object f, object g) { return call(a, b); }
  132. public override object call(object a, object b, object c, object d, object e, object f, object g, object h) { return call(a, b); }
  133. }
  134. public abstract class Indirect3 : Indirect
  135. {
  136. protected Indirect3(FuncType type) : base(type) {}
  137. protected Indirect3() : base(type3) {}
  138. public override object callList(List args) { return call(args.get(0), args.get(1), args.get(2)); }
  139. public override object call() { throw tooFewArgs(0); }
  140. public override object call(object a) { throw tooFewArgs(1); }
  141. public override object call(object a, object b) { throw tooFewArgs(2); }
  142. public override abstract object call(object a, object b, object c);
  143. public override object call(object a, object b, object c, object d) { return call(a, b, c); }
  144. public override object call(object a, object b, object c, object d, object e) { return call(a, b, c); }
  145. public override object call(object a, object b, object c, object d, object e, object f) { return call(a, b, c); }
  146. public override object call(object a, object b, object c, object d, object e, object f, object g) { return call(a, b, c); }
  147. public override object call(object a, object b, object c, object d, object e, object f, object g, object h) { return call(a, b, c); }
  148. }
  149. public abstract class Indirect4 : Indirect
  150. {
  151. protected Indirect4(FuncType type) : base(type) {}
  152. protected Indirect4() : base(type4) {}
  153. public override object callList(List args) { return call(args.get(0), args.get(1), args.get(2), args.get(3)); }
  154. public override object call() { throw tooFewArgs(0); }
  155. public override object call(object a) { throw tooFewArgs(1); }
  156. public override object call(object a, object b) { throw tooFewArgs(2); }
  157. public override object call(object a, object b, object c) { throw tooFewArgs(3); }
  158. public override abstract object call(object a, object b, object c, object d);
  159. public override object call(object a, object b, object c, object d, object e) { return call(a, b, c, d); }
  160. public override object call(object a, object b, object c, object d, object e, object f) { return call(a, b, c, d); }
  161. public override object call(object a, object b, object c, object d, object e, object f, object g) { return call(a, b, c, d); }
  162. public override object call(object a, object b, object c, object d, object e, object f, object g, object h) { return call(a, b, c, d); }
  163. }
  164. public abstract class Indirect5 : Indirect
  165. {
  166. protected Indirect5(FuncType type) : base(type) {}
  167. public override object callList(List args) { return call(args.get(0), args.get(1), args.get(2), args.get(3), args.get(4)); }
  168. public override object call() { throw tooFewArgs(0); }
  169. public override object call(object a) { throw tooFewArgs(1); }
  170. public override object call(object a, object b) { throw tooFewArgs(2); }
  171. public override object call(object a, object b, object c) { throw tooFewArgs(3); }
  172. public override object call(object a, object b, object c, object d) { throw tooFewArgs(4); }
  173. public override abstract object call(object a, object b, object c, object d, object e);
  174. public override object call(object a, object b, object c, object d, object e, object f) { return call(a, b, c, d, e); }
  175. public override object call(object a, object b, object c, object d, object e, object f, object g) { return call(a, b, c, d, e); }
  176. public override object call(object a, object b, object c, object d, object e, object f, object g, object h) { return call(a, b, c, d, e); }
  177. }
  178. public abstract class Indirect6 : Indirect
  179. {
  180. protected Indirect6(FuncType type) : base(type) {}
  181. public override object callList(List args) { return call(args.get(0), args.get(1), args.get(2), args.get(3), args.get(4), args.get(5)); }
  182. public override object call() { throw tooFewArgs(0); }
  183. public override object call(object a) { throw tooFewArgs(1); }
  184. public override object call(object a, object b) { throw tooFewArgs(2); }
  185. public override object call(object a, object b, object c) { throw tooFewArgs(3); }
  186. public override object call(object a, object b, object c, object d) { throw tooFewArgs(4); }
  187. public override object call(object a, object b, object c, object d, object e) { throw tooFewArgs(5); }
  188. public override abstract object call(object a, object b, object c, object d, object e, object f);
  189. public override object call(object a, object b, object c, object d, object e, object f, object g) { return call(a, b, c, d, e, f); }
  190. public override object call(object a, object b, object c, object d, object e, object f, object g, object h) { return call(a, b, c, d, e, f); }
  191. }
  192. public abstract class Indirect7 : Indirect
  193. {
  194. protected Indirect7(FuncType type) : base(type) {}
  195. public override object callList(List args) { return call(args.get(0), args.get(1), args.get(2), args.get(3), args.get(4), args.get(5), args.get(6)); }
  196. public override object call() { throw tooFewArgs(0); }
  197. public override object call(object a) { throw tooFewArgs(1); }
  198. public override object call(object a, object b) { throw tooFewArgs(2); }
  199. public override object call(object a, object b, object c) { throw tooFewArgs(3); }
  200. public override object call(object a, object b, object c, object d) { throw tooFewArgs(4); }
  201. public override object call(object a, object b, object c, object d, object e) { throw tooFewArgs(5); }
  202. public override object call(object a, object b, object c, object d, object e, object f) { throw tooFewArgs(6); }
  203. public override abstract object call(object a, object b, object c, object d, object e, object f, object g);
  204. public override object call(object a, object b, object c, object d, object e, object f, object g, object h) { return call(a, b, c, d, e, f, g); }
  205. }
  206. public abstract class Indirect8 : Indirect
  207. {
  208. protected Indirect8(FuncType type) : base(type) {}
  209. public override object callList(List args) { return call(args.get(0), args.get(1), args.get(2), args.get(3), args.get(4), args.get(5), args.get(6), args.get(7)); }
  210. public override object call() { throw tooFewArgs(0); }
  211. public override object call(object a) { throw tooFewArgs(1); }
  212. public override object call(object a, object b) { throw tooFewArgs(2); }
  213. public override object call(object a, object b, object c) { throw tooFewArgs(3); }
  214. public override object call(object a, object b, object c, object d) { throw tooFewArgs(4); }
  215. public override object call(object a, object b, object c, object d, object e) { throw tooFewArgs(5); }
  216. public override object call(object a, object b, object c, object d, object e, object f) { throw tooFewArgs(6); }
  217. public override object call(object a, object b, object c, object d, object e, object f, object g) { throw tooFewArgs(7); }
  218. public override abstract object call(object a, object b, object c, object d, object e, object f, object g, object h);
  219. }
  220. public abstract class IndirectX : Indirect
  221. {
  222. protected IndirectX(FuncType type) : base(type) {}
  223. public override abstract object callList(List args);
  224. public override object call() { throw tooFewArgs(0); }
  225. public override object call(object a) { throw tooFewArgs(1); }
  226. public override object call(object a, object b) { throw tooFewArgs(2); }
  227. public override object call(object a, object b, object c) { throw tooFewArgs(3); }
  228. public override object call(object a, object b, object c, object d) { throw tooFewArgs(4); }
  229. public override object call(object a, object b, object c, object d, object e) { throw tooFewArgs(5); }
  230. public override object call(object a, object b, object c, object d, object e, object f) { throw tooFewArgs(6); }
  231. public override object call(object a, object b, object c, object d, object e, object f, object g) { throw tooFewArgs(7); }
  232. public override object call(object a, object b, object c, object d, object e, object f, object g, object h) { throw tooFewArgs(8); }
  233. }
  234. //////////////////////////////////////////////////////////////////////////
  235. // Retype
  236. //////////////////////////////////////////////////////////////////////////
  237. public Func retype(Type t)
  238. {
  239. try
  240. {
  241. return new Wrapper((FuncType)t, this);
  242. }
  243. catch (System.InvalidCastException)
  244. {
  245. throw ArgErr.make("Not a Func type: " + t).val;
  246. }
  247. }
  248. internal class Wrapper : Indirect
  249. {
  250. internal Wrapper(FuncType t, Func orig) : base(t) { m_orig = orig; }
  251. public override bool isImmutable() { return m_orig.isImmutable(); }
  252. public override Method method() { return m_orig.method(); }
  253. public override object callOn(object target, List args) { return m_orig.callOn(target, args); }
  254. public override object callList(List args) { return m_orig.callList(args); }
  255. public override object call() { return m_orig.call(); }
  256. public override object call(object a) { return m_orig.call(a); }
  257. public override object call(object a, object b) { return m_orig.call(a, b); }
  258. public override object call(object a, object b, object c) { return m_orig.call(a, b, c); }
  259. public override object call(object a, object b, object c, object d) { return m_orig.call(a, b, c, d); }
  260. public override object call(object a, object b, object c, object d, object e) { return m_orig.call(a, b, c, d, e); }
  261. public override object call(object a, object b, object c, object d, object e, object f) { return m_orig.call(a, b, c, d, e, f); }
  262. public override object call(object a, object b, object c, object d, object e, object f, object g) { return m_orig.call(a, b, c, d, e, f, g); }
  263. public override object call(object a, object b, object c, object d, object e, object f, object g, object h) { return m_orig.call(a, b, c, d, e, f, g, h); }
  264. Func m_orig;
  265. }
  266. //////////////////////////////////////////////////////////////////////////
  267. // Bind
  268. //////////////////////////////////////////////////////////////////////////
  269. public Func bind(List args)
  270. {
  271. if (args.sz() == 0) return this;
  272. if (args.sz() > @params().sz()) throw ArgErr.make("args.size > params.size").val;
  273. Type[] newParams = new Type[@params().sz()-args.sz()];
  274. for (int i=0; i<newParams.Length; ++i)
  275. newParams[i] = ((Param)@params().get(args.sz()+i)).m_type;
  276. FuncType newType = new FuncType(newParams, this.returns());
  277. return new BindFunc(newType, this, args);
  278. }
  279. internal class BindFunc : Indirect
  280. {
  281. internal BindFunc (FuncType type, Func orig, List bound)
  282. : base(type)
  283. {
  284. this.m_orig = orig;
  285. this.m_bound = bound.ro();
  286. }
  287. public override Method method() { return null; }
  288. public override bool isImmutable()
  289. {
  290. if (this.m_isImmutable == null)
  291. {
  292. bool isImmutable = false;
  293. if (m_orig.isImmutable())
  294. {
  295. isImmutable = true;
  296. for (int i=0; i<m_bound.sz(); ++i)
  297. {
  298. object obj = m_bound.get(i);
  299. if (obj != null && !FanObj.isImmutable(obj))
  300. { isImmutable = false; break; }
  301. }
  302. }
  303. this.m_isImmutable = Boolean.valueOf(isImmutable);
  304. }
  305. return this.m_isImmutable.booleanValue();
  306. }
  307. // this isn't a very optimized implementation
  308. public override object call() { return callList(new List(Sys.ObjType, new object[] {})); }
  309. public override object call(object a) { return callList(new List(Sys.ObjType, new object[] {a})); }
  310. public override object call(object a, object b) { return callList(new List(Sys.ObjType, new object[] {a,b})); }
  311. public override object call(object a, object b, object c) { return callList(new List(Sys.ObjType, new object[] {a,b,c})); }
  312. public override object call(object a, object b, object c, object d) { return callList(new List(Sys.ObjType, new object[] {a,b,c,d})); }
  313. public override object call(object a, object b, object c, object d, object e) { return callList(new List(Sys.ObjType, new object[] {a,b,c,d,e})); }
  314. public override object call(object a, object b, object c, object d, object e, object f) { return callList(new List(Sys.ObjType, new object[] {a,b,c,d,e,f})); }
  315. public override object call(object a, object b, object c, object d, object e, object f, object g) { return callList(new List(Sys.ObjType, new object[] {a,b,c,d,e,f,g})); }
  316. public override object call(object a, object b, object c, object d, object e, object f, object g, object h) { return callList(new List(Sys.ObjType, new object[] {a,b,c,d,e,f,g,h})); }
  317. public override object callList(List args)
  318. {
  319. int origReq = m_orig.@params().sz();
  320. int haveSize = m_bound.sz() + args.sz();
  321. Method m = m_orig.method();
  322. if (m != null)
  323. {
  324. origReq = m.minParams();
  325. if (haveSize > origReq) origReq = haveSize;
  326. }
  327. if (origReq <= m_bound.sz()) return m_orig.callList(m_bound);
  328. object[] temp = new object[haveSize];
  329. m_bound.copyInto(temp, 0, m_bound.sz());
  330. args.copyInto(temp, m_bound.sz(), temp.Length-m_bound.sz());
  331. return m_orig.callList(new List(Sys.ObjType, temp));
  332. }
  333. public override object callOn(object obj, List args)
  334. {
  335. int origSize = m_orig.@params().sz();
  336. object[] temp = new object[origSize];
  337. m_bound.copyInto(temp, 0, m_bound.sz());
  338. temp[m_bound.sz()] = obj;
  339. args.copyInto(temp, m_bound.sz()+1, temp.Length-m_bound.sz()-1);
  340. return m_orig.callList(new List(Sys.ObjType, temp));
  341. }
  342. private readonly Func m_orig;
  343. private readonly List m_bound;
  344. private Boolean m_isImmutable;
  345. }
  346. //////////////////////////////////////////////////////////////////////////
  347. // Fields
  348. //////////////////////////////////////////////////////////////////////////
  349. internal static readonly object[] noArgs = new object[0];
  350. internal static readonly FuncType type0 = new FuncType(new Type[] {}, Sys.ObjType);
  351. internal static readonly FuncType type1 = new FuncType(new Type[] { Sys.ObjType }, Sys.ObjType);
  352. internal static readonly FuncType type2 = new FuncType(new Type[] { Sys.ObjType, Sys.ObjType }, Sys.ObjType);
  353. internal static readonly FuncType type3 = new FuncType(new Type[] { Sys.ObjType, Sys.ObjType, Sys.ObjType }, Sys.ObjType);
  354. internal static readonly FuncType type4 = new FuncType(new Type[] { Sys.ObjType, Sys.ObjType, Sys.ObjType, Sys.ObjType }, Sys.ObjType);
  355. }
  356. }