Map custom hash type

Map custom hash 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)

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]))

        # 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)


empty input can be memoized as well

empty input can be memoized as well

namespace Boo.OMeta

import Boo.Adt
import System.Collections.Generic

data OMetaMatch(Input as OMetaInput) = SuccessfulMatch(Value as object) | FailedMatch()

callable OMetaRule(context as OMetaGrammar, input as OMetaInput) as OMetaMatch

interface OMetaGrammar:

	def InstallRule(ruleName as string, rule as OMetaRule)
	def Apply(context as OMetaGrammar, rule as string, input as OMetaInput) as OMetaMatch
	def SuperApply(context as OMetaGrammar, rule as string, input as OMetaInput) as OMetaMatch

class OMetaGrammarRoot(OMetaGrammar):

	class MemoKey:
		final _rule as string
		final _input as OMetaInput

		def constructor(rule as string, input as OMetaInput):
			_rule = rule
			_input = input

		override def Equals(o):
			other as MemoKey = o
			return _input is other._input and _rule is other._rule

		override def GetHashCode():
			return _rule.GetHashCode() ^ _input.GetHashCode()

	_rules = Dictionary[of string, OMetaRule]()
	_memo = Dictionary[of MemoKey, OMetaMatch]()

	def InstallRule(ruleName as string, rule as OMetaRule):
		_rules[ruleName] = rule

	def Apply(context as OMetaGrammar, rule as string, input as OMetaInput):

		key = MemoKey(rule, input)
		memo as OMetaMatch
		if _memo.TryGetValue(key, memo):
			return memo

		_memo[key] = FailedMatch(input)
		memo = Eval(context, rule, input)
		_memo[key] = memo
		return memo

	def Eval(context as OMetaGrammar, rule as string, input as OMetaInput):
		found as OMetaRule
		if _rules.TryGetValue(rule, found):
			return found(context, input)
		return RuleMissing(context, rule, input)

	def SuperApply(context as OMetaGrammar, rule as string, input as OMetaInput):
		return Apply(context, rule, input)

	virtual def RuleMissing(context as OMetaGrammar, rule as string, input as OMetaInput) as OMetaMatch:
		raise "Rule '${rule}' missing!"

class OMetaGrammarPrototype(OMetaGrammarRoot):

	def constructor():
		InstallRule("whitespace", makeRule(char.IsWhiteSpace))
		InstallRule("letter", makeRule(char.IsLetter))
		InstallRule("digit", makeRule(char.IsDigit))
		InstallRule("_", makeRule({ o | return true }))

class OMetaDelegatingGrammar(OMetaGrammarRoot):

	_prototype as OMetaGrammar

	def constructor(prototype as OMetaGrammar):
		_prototype = prototype

	override def RuleMissing(context as OMetaGrammar, rule as string, input as OMetaInput):
		return SuperApply(context, rule, input)

	override def SuperApply(context as OMetaGrammar, rule as string, input as OMetaInput):
		return _prototype.SuperApply(context, rule, input)

def makeRule(predicate as System.Predicate[of object]) as OMetaRule:
	def rule(context as OMetaGrammar, input as OMetaInput) as OMetaMatch:
		if not input.IsEmpty and predicate(input.Head):
			return SuccessfulMatch(input.Tail, input.Head)
		return FailedMatch(input)
	return rule

namespace Boo.OMeta

import Boo.Adt
import System.Collections.Generic

data OMetaMatch(Input as OMetaInput) = SuccessfulMatch(Value as object) | FailedMatch()

callable OMetaRule(context as OMetaGrammar, input as OMetaInput) as OMetaMatch

interface OMetaGrammar:

	def InstallRule(ruleName as string, rule as OMetaRule)
	def Apply(context as OMetaGrammar, rule as string, input as OMetaInput) as OMetaMatch
	def SuperApply(context as OMetaGrammar, rule as string, input as OMetaInput) as OMetaMatch

class OMetaGrammarRoot(OMetaGrammar):

	class MemoKey:
		final _rule as string
		final _input as OMetaInput

		def constructor(rule as string, input as OMetaInput):
			_rule = rule
			_input = input

		override def Equals(o):
			other as MemoKey = o
			return _input is other._input and _rule is other._rule

		override def GetHashCode():
			return _rule.GetHashCode() ^ _input.GetHashCode()

	_rules = Dictionary[of string, OMetaRule]()
	_memo = Dictionary[of MemoKey, OMetaMatch]()

	def InstallRule(ruleName as string, rule as OMetaRule):
		_rules[ruleName] = rule

	def Apply(context as OMetaGrammar, rule as string, input as OMetaInput):

		if input.IsEmpty:
			return Eval(context, rule, input)

		key = MemoKey(rule, input)
		memo as OMetaMatch
		if _memo.TryGetValue(key, memo):
			return memo

		_memo[key] = FailedMatch(input)
		memo = Eval(context, rule, input)
		_memo[key] = memo
		return memo

	def Eval(context as OMetaGrammar, rule as string, input as OMetaInput):
		found as OMetaRule
		if _rules.TryGetValue(rule, found):
			return found(context, input)
		return RuleMissing(context, rule, input)

	def SuperApply(context as OMetaGrammar, rule as string, input as OMetaInput):
		return Apply(context, rule, input)

	virtual def RuleMissing(context as OMetaGrammar, rule as string, input as OMetaInput) as OMetaMatch:
		raise "Rule '${rule}' missing!"

class OMetaGrammarPrototype(OMetaGrammarRoot):

	def constructor():
		InstallRule("whitespace", makeRule(char.IsWhiteSpace))
		InstallRule("letter", makeRule(char.IsLetter))
		InstallRule("digit", makeRule(char.IsDigit))
		InstallRule("_", makeRule({ o | return true }))

class OMetaDelegatingGrammar(OMetaGrammarRoot):

	_prototype as OMetaGrammar

	def constructor(prototype as OMetaGrammar):
		_prototype = prototype

	override def RuleMissing(context as OMetaGrammar, rule as string, input as OMetaInput):
		return SuperApply(context, rule, input)

	override def SuperApply(context as OMetaGrammar, rule as string, input as OMetaInput):
		return _prototype.SuperApply(context, rule, input)

def makeRule(predicate as System.Predicate[of object]) as OMetaRule:
	def rule(context as OMetaGrammar, input as OMetaInput) as OMetaMatch:
		if not input.IsEmpty and predicate(input.Head):
			return SuccessfulMatch(input.Tail, input.Head)
		return FailedMatch(input)
	return rule


workaround for gtk# bug #61703

workaround for gtk# bug #61703

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

import System
import GLib from "glib-sharp" as GLib
import Gtk from "gtk-sharp"
import GtkSourceView from "gtksourceview-sharp"

class BooEditor(ScrolledWindow):

	static _booSourceLanguage = SourceLanguagesManager().GetLanguageFromMimeType("text/x-boo")

	_buffer = SourceBuffer(_booSourceLanguage, Highlight: true)
	_view = SourceView(_buffer, ShowLineNumbers: true, AutoIndent: true)

	def constructor():
		self.SetPolicy(PolicyType.Automatic, PolicyType.Automatic)
		self.Add(_view)

	Text:
		get:
			return _buffer.Text

class MainWindow(Window):

	_status = Statusbar(HasResizeGrip: false)
	_notebook = Notebook(TabPos: PositionType.Top, Scrollable: true)
	_accelGroup = AccelGroup()
	_editors = [] # workaround for gtk# bug #61703

	def constructor():
		super("Boo Explorer")

		self.AddAccelGroup(_accelGroup)
		self.SetDefaultSize(600, 400)
		self.DeleteEvent += OnDelete

		vbox = VBox(false, 1)
		vbox.PackStart(CreateMenuBar(), false, false, 0)
		vbox.PackStart(_notebook, true, true, 0)
		vbox.PackStart(_status, false, false, 0)

		self.Add(vbox)

		self.NewDocument()

	def NewDocument():
		editor = BooEditor()
		_notebook.AppendPage(editor, Label("unnamed.boo"))
		_editors.Add(editor)
		editor.ShowAll()

	private def CreateMenuBar():
		mb = MenuBar()

		file = Menu()
		file.Append(ImageMenuItem(Stock.New, _accelGroup, Activated: _menuItemNew_Activated))
		file.Append(ImageMenuItem(Stock.Open, _accelGroup, Activated: _menuItemOpen_Activated))
		file.Append(ImageMenuItem(Stock.Save, _accelGroup, Activated: _menuItemSave_Activated))
		file.Append(SeparatorMenuItem())
		file.Append(ImageMenuItem(Stock.Quit, _accelGroup, Activated: _menuItemExit_Activated))

		edit = Menu()
		edit.Append(ImageMenuItem(Stock.Undo, _accelGroup))
		edit.Append(ImageMenuItem(Stock.Redo, _accelGroup))
		edit.Append(SeparatorMenuItem())
		edit.Append(ImageMenuItem(Stock.Cut, _accelGroup))
		edit.Append(ImageMenuItem(Stock.Copy, _accelGroup))
		edit.Append(ImageMenuItem(Stock.Paste, _accelGroup))
		edit.Append(ImageMenuItem(Stock.Delete, _accelGroup))
		edit.Append(SeparatorMenuItem())
		edit.Append(ImageMenuItem(Stock.Preferences, _accelGroup))

		tools = Menu()
		tools.Append(ImageMenuItem(Stock.Execute, _accelGroup, Activated: _menuItemExecute_Activated))

		mb.Append(MenuItem("File", Submenu: file))
		mb.Append(MenuItem("Edit", Submenu: edit))
		mb.Append(MenuItem("Tools", Submenu: tools))
		return mb

	private def _menuItemExecute_Activated(sender, args as EventArgs):
		// can't do the simpler:
		// editor as BooEditor = _notebook.CurrentPageWidget
		// because of gtk# bug #61703

		editor as BooEditor = _editors[_notebook.CurrentPage]

		compiler = Boo.Lang.Compiler.BooCompiler()
		compiler.Parameters.Input.Add(Boo.Lang.Compiler.IO.StringInput("<script>", editor.Text))
		compiler.Parameters.Pipeline = Boo.Lang.Compiler.Pipelines.Run()

		result = compiler.Run()
		print(result.Errors.ToString()) if len(result.Errors)

	private def _menuItemNew_Activated(sender, args as EventArgs):
		self.NewDocument()

	private def _menuItemOpen_Activated(sender, args as EventArgs):
		pass

	private def _menuItemSave_Activated(sender, args as EventArgs):
		pass

	private def _menuItemExit_Activated(sender, args as EventArgs):
		Application.Quit()

	def OnDelete(sender, args as DeleteEventArgs):
		Application.Quit()
		args.RetVal = true

Application.Init()

MainWindow().ShowAll()

Application.Run()

import System
import Gtk from "gtk-sharp"
import GtkSourceView from "gtksourceview-sharp"

class BooEditor(ScrolledWindow):

	static _booSourceLanguage = SourceLanguagesManager().GetLanguageFromMimeType("text/x-boo")

	_buffer = SourceBuffer(_booSourceLanguage, Highlight: true)
	_view = SourceView(_buffer, ShowLineNumbers: true, AutoIndent: true)

	def constructor():
		super(Adjustment(IntPtr.Zero), Adjustment(IntPtr.Zero))
		self.SetPolicy(PolicyType.Automatic, PolicyType.Automatic)
		self.Add(_view)

	Text:
		get:
			return _buffer.Text

class MainWindow(Window):

	_status = Statusbar(HasResizeGrip: false)
	_notebook = Notebook(TabPos: PositionType.Top, Scrollable: true)
	_accelGroup = AccelGroup()

	def constructor():
		super("Boo Explorer")

		self.AddAccelGroup(_accelGroup)
		self.SetDefaultSize(600, 400)
		self.DeleteEvent += OnDelete

		vbox = VBox(false, 1)
		vbox.PackStart(CreateMenuBar(), false, false, 0)
		vbox.PackStart(_notebook, true, true, 0)
		vbox.PackStart(_status, false, false, 0)

		self.Add(vbox)

		self.NewDocument()

	def NewDocument():
		editor = BooEditor()
		_notebook.AppendPage(editor, Label("unnamed.boo"))
		editor.ShowAll()

	private def CreateMenuBar():
		mb = MenuBar()

		file = Menu()
		file.Append(ImageMenuItem(Stock.New, _accelGroup, Activated: _menuItemNew_Activated))
		file.Append(ImageMenuItem(Stock.Open, _accelGroup, Activated: _menuItemOpen_Activated))
		file.Append(ImageMenuItem(Stock.Save, _accelGroup, Activated: _menuItemSave_Activated))
		file.Append(SeparatorMenuItem())
		file.Append(ImageMenuItem(Stock.Quit, _accelGroup, Activated: _menuItemExit_Activated))

		edit = Menu()
		edit.Append(ImageMenuItem(Stock.Undo, _accelGroup))
		edit.Append(ImageMenuItem(Stock.Redo, _accelGroup))
		edit.Append(SeparatorMenuItem())
		edit.Append(ImageMenuItem(Stock.Cut, _accelGroup))
		edit.Append(ImageMenuItem(Stock.Copy, _accelGroup))
		edit.Append(ImageMenuItem(Stock.Paste, _accelGroup))
		edit.Append(ImageMenuItem(Stock.Delete, _accelGroup))
		edit.Append(SeparatorMenuItem())
		edit.Append(ImageMenuItem(Stock.Preferences, _accelGroup))

		tools = Menu()
		tools.Append(ImageMenuItem(Stock.Execute, _accelGroup, Activated: _menuItemExecute_Activated))

		mb.Append(MenuItem("File", Submenu: file))
		mb.Append(MenuItem("Edit", Submenu: edit))
		mb.Append(MenuItem("Tools", Submenu: tools))
		return mb

	private def _menuItemExecute_Activated(sender, args as EventArgs):
		// trying to track down a gtk-sharp bug
		// after a few executions (garbage collection?)
		// CurrentPageWidget will start to return a simple
		// ScrolledWindow (no longer a BooEditor)
		print(_notebook.CurrentPage)
		print(_notebook.CurrentPageWidget)
		editor = _notebook.CurrentPageWidget as BooEditor
		return if editor is null

		compiler = Boo.Lang.Compiler.BooCompiler()
		compiler.Parameters.Input.Add(Boo.Lang.Compiler.IO.StringInput("<script>", editor.Text))
		compiler.Parameters.Pipeline = Boo.Lang.Compiler.Pipelines.Run()

		result = compiler.Run()
		print(result.Errors.ToString()) if len(result.Errors)

	private def _menuItemNew_Activated(sender, args as EventArgs):
		self.NewDocument()

	private def _menuItemOpen_Activated(sender, args as EventArgs):
		pass

	private def _menuItemSave_Activated(sender, args as EventArgs):
		pass

	private def _menuItemExit_Activated(sender, args as EventArgs):
		Application.Quit()

	def OnDelete(sender, args as DeleteEventArgs):
		Application.Quit()
		args.RetVal = true

Application.Init()

MainWindow().ShowAll()

Application.Run()


MSBuild task: report an error if Boo exits with exit code != 0.

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

#region license
// Copyright (c) 2003, 2004, 2005 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.Microsoft.Build.Tasks

import Microsoft.Build.Framework
import Microsoft.Build.Tasks
import Microsoft.Build.Utilities
import System
import System.Diagnostics
import System.IO
import System.Globalization
import System.Text.RegularExpressions
import System.Threading

class Booc(ManagedCompiler):
"""
Represents the Boo compiler MSBuild task.

Authors:
	Sorin Ionescu (sorin.ionescu@gmail.com)
"""
	def constructor():
		NoLogo = true

	Pipeline:
	"""
	Gets/sets a specific pipeline to add to the compiler process.
	"""
		get:
			return Bag['Pipelines'] as string
		set:
			Bag['Pipelines'] = value
	NoStandardLib:
	"""
	Gets/sets if we want to link to the standard libraries or not.
	"""
		get:
			return GetBoolParameterWithDefault("NoStandardLib", false)
		set:
			Bag['NoStandardLib'] = value
	WhiteSpaceAgnostic:
	"""
	Gets/sets if we want to use whitespace agnostic mode.
	"""
		get:
			return GetBoolParameterWithDefault("WhiteSpaceAgnostic", false)
		set:
			Bag['WhiteSpaceAgnostic'] = value
	Ducky:
	"""
	Gets/sets if we want to use ducky mode.
	"""
		get:
			return GetBoolParameterWithDefault("Ducky", false)
		set:
			Bag['Ducky'] = value
	Verbosity:
	"""
	Gets/sets the verbosity level.
	"""
		get:
			return Bag['Verbosity'] as string
		set:
			Bag['Verbosity'] = value

	Culture:
	"""
	Gets/sets the culture.
	"""
		get:
			return Bag['Culture'] as string
		set:
			Bag['Culture'] = value

	SourceDirectory:
	"""
	Gets/sets the source directory.
	"""
		get:
			return Bag['Source Directory'] as string
		set:
			Bag['Source Directory'] = value

	DefineSymbols:
	"""
	Gets/sets the conditional compilation symbols.
	"""
		get:
			return Bag['DefineSymbols'] as string
		set:
			Bag['DefineSymbols'] = value

	CheckForOverflowUnderflow:
	"""
	Gets/sets if integer overlow checking is enabled.
	"""
		get:
			return GetBoolParameterWithDefault("CheckForOverflowUnderflow", true)
		set:
			Bag['CheckForOverflowUnderflow'] = value

	DisabledWarnings:
	"""
	Gets/sets a comma-separated list of warnings that should be disabled.
	"""
		get:
			return Bag['DisabledWarnings'] as string
		set:
			Bag['DisabledWarnings'] = value

	WarningsAsErrors:
	"""
	Gets/sets a comma-separated list of warnings that should be treated as errors.
	"""
		get:
			return Bag['WarningsAsErrors'] as string
		set:
			Bag['WarningsAsErrors'] = value

	Strict:
	"""
	Gets/sets whether strict mode is enabled.
	"""
		get:
			return GetBoolParameterWithDefault("Strict", false)
		set:
			Bag['Strict'] = value

	ToolName:
	"""
	Gets the tool name.
	"""
		get:
			return "booc.exe"

	GenerateFullPaths:
	"""
	If set to true the task will output warnings and errors with full file paths
	"""
		get:
			return GetBoolParameterWithDefault("GenerateFullPaths", false)
		set:
			Bag["GenerateFullPaths"] = value

	override def Execute():
	"""
	Executes the task.

	Returns:
		true if the task completed successfully; otherwise, false.
	"""
		boocCommandLine = CommandLineBuilderExtension()
		AddResponseFileCommands(boocCommandLine)

		warningPattern = regex(
			'^(?<file>.*?)(\\((?<line>\\d+),(?<column>\\d+)\\):)?' +
				'(\\s?)(?BCW\\d{4}):(\\s)WARNING:(\\s)(?<message>.*)$',
			RegexOptions.Compiled)
		# Captures the file, line, column, code, and message from a BOO warning
		# in the form of: Program.boo(1,1): BCW0000: WARNING: This is a warning.

		errorPattern = regex(
			'^(((?<file>.*?)\\((?<line>\\d+),(?<column>\\d+)\\): )?' +
				'(?BCE\\d{4})|(?<errorType>Fatal) error):' +
				'( Boo.Lang.Compiler.CompilerError:)?' +
				' (?<message>.*?)($| --->)',
			RegexOptions.Compiled |
				RegexOptions.ExplicitCapture |
				RegexOptions.Multiline)
		/*
		 * Captures the file, line, column, code, error type, and message from a
		 * BOO error of the form of:
		 * 1. Program.boo(1,1): BCE0000: This is an error.
		 * 2. Program.boo(1,1): BCE0000: Boo.Lang.Compiler.CompilerError:
		 *    	This is an error. ---> Program.boo:4:19: This is an error
		 * 3. BCE0000: This is an error.
		 * 4. Fatal error: This is an error.
		 *
		 * The second line of the following error format is not cought because
		 * .NET does not support if|then|else in regular expressions,
		 * and the regex will be horrible complicated.
		 * The second line is as worthless as the first line.
		 * Therefore, it is not worth implementing it.
		 *
		 * 	Fatal error: This is an error.
		 * 	Parameter name: format.
		 */

		buildSuccess = true
		outputLine = String.Empty
		errorLine = String.Empty
		readingDoneEvents = (ManualResetEvent(false), ManualResetEvent(false))

		boocProcessStartInfo = ProcessStartInfo(
			FileName: GenerateFullPathToTool(),
			Arguments: boocCommandLine.ToString(),
			ErrorDialog: false,
			CreateNoWindow: true,
			RedirectStandardError: true,
			RedirectStandardInput: false,
			RedirectStandardOutput: true,
			UseShellExecute: false)

		boocProcess = Process(StartInfo: boocProcessStartInfo)

		parseOutput = def(line as string):
			warningPatternMatch = warningPattern.Match(line)
			errorPatternMatch = errorPattern.Match(line)

			if warningPatternMatch.Success:
				lineOut = 0
				columnOut = 0
				int.TryParse(warningPatternMatch.Groups['line'].Value, lineOut)
				int.TryParse(warningPatternMatch.Groups['column'].Value, columnOut)
				Log.LogWarning(
					null,
					warningPatternMatch.Groups['code'].Value,
					null,
					GetFilePathToWarningOrError(warningPatternMatch.Groups['file'].Value),
					lineOut,
					columnOut,
					0,
					0,
					warningPatternMatch.Groups['message'].Value)

			elif errorPatternMatch.Success:
				code = errorPatternMatch.Groups['code'].Value
				code = 'BCE0000' if string.IsNullOrEmpty(code)
				file = GetFilePathToWarningOrError(errorPatternMatch.Groups['file'].Value)
				file = 'BOOC' if string.IsNullOrEmpty(file)

				try:
					lineNumber = int.Parse(
						errorPatternMatch.Groups['line'].Value,
						NumberStyles.Integer)

				except as FormatException:
					lineNumber = 0

				try:
					columnNumber = int.Parse(
						errorPatternMatch.Groups['column'].Value,
						NumberStyles.Integer)

				except as FormatException:
					columnNumber = 0

				Log.LogError(
					errorPatternMatch.Groups['errorType'].Value.ToLower(),
					code,
					null,
					file,
					lineNumber,
					columnNumber,
					0,
					0,
					errorPatternMatch.Groups['message'].Value)

				buildSuccess = false

			else:
				Log.LogMessage(MessageImportance.Normal, line)

		readStandardOutput = def():
			while true:
				outputLine = boocProcess.StandardOutput.ReadLine()

				if outputLine:
					parseOutput(outputLine)

				else:
					readingDoneEvents[0].Set()
					break

		readStandardError = def():
			while true:
				errorLine = boocProcess.StandardError.ReadLine()

				if errorLine:
					parseOutput(errorLine)

				else:
					readingDoneEvents[1].Set()
					break

		standardOutputReadingThread = Thread(readStandardOutput as ThreadStart)
		standardErrorReadingThread = Thread(readStandardError as ThreadStart)
		# Two threads are required (MSDN); otherwise, a deadlock WILL occur.

		try:
			boocProcess.Start()

			Log.LogMessage(
				MessageImportance.High,
				"${ToolName} ${boocProcess.StartInfo.Arguments}",
				null)

			standardOutputReadingThread.Start()
			standardErrorReadingThread.Start()

			WaitHandle.WaitAny((readingDoneEvents[0],))
			WaitHandle.WaitAny((readingDoneEvents[1],))
			# MSBuild runs on an STA thread, and WaitHandle.WaitAll()
			# is not supported.

			boocProcess.WaitForExit()
			if boocProcess.ExitCode != 0:
				if buildSuccess:
					// Report an error if booc exits with error code but we didn't
					// receive any error.
					Log.LogError("booc exited with code ${boocProcess.ExitCode}")
				buildSuccess = false
		except e as Exception:
			Log.LogErrorFromException(e)
			buildSuccess = false

		ensure:
			boocProcess.Close()

		return buildSuccess

	protected override def AddCommandLineCommands(
		commandLine as CommandLineBuilderExtension):
	"""
	Adds command line commands.

	Remarks:
		It prevents <ManagedCompiler> from adding the standard commands.
	"""
			pass

	protected override def AddResponseFileCommands(
		commandLine as CommandLineBuilderExtension):
	"""
	Generates the Boo compiler command line.

	Returns:
		The Boo compiler command line.
	"""
		commandLine.AppendSwitchIfNotNull('-t:', TargetType)
		commandLine.AppendSwitchIfNotNull('-o:', OutputAssembly)
		commandLine.AppendSwitchIfNotNull('-c:', Culture)
		commandLine.AppendSwitchIfNotNull('-srcdir:', SourceDirectory)
		commandLine.AppendSwitchIfNotNull('-keyfile:', KeyFile)
		commandLine.AppendSwitchIfNotNull('-keycontainer:', KeyContainer)
		commandLine.AppendSwitchIfNotNull('-p:', Pipeline)
		commandLine.AppendSwitchIfNotNull('-define:', DefineSymbols)
		commandLine.AppendSwitchIfNotNull("-lib:", AdditionalLibPaths, ",")
		commandLine.AppendSwitchIfNotNull('-nowarn:', DisabledWarnings)

		if TreatWarningsAsErrors:
			commandLine.AppendSwitch('-warnaserror') // all warnings are errors
		else:
			commandLine.AppendSwitchIfNotNull('-warnaserror:', WarningsAsErrors) // only specific warnings are errors

		if NoLogo:
			commandLine.AppendSwitch('-nologo')
		if NoConfig:
			commandLine.AppendSwitch('-noconfig')
		if NoStandardLib:
			commandLine.AppendSwitch('-nostdlib')
		if DelaySign:
			commandLine.AppendSwitch('-delaysign')
		if WhiteSpaceAgnostic:
			commandLine.AppendSwitch('-wsa')
		if Ducky:
			commandLine.AppendSwitch('-ducky')
		if Utf8Output:
			commandLine.AppendSwitch('-utf8')
		if Strict:
			commandLine.AppendSwitch('-strict')

		if EmitDebugInformation:
			commandLine.AppendSwitch('-debug+')
		else:
			commandLine.AppendSwitch('-debug-')

		if CheckForOverflowUnderflow:
			commandLine.AppendSwitch('-checked+')
		else:
			commandLine.AppendSwitch('-checked-')

		if ResponseFiles:
			for rsp in ResponseFiles:
				commandLine.AppendSwitchIfNotNull("@", rsp.ItemSpec)

		if References:
			for reference in References:
				commandLine.AppendSwitchIfNotNull('-r:', reference.ItemSpec)

		if Resources:
			for resource in Resources:
				commandLine.AppendSwitchIfNotNull('-resource:', resource.ItemSpec)

		if Verbosity:
			if string.Compare(
					Verbosity,
					'Normal',
					StringComparison.InvariantCultureIgnoreCase) == 0:
				pass

			elif string.Compare(
					Verbosity,
					'Warning',
					StringComparison.InvariantCultureIgnoreCase) == 0:

				commandLine.AppendSwitch('-v')

			elif string.Compare(
					Verbosity,
					'Info',
					StringComparison.InvariantCultureIgnoreCase) == 0:

				commandLine.AppendSwitch('-vv')

			elif string.Compare(
					Verbosity,
					'Verbose',
					StringComparison.InvariantCultureIgnoreCase) == 0:

				commandLine.AppendSwitch('-vvv')

			else:
				Log.LogErrorWithCodeFromResources(
					'Vbc.EnumParameterHasInvalidValue',
					'Verbosity',
					Verbosity,
					'Normal, Warning, Info, Verbose')

		commandLine.AppendFileNamesIfNotNull(Sources, ' ')

	protected override def GenerateFullPathToTool():
	"""
	Generats the full path to booc.exe.
	"""
		path = ""

		if ToolPath:
			path = Path.Combine(ToolPath, ToolName)

		return path if File.Exists(path)

		path = Path.Combine(
			Path.GetDirectoryName(typeof(Booc).Assembly.Location),
			ToolName)

		return path if File.Exists(path)

		path = ToolLocationHelper.GetPathToDotNetFrameworkFile(
			ToolName,
			TargetDotNetFrameworkVersion.VersionLatest)

		return path if File.Exists(path)

		/* //removed this error message for mono compatibility
		Log.LogErrorWithCodeFromResources(
			"General.FrameworksFileNotFound",
			ToolName,
			ToolLocationHelper.GetDotNetFrameworkVersionFolderPrefix(
				TargetDotNetFrameworkVersion.Version20))
		*/
		path = "booc"

		return path

	private def GetFilePathToWarningOrError(file as string):
		if GenerateFullPaths:
			return Path.GetFullPath(file)
		else:
			return file

#region license
// Copyright (c) 2003, 2004, 2005 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.Microsoft.Build.Tasks

import Microsoft.Build.Framework
import Microsoft.Build.Tasks
import Microsoft.Build.Utilities
import System
import System.Diagnostics
import System.IO
import System.Globalization
import System.Text.RegularExpressions
import System.Threading

class Booc(ManagedCompiler):
"""
Represents the Boo compiler MSBuild task.

Authors:
	Sorin Ionescu (sorin.ionescu@gmail.com)
"""
	def constructor():
		NoLogo = true

	Pipeline:
	"""
	Gets/sets a specific pipeline to add to the compiler process.
	"""
		get:
			return Bag['Pipelines'] as string
		set:
			Bag['Pipelines'] = value
	NoStandardLib:
	"""
	Gets/sets if we want to link to the standard libraries or not.
	"""
		get:
			return GetBoolParameterWithDefault("NoStandardLib", false)
		set:
			Bag['NoStandardLib'] = value
	WhiteSpaceAgnostic:
	"""
	Gets/sets if we want to use whitespace agnostic mode.
	"""
		get:
			return GetBoolParameterWithDefault("WhiteSpaceAgnostic", false)
		set:
			Bag['WhiteSpaceAgnostic'] = value
	Ducky:
	"""
	Gets/sets if we want to use ducky mode.
	"""
		get:
			return GetBoolParameterWithDefault("Ducky", false)
		set:
			Bag['Ducky'] = value
	Verbosity:
	"""
	Gets/sets the verbosity level.
	"""
		get:
			return Bag['Verbosity'] as string
		set:
			Bag['Verbosity'] = value

	Culture:
	"""
	Gets/sets the culture.
	"""
		get:
			return Bag['Culture'] as string
		set:
			Bag['Culture'] = value

	SourceDirectory:
	"""
	Gets/sets the source directory.
	"""
		get:
			return Bag['Source Directory'] as string
		set:
			Bag['Source Directory'] = value

	DefineSymbols:
	"""
	Gets/sets the conditional compilation symbols.
	"""
		get:
			return Bag['DefineSymbols'] as string
		set:
			Bag['DefineSymbols'] = value

	CheckForOverflowUnderflow:
	"""
	Gets/sets if integer overlow checking is enabled.
	"""
		get:
			return GetBoolParameterWithDefault("CheckForOverflowUnderflow", true)
		set:
			Bag['CheckForOverflowUnderflow'] = value

	DisabledWarnings:
	"""
	Gets/sets a comma-separated list of warnings that should be disabled.
	"""
		get:
			return Bag['DisabledWarnings'] as string
		set:
			Bag['DisabledWarnings'] = value

	WarningsAsErrors:
	"""
	Gets/sets a comma-separated list of warnings that should be treated as errors.
	"""
		get:
			return Bag['WarningsAsErrors'] as string
		set:
			Bag['WarningsAsErrors'] = value

	Strict:
	"""
	Gets/sets whether strict mode is enabled.
	"""
		get:
			return GetBoolParameterWithDefault("Strict", false)
		set:
			Bag['Strict'] = value

	ToolName:
	"""
	Gets the tool name.
	"""
		get:
			return "booc.exe"

	GenerateFullPaths:
	"""
	If set to true the task will output warnings and errors with full file paths
	"""
		get:
			return GetBoolParameterWithDefault("GenerateFullPaths", false)
		set:
			Bag["GenerateFullPaths"] = value

	override def Execute():
	"""
	Executes the task.

	Returns:
		true if the task completed successfully; otherwise, false.
	"""
		boocCommandLine = CommandLineBuilderExtension()
		AddResponseFileCommands(boocCommandLine)

		warningPattern = regex(
			'^(?<file>.*?)(\\((?<line>\\d+),(?<column>\\d+)\\):)?' +
				'(\\s?)(?BCW\\d{4}):(\\s)WARNING:(\\s)(?<message>.*)$',
			RegexOptions.Compiled)
		# Captures the file, line, column, code, and message from a BOO warning
		# in the form of: Program.boo(1,1): BCW0000: WARNING: This is a warning.

		errorPattern = regex(
			'^(((?<file>.*?)\\((?<line>\\d+),(?<column>\\d+)\\): )?' +
				'(?BCE\\d{4})|(?<errorType>Fatal) error):' +
				'( Boo.Lang.Compiler.CompilerError:)?' +
				' (?<message>.*?)($| --->)',
			RegexOptions.Compiled |
				RegexOptions.ExplicitCapture |
				RegexOptions.Multiline)
		/*
		 * Captures the file, line, column, code, error type, and message from a
		 * BOO error of the form of:
		 * 1. Program.boo(1,1): BCE0000: This is an error.
		 * 2. Program.boo(1,1): BCE0000: Boo.Lang.Compiler.CompilerError:
		 *    	This is an error. ---> Program.boo:4:19: This is an error
		 * 3. BCE0000: This is an error.
		 * 4. Fatal error: This is an error.
		 *
		 * The second line of the following error format is not cought because
		 * .NET does not support if|then|else in regular expressions,
		 * and the regex will be horrible complicated.
		 * The second line is as worthless as the first line.
		 * Therefore, it is not worth implementing it.
		 *
		 * 	Fatal error: This is an error.
		 * 	Parameter name: format.
		 */

		buildSuccess = true
		outputLine = String.Empty
		errorLine = String.Empty
		readingDoneEvents = (ManualResetEvent(false), ManualResetEvent(false))

		boocProcessStartInfo = ProcessStartInfo(
			FileName: GenerateFullPathToTool(),
			Arguments: boocCommandLine.ToString(),
			ErrorDialog: false,
			CreateNoWindow: true,
			RedirectStandardError: true,
			RedirectStandardInput: false,
			RedirectStandardOutput: true,
			UseShellExecute: false)

		boocProcess = Process(StartInfo: boocProcessStartInfo)

		parseOutput = def(line as string):
			warningPatternMatch = warningPattern.Match(line)
			errorPatternMatch = errorPattern.Match(line)

			if warningPatternMatch.Success:
				lineOut = 0
				columnOut = 0
				int.TryParse(warningPatternMatch.Groups['line'].Value, lineOut)
				int.TryParse(warningPatternMatch.Groups['column'].Value, columnOut)
				Log.LogWarning(
					null,
					warningPatternMatch.Groups['code'].Value,
					null,
					GetFilePathToWarningOrError(warningPatternMatch.Groups['file'].Value),
					lineOut,
					columnOut,
					0,
					0,
					warningPatternMatch.Groups['message'].Value)

			elif errorPatternMatch.Success:
				code = errorPatternMatch.Groups['code'].Value
				code = 'BCE0000' if string.IsNullOrEmpty(code)
				file = GetFilePathToWarningOrError(errorPatternMatch.Groups['file'].Value)
				file = 'BOOC' if string.IsNullOrEmpty(file)

				try:
					lineNumber = int.Parse(
						errorPatternMatch.Groups['line'].Value,
						NumberStyles.Integer)

				except as FormatException:
					lineNumber = 0

				try:
					columnNumber = int.Parse(
						errorPatternMatch.Groups['column'].Value,
						NumberStyles.Integer)

				except as FormatException:
					columnNumber = 0

				Log.LogError(
					errorPatternMatch.Groups['errorType'].Value.ToLower(),
					code,
					null,
					file,
					lineNumber,
					columnNumber,
					0,
					0,
					errorPatternMatch.Groups['message'].Value)

				buildSuccess = false

			else:
				Log.LogMessage(MessageImportance.Normal, line)

		readStandardOutput = def():
			while true:
				outputLine = boocProcess.StandardOutput.ReadLine()

				if outputLine:
					parseOutput(outputLine)

				else:
					readingDoneEvents[0].Set()
					break

		readStandardError = def():
			while true:
				errorLine = boocProcess.StandardError.ReadLine()

				if errorLine:
					parseOutput(errorLine)

				else:
					readingDoneEvents[1].Set()
					break

		standardOutputReadingThread = Thread(readStandardOutput as ThreadStart)
		standardErrorReadingThread = Thread(readStandardError as ThreadStart)
		# Two threads are required (MSDN); otherwise, a deadlock WILL occur.

		try:
			boocProcess.Start()

			Log.LogMessage(
				MessageImportance.High,
				"${ToolName} ${boocProcess.StartInfo.Arguments}",
				null)

			standardOutputReadingThread.Start()
			standardErrorReadingThread.Start()

			WaitHandle.WaitAny((readingDoneEvents[0],))
			WaitHandle.WaitAny((readingDoneEvents[1],))
			# MSBuild runs on an STA thread, and WaitHandle.WaitAll()
			# is not supported.

		except e as Exception:
			Log.LogErrorFromException(e)
			buildSuccess = false

		ensure:
			boocProcess.Close()

		return buildSuccess

	protected override def AddCommandLineCommands(
		commandLine as CommandLineBuilderExtension):
	"""
	Adds command line commands.

	Remarks:
		It prevents <ManagedCompiler> from adding the standard commands.
	"""
			pass

	protected override def AddResponseFileCommands(
		commandLine as CommandLineBuilderExtension):
	"""
	Generates the Boo compiler command line.

	Returns:
		The Boo compiler command line.
	"""
		commandLine.AppendSwitchIfNotNull('-t:', TargetType)
		commandLine.AppendSwitchIfNotNull('-o:', OutputAssembly)
		commandLine.AppendSwitchIfNotNull('-c:', Culture)
		commandLine.AppendSwitchIfNotNull('-srcdir:', SourceDirectory)
		commandLine.AppendSwitchIfNotNull('-keyfile:', KeyFile)
		commandLine.AppendSwitchIfNotNull('-keycontainer:', KeyContainer)
		commandLine.AppendSwitchIfNotNull('-p:', Pipeline)
		commandLine.AppendSwitchIfNotNull('-define:', DefineSymbols)
		commandLine.AppendSwitchIfNotNull("-lib:", AdditionalLibPaths, ",")
		commandLine.AppendSwitchIfNotNull('-nowarn:', DisabledWarnings)

		if TreatWarningsAsErrors:
			commandLine.AppendSwitch('-warnaserror') // all warnings are errors
		else:
			commandLine.AppendSwitchIfNotNull('-warnaserror:', WarningsAsErrors) // only specific warnings are errors

		if NoLogo:
			commandLine.AppendSwitch('-nologo')
		if NoConfig:
			commandLine.AppendSwitch('-noconfig')
		if NoStandardLib:
			commandLine.AppendSwitch('-nostdlib')
		if DelaySign:
			commandLine.AppendSwitch('-delaysign')
		if WhiteSpaceAgnostic:
			commandLine.AppendSwitch('-wsa')
		if Ducky:
			commandLine.AppendSwitch('-ducky')
		if Utf8Output:
			commandLine.AppendSwitch('-utf8')
		if Strict:
			commandLine.AppendSwitch('-strict')

		if EmitDebugInformation:
			commandLine.AppendSwitch('-debug+')
		else:
			commandLine.AppendSwitch('-debug-')

		if CheckForOverflowUnderflow:
			commandLine.AppendSwitch('-checked+')
		else:
			commandLine.AppendSwitch('-checked-')

		if ResponseFiles:
			for rsp in ResponseFiles:
				commandLine.AppendSwitchIfNotNull("@", rsp.ItemSpec)

		if References:
			for reference in References:
				commandLine.AppendSwitchIfNotNull('-r:', reference.ItemSpec)

		if Resources:
			for resource in Resources:
				commandLine.AppendSwitchIfNotNull('-resource:', resource.ItemSpec)

		if Verbosity:
			if string.Compare(
					Verbosity,
					'Normal',
					StringComparison.InvariantCultureIgnoreCase) == 0:
				pass

			elif string.Compare(
					Verbosity,
					'Warning',
					StringComparison.InvariantCultureIgnoreCase) == 0:

				commandLine.AppendSwitch('-v')

			elif string.Compare(
					Verbosity,
					'Info',
					StringComparison.InvariantCultureIgnoreCase) == 0:

				commandLine.AppendSwitch('-vv')

			elif string.Compare(
					Verbosity,
					'Verbose',
					StringComparison.InvariantCultureIgnoreCase) == 0:

				commandLine.AppendSwitch('-vvv')

			else:
				Log.LogErrorWithCodeFromResources(
					'Vbc.EnumParameterHasInvalidValue',
					'Verbosity',
					Verbosity,
					'Normal, Warning, Info, Verbose')

		commandLine.AppendFileNamesIfNotNull(Sources, ' ')

	protected override def GenerateFullPathToTool():
	"""
	Generats the full path to booc.exe.
	"""
		path = ""

		if ToolPath:
			path = Path.Combine(ToolPath, ToolName)

		return path if File.Exists(path)

		path = Path.Combine(
			Path.GetDirectoryName(typeof(Booc).Assembly.Location),
			ToolName)

		return path if File.Exists(path)

		path = ToolLocationHelper.GetPathToDotNetFrameworkFile(
			ToolName,
			TargetDotNetFrameworkVersion.VersionLatest)

		return path if File.Exists(path)

		/* //removed this error message for mono compatibility
		Log.LogErrorWithCodeFromResources(
			"General.FrameworksFileNotFound",
			ToolName,
			ToolLocationHelper.GetDotNetFrameworkVersionFolderPrefix(
				TargetDotNetFrameworkVersion.Version20))
		*/
		path = "booc"

		return path

	private def GetFilePathToWarningOrError(file as string):
		if GenerateFullPaths:
			return Path.GetFullPath(file)
		else:
			return file


remove unnecessary attributes

remove unnecessary attributes

import System.Reflection

[assembly: AssemblyTitle("Boo.Adt")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("Boo.Adt")]
[assembly: AssemblyCulture("")]
[assembly: AssemblyVersion("1.0.*")]

import System.Reflection
import System.Runtime.InteropServices

// General Information about an assembly is controlled through the following
// set of attributes. Change these attribute values to modify the information
// associated with an assembly.
[assembly: AssemblyTitle("Boo.Adt")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("Boo.Adt")]
[assembly: AssemblyCopyright("Copyright 2010")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]

// This sets the default COM visibility of types in the assembly to invisible.
// If you need to expose a type to COM, use [ComVisible(true)] on that type.
[assembly: ComVisible(false)]

// The assembly version has following format :
//
// Major.Minor.Build.Revision
//
// You can specify all values by your own or you can build default build and revision
// numbers with the '*' character (the default):

[assembly: AssemblyVersion("1.0.*")]


enum fields

enum fields

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


Malkovich! Malkovich! Malkovich!

Malkovich! Malkovich! Malkovich!

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

"""
Malkovich!
Malkovich!
Malkovich!
"""
callable Malkovich() as Malkovich

def malkovich() as Malkovich:
	print("Malkovich!")
	return malkovich

malkovich()()()

"""
Echo!
Echo!
Echo!
"""
callable Echo() as Echo

def echo() as Echo:
	print("Echo!")
	return echo

echo()()()


fixed BOO-202

fixed BOO-202

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

#region license
// Copyright (c) 2004, Daniel Grunwald (daniel@danielgrunwald.de)
// All rights reserved.
//
// BooBinding is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version.
//
// Boo Explorer is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Foobar; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
#endregion

namespace BooBinding

import System
import System.Collections
import System.IO
import System.Diagnostics
import System.Text
import System.Text.RegularExpressions
import System.CodeDom.Compiler

import ICSharpCode.Core.Services

import ICSharpCode.SharpDevelop.Internal.Project
import ICSharpCode.SharpDevelop.Gui
import ICSharpCode.SharpDevelop.Services

class BooBindingCompilerManager:
	static _normalError  = /(?<file>.*)\((?<line>\d+),(?<column>\d+)\):\s+(?<number>[\d\w]+):\s+(?<message>.*)/
	static _generalError = /(?<error>.+)\s+(?<number>[\d\w]+):\s+(?<message>.*)/

	def GetCompiledOutputName(fileName as string) as string:
		return Path.ChangeExtension(fileName, ".exe")

	def GetCompiledOutputName(project as IProject) as string:
		p as BooProject = project;
		compilerparameters as BooCompilerParameters = p.ActiveConfiguration

		fileUtilityService as FileUtilityService = ServiceManager.Services.GetService(typeof(FileUtilityService))
		exe = fileUtilityService.GetDirectoryNameWithSeparator(compilerparameters.OutputDirectory) + compilerparameters.OutputAssembly
		if (compilerparameters.CompileTarget == CompileTarget.Library):
			return exe + ".dll"
		else:
			return exe + ".exe"

	def CanCompile(fileName as string) as bool:
		return Path.GetExtension(fileName).ToLower() == ".boo";

	static _compilerNotFound = "Boo compiler not found.\nYou have to specify the path where booc.exe is in the project options!\n"

	private def MakeError(text as string):
		cr = CompilerResults(TempFileCollection())
		cr.Errors.Add(CompilerError(ErrorText: text))
		return DefaultCompilerResult(cr, text)

	private def Compile(compilerparameters as BooCompilerParameters, fileNames as (string), outputFile as string, p as IProject) as ICompilerResult:
		fileUtilityService as FileUtilityService = ServiceManager.Services.GetService(typeof(FileUtilityService))
		messageService as IMessageService = ServiceManager.Services.GetService(typeof(IMessageService))

		if compilerparameters.BooPath == "":
			messageService.ShowError(_compilerNotFound)
			return MakeError(_compilerNotFound)
		booDir = fileUtilityService.GetDirectoryNameWithSeparator(compilerparameters.BooPath)
		compilerName = booDir + "booc.exe"

		if not File.Exists(compilerName):
			messageService.ShowError(_compilerNotFound)
			return MakeError(_compilerNotFound)

		cmd = StringBuilder()
		cmd.Append("\"${compilerName}\"")

		cmd.Append(" -o:\"${outputFile}\"")

		cmd.Append(" -vv") if compilerparameters.Verbose

		cmd.Append(" -t:")
		if (compilerparameters.CompileTarget == CompileTarget.WinExe):
			cmd.Append("winexe")
		else:
			if (compilerparameters.CompileTarget == CompileTarget.Library):
				cmd.Append("library");
			else:
				cmd.Append("exe");

		// Default references are already added by booc.rsp

		if p != null:
			// write references
			for lib as ProjectReference in p.ProjectReferences:
				cmd.Append(" \"-r:${lib.GetReferencedFileName(p)}\"");
			// write embedded resources
			for finfo as ProjectFile in p.ProjectFiles:
				if finfo.Subtype != Subtype.Directory and finfo.BuildAction == BuildAction.EmbedAsResource:
					cmd.Append(" \"-resource:${finfo.Name}\"")

		for fileName as string in fileNames:
			cmd.Append(" \"${Path.GetFullPath(fileName)}\"")

		outstr = cmd.ToString()
		tf = TempFileCollection()
		output = ""
		error = ""
		Executor.ExecWaitWithCapture(outstr, Path.GetFullPath(compilerparameters.OutputDirectory), tf, output, error)

		result = ParseOutput(tf, output)

		outputDirectory = Path.GetDirectoryName(outputFile)

		CopyToDirIgnoringErrors(Path.Combine(booDir, "Boo.dll"), outputDirectory)
		for lib as ProjectReference in p.ProjectReferences:
			if lib.LocalCopy:
				CopyToDirIgnoringErrors(
					lib.GetReferencedFileName(p),
					outputDirectory)

		File.Delete(output)
		File.Delete(error)
		return result

	def CopyToDirIgnoringErrors(fname as string, outputDirectory as string):
		try:
			File.Copy(fname, Path.Combine(outputDirectory, Path.GetFileName(fname)))
		except:
			pass

	def CompileFile(fileName as string, compilerparameters as BooCompilerParameters) as ICompilerResult:
		compilerparameters.OutputDirectory = Path.GetDirectoryName(fileName)
		compilerparameters.OutputAssembly  = Path.GetFileNameWithoutExtension(fileName)

		return Compile(compilerparameters, (fileName,), GetCompiledOutputName(fileName), null)

	def CompileProject(project as BooProject) as ICompilerResult:
		compilerparameters as BooCompilerParameters = project.ActiveConfiguration

		fileNames = ArrayList()

		for	finfo as ProjectFile in project.ProjectFiles:
			if finfo.Subtype != Subtype.Directory:
				if finfo.BuildAction == BuildAction.Compile:
						fileNames.Add(finfo.Name)

		exe = GetCompiledOutputName(project)
		if compilerparameters.CompileTarget == CompileTarget.WinExe:
			WriteManifestFile(exe)

		return Compile(compilerparameters, fileNames.ToArray(typeof(string)), exe, project)

	def WriteManifestFile(fileName as string):
		manifestFile = fileName + ".manifest"
		return if File.Exists(manifestFile)
		using sw = StreamWriter(manifestFile):
			sw.WriteLine("<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>")
			sw.WriteLine("")
			sw.WriteLine("<assembly xmlns=\"urn:schemas-microsoft-com:asm.v1\" manifestVersion=\"1.0\">")
			sw.WriteLine("	<dependency>")
			sw.WriteLine("		<dependentAssembly>")
			sw.WriteLine("			<assemblyIdentity")
			sw.WriteLine("				type=\"win32\"")
			sw.WriteLine("				name=\"Microsoft.Windows.Common-Controls\"")
			sw.WriteLine("				version=\"6.0.0.0\"")
			sw.WriteLine("				processorArchitecture=\"X86\"")
			sw.WriteLine("				publicKeyToken=\"6595b64144ccf1df\"")
			sw.WriteLine("				language=\"*\"")
			sw.WriteLine("			/>")
			sw.WriteLine("		</dependentAssembly>")
			sw.WriteLine("	</dependency>")
			sw.WriteLine("</assembly>")

	def ParseOutput(tf as TempFileCollection, file as string) as ICompilerResult:
		compilerOutput = StringBuilder();

		using sr = File.OpenText(file):
			cr = CompilerResults(tf)

			curLine = sr.ReadLine()
			while curLine != null:
				compilerOutput.Append(curLine)
				compilerOutput.Append("\n")
				curLine = curLine.Trim();
				if curLine.Length == 0:
					curLine = sr.ReadLine()
					continue

				error = CompilerError()

				// try to match standard errors
				match = _normalError.Match(curLine)
				if match.Success:
					error.Column      = Int32.Parse(match.Result('${column}'));
					error.Line        = Int32.Parse(match.Result('${line}'));
					error.FileName    = Path.GetFullPath(match.Result('${file}'));
					error.ErrorNumber = match.Result('${number}');
					error.IsWarning   = error.ErrorNumber.StartsWith("BCW")
					error.ErrorText   = match.Result('${message}');
				else:
					match = _generalError.Match(curLine); // try to match general csc errors
					if match.Success:
						error.IsWarning   = match.Result('${error}') == "warning";
						error.ErrorNumber = match.Result('${number}');
						error.ErrorText   = match.Result('${message}');
					else:
						// give up and skip the line
						curLine = sr.ReadLine()
						continue

				cr.Errors.Add(error);

				curLine = sr.ReadLine()
		return DefaultCompilerResult(cr, compilerOutput.ToString())

#region license
// Copyright (c) 2004, Daniel Grunwald (daniel@danielgrunwald.de)
// All rights reserved.
//
// BooBinding is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version.
//
// Boo Explorer is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Foobar; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
#endregion

namespace BooBinding

import System
import System.Collections
import System.IO
import System.Diagnostics
import System.Text
import System.Text.RegularExpressions
import System.CodeDom.Compiler

import ICSharpCode.Core.Services

import ICSharpCode.SharpDevelop.Internal.Project
import ICSharpCode.SharpDevelop.Gui
import ICSharpCode.SharpDevelop.Services

class BooBindingCompilerManager:
	static _normalError  = /(?<file>.*)\((?<line>\d+),(?<column>\d+)\):\s+(?<number>[\d\w]+):\s+(?<message>.*)/
	static _generalError = /(?<error>.+)\s+(?<number>[\d\w]+):\s+(?<message>.*)/

	def GetCompiledOutputName(fileName as string) as string:
		return Path.ChangeExtension(fileName, ".exe")

	def GetCompiledOutputName(project as IProject) as string:
		p as BooProject = project;
		compilerparameters as BooCompilerParameters = p.ActiveConfiguration

		fileUtilityService as FileUtilityService = ServiceManager.Services.GetService(typeof(FileUtilityService))
		exe = fileUtilityService.GetDirectoryNameWithSeparator(compilerparameters.OutputDirectory) + compilerparameters.OutputAssembly
		if (compilerparameters.CompileTarget == CompileTarget.Library):
			return exe + ".dll"
		else:
			return exe + ".exe"

	def CanCompile(fileName as string) as bool:
		return Path.GetExtension(fileName).ToLower() == ".boo";

	static _compilerNotFound = "Boo compiler not found.\nYou have to specify the path where booc.exe is in the project options!\n"

	private def MakeError(text as string):
		cr = CompilerResults(TempFileCollection())
		cr.Errors.Add(CompilerError(ErrorText: text))
		return DefaultCompilerResult(cr, text)

	private def Compile(compilerparameters as BooCompilerParameters, fileNames as (string), outputFile as string, p as IProject) as ICompilerResult:
		fileUtilityService as FileUtilityService = ServiceManager.Services.GetService(typeof(FileUtilityService))
		messageService as IMessageService = ServiceManager.Services.GetService(typeof(IMessageService))

		if compilerparameters.BooPath == "":
			messageService.ShowError(_compilerNotFound)
			return MakeError(_compilerNotFound)
		booDir = fileUtilityService.GetDirectoryNameWithSeparator(compilerparameters.BooPath)
		compilerName = booDir + "booc.exe"

		if not File.Exists(compilerName):
			messageService.ShowError(_compilerNotFound)
			return MakeError(_compilerNotFound)

		cmd = StringBuilder()
		cmd.Append("\"${compilerName}\"")

		cmd.Append(" -o:\"${outputFile}\"")

		cmd.Append(" -vv") if compilerparameters.Verbose

		cmd.Append(" -t:")
		if (compilerparameters.CompileTarget == CompileTarget.WinExe):
			cmd.Append("winexe")
		else:
			if (compilerparameters.CompileTarget == CompileTarget.Library):
				cmd.Append("library");
			else:
				cmd.Append("exe");

		// Default references are already added by booc.rsp

		if p != null:
			// write references
			for lib as ProjectReference in p.ProjectReferences:
				cmd.Append(" \"-r:${lib.GetReferencedFileName(p)}\"");
			// write embedded resources
			for finfo as ProjectFile in p.ProjectFiles:
				if finfo.Subtype != Subtype.Directory and finfo.BuildAction == BuildAction.EmbedAsResource:
					cmd.Append(" \"-resource:${finfo.Name}\"")

		for fileName as string in fileNames:
			cmd.Append(" \"${Path.GetFullPath(fileName)}\"")

		outstr = cmd.ToString()
		tf = TempFileCollection()
		output = ""
		error = ""
		Executor.ExecWaitWithCapture(outstr, Path.GetFullPath(compilerparameters.OutputDirectory), tf, output, error)

		result = ParseOutput(tf, output)

		outputDirectory = Path.GetDirectoryName(outputFile)

		CopyToDirIgnoringErrors(Path.Combine(booDir, "Boo.dll"), outputDirectory)
		for lib as ProjectReference in p.ProjectReferences:
			if lib.LocalCopy:
				CopyToDirIgnoringErrors(
					lib.GetReferencedFileName(p),
					outputDirectory)

		File.Delete(output)
		File.Delete(error)
		return result

	def CopyToDirIgnoringErrors(fname as string, outputDirectory as string):
		try:
			File.Copy(fname, Path.Combine(outputDirectory, Path.GetFileName(fname)))
		except:
			pass

	def CompileFile(fileName as string, compilerparameters as BooCompilerParameters) as ICompilerResult:
		compilerparameters.OutputDirectory = Path.GetDirectoryName(fileName)
		compilerparameters.OutputAssembly  = Path.GetFileNameWithoutExtension(fileName)

		return Compile(compilerparameters, (fileName,), GetCompiledOutputName(fileName), null)

	def CompileProject(project as BooProject) as ICompilerResult:
		compilerparameters as BooCompilerParameters = project.ActiveConfiguration

		fileNames = ArrayList()

		for	finfo as ProjectFile in project.ProjectFiles:
			if finfo.Subtype != Subtype.Directory:
				if finfo.BuildAction == BuildAction.Compile:
						fileNames.Add(finfo.Name)

		exe = GetCompiledOutputName(project)
		if compilerparameters.CompileTarget == CompileTarget.WinExe:
			WriteManifestFile(exe)

		return Compile(compilerparameters, fileNames.ToArray(typeof(string)), exe, project)

	def WriteManifestFile(fileName as string):
		manifestFile = fileName + ".manifest"
		return if File.Exists(manifestFile)
		using sw = StreamWriter(manifestFile):
			sw.WriteLine("<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>")
			sw.WriteLine("")
			sw.WriteLine("<assembly xmlns=\"urn:schemas-microsoft-com:asm.v1\" manifestVersion=\"1.0\">")
			sw.WriteLine("	<dependency>")
			sw.WriteLine("		<dependentAssembly>")
			sw.WriteLine("			<assemblyIdentity")
			sw.WriteLine("				type=\"win32\"")
			sw.WriteLine("				name=\"Microsoft.Windows.Common-Controls\"")
			sw.WriteLine("				version=\"6.0.0.0\"")
			sw.WriteLine("				processorArchitecture=\"X86\"")
			sw.WriteLine("				publicKeyToken=\"6595b64144ccf1df\"")
			sw.WriteLine("				language=\"*\"")
			sw.WriteLine("			/>")
			sw.WriteLine("		</dependentAssembly>")
			sw.WriteLine("	</dependency>")
			sw.WriteLine("</assembly>")

	def ParseOutput(tf as TempFileCollection, file as string) as ICompilerResult:
		compilerOutput = StringBuilder();

		using sr = File.OpenText(file):
			cr = CompilerResults(tf)

			curLine = sr.ReadLine()
			while curLine != null:
				compilerOutput.Append(curLine)
				compilerOutput.Append("\n")
				curLine = curLine.Trim();
				if curLine.Length == 0:
					curLine = sr.ReadLine()
					continue

				error = CompilerError()

				// try to match standard errors
				match = _normalError.Match(curLine)
				if match.Success:
					error.Column      = Int32.Parse(match.Result('${column}'));
					error.Line        = Int32.Parse(match.Result('${line}'));
					error.FileName    = Path.GetFullPath(match.Result('${file}'));
					//error.IsWarning   = match.Result('${error}') == "warning";
					error.ErrorNumber = match.Result('${number}');
					error.ErrorText   = match.Result('${message}');
				else:
					match = _generalError.Match(curLine); // try to match general csc errors
					if match.Success:
						error.IsWarning   = match.Result('${error}') == "warning";
						error.ErrorNumber = match.Result('${number}');
						error.ErrorText   = match.Result('${message}');
					else:
						// give up and skip the line
						curLine = sr.ReadLine()
						continue

				cr.Errors.Add(error);

				curLine = sr.ReadLine()
		return DefaultCompilerResult(cr, compilerOutput.ToString())


code completion patch by Arron Washington

git-svn-id: c3b8989232654601f1acea7403f771adaaa44a81@1296 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

"""
Interactive Forms-based Console
"""

namespace booish.gui

import System
import System.Text
import System.IO
import System.Reflection
import booish
import System.Windows.Forms
import System.Drawing
import System.Runtime.InteropServices

class KeyChar:

	public static Enter = chr(Keys.Enter)

	public static Dot = chr('.')

	public static Back = chr(Keys.Back)

	public static Esc = chr(Keys.Escape)

class CompletionBox(ListBox):

	_interpreter as InteractiveInterpreter

	def constructor(interpreter):
		self._interpreter = interpreter
		self.Visible = false

	def Fill(type as System.Type):

		members = []
		for member in type.GetMembers():
			if IsValidSuggestion(member):
				if member isa FieldInfo:
					field = member as FieldInfo
					members.Add("${field.Name} as ${getBooTypeName(field.FieldType)}")
				elif member isa PropertyInfo:
					property = member as PropertyInfo
					getField = ("", "getter,")[property.CanRead]
					setField = ("", "setter")[property.CanWrite]
					members.Add("${member.Name} as ${getBooTypeName(property.PropertyType)} (${getField} ${setField})")
				elif member isa MethodInfo:
					method = member as MethodInfo
					params = join("${param.Name} as ${getBooTypeName(param.ParameterType)}"
										for param in method.GetParameters())
					returnValue = ""
					returnValue = " as ${getBooTypeName(method.ReturnType)}" if method.ReturnType is not void
					members.Add("${member.Name}(${params})${returnValue}")

		Items.Clear()
		for item in members.Sort():
			Items.Add(item)

	def Show(pos as Point):
		self.Location = pos
		self.Visible = true
		self.Focus()

	private def IsValidSuggestion(member as MemberInfo):
		return false if not IsPublic(member)
		method = member as MethodBase
		if method is not null:
			return false if method.IsSpecialName
		return true

	private def IsPublic(member as MemberInfo):
		if MemberTypes.Method == member.MemberType:
			return cast(MethodBase, member).IsPublic
		if MemberTypes.Property == member.MemberType:
			p as PropertyInfo = member
			return (p.GetGetMethod() or p.GetSetMethod()).IsPublic
		if MemberTypes.Field == member.MemberType:
			return cast(FieldInfo, member).IsPublic
		return true

	override def OnLostFocus(args as EventArgs):
		self.Visible = false
		super(args)

	override def OnKeyPress(args as KeyPressEventArgs):
		finish = def ():
			Parent.Focus()
			args.Handled = true

		if args.KeyChar in KeyChar.Esc, KeyChar.Back:
			finish()
		elif KeyChar.Enter == args.KeyChar:
			cast(TextBox, Parent).SelectedText = /\w+/.Match(SelectedItem).Groups[0].Value
			finish()
		else:
			super(args)

	private def getBooTypeName(type as System.Type):
		return _interpreter.getBooTypeName(type)

class PromptBox(TextBox):

	enum InputState:
		SingleLine = 0
		Block = 1

	_state = InputState.SingleLine

	_block = System.IO.StringWriter()

	_console = StringWriter()

	[getter(Interpreter)]
	_interpreter = InteractiveInterpreter(
								RememberLastValue: true,
								Print: print)

	_completionBox = CompletionBox(_interpreter)

	def constructor():
		self.Dock = DockStyle.Fill
		self.Multiline = true
		self.AcceptsTab = true
		self.ScrollBars = ScrollBars.Vertical
		_interpreter.References.Add(typeof(TextBox).Assembly)
		_interpreter.References.Add(typeof(Font).Assembly)
		_interpreter.SetValue("inspect", inspect)

		Controls.Add(_completionBox)

		prompt()

	CaretPos:
		get:
			p as Point
			assert booish.gui.externs.User32.GetCaretPos(p)
			return p

	def GetCurrentLine():
		line = Lines[-1][4:]
		print("")
		return line

	def SingleLineInputState():
		code = GetCurrentLine()

		if code[-1:] in ":", "\\":
			_state = InputState.Block
			_block.GetStringBuilder().Length = 0
			_block.WriteLine(code)
		else:
			Eval(code)

	def BlockInputState():
		code = GetCurrentLine()
		if 0 == len(code):
			Eval(_block.ToString())
			_state = InputState.SingleLine
		else:
			_block.WriteLine(code)

	override def OnKeyPress(args as KeyPressEventArgs):
		if KeyChar.Enter == args.KeyChar:
			try:
				(SingleLineInputState, BlockInputState)[_state]()
			except x:
				print(x)
			prompt()
			args.Handled = true
		elif KeyChar.Dot == args.KeyChar:
			self.SelectedText = "."
			DotComplete()
			args.Handled = true

		super(args)

	override def OnResize(args as EventArgs):
		_completionBox.Size = System.Drawing.Size(Width*.65, Height*.4)
		super(args)

	def DotComplete():
		m = /((\w|\.)+)\.$/.Match(self.Lines[-1])
		if m.Success:
			// only simple identifiers right now
			expression = m.Groups[1].Value
			if /^\w+$/.IsMatch(expression):
				type = _interpreter.Lookup(expression)
				if type is not null:
					_completionBox.Fill(type)
					_completionBox.Show(CaretPos)

	def Eval(code as string):
		saved = Console.Out
		Console.SetOut(_console)
		try:
			_interpreter.LoopEval(code)
		ensure:
			FlushConsole()
			Console.SetOut(saved)

	def FlushConsole():
		AppendText(_console.ToString())
		_console.GetStringBuilder().Length = 0

	def print(msg):
		AppendText("${msg}\r\n")

	def inspect([required] obj):
		f = Form(Text: "Object Inspector [${obj}]")
		f.Controls.Add(PropertyGrid(
							Dock: DockStyle.Fill,
							SelectedObject: obj,
							Font: Font))
		f.Show()
		return f

	def prompt():
		AppendText((">>> ", "... ")[_state])

def chr(key as Keys):
	return cast(IConvertible, cast(int, key)).ToChar(null)

def chr(s as string):
	assert len(s) == 1
	return s[0]

#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

"""
Interactive Forms-based Console
"""

namespace booish.gui

import System
import System.IO
import System.Reflection
import booish
import System.Windows.Forms
import System.Drawing
import System.Runtime.InteropServices

class KeyChar:

	public static Enter = chr(Keys.Enter)

	public static Dot = chr('.')

	public static Back = chr(Keys.Back)

	public static Esc = chr(Keys.Escape)

class CompletionBox(ListBox):

	def constructor():
		self.Visible = false

	def Fill(type as System.Type):

		members = {}
		for member in type.GetMembers():
			if member.Name not in members:
				if IsValidSuggestion(member):
					members.Add(member.Name, member)

		Items.Clear()
		for item in List(members.Keys).Sort():
			Items.Add(item)

	def Show(pos as Point):
		self.Location = pos
		self.Visible = true
		self.Focus()

	private def IsValidSuggestion(member as MemberInfo):
		return false if not IsPublic(member)
		method = member as MethodBase
		if method is not null:
			return false if method.IsSpecialName
		return true

	private def IsPublic(member as MemberInfo):
		if MemberTypes.Method == member.MemberType:
			return cast(MethodBase, member).IsPublic
		if MemberTypes.Property == member.MemberType:
			p as PropertyInfo = member
			return (p.GetGetMethod() or p.GetSetMethod()).IsPublic
		if MemberTypes.Field == member.MemberType:
			return cast(FieldInfo, member).IsPublic
		return true

	override def OnLostFocus(args as EventArgs):
		self.Visible = false
		super(args)

	override def OnKeyPress(args as KeyPressEventArgs):
		finish = def ():
			Parent.Focus()
			args.Handled = true

		if args.KeyChar in KeyChar.Esc, KeyChar.Back:
			finish()
		elif KeyChar.Enter == args.KeyChar:
			cast(TextBox, Parent).SelectedText = SelectedItem
			finish()
		else:
			super(args)

class PromptBox(TextBox):

	enum InputState:
		SingleLine = 0
		Block = 1

	_state = InputState.SingleLine

	_block = System.IO.StringWriter()

	_console = StringWriter()

	[getter(Interpreter)]
	_interpreter = InteractiveInterpreter(
								RememberLastValue: true,
								Print: print)

	_completionBox = CompletionBox()

	def constructor():
		self.Dock = DockStyle.Fill
		self.Multiline = true
		self.AcceptsTab = true
		self.ScrollBars = ScrollBars.Vertical
		_interpreter.References.Add(typeof(TextBox).Assembly)
		_interpreter.References.Add(typeof(Font).Assembly)
		_interpreter.SetValue("inspect", inspect)

		Controls.Add(_completionBox)

		prompt()

	CaretPos:
		get:
			p as Point
			assert booish.gui.externs.User32.GetCaretPos(p)
			return p

	def GetCurrentLine():
		line = Lines[-1][4:]
		print("")
		return line

	def SingleLineInputState():
		code = GetCurrentLine()

		if code[-1:] in ":", "\\":
			_state = InputState.Block
			_block.GetStringBuilder().Length = 0
			_block.WriteLine(code)
		else:
			Eval(code)

	def BlockInputState():
		code = GetCurrentLine()
		if 0 == len(code):
			Eval(_block.ToString())
			_state = InputState.SingleLine
		else:
			_block.WriteLine(code)

	override def OnKeyPress(args as KeyPressEventArgs):
		if KeyChar.Enter == args.KeyChar:
			try:
				(SingleLineInputState, BlockInputState)[_state]()
			except x:
				print(x)
			prompt()
			args.Handled = true
		elif KeyChar.Dot == args.KeyChar:
			self.SelectedText = "."
			DotComplete()
			args.Handled = true

		super(args)

	override def OnResize(args as EventArgs):
		_completionBox.Size = System.Drawing.Size(Width*.5, Height*.4)
		super(args)

	def DotComplete():
		m = /((\w|\.)+)\.$/.Match(self.Lines[-1])
		if m.Success:
			// only simple identifiers right now
			expression = m.Groups[1].Value
			if /^\w+$/.IsMatch(expression):
				type = _interpreter.Lookup(expression)
				if type is not null:
					_completionBox.Fill(type)
					_completionBox.Show(CaretPos)

	def Eval(code as string):
		saved = Console.Out
		Console.SetOut(_console)
		try:
			_interpreter.LoopEval(code)
		ensure:
			FlushConsole()
			Console.SetOut(saved)

	def FlushConsole():
		AppendText(_console.ToString())
		_console.GetStringBuilder().Length = 0

	def print(msg):
		AppendText("${msg}\r\n")

	def inspect([required] obj):
		f = Form(Text: "Object Inspector [${obj}]")
		f.Controls.Add(PropertyGrid(
							Dock: DockStyle.Fill,
							SelectedObject: obj,
							Font: Font))
		f.Show()
		return f

	def prompt():
		AppendText((">>> ", "... ")[_state])

def chr(key as Keys):
	return cast(IConvertible, cast(int, key)).ToChar(null)

def chr(s as string):
	assert len(s) == 1
	return s[0]


preparing

preparing

git-svn-id: c3b8989232654601f1acea7403f771adaaa44a81@1564 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.Tests

import NUnit.Framework
import Boo.IO
import System.IO
import System.Text

[TestFixture]
class TextFileFixture:

	[Test]
	def TestReadFile():

		fname = WriteTempFile("cabeÃ§Ã£o", Encoding.Default)
		Assert.AreEqual("cabeÃ§Ã£o", TextFile.ReadFile(fname))

		fname = WriteTempFile("cabeÃ§Ã£o", Encoding.UTF8)
		Assert.AreEqual("cabeÃ§Ã£o", TextFile.ReadFile(fname))

	[Test]
	def TestWriteFile():
		TextFile.WriteFile(fname=Path.GetTempFileName(), "zuÃ§aqÃ¼istÃ£o")
		Assert.AreEqual("zuÃ§aqÃ¼istÃ£o", ReadUTF8File(fname))

	def ReadUTF8File(fname as string):
		using reader=File.OpenText(fname):
			return reader.ReadToEnd()

	def WriteTempFile(content as string, encoding as Encoding) as string:
		using writer=StreamWriter(File.OpenWrite(fname=Path.GetTempFileName()), encoding):
			writer.Write(content)
			return fname