ESC clears the current line; exec allows the execution of external scripts in the context of the interpreter

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

#region license
// Copyright (c) 2004, Rodrigo B. de Oliveira (rbo@acm.org)
// All rights reserved.
//
// This file is part of Boo Explorer.
//
// Boo Explorer 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

"""
Interactive Forms-based Console
"""
namespace booish.gui

import System
import System.Drawing
import System.IO
import System.Windows.Forms
import ICSharpCode.TextEditor
import ICSharpCode.TextEditor.Document
import ICSharpCode.TextEditor.Actions
import ICSharpCode.TextEditor.Gui.CompletionWindow
import Boo.Lang.Compiler.TypeSystem

interface ICompletionWindowImageProvider:
	ImageList as ImageList:
		get
	NamespaceIndex as int:
		get
	ClassIndex as int:
		get
	InterfaceIndex as int:
		get
	EnumIndex as int:
		get
	StructIndex as int:
		get
	CallableIndex as int:
		get
	MethodIndex as int:
		get
	FieldIndex as int:
		get
	LiteralIndex as int:
		get
	PropertyIndex as int:
		get
	EventIndex as int:
		get

class InteractiveInterpreterControl(TextEditorControl):

	enum InputState:
		SingleLine = 0
		Block = 1

	class NullCompletionWindowImageProvider(ICompletionWindowImageProvider):

		public static final Instance = NullCompletionWindowImageProvider()

		[getter(ImageList)]
		_imageList = System.Windows.Forms.ImageList()

		NamespaceIndex as int:
			get:
				return 0
		ClassIndex as int:
			get:
				return 0
		InterfaceIndex as int:
			get:
				return 0
		EnumIndex as int:
			get:
				return 0
		StructIndex as int:
			get:
				return 0
		CallableIndex as int:
			get:
				return 0
		MethodIndex as int:
			get:
				return 0
		FieldIndex as int:
			get:
				return 0
		LiteralIndex as int:
			get:
				return 0
		PropertyIndex as int:
			get:
				return 0
		EventIndex as int:
			get:
				return 0

	class LineHistory:

		_lines = []
		_current = 0

		event CurrentLineChanged as EventHandler

		def Add([required] line as string):
			if len(line) > 0 and line != LastLine:
				_lines.Add(line)
			_current = len(_lines)

		LastLine as string:
			get:
				return null if 0 == len(_lines)
				return _lines[-1]

		CurrentLine as string:
			get:
				return null if 0 == len(_lines)
				return _lines[_current]

		def Up():
			MoveTo(_current - 1)

		def Down():
			MoveTo(_current + 1)

		def MoveTo(index as int):
			return if 0 == len(_lines)
			old = _current
			_current = index % len(_lines)
			if old != _current:
				CurrentLineChanged(self, EventArgs.Empty)

	_state = InputState.SingleLine

	_block = System.IO.StringWriter()

	_console = System.IO.StringWriter()

	[getter(Interpreter)]
	_interpreter as Boo.Lang.Interpreter.InteractiveInterpreter

	_codeCompletionWindow as CodeCompletionWindow

	[property(CompletionWindowImageProvider, value is not null)]
	_imageProvider as ICompletionWindowImageProvider = NullCompletionWindowImageProvider()

	_lineHistory as LineHistory

	// HACK: when the completion window is shown through CTRL+SPACE
	// it behaves very strangely, the best we can do right now is
	// to prevent the user from typing
	_blockKeys = false

	def constructor():
		self._interpreter = Boo.Lang.Interpreter.InteractiveInterpreter(
								RememberLastValue: true,
								Print: print)
		self._interpreter.SetValue("cls", cls)
		self._interpreter.SetValue("exec", exec)
		self._lineHistory = LineHistory(CurrentLineChanged: _lineHistory_CurrentLineChanged)
		self.Document.HighlightingStrategy = GetBooHighlighting()
		self.EnableFolding =  false
		self.ShowLineNumbers =  false
		self.ShowSpaces = false
		self.ShowTabs =  true
		self.ShowEOLMarkers = false
		self.AllowCaretBeyondEOL = false
		self.ShowInvalidLines = false
		self.Dock = DockStyle.Fill

	CaretColumn:
		get:
			return self.ActiveTextAreaControl.Caret.Column

	CurrentLineText:
		get:
			segment = GetLastLineSegment()
			return self.Document.GetText(segment)[4:]

	override def OnLoad(args as EventArgs):
		super(args)
		prompt()

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

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

	private def ConsumeCurrentLine():
		text = CurrentLineText
		_lineHistory.Add(text)
		print("")
		return text

	private def GetLastLineSegment():
		return self.Document.GetLineSegment(self.Document.LineSegmentCollection.Count)

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

	private def BlockInputState():
		code = ConsumeCurrentLine()
		if 0 == len(code):
			Eval(_block.ToString())
		else:
			_block.WriteLine(code)

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

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

	def ClearLine():
		segment = GetLastLineSegment()
		self.Document.Replace(segment.Offset + 4,
			self.CurrentLineText.Length,
			"")

	def AppendText(text as string):
		segment = GetLastLineSegment()
		self.Document.Insert(segment.Offset + segment.TotalLength, text)
		MoveCaretToEnd()

	def MoveCaretToEnd():
		segment = GetLastLineSegment()
		newOffset = segment.Offset + segment.TotalLength
		MoveCaretToOffset(newOffset)

	def MoveCaretToOffset(offset as int):
		self.ActiveTextAreaControl.Caret.Position = self.Document.OffsetToPosition(offset)

	override def InitializeTextAreaControl(newControl as TextAreaControl):
		super(newControl)
		newControl.TextArea.DoProcessDialogKey += HandleDialogKey
		newControl.TextArea.KeyEventHandler += HandleKeyPress

	InCodeCompletion:
		get:
			return _codeCompletionWindow is not null and not _codeCompletionWindow.IsDisposed

	private def DotComplete(ch as System.Char):
		ShowCompletionWindow(
			CodeCompletionDataProvider(_imageProvider, GetSuggestions()),
			ch)

	private def ShowCompletionWindow(completionDataProvider, ch as System.Char):
		_codeCompletionWindow = CodeCompletionWindow.ShowCompletionWindow(
					self.ParentForm,
					self,
					"<code>",
					completionDataProvider,
					ch)
		if _codeCompletionWindow is not null:
			_codeCompletionWindow.Closed += def():
				_blockKeys = false

	private def CtrlSpaceComplete():
		_blockKeys = true
		ShowCompletionWindow(
			GlobalsCompletionDataProvider(_imageProvider, self._interpreter),
			Char.MinValue)

	private def GetSuggestions():
		code = CurrentLineText.Insert(self.CaretColumn-4, ".__codecomplete__")
		code = code.Insert(0, _block.ToString()) if InputState.Block == _state
		suggestion = _interpreter.SuggestCodeCompletion(code) as INamespace
		return array(IEntity, 0) if suggestion is null
		return GetChildNamespaces(suggestion) if code.StartsWith("import ")
		return suggestion.GetMembers()

	private def GetChildNamespaces(parent as INamespace):
		return array(member
					for member in parent.GetMembers()
					if member.EntityType == EntityType.Namespace)

	private def HandleDialogKey(key as Keys):
		return false if InCodeCompletion

		if key == Keys.Enter:
			try:
				(SingleLineInputState, BlockInputState)[_state]()
			except x:
				print(x)
			prompt()
			return true

		if key == Keys.Up:
			_lineHistory.Up()
			return true
		if key == Keys.Down:
			_lineHistory.Down()
			return true

		if key == (Keys.Control | Keys.Space):
			CtrlSpaceComplete()
			return true

		if key in Keys.Home, Keys.Shift|Keys.Home, Keys.Control|Keys.Home:
			MoveCaretToOffset(GetLastLineSegment().Offset + 4)
			return true

		if key == Keys.Escape:
			ClearLine()
			return true

		if key in Keys.Back, Keys.Left:
			if self.CaretColumn < 5:
				return true
		else:
			if self.CaretColumn < 4:
				MoveCaretToEnd()

		return false

	private def HandleKeyPress(ch as System.Char) as bool:
		return true if _blockKeys

		if InCodeCompletion:
			_codeCompletionWindow.ProcessKeyEvent(ch)

		if ch == "."[0]:
			DotComplete(ch)

		return false

	private def cls():
		self.Document.TextContent = ""
		self.ActiveTextAreaControl.Refresh()

	private def exec(scriptName as string):
		_interpreter.Eval(Boo.IO.TextFile.ReadFile(scriptName))

	private def _lineHistory_CurrentLineChanged():
		segment = GetLastLineSegment()
		self.Document.Replace(segment.Offset + 4,
			self.CurrentLineText.Length,
			_lineHistory.CurrentLine)

	def GetBooHighlighting():
		return HighlightingManager.Manager.FindHighlighter("Boo")

	static def InstallDefaultSyntaxModeProvider():
		HighlightingManager.Manager.AddSyntaxModeFileProvider(
			FileSyntaxModeProvider(Path.GetDirectoryName(Application.ExecutablePath)))

#region license
// Copyright (c) 2004, Rodrigo B. de Oliveira (rbo@acm.org)
// All rights reserved.
//
// This file is part of Boo Explorer.
//
// Boo Explorer 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

"""
Interactive Forms-based Console
"""
namespace booish.gui

import System
import System.Drawing
import System.IO
import System.Windows.Forms
import ICSharpCode.TextEditor
import ICSharpCode.TextEditor.Document
import ICSharpCode.TextEditor.Actions
import ICSharpCode.TextEditor.Gui.CompletionWindow
import Boo.Lang.Compiler.TypeSystem

interface ICompletionWindowImageProvider:
	ImageList as ImageList:
		get
	NamespaceIndex as int:
		get
	ClassIndex as int:
		get
	InterfaceIndex as int:
		get
	EnumIndex as int:
		get
	StructIndex as int:
		get
	CallableIndex as int:
		get
	MethodIndex as int:
		get
	FieldIndex as int:
		get
	LiteralIndex as int:
		get
	PropertyIndex as int:
		get
	EventIndex as int:
		get

class InteractiveInterpreterControl(TextEditorControl):

	enum InputState:
		SingleLine = 0
		Block = 1

	class NullCompletionWindowImageProvider(ICompletionWindowImageProvider):

		public static final Instance = NullCompletionWindowImageProvider()

		[getter(ImageList)]
		_imageList = System.Windows.Forms.ImageList()

		NamespaceIndex as int:
			get:
				return 0
		ClassIndex as int:
			get:
				return 0
		InterfaceIndex as int:
			get:
				return 0
		EnumIndex as int:
			get:
				return 0
		StructIndex as int:
			get:
				return 0
		CallableIndex as int:
			get:
				return 0
		MethodIndex as int:
			get:
				return 0
		FieldIndex as int:
			get:
				return 0
		LiteralIndex as int:
			get:
				return 0
		PropertyIndex as int:
			get:
				return 0
		EventIndex as int:
			get:
				return 0

	class LineHistory:

		_lines = []
		_current = 0

		event CurrentLineChanged as EventHandler

		def Add([required] line as string):
			if len(line) > 0 and line != LastLine:
				_lines.Add(line)
			_current = len(_lines)

		LastLine as string:
			get:
				return null if 0 == len(_lines)
				return _lines[-1]

		CurrentLine as string:
			get:
				return null if 0 == len(_lines)
				return _lines[_current]

		def Up():
			MoveTo(_current - 1)

		def Down():
			MoveTo(_current + 1)

		def MoveTo(index as int):
			return if 0 == len(_lines)
			old = _current
			_current = index % len(_lines)
			if old != _current:
				CurrentLineChanged(self, EventArgs.Empty)

	_state = InputState.SingleLine

	_block = System.IO.StringWriter()

	_console = System.IO.StringWriter()

	[getter(Interpreter)]
	_interpreter as Boo.Lang.Interpreter.InteractiveInterpreter

	_codeCompletionWindow as CodeCompletionWindow

	[property(CompletionWindowImageProvider, value is not null)]
	_imageProvider as ICompletionWindowImageProvider = NullCompletionWindowImageProvider()

	_lineHistory as LineHistory

	// HACK: when the completion window is shown through CTRL+SPACE
	// it behaves very strangely, the best we can do right now is
	// to prevent the user from typing
	_blockKeys = false

	def constructor():
		self._interpreter = Boo.Lang.Interpreter.InteractiveInterpreter(
								RememberLastValue: true,
								Print: print)
		self._interpreter.SetValue("cls", cls)
		self._lineHistory = LineHistory(CurrentLineChanged: _lineHistory_CurrentLineChanged)
		self.Document.HighlightingStrategy = GetBooHighlighting()
		self.EnableFolding =  false
		self.ShowLineNumbers =  false
		self.ShowSpaces = false
		self.ShowTabs =  true
		self.ShowEOLMarkers = false
		self.AllowCaretBeyondEOL = false
		self.ShowInvalidLines = false
		self.Dock = DockStyle.Fill

	CaretColumn:
		get:
			return self.ActiveTextAreaControl.Caret.Column

	CurrentLineText:
		get:
			segment = GetLastLineSegment()
			return self.Document.GetText(segment)[4:]

	override def OnLoad(args as EventArgs):
		super(args)
		prompt()

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

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

	private def ConsumeCurrentLine():
		text = CurrentLineText
		_lineHistory.Add(text)
		print("")
		return text

	private def GetLastLineSegment():
		return self.Document.GetLineSegment(self.Document.LineSegmentCollection.Count)

	private def SingleLineInputState():
		code = ConsumeCurrentLine()

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

	private def BlockInputState():
		code = ConsumeCurrentLine()
		if 0 == len(code):
			Eval(_block.ToString())
		else:
			_block.WriteLine(code)

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

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

	def AppendText(text as string):
		segment = GetLastLineSegment()
		self.Document.Insert(segment.Offset + segment.TotalLength, text)
		MoveCaretToEnd()

	def MoveCaretToEnd():
		segment = GetLastLineSegment()
		newOffset = segment.Offset + segment.TotalLength
		MoveCaretToOffset(newOffset)

	def MoveCaretToOffset(offset as int):
		self.ActiveTextAreaControl.Caret.Position = self.Document.OffsetToPosition(offset)

	override def InitializeTextAreaControl(newControl as TextAreaControl):
		super(newControl)
		newControl.TextArea.DoProcessDialogKey += HandleDialogKey
		newControl.TextArea.KeyEventHandler += HandleKeyPress

	InCodeCompletion:
		get:
			return _codeCompletionWindow is not null and not _codeCompletionWindow.IsDisposed

	private def DotComplete(ch as System.Char):
		ShowCompletionWindow(
			CodeCompletionDataProvider(_imageProvider, GetSuggestions()),
			ch)

	private def ShowCompletionWindow(completionDataProvider, ch as System.Char):
		_codeCompletionWindow = CodeCompletionWindow.ShowCompletionWindow(
					self.ParentForm,
					self,
					"<code>",
					completionDataProvider,
					ch)
		if _codeCompletionWindow is not null:
			_codeCompletionWindow.Closed += def():
				_blockKeys = false

	private def CtrlSpaceComplete():
		_blockKeys = true
		ShowCompletionWindow(
			GlobalsCompletionDataProvider(_imageProvider, self._interpreter),
			Char.MinValue)

	private def GetSuggestions():
		code = CurrentLineText.Insert(self.CaretColumn-4, ".__codecomplete__")
		code = code.Insert(0, _block.ToString()) if InputState.Block == _state
		suggestion = _interpreter.SuggestCodeCompletion(code) as INamespace
		return array(IEntity, 0) if suggestion is null
		return GetChildNamespaces(suggestion) if code.StartsWith("import ")
		return suggestion.GetMembers()

	private def GetChildNamespaces(parent as INamespace):
		return array(member
					for member in parent.GetMembers()
					if member.EntityType == EntityType.Namespace)

	private def HandleDialogKey(key as Keys):
		return false if InCodeCompletion

		if key == Keys.Enter:
			try:
				(SingleLineInputState, BlockInputState)[_state]()
			except x:
				print(x)
			prompt()
			return true

		if key == Keys.Up:
			_lineHistory.Up()
			return true
		if key == Keys.Down:
			_lineHistory.Down()
			return true

		if key == (Keys.Control | Keys.Space):
			CtrlSpaceComplete()
			return true

		if key in Keys.Home, Keys.Shift|Keys.Home, Keys.Control|Keys.Home:
			MoveCaretToOffset(GetLastLineSegment().Offset + 4)
			return true

		if key in Keys.Back, Keys.Left:
			if self.CaretColumn < 5:
				return true
		else:
			if self.CaretColumn < 4:
				MoveCaretToEnd()

		return false

	private def HandleKeyPress(ch as System.Char) as bool:
		return true if _blockKeys

		if InCodeCompletion:
			_codeCompletionWindow.ProcessKeyEvent(ch)

		if ch == "."[0]:
			DotComplete(ch)

		return false

	private def cls():
		self.Document.TextContent = ""
		self.ActiveTextAreaControl.Refresh()

	private def _lineHistory_CurrentLineChanged():
		segment = GetLastLineSegment()
		self.Document.Replace(segment.Offset + 4,
			self.CurrentLineText.Length,
			_lineHistory.CurrentLine)

	def GetBooHighlighting():
		return HighlightingManager.Manager.FindHighlighter("Boo")

	static def InstallDefaultSyntaxModeProvider():
		HighlightingManager.Manager.AddSyntaxModeFileProvider(
			FileSyntaxModeProvider(Path.GetDirectoryName(Application.ExecutablePath)))


Make indentations consistent with the rest of the entries in primitive.

#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

// authors:
// Arron Washington
// Ian MacLean (original C# version)

//See also:
//http://svn.myrealbox.com/viewcvs/trunk/mcs/class/System/Microsoft.CSharp/CSharpCodeGenerator.cs?view=auto
//http://svn.myrealbox.com/viewcvs/trunk/mcs/class/System/Microsoft.VisualBasic/VBCodeGenerator.cs?view=auto

namespace Boo.Lang.CodeDom

import System.CodeDom
import System.CodeDom.Compiler
import System.Reflection
import System.Collections
import System.Text.RegularExpressions
import System.Globalization

class BooCodeGenerator(CodeGenerator):
	static _NET_2_0 as bool = System.Environment.Version >= System.Version(2, 0)

	static primitives = { "System.Double" : "double",
						"System.Single" : "single",
						"System.Int32" : "int",
						"System.Int64" : "long",
						"System.Int16" : "short",
						"System.UInt16" : "ushort",
						"System.UInt32" : "uint",
						"System.Uint64" : "ulong",
						"System.Byte": "byte",
						"System.Sbyte": "sbyte",
						"System.Decimal": "decimal",
						"System.Boolean" : "bool",
						"System.Char" : "char",
						"System.String" : "string",
						"System.Object" : "object",
						"System.Void" : "void",
						"System.DateTime" : "date",
						"System.TimeSpan" : "timespan" }

	protected NullToken as string:
		get:
			return "null"

	// workaround for MS's implementation around code snippets
	protected BooIndent as int:
		get:
			return _booIndent
		set:
			_booIndent = value
			Indent = value
	_booIndent = 0

	protected override def OutputType(typeRef as CodeTypeReference):
		Output.Write(GetTypeOutput(typeRef))

	protected override def GenerateArrayCreateExpression(exp as CodeArrayCreateExpression) :
		if exp.Initializers is not null and exp.Size == 0 and exp.SizeExpression is null:
			Output.Write("(")
			if exp.CreateType is not null:
				Output.Write("of ")
				OutputType(exp.CreateType)
				Output.Write(": ")
			OutputExpressionList(exp.Initializers)
			//no trailing comma needed for single item with "of" type
			if exp.Initializers.Count==0 or (exp.Initializers.Count==1 and not exp.CreateType):
				Output.Write(",")
			Output.Write(")")
		else:
			Output.Write("array(")
			OutputType(exp.CreateType)
			Output.Write(", ")
			if exp.SizeExpression is not null:
				GenerateExpression(exp.SizeExpression)
			else:
				Output.Write(exp.Size)
			Output.Write(")")

	protected override def GenerateBaseReferenceExpression(e as CodeBaseReferenceExpression) :
		Output.Write("super")

	protected override def GenerateCastExpression(e as CodeCastExpression) :
		Output.Write("cast(")
		OutputType(e.TargetType)
		Output.Write(",")
		GenerateExpression(e.Expression)
		Output.Write(")")

	protected override def GenerateDelegateCreateExpression(e as CodeDelegateCreateExpression) :
		GenerateExpression(e.TargetObject)
		Output.Write(".${e.MethodName} as ")
		OutputType(e.DelegateType)

	protected override def GenerateFieldReferenceExpression(e as CodeFieldReferenceExpression):
		MemberReference(e.TargetObject, e.FieldName)

	protected override def GenerateArgumentReferenceExpression(e as CodeArgumentReferenceExpression) :
		Output.Write(e.ParameterName)

	protected override def GenerateVariableReferenceExpression(e as CodeVariableReferenceExpression) :
		Output.Write(e.VariableName)

	protected override def GenerateIndexerExpression(e as CodeIndexerExpression) :
		Indexer(e.TargetObject, e.Indices)

	protected override def GenerateArrayIndexerExpression(e as CodeArrayIndexerExpression) :
		Indexer(e.TargetObject, e.Indices)

	protected override def GenerateMethodInvokeExpression(e as CodeMethodInvokeExpression) :
		Invocation(e.Method, e.Parameters)

	protected override def GenerateMethodReferenceExpression(e as CodeMethodReferenceExpression) :
		MemberReference(e.TargetObject, e.MethodName)
	protected override def GenerateEventReferenceExpression(e as CodeEventReferenceExpression) :
		MemberReference(e.TargetObject, e.EventName)

	protected override def GenerateDelegateInvokeExpression(e as CodeDelegateInvokeExpression) :
		Invocation(e.TargetObject, e.Parameters)

	protected override def GenerateObjectCreateExpression(e as CodeObjectCreateExpression) :
		OutputType(e.CreateType)
		Output.Write("(")
		OutputExpressionList(e.Parameters)
		Output.Write(")")

	protected override def GeneratePropertyReferenceExpression(e as CodePropertyReferenceExpression) :
		MemberReference(e.TargetObject, e.PropertyName)

	protected override def GeneratePropertySetValueReferenceExpression(e as CodePropertySetValueReferenceExpression) :
		Output.Write("value")

	protected override def GenerateThisReferenceExpression(e as CodeThisReferenceExpression) :
		Output.Write("self")

	protected override def GenerateExpressionStatement(e as CodeExpressionStatement) :
		GenerateExpression(e.Expression)
		Output.WriteLine()

	protected override def GenerateIterationStatement(e as CodeIterationStatement):
		if e.InitStatement:
			GenerateStatement(e.InitStatement)
		Output.Write("while ")
		GenerateExpression(e.TestExpression)
		BeginBlock()
		if e.Statements and e.Statements.IsValid():
			GenerateStatements(e.Statements)
		if e.IncrementStatement:
			GenerateStatement(e.IncrementStatement)
		else:
			passcheck(e.Statements)
		EndBlock()

	protected override def GenerateThrowExceptionStatement(e as CodeThrowExceptionStatement) :
		Output.Write("raise ")
		GenerateExpression(e.ToThrow)
		Output.WriteLine()

	protected override def GenerateComment(comment as CodeComment) :
		//TODO: check comment.DocComment when boo doc format is available
		commentSymbol = "#"
		txt = comment.Text

		Output.Write(commentSymbol + " ")

		i = 0
		while i<len(txt):
			rawArrayIndexing:
				Output.Write(txt[i])
				if txt[i] == char('\r'):
					if i<len(txt)-1 and txt[i+1]==char('\n'):
						continue
					Output.Write(commentSymbol)
				elif txt[i] == char('\n'):
					Output.Write(commentSymbol)
			++i
		Output.WriteLine()

	protected override def GenerateMethodReturnStatement(e as CodeMethodReturnStatement) :
		if e.Expression is null:
			Output.WriteLine("return")
			return
		Output.Write("return ")
		GenerateExpression(e.Expression)
		Output.WriteLine()

	protected override def GenerateConditionStatement(e as CodeConditionStatement) :
		Output.Write("if ")
		GenerateExpression(e.Condition)
		BeginBlock()
		GenerateStatements(e.TrueStatements)
		passcheck(e.TrueStatements)
		EndBlock(false)
		if e.FalseStatements and e.FalseStatements.IsValid():
			Output.Write("else")
			BeginBlock()
			GenerateStatements(e.FalseStatements)
			passcheck(e.FalseStatements)
			EndBlock(false)
		End()

	protected override def GenerateTryCatchFinallyStatement(e as CodeTryCatchFinallyStatement) :
		Output.Write("try")
		BeginBlock()
		GenerateStatements(e.TryStatements)
		passcheck(e.TryStatements)
		EndBlock(false)
		for exp as CodeCatchClause in e.CatchClauses:
			Output.Write("except ")
			Output.Write("${exp.LocalName} as ")
			OutputType(exp.CatchExceptionType)
			BeginBlock()
			GenerateStatements(exp.Statements)
			passcheck(exp.Statements)
			EndBlock(false)

		if e.FinallyStatements and e.FinallyStatements.Count > 0:
			Output.Write("ensure")
			BeginBlock()
			GenerateStatements(e.FinallyStatements)
			passcheck(e.FinallyStatements)
			EndBlock(false)
		End()

	protected override def GenerateAssignStatement(e as CodeAssignStatement) :
		GenerateExpression(e.Left)
		Output.Write(" = ")
		GenerateExpression(e.Right)
		Output.WriteLine()
	protected override def GenerateAttachEventStatement(e as CodeAttachEventStatement) :
		GenerateExpression(e.Event)
		Output.Write(" += ")
		GenerateExpression(e.Listener)
		Output.WriteLine()
	protected override def GenerateRemoveEventStatement(e as CodeRemoveEventStatement) :
		GenerateExpression(e.Event)
		Output.Write(" -= ")
		GenerateExpression(e.Listener)
		Output.WriteLine()
	protected override def GenerateGotoStatement(e as CodeGotoStatement) :
		Output.WriteLine("goto ${e.Label}")
	protected override def GenerateLabeledStatement(e as CodeLabeledStatement) :
		Output.WriteLine(":${e.Label}")
		if e.Statement:
			GenerateStatement(e.Statement)
	protected override def GenerateVariableDeclarationStatement(e as CodeVariableDeclarationStatement) :
		Output.Write("${e.Name} as ")
		OutputType(e.Type)
		if e.InitExpression:
			Output.Write(" = ")
			GenerateExpression(e.InitExpression)
		Output.WriteLine()
	protected override def GenerateLinePragmaStart(e as CodeLinePragma) :
		pass

	protected override def GenerateLinePragmaEnd(e as CodeLinePragma) :
		pass

	protected override def GenerateEvent(e as CodeMemberEvent, c as CodeTypeDeclaration) :

		if e.PrivateImplementationType:
			raise "Does not support private implementation type."
		if e.ImplementationTypes.IsValid():
			raise "Does not implement these types: ${join(e.ImplementationTypes)}"
		e.Attributes |= MemberAttributes.Final

		ModifiersAndAttributes(e)

		Output.Write("event ${e.Name} as ")
		OutputType(e.Type)
		Output.WriteLine()

	protected override def GenerateField(e as CodeMemberField):
		if CurrentClass.IsEnum:
			Output.Write(e.Name)
		else:
			ModifiersAndAttributes(e)
			Output.Write("${e.Name} as ")
			OutputType(e.Type)

		if e.InitExpression:
			Output.Write(" = ")
			GenerateExpression(e.InitExpression)

	protected override def GenerateSnippetMember(e as CodeSnippetTypeMember) :
		if e.CustomAttributes:
			OutputAttributes(e.CustomAttributes, null, false)
		Output.WriteLine(FixIndent(e.Text, Options.IndentString, BooIndent, false))

	protected override def GenerateSnippetExpression(e as CodeSnippetExpression) :
		//Output.Write("("+e.Value+")")
		Output.Write(e.Value)

	protected override def GenerateSnippetCompileUnit(e as CodeSnippetCompileUnit) :
		Output.WriteLine(FixIndent(e.Value, Options.IndentString, BooIndent, false))

	protected override def GenerateSnippetStatement(e as CodeSnippetStatement) :
		if _NET_2_0:
			Output.WriteLine(e.Value)
		else:
			Output.WriteLine(FixIndent(e.Value, Options.IndentString, BooIndent, false))

	protected override def GenerateEntryPointMethod(e as CodeEntryPointMethod, c as CodeTypeDeclaration) :
		Method(e, "Main")

	protected override def GenerateMethod(e as CodeMemberMethod, c as CodeTypeDeclaration) :
		Method(e, e.Name)

	protected override def GeneratePrimitiveExpression(e as CodePrimitiveExpression) :
		if e.Value isa char:
			Output.Write("char(")
			super.GeneratePrimitiveExpression(e)
			Output.Write(")")
		else:
			super.GeneratePrimitiveExpression(e)

	protected override def GenerateProperty(e as CodeMemberProperty, c as CodeTypeDeclaration) :
		ModifiersAndAttributes(e)

		if (e.Parameters.Count > 0
			and string.Compare(e.Name, "Item", true, CultureInfo.InvariantCulture) == 0):
			Output.Write(" self")
		else:
			Output.Write(" ${e.Name}")
		if len(e.Parameters) > 0:
			Output.Write("[")
			OutputParameters(e.Parameters)
			Output.Write("]")
		Output.Write(" as ")
		OutputType(e.Type)
		BeginBlock()
		if e.HasGet:
			Output.Write("get")
			BeginBlock()
			GenerateStatements(e.GetStatements)
			passcheck(e.GetStatements)
			EndBlock() //TODO: Change to EndBlock(false) when BOO-631 accepted
		if e.HasSet:
			Output.Write("set")
			BeginBlock()
			GenerateStatements(e.SetStatements)
			passcheck(e.SetStatements)
			EndBlock() //TODO: Change to EndBlock(false) when BOO-631 accepted
		EndBlock()

	protected override def GenerateConstructor(e as CodeConstructor, c as CodeTypeDeclaration) :
		e.Attributes |= MemberAttributes.Final
		Method(e, "constructor")

	protected override def GenerateTypeConstructor(e as CodeTypeConstructor) :
		e.Attributes |= MemberAttributes.Static
		e.Attributes |= MemberAttributes.Public
		e.Parameters.Clear()
		Method(e, "constructor")

	protected override def GenerateTypeStart(e as CodeTypeDeclaration):
		if e.CustomAttributes:
			OutputAttributes(e.CustomAttributes, null, false)
		if e isa CodeTypeDelegate:
			GenerateDelegate(e)
			return

		//TODO: move this to an override of OutputTypeAttributes

		//FIXME: When boo gets preprocessor directives, i.e. #if NET_2_0
		//Til then we have to partially rely on super.OutputTypeAttributes

		//output "final", since super.OutputTypeAttributes outputs "sealed"
		if e.TypeAttributes & TypeAttributes.Sealed == TypeAttributes.Sealed:
			Output.Write("final ")

			//remove sealed from attributes:

			//FIXME: when boo enum processing fixed
			//e.TypeAttributes &= ~TypeAttributes.Sealed
			e.TypeAttributes &= cast(TypeAttributes,~cast(int,TypeAttributes.Sealed))

		visibility = e.TypeAttributes & TypeAttributes.VisibilityMask
		if visibility == TypeAttributes.Public or visibility == TypeAttributes.NestedPublic:
			pass //Output.Write("public ") //public by default
		elif visibility == TypeAttributes.NestedPrivate:
			Output.Write("private ")
		elif (visibility == TypeAttributes.NotPublic or
			TypeAttributes.NestedFamANDAssem or
			TypeAttributes.NestedAssembly):
			Output.Write("internal ")
		elif visibility == TypeAttributes.NestedFamily:
			//FIXME: BOO-666
			Output.Write("protected ")
		elif visibility == TypeAttributes.NestedFamORAssem:
			//FIXME: BOO-666
			Output.Write("internal ")

		if e.IsPartial:
			Output.Write("partial ")

		//super OutputTypeAttributes ignores TypeAttributes.NotPublic (internal)
		//FIXME: when boo enum processing fixed
		//e.TypeAttributes &= ~TypeAttributes.VisibilityMask
		e.TypeAttributes &= cast(TypeAttributes,~cast(int,TypeAttributes.VisibilityMask))
		e.TypeAttributes |= TypeAttributes.NotPublic //not really nec. since val is 0

		//TODO: Remove call to OutputTypeAttributes
		OutputTypeAttributes(e.TypeAttributes, e.IsStruct, e.IsEnum)
		/////////////////////////////////////

		Output.Write("${e.Name}")
		if len(e.BaseTypes):
			Output.Write("(")
			for index in range(len(e.BaseTypes)):
				var as CodeTypeReference = e.BaseTypes[index]
				OutputType(var)
				continue unless index + 1 != e.BaseTypes.Count
				Output.Write(",")
			Output.Write(")")

		BeginBlock()
		#Ah hah hah, yeah, no. Empty class.
		passcheck(e.Members)

	private def GenerateDelegate(e as CodeTypeDelegate):
		if e.TypeAttributes & TypeAttributes.Sealed == TypeAttributes.Sealed:
			Output.Write("final ")
		if e.TypeAttributes & TypeAttributes.NestedFamORAssem == TypeAttributes.Public:
			Output.Write("public ")
		Output.Write("callable ${e.Name}(")
		OutputParameters(e.Parameters)
		Output.Write(") as ")
		OutputType(e.ReturnType)

	protected override def GenerateTypeEnd(e as CodeTypeDeclaration) :
		EndBlock()

	protected override def GenerateNamespaceStart(e as CodeNamespace) :
		if e is null or string.IsNullOrEmpty(e.Name):
			return
		Output.WriteLine("namespace ${e.Name}")

	protected override def GenerateNamespaceEnd(e as CodeNamespace) :
		pass

	protected override def GenerateNamespaceImport(e as CodeNamespaceImport) :
		Output.WriteLine("import ${e.Namespace}")

	protected override def GenerateAttributeDeclarationsStart(attributes as CodeAttributeDeclarationCollection) :
		Output.Write("[")

	protected override def GenerateAttributeDeclarationsEnd(attributes as CodeAttributeDeclarationCollection) :
		Output.Write("]")

	protected override def Supports(support as GeneratorSupport) as bool:
		return true

	protected override def IsValidIdentifier(value as string) as bool:
		return true

	protected override def CreateEscapedIdentifier(value as string) as string:
		return value

	protected override def CreateValidIdentifier(value as string) as string:
		return value

	def NonGenericName(typeName as string):
		return typeName[:typeName.IndexOf(char('`'))]

	protected override def GetTypeOutput(typeRef as CodeTypeReference) as string:
		if typeRef.ArrayElementType:
			out = GetTypeOutput(typeRef.ArrayElementType)
		elif typeRef.BaseType in primitives:
			out = primitives[typeRef.BaseType]
		else:
			// BaseType uses .NET syntax for inner classes, so we have to replace '+' with '.'
			out = typeRef.BaseType.Replace('+', '.')
			typeArgs = typeRef.TypeArguments
			if len(typeArgs) > 0:
				out = "${NonGenericName(out)}[of ${join(GetTypeOutput(arg) for arg in typeArgs, ', ')}]"

		if typeRef.ArrayRank == 0:
			return out
		elif typeRef.ArrayRank == 1:
			return "(${out})"
		else:
			return "(${out}, ${typeRef.ArrayRank})"

	protected override def QuoteSnippetString(snippet as string) as string:
		s = snippet.Replace("\\", "\\\\")
		s = s.Replace("\"", "\\\"")
		s = s.Replace("\t", "\\t")
		s = s.Replace("\r", "\\r")
		s = s.Replace("\n", "\\n")
		return "\"" + s + "\""

	def Method(method as duck, name as string):
		ModifiersAndAttributes(method)
		Output.Write("def ${name}(")
		OutputParameters(method.Parameters)
		Output.Write(")")
		if method.ReturnTypeCustomAttributes:
			OutputAttributes(method.ReturnTypeCustomAttributes, null, true)
		unless GetTypeOutput(method.ReturnType) == "void":
			Output.Write(" as ")
			OutputType(method.ReturnType)
		BeginBlock()
		ctor = method as CodeConstructor
		do_pass = true
		if ctor:
			if ctor.BaseConstructorArgs.IsValid():
				Output.Write("super(")
				OutputExpressionList(ctor.BaseConstructorArgs)
				Output.WriteLine(")")
				do_pass = false
			if ctor.ChainedConstructorArgs.IsValid():
				Output.Write("self(")
				OutputExpressionList(ctor.ChainedConstructorArgs)
				Output.WriteLine(")")
				do_pass = false
		GenerateStatements(method.Statements)
		if do_pass:
			passcheck(method.Statements)
		EndBlock()

	def MemberReference(target as CodeExpression, member as string):
		if target: #target.method( ... )
			GenerateExpression(target)
			Output.Write(".${member}")
		else: #method( ... )
			Output.Write(member)

	def Indexer(target as CodeExpression, indices as CodeExpressionCollection):
		GenerateExpression(target)
		Output.Write("[")
		OutputExpressionList(indices)
		Output.Write("]")

	def Invocation(target as CodeExpression, parameters as CodeExpressionCollection):
		GenerateExpression(target)
		Output.Write("(")
		OutputExpressionList(parameters)
		Output.Write(")")

	protected override def OutputExpressionList(exps as CodeExpressionCollection):
		if exps is null or exps.Count == 0:
			return
		total = exps.Count
		i = 0
		while i < total:
			e as CodeExpression = exps[i]
			if AsBool(e.UserData["Explode"]):
				Output.Write("*")
			GenerateExpression(e)
			if i < total-1:
				Output.Write(", ")
			++i

	def passcheck(stuff as ICollection):
		return if stuff.IsValid()
		if not AsBool(Options["WhiteSpaceAgnostic"]):
			Output.WriteLine("pass")

	override def OutputTypeNamePair(type as CodeTypeReference, name as string):
		Output.Write("${name} as ")
		OutputType(type)

	protected override def GenerateParameterDeclarationExpression(e as CodeParameterDeclarationExpression):
		name = e.Name
		if e.Type.ArrayElementType:
			paramarray as CodeAttributeDeclaration = null
			for att as CodeAttributeDeclaration in e.CustomAttributes:
				if att.Name.EndsWith("ParamArrayAttribute") or att.Name.EndsWith("ParamArray"):
					paramarray = att
					break
			if paramarray:
				e.CustomAttributes.Remove(paramarray)
				name = "*"+e.Name

		OutputAttributes(e.CustomAttributes, null, true)
		OutputDirection(e.Direction)
		OutputTypeNamePair(e.Type, name)

	private def OutputAttributes(attributes as CodeAttributeDeclarationCollection, prefix as string, inline as bool):
		for att as CodeAttributeDeclaration in attributes:
			GenerateAttributeDeclarationsStart(attributes)
			Output.Write(prefix) if prefix
			OutputAttribute(att)
			GenerateAttributeDeclarationsEnd(attributes)
			if inline:  //for parameter and return type attributes
				pass //Output.Write(" ")
			else:
				Output.WriteLine()

	private def OutputAttribute(attribute as CodeAttributeDeclaration):
		Output.Write(attribute.Name.Replace ('+', '.'))
		if len(attribute.Arguments) == 0:
			return

		Output.Write('(')
		first = true
		for argument as CodeAttributeArgument in attribute.Arguments:
			if first:
				OutputAttributeArgument(argument)
				first = false
			else:
				Output.Write(", ")
				OutputAttributeArgument(argument)
		Output.Write(')')

	def ModifiersAndAttributes(typeMember as CodeTypeMember):
		if typeMember.CustomAttributes:
			OutputAttributes(typeMember.CustomAttributes, null, false)

		//FIXME: We just ignore "new" methods, since they are unsupported in boo
		if typeMember.Attributes & MemberAttributes.VTableMask == MemberAttributes.New:
			typeMember.Attributes &= cast(MemberAttributes,~cast(int,MemberAttributes.New))

		//TODO: Override these.  Right now we are lucky C# and boo are the same
		//with respect to keywords and defaults (such as final/sealed by default).
		//We should override for example to not print out "public" since it is boo default.
		OutputMemberAccessModifier(typeMember.Attributes)
		OutputMemberScopeModifier(typeMember.Attributes)

	def OutputAttributeArgument(arg as CodeAttributeArgument):
		if arg.Name and arg.Name != "":
			Output.Write(arg.Name)
			Output.Write(":")
		GenerateExpression(arg.Value)

	protected override def OutputDirection(direction as FieldDirection):
		if direction == FieldDirection.Ref or direction == FieldDirection.Out:
			Output.Write("ref ")

	protected override def OutputFieldScopeModifier(attributes as MemberAttributes):
		scope = attributes & MemberAttributes.ScopeMask
		if scope == MemberAttributes.Static:
			Output.Write("static ")
		elif scope == MemberAttributes.Const:
			Output.Write("static final ")

	private def AsBool(data):
		return data is not null and data isa bool and cast(bool,data)

	protected override def GenerateCompileUnitStart(compileUnit as CodeCompileUnit):
		GenerateComment(CodeComment("------------------------------------------------------------------------------"))
		GenerateComment(CodeComment("This code was automatically generated by Boo.Lang.CodeDom v.${BooVersion}."))
		GenerateComment(CodeComment(""))
		GenerateComment(CodeComment("     Changes to this file may cause incorrect behavior and will be lost if "))
		GenerateComment(CodeComment("     the code is regenerated."))
		GenerateComment(CodeComment("------------------------------------------------------------------------------"))
		Output.WriteLine()

		//for future:
		if AsBool(Options["WhiteSpaceAgnostic"]):
			Output.WriteLine("//option WhiteSpaceAgnostic")
			Output.WriteLine()

		//super.GenerateCompileUnitStart(compileUnit)

	protected override def GenerateCompileUnit(compileUnit as CodeCompileUnit):
		GenerateCompileUnitStart(compileUnit)

		for ns as CodeNamespace in compileUnit.Namespaces:
			GenerateNamespace(ns)

		if compileUnit.AssemblyCustomAttributes.Count > 0:
			OutputAttributes(compileUnit.AssemblyCustomAttributes,
					"assembly:", false)
			Output.WriteLine("")

		GenerateCompileUnitEnd(compileUnit)

	protected virtual def BeginBlock():
		Output.WriteLine(":")
		++BooIndent

	protected virtual def EndBlock():
		EndBlock(true)

	protected virtual def EndBlock(realend as bool):
		--BooIndent
		if realend:
			End()

	protected virtual def End():
		if AsBool(Options["WhiteSpaceAgnostic"]):
			Output.WriteLine("end")

#region FixIndent
	static newlinePattern = Regex("\\n",RegexOptions.Compiled)
	static whiteSpacePattern = Regex("(\\s*)",RegexOptions.Compiled)

	static public def FixIndent(code as string, indentstring as string,
				indentlevel as int, indentfirst as bool) as string:
		//how much the code should be indented:
		if indentlevel > 0:
			indentprefix = indentstring * indentlevel
			nonEmptyPrefix = (indentprefix != string.Empty)
		else:
			indentprefix = string.Empty
			nonEmptyPrefix = false

		if code is null or code==string.Empty:
			if indentfirst:
				return indentprefix
			else:
				return string.Empty

		lines = newlinePattern.Split(code.Replace("\r\n","\n"))

		foundFirstCodeLine = false //first line of real code
		insidecomment = 0 //inside /* */
		insidestring = false  //inside """ """
		firstline = true
		buffer = System.Text.StringBuilder()
		indent = ""
		indentSize = 0
		toTabs = indentprefix.StartsWith("\t") //otherwise, assume spaces
		for line in lines:
			//ignore comments before the first line of real code
			if not foundFirstCodeLine:
				trimmed = line.Trim()
				startmultiline = trimmed.StartsWith("/*")

				//if not whitespace and not a comment...
				if (insidecomment <= 0 and
						not startmultiline and
						not trimmed == string.Empty and
						not trimmed.StartsWith("#") and
						not trimmed.StartsWith("//")):
					foundFirstCodeLine = true
					indent = whiteSpacePattern.Match(line).Groups[0].Value
					indentSize = len(indent)
					insidecomment = 0

				//special stuff for handling multiline comments before code
				if startmultiline or insidecomment > 0:
					j = 0
					linelen = len(trimmed) - 1
					while j < linelen:
						rawArrayIndexing:
							c = trimmed[j]
						if c==char('/'):
							rawArrayIndexing:
								nextc = trimmed[j+1]
							if nextc==char('*'):
								++insidecomment
								++j
						elif c==char('*') and insidecomment > 0:
							rawArrayIndexing:
								nextc = trimmed[j+1]
							if nextc==char('/'):
								--insidecomment
								++j
						++j

			if not foundFirstCodeLine or not insidestring:
				if firstline:
					firstline = false
					if indentfirst and nonEmptyPrefix:
						buffer.Append(indentprefix)
				else:
					if nonEmptyPrefix:
						buffer.Append(indentprefix)

				if not foundFirstCodeLine:
					buffer.Append(line + System.Environment.NewLine)
					continue

				if line.StartsWith(indent):
					if indentSize > 0:
						rest = line[indentSize:]
					else:
						rest = line
					if len(rest) > 0:
						//convert any more leading whitespace to tabs or spaces
						//so we don't mix tabs and spaces on same line
						ws = whiteSpacePattern.Match(rest).Groups[0].Value
						sz = len(ws)
						if len(ws):
							rawArrayIndexing:
								c = rest[0]
							if toTabs:
								if c==char(' '):
									rest = rest[sz:]
									ws = ws.Replace("    ","\t")
									ws = ws.Replace("   ","\t")
									ws = ws.Replace("  ","\t")
									ws = ws.Replace(" ","\t")
									buffer.Append(ws)
							else:
								if c==char('\t'):
									rest = rest[sz:]
									ws = ws.Replace("\t","    ")
									buffer.Append(ws)
						buffer.Append(rest)
				else: //line is not indented as expected, pass it on as is:
					buffer.Append(line)
			else: //we are inside a triple quoted string:
				buffer.Append(line)

			buffer.Append(System.Environment.NewLine)

			//scan for triple quoted string literals:
			//   for speed reasons, I'm not also checking for insidecomment,
			//   so if you have an odd # of triple quotes inside a comment,
			//   you can break this.
			j = 0
			linelen = len(line) - 2
			while j < linelen:
				rawArrayIndexing:
					c1 = line[j]
				if c1==char('"'):
					rawArrayIndexing:
						c2 = line[j+1]
					if c2==char('"'):
						rawArrayIndexing:
							c3 = line[j+2]
						if c3==char('"'):
							insidestring = not insidestring
							j += 2
				++j

		return buffer.ToString()
#endregion


* BOO-913: Marcus is stupid when it comes to "true" != "True"

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

"""
True
"""
import Builtins

class Builtins:
	static def DoIt():
		return true

a = DoIt()
print(a)

"""
true
"""
import Builtins

class Builtins:
	static def DoIt():
		return true

a = DoIt()
print(a)


implemented load and execution of jar integration script

namespace Boojay.Compilation.Tests

import System.IO

import Boo.Lang.Compiler
import Boo.Lang.Compiler.Ast

import NUnit.Framework from nunit.framework

[TestFixture]
partial class JarIntergrationTest(CommonIntegrationTest):

	_assembly as Assembly

	override def compileTest(unit as CompileUnit):
		main = unit.Modules[0]
		main.Imports.Add([| import Boojay.Compilation.Tests |])

		compiler = newBooCompiler()
		compiler.Parameters.References.Add(typeof(CommonIntegrationTest).Assembly)
		compiler.Parameters.References.Add(typeof(Boo.Lang.Compiler.BooCompiler).Assembly)

		result = compiler.Run(unit)
		assert 0 == len(result.Errors), result.Errors.ToString(true) + unit.ToCodeString()

		_assembly = result.GeneratedAssembly

	override def runTest(main as Module):
		result = captureOutput:
			mainModule as duck = _assembly.GetTypes()[0]
			mainModule.Main(array(string,0))

		return result

	private def captureOutput(block as callable):
		old = System.Console.Out
		writer = StringWriter()
		System.Console.SetOut(writer)

		try:
			block()
		ensure:
			System.Console.SetOut(old)

		return writer.ToString()

namespace Boojay.Compilation.Tests

import Boo.Lang.Compiler.Ast

import NUnit.Framework from nunit.framework

[TestFixture]
partial class JarIntergrationTest(CommonIntegrationTest):
	override def compileTest(unit as CompileUnit):
		main = unit.Modules[0]
		main.Imports.Add([| import Boojay.Compilation.Tests |])

		compiler = newBooCompiler()
		compiler.Parameters.References.Add(typeof(CommonIntegrationTest).Assembly)

		result = compiler.Run(unit)
		assert 0 == len(result.Errors), result.Errors.ToString(true) + unit.ToCodeString()

	override def runTest(main as Module):
		return ""


BooBinding: Add OnCharLiteralExpression to CodeDomVisitor. (BOO-321)

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

namespace BooBinding

import System
import System.Collections
import System.CodeDom
import System.Text
import Boo.Lang.Compiler
import Boo.Lang.Compiler.Ast
import Boo.Lang.Compiler.Ast.Visitors
import Boo.Lang.Parser
import SharpDevelop.Internal.Parser

class CodeDomVisitor(IAstVisitor):
"""The CodeDomVisitor is able to convert from the Boo AST to System.CodeDom
It makes use of the SharpDevelop parser service to get necessary additional information about the
types."""
	[Getter(OutputCompileUnit)]
	_compileUnit = CodeCompileUnit()
	_namespace as CodeNamespace
	_class as CodeTypeDeclaration
	_statements as CodeStatementCollection
	_expression as CodeExpression

	def ConvModifiers(member as TypeMember) as MemberAttributes:
		if member isa Field:
			return ConvModifiers(member.Modifiers, MemberAttributes.Family)
		else:
			return ConvModifiers(member.Modifiers, MemberAttributes.Public)

	def ConvModifiers(modifier as TypeMemberModifiers, defaultAttr as MemberAttributes) as MemberAttributes:
		// Boo is not able to convert 0 to MemberAttributes, therefore we need to use
		// a trick to get the default value
		noAttr = MemberAttributes.Abstract & MemberAttributes.Final
		attr = noAttr
		if (modifier & TypeMemberModifiers.Abstract) == TypeMemberModifiers.Abstract:
			attr = attr | MemberAttributes.Abstract
		if (modifier & TypeMemberModifiers.Final) == TypeMemberModifiers.Final:
			attr = attr | MemberAttributes.Const
		if (modifier & TypeMemberModifiers.Internal) == TypeMemberModifiers.Internal:
			attr = attr | MemberAttributes.Assembly
		if (modifier & TypeMemberModifiers.Override) == TypeMemberModifiers.Override:
			attr = attr | MemberAttributes.Override
		if (modifier & TypeMemberModifiers.Private) == TypeMemberModifiers.Private:
			attr = attr | MemberAttributes.Private
		if (modifier & TypeMemberModifiers.Protected) == TypeMemberModifiers.Protected:
			attr = attr | MemberAttributes.Family
		if (modifier & TypeMemberModifiers.Public) == TypeMemberModifiers.Public:
			attr = attr | MemberAttributes.Public
		if (modifier & TypeMemberModifiers.Static) == TypeMemberModifiers.Static:
			attr = attr | MemberAttributes.Static
		if (modifier & TypeMemberModifiers.Virtual) != TypeMemberModifiers.Virtual:
			attr = attr | MemberAttributes.Final
		if attr == noAttr:
			return defaultAttr
		else:
			return attr

	def ConvTypeRef(ref as TypeReference):
		return null if ref == null
		name = ref.ToString()
		expandedName = BooAmbience.ReverseTypeConversionTable[name]
		name = expandedName if expandedName != null
		return CodeTypeReference(name)

	def OnCompileUnit(node as CompileUnit):
		for m as Module in node.Modules:
			m.Accept(self)

	def OnModule(node as Module):
		if node.Namespace == null:
			_namespace = CodeNamespace("Global")
			_compileUnit.Namespaces.Add(_namespace)
		else:
			node.Namespace.Accept(self)
		for i as Import in node.Imports:
			i.Accept(self)
		for m as TypeMember in node.Members:
			m.Accept(self)

	def OnNamespaceDeclaration(node as NamespaceDeclaration):
		_namespace = CodeNamespace(node.Name)
		_compileUnit.Namespaces.Add(_namespace)

	def OnImport(node as Import):
		_namespace.Imports.Add(CodeNamespaceImport(node.Namespace))

	def OnClassDefinition(node as ClassDefinition):
		oldClass = _class
		_class = CodeTypeDeclaration(node.Name)
		_class.IsClass = true

		for b as TypeReference in node.BaseTypes:
			_class.BaseTypes.Add(ConvTypeRef(b))

		for member as TypeMember in node.Members:
			member.Accept(self)

		if oldClass == null:
			_namespace.Types.Add(_class)
		else:
			oldClass.Members.Add(_class)
		_class = oldClass

	def OnStructDefinition(node as StructDefinition):
		oldClass = _class
		_class = CodeTypeDeclaration(node.Name)
		_class.IsStruct = true

		for b as TypeReference in node.BaseTypes:
			_class.BaseTypes.Add(ConvTypeRef(b))

		for member as TypeMember in node.Members:
			member.Accept(self)

		if oldClass == null:
			_namespace.Types.Add(_class)
		else:
			oldClass.Members.Add(_class)
		_class = oldClass

	def OnInterfaceDefinition(node as InterfaceDefinition):
		oldClass = _class
		_class = CodeTypeDeclaration(node.Name)
		_class.IsInterface = true

		for b as TypeReference in node.BaseTypes:
			_class.BaseTypes.Add(ConvTypeRef(b))

		for member as TypeMember in node.Members:
			member.Accept(self)

		if oldClass == null:
			_namespace.Types.Add(_class)
		else:
			oldClass.Members.Add(_class)
		_class = oldClass

	def OnField(node as Field):
		field = CodeMemberField(ConvTypeRef(node.Type), node.Name)
		field.Attributes = ConvModifiers(node)
		if node.Initializer != null:
			_expression = null
			//Visit(node.Initializer)
			field.InitExpression = _expression
		_class.Members.Add(field)

	def OnConstructor(node as Constructor):
		ConvertMethod(node, CodeConstructor())

	def OnMethod(node as Method):
		ConvertMethod(node, CodeMemberMethod(Name: node.Name))

	def OnDestructor(node as Destructor):
		ConvertMethod(node, CodeMemberMethod(Name: "Finalize"))

	def ConvertMethod(node as Method, method as CodeMemberMethod):
		method.Attributes = ConvModifiers(node)
		method.ReturnType = ConvTypeRef(node.ReturnType)
		if node.Parameters != null:
			for p as ParameterDeclaration in node.Parameters:
				method.Parameters.Add(CodeParameterDeclarationExpression(ConvTypeRef(p.Type), p.Name))
		_statements = method.Statements

		if node.Body != null:
			node.Body.Accept(self)

		_class.Members.Add(method)

	def OnArrayLiteralExpression(node as ArrayLiteralExpression):
		pass

	def OnArrayTypeReference(node as ArrayTypeReference):
		pass

	def OnAsExpression(node as AsExpression):
		pass

	def OnAttribute(node as Boo.Lang.Compiler.Ast.Attribute):
		pass

	def OnBinaryExpression(node as BinaryExpression):
		op = node.Operator
		if op == BinaryOperatorType.Assign:
			_expression = null
			node.Left.Accept(self)
			left = _expression
			_expression = null
			node.Right.Accept(self)
			if left != null and _expression != null:
				_statements.Add(CodeAssignStatement(left, _expression))
			_expression = null
			return

	def OnBlock(node as Block):
		for n as Statement in node.Statements:
			n.Accept(self)

	def OnBreakStatement(node as BreakStatement):
		pass

	def OnCallableBlockExpression(node as CallableBlockExpression):
		pass

	def OnCallableDefinition(node as CallableDefinition):
		pass

	def OnCallableTypeReference(node as CallableTypeReference):
		pass

	def OnCastExpression(node as CastExpression):
		pass

	def OnContinueStatement(node as ContinueStatement):
		pass

	def OnDeclaration(node as Declaration):
		pass

	def OnDeclarationStatement(node as DeclarationStatement):
		pass

	def OnEnumDefinition(node as EnumDefinition):
		pass

	def OnEnumMember(node as EnumMember):
		pass

	def OnParameterDeclaration(node as ParameterDeclaration):
		pass

	def OnEvent(node as Event):
		pass

	def OnExceptionHandler(node as ExceptionHandler):
		pass

	def OnExpressionInterpolationExpression(node as ExpressionInterpolationExpression):
		pass

	def OnExpressionPair(node as ExpressionPair):
		pass

	def OnExpressionStatement(node as ExpressionStatement):
		_expression = null
		node.Expression.Accept(self)
		if _expression != null:
			_statements.Add(CodeExpressionStatement(_expression))

	def OnForStatement(node as ForStatement):
		pass

	def OnExtendedGeneratorExpression(node as ExtendedGeneratorExpression):
		pass

	def OnGeneratorExpression(node as GeneratorExpression):
		pass

	def OnGivenStatement(node as GivenStatement):
		pass

	def OnGotoStatement(node as GotoStatement):
		_statements.Add(CodeGotoStatement(node.Label.Name))

	def OnNullLiteralExpression(node as NullLiteralExpression):
		_expression = CodePrimitiveExpression(null)

	def OnBoolLiteralExpression(node as BoolLiteralExpression):
		_expression = CodePrimitiveExpression(node.Value)

	def OnStringLiteralExpression(node as StringLiteralExpression):
		_expression = CodePrimitiveExpression(node.Value)

	def OnCharLiteralExpression(node as CharLiteralExpression):
		_expression = CodePrimitiveExpression(node.Value)

	def OnHashLiteralExpression(node as HashLiteralExpression):
		pass

	def OnIntegerLiteralExpression(node as IntegerLiteralExpression):
		_expression = CodePrimitiveExpression(node.Value)

	def OnDoubleLiteralExpression(node as DoubleLiteralExpression):
		_expression = CodePrimitiveExpression(node.Value)

	def OnListLiteralExpression(node as ListLiteralExpression):
		pass

	def OnIfStatement(node as IfStatement):
		pass

	def OnLabelStatement(node as LabelStatement):
		pass

	def OnLocal(node as Local):
		pass

	def OnMacroStatement(node as MacroStatement):
		pass

	def OnMemberReferenceExpression(node as MemberReferenceExpression):
		_expression = null
		node.Target.Accept(self)
		if _expression != null:
			if _expression isa CodeTypeReferenceExpression:
				// TODO: lookup if expression is static member or subtype
				_expression = CodeTypeReferenceExpression("${cast(CodeTypeReferenceExpression, _expression).Type.BaseType}.${node.Name}")
			else:
				_expression = CreateMemberExpression(_expression, node.Name)

	def OnReferenceExpression(node as ReferenceExpression):
		p = GetParserService()
		if p.GetClass(node.Name) != null:
			_expression = CodeTypeReferenceExpression(node.Name)
		elif p.NamespaceExists(node.Name):
			_expression = CodeTypeReferenceExpression(node.Name)
		else:
			_expression = CreateMemberExpression(CodeThisReferenceExpression(), node.Name)

	def CreateMemberExpression(expr as CodeExpression, name as string):
		if expr isa CodeTypeReferenceExpression:
			typeRef = cast(CodeTypeReferenceExpression, _expression).Type.BaseType
			return CreateMemberExpression(expr, typeRef, name, true)
		elif expr isa CodeThisReferenceExpression:
			typeRef = "${_namespace.Name}.${_class.Name}"
			return CreateMemberExpression(expr, typeRef, name, false)
		return CodeFieldReferenceExpression(expr, name)

	def CreateMemberExpression(target as CodeExpression, parentName as string, name as string, isStatic as bool):
		combinedName = "${parentName}.${name}"
		p = GetParserService()
		parentClass = p.GetClass(parentName)
		if parentClass == null:
			if p.GetClass(combinedName) != null:
				return CodeTypeReferenceExpression(combinedName)
			elif p.NamespaceExists(combinedName):
				return CodeTypeReferenceExpression(combinedName)
		else:
			if isStatic:
				for innerClass as IClass in parentClass.InnerClasses:
					if innerClass.Name == name:
						return CodeTypeReferenceExpression(combinedName)
			for c as IClass in parentClass.ClassInheritanceTree:
				for ev as IEvent in c.Events:
					if ev.IsStatic == isStatic:
						return CodeEventReferenceExpression(target, name)
				for me as IMethod in c.Methods:
					if me.IsStatic == isStatic:
						return CodeMethodReferenceExpression(target, name)
				for prop as IProperty in c.Properties:
					if prop.IsStatic == isStatic:
						return CodePropertyReferenceExpression(target, name)
				for field as IField in c.Fields:
					if field.IsStatic == isStatic:
						return CodeFieldReferenceExpression(target, name)
		return CodeFieldReferenceExpression(target, name)

	def GetParserService() as ICSharpCode.SharpDevelop.Services.IParserService:
		return ICSharpCode.Core.Services.ServiceManager.Services.GetService(typeof(ICSharpCode.SharpDevelop.Services.IParserService))

	def OnMethodInvocationExpression(node as MethodInvocationExpression):
		_expression = null
		node.Target.Accept(self)
		if _expression != null:
			if _expression isa CodeTypeReferenceExpression:
				_expression = CodeObjectCreateExpression(cast(CodeTypeReferenceExpression, _expression).Type, ConvertExpressions(node.Arguments))
			elif _expression isa CodeMethodReferenceExpression:
				_expression = CodeMethodInvokeExpression(_expression, ConvertExpressions(node.Arguments))
			elif _expression isa CodeFieldReferenceExpression:
				// when a type is unknown, a MemberReferenceExpression is translated into a CodeFieldReferenceExpression
				cfre as CodeFieldReferenceExpression = _expression
				_expression = CodeMethodInvokeExpression(cfre.TargetObject, cfre.FieldName, ConvertExpressions(node.Arguments))
			else:
				_expression = null

	def ConvertExpressions(expressions as ExpressionCollection):
	"""Converts a list of expressions to CodeDom expressions."""
		args = array(CodeExpression, expressions.Count)
		i = 0
		while i < args.Length:
			_expression = null
			expressions[i].Accept(self)
			args[i] = _expression
			i += 1
		return args

	def OnOmittedExpression(node as OmittedExpression):
		pass

	def OnProperty(node as Property):
		pass

	def OnRaiseStatement(node as RaiseStatement):
		pass

	def OnRELiteralExpression(node as RELiteralExpression):
		pass

	def OnRetryStatement(node as RetryStatement):
		pass

	def OnReturnStatement(node as ReturnStatement):
		_expression = null
		if node.Expression != null:
			node.Expression.Accept(self)
		_statements.Add(CodeMethodReturnStatement(_expression))

	def OnSelfLiteralExpression(node as SelfLiteralExpression):
		_expression = CodeThisReferenceExpression()

	def OnSimpleTypeReference(node as SimpleTypeReference):
		pass

	def OnSlice(node as Slice):
		pass

	def OnSlicingExpression(node as SlicingExpression):
		pass

	def OnStatementModifier(node as StatementModifier):
		pass

	def OnSuperLiteralExpression(node as SuperLiteralExpression):
		_expression = CodeBaseReferenceExpression()

	def OnTernaryExpression(node as TernaryExpression):
		pass

	def OnTimeSpanLiteralExpression(node as TimeSpanLiteralExpression):
		pass

	def OnTryStatement(node as TryStatement):
		pass

	def OnTypeofExpression(node as TypeofExpression):
		pass

	def OnUnaryExpression(node as UnaryExpression):
		pass

	def OnUnlessStatement(node as UnlessStatement):
		pass

	def OnUnpackStatement(node as UnpackStatement):
		pass

	def OnWhenClause(node as WhenClause):
		pass

	def OnWhileStatement(node as WhileStatement):
		pass

	def OnYieldStatement(node as YieldStatement):
		pass

namespace BooBinding

import System
import System.Collections
import System.CodeDom
import System.Text
import Boo.Lang.Compiler
import Boo.Lang.Compiler.Ast
import Boo.Lang.Compiler.Ast.Visitors
import Boo.Lang.Parser
import SharpDevelop.Internal.Parser

class CodeDomVisitor(IAstVisitor):
"""The CodeDomVisitor is able to convert from the Boo AST to System.CodeDom
It makes use of the SharpDevelop parser service to get necessary additional information about the
types."""
	[Getter(OutputCompileUnit)]
	_compileUnit = CodeCompileUnit()
	_namespace as CodeNamespace
	_class as CodeTypeDeclaration
	_statements as CodeStatementCollection
	_expression as CodeExpression

	def ConvModifiers(member as TypeMember) as MemberAttributes:
		if member isa Field:
			return ConvModifiers(member.Modifiers, MemberAttributes.Family)
		else:
			return ConvModifiers(member.Modifiers, MemberAttributes.Public)

	def ConvModifiers(modifier as TypeMemberModifiers, defaultAttr as MemberAttributes) as MemberAttributes:
		// Boo is not able to convert 0 to MemberAttributes, therefore we need to use
		// a trick to get the default value
		noAttr = MemberAttributes.Abstract & MemberAttributes.Final
		attr = noAttr
		if (modifier & TypeMemberModifiers.Abstract) == TypeMemberModifiers.Abstract:
			attr = attr | MemberAttributes.Abstract
		if (modifier & TypeMemberModifiers.Final) == TypeMemberModifiers.Final:
			attr = attr | MemberAttributes.Const
		if (modifier & TypeMemberModifiers.Internal) == TypeMemberModifiers.Internal:
			attr = attr | MemberAttributes.Assembly
		if (modifier & TypeMemberModifiers.Override) == TypeMemberModifiers.Override:
			attr = attr | MemberAttributes.Override
		if (modifier & TypeMemberModifiers.Private) == TypeMemberModifiers.Private:
			attr = attr | MemberAttributes.Private
		if (modifier & TypeMemberModifiers.Protected) == TypeMemberModifiers.Protected:
			attr = attr | MemberAttributes.Family
		if (modifier & TypeMemberModifiers.Public) == TypeMemberModifiers.Public:
			attr = attr | MemberAttributes.Public
		if (modifier & TypeMemberModifiers.Static) == TypeMemberModifiers.Static:
			attr = attr | MemberAttributes.Static
		if (modifier & TypeMemberModifiers.Virtual) != TypeMemberModifiers.Virtual:
			attr = attr | MemberAttributes.Final
		if attr == noAttr:
			return defaultAttr
		else:
			return attr

	def ConvTypeRef(ref as TypeReference):
		return null if ref == null
		name = ref.ToString()
		expandedName = BooAmbience.ReverseTypeConversionTable[name]
		name = expandedName if expandedName != null
		return CodeTypeReference(name)

	def OnCompileUnit(node as CompileUnit):
		for m as Module in node.Modules:
			m.Accept(self)

	def OnModule(node as Module):
		if node.Namespace == null:
			_namespace = CodeNamespace("Global")
			_compileUnit.Namespaces.Add(_namespace)
		else:
			node.Namespace.Accept(self)
		for i as Import in node.Imports:
			i.Accept(self)
		for m as TypeMember in node.Members:
			m.Accept(self)

	def OnNamespaceDeclaration(node as NamespaceDeclaration):
		_namespace = CodeNamespace(node.Name)
		_compileUnit.Namespaces.Add(_namespace)

	def OnImport(node as Import):
		_namespace.Imports.Add(CodeNamespaceImport(node.Namespace))

	def OnClassDefinition(node as ClassDefinition):
		oldClass = _class
		_class = CodeTypeDeclaration(node.Name)
		_class.IsClass = true

		for b as TypeReference in node.BaseTypes:
			_class.BaseTypes.Add(ConvTypeRef(b))

		for member as TypeMember in node.Members:
			member.Accept(self)

		if oldClass == null:
			_namespace.Types.Add(_class)
		else:
			oldClass.Members.Add(_class)
		_class = oldClass

	def OnStructDefinition(node as StructDefinition):
		oldClass = _class
		_class = CodeTypeDeclaration(node.Name)
		_class.IsStruct = true

		for b as TypeReference in node.BaseTypes:
			_class.BaseTypes.Add(ConvTypeRef(b))

		for member as TypeMember in node.Members:
			member.Accept(self)

		if oldClass == null:
			_namespace.Types.Add(_class)
		else:
			oldClass.Members.Add(_class)
		_class = oldClass

	def OnInterfaceDefinition(node as InterfaceDefinition):
		oldClass = _class
		_class = CodeTypeDeclaration(node.Name)
		_class.IsInterface = true

		for b as TypeReference in node.BaseTypes:
			_class.BaseTypes.Add(ConvTypeRef(b))

		for member as TypeMember in node.Members:
			member.Accept(self)

		if oldClass == null:
			_namespace.Types.Add(_class)
		else:
			oldClass.Members.Add(_class)
		_class = oldClass

	def OnField(node as Field):
		field = CodeMemberField(ConvTypeRef(node.Type), node.Name)
		field.Attributes = ConvModifiers(node)
		if node.Initializer != null:
			_expression = null
			//Visit(node.Initializer)
			field.InitExpression = _expression
		_class.Members.Add(field)

	def OnConstructor(node as Constructor):
		ConvertMethod(node, CodeConstructor())

	def OnMethod(node as Method):
		ConvertMethod(node, CodeMemberMethod(Name: node.Name))

	def OnDestructor(node as Destructor):
		ConvertMethod(node, CodeMemberMethod(Name: "Finalize"))

	def ConvertMethod(node as Method, method as CodeMemberMethod):
		method.Attributes = ConvModifiers(node)
		method.ReturnType = ConvTypeRef(node.ReturnType)
		if node.Parameters != null:
			for p as ParameterDeclaration in node.Parameters:
				method.Parameters.Add(CodeParameterDeclarationExpression(ConvTypeRef(p.Type), p.Name))
		_statements = method.Statements

		if node.Body != null:
			node.Body.Accept(self)

		_class.Members.Add(method)

	def OnArrayLiteralExpression(node as ArrayLiteralExpression):
		pass

	def OnArrayTypeReference(node as ArrayTypeReference):
		pass

	def OnAsExpression(node as AsExpression):
		pass

	def OnAttribute(node as Boo.Lang.Compiler.Ast.Attribute):
		pass

	def OnBinaryExpression(node as BinaryExpression):
		op = node.Operator
		if op == BinaryOperatorType.Assign:
			_expression = null
			node.Left.Accept(self)
			left = _expression
			_expression = null
			node.Right.Accept(self)
			if left != null and _expression != null:
				_statements.Add(CodeAssignStatement(left, _expression))
			_expression = null
			return

	def OnBlock(node as Block):
		for n as Statement in node.Statements:
			n.Accept(self)

	def OnBreakStatement(node as BreakStatement):
		pass

	def OnCallableBlockExpression(node as CallableBlockExpression):
		pass

	def OnCallableDefinition(node as CallableDefinition):
		pass

	def OnCallableTypeReference(node as CallableTypeReference):
		pass

	def OnCastExpression(node as CastExpression):
		pass

	def OnContinueStatement(node as ContinueStatement):
		pass

	def OnDeclaration(node as Declaration):
		pass

	def OnDeclarationStatement(node as DeclarationStatement):
		pass

	def OnEnumDefinition(node as EnumDefinition):
		pass

	def OnEnumMember(node as EnumMember):
		pass

	def OnParameterDeclaration(node as ParameterDeclaration):
		pass

	def OnEvent(node as Event):
		pass

	def OnExceptionHandler(node as ExceptionHandler):
		pass

	def OnExpressionInterpolationExpression(node as ExpressionInterpolationExpression):
		pass

	def OnExpressionPair(node as ExpressionPair):
		pass

	def OnExpressionStatement(node as ExpressionStatement):
		_expression = null
		node.Expression.Accept(self)
		if _expression != null:
			_statements.Add(CodeExpressionStatement(_expression))

	def OnForStatement(node as ForStatement):
		pass

	def OnExtendedGeneratorExpression(node as ExtendedGeneratorExpression):
		pass

	def OnGeneratorExpression(node as GeneratorExpression):
		pass

	def OnGivenStatement(node as GivenStatement):
		pass

	def OnGotoStatement(node as GotoStatement):
		_statements.Add(CodeGotoStatement(node.Label.Name))

	def OnNullLiteralExpression(node as NullLiteralExpression):
		_expression = CodePrimitiveExpression(null)

	def OnBoolLiteralExpression(node as BoolLiteralExpression):
		_expression = CodePrimitiveExpression(node.Value)

	def OnStringLiteralExpression(node as StringLiteralExpression):
		_expression = CodePrimitiveExpression(node.Value)

	def OnHashLiteralExpression(node as HashLiteralExpression):
		pass

	def OnIntegerLiteralExpression(node as IntegerLiteralExpression):
		_expression = CodePrimitiveExpression(node.Value)

	def OnDoubleLiteralExpression(node as DoubleLiteralExpression):
		_expression = CodePrimitiveExpression(node.Value)

	def OnListLiteralExpression(node as ListLiteralExpression):
		pass

	def OnIfStatement(node as IfStatement):
		pass

	def OnLabelStatement(node as LabelStatement):
		pass

	def OnLocal(node as Local):
		pass

	def OnMacroStatement(node as MacroStatement):
		pass

	def OnMemberReferenceExpression(node as MemberReferenceExpression):
		_expression = null
		node.Target.Accept(self)
		if _expression != null:
			if _expression isa CodeTypeReferenceExpression:
				// TODO: lookup if expression is static member or subtype
				_expression = CodeTypeReferenceExpression("${cast(CodeTypeReferenceExpression, _expression).Type.BaseType}.${node.Name}")
			else:
				_expression = CreateMemberExpression(_expression, node.Name)

	def OnReferenceExpression(node as ReferenceExpression):
		p = GetParserService()
		if p.GetClass(node.Name) != null:
			_expression = CodeTypeReferenceExpression(node.Name)
		elif p.NamespaceExists(node.Name):
			_expression = CodeTypeReferenceExpression(node.Name)
		else:
			_expression = CreateMemberExpression(CodeThisReferenceExpression(), node.Name)

	def CreateMemberExpression(expr as CodeExpression, name as string):
		if expr isa CodeTypeReferenceExpression:
			typeRef = cast(CodeTypeReferenceExpression, _expression).Type.BaseType
			return CreateMemberExpression(expr, typeRef, name, true)
		elif expr isa CodeThisReferenceExpression:
			typeRef = "${_namespace.Name}.${_class.Name}"
			return CreateMemberExpression(expr, typeRef, name, false)
		return CodeFieldReferenceExpression(expr, name)

	def CreateMemberExpression(target as CodeExpression, parentName as string, name as string, isStatic as bool):
		combinedName = "${parentName}.${name}"
		p = GetParserService()
		parentClass = p.GetClass(parentName)
		if parentClass == null:
			if p.GetClass(combinedName) != null:
				return CodeTypeReferenceExpression(combinedName)
			elif p.NamespaceExists(combinedName):
				return CodeTypeReferenceExpression(combinedName)
		else:
			if isStatic:
				for innerClass as IClass in parentClass.InnerClasses:
					if innerClass.Name == name:
						return CodeTypeReferenceExpression(combinedName)
			for c as IClass in parentClass.ClassInheritanceTree:
				for ev as IEvent in c.Events:
					if ev.IsStatic == isStatic:
						return CodeEventReferenceExpression(target, name)
				for me as IMethod in c.Methods:
					if me.IsStatic == isStatic:
						return CodeMethodReferenceExpression(target, name)
				for prop as IProperty in c.Properties:
					if prop.IsStatic == isStatic:
						return CodePropertyReferenceExpression(target, name)
				for field as IField in c.Fields:
					if field.IsStatic == isStatic:
						return CodeFieldReferenceExpression(target, name)
		return CodeFieldReferenceExpression(target, name)

	def GetParserService() as ICSharpCode.SharpDevelop.Services.IParserService:
		return ICSharpCode.Core.Services.ServiceManager.Services.GetService(typeof(ICSharpCode.SharpDevelop.Services.IParserService))

	def OnMethodInvocationExpression(node as MethodInvocationExpression):
		_expression = null
		node.Target.Accept(self)
		if _expression != null:
			if _expression isa CodeTypeReferenceExpression:
				_expression = CodeObjectCreateExpression(cast(CodeTypeReferenceExpression, _expression).Type, ConvertExpressions(node.Arguments))
			elif _expression isa CodeMethodReferenceExpression:
				_expression = CodeMethodInvokeExpression(_expression, ConvertExpressions(node.Arguments))
			elif _expression isa CodeFieldReferenceExpression:
				// when a type is unknown, a MemberReferenceExpression is translated into a CodeFieldReferenceExpression
				cfre as CodeFieldReferenceExpression = _expression
				_expression = CodeMethodInvokeExpression(cfre.TargetObject, cfre.FieldName, ConvertExpressions(node.Arguments))
			else:
				_expression = null

	def ConvertExpressions(expressions as ExpressionCollection):
	"""Converts a list of expressions to CodeDom expressions."""
		args = array(CodeExpression, expressions.Count)
		i = 0
		while i < args.Length:
			_expression = null
			expressions[i].Accept(self)
			args[i] = _expression
			i += 1
		return args

	def OnOmittedExpression(node as OmittedExpression):
		pass

	def OnProperty(node as Property):
		pass

	def OnRaiseStatement(node as RaiseStatement):
		pass

	def OnRELiteralExpression(node as RELiteralExpression):
		pass

	def OnRetryStatement(node as RetryStatement):
		pass

	def OnReturnStatement(node as ReturnStatement):
		_expression = null
		if node.Expression != null:
			node.Expression.Accept(self)
		_statements.Add(CodeMethodReturnStatement(_expression))

	def OnSelfLiteralExpression(node as SelfLiteralExpression):
		_expression = CodeThisReferenceExpression()

	def OnSimpleTypeReference(node as SimpleTypeReference):
		pass

	def OnSlice(node as Slice):
		pass

	def OnSlicingExpression(node as SlicingExpression):
		pass

	def OnStatementModifier(node as StatementModifier):
		pass

	def OnSuperLiteralExpression(node as SuperLiteralExpression):
		_expression = CodeBaseReferenceExpression()

	def OnTernaryExpression(node as TernaryExpression):
		pass

	def OnTimeSpanLiteralExpression(node as TimeSpanLiteralExpression):
		pass

	def OnTryStatement(node as TryStatement):
		pass

	def OnTypeofExpression(node as TypeofExpression):
		pass

	def OnUnaryExpression(node as UnaryExpression):
		pass

	def OnUnlessStatement(node as UnlessStatement):
		pass

	def OnUnpackStatement(node as UnpackStatement):
		pass

	def OnWhenClause(node as WhenClause):
		pass

	def OnWhileStatement(node as WhileStatement):
		pass

	def OnYieldStatement(node as YieldStatement):
		pass


use context subclass instead of generics

namespace pegs

import Boo.Pegs

class CalculatorContext(PegContext):

	[getter(Stack)] _stack = []

	def constructor(text as string):
		super(text)

def push(ctx as CalculatorContext, value as int):
	ctx.Stack.Push(value)

def pop(ctx as CalculatorContext) as int:
	return ctx.Stack.Pop()

def readEvalLoop(calculator as PegExpression):
	while true:
		expression = prompt("> ")
		if string.IsNullOrEmpty(expression): break
		ctx = CalculatorContext(expression)
		if calculator.Match(ctx):
			print pop(ctx)
		else:
			print "--" + "-" * ctx.Input.Position + "^"
			print "DOES NOT COMPUTE!"

// the $ operator inside actions means
// "access the function specified passing the context as the first argument"
// in other words, $pop means pop(context)

peg:
	calculator = spacing, addition, eof
	addition = term, --("+", spacing, term, { $push($pop + $pop) })
	term = factor, --("*", spacing, factor, { $push($pop * $pop) })
	factor = ++digit(), { $push(int.Parse($text)) }, spacing
	spacing = --whitespace()
	eof = not any()

readEvalLoop calculator

namespace pegs

import Boo.Pegs

def push(ctx as PegContextWithPayload[of List], value as int):
	ctx.Payload.Push(value)

def pop(ctx as PegContextWithPayload[of List]) as int:
	return ctx.Payload.Pop()

def readEvalLoop(calculator as PegExpression):
	while true:
		expression = prompt("> ")
		if string.IsNullOrEmpty(expression): break
		ctx = PegContextWithPayload[of List](expression, [])
		if calculator.Match(ctx):
			print pop(ctx)
		else:
			print "--" + "-" * ctx.Input.Position + "^"
			print "DOES NOT COMPUTE!"

// the $ operator inside actions means
// "access the function specified passing the context as the first argument"
// in other words, $pop means pop(context)

peg:
	calculator = spacing, addition, eof
	addition = term, --("+", spacing, term, { $push($pop + $pop) })
	term = factor, --("*", spacing, factor, { $push($pop * $pop) })
	factor = ++digit(), { $push(int.Parse($text)) }, spacing
	spacing = --whitespace()
	eof = not any()

readEvalLoop calculator


handle no debug option in nant booc task too

git-svn-id: fcce7d6ce0ac15bf24f68871b5145d46fc068279@2133 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.None
	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

	[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:
			DebugOutput = DebugOutput.Enable

	[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

#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.None
	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

	[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:
			DebugOutput = DebugOutput.Enable

	[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')

		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


update to latest boo: InternalCallableType moved to Boo.Lang.Compiler.TypeSystem.Internal

namespace Boojay.Compilation.Steps

import Boo.Lang.Compiler.Ast
import Boo.Lang.Compiler.TypeSystem.Internal
import Boo.Lang.Compiler.Steps

class NormalizeCallables(AbstractTransformerCompilerStep):

	override def Run():
		if len(Errors) > 0:
			return
		Visit CompileUnit

	override def EnterClassDefinition(node as ClassDefinition):
		if node.Name == "CompilerGeneratedExtensions":
			RemoveCurrentNode()
			return false
		return true

	override def LeaveClassDefinition(node as ClassDefinition):
		callableType = bindingFor(node) as InternalCallableType
		if callableType is null:
			return
		normalize callableType

	def normalize(type as InternalCallableType):
		typeDef = type.TypeDefinition
		typeDef.Members.Remove(typeDef.Members["BeginInvoke"])
		typeDef.Members.Remove(typeDef.Members["EndInvoke"])

		ctor = typeDef.GetConstructor(0)
		ctor.Parameters.Clear()
		ctor.Body.Add(CodeBuilder.CreateSuperConstructorInvocation(type.BaseType))

		invoke = typeDef.Members["Invoke"]
		invoke.Modifiers = TypeMemberModifiers.Public | TypeMemberModifiers.Abstract

		typeDef.Modifiers &= ~TypeMemberModifiers.Final
		typeDef.Modifiers |= TypeMemberModifiers.Abstract

namespace Boojay.Compilation.Steps

import Boo.Lang.Compiler.Ast
import Boo.Lang.Compiler.TypeSystem
import Boo.Lang.Compiler.Steps

class NormalizeCallables(AbstractTransformerCompilerStep):

	override def Run():
		if len(Errors) > 0:
			return
		Visit CompileUnit

	override def EnterClassDefinition(node as ClassDefinition):
		if node.Name == "CompilerGeneratedExtensions":
			RemoveCurrentNode()
			return false
		return true

	override def LeaveClassDefinition(node as ClassDefinition):
		callableType = bindingFor(node) as InternalCallableType
		if callableType is null:
			return
		normalize callableType

	def normalize(type as InternalCallableType):
		typeDef = type.TypeDefinition
		typeDef.Members.Remove(typeDef.Members["BeginInvoke"])
		typeDef.Members.Remove(typeDef.Members["EndInvoke"])

		ctor = typeDef.GetConstructor(0)
		ctor.Parameters.Clear()
		ctor.Body.Add(CodeBuilder.CreateSuperConstructorInvocation(type.BaseType))

		invoke = typeDef.Members["Invoke"]
		invoke.Modifiers = TypeMemberModifiers.Public | TypeMemberModifiers.Abstract

		typeDef.Modifiers &= ~TypeMemberModifiers.Final
		typeDef.Modifiers |= TypeMemberModifiers.Abstract