component container to properly dispose of internal controls

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

namespace BooExplorer

import System
import System.Environment
import System.IO
import System.ComponentModel
import System.Windows.Forms
import System.Drawing
import WeifenLuo.WinFormsUI
import Boo.Lang.Compiler
import Boo.Lang.Compiler.Pipelines
import Boo.Lang.Compiler.Ast
import Boo.Lang.Compiler.IO

class MainForm(Form):

	_dockPanel as DockPanel
	_status as StatusBar
	_statusPanel1 as StatusBarPanel
	_timer as Timer

	[getter(Settings)]
	_settings = LoadSettings()

	[getter(DocumentOutline)]
	_documentOutline = BooExplorer.DocumentOutline()

	[getter(TaskList)]
	_taskList = BooExplorer.TaskList(self)

	[getter(OutputPane)]
	_outputPane = BooExplorer.OutputPane()

	[getter(InteractiveConsole)]
	_interactiveConsole = BooExplorer.InteractiveConsole(self)

	[getter(TextInterceptors)]
	_textInterceptors as (ITextInterceptor)

	_argv as (string)

	_menuItemClose as MenuItem
	_menuItemSave as MenuItem
	_menuItemSaveAs as MenuItem

	_parser = BooCompiler()

	_resourceManager = System.Resources.ResourceManager(MainForm)

	_container = System.ComponentModel.Container()

	def constructor(argv as (string)):
		_argv = argv
		_dockPanel = DockPanel(Dock: DockStyle.Fill,
						ActiveAutoHideContent: null,
						TabIndex: 1,
						ActiveDocumentChanged: _dockPanel_ActiveDocumentChanged)

		_statusPanel1 = StatusBarPanel(AutoSize: StatusBarPanelAutoSize.Contents)

		_status = StatusBar(ShowPanels: true, TabIndex: 2)
		_status.Panels.Add(_statusPanel1)

		_parser.Parameters.Pipeline = Boo.Lang.Compiler.Pipelines.Parse()
		(_parser.Parameters.Pipeline[0] as duck).TabSize = 1

		SuspendLayout()

		self.Icon = _resourceManager.GetObject("_icon")
		self.Size = System.Drawing.Size(800, 600)
		self.Menu = CreateMainMenu()
		self.Text = "Boo Explorer"
		self.IsMdiContainer = true

		_container.Add(_dockPanel)
		_container.Add(_status)

		Controls.AddRange((
					_dockPanel,
					_status))
		ResumeLayout(false)

		LoadInterceptors()

		_timer = Timer(Tick: _timer_Tick, Interval: 50ms.TotalMilliseconds)
		_timer.Enabled = true

	override def Dispose(flag as bool):
		_container.Dispose()
		super(flag)

	private def GetSettingsFileName():
		return Path.Combine(GetApplicationDataFolder(), "settings.xml")

	private def SaveSettings():
		_settings.Save(GetSettingsFileName())

	private def LoadSettings():
		fname = GetSettingsFileName()
		if File.Exists(fname):
			return BooxSettings.Load(fname)
		return BooxSettings()

	private def CreateMainMenu():

		menu = MainMenu()
		file = MenuItem(Text: "&File", MergeOrder: 0)
		file.MenuItems.Add(MenuItem(Text: "&Open...",
									Click: _menuItemOpen_Click,
									Shortcut: Shortcut.CtrlO))
		file.MenuItems.Add(MenuItem(Text: "&New",
									Click: _menuItemNew_Click,
									Shortcut: Shortcut.CtrlN))

		file.MenuItems.Add(MenuItem("-"))

		file.MenuItems.Add(_menuItemSave = MenuItem(Text: "&Save",
									Enabled: false,
									Click: _menuItemSave_Click,
									Shortcut: Shortcut.CtrlS))
		file.MenuItems.Add(_menuItemSaveAs = MenuItem(Text: "S&ave as...",
									Enabled: false,
									Click: _menuItemSaveAs_Click))

		file.MenuItems.Add(_menuItemClose = MenuItem(Text: "&Close",
									Click: _menuItemClose_Click,
									Shortcut: Shortcut.CtrlW,
									Enabled: false))

		file.MenuItems.Add(MenuItem("-"))
		file.MenuItems.Add(MenuItem(Text: "E&xit",
									Shortcut: Shortcut.CtrlQ,
									Click: _menuItemExit_Click))

		tools = MenuItem(Text: "&Tools", MergeOrder: 2, MergeType: MenuMerge.MergeItems)
		tools.MenuItems.Add(MenuItem(Text: "&Options",
								Shortcut: Shortcut.CtrlO,
								Click: _menuItemOptions_Click,
								MergeOrder: int.MaxValue))

		view = MenuItem(Text: "&View", MergeOrder: 4)
		view.MenuItems.AddRange(
			(
				MenuItem(Text: "Document Outline",
						Click: _menuItemDocumentOutline_Click,
						Shortcut: Shortcut.CtrlShiftD),
				MenuItem(Text: "Task List",
						Click: _menuItemTaskList_Click,
						Shortcut: Shortcut.CtrlShiftT),
				MenuItem(Text: "Output",
						Click: _menuItemOutputPane_Click,
						Shortcut: Shortcut.CtrlShiftO),
				MenuItem(Text: "Prompt",
						Click: ShowPrompt,
						Shortcut: Shortcut.CtrlShiftP)
			))

		menu.MenuItems.AddRange((file, tools, view))
		return menu

	def _timer_Tick(sender, args as EventArgs):
		_timer.Enabled = false

		if File.Exists(GetDockStateXmlFileName()):
			LoadDockState()
			OpenDocuments(_argv)
		else:
			if len(_argv):
				OpenDocuments(_argv)
			else:
				NewDocument()
			ShowDocumentOutline()

	StatusText as string:
		set:
			_statusPanel1.Text = value

	def ParseString(fname as string, code as string):
		try:
			_parser.Parameters.Input.Add(StringInput(fname, code))
			return _parser.Run().CompileUnit
		ensure:
			_parser.Parameters.Input.Clear()

	private def LoadInterceptors():
		tempInterceptors = []

		if _settings.LoadPlugins:
			for file in Directory.GetFiles(MapPath("scripts"), "*.int"):
				interceptors = LoadInterceptorsFromFile(file)
				tempInterceptors = tempInterceptors + interceptors if interceptors

		_textInterceptors = array(ITextInterceptor, tempInterceptors)
		StatusText = "Loaded ${len(_textInterceptors)} TextInterceptor(s)"

	def MapPath(path as string):
		return Path.Combine(Path.GetDirectoryName(Application.ExecutablePath), path)

	def LoadInterceptorsFromFile(fileName as string):
		script = ScriptCompiler.CompileFile(fileName)
		if len(script.Errors):
			for error in script.Errors:
				print("Compiler error: ${error}")
			return null

		retTypes = script.GetTypes()
		return null unless retTypes
		return [cast(ITextInterceptor, retType()) for retType in retTypes if retType() isa ITextInterceptor]

	def Expand(fname as string, code as string):
		compiler = BooCompiler()
		compiler.Parameters.OutputWriter = StringWriter()
		compiler.Parameters.Pipeline = CompileToBoo()
		compiler.Parameters.Input.Add(StringInput(fname, code))

		result = compiler.Run()
		self.UpdateTaskList(result.Errors)

		NewDocument().TextContent = compiler.Parameters.OutputWriter.ToString()

	def ShowDocumentOutline():
		ShowContent(_documentOutline)

	private def ShowContent(content as DockContent):
		content.Show(_dockPanel)
		if DockState.Unknown == content.DockState:
			content.Pane.DockState = content.ShowHint

	def NewDocument():
		editor = BooEditor(self)
		editor.Show(_dockPanel)
		editor.TextArea.Focus()
		return editor

	def OpenDocuments([required] fnames):
		for fname in fnames:
			try:
				OpenDocument(fname)
			except x:
				print(x)

	def OpenDocument([required] filename as string):
		filename = Path.GetFullPath(filename)
		content = FindEditor(filename)
		if content is null:
			editor = CreateEditor(filename)
			editor.Show(_dockPanel)
			editor.TextArea.Focus()
			return editor
		else:
			content.Show(_dockPanel)
			content.TextArea.Focus()
			return content

	private def CreateEditor([required] fname as string):
		editor = BooEditor(self)
		editor.Open(fname)
		return editor

	def _dockPanel_ActiveDocumentChanged(sender, args as EventArgs):
		document = _dockPanel.ActiveDocument
		editor = document as BooEditor
		_documentOutline.ActiveDocument = editor
		_menuItemClose.Enabled = document is not null
		_menuItemSaveAs.Enabled = _menuItemSave.Enabled = document is not null

	def _menuItemSaveAs_Click(sender, args as EventArgs):
		cast(BooEditor, _dockPanel.ActiveDocument).SaveAs()

	def _menuItemSave_Click(sender, args as EventArgs):
		cast(BooEditor, _dockPanel.ActiveDocument).Save()

	def _menuItemExit_Click(sender, args as EventArgs):
		self.Close()

	def _menuItemClose_Click(sender, args as EventArgs):
		_dockPanel.ActiveDocument.Close()

	def _menuItemDocumentOutline_Click(sender, args as EventArgs):
		ShowDocumentOutline()

	def _menuItemTaskList_Click(sender, args as EventArgs):
		ShowTaskList()

	def UpdateTaskList(errors as CompilerErrorCollection):
		_taskList.Update(errors)
		ShowTaskList() if len(errors)

	def ShowTaskList():
		ShowContent(_taskList)

	def ShowOutputPane():
		ShowContent(_outputPane)

	def ShowPrompt():
		ShowContent(_interactiveConsole)

	def _menuItemOutputPane_Click(sender, args as EventArgs):
		ShowOutputPane()

	def _menuItemOptions_Click():
		dlg = Form(Text: "Options")
		dlg.Controls.Add(PropertyGrid(
							Dock: DockStyle.Fill,
							SelectedObject: _settings,
							Font: Font,
							PropertySort: PropertySort.Alphabetical))
		dlg.ShowDialog()
		SaveSettings()

	def _menuItemOpen_Click(sender, args as EventArgs):
		dlg = OpenFileDialog(
					Filter: "boo files (*.boo)|*.boo|All files (*.*)|*.*",
					Multiselect: true)
		if DialogResult.OK == dlg.ShowDialog(self):
			for fname in dlg.FileNames:
				OpenDocument(fname)

	def _menuItemNew_Click(sender, args as EventArgs):
		NewDocument()

	def GetApplicationDataFolder():
		folder = Application.UserAppDataPath
		Directory.CreateDirectory(folder) unless Directory.Exists(folder)
		return folder

	def GetDockStateXmlFileName():
		return Path.Combine(GetApplicationDataFolder(), "dockstate.xml")

	def SaveDockState():
		_dockPanel.SaveAsXml(GetDockStateXmlFileName())

	def LoadDockState():
		_dockPanel.LoadFromXml(GetDockStateXmlFileName(), OnDeserializeDockContent)

	def OnDeserializeDockContent(persistString as string) as DockContent:
		type, content = /\|/.Split(persistString)
		print("type: ${type}, content: ${content}")
		if "DocumentOutline" == type:
			return _documentOutline
		if "InteractiveConsole" == type:
			return _interactiveConsole
		if "TaskList" == type:
			return _taskList
		if "OutputPane" == type:
			return _outputPane
		if "BooEditor" == type:
			editor = BooEditor(self)
			editor.Open(content) if File.Exists(content)
			return editor
		raise ArgumentException("Invalid persistence string: ${persistString}")

	override protected def OnClosed(args as EventArgs):
		SaveDockState()
		super(args)

	override protected def OnClosing(args as CancelEventArgs):
		super(args)
		if not args.Cancel:
			dirtyDocuments = [
							editor.GetSafeFileName()
							for document in _dockPanel.Documents
							if (editor=(document as BooEditor)) and editor.IsDirty
							]
			return unless len(dirtyDocuments)

			args.Cancel = (
							DialogResult.Yes !=
							MessageBox.Show("The following files were modified:\n\n\t" +
											join(dirtyDocuments, "\n\t") +
											"\n\nAre you sure you want to leave and lose all your changes?",
											"Boo Explorer",
											MessageBoxButtons.YesNo))

	def FindEditor(fname as string):
		for document in _dockPanel.Documents:
			editor = document as BooEditor
			if editor and editor.FileName == fname:
				return editor
		return null

#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

namespace BooExplorer

import System
import System.Environment
import System.IO
import System.ComponentModel
import System.Windows.Forms
import System.Drawing
import WeifenLuo.WinFormsUI
import Boo.Lang.Compiler
import Boo.Lang.Compiler.Pipelines
import Boo.Lang.Compiler.Ast
import Boo.Lang.Compiler.IO

class MainForm(Form):

	_dockPanel as DockPanel
	_status as StatusBar
	_statusPanel1 as StatusBarPanel
	_timer as Timer

	[getter(Settings)]
	_settings = LoadSettings()

	[getter(DocumentOutline)]
	_documentOutline = BooExplorer.DocumentOutline()

	[getter(TaskList)]
	_taskList = BooExplorer.TaskList(self)

	[getter(OutputPane)]
	_outputPane = BooExplorer.OutputPane()

	[getter(InteractiveConsole)]
	_interactiveConsole = BooExplorer.InteractiveConsole(self)

	[getter(TextInterceptors)]
	_textInterceptors as (ITextInterceptor)

	_argv as (string)

	_menuItemClose as MenuItem
	_menuItemSave as MenuItem
	_menuItemSaveAs as MenuItem

	_parser = BooCompiler()

	_resourceManager = System.Resources.ResourceManager(MainForm)

	def constructor(argv as (string)):
		_argv = argv
		_dockPanel = DockPanel(Dock: DockStyle.Fill,
						ActiveAutoHideContent: null,
						TabIndex: 1,
						ActiveDocumentChanged: _dockPanel_ActiveDocumentChanged)

		_statusPanel1 = StatusBarPanel(AutoSize: StatusBarPanelAutoSize.Contents)

		_status = StatusBar(ShowPanels: true, TabIndex: 2)
		_status.Panels.Add(_statusPanel1)

		_parser.Parameters.Pipeline = Boo.Lang.Compiler.Pipelines.Parse()
		(_parser.Parameters.Pipeline[0] as duck).TabSize = 1

		SuspendLayout()

		self.Icon = _resourceManager.GetObject("_icon")
		self.Size = System.Drawing.Size(800, 600)
		self.Menu = CreateMainMenu()
		self.Text = "Boo Explorer"
		self.IsMdiContainer = true

		Controls.AddRange((
					_dockPanel,
					_status))
		ResumeLayout(false)

		LoadInterceptors()

		_timer = Timer(Tick: _timer_Tick, Interval: 50ms.TotalMilliseconds)
		_timer.Enabled = true

	private def GetSettingsFileName():
		return Path.Combine(GetApplicationDataFolder(), "settings.xml")

	private def SaveSettings():
		_settings.Save(GetSettingsFileName())

	private def LoadSettings():
		fname = GetSettingsFileName()
		if File.Exists(fname):
			return BooxSettings.Load(fname)
		return BooxSettings()

	private def CreateMainMenu():

		menu = MainMenu()
		file = MenuItem(Text: "&File", MergeOrder: 0)
		file.MenuItems.Add(MenuItem(Text: "&Open...",
									Click: _menuItemOpen_Click,
									Shortcut: Shortcut.CtrlO))
		file.MenuItems.Add(MenuItem(Text: "&New",
									Click: _menuItemNew_Click,
									Shortcut: Shortcut.CtrlN))

		file.MenuItems.Add(MenuItem("-"))

		file.MenuItems.Add(_menuItemSave = MenuItem(Text: "&Save",
									Enabled: false,
									Click: _menuItemSave_Click,
									Shortcut: Shortcut.CtrlS))
		file.MenuItems.Add(_menuItemSaveAs = MenuItem(Text: "S&ave as...",
									Enabled: false,
									Click: _menuItemSaveAs_Click))

		file.MenuItems.Add(_menuItemClose = MenuItem(Text: "&Close",
									Click: _menuItemClose_Click,
									Shortcut: Shortcut.CtrlW,
									Enabled: false))

		file.MenuItems.Add(MenuItem("-"))
		file.MenuItems.Add(MenuItem(Text: "E&xit",
									Shortcut: Shortcut.CtrlQ,
									Click: _menuItemExit_Click))

		tools = MenuItem(Text: "&Tools", MergeOrder: 2, MergeType: MenuMerge.MergeItems)
		tools.MenuItems.Add(MenuItem(Text: "&Options",
								Shortcut: Shortcut.CtrlO,
								Click: _menuItemOptions_Click,
								MergeOrder: int.MaxValue))

		view = MenuItem(Text: "&View", MergeOrder: 4)
		view.MenuItems.AddRange(
			(
				MenuItem(Text: "Document Outline",
						Click: _menuItemDocumentOutline_Click,
						Shortcut: Shortcut.CtrlShiftD),
				MenuItem(Text: "Task List",
						Click: _menuItemTaskList_Click,
						Shortcut: Shortcut.CtrlShiftT),
				MenuItem(Text: "Output",
						Click: _menuItemOutputPane_Click,
						Shortcut: Shortcut.CtrlShiftO),
				MenuItem(Text: "Prompt",
						Click: ShowPrompt,
						Shortcut: Shortcut.CtrlShiftP)
			))

		menu.MenuItems.AddRange((file, tools, view))
		return menu

	def _timer_Tick(sender, args as EventArgs):
		_timer.Enabled = false

		if File.Exists(GetDockStateXmlFileName()):
			LoadDockState()
			OpenDocuments(_argv)
		else:
			if len(_argv):
				OpenDocuments(_argv)
			else:
				NewDocument()
			ShowDocumentOutline()

	StatusText as string:
		set:
			_statusPanel1.Text = value

	def ParseString(fname as string, code as string):
		try:
			_parser.Parameters.Input.Add(StringInput(fname, code))
			return _parser.Run().CompileUnit
		ensure:
			_parser.Parameters.Input.Clear()

	private def LoadInterceptors():
		tempInterceptors = []

		if _settings.LoadPlugins:
			for file in Directory.GetFiles(MapPath("scripts"), "*.int"):
				interceptors = LoadInterceptorsFromFile(file)
				tempInterceptors = tempInterceptors + interceptors if interceptors

		_textInterceptors = array(ITextInterceptor, tempInterceptors)
		StatusText = "Loaded ${len(_textInterceptors)} TextInterceptor(s)"

	def MapPath(path as string):
		return Path.Combine(Path.GetDirectoryName(Application.ExecutablePath), path)

	def LoadInterceptorsFromFile(fileName as string):
		script = ScriptCompiler.CompileFile(fileName)
		if len(script.Errors):
			for error in script.Errors:
				print("Compiler error: ${error}")
			return null

		retTypes = script.GetTypes()
		return null unless retTypes
		return [cast(ITextInterceptor, retType()) for retType in retTypes if retType() isa ITextInterceptor]

	def Expand(fname as string, code as string):
		compiler = BooCompiler()
		compiler.Parameters.OutputWriter = StringWriter()
		compiler.Parameters.Pipeline = CompileToBoo()
		compiler.Parameters.Input.Add(StringInput(fname, code))

		result = compiler.Run()
		self.UpdateTaskList(result.Errors)

		NewDocument().TextContent = compiler.Parameters.OutputWriter.ToString()

	def ShowDocumentOutline():
		ShowContent(_documentOutline)

	private def ShowContent(content as DockContent):
		content.Show(_dockPanel)
		if DockState.Unknown == content.DockState:
			content.Pane.DockState = content.ShowHint

	def NewDocument():
		editor = BooEditor(self)
		editor.Show(_dockPanel)
		editor.TextArea.Focus()
		return editor

	def OpenDocuments([required] fnames):
		for fname in fnames:
			try:
				OpenDocument(fname)
			except x:
				print(x)

	def OpenDocument([required] filename as string):
		filename = Path.GetFullPath(filename)
		content = FindEditor(filename)
		if content is null:
			editor = CreateEditor(filename)
			editor.Show(_dockPanel)
			editor.TextArea.Focus()
			return editor
		else:
			content.Show(_dockPanel)
			content.TextArea.Focus()
			return content

	private def CreateEditor([required] fname as string):
		editor = BooEditor(self)
		editor.Open(fname)
		return editor

	def _dockPanel_ActiveDocumentChanged(sender, args as EventArgs):
		document = _dockPanel.ActiveDocument
		editor = document as BooEditor
		_documentOutline.ActiveDocument = editor
		_menuItemClose.Enabled = document is not null
		_menuItemSaveAs.Enabled = _menuItemSave.Enabled = document is not null

	def _menuItemSaveAs_Click(sender, args as EventArgs):
		cast(BooEditor, _dockPanel.ActiveDocument).SaveAs()

	def _menuItemSave_Click(sender, args as EventArgs):
		cast(BooEditor, _dockPanel.ActiveDocument).Save()

	def _menuItemExit_Click(sender, args as EventArgs):
		self.Close()

	def _menuItemClose_Click(sender, args as EventArgs):
		_dockPanel.ActiveDocument.Close()

	def _menuItemDocumentOutline_Click(sender, args as EventArgs):
		ShowDocumentOutline()

	def _menuItemTaskList_Click(sender, args as EventArgs):
		ShowTaskList()

	def UpdateTaskList(errors as CompilerErrorCollection):
		_taskList.Update(errors)
		ShowTaskList() if len(errors)

	def ShowTaskList():
		ShowContent(_taskList)

	def ShowOutputPane():
		ShowContent(_outputPane)

	def ShowPrompt():
		ShowContent(_interactiveConsole)

	def _menuItemOutputPane_Click(sender, args as EventArgs):
		ShowOutputPane()

	def _menuItemOptions_Click():
		dlg = Form(Text: "Options")
		dlg.Controls.Add(PropertyGrid(
							Dock: DockStyle.Fill,
							SelectedObject: _settings,
							Font: Font,
							PropertySort: PropertySort.Alphabetical))
		dlg.ShowDialog()
		SaveSettings()

	def _menuItemOpen_Click(sender, args as EventArgs):
		dlg = OpenFileDialog(
					Filter: "boo files (*.boo)|*.boo|All files (*.*)|*.*",
					Multiselect: true)
		if DialogResult.OK == dlg.ShowDialog(self):
			for fname in dlg.FileNames:
				OpenDocument(fname)

	def _menuItemNew_Click(sender, args as EventArgs):
		NewDocument()

	def GetApplicationDataFolder():
		folder = Application.UserAppDataPath
		Directory.CreateDirectory(folder) unless Directory.Exists(folder)
		return folder

	def GetDockStateXmlFileName():
		return Path.Combine(GetApplicationDataFolder(), "dockstate.xml")

	def SaveDockState():
		_dockPanel.SaveAsXml(GetDockStateXmlFileName())

	def LoadDockState():
		_dockPanel.LoadFromXml(GetDockStateXmlFileName(), OnDeserializeDockContent)

	def OnDeserializeDockContent(persistString as string) as DockContent:
		type, content = /\|/.Split(persistString)
		print("type: ${type}, content: ${content}")
		if "DocumentOutline" == type:
			return _documentOutline
		if "InteractiveConsole" == type:
			return _interactiveConsole
		if "TaskList" == type:
			return _taskList
		if "OutputPane" == type:
			return _outputPane
		if "BooEditor" == type:
			editor = BooEditor(self)
			editor.Open(content) if File.Exists(content)
			return editor
		raise ArgumentException("Invalid persistence string: ${persistString}")

	override protected def OnClosed(args as EventArgs):
		SaveDockState()
		super(args)

	override protected def OnClosing(args as CancelEventArgs):
		super(args)
		if not args.Cancel:
			dirtyDocuments = [
							editor.GetSafeFileName()
							for document in _dockPanel.Documents
							if (editor=(document as BooEditor)) and editor.IsDirty
							]
			return unless len(dirtyDocuments)

			args.Cancel = (
							DialogResult.Yes !=
							MessageBox.Show("The following files were modified:\n\n\t" +
											join(dirtyDocuments, "\n\t") +
											"\n\nAre you sure you want to leave and lose all your changes?",
											"Boo Explorer",
											MessageBoxButtons.YesNo))

	def FindEditor(fname as string):
		for document in _dockPanel.Documents:
			editor = document as BooEditor
			if editor and editor.FileName == fname:
				return editor
		return null


code gardening (clean warning)

code gardening (clean warning)

#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.Compiler.Tests

import System
import System.IO
import System.Reflection
import Boo.Lang.Compiler
import Boo.Lang.Compiler.IO
import Boo.Lang.Compiler.Pipelines
import NUnit.Framework

class CaptureContext(ICompilerStep):

	[getter(CompilerContext)]
	_context as CompilerContext

	def Initialize(context as CompilerContext):
		_context = context

	def Run():
		pass

	def Dispose():
		pass

class AssertCurrentContext(Boo.Lang.Compiler.Steps.AbstractCompilerStep):
	override def Run():
		Assert.IsNotNull(Context)
		Assert.AreSame(Context, CompilerContext.Current)

[TestFixture]
class CompilerTestFixture:

	_compiler as Boo.Lang.Compiler.BooCompiler

	[SetUp]
	def SetUp():
		_compiler = Boo.Lang.Compiler.BooCompiler()

	[Test]
	def CurrentContext():
		_compiler.Parameters.Pipeline = NewPipeline(AssertCurrentContext())
		errors = _compiler.Run().Errors
		Assert.AreEqual(0, len(errors), errors.ToString(true))

	[Test]
	def DefaultDebugSetting():
		Assert.AreEqual(true, _compiler.Parameters.Debug, "Debug must be true by default")

	[Test]
	def DefaultPipeline():
		Assert.IsNull(_compiler.Parameters.Pipeline, "Pipeline must be null!")

	[Test]
	def RunWithoutPipeline():
		try:
			_compiler.Run()
			Assert.Fail()
		except as InvalidOperationException:
			pass

	[Test]
	def RunWithPipeline():
		capture = CaptureContext()

		_compiler.Parameters.Pipeline = NewPipeline(capture)

		context = _compiler.Run()
		Assert.IsNotNull(context)
		Assert.AreSame(context, capture.CompilerContext)

	def NewPipeline(*steps as (ICompilerStep)):
		pipeline = CompilerPipeline()
		for step in steps: pipeline.Add(step)
		return pipeline

	[Test]
	def DefaultOutputType():
		Assert.AreEqual(CompilerOutputType.Auto, _compiler.Parameters.OutputType,
				"Default compiler output type must be CompilerOutputType.Auto.")

	[Test]
	def DefaultAssemblyReferences():
		parameters = _compiler.Parameters
		references = parameters.References
		Assert.AreEqual(5, references.Count)
		Assert.IsTrue(references.Contains(typeof(string).Assembly), "(ms)corlib.dll must be referenced by default!")
		Assert.IsTrue(references.Contains(parameters.LoadAssembly("System")), "System.dll must be referenced by default!")
		Assert.IsTrue(references.Contains(parameters.LoadAssembly("System.Core")), "System.Core.dll must be referenced by default!")
		Assert.IsTrue(references.Contains(typeof(Boo.Lang.Builtins).Assembly), "Boo.dll must referenced by default!")
		Assert.IsTrue(references.Contains(typeof(Boo.Lang.Extensions.PrintMacro).Assembly), "Boo.Lang.Extensions.dll must be referenced by default!")

	[Test]
	def DefaultGenerateInMemory():
		assert _compiler.Parameters.GenerateInMemory

	[Test]
	def CompileOnlyToFile():
		_compiler.Parameters.GenerateInMemory = false
		_compiler.Parameters.Pipeline = Boo.Lang.Compiler.Pipelines.CompileToFile()
		_compiler.Parameters.Input.Add(StringInput("foo", "print 'foo'"))
		_compiler.Parameters.OutputAssembly = fname = Path.GetTempFileName()

		context = _compiler.Run()
		Assert.AreEqual(0, len(context.Errors), context.Errors.ToString(true))
		assert File.Exists(fname)
		assert context.GeneratedAssembly is null

		asm = System.Reflection.Assembly.LoadFrom(fname)
		assert asm is not null
		assert asm.EntryPoint is not null
		types = asm.GetTypes()
		Assert.AreEqual(1, len(types))
		writer = System.IO.StringWriter()
		saved = Console.Out
		Console.SetOut(writer)
		try:
			asm.EntryPoint.Invoke(null, (array(string, 0), ))
		ensure:
			Console.SetOut(saved)
		Assert.AreEqual("foo", writer.ToString().Trim())

	[Test]
	def VerboseCompile():
		_compiler.Parameters.TraceLevel = System.Diagnostics.TraceLevel.Verbose;
		CompileOnlyToFile()

#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.Compiler.Tests

import System
import System.IO
import System.Reflection
import Boo.Lang.Compiler
import Boo.Lang.Compiler.IO
import Boo.Lang.Compiler.Pipelines
import NUnit.Framework

class CaptureContext(ICompilerStep):

	[getter(CompilerContext)]
	_context as CompilerContext

	def Initialize(context as CompilerContext):
		_context = context

	def Run():
		pass

	def Dispose():
		pass

class AssertCurrentContext(Boo.Lang.Compiler.Steps.AbstractCompilerStep):
	override def Run():
		Assert.IsNotNull(Context)
		Assert.AreSame(Context, CompilerContext.Current)

[TestFixture]
class CompilerTestFixture:

	_compiler as Boo.Lang.Compiler.BooCompiler

	[SetUp]
	def SetUp():
		_compiler = Boo.Lang.Compiler.BooCompiler()

	[Test]
	def CurrentContext():
		_compiler.Parameters.Pipeline = NewPipeline(AssertCurrentContext())
		errors = _compiler.Run().Errors
		Assert.AreEqual(0, len(errors), errors.ToString(true))

	[Test]
	def DefaultDebugSetting():
		Assert.AreEqual(true, _compiler.Parameters.Debug, "Debug must be true by default")

	[Test]
	def DefaultPipeline():
		Assert.IsNull(_compiler.Parameters.Pipeline, "Pipeline must be null!")

	[Test]
	def RunWithoutPipeline():
		try:
			_compiler.Run()
			Assert.Fail()
		except InvalidOperationException:
			pass

	[Test]
	def RunWithPipeline():
		capture = CaptureContext()

		_compiler.Parameters.Pipeline = NewPipeline(capture)

		context = _compiler.Run()
		Assert.IsNotNull(context)
		Assert.AreSame(context, capture.CompilerContext)

	def NewPipeline(*steps as (ICompilerStep)):
		pipeline = CompilerPipeline()
		for step in steps: pipeline.Add(step)
		return pipeline

	[Test]
	def DefaultOutputType():
		Assert.AreEqual(CompilerOutputType.Auto, _compiler.Parameters.OutputType,
				"Default compiler output type must be CompilerOutputType.Auto.")

	[Test]
	def DefaultAssemblyReferences():
		parameters = _compiler.Parameters
		references = parameters.References
		Assert.AreEqual(5, references.Count)
		Assert.IsTrue(references.Contains(typeof(string).Assembly), "(ms)corlib.dll must be referenced by default!")
		Assert.IsTrue(references.Contains(parameters.LoadAssembly("System")), "System.dll must be referenced by default!")
		Assert.IsTrue(references.Contains(parameters.LoadAssembly("System.Core")), "System.Core.dll must be referenced by default!")
		Assert.IsTrue(references.Contains(typeof(Boo.Lang.Builtins).Assembly), "Boo.dll must referenced by default!")
		Assert.IsTrue(references.Contains(typeof(Boo.Lang.Extensions.PrintMacro).Assembly), "Boo.Lang.Extensions.dll must be referenced by default!")

	[Test]
	def DefaultGenerateInMemory():
		assert _compiler.Parameters.GenerateInMemory

	[Test]
	def CompileOnlyToFile():
		_compiler.Parameters.GenerateInMemory = false
		_compiler.Parameters.Pipeline = Boo.Lang.Compiler.Pipelines.CompileToFile()
		_compiler.Parameters.Input.Add(StringInput("foo", "print 'foo'"))
		_compiler.Parameters.OutputAssembly = fname = Path.GetTempFileName()

		context = _compiler.Run()
		Assert.AreEqual(0, len(context.Errors), context.Errors.ToString(true))
		assert File.Exists(fname)
		assert context.GeneratedAssembly is null

		asm = System.Reflection.Assembly.LoadFrom(fname)
		assert asm is not null
		assert asm.EntryPoint is not null
		types = asm.GetTypes()
		Assert.AreEqual(1, len(types))
		writer = System.IO.StringWriter()
		saved = Console.Out
		Console.SetOut(writer)
		try:
			asm.EntryPoint.Invoke(null, (array(string, 0), ))
		ensure:
			Console.SetOut(saved)
		Assert.AreEqual("foo", writer.ToString().Trim())

	[Test]
	def VerboseCompile():
		_compiler.Parameters.TraceLevel = System.Diagnostics.TraceLevel.Verbose;
		CompileOnlyToFile()


prefer linq over loops

prefer linq over loops

namespace UnityScript.Steps

import UnityScript.Core

import Boo.Lang.Compiler.Ast
import Boo.Lang.Compiler.Steps
import System.Linq

class ApplySemantics(AbstractVisitorCompilerStep):

	override def Run():
		Visit(CompileUnit)

	class DeclareGlobalVariables(DepthFirstTransformer):

		_class as ClassDefinition

		def constructor(cd as ClassDefinition):
			_class = cd

		override def EnterBlock(node as Block):
			if node.ParentNode isa Method: return true
			return false

		override def OnDeclarationStatement(node as DeclarationStatement):

			return if node.ContainsAnnotation('PrivateScope')

			field = [|
				public $(node.Declaration.Name) as $(node.Declaration.Type) = $(node.Initializer)
			|]
			field.LexicalInfo = node.LexicalInfo
			_class.Members.Add(field)

			RemoveCurrentNode()

	UnityScriptParameters as UnityScript.UnityScriptCompilerParameters:
		get: return _context.Parameters

	override def OnModule(module as Module):

		SetUpDefaultImports(module)
		if ModuleContainsOnlyTypeDefinitions(module):
			return

		script = FindOrCreateScriptClass(module)
		MakeItPartial(script)
		MoveMembers(module, script)
		SetUpMainMethod(module, script)
		MoveAttributes(module, script)
		module.Members.Add(script)
		SetScriptClass(Context, script)

	def ModuleContainsOnlyTypeDefinitions(module as Module):
		return not module.Members.IsEmpty and module.Members.All({ m | m isa TypeDefinition }) and module.Globals.IsEmpty and module.Attributes.IsEmpty

	def SetUpMainMethod(module as Module, script as TypeDefinition):
		TransformGlobalVariablesIntoFields(module, script)
		MoveGlobalStatementsToMainMethodOf(script, module)

	def MoveGlobalStatementsToMainMethodOf(script as TypeDefinition, module as Module):

		main = ExistingMainMethodOn(script)

		if main is null:
			main = NewMainMethodFor(module)
			script.Members.Add(main)
		else:
			Warnings.Add(UnityScriptWarnings.ScriptMainMethodIsImplicitlyDefined(main.LexicalInfo, main.Name))

		main.Body.Statements.AddRange(module.Globals.Statements)
		module.Globals.Statements.Clear()

	def TransformGlobalVariablesIntoFields(module as Module, script as TypeDefinition):
		if not UnityScriptParameters.GlobalVariablesBecomeFields:
			return
		module.Globals.Accept(DeclareGlobalVariables(script))

	def ExistingMainMethodOn(typeDef as TypeDefinition):
		return typeDef.Members.OfType[of Method]().FirstOrDefault(IsMainMethod)

	def IsMainMethod(m as Method):
		return (
			m is not null
			and m.Name == ScriptMainMethod
			and len(m.Parameters) == 0)

	def MakeItPartial(global as ClassDefinition):
		global.Modifiers |= TypeMemberModifiers.Partial

	def SetUpDefaultImports(module as Module):
		for ns as string in self.UnityScriptParameters.Imports:
			module.Imports.Add(Import(ns))

	def MoveAttributes(fromType as TypeDefinition, toType as TypeDefinition):
		toType.Attributes.AddRange(fromType.Attributes)
		fromType.Attributes.Clear()

	def MoveMembers(fromType as TypeDefinition, toType as TypeDefinition):
		moved = []
		for member in fromType.Members:
			if not member isa TypeDefinition:
				movedMember = MovedMember(toType, member)
				toType.Members.Add(movedMember)
				Visit(movedMember)
				moved.Add(member)
			else:
				Visit(member)

		for member in moved:
			fromType.Members.Remove(member)

	def MovedMember(toType as TypeDefinition, member as TypeMember):
		if not toType.ContainsAnnotation("UserDefined"): return member
		if not IsConstructorMethod(toType, member): return member
		return ConstructorFromMethod(member)

	def IsConstructorMethod(toType as TypeDefinition, member as TypeMember):
		if member.NodeType != NodeType.Method: return false
		return toType.Name == member.Name

	def ConstructorFromMethod(method as Method):
		return Constructor(
			Parameters: method.Parameters,
			Body: method.Body,
			Attributes: method.Attributes,
			Modifiers: method.Modifiers,
			LexicalInfo: method.LexicalInfo,
			EndSourceLocation: method.EndSourceLocation)

	def FindOrCreateScriptClass(module as Module):
		for existing in module.Members.OfType of ClassDefinition():
			if existing.Name == module.Name:
				module.Members.Remove(existing)
				if existing.IsPartial: AddScriptBaseType(existing)
				existing.Annotate("UserDefined")
				return existing

		klass = ClassDefinition(module.LexicalInfo, Name: module.Name, EndSourceLocation: module.EndSourceLocation, IsSynthetic: true)
		AddScriptBaseType(klass)
		return klass

	def AddScriptBaseType(klass as ClassDefinition):
		klass.BaseTypes.Add(CodeBuilder.CreateTypeReference(UnityScriptParameters.ScriptBaseType))

	ScriptMainMethod:
		get: return self.UnityScriptParameters.ScriptMainMethod

	def NewMainMethodFor(module as Module):
		return Method(
			LexicalInfo: (Copy(module.Globals.Statements[0].LexicalInfo) if not module.Globals.IsEmpty else module.LexicalInfo),
			Name: ScriptMainMethod,
			Modifiers: TypeMemberModifiers.Public | TypeMemberModifiers.Virtual,
			EndSourceLocation: module.EndSourceLocation)

def Copy(li as LexicalInfo):
	return LexicalInfo(li.FileName, li.Line, li.Column)

namespace UnityScript.Steps

import UnityScript.Core

import Boo.Lang.Compiler.Ast
import Boo.Lang.Compiler.Steps
import System.Linq

class ApplySemantics(AbstractVisitorCompilerStep):

	override def Run():
		Visit(CompileUnit)

	class DeclareGlobalVariables(DepthFirstTransformer):

		_class as ClassDefinition

		def constructor(cd as ClassDefinition):
			_class = cd

		override def EnterBlock(node as Block):
			if node.ParentNode isa Method: return true
			return false

		override def OnDeclarationStatement(node as DeclarationStatement):

			return if node.ContainsAnnotation('PrivateScope')

			field = [|
				public $(node.Declaration.Name) as $(node.Declaration.Type) = $(node.Initializer)
			|]
			field.LexicalInfo = node.LexicalInfo
			_class.Members.Add(field)

			RemoveCurrentNode()

	UnityScriptParameters as UnityScript.UnityScriptCompilerParameters:
		get: return _context.Parameters

	override def OnModule(module as Module):

		SetUpDefaultImports(module)
		if ModuleContainsOnlyTypeDefinitions(module):
			return

		script = FindOrCreateScriptClass(module)
		MakeItPartial(script)
		MoveMembers(module, script)
		SetUpMainMethod(module, script)
		MoveAttributes(module, script)
		module.Members.Add(script)
		SetScriptClass(Context, script)

	def ModuleContainsOnlyTypeDefinitions(module as Module):
		return not module.Members.IsEmpty and module.Members.All({ m | m isa TypeDefinition }) and module.Globals.IsEmpty and module.Attributes.IsEmpty

	def SetUpMainMethod(module as Module, script as TypeDefinition):
		TransformGlobalVariablesIntoFields(module, script)
		MoveGlobalStatementsToMainMethodOf(script, module)

	def MoveGlobalStatementsToMainMethodOf(script as TypeDefinition, module as Module):

		main = ExistingMainMethodOn(script)

		if main is null:
			main = NewMainMethodFor(module)
			script.Members.Add(main)
		else:
			Warnings.Add(UnityScriptWarnings.ScriptMainMethodIsImplicitlyDefined(main.LexicalInfo, main.Name))

		main.Body.Statements.AddRange(module.Globals.Statements)
		module.Globals.Statements.Clear()

	def TransformGlobalVariablesIntoFields(module as Module, script as TypeDefinition):
		if not UnityScriptParameters.GlobalVariablesBecomeFields:
			return
		module.Globals.Accept(DeclareGlobalVariables(script))

	def ExistingMainMethodOn(typeDef as TypeDefinition):
		for member in typeDef.Members:
			method = member as Method
			isMainMethod = method is not null \
				and method.Name == ScriptMainMethod \
				and len(method.Parameters) == 0
			return method if isMainMethod

	def MakeItPartial(global as ClassDefinition):
		global.Modifiers |= TypeMemberModifiers.Partial

	def SetUpDefaultImports(module as Module):
		for ns as string in self.UnityScriptParameters.Imports:
			module.Imports.Add(Import(ns))

	def MoveAttributes(fromType as TypeDefinition, toType as TypeDefinition):
		toType.Attributes.AddRange(fromType.Attributes)
		fromType.Attributes.Clear()

	def MoveMembers(fromType as TypeDefinition, toType as TypeDefinition):
		moved = []
		for member in fromType.Members:
			if not member isa TypeDefinition:
				movedMember = MovedMember(toType, member)
				toType.Members.Add(movedMember)
				Visit(movedMember)
				moved.Add(member)
			else:
				Visit(member)

		for member in moved:
			fromType.Members.Remove(member)

	def MovedMember(toType as TypeDefinition, member as TypeMember):
		if not toType.ContainsAnnotation("UserDefined"): return member
		if not IsConstructorMethod(toType, member): return member
		return ConstructorFromMethod(member)

	def IsConstructorMethod(toType as TypeDefinition, member as TypeMember):
		if member.NodeType != NodeType.Method: return false
		return toType.Name == member.Name

	def ConstructorFromMethod(method as Method):
		return Constructor(
			Parameters: method.Parameters,
			Body: method.Body,
			Attributes: method.Attributes,
			Modifiers: method.Modifiers,
			LexicalInfo: method.LexicalInfo,
			EndSourceLocation: method.EndSourceLocation)

	def FindOrCreateScriptClass(module as Module):
		for existing in module.Members.OfType of ClassDefinition():
			if existing.Name == module.Name:
				module.Members.Remove(existing)
				if existing.IsPartial: AddScriptBaseType(existing)
				existing.Annotate("UserDefined")
				return existing

		klass = ClassDefinition(module.LexicalInfo, Name: module.Name, EndSourceLocation: module.EndSourceLocation, IsSynthetic: true)
		AddScriptBaseType(klass)
		return klass

	def AddScriptBaseType(klass as ClassDefinition):
		klass.BaseTypes.Add(CodeBuilder.CreateTypeReference(UnityScriptParameters.ScriptBaseType))

	ScriptMainMethod:
		get: return self.UnityScriptParameters.ScriptMainMethod

	def NewMainMethodFor(module as Module):
		return Method(
			LexicalInfo: (Copy(module.Globals.Statements[0].LexicalInfo) if not module.Globals.IsEmpty else module.LexicalInfo),
			Name: ScriptMainMethod,
			Modifiers: TypeMemberModifiers.Public | TypeMemberModifiers.Virtual,
			EndSourceLocation: module.EndSourceLocation)

def Copy(li as LexicalInfo):
	return LexicalInfo(li.FileName, li.Line, li.Column)


BodyRegion for delegates

BodyRegion for delegates

namespace Boo.MonoDevelop.ProjectModel

import Boo.Lang.Compiler.Ast
import MonoDevelop.Projects.Dom as MD
import Boo.Lang.PatternMatching

class DomConversionVisitor(DepthFirstVisitor):

	_result as MD.CompilationUnit
	_currentType as MD.DomType
	_namespace as string

	def constructor(result as MD.CompilationUnit):
		_result = result

	override def OnModule(node as Module):
		_namespace = null
		Visit(node.Namespace)
		Visit(node.Members)

	override def OnNamespaceDeclaration(node as NamespaceDeclaration):
		_namespace = node.Name
		region = BodyRegionOf(node.ParentNode)
		domUsing = MD.DomUsing(IsFromNamespace: true, Region: region)
		domUsing.Add(_namespace)
		_result.Add(domUsing)

	override def OnImport(node as Import):
		region = BodyRegionOf(node)
		domUsing = MD.DomUsing(Region: region)
		domUsing.Add(node.Namespace)
		_result.Add(domUsing)

	override def OnClassDefinition(node as ClassDefinition):
		OnTypeDefinition(node, MD.ClassType.Class)

	override def OnInterfaceDefinition(node as InterfaceDefinition):
		OnTypeDefinition(node, MD.ClassType.Interface)

	override def OnStructDefinition(node as StructDefinition):
		OnTypeDefinition(node, MD.ClassType.Struct)

	override def OnEnumDefinition(node as EnumDefinition):
		OnTypeDefinition(node, MD.ClassType.Enum)

	def OnTypeDefinition(node as TypeDefinition, classType as MD.ClassType):
		converted = MD.DomType(
						Name: node.Name,
						ClassType: classType,
						Location: LocationOf(node),
						BodyRegion: BodyRegionOf(node),
						DeclaringType: _currentType,
						Modifiers: ModifiersFrom(node))

		WithCurrentType converted:
			Visit(node.Members)

		AddType(converted)

	override def OnCallableDefinition(node as CallableDefinition):
		parameters = System.Collections.Generic.List[of MD.IParameter]()
		for p in node.Parameters: parameters.Add(ParameterFrom(null, p))

		converted = MD.DomType.CreateDelegate(_result, node.Name, LocationOf(node), ReturnTypeFrom(node.ReturnType), parameters)
		converted.Modifiers = ModifiersFrom(node)
		converted.DeclaringType = _currentType
		converted.BodyRegion = BodyRegionOf(node)

		for p in parameters: p.DeclaringMember = converted

		AddType(converted)

	override def OnField(node as Field):
		if _currentType is null: return

		_currentType.Add(MD.DomField(
							Name: node.Name,
							ReturnType: ParameterTypeFrom(node.Type),
							Location: LocationOf(node),
							BodyRegion: BodyRegionOf(node),
							DeclaringType: _currentType,
							Modifiers: ModifiersFrom(node)))

	override def OnProperty(node as Property):
		if _currentType is null: return

		converted = MD.DomProperty(
							Name: node.Name,
							ReturnType: ParameterTypeFrom(node.Type),
							Location: LocationOf(node),
							BodyRegion: BodyRegionOf(node),
							DeclaringType: _currentType,
							Modifiers: ModifiersFrom(node))
		if node.Getter is not null:
			converted.PropertyModifier |= MD.PropertyModifier.HasGet
			converted.GetRegion = BodyRegionOf(node.Getter)
		if node.Setter is not null:
			converted.PropertyModifier |= MD.PropertyModifier.HasSet
			converted.SetRegion = BodyRegionOf(node.Setter)

		_currentType.Add(converted)

	override def OnEnumMember(node as EnumMember):
		if _currentType is null: return

		_currentType.Add(MD.DomField(
							Name: node.Name,
							ReturnType: MD.DomReturnType(_currentType),
							Location: LocationOf(node),
							DeclaringType: _currentType,
							Modifiers: MD.Modifiers.Public | MD.Modifiers.Static | MD.Modifiers.Final))

	override def OnConstructor(node as Constructor):
		OnMethod(node, MD.MethodModifier.IsConstructor)

	override def OnDestructor(node as Destructor):
		OnMethod(node, MD.MethodModifier.IsFinalizer)

	override def OnMethod(node as Method):
		OnMethod(node, MD.MethodModifier.None)

	def OnMethod(node as Method, methodModifier as MD.MethodModifier):
		if _currentType is null: return

		converted = MD.DomMethod(
							Name: node.Name,
							Location: LocationOf(node),
							BodyRegion: BodyRegionOf(node),
							DeclaringType: _currentType,
							ReturnType: (MethodReturnTypeFrom(node) if IsRegularMethod(methodModifier) else null),
							Modifiers: ModifiersFrom(node),
							MethodModifier: methodModifier)

		for parameter in node.Parameters:
			converted.Add(ParameterFrom(converted, parameter))

		_currentType.Add(converted)

	def IsRegularMethod(modifier as MD.MethodModifier):
		match modifier:
			case MD.MethodModifier.IsConstructor | MD.MethodModifier.IsFinalizer:
				return false
			otherwise:
				return true

	def ModifiersFrom(node as TypeMember):
		modifiers = MD.Modifiers.None
		modifiers |= MD.Modifiers.Public if node.IsPublic
		modifiers |= MD.Modifiers.Private if node.IsPrivate
		modifiers |= MD.Modifiers.Protected if node.IsProtected
		modifiers |= MD.Modifiers.Internal if node.IsInternal
		modifiers |= MD.Modifiers.Static if node.IsStatic
		modifiers |= MD.Modifiers.Virtual if node.IsVirtual
		modifiers |= MD.Modifiers.Abstract if node.IsAbstract
		modifiers |= MD.Modifiers.Override if node.IsOverride
		modifiers |= MD.Modifiers.Final if node.IsFinal
		return modifiers

	def ParameterFrom(declaringMember as MD.IMember, parameter as ParameterDeclaration):
		return MD.DomParameter(
					DeclaringMember: declaringMember,
					Name: parameter.Name,
					ReturnType: ParameterTypeFrom(parameter.Type),
					Location: LocationOf(parameter))

	virtual def MethodReturnTypeFrom(method as Method):
		if method.ReturnType is not null:
			return ReturnTypeFrom(method.ReturnType)

		match ReturnTypeDetector().Detect(method):
			case ReturnTypeDetector.Result.Yields:
				return MD.DomReturnType("System.Collections.IEnumerator")
			case ReturnTypeDetector.Result.Returns:
				return MD.DomReturnType("object")
			otherwise:
				return MD.DomReturnType("void")

	class ReturnTypeDetector(DepthFirstVisitor):
		enum Result:
			Returns
			Yields
			None

		_result = Result.None

		def Detect(node as Method):
			VisitAllowingCancellation(node)
			return _result

		override def OnBlockExpression(node as BlockExpression):
			pass // skip over closures

		override def OnReturnStatement(node as ReturnStatement):
			if node.Expression is null: return
			_result = Result.Returns
			Cancel()

		override def OnYieldStatement(node as YieldStatement):
			_result = Result.Yields
			Cancel()

	virtual def ParameterTypeFrom(typeRef as TypeReference):
		if typeRef is null: return MD.DomReturnType("object")
		return ReturnTypeFrom(typeRef)

	virtual def ReturnTypeFrom(typeRef as TypeReference) as MD.DomReturnType:
		match typeRef:
			case SimpleTypeReference(Name: name):
				return MD.DomReturnType(name)
			case ArrayTypeReference(ElementType: elementType):
				type = ReturnTypeFrom(elementType)
				type.ArrayDimensions = 1
				type.SetDimension(0, 1)
				return type
			otherwise:
				return MD.DomReturnType("void")

	def AddType(type as MD.DomType):
		if _currentType is not null:
			_currentType.Add(type)
		else:
			type.Namespace = _namespace
			_result.Add(type)

	def WithCurrentType(type as MD.DomType, block as callable()):
		saved = _currentType
		_currentType = type
		try:
			block()
		ensure:
			_currentType = saved

	def BodyRegionOf(node as Node):
		return MD.DomRegion(DomLocationFrom(node.LexicalInfo), DomLocationFrom(node.EndSourceLocation))

	def LocationOf(node as Node):
		location = node.LexicalInfo
		return DomLocationFrom(location)

	def DomLocationFrom(location as SourceLocation):
		return MD.DomLocation(location.Line, location.Column)

namespace Boo.MonoDevelop.ProjectModel

import Boo.Lang.Compiler.Ast
import MonoDevelop.Projects.Dom as MD
import Boo.Lang.PatternMatching

class DomConversionVisitor(DepthFirstVisitor):

	_result as MD.CompilationUnit
	_currentType as MD.DomType
	_namespace as string

	def constructor(result as MD.CompilationUnit):
		_result = result

	override def OnModule(node as Module):
		_namespace = null
		Visit(node.Namespace)
		Visit(node.Members)

	override def OnNamespaceDeclaration(node as NamespaceDeclaration):
		_namespace = node.Name
		region = BodyRegionOf(node.ParentNode)
		domUsing = MD.DomUsing(IsFromNamespace: true, Region: region)
		domUsing.Add(_namespace)
		_result.Add(domUsing)

	override def OnImport(node as Import):
		region = BodyRegionOf(node)
		domUsing = MD.DomUsing(Region: region)
		domUsing.Add(node.Namespace)
		_result.Add(domUsing)

	override def OnClassDefinition(node as ClassDefinition):
		OnTypeDefinition(node, MD.ClassType.Class)

	override def OnInterfaceDefinition(node as InterfaceDefinition):
		OnTypeDefinition(node, MD.ClassType.Interface)

	override def OnStructDefinition(node as StructDefinition):
		OnTypeDefinition(node, MD.ClassType.Struct)

	override def OnEnumDefinition(node as EnumDefinition):
		OnTypeDefinition(node, MD.ClassType.Enum)

	def OnTypeDefinition(node as TypeDefinition, classType as MD.ClassType):
		converted = MD.DomType(
						Name: node.Name,
						ClassType: classType,
						Location: LocationOf(node),
						BodyRegion: BodyRegionOf(node),
						DeclaringType: _currentType,
						Modifiers: ModifiersFrom(node))

		WithCurrentType converted:
			Visit(node.Members)

		AddType(converted)

	override def OnCallableDefinition(node as CallableDefinition):
		parameters = System.Collections.Generic.List[of MD.IParameter](ParameterFrom(null, p) for p in node.Parameters)
		converted = MD.DomType.CreateDelegate(_result, node.Name, LocationOf(node), ReturnTypeFrom(node.ReturnType), parameters)
		converted.Modifiers = ModifiersFrom(node)
		converted.DeclaringType = _currentType
		for p in parameters: p.DeclaringMember = converted
		AddType(converted)

	override def OnField(node as Field):
		if _currentType is null: return

		_currentType.Add(MD.DomField(
							Name: node.Name,
							ReturnType: ParameterTypeFrom(node.Type),
							Location: LocationOf(node),
							BodyRegion: BodyRegionOf(node),
							DeclaringType: _currentType,
							Modifiers: ModifiersFrom(node)))

	override def OnProperty(node as Property):
		if _currentType is null: return

		converted = MD.DomProperty(
							Name: node.Name,
							ReturnType: ParameterTypeFrom(node.Type),
							Location: LocationOf(node),
							BodyRegion: BodyRegionOf(node),
							DeclaringType: _currentType,
							Modifiers: ModifiersFrom(node))
		if node.Getter is not null:
			converted.PropertyModifier |= MD.PropertyModifier.HasGet
			converted.GetRegion = BodyRegionOf(node.Getter)
		if node.Setter is not null:
			converted.PropertyModifier |= MD.PropertyModifier.HasSet
			converted.SetRegion = BodyRegionOf(node.Setter)

		_currentType.Add(converted)

	override def OnEnumMember(node as EnumMember):
		if _currentType is null: return

		_currentType.Add(MD.DomField(
							Name: node.Name,
							ReturnType: MD.DomReturnType(_currentType),
							Location: LocationOf(node),
							DeclaringType: _currentType,
							Modifiers: MD.Modifiers.Public | MD.Modifiers.Static | MD.Modifiers.Final))

	override def OnConstructor(node as Constructor):
		OnMethod(node, MD.MethodModifier.IsConstructor)

	override def OnDestructor(node as Destructor):
		OnMethod(node, MD.MethodModifier.IsFinalizer)

	override def OnMethod(node as Method):
		OnMethod(node, MD.MethodModifier.None)

	def OnMethod(node as Method, methodModifier as MD.MethodModifier):
		if _currentType is null: return

		converted = MD.DomMethod(
							Name: node.Name,
							Location: LocationOf(node),
							BodyRegion: BodyRegionOf(node),
							DeclaringType: _currentType,
							ReturnType: (MethodReturnTypeFrom(node) if IsRegularMethod(methodModifier) else null),
							Modifiers: ModifiersFrom(node),
							MethodModifier: methodModifier)

		for parameter in node.Parameters:
			converted.Add(ParameterFrom(converted, parameter))

		_currentType.Add(converted)

	def IsRegularMethod(modifier as MD.MethodModifier):
		match modifier:
			case MD.MethodModifier.IsConstructor | MD.MethodModifier.IsFinalizer:
				return false
			otherwise:
				return true

	def ModifiersFrom(node as TypeMember):
		modifiers = MD.Modifiers.None
		modifiers |= MD.Modifiers.Public if node.IsPublic
		modifiers |= MD.Modifiers.Private if node.IsPrivate
		modifiers |= MD.Modifiers.Protected if node.IsProtected
		modifiers |= MD.Modifiers.Internal if node.IsInternal
		modifiers |= MD.Modifiers.Static if node.IsStatic
		modifiers |= MD.Modifiers.Virtual if node.IsVirtual
		modifiers |= MD.Modifiers.Abstract if node.IsAbstract
		modifiers |= MD.Modifiers.Override if node.IsOverride
		modifiers |= MD.Modifiers.Final if node.IsFinal
		return modifiers

	def ParameterFrom(declaringMember as MD.IMember, parameter as ParameterDeclaration):
		return MD.DomParameter(
					DeclaringMember: declaringMember,
					Name: parameter.Name,
					ReturnType: ParameterTypeFrom(parameter.Type),
					Location: LocationOf(parameter))

	virtual def MethodReturnTypeFrom(method as Method):
		if method.ReturnType is not null:
			return ReturnTypeFrom(method.ReturnType)

		match ReturnTypeDetector().Detect(method):
			case ReturnTypeDetector.Result.Yields:
				return MD.DomReturnType("System.Collections.IEnumerator")
			case ReturnTypeDetector.Result.Returns:
				return MD.DomReturnType("object")
			otherwise:
				return MD.DomReturnType("void")

	class ReturnTypeDetector(DepthFirstVisitor):
		enum Result:
			Returns
			Yields
			None

		_result = Result.None

		def Detect(node as Method):
			VisitAllowingCancellation(node)
			return _result

		override def OnBlockExpression(node as BlockExpression):
			pass // skip over closures

		override def OnReturnStatement(node as ReturnStatement):
			if node.Expression is null: return
			_result = Result.Returns
			Cancel()

		override def OnYieldStatement(node as YieldStatement):
			_result = Result.Yields
			Cancel()

	virtual def ParameterTypeFrom(typeRef as TypeReference):
		if typeRef is null: return MD.DomReturnType("object")
		return ReturnTypeFrom(typeRef)

	virtual def ReturnTypeFrom(typeRef as TypeReference) as MD.DomReturnType:
		match typeRef:
			case SimpleTypeReference(Name: name):
				return MD.DomReturnType(name)
			case ArrayTypeReference(ElementType: elementType):
				type = ReturnTypeFrom(elementType)
				type.ArrayDimensions = 1
				type.SetDimension(0, 1)
				return type
			otherwise:
				return MD.DomReturnType("void")

	def AddType(type as MD.DomType):
		if _currentType is not null:
			_currentType.Add(type)
		else:
			type.Namespace = _namespace
			_result.Add(type)

	def WithCurrentType(type as MD.DomType, block as callable()):
		saved = _currentType
		_currentType = type
		try:
			block()
		ensure:
			_currentType = saved

	def BodyRegionOf(node as Node):
		return MD.DomRegion(DomLocationFrom(node.LexicalInfo), DomLocationFrom(node.EndSourceLocation))

	def LocationOf(node as Node):
		location = node.LexicalInfo
		return DomLocationFrom(location)

	def DomLocationFrom(location as SourceLocation):
		return MD.DomLocation(location.Line, location.Column)


compiler can infer the parameter type now

"""
1st
finished
2nd
finished again
3rd
"""
import System

def foo(msg):
	print msg

def wait(result as IAsyncResult):
	result.AsyncWaitHandle.WaitOne()

wait(foo.BeginInvoke("1st", { result | print result.AsyncState }, "finished"))

wait(foo.BeginInvoke("2nd", { print "finished again" }, null))

wait(foo.BeginInvoke("3rd", null, null))

"""
1st
finished
2nd
finished again
3rd
"""
import System

def foo(msg):
	print msg

def wait(result as IAsyncResult):
	result.AsyncWaitHandle.WaitOne()

wait(foo.BeginInvoke("1st", { result as IAsyncResult | print result.AsyncState }, "finished"))

wait(foo.BeginInvoke("2nd", { print "finished again" }, null))

wait(foo.BeginInvoke("3rd", null, null))


Georges improvements

Georges improvements

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

#region license
// Copyright (c) 2003, 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

"""
This example shows how to use IQuackFu.QuackGet to provide
transparent access to xml elements.
"""

import System
import System.Xml from System.Xml
import System.Reflection

[DefaultMember("Item")]
class XmlObject(IQuackFu):

	_element as XmlElement

	Item([required] key):
		get:
			item = _element.Attributes.GetNamedItem(key)
			return item.InnerText if item

	def constructor(element as XmlElement):
		_element = element

	def constructor(text as string):
		doc = XmlDocument()
		doc.LoadXml(text)
		_element = doc.DocumentElement

	def QuackInvoke(name as string, args as (object)) as object:
		pass

	def QuackSet(name as string, value) as object:
		pass

	def QuackGet(name as string) as object:
		elements = _element.SelectNodes(name)
		if elements is not null:
			return XmlObject(elements[0]) if elements.Count == 1
			return XmlObject(e) for e in elements

	override def ToString():
		return _element.InnerText

xml = """
<Person>
	<FirstName>John</FirstName>
	<LastName>Cleese</LastName>
	<Phone place="home">1111-111-111</Phone>
	<Phone place="work">2222-222-222</Phone>
</Person>
"""

person as duck = XmlObject(xml)
print person.FirstName
print person.LastName
for phone as XmlObject in person.Phone:
	print phone['place'], phone

#region license
// Copyright (c) 2003, 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

"""
This example shows how to use IQuackFu.QuackGet to provide
transparent access to xml elements.
"""

import System
import System.Xml from System.Xml

class XmlObject(IQuackFu):

	_element as XmlElement

	def constructor(element as XmlElement):
		_element = element

	def constructor(text as string):
		doc = XmlDocument()
		doc.LoadXml(text)
		_element = doc.DocumentElement

	def QuackInvoke(name as string, args as (object)) as object:
		pass

	def QuackSet(name as string, value) as object:
		pass

	def QuackGet(name as string) as object:
		element = _element.SelectSingleNode(name)
		return XmlObject(element) if element is not null

	override def ToString():
		return _element.InnerText

xml = """
<Person>
	<FirstName>John</FirstName>
	<LastName>Cleese</LastName>
</Person>
"""

person as duck = XmlObject(xml)
print person.FirstName
print person.LastName


object inspector

object inspector

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

import System
import booish
import System.Windows.Forms
import System.Drawing
import WeifenLuo.WinFormsUI

class InteractiveConsole(DockContent):

	def constructor(mainForm as MainForm):

		self.Text = "Interactive Console"
		self.Controls.Add(console=PromptBox(Dock: DockStyle.Fill,
					Font: System.Drawing.Font("Lucida Console", 12)))

		console.Interpreter.SetValue("MainForm", mainForm)
		console.Interpreter.SetValue("inspect", inspect)

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

	override def GetPersistString():
		return "InteractiveConsole|"

class PromptBox(TextBox):

	static Enter = chr(13)

	enum InputState:
		SingleLine = 0
		Block = 1

	_state = InputState.SingleLine

	_block = System.IO.StringWriter()

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

	def constructor():
		self.Multiline = true
		self.AcceptsTab = true
		self.ScrollBars = ScrollBars.Vertical
		_interpreter.References.Add(typeof(TextBox).Assembly)
		_interpreter.References.Add(typeof(Font).Assembly)

		prompt()

	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:
			_interpreter.LoopEval(code)

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

	override def OnKeyPress(args as KeyPressEventArgs):
		if Enter == args.KeyChar:
			try:
				(SingleLineInputState, BlockInputState)[_state]()
			except x:
				print(x)
			prompt()
			args.Handled = true
		super(args)

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

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

	static def chr(value as int):
		return cast(IConvertible, value).ToChar(null)

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

import System
import booish
import System.Windows.Forms
import System.Drawing
import WeifenLuo.WinFormsUI

class InteractiveConsole(DockContent):

	def constructor(mainForm as MainForm):

		self.Text = "Interactive Console"
		self.Controls.Add(console=PromptBox(Dock: DockStyle.Fill,
					Font: System.Drawing.Font("Lucida Console", 12)))

		console.Interpreter.SetValue("MainForm", mainForm)

	override def GetPersistString():
		return "InteractiveConsole|"

class PromptBox(TextBox):

	static Enter = chr(13)

	enum InputState:
		SingleLine = 0
		Block = 1

	_state = InputState.SingleLine

	_block = System.IO.StringWriter()

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

	def constructor():
		self.Multiline = true
		self.AcceptsTab = true
		self.ScrollBars = ScrollBars.Vertical
		_interpreter.References.Add(typeof(TextBox).Assembly)
		_interpreter.References.Add(typeof(Font).Assembly)

		prompt()

	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:
			_interpreter.LoopEval(code)

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

	override def OnKeyPress(args as KeyPressEventArgs):
		if Enter == args.KeyChar:
			try:
				(SingleLineInputState, BlockInputState)[_state]()
			except x:
				print(x)
			prompt()
			args.Handled = true
		super(args)

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

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

	static def chr(value as int):
		return cast(IConvertible, value).ToChar(null)


make it clearer that the template are fields

git-svn-id: fcce7d6ce0ac15bf24f68871b5145d46fc068279@1839 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.Lang.Useful.Attributes

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

class OnceAttribute(AbstractAstAttribute):
"""
Caches the return value of a method.

@author Sorin Ionescu (sorin.ionescu@gmail.com)
"""
	private class ReturnValueStorageVisitor(DepthFirstVisitor):
	"""
	Replaces returns statements with binary expressions that
	store the values of the return statements.
	"""
		_returnValue as ReferenceExpression

		def constructor(returnValue as ReferenceExpression):
			_returnValue = returnValue

		override def OnReturnStatement(returnStatement as ReturnStatement):
		"""
		Replaces returns statements with binary expressions that
		store the values of the return statements.
		"""
			returnValueAssignment = BinaryExpression(
				LexicalInfo: returnStatement.LexicalInfo,
				Operator: BinaryOperatorType.Assign,
				Left: _returnValue,
				Right: returnStatement.Expression)

			parentNode = returnStatement.ParentNode
			parentNode.Replace(
				returnStatement,
				ExpressionStatement(returnValueAssignment))

	_method as Method
	_methodLock as Field
	_cached as Field
	_returnValue as Field

	override def Dispose():
	"""
	Dont get rid of the context because we'll need it later.
	"""
		pass

	override def Apply(node as Node):
	"""
	Applies the <OnceAttribute> to [node].

	Parameters:
		node
			The node to apply the <OnceAttribute> to.
	"""
		assert node isa Method

		_method = node

		CreateCachedField()
		CreateMethodLockField()

		Context.Parameters.Pipeline.AfterStep += def(
			sender,
			e as CompilerStepEventArgs):

			return if not e.Step isa ProcessMethodBodies

			# Void methods cannot be cached.
			assert _method.ReturnType.Entity is not \
				self.TypeSystemServices.VoidType, "once attribute cannot be applied to void methods"

			CreateReturnValueField()

			# Visit the node and replace return statements
			# with binary expressions that store the return
			# statement values.
			_method.Accept(
				ReturnValueStorageVisitor(self.CodeBuilder.CreateReference(_returnValue)))

			MakeMethodCacheable()

	def CreateReturnValueField():
	"""
	Creates the field that stores the return value of the cached method.
	"""
		template = self.CodeBuilder.CreateField('field', _method.ReturnType.Entity)
		_returnValue = AddField(template, "___${_method.Name}_returnValue")

	def CreateCachedField():
	"""
	Creates the cached flag.

	Remarks:
		The flag is used to check whether the method has been cached.
	"""
		template = ast:
			private field as bool
		_cached = AddField(template, "___${_method.Name}_cached")

	def CreateMethodLockField():
	"""
	Creates the lock field.

	Remarks:
		The field is used to lock on when the operatation is thread safe.
	"""
		template = ast:
			private field as object = object()
		_methodLock = AddField(template, "___${_method.Name}_lock")

	def AddField(template as Field, name as string):
		template.LexicalInfo = self.LexicalInfo
		template.Name = name
		template.Modifiers = TypeMemberModifiers.Private
		template.Modifiers |= TypeMemberModifiers.Static if IsStaticMethod()
		_method.DeclaringType.Members.Add(template)
		return template

	def IsStaticMethod():
		return _method.IsStatic or _method.ParentNode isa Module

	def MakeMethodCacheable():
	"""
	Modifies the method body to make it cacheable.
	"""
		methodBody = Block(LexicalInfo)

		# Create the double checked lock pattern.
		outerIfNotCached = IfStatement(
			LexicalInfo: LexicalInfo,
			Condition: self.CodeBuilder.CreateNotExpression(
						self.CodeBuilder.CreateReference(_cached)),
			TrueBlock: Block())

		innerIfNotCached = outerIfNotCached.CloneNode()
		innerIfNotCached.TrueBlock.Add(_method.Body)
		innerIfNotCached.TrueBlock.Add(
			BinaryExpression(
				LexicalInfo,
				BinaryOperatorType.Assign,
				self.CodeBuilder.CreateReference(_cached),
				self.CodeBuilder.CreateBoolLiteral(true)))

		monitorEnterInvocation = self.CodeBuilder.CreateMethodInvocation(
			self.TypeSystemServices.Map(typeof(Monitor).GetMethod('Enter')),
			self.CodeBuilder.CreateReference(_methodLock))

		monitorExitInvocation = self.CodeBuilder.CreateMethodInvocation(
			self.TypeSystemServices.Map(typeof(Monitor).GetMethod('Exit')),
			self.CodeBuilder.CreateReference(_methodLock))

		protectedBlock = Block(LexicalInfo)
		protectedBlock.Add(innerIfNotCached)

		ensureBlock = Block(LexicalInfo)
		ensureBlock.Add(monitorExitInvocation)

		outerIfNotCached.TrueBlock.Add(monitorEnterInvocation)
		outerIfNotCached.TrueBlock.Add(
			TryStatement(
				LexicalInfo: LexicalInfo,
				ProtectedBlock: protectedBlock,
				EnsureBlock: ensureBlock))

		methodBody.Add(outerIfNotCached)
		methodBody.Add(
			ReturnStatement(
				LexicalInfo: LexicalInfo,
				Expression: self.CodeBuilder.CreateReference(_returnValue)))

		_method.Body = methodBody

#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.Lang.Useful.Attributes

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

class OnceAttribute(AbstractAstAttribute):
"""
Caches the return value of a method.

@author Sorin Ionescu (sorin.ionescu@gmail.com)
"""
	private class ReturnValueStorageVisitor(DepthFirstVisitor):
	"""
	Replaces returns statements with binary expressions that
	store the values of the return statements.
	"""
		_returnValue as ReferenceExpression

		def constructor(returnValue as ReferenceExpression):
			_returnValue = returnValue

		override def OnReturnStatement(returnStatement as ReturnStatement):
		"""
		Replaces returns statements with binary expressions that
		store the values of the return statements.
		"""
			returnValueAssignment = BinaryExpression(
				LexicalInfo: returnStatement.LexicalInfo,
				Operator: BinaryOperatorType.Assign,
				Left: _returnValue,
				Right: returnStatement.Expression)

			parentNode = returnStatement.ParentNode
			parentNode.Replace(
				returnStatement,
				ExpressionStatement(returnValueAssignment))

	_method as Method
	_methodLock as Field
	_cached as Field
	_returnValue as Field

	override def Dispose():
	"""
	Dont get rid of the context because we'll need it later.
	"""
		pass

	override def Apply(node as Node):
	"""
	Applies the <OnceAttribute> to [node].

	Parameters:
		node
			The node to apply the <OnceAttribute> to.
	"""
		assert node isa Method

		_method = node

		CreateCachedField()
		CreateMethodLockField()

		Context.Parameters.Pipeline.AfterStep += def(
			sender,
			e as CompilerStepEventArgs):

			return if not e.Step isa ProcessMethodBodies

			# Void methods cannot be cached.
			assert _method.ReturnType.Entity is not \
				self.TypeSystemServices.VoidType, "once attribute cannot be applied to void methods"

			CreateReturnValueField()

			# Visit the node and replace return statements
			# with binary expressions that store the return
			# statement values.
			_method.Accept(
				ReturnValueStorageVisitor(self.CodeBuilder.CreateReference(_returnValue)))

			MakeMethodCacheable()

	def CreateReturnValueField():
	"""
	Creates the field that stores the return value of the cached method.
	"""
		template = self.CodeBuilder.CreateField('field', _method.ReturnType.Entity)
		_returnValue = AddField(template, "___${_method.Name}_returnValue")

	def CreateCachedField():
	"""
	Creates the cached flag.

	Remarks:
		The flag is used to check whether the method has been cached.
	"""
		template = ast:
			field as bool
		_cached = AddField(template, "___${_method.Name}_cached")

	def CreateMethodLockField():
	"""
	Creates the lock field.

	Remarks:
		The field is used to lock on when the operatation is thread safe.
	"""
		template = ast:
			field as object = object()
		_methodLock = AddField(template, "___${_method.Name}_lock")

	def AddField(template as Field, name as string):
		template.LexicalInfo = self.LexicalInfo
		template.Name = name
		template.Modifiers = TypeMemberModifiers.Private
		template.Modifiers |= TypeMemberModifiers.Static if IsStaticMethod()
		_method.DeclaringType.Members.Add(template)
		return template

	def IsStaticMethod():
		return _method.IsStatic or _method.ParentNode isa Module

	def MakeMethodCacheable():
	"""
	Modifies the method body to make it cacheable.
	"""
		methodBody = Block(LexicalInfo)

		# Create the double checked lock pattern.
		outerIfNotCached = IfStatement(
			LexicalInfo: LexicalInfo,
			Condition: self.CodeBuilder.CreateNotExpression(
						self.CodeBuilder.CreateReference(_cached)),
			TrueBlock: Block())

		innerIfNotCached = outerIfNotCached.CloneNode()
		innerIfNotCached.TrueBlock.Add(_method.Body)
		innerIfNotCached.TrueBlock.Add(
			BinaryExpression(
				LexicalInfo,
				BinaryOperatorType.Assign,
				self.CodeBuilder.CreateReference(_cached),
				self.CodeBuilder.CreateBoolLiteral(true)))

		monitorEnterInvocation = self.CodeBuilder.CreateMethodInvocation(
			self.TypeSystemServices.Map(typeof(Monitor).GetMethod('Enter')),
			self.CodeBuilder.CreateReference(_methodLock))

		monitorExitInvocation = self.CodeBuilder.CreateMethodInvocation(
			self.TypeSystemServices.Map(typeof(Monitor).GetMethod('Exit')),
			self.CodeBuilder.CreateReference(_methodLock))

		protectedBlock = Block(LexicalInfo)
		protectedBlock.Add(innerIfNotCached)

		ensureBlock = Block(LexicalInfo)
		ensureBlock.Add(monitorExitInvocation)

		outerIfNotCached.TrueBlock.Add(monitorEnterInvocation)
		outerIfNotCached.TrueBlock.Add(
			TryStatement(
				LexicalInfo: LexicalInfo,
				ProtectedBlock: protectedBlock,
				EnsureBlock: ensureBlock))

		methodBody.Add(outerIfNotCached)
		methodBody.Add(
			ReturnStatement(
				LexicalInfo: LexicalInfo,
				Expression: self.CodeBuilder.CreateReference(_returnValue)))

		_method.Body = methodBody


Update build script

Update build script

solution_file = "GitAspx.sln"
project_file = "GitAspx/GitAspx.csproj"

target default, (init, compile, package):
  pass

target init:
  rm("build")

target compile:
   msbuild(file: project_file, configuration: "release", version: "4", targets: ("Build", "_CopyWebApplication"), properties: { "OutDir": "../build/output/" })

target package:
  zip("Build/Output/_PublishedWebsites/Gitaspx", "Build/GitAspx.zip")

solution_file = "GitAspx.sln"
project_file = "GitAspx/GitAspx.csproj"

target default, (init, compile, test, deploy, package):
  pass

target init:
  rm("build")

target compile:
  msbuild(file: solution_file, configuration: "release", version: "4")

target test:
  pass # Need to implement

target deploy:
  msbuild(file: project_file, configuration: "release", version: "4", targets: ("_CopyWebApplication",), properties: { "OutDir": "../build/" }, verbosity: "normal")

target package:
  zip("Build/_PublishedWebsites/Gitaspx", "Build/GitAspx.zip")


Remove missnamed file

Remove missnamed file

// DO NOT EDIT! File automatically generated from parser error examples

namespace Boo.Lang.Parser
{
    static class GeneratedErrorPatterns
    {
        public static List<ErrorPattern> Patterns
        {
            get
            {
                List<ErrorPattern> list = new List<ErrorPattern>();

                list.Add(
                    new Boo.Lang.Parser.NoViableAltErrorPattern(
                        "Unbalanced expression, closing paren not found",
                        "array_or_expression"
                    )

                );
                list.Add(
                    new Boo.Lang.Parser.NoViableAltErrorPattern(
                        "Unbalanced expression, closing paren not found",
                        "array_or_expression"
                    )

                );
                list.Add(
                    new Boo.Lang.Parser.MismatchedErrorPattern(
                        "Unbalanced expression, closing paren not found",
                        "argument"
                    )

                );
                list.Add(
                    new Boo.Lang.Parser.NoViableAltErrorPattern(
                        "Unbalanced expression, opening paren not found",
                        "array_or_expression"
                    )

                );
                list.Add(
                    new Boo.Lang.Parser.MismatchedErrorPattern(
                        "Either separate expressions with commas or make sure your parens are balanced",
                        "argument"
                    )

                );
                list.Add(
                    new Boo.Lang.Parser.MismatchedErrorPattern(
                        "Expressions must be separated by commas",
                        "argument"
                    )

                );
                list.Add(
                    new Boo.Lang.Parser.NoViableAltErrorPattern(
                        "Expressions must be separated by commas",
                        "array_or_expression"
                    )

                );
                list.Add(
                    new Boo.Lang.Parser.MismatchedErrorPattern(
                        "Block must be indented",
                        "docstring"
                    )

                );
                list.Add(
                    new Boo.Lang.Parser.MismatchedErrorPattern(
                        "Block must be indented",
                        "docstring"
                    )

                );
                list.Add(
                    new Boo.Lang.Parser.NoViableAltErrorPattern(
                        "Block must be indented",
                        "expression"
                    )

                );

                return list;
            }
        }
    }
}