BOO-990: Allow testcases to be ignored.

BOO-990: Allow testcases to be ignored.

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

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

import System
import System.IO
import Boo.Lang.Compiler.Ast.Visitors
import Boo.Lang.Parser

class Util:
	public static argv as (string)

def PortParserTestCases():
"""
Generates WSA parser test cases from
normal parser test cases.
"""
	for testcase in Directory.GetFiles("testcases/parser/roundtrip", "*.boo"):
		if not testcase.EndsWith(".boo"): continue

		fname = Path.GetFileName(testcase)
		wsaTestCase = Path.Combine("testcases/parser/wsa", fname)
		if not File.Exists(wsaTestCase):
			PortParserTestCase(testcase, wsaTestCase)
			print fname

def CopyDocstring(fname as string, writer as TextWriter):
	using file=File.OpenText(fname):
		tripleQuoteCount = 0
		for line in file:
			writer.WriteLine(line)
			if line.Trim() == '"""':
				++tripleQuoteCount
				break if tripleQuoteCount == 2

def PortParserTestCase(fromTestCase as string, toTestCase as string):
	using writer = StreamWriter(toTestCase):
		CopyDocstring(fromTestCase, writer)
		module=BooParser.ParseFile(fromTestCase).Modules[0]
		module.Accept(BooPrinterVisitor(writer, BooPrinterVisitor.PrintOptions.WSA))

def GetTestCaseName(fname as string):
	return Path.GetFileNameWithoutExtension(fname).Replace("-", "_")

def MapPath(path):
#	return Path.Combine(Project.BaseDirectory, path)
	return Path.GetFullPath(path)

def WriteTestCases(writer as TextWriter, baseDir as string):
	count, ignored = 0, 0
	for fname as string in Directory.GetFiles(MapPath("testcases/${baseDir}")):
		continue unless fname.EndsWith(".boo")
		ignore = false
		message = ''
		using file = File.OpenText(fname):
			while firstLine = file.ReadLine().Trim():
				break unless firstLine.StartsWith('#')
				if firstLine.StartsWith('#ignore', StringComparison.InvariantCultureIgnoreCase):
					message += ' ' + (firstLine[8:] if len(firstLine) > 9 else '').Trim()
					ignore = true
		++count unless ignore
		++ignored if ignore
		attribute = ("[Ignore(\"${message}\")]" if ignore else '')
		writer.Write("""
		${attribute}[Test]
		public void ${GetTestCaseName(fname)}()
		{
			RunCompilerTestCase(@"${NormalizePath(Path.GetFileName(fname))}");
		}
		""")
	print("{0,5} {1,7}  {2}" % (count, ignored, baseDir))

def GenerateTestFixture(srcDir as string, targetFile as string, fixtureAssembly as string, header as string):
	return if Util.argv and len(Util.argv) and Util.argv[0] == fixtureAssembly
	using writer=StreamWriter(MapPath(targetFile)):
		writer.Write(header)
		WriteTestCases(writer, srcDir)
		writer.Write("""

		override protected string GetRelativeTestCasesPath()
		{
			return "${NormalizePath(srcDir)}";
		}
	}
}
""")

def NormalizePath(path as string):
	return path.Replace('\\', '/')

def GenerateIntegrationTestFixtures():
	for dir in Directory.GetDirectories("testcases/integration"):
		if /\.svn/.IsMatch(dir): continue
		GenerateIntegrationTestFixture("integration/${Path.GetFileName(dir)}")

def PascalCase(name as string):
	return name[:1].ToUpper() + name[1:]

def IntegrationTestFixtureName(dir as string):
	baseName = join(PascalCase(part) for part in /-/.Split(Path.GetFileName(dir)), '')
	return "${baseName}IntegrationTestFixture"

def GenerateIntegrationTestFixture(dir as string):
	fixtureName = IntegrationTestFixtureName(dir)
	header = """namespace BooCompiler.Tests
{
	using NUnit.Framework;

	[TestFixture]
	public class ${fixtureName} : AbstractCompilerTestCase
	{
	"""
	GenerateTestFixture(dir, "BooCompiler.Tests/${fixtureName}.cs", "BooCompiler.${fixtureName.Replace('TestFixture', '')}", header)

#Util.argv = argv

print("{0,-5} {1,-7}  {2}" % ('tests', 'ignored', 'directory'))

GenerateIntegrationTestFixtures()

GenerateTestFixture("regression", "BooCompiler.Tests/RegressionTestFixture.cs", "BooCompiler.Regression", """
namespace BooCompiler.Tests
{
	using NUnit.Framework;

	[TestFixture]
	public class RegressionTestFixture : AbstractCompilerTestCase
	{
""")

GenerateTestFixture("errors", "BooCompiler.Tests/CompilerErrorsTestFixture.cs", "BooCompiler.CompilerErrors", """
namespace BooCompiler.Tests
{
	using NUnit.Framework;
	using Boo.Lang.Compiler;

	[TestFixture]
	public class CompilerErrorsTestFixture : AbstractCompilerErrorsTestFixture
	{
""")

GenerateTestFixture("warnings", "BooCompiler.Tests/CompilerWarningsTestFixture.cs", "BooCompiler.CompilerWarnings", """
namespace BooCompiler.Tests
{
	using NUnit.Framework;
	using Boo.Lang.Compiler;

	[TestFixture]
	public class CompilerWarningsTestFixture : AbstractCompilerTestCase
	{
		protected override CompilerPipeline SetUpCompilerPipeline()
		{
			CompilerPipeline pipeline = new Boo.Lang.Compiler.Pipelines.Compile();
			pipeline.Add(new Boo.Lang.Compiler.Steps.PrintWarnings());
			return pipeline;
		}
""")

GenerateTestFixture("macros", "BooCompiler.Tests/MacrosTestFixture.cs", "BooCompiler.Macros", """
namespace BooCompiler.Tests
{
	using NUnit.Framework;

	[TestFixture]
	public class MacrosTestFixture : AbstractCompilerTestCase
	{
""")

GenerateTestFixture("stdlib", "BooCompiler.Tests/StdlibTestFixture.cs", "BooCompiler.Stdlib", """
namespace BooCompiler.Tests
{
	using NUnit.Framework;

	[TestFixture]
	public class StdlibTestFixture : AbstractCompilerTestCase
	{
""")

GenerateTestFixture("attributes", "BooCompiler.Tests/AttributesTestFixture.cs", "BooCompiler.Attributes", """
namespace BooCompiler.Tests
{
	using NUnit.Framework;
	using Boo.Lang.Compiler;
	using Boo.Lang.Compiler.Steps;

	[TestFixture]
	public class AttributesTestFixture : AbstractCompilerTestCase
	{
		override protected CompilerPipeline SetUpCompilerPipeline()
		{
			CompilerPipeline pipeline = new Boo.Lang.Compiler.Pipelines.Parse();
			pipeline.Add(new InitializeTypeSystemServices());
			pipeline.Add(new InitializeNameResolutionService());
			pipeline.Add(new IntroduceGlobalNamespaces());
			pipeline.Add(new BindNamespaces());
			pipeline.Add(new BindAndApplyAttributes());
			pipeline.Add(new PrintBoo());
			return pipeline;
		}
""")

GenerateTestFixture("parser/roundtrip", "build/ParserRoundtripTestFixture.cs", "Boo.Lang.Parser", """
namespace Boo.Lang.Parser.Tests
{
	using NUnit.Framework;

	[TestFixture]
	public class ParserRoundtripTestFixture : AbstractParserTestFixture
	{
		void RunCompilerTestCase(string fname)
		{
			RunParserTestCase(fname);
		}
""")

PortParserTestCases()
GenerateTestFixture("parser/wsa", "build/WSAParserRoundtripTestFixture.cs", "Boo.Lang.Parser", """
namespace Boo.Lang.Parser.Tests
{
	using NUnit.Framework;

	[TestFixture]
	public class WSAParserRoundtripTestFixture : AbstractWSAParserTestFixture
	{
		void RunCompilerTestCase(string fname)
		{
			RunParserTestCase(fname);
		}
""")

GenerateTestFixture("semantics", "BooCompiler.Tests/SemanticsTestFixture.cs", "BooCompiler.Semantics", """
namespace BooCompiler.Tests
{
	using NUnit.Framework;
	using Boo.Lang.Compiler;
	using Boo.Lang.Compiler.Pipelines;

	[TestFixture]
	public class SemanticsTestFixture : AbstractCompilerTestCase
	{
		protected override CompilerPipeline SetUpCompilerPipeline()
		{
			return new CompileToBoo();
		}
""")

GenerateTestFixture("ducky", "BooCompiler.Tests/DuckyTestFixture.cs", "BooCompiler.Ducky", """
namespace BooCompiler.Tests
{
	using NUnit.Framework;
	using Boo.Lang.Compiler;
	using Boo.Lang.Compiler.Pipelines;

	[TestFixture]
	public class DuckyTestFixture : AbstractCompilerTestCase
	{
		protected override void CustomizeCompilerParameters()
		{
			_parameters.Ducky = true;
		}
""")

GenerateTestFixture("net2/generics", "BooCompiler.Tests/GenericsTestFixture.cs", "BooCompiler.Generics", """
namespace BooCompiler.Tests
{
	using NUnit.Framework;

	[TestFixture]
	public class GenericsTestFixture : AbstractCompilerTestCase
	{
		override protected void RunCompilerTestCase(string name)
		{
			if (System.Environment.Version.Major < 2) Assert.Ignore("Test requires .net 2.");
			System.ResolveEventHandler resolver = InstallAssemblyResolver(BaseTestCasesPath);
			try
			{
				base.RunCompilerTestCase(name);
			}
			finally
			{
				RemoveAssemblyResolver(resolver);
			}
		}

		override protected void CopyDependencies()
		{
			CopyAssembliesFromTestCasePath();
		}
""")

GenerateTestFixture("net2/errors", "BooCompiler.Tests/Net2ErrorsTestFixture.cs", "BooCompiler.Net2Errors", """
namespace BooCompiler.Tests
{
	using NUnit.Framework;

	[TestFixture]
	public class Net2ErrorsTestFixture : AbstractCompilerErrorsTestFixture
	{
		override protected void RunCompilerTestCase(string name)
		{
			if (System.Environment.Version.Major < 2) Assert.Ignore("Test requires .net 2.");
			base.RunCompilerTestCase(name);
		}
""")

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

import System
import System.IO
import Boo.Lang.Compiler.Ast.Visitors
import Boo.Lang.Parser

def PortParserTestCases():
"""
Generates WSA parser test cases from
normal parser test cases.
"""
	for testcase in Directory.GetFiles("testcases/parser/roundtrip", "*.boo"):
		if not testcase.EndsWith(".boo"): continue

		fname = Path.GetFileName(testcase)
		wsaTestCase = Path.Combine("testcases/parser/wsa", fname)
		if not File.Exists(wsaTestCase):
			PortParserTestCase(testcase, wsaTestCase)
			print fname

def CopyDocstring(fname as string, writer as TextWriter):
	using file=File.OpenText(fname):
		tripleQuoteCount = 0
		for line in file:
			writer.WriteLine(line)
			if line.Trim() == '"""':
				++tripleQuoteCount
				break if tripleQuoteCount == 2

def PortParserTestCase(fromTestCase as string, toTestCase as string):
	using writer = StreamWriter(toTestCase):
		CopyDocstring(fromTestCase, writer)
		module=BooParser.ParseFile(fromTestCase).Modules[0]
		module.Accept(BooPrinterVisitor(writer, BooPrinterVisitor.PrintOptions.WSA))

def GetTestCaseName(fname as string):
	return Path.GetFileNameWithoutExtension(fname).Replace("-", "_")

def MapPath(path):
#	return Path.Combine(Project.BaseDirectory, path)
	return Path.GetFullPath(path)

def WriteTestCases(writer as TextWriter, baseDir as string):
	count = 0
	for fname as string in Directory.GetFiles(MapPath("testcases/${baseDir}")):
		continue unless fname.EndsWith(".boo")
		++count
		writer.Write("""
		[Test]
		public void ${GetTestCaseName(fname)}()
		{
			RunCompilerTestCase(@"${NormalizePath(Path.GetFileName(fname))}");
		}
		""")
	print("${count} test cases found in ${baseDir}.")

def GenerateTestFixture(srcDir as string, targetFile as string, header as string):
	using writer=StreamWriter(MapPath(targetFile)):
		writer.Write(header)
		WriteTestCases(writer, srcDir)
		writer.Write("""

		override protected string GetRelativeTestCasesPath()
		{
			return "${NormalizePath(srcDir)}";
		}
	}
}
""")

def NormalizePath(path as string):
	return path.Replace('\\', '/')

def GenerateIntegrationTestFixtures():
	for dir in Directory.GetDirectories("testcases/integration"):
		if /\.svn/.IsMatch(dir): continue
		GenerateIntegrationTestFixture("integration/${Path.GetFileName(dir)}")

def PascalCase(name as string):
	return name[:1].ToUpper() + name[1:]

def IntegrationTestFixtureName(dir as string):
	baseName = join(PascalCase(part) for part in /-/.Split(Path.GetFileName(dir)), '')
	return "${baseName}IntegrationTestFixture"

def GenerateIntegrationTestFixture(dir as string):
	fixtureName = IntegrationTestFixtureName(dir)
	header = """namespace BooCompiler.Tests
{
	using NUnit.Framework;

	[TestFixture]
	public class ${fixtureName} : AbstractCompilerTestCase
	{
	"""
	GenerateTestFixture(dir, "BooCompiler.Tests/${fixtureName}.cs", header)

GenerateIntegrationTestFixtures()

GenerateTestFixture("regression", "BooCompiler.Tests/RegressionTestFixture.cs", """
namespace BooCompiler.Tests
{
	using NUnit.Framework;

	[TestFixture]
	public class RegressionTestFixture : AbstractCompilerTestCase
	{
""")

GenerateTestFixture("errors", "BooCompiler.Tests/CompilerErrorsTestFixture.cs", """
namespace BooCompiler.Tests
{
	using NUnit.Framework;
	using Boo.Lang.Compiler;

	[TestFixture]
	public class CompilerErrorsTestFixture : AbstractCompilerErrorsTestFixture
	{
""")

GenerateTestFixture("warnings", "BooCompiler.Tests/CompilerWarningsTestFixture.cs", """
namespace BooCompiler.Tests
{
	using NUnit.Framework;
	using Boo.Lang.Compiler;

	[TestFixture]
	public class CompilerWarningsTestFixture : AbstractCompilerTestCase
	{
		protected override CompilerPipeline SetUpCompilerPipeline()
		{
			CompilerPipeline pipeline = new Boo.Lang.Compiler.Pipelines.Compile();
			pipeline.Add(new Boo.Lang.Compiler.Steps.PrintWarnings());
			return pipeline;
		}
""")

GenerateTestFixture("macros", "BooCompiler.Tests/MacrosTestFixture.cs", """
namespace BooCompiler.Tests
{
	using NUnit.Framework;

	[TestFixture]
	public class MacrosTestFixture : AbstractCompilerTestCase
	{
""")

GenerateTestFixture("stdlib", "BooCompiler.Tests/StdlibTestFixture.cs", """
namespace BooCompiler.Tests
{
	using NUnit.Framework;

	[TestFixture]
	public class StdlibTestFixture : AbstractCompilerTestCase
	{
""")

GenerateTestFixture("attributes", "BooCompiler.Tests/AttributesTestFixture.cs", """
namespace BooCompiler.Tests
{
	using NUnit.Framework;
	using Boo.Lang.Compiler;
	using Boo.Lang.Compiler.Steps;

	[TestFixture]
	public class AttributesTestFixture : AbstractCompilerTestCase
	{
		override protected CompilerPipeline SetUpCompilerPipeline()
		{
			CompilerPipeline pipeline = new Boo.Lang.Compiler.Pipelines.Parse();
			pipeline.Add(new InitializeTypeSystemServices());
			pipeline.Add(new InitializeNameResolutionService());
			pipeline.Add(new IntroduceGlobalNamespaces());
			pipeline.Add(new BindNamespaces());
			pipeline.Add(new BindAndApplyAttributes());
			pipeline.Add(new PrintBoo());
			return pipeline;
		}
""")

GenerateTestFixture("parser/roundtrip", "build/ParserRoundtripTestFixture.cs", """
namespace Boo.Lang.Parser.Tests
{
	using NUnit.Framework;

	[TestFixture]
	public class ParserRoundtripTestFixture : AbstractParserTestFixture
	{
		void RunCompilerTestCase(string fname)
		{
			RunParserTestCase(fname);
		}
""")

PortParserTestCases()
GenerateTestFixture("parser/wsa", "build/WSAParserRoundtripTestFixture.cs", """
namespace Boo.Lang.Parser.Tests
{
	using NUnit.Framework;

	[TestFixture]
	public class WSAParserRoundtripTestFixture : AbstractWSAParserTestFixture
	{
		void RunCompilerTestCase(string fname)
		{
			RunParserTestCase(fname);
		}
""")

GenerateTestFixture("semantics", "BooCompiler.Tests/SemanticsTestFixture.cs", """
namespace BooCompiler.Tests
{
	using NUnit.Framework;
	using Boo.Lang.Compiler;
	using Boo.Lang.Compiler.Pipelines;

	[TestFixture]
	public class SemanticsTestFixture : AbstractCompilerTestCase
	{
		protected override CompilerPipeline SetUpCompilerPipeline()
		{
			return new CompileToBoo();
		}
""")

GenerateTestFixture("ducky", "BooCompiler.Tests/DuckyTestFixture.cs", """
namespace BooCompiler.Tests
{
	using NUnit.Framework;
	using Boo.Lang.Compiler;
	using Boo.Lang.Compiler.Pipelines;

	[TestFixture]
	public class DuckyTestFixture : AbstractCompilerTestCase
	{
		protected override void CustomizeCompilerParameters()
		{
			_parameters.Ducky = true;
		}
""")

GenerateTestFixture("net2/generics", "BooCompiler.Tests/GenericsTestFixture.cs", """
namespace BooCompiler.Tests
{
	using NUnit.Framework;

	[TestFixture]
	public class GenericsTestFixture : AbstractCompilerTestCase
	{
		override protected void RunCompilerTestCase(string name)
		{
			if (System.Environment.Version.Major < 2) Assert.Ignore("Test requires .net 2.");
			System.ResolveEventHandler resolver = InstallAssemblyResolver(BaseTestCasesPath);
			try
			{
				base.RunCompilerTestCase(name);
			}
			finally
			{
				RemoveAssemblyResolver(resolver);
			}
		}

		override protected void CopyDependencies()
		{
			CopyAssembliesFromTestCasePath();
		}
""")

GenerateTestFixture("net2/errors", "BooCompiler.Tests/Net2ErrorsTestFixture.cs", """
namespace BooCompiler.Tests
{
	using NUnit.Framework;

	[TestFixture]
	public class Net2ErrorsTestFixture : AbstractCompilerErrorsTestFixture
	{
		override protected void RunCompilerTestCase(string name)
		{
			if (System.Environment.Version.Major < 2) Assert.Ignore("Test requires .net 2.");
			base.RunCompilerTestCase(name);
		}
""")


movido indice do icone para enum

movido indice do icone para enum

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

namespace BooExplorer

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

enum TypeIcon:
	Namespace
	PublicClass
	PublicInterface
	PublicEnum
	PublicField
	PublicProperty
	PublicMethod

class DocumentOutline(Content):

	_activeDocument as BooEditor
	_tree as TreeView
	_imageList as ImageList
	_treeViewVisitor as TreeViewVisitor
	_timer = Timer(Tick: _timer_Tick, Interval: 3s.TotalMilliseconds)
	_module as Module

	def constructor():
		InitImageList()
		InitTreeView()

		_treeViewVisitor = TreeViewVisitor(_tree)

		SuspendLayout()

		Controls.Add(_tree)
		self.AllowedStates = (
					ContentStates.Float |
					ContentStates.DockLeft |
					ContentStates.DockRight)
		self.ClientSize = System.Drawing.Size(295, 347)

		self.DockPadding.Bottom = 2
		self.DockPadding.Top = 26
		self.HideOnClose = true
		self.ShowHint = WeifenLuo.WinFormsUI.DockState.DockRight
		self.Text = "Document Outline"
		ResumeLayout(false)

	def InitImageList():
		_imageList = ImageList()
		appPath = Path.GetDirectoryName(Application.ExecutablePath)

		imageListName = ["namespace.png", "class.png", "interface.png",
						"enum.png", "field.png", "property.png", "method.png"]

		try:
			for imageName in imageListName:
				_imageList.Images.Add(Image.FromFile(Path.Combine(appPath, imageName)))
		except ex as FileNotFoundException:
			pass

	def InitTreeView():
		_tree = TreeView(Dock: DockStyle.Fill,
						DoubleClick: _tree_DoubleClick,
						ImageIndex: cast(int, TypeIcon.Namespace),
						SelectedImageIndex: cast(int, TypeIcon.Namespace),
						ImageList: _imageList)

	ActiveDocument as BooEditor:
		set:
			_activeDocument = value
			_timer.Enabled = value is not null
			Update() if self.Visible

	def Update():
		if _activeDocument is null:
			_tree.Nodes.Clear()
		else:
			_activeDocument.UpdateModule()
			UpdateTree(_activeDocument.Module)

	def UpdateTree(module as Module):
		if module is not _module:
			_module = module
			_treeViewVisitor.Switch(_module)

	def _timer_Tick(sender, args as EventArgs):
		Update()

	def _tree_DoubleClick(sender, args as EventArgs):
		return unless _activeDocument

		if (treeNode = _tree.SelectedNode):
			node as Node = treeNode.Tag
			if node is not null:
				info = node.LexicalInfo
				_activeDocument.GoTo(info.Line-1)

class TreeViewVisitor(DepthFirstSwitcher):

	_tree as TreeView
	_current as TreeNode

	def constructor(tree):
		_tree = tree

	override def OnModule(node as Module):

		_current = TreeNode("root")
		Switch(node.Members)

		_tree.BeginUpdate()
		_tree.Nodes.Clear()
		if len(_current.Nodes):
			_tree.Nodes.AddRange(array(TreeNode, _current.Nodes))
			_tree.ExpandAll()
			_tree.Nodes[0].EnsureVisible()
		_tree.EndUpdate()

	override def OnProperty(node as Property):
		Add(node.Name, cast(int, TypeIcon.PublicProperty), node)

	override def OnField(node as Field):
		Add(node.Name, cast(int, TypeIcon.PublicField), node)

	override def OnInterfaceDefinition(node as InterfaceDefinition):
		OnTypeDefinition(node, cast(int, TypeIcon.PublicInterface))

	override def OnClassDefinition(node as ClassDefinition):
		OnTypeDefinition(node, cast(int, TypeIcon.PublicClass))

	override def OnEnumDefinition(node as EnumDefinition):
		OnTypeDefinition(node, cast(int, TypeIcon.PublicEnum))

	def OnTypeDefinition(node as TypeDefinition, imageIndex as int):
		saved = _current

		_current = Add(node.Name, imageIndex, imageIndex, node)
		Switch(node.Members)

		_current = saved

	override def OnConstructor(node as Constructor):
		OnMethod(node)

	override def OnMethod(node as Method):
		name = "${node.Name}(${join([p.Name for p as ParameterDeclaration in node.Parameters], ', ')})"
		Add(name, 6, 6, node)

	def Add(text as string, data):
		node = _current.Nodes.Add(text)
		node.Tag = data
		return node

	def Add(text as string, imageIndex as int, data):
		Add(text, imageIndex, imageIndex, data)

	def Add(text as string, imageIndex as int, selectedImageIndex as int, data):
		node = _current.Nodes.Add(text)
		node.Tag = data
		node.ImageIndex = imageIndex
		node.SelectedImageIndex = selectedImageIndex
		return node

namespace BooExplorer

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

class DocumentOutline(Content):

	_activeDocument as BooEditor
	_tree as TreeView
	_imageList as ImageList
	_treeViewVisitor as TreeViewVisitor
	_timer = Timer(Tick: _timer_Tick, Interval: 3s.TotalMilliseconds)
	_module as Module

	def constructor():
		InitImageList()
		InitTreeView()

		_treeViewVisitor = TreeViewVisitor(_tree)

		SuspendLayout()

		Controls.Add(_tree)
		self.AllowedStates = (
					ContentStates.Float |
					ContentStates.DockLeft |
					ContentStates.DockRight)
		self.ClientSize = System.Drawing.Size(295, 347)

		self.DockPadding.Bottom = 2
		self.DockPadding.Top = 26
		self.HideOnClose = true
		self.ShowHint = WeifenLuo.WinFormsUI.DockState.DockRight
		self.Text = "Document Outline"
		ResumeLayout(false)

	def InitImageList():
		_imageList = ImageList()
		appPath = Path.GetDirectoryName(Application.ExecutablePath)

		try:
			_imageList.Images.Add(Image.FromFile(Path.Combine(appPath, "namespace.png")))
			_imageList.Images.Add(Image.FromFile(Path.Combine(appPath, "class.png")))
			_imageList.Images.Add(Image.FromFile(Path.Combine(appPath, "interface.png")))
			_imageList.Images.Add(Image.FromFile(Path.Combine(appPath, "field.png")))
			_imageList.Images.Add(Image.FromFile(Path.Combine(appPath, "property.png")))
			_imageList.Images.Add(Image.FromFile(Path.Combine(appPath, "enum.png")))
			_imageList.Images.Add(Image.FromFile(Path.Combine(appPath, "method.png")))
		except ex as FileNotFoundException:
			pass

	def InitTreeView():
		_tree = TreeView(Dock: DockStyle.Fill,
						DoubleClick: _tree_DoubleClick,
						ImageIndex: 0,
						SelectedImageIndex: 0,
						ImageList: _imageList)

	ActiveDocument as BooEditor:
		set:
			_activeDocument = value
			_timer.Enabled = value is not null
			Update() if self.Visible

	def Update():
		if _activeDocument is null:
			_tree.Nodes.Clear()
		else:
			_activeDocument.UpdateModule()
			UpdateTree(_activeDocument.Module)

	def UpdateTree(module as Module):
		if module is not _module:
			_module = module
			_treeViewVisitor.Switch(_module)

	def _timer_Tick(sender, args as EventArgs):
		Update()

	def _tree_DoubleClick(sender, args as EventArgs):
		return unless _activeDocument

		if (treeNode = _tree.SelectedNode):
			node as Node = treeNode.Tag
			if node is not null:
				info = node.LexicalInfo
				_activeDocument.GoTo(info.Line-1)

class TreeViewVisitor(DepthFirstSwitcher):

	_tree as TreeView
	_current as TreeNode

	def constructor(tree):
		_tree = tree

	override def OnModule(node as Module):

		_current = TreeNode("root")
		Switch(node.Members)

		_tree.BeginUpdate()
		_tree.Nodes.Clear()
		if len(_current.Nodes):
			_tree.Nodes.AddRange(array(TreeNode, _current.Nodes))
			_tree.ExpandAll()
			_tree.Nodes[0].EnsureVisible()
		_tree.EndUpdate()

	override def OnProperty(node as Property):
		Add(node.Name, 4, 4, node)

	override def OnField(node as Field):
		Add(node.Name, 3, 3, node)

	override def OnInterfaceDefinition(node as InterfaceDefinition):
		OnTypeDefinition(node, 2, 2)

	override def OnClassDefinition(node as ClassDefinition):
		OnTypeDefinition(node, 1, 1)

	override def OnEnumDefinition(node as EnumDefinition):
		OnTypeDefinition(node, 5, 5)

	def OnTypeDefinition(node as TypeDefinition, imageIndex, selectedImageIndex):
		saved = _current

		_current = Add(node.Name, imageIndex, selectedImageIndex, node)
		Switch(node.Members)

		_current = saved

	override def OnConstructor(node as Constructor):
		OnMethod(node)

	override def OnMethod(node as Method):
		name = "${node.Name}(${join([p.Name for p as ParameterDeclaration in node.Parameters], ', ')})"
		Add(name, 6, 6, node)

	def Add(text as string, data):
		node = _current.Nodes.Add(text)
		node.Tag = data
		return node

	def Add(text as string, imageIndex, selectedImageIndex, data):
		node = _current.Nodes.Add(text)
		node.Tag = data
		node.ImageIndex = imageIndex
		node.SelectedImageIndex = selectedImageIndex
		return node


closures

closures

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

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

import System
import System.Windows.Forms from System.Windows.Forms

class App:

	[getter(Times)]
	_times = 0

	def Run():
		f = Form(Text: "My first boo winforms app",
				Closed: Application.Exit)

		button = Button(Text: "click me!")
		button.Click += callable:
			print("clicked!")
			++_times

		f.Controls.Add(button)
		f.Show()

		Application.Run(f)

app = App()
app.Run()
print("The button was clicked ${app.Times} times.")

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

import System
import System.Windows.Forms from System.Windows.Forms

class App:
	[getter(Times)]
	_times as int

	private def OnClick():
		print("clicked!")
		++_times

	def Run():
		f = Form(Text: "My first boo winforms app",
				Closed: Application.Exit)

		f.Controls.Add(
				Button(Text: "click me!",
						Click: OnClick))
		f.Show()

		Application.Run(f)

app = App()
app.Run()
print("The button was clicked ${app.Times} times.")


better version

better version

git-svn-id: fcce7d6ce0ac15bf24f68871b5145d46fc068279@2287 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.Diagnostics
import System.IO
import NAnt.Core
import NAnt.Core.Attributes
import NAnt.Core.Types
import Boo.Lang.Compiler
import Boo.Lang.Compiler.IO
import Boo.Lang.Compiler.Ast
import Boo.Lang.Compiler.Pipelines
import Boo.Lang.Compiler.Steps

class AbstractScript:

	[property(Project)]
	_project as Project

	[property(Task)]
	_task as BooTask

	def print(msg):
		_task.LogInfo(msg)

	abstract def Run():
		pass

class PrepareScriptStep(AbstractCompilerStep):

	override def Run():
		module = CompileUnit.Modules[0]

		method = Method(Name: "Run",
						Modifiers: TypeMemberModifiers.Override,
						Body: module.Globals)

		module.Globals = Block()

		script = ClassDefinition(Name: "__Script__")
		script.BaseTypes.Add(SimpleTypeReference("Boo.NAnt.AbstractScript"))
		script.Members.Add(method)
		script.Members.Extend(module.Members)

		module.Members.Clear()
		module.Members.Add(script)

def WithWorkingDir(dir as string, block as callable()):
	_saved = Environment.CurrentDirectory
	Environment.CurrentDirectory = dir
	try:
		block()
	ensure:
		Environment.CurrentDirectory = _saved

[TaskName("boo")]
class BooTask(AbstractBooTask):

	_src as FileInfo

	[TaskAttribute("src", Required: false)]
	Source:
		get:
			return _src
		set:
			_src = value

	override def ExecuteTask():

		compiler = BooCompiler()
		parameters = compiler.Parameters
		parameters.OutputType = CompilerOutputType.Library
		if _src:
			parameters.Input.Add(FileInput(_src.ToString()))
		else:
			parameters.Input.Add(StringInput("boo", reindent(getSourceCode())))
		parameters.References.Add(GetType().Assembly)
		parameters.References.Add(typeof(NAnt.Core.Project).Assembly)

		result = RunCompiler(compiler)

		print("script successfully compiled.")
		try:
			scriptType = result.GeneratedAssembly.GetType("__Script__", true)
			script as AbstractScript = scriptType()
			script.Project = Project
			script.Task = self
			WithWorkingDir(Project.BaseDirectory) do:
				script.Run()
		except x:
			raise BuildException(x.Message, Location, x)

	override def GetDefaultPipeline():
		pipeline = CompileToMemory()
		pipeline.Insert(1, PrepareScriptStep())
		return pipeline

	private def getSourceCode():
		codeNode = self.XmlNode.SelectSingleNode("code")
		return (codeNode or self.XmlNode).InnerText

	private def reindent(code as string):
		lines = /\n/.Split(code.Replace("\r\n", "\n"))
		lines = [line for line in lines if len(line.Trim())].ToArray(string)

		first = lines[0]
		indent = /(\s*)/.Match(first).Groups[0].Value
		return code if 0 == len(indent)

		buffer = System.Text.StringBuilder()
		for line in lines:
			if not line.StartsWith(indent):
				return code // let the parser complain about it
			else:
				buffer.Append(line[len(indent):])
				buffer.Append("\n")
		return buffer.ToString()

#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.Diagnostics
import System.IO
import NAnt.Core
import NAnt.Core.Attributes
import NAnt.Core.Types
import Boo.Lang.Compiler
import Boo.Lang.Compiler.IO
import Boo.Lang.Compiler.Ast
import Boo.Lang.Compiler.Pipelines
import Boo.Lang.Compiler.Steps

class AbstractScript:

	[property(Project)]
	_project as Project

	[property(Task)]
	_task as BooTask

	def print(msg):
		_task.LogInfo(msg)

	abstract def Run():
		pass

class PrepareScriptStep(AbstractCompilerStep):

	override def Run():
		module = CompileUnit.Modules[0]

		method = Method(Name: "Run",
						Modifiers: TypeMemberModifiers.Override,
						Body: module.Globals)

		module.Globals = Block()

		script = ClassDefinition(Name: "__Script__")
		script.BaseTypes.Add(SimpleTypeReference("Boo.NAnt.AbstractScript"))
		script.Members.Add(method)
		script.Members.Extend(module.Members)

		module.Members.Clear()
		module.Members.Add(script)

class WithWorkingDir(IDisposable):
	_saved as string
	def constructor(dir as string):
		_saved = Environment.CurrentDirectory
		Environment.CurrentDirectory = dir
	def Dispose():
		Environment.CurrentDirectory = _saved

[TaskName("boo")]
class BooTask(AbstractBooTask):

	_src as FileInfo

	[TaskAttribute("src", Required: false)]
	Source:
		get:
			return _src
		set:
			_src = value

	override def ExecuteTask():

		compiler = BooCompiler()
		parameters = compiler.Parameters
		parameters.OutputType = CompilerOutputType.Library
		if _src:
			parameters.Input.Add(FileInput(_src.ToString()))
		else:
			parameters.Input.Add(StringInput("boo", reindent(getSourceCode())))
		parameters.References.Add(GetType().Assembly)
		parameters.References.Add(typeof(NAnt.Core.Project).Assembly)

		result = RunCompiler(compiler)

		print("script successfully compiled.")
		using WithWorkingDir(Project.BaseDirectory):
			try:
				scriptType = result.GeneratedAssembly.GetType("__Script__", true)
				script as AbstractScript = scriptType()
				script.Project = Project
				script.Task = self
				script.Run()
			except x:
				raise BuildException(x.Message, Location, x)

	override def GetDefaultPipeline():
		pipeline = CompileToMemory()
		pipeline.Insert(1, PrepareScriptStep())
		return pipeline

	private def getSourceCode():
		codeNode = self.XmlNode.SelectSingleNode("code")
		return (codeNode or self.XmlNode).InnerText

	private def reindent(code as string):
		lines = /\n/.Split(code.Replace("\r\n", "\n"))
		lines = [line for line in lines if len(line.Trim())].ToArray(string)

		first = lines[0]
		indent = /(\s*)/.Match(first).Groups[0].Value
		return code if 0 == len(indent)

		buffer = System.Text.StringBuilder()
		for line in lines:
			if not line.StartsWith(indent):
				return code // let the parser complain about it
			else:
				buffer.Append(line[len(indent):])
				buffer.Append("\n")
		return buffer.ToString()


removed unnecessary indirection (memberForArgs) and added a simple checking to make sure 1 and only argument is passed in

namespace Boo.Adt

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

class DataMacro(AbstractAstMacro):

	override def Expand(node as MacroStatement):
		DataMacroExpansion(node)

class DataMacroExpansion:

	_module as Module
	_baseType as TypeReference

	def constructor(node as MacroStatement):

		assert 1 == len(node.Arguments)

		match node.Arguments[0]:
			case BinaryExpression(
					Operator: BinaryOperatorType.Assign,
					Left: left,
					Right: right):
				_module = enclosingModule(node)
				_baseType = createBaseType(left)
				expandDataConstructors(right)

	def enclosingModule(node as Node):
		return node.GetAncestor(NodeType.Module)

	def createBaseType(node as ReferenceExpression):
		type = [|
			abstract class $node:
				pass
		|]
		registerType(type)
		return SimpleTypeReference(LexicalInfo: node.LexicalInfo, Name: node.Name)

	def expandDataConstructors(node as Expression):
		match node:
			case BinaryExpression(Operator: BinaryOperatorType.BitwiseOr,
								Left: left,
								Right: right):
				expandDataConstructors(left)
				expandDataConstructors(right)
			case MethodInvocationExpression():
				expandDataConstructor(node)

	def expandDataConstructor(node as MethodInvocationExpression):
		match node.Target:
			case ReferenceExpression(Name: name):
				type = [|
					class $name($_baseType):
						pass
				|]
		type.LexicalInfo = node.LexicalInfo
		for arg in node.Arguments:
			type.Members.Add(fieldForArg(arg))
		type.Members.Add(toStringForType(type))
		type.Members.Add(equalsForType(type))
		type.Members.Add(constructorForInvocation(node))
		registerType(type)

	def equalsForType(type as TypeDefinition):

		method = [|
			override def Equals(o):
				if o is null: return false
				if GetType() != o.GetType(): return false
				other as $(type.Name) = o
		|]

		for field in fields(type):
			comparison = [|
				if self.$(field.Name) != other.$(field.Name):
					return false
			|]
			method.Body.Add(comparison)

		method.Body.Add([| return true |])
		return method

	def toStringForType(type as TypeDefinition):
		expression = ExpressionInterpolationExpression()
		items = expression.Expressions
		items.Add([| $("${type.Name}(") |])

		comma = false
		for field in fields(type):
			if comma: items.Add([| ", " |])
			items.Add([| self.$(field.Name) |])
			comma = true

		items.Add([| $(")") |])
		return [|
			override def ToString():
				return $expression
		|]

	def fields(type as TypeDefinition):
		return f for f as Field in type.Members.Select(NodeType.Field)

	def constructorForInvocation(node as MethodInvocationExpression):
		ctor = [|
			def constructor():
				pass
		|]
		for arg in node.Arguments:
			match arg:
				case TryCastExpression(
						Target: ReferenceExpression(Name: name),
						Type: type):
					ctor.Parameters.Add(
						ParameterDeclaration(Name: name, Type: type))
					ctor.Body.Add([|
						self.$name = $(ReferenceExpression(name))
					|])
		return ctor

	def fieldForArg(node as TryCastExpression):
		match node.Target:
			case ReferenceExpression(Name: name):
				return [|
					public final $name as $(node.Type)
				|]

	def registerType(type as TypeDefinition):
		_module.Members.Add(type)

namespace Boo.Adt

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

class DataMacro(AbstractAstMacro):

	override def Expand(node as MacroStatement):
		DataMacroExpansion(node)

class DataMacroExpansion:

	_module as Module
	_baseType as TypeReference

	def constructor(node as MacroStatement):
		match node.Arguments[0]:
			case BinaryExpression(
					Operator: BinaryOperatorType.Assign,
					Left: left,
					Right: right):
				_module = enclosingModule(node)
				_baseType = createBaseType(left)
				expandDataConstructors(right)

	def enclosingModule(node as Node):
		return node.GetAncestor(NodeType.Module)

	def createBaseType(node as ReferenceExpression):
		type = [|
			abstract class $node:
				pass
		|]
		registerType(type)
		return SimpleTypeReference(LexicalInfo: node.LexicalInfo, Name: node.Name)

	def expandDataConstructors(node as Expression):
		match node:
			case BinaryExpression(Operator: BinaryOperatorType.BitwiseOr,
								Left: left,
								Right: right):
				expandDataConstructors(left)
				expandDataConstructors(right)
			case MethodInvocationExpression():
				expandDataConstructor(node)

	def expandDataConstructor(node as MethodInvocationExpression):
		match node.Target:
			case ReferenceExpression(Name: name):
				type = [|
					class $name($_baseType):
						pass
				|]
		type.LexicalInfo = node.LexicalInfo
		for member in membersForArgs(node):
			type.Members.Add(member)
		type.Members.Add(toStringForType(type))
		type.Members.Add(equalsForType(type))
		type.Members.Add(constructorForInvocation(node))
		registerType(type)

	def equalsForType(type as TypeDefinition):

		method = [|
			override def Equals(o):
				if o is null: return false
				if GetType() != o.GetType(): return false
				other as $(type.Name) = o
		|]

		for field in fields(type):
			comparison = [|
				if self.$(field.Name) != other.$(field.Name):
					return false
			|]
			method.Body.Add(comparison)

		method.Body.Add([| return true |])
		return method

	def toStringForType(type as TypeDefinition):
		expression = ExpressionInterpolationExpression()
		items = expression.Expressions
		items.Add([| $("${type.Name}(") |])

		comma = false
		for field in fields(type):
			if comma: items.Add([| ", " |])
			items.Add([| self.$(field.Name) |])
			comma = true

		items.Add([| $(")") |])
		return [|
			override def ToString():
				return $expression
		|]

	def fields(type as TypeDefinition):
		return f for f as Field in type.Members.Select(NodeType.Field)

	def constructorForInvocation(node as MethodInvocationExpression):
		ctor = [|
			def constructor():
				pass
		|]
		for arg in node.Arguments:
			match arg:
				case TryCastExpression(
						Target: ReferenceExpression(Name: name),
						Type: type):
					ctor.Parameters.Add(
						ParameterDeclaration(Name: name, Type: type))
					ctor.Body.Add([|
						self.$name = $(ReferenceExpression(name))
					|])
		return ctor

	def membersForArgs(node as MethodInvocationExpression):
		for arg in node.Arguments:
			yield fieldForArg(arg)

	def fieldForArg(node as TryCastExpression):
		match node.Target:
			case ReferenceExpression(Name: name):
				return [|
					public final $name as $(node.Type)
				|]

	def registerType(type as TypeDefinition):
		_module.Members.Add(type)


expose PatchBooPipeline as an api for monolipse

namespace Boojay.Compilation.BoojayPipelines

import Boojay.Compilation.Steps
import Boo.Lang.Compiler.Steps

def PatchBooPipeline(pipeline as Boo.Lang.Compiler.CompilerPipeline):
"""
Patches a boo pipeline to make it work like a boojay one.
"""
	pipeline.Insert(0, InitializeEntityNameMatcher())
	pipeline.InsertAfter(NormalizeTypeAndMemberDefinitions, NormalizeLiterals())
	pipeline.Replace(IntroduceGlobalNamespaces, IntroduceBoojayNamespaces())
	pipeline.Replace(InitializeTypeSystemServices, InitializeJavaTypeSystem())
	pipeline.InsertBefore(NormalizeIterationStatements, NormalizeIterations())

class BoojayCompilation(Boo.Lang.Compiler.Pipelines.Compile):

	def constructor():
		Add(NormalizeCallables())
		Add(PatchCallableConstruction())
		Add(InjectCasts())
		PatchBooPipeline(self)

class ProduceBytecode(BoojayCompilation):

	def constructor():
		Add(BoojayEmitter())

class ProduceBoo(BoojayCompilation):

	def constructor():
		Add(PrintBoo())

namespace Boojay.Compilation.BoojayPipelines

import Boojay.Compilation.Steps
import Boo.Lang.Compiler.Steps

class BoojayCompilation(Boo.Lang.Compiler.Pipelines.Compile):

	def constructor():
		Insert(0, InitializeEntityNameMatcher())
		InsertAfter(NormalizeTypeAndMemberDefinitions, NormalizeLiterals())
		Replace(IntroduceGlobalNamespaces, IntroduceBoojayNamespaces())
		Replace(InitializeTypeSystemServices, InitializeJavaTypeSystem())
		InsertBefore(NormalizeIterationStatements, NormalizeIterations())
		Add(NormalizeCallables())
		Add(PatchCallableConstruction())
		Add(InjectCasts())

class ProduceBytecode(BoojayCompilation):

	def constructor():
		Add(BoojayEmitter())

class ProduceBoo(BoojayCompilation):

	def constructor():
		Add(PrintBoo())


remove unnecessary semicolons

remove unnecessary semicolons

namespace UnityScript.Lang

import System
import System.Collections

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

	def constructor():
		pass

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

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

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

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

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

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

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

	def clear():
		Clear()

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

	def pop():
		return self.Pop()

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

	def shift():
		return self.Shift()

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

	def toString ():
		return ToString()

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

		return arr

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

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

namespace UnityScript.Lang

import System
import System.Collections

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

	def constructor():
		pass

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

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

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

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

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

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

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

	def clear():
		Clear()

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

	def pop():
		return self.Pop()

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

	def shift():
		return self.Shift()

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

	def toString ():
		return ToString()

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

		return arr

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