booish2: remove unix-isms

booish2: remove unix-isms

git-svn-id: fcce7d6ce0ac15bf24f68871b5145d46fc068279@2417 2c1201b4-01cd-e047-a400-b836ae1fbc61

#region license
// Copyright (c) 2004, Rodrigo B. de Oliveira (rbo@acm.org)
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without modification,
// are permitted provided that the following conditions are met:
//
//     * Redistributions of source code must retain the above copyright notice,
//     this list of conditions and the following disclaimer.
//     * Redistributions in binary form must reproduce the above copyright notice,
//     this list of conditions and the following disclaimer in the documentation
//     and/or other materials provided with the distribution.
//     * Neither the name of Rodrigo B. de Oliveira nor the names of its
//     contributors may be used to endorse or promote products derived from this
//     software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
// THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#endregion

namespace Boo.Lang.Interpreter

import System
import System.Collections
import System.IO
import System.Text
import System.Text.RegularExpressions
import System.Reflection
import Boo.Lang
import Boo.Lang.Compiler
import Boo.Lang.Compiler.Ast
import Boo.Lang.Compiler.TypeSystem
import Boo.Lang.Compiler.IO

class InteractiveInterpreter2(AbstractInterpreter):

	_values = {}

	_declarations = {}

	_representers = []

	[property(ShowWarnings)]
	_showWarnings = false

	[property(BlockStarters, value is not null)]
	_blockStarters = ":", "\\"

	[getter(LastValue)]
	_lastValue

	[property(Print, value is not null)]
	_print as callable(object) = print

	def constructor():
		super()
		InitializeStandardReferences()

	def constructor(parser as ICompilerStep):
		super(parser)
		InitializeStandardReferences()

	def Reset():
		_values.Clear()
		_declarations.Clear()
		_lastValue = null
		InitializeStandardReferences()

	private _buffer = StringBuilder()

	# color for messages from the interpreter (not from user code)
	[property(InterpreterColor)]
	_interpreterColor = ConsoleColor.Gray

	[property(PromptColor)]
	_promptColor = ConsoleColor.Green

	[property(ExceptionColor)]
	_exceptionColor = ConsoleColor.Red

	[property(SuggestionsColor)]
	_suggestionsColor = ConsoleColor.Yellow

	[property(SelectedSuggestionColor)]
	_selectedSuggestionColor = ConsoleColor.Magenta

	[property(SelectedSuggestionIndex)]
	_selectedSuggestionIndex = -1

	[property(Suggestions)]
	_suggestions as (object)

	_builtins as (IEntity)

	_filter as string

	CanAutoComplete as bool:
		get:
			return _selectedSuggestionIndex >= 0 and _suggestions is not null

	private def ConsolePrintPrompt():
		Console.ForegroundColor = _promptColor
		if _indent == 0:
			Console.Write(">>>")
		else:
			Console.Write("...")
			#TODO: automatic indentation option ?
			#for i in range(_indent):
			#	_buffer.Append("\t")
			#	Console.Write("\t")
		Console.ResetColor()

	private def ConsolePrintException(e as Exception):
		Console.ForegroundColor = _exceptionColor
		print e
		Console.ResetColor()

	protected def ConsolePrintSuggestions():
		cursorLeft = Console.CursorLeft
		cursorTop = Console.CursorTop
		Console.Write(Environment.NewLine)

		i = 0

		if _suggestions isa (string):
			for l in _suggestions as (string):
				Console.ForegroundColor = _suggestionsColor
				if i > 0:
					Console.Write(", ")
				if i == _selectedSuggestionIndex:
					Console.ForegroundColor = _selectedSuggestionColor
				Console.Write(l)
				i++

		elif _suggestions isa (IEntity):
			for e in _suggestions as (IEntity):
				Console.ForegroundColor = _suggestionsColor
				if i > 0:
					Console.Write(", ")
				if i == _selectedSuggestionIndex:
					Console.ForegroundColor = _selectedSuggestionColor
				Console.Write(DescribeEntity(e))
				i++

		Console.ResetColor()
		Console.CursorLeft = cursorLeft
		Console.CursorTop = cursorTop
		Console.Write(Environment.NewLine)
		ConsolePrintPrompt()
		Console.Write(_buffer.ToString())

	private static re_open = Regex("\\(", RegexOptions.Singleline)
	private static re_close = Regex("\\)", RegexOptions.Singleline)

	def DisplaySuggestions(query as string):
		#TODO: FIXME: refactor to one regex?
		p_open = re_open.Matches(query).Count
		p_close = re_close.Matches(query).Count
		if p_open > p_close:
			query = query.Split(" ,(\t".ToCharArray(), 100)[-1]
		else:
			query = query.Split(" ,\t".ToCharArray(), 100)[-1]
		if query.LastIndexOf('.') > 0:
			codeToComplete = query[0:query.LastIndexOf('.')+1]
			_suggestions = SuggestCodeCompletion(codeToComplete+"__codecomplete__")
			_filter = query[query.LastIndexOf('.')+1:]
			_suggestions = array(e for e in _suggestions as (IEntity)
								unless not e.Name.StartsWith(_filter)) as (IEntity)

		if not _suggestions or 0 == len(_suggestions): #suggest a  var
			_filter = query
			_suggestions = array(var.ToString() for var in _values.Keys
									unless not var.ToString().StartsWith(_filter))

		if not _suggestions or 0 == len(_suggestions):
			_selectedSuggestionIndex = -1
			#Console.Beep() #TODO: flash background?
		elif 1 == len(_suggestions):
			AutoComplete()
		else:
			ConsolePrintSuggestions()

	def AutoComplete():
		if not _suggestions:
			raise InvalidOperationException("no suggestions")

		s = _suggestions[_selectedSuggestionIndex] as IEntity
		if s:
			if s.EntityType == EntityType.Method:
				m = s as IMethod
				completion = s.Name[len(_filter):]
				Console.Write(completion)
				_buffer.Append(completion)
				if not m.GetParameters() or m.GetParameters().Length == 0:
					Console.Write('()')
					_buffer.Append('()')
				else:
					Console.Write('(')
					_buffer.Append('(')

			else: # not a Method
				completion = s.Name[len(_filter):]
				Console.Write(completion)
				_buffer.Append(completion)
		else:
			completion = (_suggestions[_selectedSuggestionIndex] as string)[len(_filter):]
			Console.Write(completion)
			_buffer.Append(completion)

		_selectedSuggestionIndex = -1
		_suggestions = null

	def ConsoleLoopEval():
		Console.CursorVisible = true
		ConsolePrintPrompt()

		lastChar = char('0')
		key = ConsoleKey.LeftArrow
		while key != ConsoleKey.Escape:
			cki = Console.ReadKey(true) #TODO: fix mono different behavior when ()
			key = cki.Key
			keyChar = cki.KeyChar
			control = false

			newLine = keyChar in Environment.NewLine

			if char.IsControl(keyChar):
				control = true
				if keyChar == char('\t'):
					test = char(' ')
					test = _buffer.ToString()[_buffer.Length-1] if _buffer.Length > 0
					if char.IsLetterOrDigit(test) or test == char('.'):
						_selectedSuggestionIndex = 0
						DisplaySuggestions(_buffer.ToString())
					else:
						_buffer.Append("\t")
						Console.Write("\t")
				if key == ConsoleKey.Backspace:
					if Console.CursorLeft > 3 and _buffer.Length > 0:
						Console.CursorLeft--
						Console.Write(" ")
						Console.CursorLeft--
						_buffer.Length--
					#else:	#TODO: flash background?
					#	Console.Beep()
				if CanAutoComplete:
					if key == ConsoleKey.LeftArrow:
						if _selectedSuggestionIndex > 0:
							_selectedSuggestionIndex--
						else:
							_selectedSuggestionIndex = len(_suggestions)
						DisplaySuggestions(_buffer.ToString())
					if key == ConsoleKey.RightArrow:
						if _selectedSuggestionIndex+1 < len(_suggestions):
							_selectedSuggestionIndex++
						else:
							_selectedSuggestionIndex = 0
						DisplaySuggestions(_buffer.ToString())
					if newLine:
						AutoComplete()
						continue
				if not newLine:
					continue

			_selectedSuggestionIndex = -1

			_buffer.Append(keyChar) if not newLine and not control
			Console.Write(keyChar) if not newLine
			Console.Write(Environment.NewLine) if newLine
			if newLine:
				line = _buffer.ToString()

				#TODO: refactor this into runCommand(line)
				if line == "/q":
					break
				if line == "/?":
					DisplayHelp()
					_selectedSuggestionIndex = -1
					_buffer.Length = 0
					ConsolePrintPrompt()
					continue

				_buffer.Append(Environment.NewLine)
				line = _buffer.ToString()

				try:
					_indent++ if lastChar.ToString() in _blockStarters
					_indent-- if lastChar == keyChar and _indent > 0
					if _indent == 0:
						_buffer.Length = 0
						InternalLoopEval(line)
				except x as System.Reflection.TargetInvocationException:
					ConsolePrintException(x.InnerException)
				except x:
					ConsolePrintException(x)
				ConsolePrintPrompt()

			lastChar = keyChar

		DisplayGoodbye()

	private _indent as int = 0

	def LoopEval(code as string):
		using console = ConsoleCapture():
			result = InternalLoopEval(code)
			for line in System.IO.StringReader(console.ToString()):
				_print(line)
		return result

	private def InternalLoopEval(code as string):
		result = self.Eval(code)
		if ShowWarnings:
			self.DisplayProblems(result.Warnings)
		if not self.DisplayProblems(result.Errors):
			ProcessLastValue()
		return result

	private def ProcessLastValue():
		_ = self.LastValue
		if _ is not null:
			_print(repr(_))
			SetValue("_", _)

	override def Declare([required] name as string,
				[required] type as System.Type):
		_declarations.Add(name, type)

	override def SetLastValue(value):
		_lastValue = value

	override def SetValue(name as string, value):
		_values[name] = value
		return value

	override def GetValue(name as string):
		return _values[name]

	override def Lookup([required] name as string):
		type as System.Type = _declarations[name]
		return type if type is not null

		value = GetValue(name)
		return value.GetType() if value is not null

	def DisplayProblems(problems as ICollection):
		return if problems is null or problems.Count == 0
		Console.ForegroundColor = _exceptionColor
		for problem as duck in problems:
			markLocation(problem.LexicalInfo)
			type = ("WARNING", "ERROR")[problem isa CompilerError]
			_print("${type}: ${problem.Message}")
		Console.ResetColor()
		if problems.Count > 0:
			return true
		return false

	private def markLocation(location as LexicalInfo):
		pos = location.Column
		_print("---" + "-" * pos + "^") if pos > 0

	private def InitializeStandardReferences():
		SetValue("interpreter", self)
		SetValue("dir", dir)
		SetValue("help", help)
		SetValue("print", { value | _print(value) })
		SetValue("load", load)
		SetValue("globals", globals)
		SetValue("getRootNamespace", Namespace.GetRootNamespace)

	def DisplayHelp():
		Console.ForegroundColor = _interpreterColor
		print """Welcome to booish, an interpreter for the boo programming language.
Running boo ${BooVersion} in CLR v${Environment.Version}.

The following builtin functions are available:
    /d[ir] type : lists the members of a type
    /h[elp] type : prints detailed information about a type
    /l[oad] file : evals an external boo file
    /g[lobals] : returns names of all variables known to interpreter
    /n[ames] : namespace navigation
    /q[uit] : exits the interpreter

Enter boo code in the prompt below."""
		Console.ResetColor()

	def DisplayGoodbye():	// booish is friendly
		Console.ForegroundColor = _interpreterColor
		print ""
		print "Have a nice day!" if date.Now.Hour < 16
		print "Have a nice evening!" if date.Now.Hour >= 16
		Console.ResetColor()

	def globals():
		return array(string, _values.Keys)

	def dir([required] obj):
		type = (obj as Type) or obj.GetType()
		return array(
				member for member in type.GetMembers()
				unless (method=(member as System.Reflection.MethodInfo))
				and method.IsSpecialName)

	def load([required] path as string):
		if path.EndsWith(".boo"):
			result = EvalCompilerInput(FileInput(path))
			if ShowWarnings:
				DisplayProblems(result.Warnings)
			if not DisplayProblems(result.Errors):
				ProcessLastValue()
		else:
			try:
				References.Add(System.Reflection.Assembly.LoadFrom(path))
			except e:
				print e.Message

	def help(obj):
		type = (obj as Type) or obj.GetType()
		DescribeType("    ", type)

	def DescribeType(indent as string, type as Type):
		if type.IsInterface:
			typeDef = "interface"
			baseTypes = array(GetBooTypeName(t) for t in type.GetInterfaces())
		else:
			typeDef = "class"
			baseTypes = (GetBooTypeName(type.BaseType),) + array(GetBooTypeName(t) for t in type.GetInterfaces())

		_print("${typeDef} ${type.Name}(${join(baseTypes, ', ')}):")
		_print("")

		for ctor in type.GetConstructors():
			_print("${indent}def constructor(${DescribeParameters(ctor.GetParameters())})")
			_print("")

		sortByName = def (lhs as Reflection.MemberInfo, rhs as Reflection.MemberInfo):
			return lhs.Name.CompareTo(rhs.Name)

		for f as Reflection.FieldInfo in List(type.GetFields()).Sort(sortByName):
			_print("${indent}public ${DescribeField(f)}")
			_print("")

		for p as Reflection.PropertyInfo in List(type.GetProperties()).Sort(sortByName):
			_print("${indent}${DescribeProperty(p)}:")
			_print("${indent}${indent}get") if p.GetGetMethod() is not null
			_print("${indent}${indent}set") if p.GetSetMethod() is not null
			_print("")

		for m as Reflection.MethodInfo in List(type.GetMethods()).Sort(sortByName):
			continue if m.IsSpecialName
			_print("${indent}${DescribeMethod(m)}")
			_print("")

		for e as Reflection.EventInfo in List(type.GetEvents()).Sort(sortByName):
			_print("${indent}${DescribeEvent(e)}")
			_print("")

	static def DescribeEntity(entity as IEntity):
		method = entity as ExternalMethod
		if method is not null:
			return InteractiveInterpreter.DescribeMethod(method.MethodInfo)
		field = entity as ExternalField
		if field is not null:
			return InteractiveInterpreter.DescribeField(field.FieldInfo)
		property = entity as ExternalProperty
		if property is not null:
			return InteractiveInterpreter.DescribeProperty(property.PropertyInfo)
		e = entity as ExternalEvent
		if e is not null:
			return InteractiveInterpreter.DescribeEvent(e.EventInfo)
		return entity.ToString()

	static def DescribeEvent(e as Reflection.EventInfo):
		return "${DescribeModifiers(e)}event ${e.Name} as ${e.EventHandlerType}"

	static def DescribeProperty(p as Reflection.PropertyInfo):
		modifiers = DescribeModifiers(p)
		params = DescribePropertyParameters(p.GetIndexParameters())
		return "${modifiers}${p.Name}${params} as ${GetBooTypeName(p.PropertyType)}"

	static def DescribeField(f as Reflection.FieldInfo):
		return "${DescribeModifiers(f)}${f.Name} as ${GetBooTypeName(f.FieldType)}"

	static def DescribeMethod(m as Reflection.MethodInfo):
		returnType = GetBooTypeName(m.ReturnType)
		modifiers = DescribeModifiers(m)
		return "${modifiers}def ${m.Name}(${DescribeParameters(m.GetParameters())}) as ${returnType}"

	static def DescribeModifiers(f as Reflection.FieldInfo):
		return "static " if f.IsStatic
		return ""

	static def DescribeModifiers(m as Reflection.MethodBase):
		return "static " if m.IsStatic
		return ""

	static def DescribeModifiers(e as Reflection.EventInfo):
		return DescribeModifiers(e.GetAddMethod(true) or e.GetRemoveMethod(true))

	static def DescribeModifiers(p as Reflection.PropertyInfo):
		accessor = p.GetGetMethod(true) or p.GetSetMethod(true)
		return DescribeModifiers(accessor)

	static def DescribePropertyParameters(parameters as (Reflection.ParameterInfo)):
		return "" if 0 == len(parameters)
		return "(${DescribeParameters(parameters)})"

	static def DescribeParameters(parameters as (Reflection.ParameterInfo)):
		return join(DescribeParameter(p) for p in parameters, ", ")

	static def DescribeParameter(p as Reflection.ParameterInfo):
		return "${p.Name} as ${GetBooTypeName(p.ParameterType)}"

	static def GetBooTypeName(type as System.Type) as string:
		return "(${GetBooTypeName(type.GetElementType())})" if type.IsArray
		return "object" if object is type
		return "string" if string is type
		return "void" if void is type
		return "bool" if bool is type
		return "byte" if byte is type
		return "char" if char is type
		return "sbyte" if sbyte is type
		return "short" if short is type
		return "ushort" if ushort is type
		return "int" if int is type
		return "uint" if uint is type
		return "long" if long is type
		return "ulong" if ulong is type
		return "single" if single is type
		return "double" if double is type
		return "date" if date is type
		return "timespan" if timespan is type
		return "regex" if regex is type
		return type.FullName

	def repr(value):
		writer = System.IO.StringWriter()
		repr(value, writer)
		return writer.ToString()

	def repr(value, writer as System.IO.TextWriter):
		return unless value is not null
		InitializeRepresenters() if 0 == len(_representers)
		GetBestRepresenter(value.GetType())(value, writer)

	private def InitializeRepresenters():
		AddRepresenter(string) do (value as string, writer as TextWriter):
			Visitors.BooPrinterVisitor.WriteStringLiteral(value, writer)

		AddRepresenter(bool) do (value as bool, writer as TextWriter):
			writer.Write(("false", "true")[value])

		AddRepresenter(Array) do (a as Array, writer as TextWriter):
			writer.Write("(")
			RepresentItems(a, writer)
			writer.Write(")")

		AddRepresenter(Delegate) do (d as Delegate, writer as TextWriter):
			method = d.Method
			writer.Write(method.DeclaringType.FullName)
			writer.Write(".")
			writer.Write(method.Name)

		AddRepresenter(IDictionary) do (value as IDictionary, writer as TextWriter):
			writer.Write("{")
			i = 0
			for key in value.Keys:
				writer.Write(", ") if i
				repr(key, writer)
				writer.Write(": ")
				repr(value[key], writer)
				++i
			writer.Write("}")

		AddRepresenter(IList) do (value as IList, writer as TextWriter):
			writer.Write("[")
			RepresentItems(value, writer)
			writer.Write("]")

		AddRepresenter(object) do (value, writer as TextWriter):
			writer.Write(value)

	private def RepresentItems(items, writer as TextWriter):
		i = 0
		for item in items:
			writer.Write(", ") if i > 0
			repr(item, writer)
			++i

	callable Representer(value, writer as TextWriter)

	private def AddRepresenter(type as Type, value as Representer):
		_representers.Add((type, value))

	def GetBestRepresenter(type as Type) as Representer:
		for key as Type, value in _representers:
			return value if key.IsAssignableFrom(type)
		assert false, "An appropriate representer could not be found!"

#region license
// Copyright (c) 2004, Rodrigo B. de Oliveira (rbo@acm.org)
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without modification,
// are permitted provided that the following conditions are met:
//
//     * Redistributions of source code must retain the above copyright notice,
//     this list of conditions and the following disclaimer.
//     * Redistributions in binary form must reproduce the above copyright notice,
//     this list of conditions and the following disclaimer in the documentation
//     and/or other materials provided with the distribution.
//     * Neither the name of Rodrigo B. de Oliveira nor the names of its
//     contributors may be used to endorse or promote products derived from this
//     software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
// THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#endregion

namespace Boo.Lang.Interpreter

import System
import System.Collections
import System.IO
import System.Text
import System.Text.RegularExpressions
import System.Reflection
import Boo.Lang
import Boo.Lang.Compiler
import Boo.Lang.Compiler.Ast
import Boo.Lang.Compiler.TypeSystem
import Boo.Lang.Compiler.IO

class InteractiveInterpreter2(AbstractInterpreter):

	_values = {}

	_declarations = {}

	_representers = []

	[property(ShowWarnings)]
	_showWarnings = false

	[property(BlockStarters, value is not null)]
	_blockStarters = ":", "\\"

	[getter(LastValue)]
	_lastValue

	[property(Print, value is not null)]
	_print as callable(object) = print

	def constructor():
		super()
		InitializeStandardReferences()

	def constructor(parser as ICompilerStep):
		super(parser)
		InitializeStandardReferences()

	def Reset():
		_values.Clear()
		_declarations.Clear()
		_lastValue = null
		InitializeStandardReferences()

	private _buffer = StringBuilder()

	# color for messages from the interpreter (not from user code)
	[property(InterpreterColor)]
	_interpreterColor = ConsoleColor.Gray

	[property(PromptColor)]
	_promptColor = ConsoleColor.Green

	[property(ExceptionColor)]
	_exceptionColor = ConsoleColor.Red

	[property(SuggestionsColor)]
	_suggestionsColor = ConsoleColor.Yellow

	[property(SelectedSuggestionColor)]
	_selectedSuggestionColor = ConsoleColor.Magenta

	[property(SelectedSuggestionIndex)]
	_selectedSuggestionIndex = -1

	[property(Suggestions)]
	_suggestions as (object)

	_builtins as (IEntity)

	_filter as string

	CanAutoComplete as bool:
		get:
			return _selectedSuggestionIndex >= 0 and _suggestions is not null

	private def ConsolePrintPrompt():
		Console.ForegroundColor = _promptColor
		if _indent == 0:
			Console.Write(">>>")
		else:
			Console.Write("...")
			#TODO: automatic indentation option ?
			#for i in range(_indent):
			#	_buffer.Append("\t")
			#	Console.Write("\t")
		Console.ResetColor()

	private def ConsolePrintException(e as Exception):
		Console.ForegroundColor = _exceptionColor
		print e
		Console.ResetColor()

	protected def ConsolePrintSuggestions():
		cursorLeft = Console.CursorLeft
		cursorTop = Console.CursorTop
		Console.Write("\n")

		i = 0

		if _suggestions isa (string):
			for l in _suggestions as (string):
				Console.ForegroundColor = _suggestionsColor
				if i > 0:
					Console.Write(", ")
				if i == _selectedSuggestionIndex:
					Console.ForegroundColor = _selectedSuggestionColor
				Console.Write(l)
				i++

		elif _suggestions isa (IEntity):
			for e in _suggestions as (IEntity):
				Console.ForegroundColor = _suggestionsColor
				if i > 0:
					Console.Write(", ")
				if i == _selectedSuggestionIndex:
					Console.ForegroundColor = _selectedSuggestionColor
				Console.Write(DescribeEntity(e))
				i++

		Console.ResetColor()
		Console.CursorLeft = cursorLeft
		Console.CursorTop = cursorTop
		Console.Write("\n")
		ConsolePrintPrompt()
		Console.Write(_buffer.ToString())

	private static re_open = Regex("\\(", RegexOptions.Singleline)
	private static re_close = Regex("\\)", RegexOptions.Singleline)

	def DisplaySuggestions(query as string):
		#TODO: FIXME: refactor to one regex?
		p_open = re_open.Matches(query).Count
		p_close = re_close.Matches(query).Count
		if p_open > p_close:
			query = query.Split(" ,(\t".ToCharArray(), 100)[-1]
		else:
			query = query.Split(" ,\t".ToCharArray(), 100)[-1]
		if query.LastIndexOf('.') > 0:
			codeToComplete = query[0:query.LastIndexOf('.')+1]
			_suggestions = SuggestCodeCompletion(codeToComplete+"__codecomplete__")
			_filter = query[query.LastIndexOf('.')+1:]
			_suggestions = array(e for e in _suggestions as (IEntity)
								unless not e.Name.StartsWith(_filter)) as (IEntity)

		if not _suggestions or 0 == len(_suggestions): #suggest a  var
			_filter = query
			_suggestions = array(var.ToString() for var in _values.Keys
									unless not var.ToString().StartsWith(_filter))

		if not _suggestions or 0 == len(_suggestions):
			_selectedSuggestionIndex = -1
			#Console.Beep() #TODO: flash background?
		elif 1 == len(_suggestions):
			AutoComplete()
		else:
			ConsolePrintSuggestions()

	def AutoComplete():
		if not _suggestions:
			raise InvalidOperationException("no suggestions")

		s = _suggestions[_selectedSuggestionIndex] as IEntity
		if s:
			if s.EntityType == EntityType.Method:
				m = s as IMethod
				completion = s.Name[len(_filter):]
				Console.Write(completion)
				_buffer.Append(completion)
				if not m.GetParameters() or m.GetParameters().Length == 0:
					Console.Write('()')
					_buffer.Append('()')
				else:
					Console.Write('(')
					_buffer.Append('(')

			else: # not a Method
				completion = s.Name[len(_filter):]
				Console.Write(completion)
				_buffer.Append(completion)
		else:
			completion = (_suggestions[_selectedSuggestionIndex] as string)[len(_filter):]
			Console.Write(completion)
			_buffer.Append(completion)

		_selectedSuggestionIndex = -1
		_suggestions = null

	def ConsoleLoopEval():
		Console.CursorVisible = true
		ConsolePrintPrompt()

		lastChar = char('0')
		key = ConsoleKey.LeftArrow
		while key != ConsoleKey.Escape:
			cki = Console.ReadKey(true) #TODO: fix mono different behavior when ()
			key = cki.Key
			keyChar = cki.KeyChar
			control = false

			newLine = keyChar in Environment.NewLine #FIXME: win32 is "\r\n"

			if char.IsControl(keyChar):
				control = true
				if keyChar == char('\t'):
					test = char(' ')
					test = _buffer.ToString()[_buffer.Length-1] if _buffer.Length > 0
					if char.IsLetterOrDigit(test) or test == char('.'):
						_selectedSuggestionIndex = 0
						DisplaySuggestions(_buffer.ToString())
					else:
						_buffer.Append("\t")
						Console.Write("\t")
				if key == ConsoleKey.Backspace:
					if Console.CursorLeft > 3 and _buffer.Length > 0:
						Console.CursorLeft--
						Console.Write(" ")
						Console.CursorLeft--
						_buffer.Length--
					#else:	#TODO: flash background?
					#	Console.Beep()
				if CanAutoComplete:
					if key == ConsoleKey.LeftArrow:
						if _selectedSuggestionIndex > 0:
							_selectedSuggestionIndex--
						else:
							_selectedSuggestionIndex = len(_suggestions)
						DisplaySuggestions(_buffer.ToString())
					if key == ConsoleKey.RightArrow:
						if _selectedSuggestionIndex+1 < len(_suggestions):
							_selectedSuggestionIndex++
						else:
							_selectedSuggestionIndex = 0
						DisplaySuggestions(_buffer.ToString())
					if newLine:
						AutoComplete()
						continue
				if not newLine:
					continue

			_selectedSuggestionIndex = -1

			_buffer.Append(keyChar) if not newLine and not control
			Console.Write(keyChar) if not newLine
			Console.Write(Environment.NewLine) if newLine
			if newLine:
				line = _buffer.ToString()

				#TODO: refactor this into runCommand(line)
				if line == "/q":
					break
				if line == "/?":
					DisplayHelp()
					_selectedSuggestionIndex = -1
					_buffer.Length = 0
					ConsolePrintPrompt()
					continue

				_buffer.Append(Environment.NewLine)
				line = _buffer.ToString()

				try:
					_indent++ if lastChar.ToString() in _blockStarters
					_indent-- if lastChar == keyChar and _indent > 0
					if _indent == 0:
						_buffer.Length = 0
						InternalLoopEval(line)
				except x as System.Reflection.TargetInvocationException:
					ConsolePrintException(x.InnerException)
				except x:
					ConsolePrintException(x)
				ConsolePrintPrompt()

			lastChar = keyChar

		DisplayGoodbye()

	private _indent as int = 0

	def LoopEval(code as string):
		using console = ConsoleCapture():
			result = InternalLoopEval(code)
			for line in System.IO.StringReader(console.ToString()):
				_print(line)
		return result

	private def InternalLoopEval(code as string):
		result = self.Eval(code)
		if ShowWarnings:
			self.DisplayProblems(result.Warnings)
		if not self.DisplayProblems(result.Errors):
			ProcessLastValue()
		return result

	private def ProcessLastValue():
		_ = self.LastValue
		if _ is not null:
			_print(repr(_))
			SetValue("_", _)

	override def Declare([required] name as string,
				[required] type as System.Type):
		_declarations.Add(name, type)

	override def SetLastValue(value):
		_lastValue = value

	override def SetValue(name as string, value):
		_values[name] = value
		return value

	override def GetValue(name as string):
		return _values[name]

	override def Lookup([required] name as string):
		type as System.Type = _declarations[name]
		return type if type is not null

		value = GetValue(name)
		return value.GetType() if value is not null

	def DisplayProblems(problems as ICollection):
		return if problems is null or problems.Count == 0
		Console.ForegroundColor = _exceptionColor
		for problem as duck in problems:
			markLocation(problem.LexicalInfo)
			type = ("WARNING", "ERROR")[problem isa CompilerError]
			_print("${type}: ${problem.Message}")
		Console.ResetColor()
		if problems.Count > 0:
			return true
		return false

	private def markLocation(location as LexicalInfo):
		pos = location.Column
		_print("---" + "-" * pos + "^") if pos > 0

	private def InitializeStandardReferences():
		SetValue("interpreter", self)
		SetValue("dir", dir)
		SetValue("help", help)
		SetValue("print", { value | _print(value) })
		SetValue("load", load)
		SetValue("globals", globals)
		SetValue("getRootNamespace", Namespace.GetRootNamespace)

	def DisplayHelp():
		Console.ForegroundColor = _interpreterColor
		print """Welcome to booish, an interpreter for the boo programming language.
Running boo ${BooVersion} in CLR v${Environment.Version}.

The following builtin functions are available:
    /d[ir] type : lists the members of a type
    /h[elp] type : prints detailed information about a type
    /l[oad] file : evals an external boo file
    /g[lobals] : returns names of all variables known to interpreter
    /n[ames] : namespace navigation
    /q[uit] : exits the interpreter

Enter boo code in the prompt below."""
		Console.ResetColor()

	def DisplayGoodbye():	// booish is friendly
		Console.ForegroundColor = _interpreterColor
		print "\nHave a nice day!" if date.Now.Hour < 16
		print "\nHave a nice evening!" if date.Now.Hour >= 16
		Console.ResetColor()

	def globals():
		return array(string, _values.Keys)

	def dir([required] obj):
		type = (obj as Type) or obj.GetType()
		return array(
				member for member in type.GetMembers()
				unless (method=(member as System.Reflection.MethodInfo))
				and method.IsSpecialName)

	def load([required] path as string):
		if path.EndsWith(".boo"):
			result = EvalCompilerInput(FileInput(path))
			if ShowWarnings:
				DisplayProblems(result.Warnings)
			if not DisplayProblems(result.Errors):
				ProcessLastValue()
		else:
			try:
				References.Add(System.Reflection.Assembly.LoadFrom(path))
			except e:
				print e.Message

	def help(obj):
		type = (obj as Type) or obj.GetType()
		DescribeType("    ", type)

	def DescribeType(indent as string, type as Type):
		if type.IsInterface:
			typeDef = "interface"
			baseTypes = array(GetBooTypeName(t) for t in type.GetInterfaces())
		else:
			typeDef = "class"
			baseTypes = (GetBooTypeName(type.BaseType),) + array(GetBooTypeName(t) for t in type.GetInterfaces())

		_print("${typeDef} ${type.Name}(${join(baseTypes, ', ')}):")
		_print("")

		for ctor in type.GetConstructors():
			_print("${indent}def constructor(${DescribeParameters(ctor.GetParameters())})")
			_print("")

		sortByName = def (lhs as Reflection.MemberInfo, rhs as Reflection.MemberInfo):
			return lhs.Name.CompareTo(rhs.Name)

		for f as Reflection.FieldInfo in List(type.GetFields()).Sort(sortByName):
			_print("${indent}public ${DescribeField(f)}")
			_print("")

		for p as Reflection.PropertyInfo in List(type.GetProperties()).Sort(sortByName):
			_print("${indent}${DescribeProperty(p)}:")
			_print("${indent}${indent}get") if p.GetGetMethod() is not null
			_print("${indent}${indent}set") if p.GetSetMethod() is not null
			_print("")

		for m as Reflection.MethodInfo in List(type.GetMethods()).Sort(sortByName):
			continue if m.IsSpecialName
			_print("${indent}${DescribeMethod(m)}")
			_print("")

		for e as Reflection.EventInfo in List(type.GetEvents()).Sort(sortByName):
			_print("${indent}${DescribeEvent(e)}")
			_print("")

	static def DescribeEntity(entity as IEntity):
		method = entity as ExternalMethod
		if method is not null:
			return InteractiveInterpreter.DescribeMethod(method.MethodInfo)
		field = entity as ExternalField
		if field is not null:
			return InteractiveInterpreter.DescribeField(field.FieldInfo)
		property = entity as ExternalProperty
		if property is not null:
			return InteractiveInterpreter.DescribeProperty(property.PropertyInfo)
		e = entity as ExternalEvent
		if e is not null:
			return InteractiveInterpreter.DescribeEvent(e.EventInfo)
		return entity.ToString()

	static def DescribeEvent(e as Reflection.EventInfo):
		return "${DescribeModifiers(e)}event ${e.Name} as ${e.EventHandlerType}"

	static def DescribeProperty(p as Reflection.PropertyInfo):
		modifiers = DescribeModifiers(p)
		params = DescribePropertyParameters(p.GetIndexParameters())
		return "${modifiers}${p.Name}${params} as ${GetBooTypeName(p.PropertyType)}"

	static def DescribeField(f as Reflection.FieldInfo):
		return "${DescribeModifiers(f)}${f.Name} as ${GetBooTypeName(f.FieldType)}"

	static def DescribeMethod(m as Reflection.MethodInfo):
		returnType = GetBooTypeName(m.ReturnType)
		modifiers = DescribeModifiers(m)
		return "${modifiers}def ${m.Name}(${DescribeParameters(m.GetParameters())}) as ${returnType}"

	static def DescribeModifiers(f as Reflection.FieldInfo):
		return "static " if f.IsStatic
		return ""

	static def DescribeModifiers(m as Reflection.MethodBase):
		return "static " if m.IsStatic
		return ""

	static def DescribeModifiers(e as Reflection.EventInfo):
		return DescribeModifiers(e.GetAddMethod(true) or e.GetRemoveMethod(true))

	static def DescribeModifiers(p as Reflection.PropertyInfo):
		accessor = p.GetGetMethod(true) or p.GetSetMethod(true)
		return DescribeModifiers(accessor)

	static def DescribePropertyParameters(parameters as (Reflection.ParameterInfo)):
		return "" if 0 == len(parameters)
		return "(${DescribeParameters(parameters)})"

	static def DescribeParameters(parameters as (Reflection.ParameterInfo)):
		return join(DescribeParameter(p) for p in parameters, ", ")

	static def DescribeParameter(p as Reflection.ParameterInfo):
		return "${p.Name} as ${GetBooTypeName(p.ParameterType)}"

	static def GetBooTypeName(type as System.Type) as string:
		return "(${GetBooTypeName(type.GetElementType())})" if type.IsArray
		return "object" if object is type
		return "string" if string is type
		return "void" if void is type
		return "bool" if bool is type
		return "byte" if byte is type
		return "char" if char is type
		return "sbyte" if sbyte is type
		return "short" if short is type
		return "ushort" if ushort is type
		return "int" if int is type
		return "uint" if uint is type
		return "long" if long is type
		return "ulong" if ulong is type
		return "single" if single is type
		return "double" if double is type
		return "date" if date is type
		return "timespan" if timespan is type
		return "regex" if regex is type
		return type.FullName

	def repr(value):
		writer = System.IO.StringWriter()
		repr(value, writer)
		return writer.ToString()

	def repr(value, writer as System.IO.TextWriter):
		return unless value is not null
		InitializeRepresenters() if 0 == len(_representers)
		GetBestRepresenter(value.GetType())(value, writer)

	private def InitializeRepresenters():
		AddRepresenter(string) do (value as string, writer as TextWriter):
			Visitors.BooPrinterVisitor.WriteStringLiteral(value, writer)

		AddRepresenter(bool) do (value as bool, writer as TextWriter):
			writer.Write(("false", "true")[value])

		AddRepresenter(Array) do (a as Array, writer as TextWriter):
			writer.Write("(")
			RepresentItems(a, writer)
			writer.Write(")")

		AddRepresenter(Delegate) do (d as Delegate, writer as TextWriter):
			method = d.Method
			writer.Write(method.DeclaringType.FullName)
			writer.Write(".")
			writer.Write(method.Name)

		AddRepresenter(IDictionary) do (value as IDictionary, writer as TextWriter):
			writer.Write("{")
			i = 0
			for key in value.Keys:
				writer.Write(", ") if i
				repr(key, writer)
				writer.Write(": ")
				repr(value[key], writer)
				++i
			writer.Write("}")

		AddRepresenter(IList) do (value as IList, writer as TextWriter):
			writer.Write("[")
			RepresentItems(value, writer)
			writer.Write("]")

		AddRepresenter(object) do (value, writer as TextWriter):
			writer.Write(value)

	private def RepresentItems(items, writer as TextWriter):
		i = 0
		for item in items:
			writer.Write(", ") if i > 0
			repr(item, writer)
			++i

	callable Representer(value, writer as TextWriter)

	private def AddRepresenter(type as Type, value as Representer):
		_representers.Add((type, value))

	def GetBestRepresenter(type as Type) as Representer:
		for key as Type, value in _representers:
			return value if key.IsAssignableFrom(type)
		assert false, "An appropriate representer could not be found!"


Fix example.

Fix example.

git-svn-id: fcce7d6ce0ac15bf24f68871b5145d46fc068279@2926 2c1201b4-01cd-e047-a400-b836ae1fbc61

#region license
// Copyright (c) 2004, Rodrigo B. de Oliveira (rbo@acm.org)
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without modification,
// are permitted provided that the following conditions are met:
//
//     * Redistributions of source code must retain the above copyright notice,
//     this list of conditions and the following disclaimer.
//     * Redistributions in binary form must reproduce the above copyright notice,
//     this list of conditions and the following disclaimer in the documentation
//     and/or other materials provided with the distribution.
//     * Neither the name of Rodrigo B. de Oliveira nor the names of its
//     contributors may be used to endorse or promote products derived from this
//     software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
// THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#endregion

import System
import System.IO
import System.Runtime.Serialization.Formatters.Binary

def serialize(obj):
	stream = MemoryStream()
	BinaryFormatter().Serialize(stream, obj)
	return stream.ToArray()

def deserialize(buffer as (byte)):
	return BinaryFormatter().Deserialize(MemoryStream(buffer))

arr = (1, 2, 3,)
arr = deserialize(serialize(arr))
print(join(arr))

#region license
// Copyright (c) 2004, Rodrigo B. de Oliveira (rbo@acm.org)
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without modification,
// are permitted provided that the following conditions are met:
//
//     * Redistributions of source code must retain the above copyright notice,
//     this list of conditions and the following disclaimer.
//     * Redistributions in binary form must reproduce the above copyright notice,
//     this list of conditions and the following disclaimer in the documentation
//     and/or other materials provided with the distribution.
//     * Neither the name of Rodrigo B. de Oliveira nor the names of its
//     contributors may be used to endorse or promote products derived from this
//     software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
// THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#endregion

import System
import System.IO
import System.Runtime.Serialization.Formatters.Binary

def serialize(obj):
	stream = MemoryStream()
	BinaryFormatter().Serialize(stream, obj)
	return stream.ToArray()

def deserialize(buffer as (byte)):
	return BinaryFormatter().Deserialize(MemoryStream(buffer))

array = (1, 2, 3)
array = deserialize(serialize(array))
print(join(array))


Better assembly resolution

Better assembly resolution

git-svn-id: c3b8989232654601f1acea7403f771adaaa44a81@366 2c1201b4-01cd-e047-a400-b836ae1fbc61

#region license
// boo - an extensible programming language for the CLI
// Copyright (C) 2004 Rodrigo B. de Oliveira
//
// Permission is hereby granted, free of charge, to any person
// obtaining a copy of this software and associated documentation
// files (the "Software"), to deal in the Software without restriction,
// including without limitation the rights to use, copy, modify, merge,
// publish, distribute, sublicense, and/or sell copies of the Software,
// and to permit persons to whom the Software is furnished to do so,
// subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included
// in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE
// OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//
// Contact Information
//
// mailto:rbo@acm.org
#endregion

import System
import System.IO
import System.Reflection
import Boo.Lang.Compiler
import Boo.Lang.Compiler.IO

class AssemblyResolver:

	_cache = {}

	def AddAssembly([required] asm as Assembly):
		_cache[GetSimpleName(asm.FullName)] = asm

	def AssemblyResolve(sender, args as ResolveEventArgs) as Assembly:
		simpleName = GetSimpleName(args.Name)

		asm as Assembly = _cache[simpleName]
		if asm is null:
			basePath = Path.GetFullPath(simpleName)
			asm = ProbeFile(basePath + ".dll")
			if asm is null:
				asm = ProbeFile(basePath + ".exe")
			_cache[simpleName] = asm

		return asm

	private def GetSimpleName(name as string):
		return /,\s*/.Split(name)[0]

	private def ProbeFile(fname as string):
		return Assembly.LoadFrom(fname) if File.Exists(fname)

def consume(reader as TextReader):
	writer = StringWriter()
	for line in reader:
		writer.WriteLine(line)
	return writer.ToString()

def main(argv as (string)):
	compiler = BooCompiler()

	// boo memory pipeline
	// compiles the code in memory only
	compiler.Parameters.Pipeline.Load("boom")

	if "-" == argv[0]:
		compiler.Parameters.Input.Add(StringInput("<stdin>", consume(Console.In)))
	else:
		compiler.Parameters.Input.Add(FileInput(argv[0]))

	resolver = AssemblyResolver()
	AppDomain.CurrentDomain.AssemblyResolve += resolver.AssemblyResolve
	result = compiler.Run()
	if len(result.Errors):
		for error as CompilerError in result.Errors:
			print(error.ToString(true))
		return -1
	else:
		try:
			resolver.AddAssembly(result.GeneratedAssembly)
			result.GeneratedAssemblyEntryPoint.Invoke(null, (argv[1:],))
		except x as TargetInvocationException:
			print(x.InnerException)
			return -1
	return 0

if len(argv) > 0:
	Environment.Exit(main(argv))
else:
	print("booi <script.boo>")

#region license
// boo - an extensible programming language for the CLI
// Copyright (C) 2004 Rodrigo B. de Oliveira
//
// Permission is hereby granted, free of charge, to any person
// obtaining a copy of this software and associated documentation
// files (the "Software"), to deal in the Software without restriction,
// including without limitation the rights to use, copy, modify, merge,
// publish, distribute, sublicense, and/or sell copies of the Software,
// and to permit persons to whom the Software is furnished to do so,
// subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included
// in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE
// OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//
// Contact Information
//
// mailto:rbo@acm.org
#endregion

import System
import System.IO
import System.Reflection
import Boo.Lang.Compiler
import Boo.Lang.Compiler.IO

class AssemblyResolver:

	_cache = {}

	def AddAssembly([required] asm as Assembly):
		_cache[GetSimpleName(asm.FullName)] = asm

	def AssemblyResolve(sender, args as ResolveEventArgs) as Assembly:
		simpleName = GetSimpleName(args.Name)

		asm as Assembly = _cache[simpleName]
		if asm is null:
			basePath = Path.GetFullPath(simpleName)
			asm = ProbeFile(basePath + ".dll")
			if asm is null:
				asm = ProbeFile(basePath + ".exe")
			_cache[simpleName] = asm

		return asm

	private def GetSimpleName(name as string):
		return /,\s*/.Split(name)[0]

	private def ProbeFile(fname as string):
		return Assembly.LoadFrom(fname) if File.Exists(fname)

def consume(reader as TextReader):
	lines = []
	for line in reader:
		lines.Add(line)
	return join(lines, "\n")

def main(argv as (string)):
	compiler = BooCompiler()

	// boo memory pipeline
	// compiles the code in memory only
	compiler.Parameters.Pipeline.Load("boom")

	if "-" == argv[0]:
		compiler.Parameters.Input.Add(StringInput("<stdin>", consume(Console.In)))
	else:
		compiler.Parameters.Input.Add(FileInput(argv[0]))

	resolver = AssemblyResolver()
	AppDomain.CurrentDomain.AssemblyResolve += resolver.AssemblyResolve
	result = compiler.Run()
	if len(result.Errors):
		for error as CompilerError in result.Errors:
			print(error.ToString(true))
		return -1
	else:
		try:
			resolver.AddAssembly(result.GeneratedAssembly)
			result.GeneratedAssemblyEntryPoint.Invoke(null, (argv[1:],))
		except x as TargetInvocationException:
			print(x.InnerException)
			return -1
	return 0

if len(argv) > 0:
	Environment.Exit(main(argv))
else:
	print("booi <script.boo>")


Revert "don't depend on System.Collections.CollectionBase for it has been removed from newer .net profiles"

This reverts commit 3fad646617617dc842599a0bc08934bc1c69fc49.

namespace UnityScript.Lang

import System
import System.Collections

class Array(CollectionBase, Boo.Lang.Runtime.ICoercible):

	def constructor():
		pass

	def constructor([required(capacity >= 0)] capacity as int):
		EnsureCapacity(capacity)

	def constructor(collection as IEnumerable):
		if collection isa String:
			Add(collection)
		else:
			AddRange(collection)

	def constructor(*items):
		if len(items) == 1 and items[0] isa IEnumerable:
			AddRange(items[0])
		else:
			AddRange(items)

	static def op_Implicit(e as IEnumerable) as Array:
		if e is null: return null
		return Array(e)

	static def op_Implicit(a as System.Array) as Array:
		if a is null: return null
		return Array((a as IEnumerable))

	length:
		get:
			return self.Count
		set:
			EnsureCapacity(value)

			if value < self.Count:
				self.InnerList.RemoveRange(value, InnerList.Count - value)

	def clear():
		Clear()

	def Coerce(toType as System.Type):
		if toType.IsArray: return ToBuiltin(toType.GetElementType())
		return self

	def ToBuiltin(type as System.Type):
		return self.InnerList.ToArray(type)

	def Add(value as object, *items):
		self.AddImpl(value, items)

	def Add(value as object):
		self.InnerList.Add(value)

	def Push(value as object, *items):
		return self.AddImpl(value, items)

	def push(value as object, *items):
		return self.AddImpl(value, items)

	// workaround for mono reflection bug
	def push(value as object):
		self.InnerList.Add(value)
		return self.InnerList.Count

	def Push(value as object):
		return self.push(value)

	def Unshift(value as object, *items):
		return self.UnshiftImpl(value, items)

	def unshift(value as object, *items):
		return self.UnshiftImpl(value, items)

	def Splice (index as int, howmany as int, *items):
		SpliceImpl (index, howmany, items)

	def splice (index as int, howmany as int, *items):
		SpliceImpl (index, howmany, items)

	# How do i allow the vararg only for ICollections?
	def Concat(value as ICollection, *items):
		return ConcatImpl(value, items)

	# How do i allow the vararg only for ICollections?
	def concat(value as ICollection, *items):
		return ConcatImpl(value, items)

	# Pop last and return
	def Pop():
		last = self.InnerList.Count - 1
		popped = self.InnerList[last]
		self.InnerList.RemoveAt(last)
		return popped

	def pop():
		return self.Pop()

	# Remove first element
	def Shift():
		first = 0
		popped = self.InnerList[first]
		self.InnerList.RemoveAt(0)
		return popped

	def shift():
		return self.Shift()

	# Convert to string
	def ToString ():
		return self.Join(",")

	def toString ():
		return ToString()

	# Returns array with elements removed
	def Slice(start as int, end as int):
		normalStart = NormalizeIndex(start)
		normalEnd = NormalizeIndex(end)
		return Array(InnerList.GetRange(normalStart, normalEnd - normalStart))

	def Slice(start as int):
		return self.Slice(start, self.InnerList.Count)

	def slice(start as int, end as int):
		return self.Slice(start, end)

	def slice(start as int):
		return self.Slice(start)

	# Revert
	def Reverse() as Array:
		self.InnerList.Reverse()
		return self

	def reverse() as Array:
		self.Reverse()
		return self

	callable Comparison(lhs as object, rhs as object) as int

	private class ComparisonComparer(IComparer):
		def constructor(comparison as Comparison):
			_comparison = comparison
		def Compare(lhs, rhs):
			return _comparison(lhs, rhs)
		_comparison as Comparison

	def Sort(comparison as Comparison):
		self.InnerList.Sort(ComparisonComparer(comparison))

	def sort(comparison as Comparison):
		Sort(comparison)

	# Sort
	def Sort() as Array:
		self.InnerList.Sort()
		return self

	def sort() as Array:
		self.Sort()
		return self

	# Combine to a string
	def Join (seperator as String):
		return Builtins.join(self.InnerList, seperator)

	def join (seperator as String):
		return Builtins.join(self.InnerList, seperator)

	# Remove
	def Remove (obj as Object):
		self.InnerList.Remove(obj)

	def remove (obj as Object):
		self.Remove(obj)

	self[index as int] as object:
		get:
			return self.InnerList[index]
		set:
			EnsureCapacity(index+1)
			self.InnerList[index] = value

	def AddRange([required] collection as IEnumerable):
		for item in collection:
			self.InnerList.Add(item)

	override protected def OnValidate(newValue):
		pass // anything goes

	private def AddImpl(value as object, [required] items as IEnumerable):
		self.InnerList.Add(value)

		for item in items:
			self.InnerList.Add(item)
		return self.InnerList.Count

	private def UnshiftImpl(value as object, [required] items as IEnumerable):
		self.InnerList.InsertRange(0, items)
		self.InnerList.Insert(0, value)
		return self.InnerList.Count

	private def SpliceImpl (index as int, howmany as int, [required] items as IEnumerable):
		if howmany != 0:
			self.InnerList.RemoveRange(index, howmany)
		self.InnerList.InsertRange(index, items)

	private def ConcatImpl(value as ICollection, [required] items as IEnumerable):
		arr = Array (self.InnerList)
		arr.InnerList.AddRange(value)

		for item as ICollection in items:
			arr.InnerList.AddRange(item)

		return arr

	private def EnsureCapacity(capacity as int):
		return if capacity < Count
		for i in range(capacity-self.Count):
			InnerList.Add(null)

	private def NormalizeIndex(index as int):
		return index if index >= 0
		return index + InnerList.Count

namespace UnityScript.Lang

import System
import System.Collections

class Array(IList, Boo.Lang.Runtime.ICoercible):

	InnerList = System.Collections.Generic.List of object()

	def constructor():
		pass

	def constructor([required(capacity >= 0)] capacity as int):
		EnsureCapacity(capacity)

	def constructor(collection as IEnumerable):
		if collection isa String:
			Add(collection)
		else:
			AddRange(collection)

	def constructor(*items):
		if len(items) == 1 and items[0] isa IEnumerable:
			AddRange(items[0])
		else:
			AddRange(items)

	def GetEnumerator():
		return InnerList.GetEnumerator()

	def CopyTo(target as System.Array, targetIndex as int):
		elementType = target.GetType().GetElementType()
		elementsToCopy = Math.Min(len(target) - targetIndex, Count)
		sourceIndex = 0
		while sourceIndex < elementsToCopy:
			rawArrayIndexing:
				target[targetIndex++] = Boo.Lang.Runtime.RuntimeServices.Coerce(InnerList[sourceIndex++], elementType)

	Count:
		get: return InnerList.Count

	ICollection.IsSynchronized:
		get: return false

	ICollection.SyncRoot:
		get: return self

	def Clear():
		InnerList.Clear()

	def Contains(o):
		return InnerList.Contains(o)

	def IndexOf(o):
		return InnerList.IndexOf(o)

	def Insert(index as int, element):
		InnerList.Insert(index, element)

	def RemoveAt(index as int):
		InnerList.RemoveAt(index)

	IList.IsReadOnly:
		get: return false

	IList.IsFixedSize:
		get: return false

	static def op_Implicit(e as IEnumerable) as Array:
		if e is null: return null
		return Array(e)

	static def op_Implicit(a as System.Array) as Array:
		if a is null: return null
		return Array((a as IEnumerable))

	length:
		get:
			return self.Count
		set:
			EnsureCapacity(value)

			if value < self.Count:
				self.InnerList.RemoveRange(value, InnerList.Count - value)

	def clear():
		Clear()

	def Coerce(toType as System.Type):
		if toType.IsArray: return ToBuiltin(toType.GetElementType())
		return self

	def ToBuiltin(type as System.Type):
		result = System.Array.CreateInstance(type, Count)
		CopyTo(result, 0)
		return result

	def Add(value as object, *items):
		self.AddImpl(value, items)

	def Add(value as object):
		self.InnerList.Add(value)

	def Push(value as object, *items):
		return self.AddImpl(value, items)

	def push(value as object, *items):
		return self.AddImpl(value, items)

	// workaround for mono reflection bug
	def push(value as object):
		self.InnerList.Add(value)
		return self.InnerList.Count

	def Push(value as object):
		return self.push(value)

	def Unshift(value as object, *items):
		return self.UnshiftImpl(value, items)

	def unshift(value as object, *items):
		return self.UnshiftImpl(value, items)

	def Splice (index as int, howmany as int, *items):
		SpliceImpl (index, howmany, items)

	def splice (index as int, howmany as int, *items):
		SpliceImpl (index, howmany, items)

	# How do i allow the vararg only for ICollections?
	def Concat(value as ICollection, *items):
		return ConcatImpl(value, items)

	# How do i allow the vararg only for ICollections?
	def concat(value as ICollection, *items):
		return ConcatImpl(value, items)

	# Pop last and return
	def Pop():
		last = self.InnerList.Count - 1
		popped = self.InnerList[last]
		self.InnerList.RemoveAt(last)
		return popped

	def pop():
		return self.Pop()

	# Remove first element
	def Shift():
		first = 0
		popped = self.InnerList[first]
		self.InnerList.RemoveAt(0)
		return popped

	def shift():
		return self.Shift()

	# Convert to string
	def ToString ():
		return self.Join(",")

	def toString ():
		return ToString()

	# Returns array with elements removed
	def Slice(start as int, end as int):
		normalStart = NormalizeIndex(start)
		normalEnd = NormalizeIndex(end)
		return Array(InnerList.GetRange(normalStart, normalEnd - normalStart))

	def Slice(start as int):
		return self.Slice(start, self.InnerList.Count)

	def slice(start as int, end as int):
		return self.Slice(start, end)

	def slice(start as int):
		return self.Slice(start)

	# Revert
	def Reverse() as Array:
		self.InnerList.Reverse()
		return self

	def reverse() as Array:
		self.Reverse()
		return self

	callable Comparison(lhs as object, rhs as object) as int

	def Sort(comparison as Comparison):
		self.InnerList.Sort({ x, y | comparison(x, y) })

	def sort(comparison as Comparison):
		Sort(comparison)

	# Sort
	def Sort() as Array:
		self.InnerList.Sort()
		return self

	def sort() as Array:
		return self.Sort()

	# Combine to a string
	def Join (seperator as String):
		return Builtins.join(self.InnerList, seperator)

	def join (seperator as String):
		return self.Join(seperator)

	# Remove
	def Remove (obj as Object):
		self.InnerList.Remove(obj)

	def remove (obj as Object):
		self.Remove(obj)

	self[index as int] as object:
		get:
			return self.InnerList[index]
		set:
			EnsureCapacity(index+1)
			self.InnerList[index] = value

	def AddRange([required] collection as IEnumerable):
		for item in collection:
			self.InnerList.Add(item)

	private def AddImpl(value as object, [required] items as IEnumerable):
		self.InnerList.Add(value)
		for item in items:
			self.InnerList.Add(item)
		return self.InnerList.Count

	private def UnshiftImpl(value as object, [required] items as IEnumerable):
		self.InnerList.InsertRange(0, items)
		self.InnerList.Insert(0, value)
		return self.InnerList.Count

	private def SpliceImpl (index as int, howmany as int, [required] items as IEnumerable):
		if howmany != 0:
			self.InnerList.RemoveRange(index, howmany)
		self.InnerList.InsertRange(index, items)

	private def ConcatImpl(value as ICollection, [required] items as IEnumerable):
		arr = Array (self.InnerList)
		arr.AddRange(value)
		for item as ICollection in items:
			arr.AddRange(item)
		return arr

	private def EnsureCapacity(capacity as int):
		return if capacity < Count
		for i in range(capacity-self.Count):
			InnerList.Add(null)

	private def NormalizeIndex(index as int):
		return index if index >= 0
		return index + InnerList.Count


Reverting previous change in common-asm-info.boo, since it breaks the NAnt build.

git-svn-id: bab0c2de90ee11a20376049c2cdee62584491f34@2549 73e77b4c-caa6-f847-a29a-24ab75ae54b6

// Copyright 2004-2005 Castle Project - http://www.castleproject.org/
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
import System.Reflection

[assembly: AssemblyDelaySign(false)]
[assembly: AssemblyTitle("Castle.MonoRail.Views.Brail")]
[assembly: AssemblyKeyFile("../../../CastleKey.snk")]
[assembly: AssemblyVersion("1.0.0.0")]
[assembly: AssemblyDescription("Castle.MonoRail.Views.Brail: View Engine for MonoRail using Boo")]
[assembly: AssemblyCopyright("Copyright (c) 2005, Castle Project http://www.castleproject.org/")]

// Copyright 2004-2005 Castle Project - http://www.castleproject.org/
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
import System.Reflection

[assembly: AssemblyDelaySign(false)]
[assembly: AssemblyTitle("Castle.MonoRail.Views.Brail")]
[assembly: AssemblyKeyFile("../../../../CastleKey.snk")]
[assembly: AssemblyVersion("1.0.0.0")]
[assembly: AssemblyDescription("Castle.MonoRail.Views.Brail: View Engine for MonoRail using Boo")]
[assembly: AssemblyCopyright("Copyright (c) 2005, Castle Project http://www.castleproject.org/")]


new command line option -cp

new command line option -cp

namespace boojay

import System.IO
import Boo.Lang.Useful.CommandLine from Boo.Lang.Useful

class CommandLine(AbstractCommandLine):

	[getter(Classpaths)]
	_classpaths = List[of string]()

	[getter(References)]
	_references = List[of string]()

	_sourceFiles = List[of string]()

	_srcDirs = List[of string]()

	def constructor(argv):
		Parse(argv)

	def SourceFiles():

		for srcFile as string in _sourceFiles:
			yield srcFile

		for srcDir in _srcDirs:
			for fname in Directory.GetFiles(srcDir, "*.boo"):
				continue unless fname.EndsWith("boo")
				yield fname

	IsValid:
		get: return len(self._sourceFiles) > 0 or len(self._srcDirs) > 0

	[Option("Output directory", ShortForm: "o", LongForm: "out")]
	public OutputDirectory = "."

	[Option("Prints the resulting bytecode to stdout.", ShortForm: 'p', LongForm: "print")]
	public PrintCode = false

	[Option("Prints the expanded boo code to stdout.", LongForm: "boo")]
	public Boo = false

	[Option("Enables duck typing.", LongForm: "ducky")]
	public Ducky = false

	[Option("Enables writing debug symbols.", LongForm: "debug")]
	public Debug = false

	[Option("Enables verbose mode.", LongForm: "verbose")]
	public Verbose = false

	[Option("Prints additional compiler internal messages to stdout.", LongForm: "debug-compiler")]
	public DebugCompiler = false

	[Option("References the specified {assembly}", ShortForm: 'r', LongForm: "reference", MaxOccurs: int.MaxValue)]
	def AddReference(reference as string):
		_references.AddUnique(reference)

	[Option("Add the specified {classpath}", LongForm: "cp", MaxOccurs: int.MaxValue)]
	def AddClasspath(classpath as string):
		_classpaths.AddUnique(classpath)

	[Option("Includes all *.boo files from {srcdir}", LongForm: "srcdir", MaxOccurs: int.MaxValue)]
	def AddSourceDir(srcDir as string):
		_srcDirs.AddUnique(Path.GetFullPath(srcDir))

	[Option("display this help and exit", LongForm: "help")]
	public DoHelp = false

	[Argument]
	def AddSourceFile([required] sourceFile as string):
		_sourceFiles.Add(sourceFile)

namespace boojay

import System.IO
import Boo.Lang.Useful.CommandLine from Boo.Lang.Useful

class CommandLine(AbstractCommandLine):

	[getter(References)]
	_references = List[of string]()

	_sourceFiles = List[of string]()

	_srcDirs = List[of string]()

	def constructor(argv):
		Parse(argv)

	def SourceFiles():

		for srcFile as string in _sourceFiles:
			yield srcFile

		for srcDir in _srcDirs:
			for fname in Directory.GetFiles(srcDir, "*.boo"):
				continue unless fname.EndsWith("boo")
				yield fname

	IsValid:
		get: return len(self._sourceFiles) > 0 or len(self._srcDirs) > 0

	[Option("Output directory", ShortForm: "o", LongForm: "out")]
	public OutputDirectory = "."

	[Option("Prints the resulting bytecode to stdout.", ShortForm: 'p', LongForm: "print")]
	public PrintCode = false

	[Option("Prints the expanded boo code to stdout.", LongForm: "boo")]
	public Boo = false

	[Option("Enables duck typing.", LongForm: "ducky")]
	public Ducky = false

	[Option("Enables writing debug symbols.", LongForm: "debug")]
	public Debug = false

	[Option("Enables verbose mode.", LongForm: "verbose")]
	public Verbose = false

	[Option("Prints additional compiler internal messages to stdout.", LongForm: "debug-compiler")]
	public DebugCompiler = false

	[Option("References the specified {assembly}", ShortForm: 'r', LongForm: "reference", MaxOccurs: int.MaxValue)]
	def AddReference(reference as string):
		_references.AddUnique(reference)

	[Option("Includes all *.boo files from {srcdir}", LongForm: "srcdir", MaxOccurs: int.MaxValue)]
	def AddSourceDir(srcDir as string):
		_srcDirs.AddUnique(Path.GetFullPath(srcDir))

	[Option("display this help and exit", LongForm: "help")]
	public DoHelp = false

	[Argument]
	def AddSourceFile([required] sourceFile as string):
		_sourceFiles.Add(sourceFile)


treat mono-1.0==net-1.1 and mono-##==net-## when searching for booc.exe in nant task

git-svn-id: fcce7d6ce0ac15bf24f68871b5145d46fc068279@2170 2c1201b4-01cd-e047-a400-b836ae1fbc61

#region license
// Copyright (c) 2004, Rodrigo B. de Oliveira (rbo@acm.org)
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without modification,
// are permitted provided that the following conditions are met:
//
//     * Redistributions of source code must retain the above copyright notice,
//     this list of conditions and the following disclaimer.
//     * Redistributions in binary form must reproduce the above copyright notice,
//     this list of conditions and the following disclaimer in the documentation
//     and/or other materials provided with the distribution.
//     * Neither the name of Rodrigo B. de Oliveira nor the names of its
//     contributors may be used to endorse or promote products derived from this
//     software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
// THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#endregion

namespace Boo.NAnt

import System
import System.Globalization
import System.IO
import System.Text.RegularExpressions
import NAnt.Core
import NAnt.Core.Attributes
import NAnt.Core.Types
import NAnt.Core.Util
import NAnt.DotNet.Types

import NAnt.DotNet.Tasks
import System.Reflection

[TaskName('booc')]
public class BoocTask(CompilerBase):
	#region Private Instance Fields
	private _debugOutput as DebugOutput = DebugOutput.Enable
	private _exe as string

	private _useruntime = true //keep true for mono compatibility (don't call booc.exe directly)
	private _noconfig = false
	private _nostdlib = false

	#endregion Private Instance Fields
	#region Private Static Fields
	private static _classNameRegex = Regex('^((?<comment>/\\*.*?(\\*/|$))|[\\s\\.\\{]+|class\\s+(?<class>\\w+)|(?<keyword>\\w+))*')

	private static _namespaceRegex = Regex('^((?<comment>/\\*.*?(\\*/|$))|[\\s\\.\\{]+|namespace\\s+(?<namespace>(\\w+(\\.\\w+)*)+)|(?<keyword>\\w+))*')

	#endregion Private Static Fields

	def constructor():
		SupportsKeyFile = true
		SupportsKeyContainer = true

	[FrameworkConfigurable("exename")]
	[TaskAttribute('exename')]
	public override ExeName as string:
		get:
			return _exe
		set:
			_exe = value

	[FrameworkConfigurable("useruntimeengine")]
	[TaskAttribute('useruntimeengine')]
	override UseRuntimeEngine as bool:
		get:
			return _useruntime
		set:
			_useruntime = value

	#region Public Instance Properties

	[TaskAttribute('debug')]
	public DebugOutput as DebugOutput:
		get:
			return _debugOutput
		set:
			_debugOutput = value

	public Debug as bool:
		get:
			return (DebugOutput != DebugOutput.None)
		set:
			if value:
				DebugOutput = DebugOutput.Enable
			else:
				DebugOutput = DebugOutput.None

	[FrameworkConfigurable('noconfig')]
	[TaskAttribute('noconfig')]
	[BooleanValidator]
	public NoConfig as bool:
		get:
			return _noconfig
		set:
			_noconfig = value

	[FrameworkConfigurable('nostdlib')]
	[TaskAttribute('nostdlib')]
	[BooleanValidator]
	public NoStdLib as bool:
		get:
			return _nostdlib
		set:
			_nostdlib = value

	private def FindBooc() as string:
		path as string
		dir = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location)
		if Project.TargetFramework:
			frameworkname = Project.TargetFramework.Name
			path = Path.Combine(Path.Combine(dir, frameworkname), "booc.exe")
			if File.Exists(path):
				return path
			//treat mono-1.0==net-1.1 and mono-##==net-##
			frameworkname = frameworkname.Replace("mono-1.0","net-1.1").Replace("mono-","net-")
			path = Path.Combine(Path.Combine(dir, frameworkname), "booc.exe")
			if File.Exists(path):
				return path
		path = Path.Combine(dir, "booc.exe")
		if File.Exists(path):
			return path
		_useruntime = false
		return "booc" //try booc in PATH

	protected override def ExecuteTask():
		if not ExeName or ExeName == string.Empty:
			ExeName = FindBooc()
		super()

	#endregion Public Instance Properties
	#region Override implementation of CompilerBase
	protected override def WriteOptions(writer as TextWriter):
		if DebugOutput != DebugOutput.None:
			WriteOption(writer, 'debug')
		else:
			WriteOption(writer, 'debug-')
		if NoConfig and (not Arguments.Contains('-noconfig')):
			Arguments.Add(Argument('-noconfig'))
		if NoStdLib:
			WriteOption(writer, "nostdlib")
		if Verbose:
			WriteOption(writer, "vv")

	protected override def WriteOption(writer as TextWriter, name as string):
		writer.WriteLine("-{0}", name)

	protected override def WriteOption(writer as TextWriter, name as string, value as string):
		if value.IndexOf(" ") > 0 and (not value.StartsWith("\"")
						or not value.EndsWith("\"")):
			writer.WriteLine("-{0}:\"{1}\"", name, value)
		else:
			writer.WriteLine("-{0}:{1}", name, value)

	public Extension as string:
		get:
			return 'boo'

	protected ClassNameRegex as Regex:
		get:
			return _classNameRegex

	protected NamespaceRegex as Regex:
		get:
			return _namespaceRegex
	#endregion Override implementation of CompilerBase

#region license
// Copyright (c) 2004, Rodrigo B. de Oliveira (rbo@acm.org)
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without modification,
// are permitted provided that the following conditions are met:
//
//     * Redistributions of source code must retain the above copyright notice,
//     this list of conditions and the following disclaimer.
//     * Redistributions in binary form must reproduce the above copyright notice,
//     this list of conditions and the following disclaimer in the documentation
//     and/or other materials provided with the distribution.
//     * Neither the name of Rodrigo B. de Oliveira nor the names of its
//     contributors may be used to endorse or promote products derived from this
//     software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
// THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#endregion

namespace Boo.NAnt

import System
import System.Globalization
import System.IO
import System.Text.RegularExpressions
import NAnt.Core
import NAnt.Core.Attributes
import NAnt.Core.Types
import NAnt.Core.Util
import NAnt.DotNet.Types

import NAnt.DotNet.Tasks
import System.Reflection

[TaskName('booc')]
public class BoocTask(CompilerBase):
	#region Private Instance Fields
	private _debugOutput as DebugOutput = DebugOutput.Enable
	private _exe as string

	private _useruntime = true //keep true for mono compatibility (don't call booc.exe directly)
	private _noconfig = false
	private _nostdlib = false

	#endregion Private Instance Fields
	#region Private Static Fields
	private static _classNameRegex = Regex('^((?<comment>/\\*.*?(\\*/|$))|[\\s\\.\\{]+|class\\s+(?<class>\\w+)|(?<keyword>\\w+))*')

	private static _namespaceRegex = Regex('^((?<comment>/\\*.*?(\\*/|$))|[\\s\\.\\{]+|namespace\\s+(?<namespace>(\\w+(\\.\\w+)*)+)|(?<keyword>\\w+))*')

	#endregion Private Static Fields

	def constructor():
		SupportsKeyFile = true
		SupportsKeyContainer = true

	[FrameworkConfigurable("exename")]
	[TaskAttribute('exename')]
	public override ExeName as string:
		get:
			return _exe
		set:
			_exe = value

	[FrameworkConfigurable("useruntimeengine")]
	[TaskAttribute('useruntimeengine')]
	override UseRuntimeEngine as bool:
		get:
			return _useruntime
		set:
			_useruntime = value

	#region Public Instance Properties

	[TaskAttribute('debug')]
	public DebugOutput as DebugOutput:
		get:
			return _debugOutput
		set:
			_debugOutput = value

	public Debug as bool:
		get:
			return (DebugOutput != DebugOutput.None)
		set:
			if value:
				DebugOutput = DebugOutput.Enable
			else:
				DebugOutput = DebugOutput.None

	[FrameworkConfigurable('noconfig')]
	[TaskAttribute('noconfig')]
	[BooleanValidator]
	public NoConfig as bool:
		get:
			return _noconfig
		set:
			_noconfig = value

	[FrameworkConfigurable('nostdlib')]
	[TaskAttribute('nostdlib')]
	[BooleanValidator]
	public NoStdLib as bool:
		get:
			return _nostdlib
		set:
			_nostdlib = value

	private def FindBooc() as string:
		path as string
		dir = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location)
		if Project.TargetFramework:
			path = Path.Combine(dir, Project.TargetFramework.Name)
			path = Path.Combine(path, "booc.exe")
			if File.Exists(path):
				return path
		path = Path.Combine(dir, "booc.exe")
		if File.Exists(path):
			return path
		_useruntime = false
		return "booc" //try booc in PATH

	protected override def ExecuteTask():
		if not ExeName or ExeName == string.Empty:
			ExeName = FindBooc()
		super()

	#endregion Public Instance Properties
	#region Override implementation of CompilerBase
	protected override def WriteOptions(writer as TextWriter):
		if DebugOutput != DebugOutput.None:
			WriteOption(writer, 'debug')
		else:
			WriteOption(writer, 'debug-')
		if NoConfig and (not Arguments.Contains('-noconfig')):
			Arguments.Add(Argument('-noconfig'))
		if NoStdLib:
			WriteOption(writer, "nostdlib")
		if Verbose:
			WriteOption(writer, "vv")

	protected override def WriteOption(writer as TextWriter, name as string):
		writer.WriteLine("-{0}", name)

	protected override def WriteOption(writer as TextWriter, name as string, value as string):
		if value.IndexOf(" ") > 0 and (not value.StartsWith("\"")
						or not value.EndsWith("\"")):
			writer.WriteLine("-{0}:\"{1}\"", name, value)
		else:
			writer.WriteLine("-{0}:{1}", name, value)

	public Extension as string:
		get:
			return 'boo'

	protected ClassNameRegex as Regex:
		get:
			return _classNameRegex

	protected NamespaceRegex as Regex:
		get:
			return _namespaceRegex
	#endregion Override implementation of CompilerBase


Added some remarks on the purpose of this namespace. Will also be used for testing the support of XML docs.

#region license
// Copyright (c) 2013 Harald Meyer auf'm Hofe (harald_meyer@users.sourceforge.net)
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without modification,
// are permitted provided that the following conditions are met:
//
//     * Redistributions of source code must retain the above copyright notice,
//     this list of conditions and the following disclaimer.
//     * Redistributions in binary form must reproduce the above copyright notice,
//     this list of conditions and the following disclaimer in the documentation
//     and/or other materials provided with the distribution.
//     * Neither the name of Rodrigo B. de Oliveira nor the names of its
//     contributors may be used to endorse or promote products derived from this
//     software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
// THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#endregion

namespace Booish.Mod.Os
"""
The classes of this namespace implement commands for the
<c>booish</c> shell affecting the file
system like <c>dir</c> or <c>pwd</c>. On the on hand, these classes
allow to use <c>booish</c> like <c>cmd.exe</c>. On the other hand,
these classes may serve as an example for extendind the <c>booish</c>
shell by linking assemblies.
"""

import System
import System.IO
import System.IO.Directory

import Boo.Lang.Interpreter
import Boo.Lang.Interpreter.ColorScheme

[CmdClass("Directory")]
class Directory:
"""Implements CD, DIR, LS and PWD commands."""

	final static CONFIG_FILENAME = "booish\\Shell\\DirectoryConfig.ini"

	static ConfigFileName as string:
		get:
			return Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), CONFIG_FILENAME)

	def constructor():
		configFileName=ConfigFileName
		if System.IO.File.Exists(configFileName):
			for l in System.IO.File.OpenText(configFileName):
				s=l.Split(*':=, '.ToCharArray())
				self.GetType().GetMethod(s[0]).Invoke(self, (s[1],))

	_dirStack = []
	"""A list representing the stack of visited directories."""
	_dirStackIndex=-1

	[CmdDeclaration("cd chdir", Description:"Change the current working directory.")]
	public def Cd([CmdArgument(CmdArgumentCompletion.Directory, DefaultValue:"")] newDir):
	"""Change current directory."""
		if len(_dirStack) == 0:
			_dirStack.Add(GetCurrentDirectory())
			_dirStackIndex = 0
		if string.IsNullOrEmpty(newDir):
			newDir=Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments)
		newDir=Environment.ExpandEnvironmentVariables(newDir)
		_dirStack.RemoveAt(len(_dirStack)-1) while len(_dirStack)-1 > _dirStackIndex
		_dirStack.Add(newDir)
		_dirStack.RemoveAt(0) while len(_dirStack) > 100
		_dirStackIndex = len(_dirStack)-1
		SetCurrentDirectory(newDir)
		Console.WriteLine(GetCurrentDirectory())

	[CmdDeclaration("pwd workdir", Description:"Show the current working directory.")]
	public def Pwd():
	"""Show the current working directory."""
		Console.WriteLine(GetCurrentDirectory())

	[CmdDeclaration("cdb chdirback", Description:"Go back to the directory that you visited before.")]
	public def Cdb():
		if _dirStackIndex <= 0:
			WithColor(ErrorColor):
				print "I do not know where to go to."
		else:
			_dirStackIndex -= 1
			GotoStackIndexDir()

	[CmdDeclaration("cdf chdirforward", Description:"Go forward to the directory that yoo left by CHDIRBACK.")]
	public def Cdf():
		if _dirStackIndex+1 >= len(_dirStack):
			WithColor(ErrorColor):
				print "I do not know where to go to."
		else:
			_dirStackIndex += 1
			GotoStackIndexDir()

	def GotoStackIndexDir():
		SetCurrentDirectory(_dirStack[_dirStackIndex])
		Console.WriteLine(_dirStack[_dirStackIndex])

	[CmdDeclaration("dir ls", Description: "Show files and directories.")]
	public def Dir([CmdArgument(CmdArgumentCompletion.Directory, DefaultValue:".")] directory):
		LsDir(directory)
		LsFile(directory)

	_widthCreationDate=0
	[CmdDeclaration("SetWidthCreationDate", Description: "Defines the width of the column showing the creation date.")]
	public def SetWidthCreationDate([CmdArgument(CmdArgumentCompletion.None, DefaultValue:"-1")] width):
		iWidth = Convert.ToInt32(width)
		if iWidth < 0:
			Console.WriteLine("SetWidthCreationDate "+self._widthCreationDate.ToString())
		else:
			_widthCreationDate= iWidth
			WriteConfig()

	def WriteConfig():
		System.IO.Directory.CreateDirectory(Path.GetDirectoryName(ConfigFileName))
		using f=System.IO.File.CreateText(ConfigFileName):
			f.WriteLine("SetWidthCreationDate "+self._widthCreationDate.ToString())

	[CmdDeclaration("lsdir", Description: "Show directories.")]
	public def LsDir([CmdArgument(CmdArgumentCompletion.Directory, DefaultValue:".")] directory):
		for d in System.IO.Directory.GetDirectories(directory):
			if self._widthCreationDate > 0:
				Console.Write(System.IO.Directory.GetCreationTime(d).ToString("g")[:self._widthCreationDate].PadLeft(self._widthCreationDate)+' ')
			Console.WriteLine(d+"\\")

	[CmdDeclaration("lsfiles", Description: "Show files.")]
	public def LsFile([CmdArgument(CmdArgumentCompletion.Directory, DefaultValue:".")] directory):
		for f in System.IO.Directory.GetFiles(directory):
			if self._widthCreationDate > 0:
				Console.Write(System.IO.File.GetCreationTime(f).ToString("g")[:self._widthCreationDate].PadLeft(self._widthCreationDate)+' ')
			Console.WriteLine(f)

#region license
// Copyright (c) 2013 Harald Meyer auf'm Hofe (harald_meyer@users.sourceforge.net)
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without modification,
// are permitted provided that the following conditions are met:
//
//     * Redistributions of source code must retain the above copyright notice,
//     this list of conditions and the following disclaimer.
//     * Redistributions in binary form must reproduce the above copyright notice,
//     this list of conditions and the following disclaimer in the documentation
//     and/or other materials provided with the distribution.
//     * Neither the name of Rodrigo B. de Oliveira nor the names of its
//     contributors may be used to endorse or promote products derived from this
//     software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
// THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#endregion

namespace Booish.Mod.Os

import System
import System.IO
import System.IO.Directory

import Boo.Lang.Interpreter
import Boo.Lang.Interpreter.ColorScheme

[CmdClass("Directory")]
class Directory:
"""Implements CD, DIR, LS and PWD commands."""

	final static CONFIG_FILENAME = "booish\\Shell\\DirectoryConfig.ini"

	static ConfigFileName as string:
		get:
			return Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), CONFIG_FILENAME)

	def constructor():
		configFileName=ConfigFileName
		if System.IO.File.Exists(configFileName):
			for l in System.IO.File.OpenText(configFileName):
				s=l.Split(*':=, '.ToCharArray())
				self.GetType().GetMethod(s[0]).Invoke(self, (s[1],))

	_dirStack = []
	"""A list representing the stack of visited directories."""
	_dirStackIndex=-1

	[CmdDeclaration("cd chdir", Description:"Change the current working directory.")]
	public def Cd([CmdArgument(CmdArgumentCompletion.Directory, DefaultValue:"")] newDir):
	"""Change current directory."""
		if len(_dirStack) == 0:
			_dirStack.Add(GetCurrentDirectory())
			_dirStackIndex = 0
		if string.IsNullOrEmpty(newDir):
			newDir=Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments)
		newDir=Environment.ExpandEnvironmentVariables(newDir)
		_dirStack.RemoveAt(len(_dirStack)-1) while len(_dirStack)-1 > _dirStackIndex
		_dirStack.Add(newDir)
		_dirStack.RemoveAt(0) while len(_dirStack) > 100
		_dirStackIndex = len(_dirStack)-1
		SetCurrentDirectory(newDir)
		Console.WriteLine(GetCurrentDirectory())

	[CmdDeclaration("pwd workdir", Description:"Show the current working directory.")]
	public def Pwd():
	"""Show the current working directory."""
		Console.WriteLine(GetCurrentDirectory())

	[CmdDeclaration("cdb chdirback", Description:"Go back to the directory that you visited before.")]
	public def Cdb():
		if _dirStackIndex <= 0:
			WithColor(ErrorColor):
				print "I do not know where to go to."
		else:
			_dirStackIndex -= 1
			GotoStackIndexDir()

	[CmdDeclaration("cdf chdirforward", Description:"Go forward to the directory that yoo left by CHDIRBACK.")]
	public def Cdf():
		if _dirStackIndex+1 >= len(_dirStack):
			WithColor(ErrorColor):
				print "I do not know where to go to."
		else:
			_dirStackIndex += 1
			GotoStackIndexDir()

	def GotoStackIndexDir():
		SetCurrentDirectory(_dirStack[_dirStackIndex])
		Console.WriteLine(_dirStack[_dirStackIndex])

	[CmdDeclaration("dir ls", Description: "Show files and directories.")]
	public def Dir([CmdArgument(CmdArgumentCompletion.Directory, DefaultValue:".")] directory):
		LsDir(directory)
		LsFile(directory)

	_widthCreationDate=0
	[CmdDeclaration("SetWidthCreationDate", Description: "Defines the width of the column showing the creation date.")]
	public def SetWidthCreationDate([CmdArgument(CmdArgumentCompletion.None, DefaultValue:"-1")] width):
		iWidth = Convert.ToInt32(width)
		if iWidth < 0:
			Console.WriteLine("SetWidthCreationDate "+self._widthCreationDate.ToString())
		else:
			_widthCreationDate= iWidth
			WriteConfig()

	def WriteConfig():
		System.IO.Directory.CreateDirectory(Path.GetDirectoryName(ConfigFileName))
		using f=System.IO.File.CreateText(ConfigFileName):
			f.WriteLine("SetWidthCreationDate "+self._widthCreationDate.ToString())

	[CmdDeclaration("lsdir", Description: "Show directories.")]
	public def LsDir([CmdArgument(CmdArgumentCompletion.Directory, DefaultValue:".")] directory):
		for d in System.IO.Directory.GetDirectories(directory):
			if self._widthCreationDate > 0:
				Console.Write(System.IO.Directory.GetCreationTime(d).ToString("g")[:self._widthCreationDate].PadLeft(self._widthCreationDate)+' ')
			Console.WriteLine(d+"\\")

	[CmdDeclaration("lsfiles", Description: "Show files.")]
	public def LsFile([CmdArgument(CmdArgumentCompletion.Directory, DefaultValue:".")] directory):
		for f in System.IO.Directory.GetFiles(directory):
			if self._widthCreationDate > 0:
				Console.Write(System.IO.File.GetCreationTime(f).ToString("g")[:self._widthCreationDate].PadLeft(self._widthCreationDate)+' ')
			Console.WriteLine(f)


Fixed ducky value detection

Fixed ducky value detection

namespace BooJs.Compiler.TypeSystem

import Boo.Lang.Compiler.TypeSystem(BuiltinFunction, IType)
import Boo.Lang.Compiler.TypeSystem.TypeSystemServices as BooServices

import BooJs.Lang(Globals, Builtins, RuntimeServices)

class TypeSystemServices(BooServices):

    override static ErrorEntity = Globals.Error

    public IGeneratorType as IType
    public IGeneratorGenericType as IType

    override ExceptionType:
         get: return Map(Globals.Error)

    override protected def PreparePrimitives():
        # Setup new defaults for primitive types
        ObjectType = Map(Globals.Object)
        ObjectArrayType = ObjectType.MakeArrayType(1)

        StringType = Map(Globals.String)
        CharType = StringType  # We handle chars as strings

        BoolType = Map(Globals.Boolean)

        LongType = Map(Globals.NumberInt)
        IntType = LongType
        SByteType = LongType
        ShortType = LongType

        ULongType = Map(Globals.NumberUInt)
        UIntType = ULongType
        UShortType = ULongType
        ByteType = ULongType

        DoubleType = Map(Globals.Number)
        SingleType = DoubleType

        # In BooJs arrays are mutable too
        ArrayType = Map(typeof(Globals.Array))
        ListType = ArrayType
        # List is implemented with a generic version of Array
        #ListType = Map(typeof(Globals.Array[of Globals.Object]))

        HashType = Map(Builtins.Hash)

        # Enumerables
        IEnumerableType = Map(typeof(Globals.Iterable))
        IEnumerableGenericType = Map(typeof(Globals.Iterable[of*]))

        # TODO: Custom generator type
        IGeneratorType = Map(typeof(Globals.GeneratorIterator))
        IGeneratorGenericType = Map(typeof(Globals.GeneratorIterator[of*]))

        RegExpType = Map(Globals.RegExp)

        ICallableType = Map(Builtins.ICallable)

        DuckType = Map(Builtins.Duck)

        RuntimeServicesType = Map(RuntimeServices)
        BuiltinsType = Map(Builtins)

        # Add primitive types
        AddPrimitiveType("void", VoidType)
        AddPrimitiveType("object", ObjectType)
        AddPrimitiveType("callable", ICallableType)
        AddPrimitiveType("duck", DuckType)

        AddLiteralPrimitiveType("bool", BoolType)
        AddLiteralPrimitiveType("int", LongType)
        AddLiteralPrimitiveType("uint", ULongType)
        AddLiteralPrimitiveType("double", DoubleType)
        AddLiteralPrimitiveType("string", StringType)
        AddLiteralPrimitiveType('regex', RegExpType)

    override protected def PrepareBuiltinFunctions():
        AddBuiltin(BuiltinFunction.Len)
        AddBuiltin(BuiltinFunction.Eval);

    override public def CanBeReachedByPromotion(expectedType as IType, actualType as IType) as bool:
        # Boo allows to cast chars to integers, since in BooJs a char is just a string
        # we can't allow that kind of cast.
        if IsIntegerNumber(actualType) and expectedType == CharType:
            return false
        if IsIntegerNumber(expectedType) and actualType == CharType:
            return false

        return super(expectedType, actualType)

     new def IsSystemObject(type as IType):
        # ObjectType is mapped to our custom object so we have to check also against System.Object
        return super.IsSystemObject(type) or type is Map(System.Object)

     new def IsDuckType(type as IType) as bool:
        # ObjectType is mapped to our custom object so we have to check also against System.Object
        return super.IsDuckType(type) or (Context.Parameters.Ducky and IsSystemObject(type))

     override def IsDuckTyped(node as Boo.Lang.Compiler.Ast.Expression) as bool:
        type = node.ExpressionType
        return type is not null and IsDuckType(type)

namespace BooJs.Compiler.TypeSystem

import Boo.Lang.Compiler.TypeSystem(BuiltinFunction, IType)
import Boo.Lang.Compiler.TypeSystem.TypeSystemServices as BooServices

import BooJs.Lang(Globals, Builtins, RuntimeServices)

class TypeSystemServices(BooServices):

    override static ErrorEntity = Globals.Error

    public IGeneratorType as IType
    public IGeneratorGenericType as IType

    override ExceptionType:
         get: return Map(Globals.Error)

    override protected def PreparePrimitives():
        # Setup new defaults for primitive types
        ObjectType = Map(Globals.Object)
        ObjectArrayType = ObjectType.MakeArrayType(1)

        StringType = Map(Globals.String)
        CharType = StringType  # We handle chars as strings

        BoolType = Map(Globals.Boolean)

        LongType = Map(Globals.NumberInt)
        IntType = LongType
        SByteType = LongType
        ShortType = LongType

        ULongType = Map(Globals.NumberUInt)
        UIntType = ULongType
        UShortType = ULongType
        ByteType = ULongType

        DoubleType = Map(Globals.Number)
        SingleType = DoubleType

        # In BooJs arrays are mutable too
        ArrayType = Map(typeof(Globals.Array))
        ListType = ArrayType
        # List is implemented with a generic version of Array
        #ListType = Map(typeof(Globals.Array[of Globals.Object]))

        HashType = Map(Builtins.Hash)

        # Enumerables
        IEnumerableType = Map(typeof(Globals.Iterable))
        IEnumerableGenericType = Map(typeof(Globals.Iterable[of*]))

        # TODO: Custom generator type
        IGeneratorType = Map(typeof(Globals.GeneratorIterator))
        IGeneratorGenericType = Map(typeof(Globals.GeneratorIterator[of*]))

        RegExpType = Map(Globals.RegExp)

        ICallableType = Map(Builtins.ICallable)

        DuckType = Map(Builtins.Duck)

        RuntimeServicesType = Map(RuntimeServices)
        BuiltinsType = Map(Builtins)

        # Add primitive types
        AddPrimitiveType("void", VoidType)
        AddPrimitiveType("object", ObjectType)
        AddPrimitiveType("callable", ICallableType)
        AddPrimitiveType("duck", DuckType)

        AddLiteralPrimitiveType("bool", BoolType)
        AddLiteralPrimitiveType("int", LongType)
        AddLiteralPrimitiveType("uint", ULongType)
        AddLiteralPrimitiveType("double", DoubleType)
        AddLiteralPrimitiveType("string", StringType)
        AddLiteralPrimitiveType('regex', RegExpType)

    override protected def PrepareBuiltinFunctions():
        AddBuiltin(BuiltinFunction.Len)
        AddBuiltin(BuiltinFunction.Eval);

    override public def CanBeReachedByPromotion(expectedType as IType, actualType as IType) as bool:
        # Boo allows to cast chars to integers, since in BooJs a char is just a string
        # we can't allow that kind of cast.
        if IsIntegerNumber(actualType) and expectedType == CharType:
            return false
        if IsIntegerNumber(expectedType) and actualType == CharType:
            return false

        return super(expectedType, actualType)

     new def IsSystemObject(type as IType):
        # TODO: Is this ever used?
        # ObjectType is mapped to our custom object
        return type == ObjectType or type == DuckType or type == Map(System.Object)