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