PageRenderTime 49ms CodeModel.GetById 25ms RepoModel.GetById 0ms app.codeStats 0ms

/ExprObjModel/Using.cs

http://swscheme.codeplex.com
C# | 533 lines | 430 code | 79 blank | 24 comment | 20 complexity | e17eab20b1aa22404c5b36820b4aa81d MD5 | raw file
Possible License(s): GPL-2.0
  1. /*
  2. This file is part of Sunlit World Scheme
  3. http://swscheme.codeplex.com/
  4. Copyright (c) 2010 by Edward Kiser (edkiser@gmail.com)
  5. This program is free software; you can redistribute it and/or modify
  6. it under the terms of the GNU General Public License as published by
  7. the Free Software Foundation; either version 2 of the License, or
  8. (at your option) any later version.
  9. This program is distributed in the hope that it will be useful,
  10. but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. GNU General Public License for more details.
  13. You should have received a copy of the GNU General Public License along
  14. with this program; if not, write to the Free Software Foundation, Inc.,
  15. 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
  16. */
  17. using System;
  18. using System.Linq;
  19. namespace ExprObjModel
  20. {
  21. [Serializable]
  22. public class UsingSource : IExpressionSource
  23. {
  24. private FList<LetClause> clauseList;
  25. private IExpressionSource body;
  26. public UsingSource(FList<LetClause> clauseList, IExpressionSource body)
  27. {
  28. this.clauseList = clauseList;
  29. this.body = body;
  30. }
  31. #region IExpressionSource Members
  32. private EnvSpec GetBodyRequirements()
  33. {
  34. EnvSpec vars = EnvSpec.FromArray(LetClause.GetSymbols(clauseList));
  35. return body.GetRequirements() - vars;
  36. }
  37. public EnvSpec GetRequirements()
  38. {
  39. EnvSpec vars = EnvSpec.FromArray(LetClause.GetSymbols(clauseList));
  40. EnvSpec reqs = FListUtils.ToEnumerable(clauseList).Select(l => l.Value.GetRequirements()).EnvSpecUnion();
  41. EnvSpec reqsBody = body.GetRequirements() - vars;
  42. return reqs | reqsBody;
  43. }
  44. [Serializable]
  45. private class UsingExpr : IExpression
  46. {
  47. private FList<IExpression> clauseList;
  48. private int[] captures;
  49. private IExpression body;
  50. public UsingExpr(FList<IExpression> clauseList, int[] captures, IExpression body)
  51. {
  52. this.clauseList = clauseList;
  53. this.captures = captures;
  54. this.body = body;
  55. }
  56. public IRunnableStep Eval(IGlobalState gs, Environment env, IContinuation k)
  57. {
  58. Environment captured = env.Extend(captures, 0);
  59. if (clauseList == null)
  60. {
  61. return new RunnableEval(body, captured, k);
  62. }
  63. else
  64. {
  65. IContinuation k2 = new UsingContinuation1
  66. (
  67. null, 0,
  68. clauseList.Tail,
  69. captured, body, env, k
  70. );
  71. return new RunnableEval(clauseList.Head, env, k2);
  72. }
  73. }
  74. }
  75. [Serializable]
  76. private class UsingPartialContinuation1 : IPartialContinuation
  77. {
  78. private FList<object> valuesSoFar;
  79. private int countSoFar;
  80. private FList<IExpression> clauseListTail;
  81. private Environment captured;
  82. private IExpression body;
  83. private Environment outerEnv;
  84. private IPartialContinuation k;
  85. public UsingPartialContinuation1
  86. (
  87. FList<object> valuesSoFar,
  88. int countSoFar,
  89. FList<IExpression> clauseListTail,
  90. Environment captured,
  91. IExpression body,
  92. Environment outerEnv,
  93. IPartialContinuation k
  94. )
  95. {
  96. this.valuesSoFar = valuesSoFar;
  97. this.countSoFar = countSoFar;
  98. this.clauseListTail = clauseListTail;
  99. this.captured = captured;
  100. this.body = body;
  101. this.outerEnv = outerEnv;
  102. this.k = k;
  103. }
  104. public IContinuation Attach(IContinuation theNewBase, ItemAssociation a)
  105. {
  106. return a.Assoc<UsingPartialContinuation1, UsingContinuation1>(this, delegate() { return new UsingContinuation1(valuesSoFar, countSoFar, clauseListTail, captured, body, outerEnv, k.Attach(theNewBase, a)); });
  107. }
  108. }
  109. [Serializable]
  110. private class UsingContinuation1 : IContinuation
  111. {
  112. private FList<object> valuesSoFar;
  113. private int countSoFar;
  114. private FList<IExpression> clauseListTail;
  115. private Environment captured;
  116. private IExpression body;
  117. private Environment outerEnv;
  118. private IContinuation k;
  119. public UsingContinuation1
  120. (
  121. FList<object> valuesSoFar,
  122. int countSoFar,
  123. FList<IExpression> clauseListTail,
  124. Environment captured,
  125. IExpression body,
  126. Environment outerEnv,
  127. IContinuation k
  128. )
  129. {
  130. this.valuesSoFar = valuesSoFar;
  131. this.countSoFar = countSoFar;
  132. this.clauseListTail = clauseListTail;
  133. this.captured = captured;
  134. this.body = body;
  135. this.outerEnv = outerEnv;
  136. this.k = k;
  137. }
  138. #region IContinuation Members
  139. public IRunnableStep Return(IGlobalState gs, object v)
  140. {
  141. FList<object> valuesSoFar2 = new FList<object>(v, valuesSoFar);
  142. int countSoFar2 = countSoFar + 1;
  143. if (clauseListTail == null)
  144. {
  145. object[] values = new object[countSoFar2];
  146. int index = 0;
  147. while (valuesSoFar2 != null)
  148. {
  149. values[index++] = valuesSoFar2.Head;
  150. valuesSoFar2 = valuesSoFar2.Tail;
  151. }
  152. Environment e2 = captured.Extend(values);
  153. return new RunnableEval(body, e2, new UsingContinuation2(values, k));
  154. }
  155. else
  156. {
  157. IContinuation k2 = new UsingContinuation1
  158. (
  159. valuesSoFar2, countSoFar2,
  160. clauseListTail.Tail,
  161. captured, body, outerEnv, k
  162. );
  163. return new RunnableEval(clauseListTail.Head, outerEnv, k2);
  164. }
  165. }
  166. public IRunnableStep Throw(IGlobalState gs, object exc)
  167. {
  168. foreach (object obj in FListUtils.ToEnumerable(valuesSoFar))
  169. {
  170. if (obj is DisposableID)
  171. {
  172. DisposableID d = (DisposableID)obj;
  173. gs.DisposeByID(d);
  174. }
  175. }
  176. return new RunnableThrow(k, exc);
  177. }
  178. public IContinuation Parent { get { return k; } }
  179. public IProcedure EntryProc { get { return null; } }
  180. public IProcedure ExitProc { get { return null; } }
  181. public IPartialContinuation PartialCapture(Symbol baseMark, ItemAssociation a)
  182. {
  183. return a.Assoc<UsingContinuation1, UsingPartialContinuation1>(this, delegate() { return new UsingPartialContinuation1(valuesSoFar, countSoFar, clauseListTail, captured, body, outerEnv, k.PartialCapture(baseMark, a)); });
  184. }
  185. public Box DynamicLookup(Symbol s) { return k.DynamicLookup(s); }
  186. public EnvSpec DynamicEnv { get { return k.DynamicEnv; } }
  187. #endregion
  188. }
  189. [Serializable]
  190. private class UsingPartialContinuation2 : IPartialContinuation
  191. {
  192. private IPartialContinuation k;
  193. private object[] values;
  194. public UsingPartialContinuation2(object[] values, IPartialContinuation k)
  195. {
  196. this.values = values;
  197. this.k = k;
  198. }
  199. public IContinuation Attach(IContinuation theNewBase, ItemAssociation a)
  200. {
  201. return a.Assoc<UsingPartialContinuation2, UsingContinuation2>(this, delegate() { return new UsingContinuation2(values, k.Attach(theNewBase, a)); });
  202. }
  203. }
  204. [Serializable]
  205. private class UsingContinuation2 : IContinuation
  206. {
  207. private object[] values;
  208. private IContinuation k;
  209. public UsingContinuation2(object[] values, IContinuation k)
  210. {
  211. this.values = values;
  212. this.k = k;
  213. }
  214. public IRunnableStep Return(IGlobalState gs, object v)
  215. {
  216. foreach (object obj in values)
  217. {
  218. if (obj is DisposableID)
  219. {
  220. DisposableID d = (DisposableID)obj;
  221. gs.DisposeByID(d);
  222. }
  223. }
  224. return new RunnableReturn(k, v);
  225. }
  226. public IRunnableStep Throw(IGlobalState gs, object exc)
  227. {
  228. foreach (object obj in values)
  229. {
  230. if (obj is DisposableID)
  231. {
  232. DisposableID d = (DisposableID)obj;
  233. gs.DisposeByID(d);
  234. }
  235. }
  236. return new RunnableThrow(k, exc);
  237. }
  238. public IContinuation Parent { get { return k; } }
  239. public IProcedure EntryProc { get { return null; } }
  240. public IProcedure ExitProc { get { return null; } }
  241. public IPartialContinuation PartialCapture(Symbol baseMark, ItemAssociation a)
  242. {
  243. return a.Assoc<UsingContinuation2, UsingPartialContinuation2>(this, delegate() { return new UsingPartialContinuation2(values, k.PartialCapture(baseMark, a)); });
  244. }
  245. public Box DynamicLookup(Symbol s) { return k.DynamicLookup(s); }
  246. public EnvSpec DynamicEnv { get { return k.DynamicEnv; } }
  247. }
  248. public IExpression Compile(EnvDesc ed)
  249. {
  250. // produce the array of captures
  251. // (variables to capture are precisely those given by GetRequirements)
  252. // produce a new EnvDesc reflecting the captured env and params
  253. EnvSpec req = GetBodyRequirements();
  254. EnvDesc bodyEnvDesc;
  255. int[] captures;
  256. ed.SubsetShadowExtend(req, LetClause.GetSymbols(clauseList), out bodyEnvDesc, out captures);
  257. // compile the body with the new EnvDesc
  258. IExpression bodyC = body.Compile(bodyEnvDesc);
  259. // compile the let clauses with the old EnvDesc
  260. FList<IExpression> compiledClauseList = FListUtils.ReverseMap
  261. (
  262. clauseList,
  263. delegate(LetClause lc)
  264. {
  265. return lc.Value.Compile(ed);
  266. }
  267. );
  268. return new UsingExpr(compiledClauseList, captures, bodyC);
  269. }
  270. #endregion
  271. }
  272. [Serializable]
  273. public class UsingStarSource : IExpressionSource
  274. {
  275. private LetClause letClause;
  276. private IExpressionSource body;
  277. public UsingStarSource(FList<LetClause> clauseList, IExpressionSource body)
  278. {
  279. if (clauseList == null)
  280. {
  281. this.letClause = null;
  282. this.body = body;
  283. }
  284. else if (clauseList.Tail == null)
  285. {
  286. this.letClause = clauseList.Head;
  287. this.body = body;
  288. }
  289. else
  290. {
  291. this.letClause = clauseList.Head;
  292. this.body = new UsingStarSource(clauseList.Tail, body);
  293. }
  294. }
  295. #region IExpressionSource Members
  296. public EnvSpec GetRequirements()
  297. {
  298. if (letClause == null)
  299. {
  300. return body.GetRequirements();
  301. }
  302. else
  303. {
  304. EnvSpec z = body.GetRequirements();
  305. z -= letClause.Name;
  306. z |= letClause.Value.GetRequirements();
  307. return z;
  308. }
  309. }
  310. [Serializable]
  311. private class UsingStarExpr : IExpression
  312. {
  313. private int[] mapping;
  314. private IExpression value;
  315. private IExpression body;
  316. public UsingStarExpr(int[] mapping, IExpression value, IExpression body)
  317. {
  318. this.mapping = mapping;
  319. this.value = value;
  320. this.body = body;
  321. }
  322. #region IExpression Members
  323. public IRunnableStep Eval(IGlobalState gs, Environment env, IContinuation k)
  324. {
  325. return new RunnableEval(value, env, new UsingStarContinuation1(mapping, body, env, k));
  326. }
  327. #endregion
  328. }
  329. [Serializable]
  330. private class UsingStarPartialContinuation1 : IPartialContinuation
  331. {
  332. private int[] mapping;
  333. private IExpression body;
  334. private Environment env;
  335. private IPartialContinuation k;
  336. public UsingStarPartialContinuation1(int[] mapping, IExpression body, Environment env, IPartialContinuation k)
  337. {
  338. this.mapping = mapping;
  339. this.body = body;
  340. this.env = env;
  341. this.k = k;
  342. }
  343. public IContinuation Attach(IContinuation theNewBase, ItemAssociation a)
  344. {
  345. return a.Assoc<UsingStarPartialContinuation1, UsingStarContinuation1>(this, delegate() { return new UsingStarContinuation1(mapping, body, env, k.Attach(theNewBase, a)); });
  346. }
  347. }
  348. [Serializable]
  349. private class UsingStarContinuation1 : IContinuation
  350. {
  351. private int[] mapping;
  352. private IExpression body;
  353. private Environment env;
  354. private IContinuation k;
  355. public UsingStarContinuation1(int[] mapping, IExpression body, Environment env, IContinuation k)
  356. {
  357. this.mapping = mapping;
  358. this.body = body;
  359. this.env = env;
  360. this.k = k;
  361. }
  362. #region IContinuation Members
  363. public IRunnableStep Return(IGlobalState gs, object v)
  364. {
  365. Environment e2 = env.Extend(mapping, new object[] { v });
  366. return new RunnableEval(body, e2, new UsingStarContinuation2(v, k));
  367. }
  368. public IRunnableStep Throw(IGlobalState gs, object exc) { return new RunnableThrow(k, exc); }
  369. public IContinuation Parent { get { return k; } }
  370. public IProcedure EntryProc { get { return null; } }
  371. public IProcedure ExitProc { get { return null; } }
  372. public IPartialContinuation PartialCapture(Symbol baseMark, ItemAssociation a)
  373. {
  374. return a.Assoc<UsingStarContinuation1, UsingStarPartialContinuation1>(this, delegate() { return new UsingStarPartialContinuation1(mapping, body, env, k.PartialCapture(baseMark, a)); });
  375. }
  376. public Box DynamicLookup(Symbol s) { return k.DynamicLookup(s); }
  377. public EnvSpec DynamicEnv { get { return k.DynamicEnv; } }
  378. #endregion
  379. }
  380. [Serializable]
  381. private class UsingStarPartialContinuation2 : IPartialContinuation
  382. {
  383. private IPartialContinuation k;
  384. private object val;
  385. public UsingStarPartialContinuation2(object val, IPartialContinuation k)
  386. {
  387. this.val = val;
  388. this.k = k;
  389. }
  390. public IContinuation Attach(IContinuation theNewBase, ItemAssociation a)
  391. {
  392. return a.Assoc<UsingStarPartialContinuation2, UsingStarContinuation2>(this, delegate() { return new UsingStarContinuation2(val, k.Attach(theNewBase, a)); });
  393. }
  394. }
  395. [Serializable]
  396. private class UsingStarContinuation2 : IContinuation
  397. {
  398. private object val;
  399. private IContinuation k;
  400. public UsingStarContinuation2(object val, IContinuation k)
  401. {
  402. this.val = val;
  403. this.k = k;
  404. }
  405. public IRunnableStep Return(IGlobalState gs, object v)
  406. {
  407. if (val is DisposableID)
  408. {
  409. DisposableID d = (DisposableID)val;
  410. gs.DisposeByID(d);
  411. }
  412. return new RunnableReturn(k, v);
  413. }
  414. public IRunnableStep Throw(IGlobalState gs, object exc)
  415. {
  416. if (val is DisposableID)
  417. {
  418. DisposableID d = (DisposableID)val;
  419. gs.DisposeByID(d);
  420. }
  421. return new RunnableThrow(k, exc);
  422. }
  423. public IContinuation Parent { get { return k; } }
  424. public IProcedure EntryProc { get { return null; } }
  425. public IProcedure ExitProc { get { return null; } }
  426. public IPartialContinuation PartialCapture(Symbol baseMark, ItemAssociation a)
  427. {
  428. return a.Assoc<UsingStarContinuation2, UsingStarPartialContinuation2>(this, delegate() { return new UsingStarPartialContinuation2(val, k.PartialCapture(baseMark, a)); });
  429. }
  430. public Box DynamicLookup(Symbol s) { return k.DynamicLookup(s); }
  431. public EnvSpec DynamicEnv { get { return k.DynamicEnv; } }
  432. }
  433. public IExpression Compile(EnvDesc ed)
  434. {
  435. if (letClause != null)
  436. {
  437. EnvDesc edInner;
  438. int[] mapping;
  439. ed.ShadowExtend(new Symbol[] { letClause.Name }, out edInner, out mapping);
  440. IExpression compiledValue = letClause.Value.Compile(ed);
  441. IExpression compiledBody = body.Compile(edInner);
  442. return new UsingStarExpr(mapping, compiledValue, compiledBody);
  443. }
  444. else
  445. {
  446. return body.Compile(ed);
  447. }
  448. }
  449. #endregion
  450. }
  451. }