BOO-999
[boo.git] / src / Boo.Lang / Builtins.cs
blob6b069ab3ae9662abfb03004414870b10e8383cdc
1 #region license
2 // Copyright (c) 2004, Rodrigo B. de Oliveira (rbo@acm.org)
3 // All rights reserved.
4 //
5 // Redistribution and use in source and binary forms, with or without modification,
6 // are permitted provided that the following conditions are met:
7 //
8 // * Redistributions of source code must retain the above copyright notice,
9 // this list of conditions and the following disclaimer.
10 // * Redistributions in binary form must reproduce the above copyright notice,
11 // this list of conditions and the following disclaimer in the documentation
12 // and/or other materials provided with the distribution.
13 // * Neither the name of Rodrigo B. de Oliveira nor the names of its
14 // contributors may be used to endorse or promote products derived from this
15 // software without specific prior written permission.
17 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
18 // ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
19 // WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
20 // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
21 // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22 // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
23 // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
24 // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
25 // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 // THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 #endregion
29 using System;
30 using System.Collections;
31 using System.Collections.Generic;
32 using System.IO;
33 using System.Text;
34 using System.Reflection;
35 using Boo.Lang.Runtime;
37 namespace Boo.Lang
39 /// <summary>
40 /// boo language builtin functions.
41 /// </summary>
42 public class Builtins
44 public class duck
48 public static System.Version BooVersion
50 get
52 return new System.Version("0.8.1.2896");
56 public static void print(object o)
58 Console.WriteLine(o);
61 public static string gets()
63 return Console.ReadLine();
66 public static string prompt(string message)
68 Console.Write(message);
69 return Console.ReadLine();
72 public static string join(IEnumerable enumerable, string separator)
74 StringBuilder sb = new StringBuilder();
75 IEnumerator enumerator = enumerable.GetEnumerator();
76 using (enumerator as IDisposable)
78 if (enumerator.MoveNext())
80 sb.Append(enumerator.Current);
81 while (enumerator.MoveNext())
83 sb.Append(separator);
84 sb.Append(enumerator.Current);
88 return sb.ToString();
91 public static string join(IEnumerable enumerable, char separator)
93 StringBuilder sb = new StringBuilder();
94 IEnumerator enumerator = enumerable.GetEnumerator();
95 using (enumerator as IDisposable)
97 if (enumerator.MoveNext())
99 sb.Append(enumerator.Current);
100 while (enumerator.MoveNext())
102 sb.Append(separator);
103 sb.Append(enumerator.Current);
107 return sb.ToString();
110 public static string join(IEnumerable enumerable)
112 return join(enumerable, ' ');
115 public static IEnumerable map(object enumerable, ICallable function)
117 if (null == enumerable) throw new ArgumentNullException("enumerable");
118 if (null == function) throw new ArgumentNullException("function");
120 object[] args = new object[1];
121 foreach (object item in iterator(enumerable))
123 args[0] = item;
124 yield return function.Call(args);
128 public static object[] array(IEnumerable enumerable)
130 return new List(enumerable).ToArray();
133 public static Array array(Type elementType, ICollection collection)
135 if (null == collection)
137 throw new ArgumentNullException("collection");
139 if (null == elementType)
141 throw new ArgumentNullException("elementType");
144 Array array = Array.CreateInstance(elementType, collection.Count);
145 if (RuntimeServices.IsPromotableNumeric(Type.GetTypeCode(elementType)))
147 int i=0;
148 foreach (object item in collection)
150 object value = RuntimeServices.CheckNumericPromotion(item).ToType(elementType, null);
151 array.SetValue(value, i);
152 ++i;
155 else
157 collection.CopyTo(array, 0);
159 return array;
162 public static Array array(Type elementType, IEnumerable enumerable)
164 if (null == enumerable)
166 throw new ArgumentNullException("enumerable");
168 if (null == elementType)
170 throw new ArgumentNullException("elementType");
173 // future optimization, check EnumeratorItemType of enumerable
174 // and get the fast path whenever possible
175 List l = null;
176 if (RuntimeServices.IsPromotableNumeric(Type.GetTypeCode(elementType)))
178 l = new List();
179 foreach (object item in enumerable)
181 object value = RuntimeServices.CheckNumericPromotion(item).ToType(elementType, null);
182 l.Add(value);
185 else
187 l = new List(enumerable);
189 return l.ToArray(elementType);
192 public static Array array(Type elementType, int length)
194 return matrix(elementType, length);
197 public static Array matrix(Type elementType, params int[] lengths)
199 if (null == elementType)
201 throw new ArgumentNullException("elementType");
203 return Array.CreateInstance(elementType, lengths);
206 public static IEnumerable iterator(object enumerable)
208 return RuntimeServices.GetEnumerable(enumerable);
211 #if !NO_SYSTEM_DLL
212 public static System.Diagnostics.Process shellp(string filename, string arguments)
214 System.Diagnostics.Process p = new System.Diagnostics.Process();
215 p.StartInfo.Arguments = arguments;
216 p.StartInfo.CreateNoWindow = true;
217 p.StartInfo.UseShellExecute = false;
218 p.StartInfo.RedirectStandardOutput = true;
219 p.StartInfo.RedirectStandardInput = true;
220 p.StartInfo.RedirectStandardError = true;
221 p.StartInfo.FileName = filename;
222 p.Start();
223 return p;
226 public static string shell(string filename, string arguments)
228 System.Diagnostics.Process p = shellp(filename, arguments);
229 string output = p.StandardOutput.ReadToEnd();
230 p.WaitForExit();
231 return output;
233 #endif
235 internal class AssemblyExecutor : MarshalByRefObject
237 string _filename;
238 string[] _arguments;
239 string _capturedOutput = "";
241 public AssemblyExecutor(string filename, string[] arguments)
243 _filename = filename;
244 _arguments = arguments;
247 public string CapturedOutput
251 return _capturedOutput;
255 public void Execute()
257 StringWriter output = new System.IO.StringWriter();
258 TextWriter saved = Console.Out;
261 Console.SetOut(output);
262 //AppDomain.CurrentDomain.ExecuteAssembly(_filename, null, _arguments);
263 Assembly.LoadFrom(_filename).EntryPoint.Invoke(null, new object[1] { _arguments });
265 finally
267 Console.SetOut(saved);
268 _capturedOutput = output.ToString();
273 /// <summary>
274 /// Execute the specified MANAGED application in a new AppDomain.
276 /// The base directory for the new application domain will be set to
277 /// directory containing filename (Path.GetDirectoryName(Path.GetFullPath(filename))).
278 /// </summary>
279 public static string shellm(string filename, params string[] arguments)
281 AppDomainSetup setup = new AppDomainSetup();
282 setup.ApplicationBase = Path.GetDirectoryName(Path.GetFullPath(filename));
284 AppDomain domain = AppDomain.CreateDomain("shellm", null, setup);
287 AssemblyExecutor executor = new AssemblyExecutor(filename, arguments);
288 domain.DoCallBack(new CrossAppDomainDelegate(executor.Execute));
289 return executor.CapturedOutput;
291 finally
293 AppDomain.Unload(domain);
297 public static IEnumerable<object[]> enumerate(object enumerable)
299 int i = 0;
300 foreach (object item in iterator(enumerable))
302 yield return new object[] { i++, item };
306 public static IEnumerable<int> range(int max)
308 if (max < 0) /* added for coherence with behavior of compiler-optimized
309 * for-in-range() loops, should compiler loops automatically
310 * inverse iteration in this case? */
312 throw new ArgumentOutOfRangeException("max < 0");
314 return range(0, max);
317 public static IEnumerable<int> range(int begin, int end)
319 if (begin < end)
321 for (int i = begin; i < end; ++i) yield return i;
323 else if (begin > end)
325 for (int i = begin; i > end; --i) yield return i;
329 public static IEnumerable<int> range(int begin, int end, int step)
331 if (0 ==step)
333 throw new ArgumentOutOfRangeException("step == 0");
335 if (step < 0)
337 if (begin < end)
339 throw new ArgumentOutOfRangeException("begin < end && step < 0");
341 for (int i = begin; i > end; i += step) yield return i;
343 else
345 if (begin > end)
347 throw new ArgumentOutOfRangeException("begin > end && step > 0");
349 for (int i = begin; i < end; i += step) yield return i;
353 public static IEnumerable reversed(object enumerable)
355 return new List(iterator(enumerable)).Reversed;
358 public static ZipEnumerator zip(params object[] enumerables)
360 IEnumerator[] enumerators = new IEnumerator[enumerables.Length];
361 for (int i=0; i<enumerables.Length; ++i)
363 enumerators[i] = GetEnumerator(enumerables[i]);
365 return new ZipEnumerator(enumerators);
368 public static IEnumerable<object> cat(params object[] args)
370 foreach (object e in args)
372 foreach (object item in iterator(e))
374 yield return item;
379 [EnumeratorItemType(typeof(object[]))]
380 public class ZipEnumerator : IEnumerator, IEnumerable, IDisposable
382 IEnumerator[] _enumerators;
384 internal ZipEnumerator(params IEnumerator[] enumerators)
386 _enumerators = enumerators;
389 public void Dispose()
391 for (int i=0; i<_enumerators.Length; ++i)
393 IDisposable d = _enumerators[i] as IDisposable;
394 if (d != null)
395 d.Dispose();
399 public void Reset()
401 for (int i=0; i<_enumerators.Length; ++i)
403 _enumerators[i].Reset();
407 public bool MoveNext()
409 for (int i=0; i<_enumerators.Length; ++i)
411 if (!_enumerators[i].MoveNext())
413 return false;
416 return true;
419 public object Current
423 object[] current = new object[_enumerators.Length];
424 for (int i=0; i<current.Length; ++i)
426 current[i] = _enumerators[i].Current;
428 return current;
432 public IEnumerator GetEnumerator()
434 return this;
438 private static IEnumerator GetEnumerator(object enumerable)
440 return RuntimeServices.GetEnumerable(enumerable).GetEnumerator();