fixed mixed whitespaces

fixed mixed whitespaces

namespace Boo.OMeta.Parser

import System
import System.Globalization
import Boo.OMeta
import Boo.Lang.PatternMatching
import Boo.Lang.Compiler
import Boo.Lang.Compiler.Ast

def newMacro(name, args, block, m):

	if block isa List:
		node = MacroStatement(Name: tokenValue(name), Body: (block as List)[1], Modifier: m, Documentation: (block as List)[0])
	else:
		node = MacroStatement(Name: tokenValue(name), Body: block, Modifier: m)

	for arg in args: node.Arguments.Add(arg)
	return node

def newSlicing(target as Expression, slices):
	node = SlicingExpression(Target: target)
	for slice in slices: node.Indices.Add(slice)
	return node

def newSlice(begin as Expression, end as Expression, step as Expression):
	return Slice(begin, end, step)

def newRValue(items as List):
	if len(items) > 1: return newArrayLiteral(items)
	return items[0]

def newForStatement(declarations, e as Expression, body as Block, orBlock as Block, thenBlock as Block):
	node = ForStatement(Iterator: e, Block: body, OrBlock: orBlock, ThenBlock: thenBlock)
	for d in declarations: node.Declarations.Add(d)
	return node

def newWhileStatement(condition, body, orBlock, thenBlock):
	node = WhileStatement(Condition: condition, Block: body, OrBlock: orBlock, ThenBlock: thenBlock)
	return node

def newDeclaration(name, type as TypeReference):
	return Declaration(Name: tokenValue(name), Type: type)

def newDeclarationStatement(d as Declaration,  initializer as Expression):
	return DeclarationStatement(Declaration: d, Initializer: initializer)

def newUnpackStatement(declarations, e as Expression, m as StatementModifier):
	stmt = UnpackStatement(Expression: e, Modifier: m)
	for d in declarations: stmt.Declarations.Add(d)
	return stmt

def newTryStatement(protectedBlock as Block, handlers as List, failureBlock as Block, ensureBlock as Block):
	stmt = TryStatement(ProtectedBlock: protectedBlock, FailureBlock: failureBlock, EnsureBlock: ensureBlock)
	if handlers is not null:
		for h as ExceptionHandler in handlers:
			if (h.Declaration is null):
				h.Flags |= ExceptionHandlerFlags.Anonymous
				h.Flags |= ExceptionHandlerFlags.Untyped
			elif h.Declaration.Type is null:
				h.Flags |= ExceptionHandlerFlags.Untyped

			stmt.ExceptionHandlers.Add(h)
	return stmt

def newIfStatement(condition as Expression, trueBlock as Block, falseBlock as Block):
	return IfStatement(Condition: condition, TrueBlock: trueBlock, FalseBlock: falseBlock)

def newCallable(modifiers, name, genericParameters as List, parameters as List, type):
	node = CallableDefinition(Name: tokenValue(name), ReturnType: type)

	#return setUpType(ClassDefinition(Name: tokenValue(name)), attributes, modifiers, genericParameters, baseTypes, members)
	setUpMember(node, null, modifiers)

	if genericParameters is not null:
		for genericParameter in genericParameters:
			node.GenericParameters.Add(genericParameter)

	if parameters[1] is not null: //Check if ParamArray is present
		setUpParameters node, parameters
		node.Parameters.HasParamArray = true
	else:
		setUpParameters node, parameters[0]
	return node

def newModule(ns as string, doc, imports, members, stmts):
	m = Module(Documentation: doc)

	if ns is not null:
		m.Namespace = NamespaceDeclaration(ns)

	for item in imports: m.Imports.Add(item)
	for member in flatten(members):
		if member isa Ast.Attribute:
			m.AssemblyAttributes.Add(member)
		elif member isa MacroStatement:
			m.Globals.Add(member as Statement)
		else:
			m.Members.Add(member)
	for stmt as Statement in stmts: m.Globals.Add(stmt)
	return m

def newImport(qname as string, assembly, alias):
	assemblyReference = null
	if assembly isa Token:
		assemblyReference = ReferenceExpression(Name: tokenValue(assembly))
	else:
		assemblyReference = ReferenceExpression(Name: assembly) if assembly is not null

	importAlias = null
	if alias isa Token:
		importAlias =	ReferenceExpression(Name: tokenValue(alias))
	else:
		importAlias =	ReferenceExpression(Name: alias) if alias is not null

	return Import(qname, AssemblyReference: assemblyReference, Alias: importAlias)

def newInteger(sign, t, style as NumberStyles, suffix):
	s = tokenValue(sign) + tokenValue(t)
	value = long.Parse(s, style)
	result = IntegerLiteralExpression(Value: value)
	if suffix in ["L", "l"]: result.IsLong = true
	return result

def IsValidLong(sign, n):
	s = tokenValue(sign) + tokenValue(n)
	r as long
	return long.TryParse(s, NumberStyles.AllowLeadingSign, null, r)

def IsValidHexLong(sign, n):
	s = tokenValue(sign) + tokenValue(n)
	r as long
	return long.TryParse(s, NumberStyles.HexNumber, null, r)

def newFloat(t):
	value = double.Parse(t)
	return DoubleLiteralExpression(Value: value)

def newEvent(attributes, modifiers, name, type):
	return setUpMember(Event(Name: tokenValue(name), Type: type), attributes, modifiers)

def newField(attributes, modifiers, name, type, initializer):
	return setUpMember(Field(Name: tokenValue(name), Type: type, Initializer: initializer), attributes, modifiers)

def newProperty(attributes, modifiers, name, parameters, type, getter, setter):
	node = Property(Name: tokenValue(name), Type: type, Getter: getter, Setter: setter)
	setUpParameters node, parameters
	return setUpMember(node, attributes, modifiers)

def setUpAttributes(node as INodeWithAttributes, attributes) as Node:
	for a in flatten(attributes):
		node.Attributes.Add(a)
	return node

def setUpMember(member as TypeMember, attributes, modifiers):
	setUpAttributes member, attributes
	for m as TypeMemberModifiers in flatten(modifiers): member.Modifiers |= m
	return member

def setUpParameters(node as INodeWithParameters, parameters):
	for p in flatten(parameters): node.Parameters.Add(p)

def newMethod(attributes, modifiers, name, parameters as List, returnTypeAttributes, returnType as TypeReference, body as Block) as Method:
	node = Method(Name: tokenValue(name), Body: body, ReturnType: returnType)

	if parameters[1] != null: //Check if ParamArray is present
		setUpParameters node, parameters
		node.Parameters.HasParamArray = true
	else:
		setUpParameters node, parameters[0]

	for a in flatten(returnTypeAttributes): node.ReturnTypeAttributes.Add(a)
	return setUpMember(node, attributes, modifiers)

def newGenericMethod(attributes, modifiers, name, genericParameters, parameters as List, returnTypeAttributes, returnType as TypeReference, body as Block):
	node = newMethod(attributes, modifiers, name, parameters, returnTypeAttributes, returnType, body)
	for gp in flatten(genericParameters): node.GenericParameters.Add(gp)
	return node

def newConstructor(attributes, modifiers, genericParameters, parameters as List, body as Block):
	node = Constructor(Name: "constructor", Body: body)

	if parameters[1] != null: //Check if ParamArray is present
		setUpParameters node, parameters
		node.Parameters.HasParamArray = true
	else:
		setUpParameters node, parameters[0]

	setUpMember(node, attributes, modifiers)

	for gp in flatten(genericParameters): node.GenericParameters.Add(gp)
	return node

def newGenericTypeReference(qname, args):
	node = GenericTypeReference(Name: qname)
	for arg in flatten(args): node.GenericArguments.Add(arg)
	return node

def newGenericTypeDefinitionReference(qname, placeholders as List):
	return GenericTypeDefinitionReference(Name: qname,  GenericPlaceholders: placeholders.Count)

def newGenericParameterDeclaration(name, constraints):
	node = GenericParameterDeclaration(Name: tokenValue(name))

	if constraints is not null:
		for constraint in constraints:
			if constraint isa TypeReference:
				node.BaseTypes.Add(constraint)
			else:
				node.Constraints |= cast(GenericParameterConstraints, constraint)

	return node

def newParameterDeclaration(attributes, name, type):
	node = ParameterDeclaration(Name: tokenValue(name), Type: type)
	return setUpAttributes(node, attributes)

def newEnum(attributes, modifiers, name, members):
	return setUpType(EnumDefinition(Name: tokenValue(name)), attributes, modifiers, null, null, members)

def newCallableTypeReference(params, paramArray, type):
	node = CallableTypeReference(ReturnType: type)
	i = 0
	for p in flatten(params):
		node.Parameters.Add(ParameterDeclaration(Name: "arg${i++}", Type: p))

	if paramArray is not null:
		node.Parameters.Add(paramArray)
		node.Parameters.HasParamArray = true
	return node

def newStatementModifier(t, e as Expression):
	return StatementModifier(Type: t, Condition: e)

def newGeneratorExpressionBody(dl, e, f):
	node = GeneratorExpression(Iterator: e, Filter: f)
	for d in flatten(dl): node.Declarations.Add(d)
	return node

def newGeneratorExpression(projection, body as List):
	node as GeneratorExpression = body[0]
	node.Expression = projection
	if len(body) == 1: return node

	e = ExtendedGeneratorExpression()
	for item in body: e.Items.Add(item)
	return e

def newEnumField(attributes, name, initializer):
	match initializer:
		case [| -$(e=IntegerLiteralExpression()) |]:
			e.Value *= -1
			initializer = e
		otherwise:
			pass
	return setUpMember(EnumMember(Name: tokenValue(name), Initializer: initializer), attributes, null)

def newClass(attributes, modifiers, name, genericParameters, baseTypes, members):
	return setUpType(ClassDefinition(Name: tokenValue(name)), attributes, modifiers, genericParameters, baseTypes, members)

def newStruct(attributes, modifiers, name, genericParameters, baseTypes, members):
	return setUpType(StructDefinition(Name: tokenValue(name)), attributes, modifiers, genericParameters, baseTypes, members)

def setUpType(type as TypeDefinition, attributes, modifiers, genericParameters, baseTypes, members):
	if members is not null:
		for member in members: type.Members.Add(member)
	if baseTypes is not null:
		for baseType in baseTypes: type.BaseTypes.Add(baseType)
	if genericParameters is not null:
		for genericParameter in genericParameters: type.GenericParameters.Add(genericParameter)

	return setUpMember(type, attributes, modifiers)

macro setUpArgs:
	node, args = setUpArgs.Arguments
	code = [|
		if $args is not null:
			for arg in $args:
				if arg isa ExpressionPair:
					$node.NamedArguments.Add(arg)
				else:
					$node.Arguments.Add(arg)
	|]
	return code

def newAttribute(name, args):
	node = Ast.Attribute(Name: name)
	setUpArgs node, args
	return node

def newNamedArgument(name, value):
	return ExpressionPair(First: newReference(name), Second: value)

def newInterface(attributes, modifiers, name, genericParameters, baseTypes, members):
	return setUpType(InterfaceDefinition(Name: tokenValue(name)), attributes, modifiers, genericParameters, baseTypes, members)

def newInvocation(target as Expression, args as List, genericArgs as object):

	if genericArgs is not null:
		target = GenericReferenceExpression(Target: target)
		for arg in genericArgs:
			(target as GenericReferenceExpression).GenericArguments.Add(arg)

	mie = MethodInvocationExpression(Target: target)

	setUpArgs mie, flattenNoNulls(args)
	return mie

def newQuasiquoteBlock(m):
	return QuasiquoteExpression(Node: m)

def newQuasiquoteExpression(s):
	return QuasiquoteExpression(Node: s)

def newReference(t):
	return ReferenceExpression(Name: tokenValue(t))

def newMemberReference(target as Expression, name):
	return MemberReferenceExpression(Target: target, Name: tokenValue(name))

def newArrayLiteral(type, items):
	node = newArrayLiteral(items)
	node.Type = type
	return node

def newArrayLiteral(items):
	literal = ArrayLiteralExpression()
	for item in items:
		literal.Items.Add(item)
	return literal

def newListLiteral(items):
	literal = ListLiteralExpression()
	for item in items: literal.Items.Add(item)
	return literal

def newHashLiteral(items):
	literal = HashLiteralExpression()
	for item in items: literal.Items.Add(item)
	return literal

def newStringLiteral(s):
	return StringLiteralExpression(Value: s)

def newStringInterpolation(items as List):
	if len(items) == 0: return StringLiteralExpression("")
	if len(items) == 1 and items[0] isa StringLiteralExpression:
		return items[0]
	node = ExpressionInterpolationExpression()
	for item in items: node.Expressions.Add(item)
	return node

def newConditionalExpression(condition, trueValue, falseValue):
	return ConditionalExpression(Condition: condition, TrueValue: trueValue, FalseValue: falseValue)

def newBlockExpression(parameters as List, body):
	node = BlockExpression(Body: body)
	for p in parameters[0]:
		node.Parameters.Add(p)
	return node

def newTypeofExpression(type):
	return TypeofExpression(Type: type)

def newInvocationWithBlock(invocation as MethodInvocationExpression, block as BlockExpression):
	node = invocation.CloneNode()
	node.Arguments.Add(block)
	return node

def newInfixExpression(op, l as Expression, r as Expression):
	return BinaryExpression(Operator: binaryOperatorFor(op), Left: l, Right: r)

def newPrefixExpression(op, e as Expression):
	return UnaryExpression(Operator: unaryOperatorFor(op), Operand: e)

def newSuffixExpression(op, e as Expression):
	return UnaryExpression(Operator: unarySuffixOperatorFor(op), Operand: e)

def addSuffixUnaryOperator(e, postOp):
	return e if postOp is null
	return UnaryExpression(Operator: unarySuffixOperatorFor(postOp), Operand: e)

def unaryOperatorFor(op):
	match tokenValue(op):
		case "not": return UnaryOperatorType.LogicalNot
		case "-": return UnaryOperatorType.UnaryNegation
		case "~": return UnaryOperatorType.OnesComplement
		case "++": return UnaryOperatorType.Increment
		case "--": return UnaryOperatorType.Decrement
		case "*": return UnaryOperatorType.Explode

def unarySuffixOperatorFor(op):
	match tokenValue(op):
		case "++": return UnaryOperatorType.PostIncrement
		case "--": return UnaryOperatorType.PostDecrement

def binaryOperatorFor(op):
	match tokenValue(op):
		case "is": return BinaryOperatorType.ReferenceEquality
		case "isa": return BinaryOperatorType.TypeTest
		case "is not": return BinaryOperatorType.ReferenceInequality
		case "in": return BinaryOperatorType.Member
		case "not in": return BinaryOperatorType.NotMember
		case "and": return BinaryOperatorType.And
		case "or": return BinaryOperatorType.Or
		case "|": return BinaryOperatorType.BitwiseOr
		case "&": return BinaryOperatorType.BitwiseAnd
		case "^": return BinaryOperatorType.ExclusiveOr
		case "+": return BinaryOperatorType.Addition
		case "-": return BinaryOperatorType.Subtraction
		case "*": return BinaryOperatorType.Multiply
		case "**": return BinaryOperatorType.Exponentiation
		case "/": return BinaryOperatorType.Division
		case "%": return BinaryOperatorType.Modulus
		case "=": return BinaryOperatorType.Assign
		case "==": return BinaryOperatorType.Equality
		case "!=": return BinaryOperatorType.Inequality
		case "+=": return BinaryOperatorType.InPlaceAddition
		case "-=": return BinaryOperatorType.InPlaceSubtraction
		case "/=": return BinaryOperatorType.InPlaceDivision
		case "*=": return BinaryOperatorType.InPlaceMultiply
		case "^=": return BinaryOperatorType.InPlaceExclusiveOr
		case "&=": return BinaryOperatorType.InPlaceBitwiseAnd
		case "|=": return BinaryOperatorType.InPlaceBitwiseOr
		case ">>": return BinaryOperatorType.ShiftRight
		case "<<": return BinaryOperatorType.ShiftLeft
		case "<": return BinaryOperatorType.LessThan
		case "<=": return BinaryOperatorType.LessThanOrEqual
		case ">": return BinaryOperatorType.GreaterThan
		case ">=": return BinaryOperatorType.GreaterThanOrEqual
		case ">>=": return BinaryOperatorType.InPlaceShiftRight
		case "<<=": return BinaryOperatorType.InPlaceShiftLeft

def newAssignment(l as Expression, r as Expression):
	return [| $l = $r |]

def newBlock(contents, doc):
	b = Block()
	match contents:
		case Statement():
			b.Statements.Add(contents)
		otherwise:
			for item in contents:
				if item:
					b.Statements.Add(item)
	b.Documentation  = doc
	return b

def prepend(first, tail as List):
	if first is null: return tail
	return [first] + tail

def buildQName(q, rest):
	return join(tokenValue(t) for t in prepend(q, rest), '.')

def newGenericParameterConstraint(constraint):
	match tokenValue(constraint):
		case "class": return GenericParameterConstraints.ReferenceType
		case "struct": return GenericParameterConstraints.ValueType
		case "constructor": return GenericParameterConstraints.Constructable

def newGotoStatement(label, modifier):
	return GotoStatement(Label: ReferenceExpression(Name: tokenValue(label)), Modifier: modifier)

def getUnicodeChar(hex):
	return cast(char, int.Parse(flatString(hex), System.Globalization.NumberStyles.HexNumber))

def newTimeSpanLiteral(n, tu):
	value as double = 0
	if n isa IntegerLiteralExpression:
		value = (n as IntegerLiteralExpression).Value
	else:
		value = (n as DoubleLiteralExpression).Value

	match tu:
		case 'ms': return TimeSpanLiteralExpression(Value:TimeSpan.FromMilliseconds(value))
		case 's': return TimeSpanLiteralExpression(Value:TimeSpan.FromSeconds(value))
		case 'h': return TimeSpanLiteralExpression(Value:TimeSpan.FromHours(value))
		case 'm': return TimeSpanLiteralExpression(Value:TimeSpan.FromMinutes(value))
		case 'd': return TimeSpanLiteralExpression(Value:TimeSpan.FromDays(value))

def newUnlessStatement(condition, block):
	return UnlessStatement(Block: block, Condition: condition)

def newCollectionInitialization(collection, initializer):
	return CollectionInitializationExpression(Collection: collection, Initializer: initializer)

def checkEnumerableTypeShortcut(type, stars as List):
	if stars is null:
		return type

	enumerable = type
	for star in stars:
		enumerable = GenericTypeReference(Name: "System.Collections.Generic.IEnumerable")
		(enumerable as GenericTypeReference).GenericArguments.Add(type)
		type = enumerable
	return enumerable


CompilerContext.$X => my($X)

CompilerContext.$X => my($X)

namespace Boojay.Compilation.Steps

import Boo.Lang.Compiler
import Boo.Lang.Compiler.TypeSystem
import Boo.Lang.Compiler.TypeSystem.Services
import Boo.Lang.Compiler.Ast

import Boo.Lang.Environments
import Boo.Lang.PatternMatching

def resolveRuntimeMethod(methodName as string):
	return resolveMethod(typeSystem().RuntimeServicesType, methodName)

def resolveMethod(type as IType, name as string):
	return nameResolutionService().ResolveMethod(type, name)

def bindingFor(node as Node):
	return typeSystem().GetEntity(node)

def bindingFor(node as Method) as IMethod:
	return typeSystem().GetEntity(node)

def erasureFor(type as IType):
	if type isa IGenericParameter:
		return typeSystem().ObjectType

#	genericInstance = type.ConstructedInfo
#	if genericInstance is not null:
#		return genericInstance.GenericDefinition

	return type

def isJavaLangObject(type as IType):
	if typeSystem().IsSystemObject(type):
		return true
	return type is Null.Default

def definitionFor(m as IMethodBase) as IMethodBase:
	if m.DeclaringType.ConstructedInfo is null:
		return m
	return Boojay.Compilation.TypeSystem.GenericMethodDefinitionFinder(m).find()

def typeOf(e as Expression) as IType:
	match e:
		case [| null |]:
			return Null.Default
		case [| true |] | [| false |]:
			return typeSystem().BoolType
		otherwise:
			return typeSystem().GetExpressionType(e)

def typeSystem():
	return my(TypeSystemServices)

def nameResolutionService():
	return my(NameResolutionService)

def context():
	return CompilerContext.Current

def uniqueName():
	return context().GetUniqueName("$")

def uniqueReference():
	return ReferenceExpression(uniqueName())

namespace Boojay.Compilation.Steps

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

def resolveRuntimeMethod(methodName as string):
	return resolveMethod(typeSystem().RuntimeServicesType, methodName)

def resolveMethod(type as IType, name as string):
	return nameResolutionService().ResolveMethod(type, name)

def bindingFor(node as Node):
	return typeSystem().GetEntity(node)

def bindingFor(node as Method) as IMethod:
	return typeSystem().GetEntity(node)

def erasureFor(type as IType):
	if type isa IGenericParameter:
		return typeSystem().ObjectType

#	genericInstance = type.ConstructedInfo
#	if genericInstance is not null:
#		return genericInstance.GenericDefinition

	return type

def isJavaLangObject(type as IType):
	if typeSystem().IsSystemObject(type):
		return true
	return type is Null.Default

def definitionFor(m as IMethodBase) as IMethodBase:
	if m.DeclaringType.ConstructedInfo is null:
		return m
	return Boojay.Compilation.TypeSystem.GenericMethodDefinitionFinder(m).find()

def typeOf(e as Expression) as IType:
	match e:
		case [| null |]:
			return Null.Default
		case [| true |] | [| false |]:
			return typeSystem().BoolType
		otherwise:
			return typeSystem().GetExpressionType(e)

def typeSystem():
	return context().TypeSystemServices

def nameResolutionService():
	return context().NameResolutionService

def context():
	return CompilerContext.Current

def uniqueName():
	return context().GetUniqueName("$")

def uniqueReference():
	return ReferenceExpression(uniqueName())


always set Environment.ExitCode

always set Environment.ExitCode

git-svn-id: fcce7d6ce0ac15bf24f68871b5145d46fc068279@3397 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 booi

import System
import System.IO
import System.Reflection
import Boo.Lang.Compiler
import Boo.Lang.Compiler.IO
import Boo.Lang.Compiler.Pipelines
import Useful.Attributes

class Program:

	public static final DefaultErrorCode = 127
	public static final DefaultSuccessCode = 0

	_cmdLine as (string)
	_assemblyResolver = AssemblyResolver()
	_compiler = BooCompiler()
	_printWarnings = false

	def constructor(cmdLine as (string)):
		_cmdLine = cmdLine
		_compiler.Parameters.Pipeline = CompileToMemory()

	def run():
		installAssemblyResolver()
		consumedArguments = processCommandLine()
		assembly = compile()
		if assembly is null: return DefaultErrorCode
		return execute(assembly, _cmdLine[consumedArguments:])

	def compile():
		result = _compiler.Run()
		if _printWarnings and len(result.Warnings):
			print(result.Warnings.ToString())
		if len(result.Errors):
			print(result.Errors.ToString(true))
			return null
		return result.GeneratedAssembly

	def execute(generatedAssembly as Assembly, argv as (string)):

		Environment.ExitCode = exitCode = DefaultSuccessCode

		try:
			_assemblyResolver.AddAssembly(generatedAssembly)
			main = generatedAssembly.EntryPoint
			if len(main.GetParameters()) > 0:
				returnValue = main.Invoke(null, (argv,))
			else:
				returnValue = main.Invoke(null, null)
			exitCode = returnValue if returnValue is not null
		except x as TargetInvocationException:
			print(x.InnerException)
			exitCode = DefaultErrorCode
		ensure:
			Environment.ExitCode = exitCode

		return exitCode

	def processCommandLine():
		consumedArgs = 1
		for arg in _cmdLine:
			if "-" == arg:
				_compiler.Parameters.Input.Add(StringInput("<stdin>", consume(Console.In)))
				break
			elif "-ducky" == arg:
				_compiler.Parameters.Ducky = true
			elif "-wsa" == arg:
				_compiler.Parameters.Pipeline[0] = Boo.Lang.Parser.WSABooParsingStep()
			elif "-w" == arg:
				_printWarnings = true
			elif arg.StartsWith("-r:"):
				try:
					asm = _compiler.Parameters.LoadAssembly(arg[3:])
					if asm is null:
						print Boo.Lang.ResourceManager.Format("BooC.UnableToLoadAssembly", arg[3:])
					else:
						_compiler.Parameters.References.Add(asm)
						_assemblyResolver.AddAssembly(asm)
				except e:
					print e.Message
			else:
				_compiler.Parameters.Input.Add(FileInput(translatePath(arg)))
				break
			++consumedArgs
		return consumedArgs

	def translatePath(path as string):
		if isCygwin(): 	return translateCygwinPath(path)
		return path

	[once]
	def isCygwin():
		return Environment.GetEnvironmentVariable("TERM") == "cygwin"

	def translateCygwinPath(path as string):
		if not path.StartsWith("/"): return path
		if path.StartsWith("/cygdrive"):
			path = path[len("/cygdrive/"):]
			driveLetter = path[0]
			return driveLetter + ":" + path[1:]
		return Path.Combine(cygwinRoot(), path[1:])

	[once]
	def cygwinRoot():
		home = Environment.GetEnvironmentVariable("HOME")
		assert home is not null
		return home[:home.IndexOf("\\home")]

	def installAssemblyResolver():
		AppDomain.CurrentDomain.AssemblyResolve += _assemblyResolver.AssemblyResolve

def consume(reader as TextReader):
	return join(line for line in reader, "\n")

[STAThread]
def Main(argv as (string)) as int:

	if len(argv) < 1:
		print("booi <script.boo>")
		return Program.DefaultErrorCode

	return Program(argv).run();

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

import System
import System.IO
import System.Reflection
import Boo.Lang.Compiler
import Boo.Lang.Compiler.IO
import Boo.Lang.Compiler.Pipelines
import Useful.Attributes

class Program:

	public static final DefaultErrorCode = 127
	public static final DefaultSuccessCode = 0

	_cmdLine as (string)
	_assemblyResolver = AssemblyResolver()
	_compiler = BooCompiler()
	_printWarnings = false

	def constructor(cmdLine as (string)):
		_cmdLine = cmdLine
		_compiler.Parameters.Pipeline = CompileToMemory()

	def run():
		installAssemblyResolver()
		consumedArguments = processCommandLine()
		assembly = compile()
		if assembly is null: return DefaultErrorCode
		return execute(assembly, _cmdLine[consumedArguments:])

	def compile():
		result = _compiler.Run()
		if _printWarnings and len(result.Warnings):
			print(result.Warnings.ToString())
		if len(result.Errors):
			print(result.Errors.ToString(true))
			return null
		return result.GeneratedAssembly

	def execute(generatedAssembly as Assembly, argv as (string)):
		try:
			_assemblyResolver.AddAssembly(generatedAssembly)
			main = generatedAssembly.EntryPoint
			Environment.ExitCode = DefaultSuccessCode
			if len(main.GetParameters()) > 0:
				returnValue = main.Invoke(null, (argv,))
			else:
				returnValue = main.Invoke(null, null)
			Environment.ExitCode = returnValue if returnValue is not null
		except x as TargetInvocationException:
			print(x.InnerException)
			return DefaultErrorCode

		return Environment.ExitCode

	def processCommandLine():
		consumedArgs = 1
		for arg in _cmdLine:
			if "-" == arg:
				_compiler.Parameters.Input.Add(StringInput("<stdin>", consume(Console.In)))
				break
			elif "-ducky" == arg:
				_compiler.Parameters.Ducky = true
			elif "-wsa" == arg:
				_compiler.Parameters.Pipeline[0] = Boo.Lang.Parser.WSABooParsingStep()
			elif "-w" == arg:
				_printWarnings = true
			elif arg.StartsWith("-r:"):
				try:
					asm = _compiler.Parameters.LoadAssembly(arg[3:])
					if asm is null:
						print Boo.Lang.ResourceManager.Format("BooC.UnableToLoadAssembly", arg[3:])
					else:
						_compiler.Parameters.References.Add(asm)
						_assemblyResolver.AddAssembly(asm)
				except e:
					print e.Message
			else:
				_compiler.Parameters.Input.Add(FileInput(translatePath(arg)))
				break
			++consumedArgs
		return consumedArgs

	def translatePath(path as string):
		if isCygwin(): 	return translateCygwinPath(path)
		return path

	[once]
	def isCygwin():
		return Environment.GetEnvironmentVariable("TERM") == "cygwin"

	def translateCygwinPath(path as string):
		if not path.StartsWith("/"): return path
		if path.StartsWith("/cygdrive"):
			path = path[len("/cygdrive/"):]
			driveLetter = path[0]
			return driveLetter + ":" + path[1:]
		return Path.Combine(cygwinRoot(), path[1:])

	[once]
	def cygwinRoot():
		home = Environment.GetEnvironmentVariable("HOME")
		assert home is not null
		return home[:home.IndexOf("\\home")]

	def installAssemblyResolver():
		AppDomain.CurrentDomain.AssemblyResolve += _assemblyResolver.AssemblyResolve

def consume(reader as TextReader):
	return join(line for line in reader, "\n")

[STAThread]
def Main(argv as (string)) as int:

	if len(argv) < 1:
		print("booi <script.boo>")
		return Program.DefaultErrorCode

	return Program(argv).run();


use generic types whenever possible

use generic types whenever possible

namespace UnityScript.Lang

import System
import System.Collections.Generic

internal class Expando:

	_target as WeakReference
	_attributes = Dictionary[of string, object]()

	def constructor(target):
		_target = WeakReference(target)

	Target:
		get: return _target.Target

	Item[key as string]:
		get: return _attributes[key]

		set:
			if value is null:
				_attributes.Remove(key)
			else:
				_attributes[key] = value

static class ExpandoServices:

	_expandos = List[of Expando]()

	def GetExpandoProperty(target, name as string):
		expando = GetExpandoFor(target)
		if expando is null: return null
		return expando.Item[name]

	def SetExpandoProperty(target, name as string, value):
		expando = GetOrCreateExpandoFor(target)
		expando.Item[name] = value
		return value

	[lock(_expandos)]
	def GetExpandoFor(o) as Expando:
		Purge()
		return _expandos.Find({ e as Expando | e.Target is o })

	[lock(_expandos)]
	def GetOrCreateExpandoFor(o):
		e = GetExpandoFor(o)
		if e is null:
			e = Expando(o)
			_expandos.Add(e)
		return e

	ExpandoObjectCount:
		get:
			Purge()
			return len(_expandos)

	[lock(_expandos)]
	def Purge():
		_expandos.RemoveAll({ e as Expando | e.Target is null })

namespace UnityScript.Lang

import System
import System.Collections

internal class Expando:

	_target as WeakReference
	_attributes = Hashtable()

	def constructor(target):
		_target = WeakReference(target)

	Target:
		get: return _target.Target

	Item[key]:
		get:
			return _attributes[key]

		set:
			if value is null:
				_attributes.Remove(key)
			else:
				_attributes[key] = value

static class ExpandoServices:

	_expandos = List()

	def GetExpandoProperty(target, name as string):
		expando = GetExpandoFor(target)
		if expando is null: return null
		return expando.Item[name]

	def SetExpandoProperty(target, name as string, value):
		expando = GetOrCreateExpandoFor(target)
		expando.Item[name] = value
		return value

	[lock(_expandos)]
	def GetExpandoFor(o) as Expando:
		Purge()
		return _expandos.Find({ e as Expando | e.Target is o })

	[lock(_expandos)]
	def GetOrCreateExpandoFor(o):
		e = GetExpandoFor(o)
		if e is null:
			e = Expando(o)
			_expandos.Add(e)
		return e

	ExpandoObjectCount:
		get:
			Purge()
			return len(_expandos)

	[lock(_expandos)]
	def Purge():
		_expandos.RemoveAll({ e as Expando | e.Target is null })


unused import

unused import

namespace Boojay.Compilation.Tests

import System
import System.IO

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

import Boojay.Compilation
import Boojay.Compilation.TypeSystem

static class JavaClassRunner:
	def run(className as string, *jars as (string)):
		classPath = (ProjectFolders.binFolder(), ProjectFolders.distFolder() + "/boojay.lang.jar") + jars

		exitCode as int, output, error as string = runp("java", "-cp ${quote(join(classPath, Path.PathSeparator))} ${className}")

		if exitCode != 0: raise output + "\n" + error
		return output

	def runp(filename as string, arguments as string):
		p = System.Diagnostics.Process()
		p.StartInfo.Arguments = arguments
		p.StartInfo.CreateNoWindow = true
		p.StartInfo.UseShellExecute = false
		p.StartInfo.RedirectStandardOutput = true
		p.StartInfo.RedirectStandardInput = true
		p.StartInfo.RedirectStandardError = true
		p.StartInfo.FileName = filename

		result = ""
		p.OutputDataReceived += def(sender, e as System.Diagnostics.DataReceivedEventArgs):
			result += e.Data + "\n"

		p.Start()
		p.BeginOutputReadLine()
		p.WaitForExit()

		exitCode = p.ExitCode
		error = p.StandardError.ReadToEnd()

		p.Close()

		return (exitCode, result, error)

static class ProjectFolders:
	def binFolder():
		return Path.GetFullPath(Path.Combine(testParentFolder(), "bin"))

	def distFolder():
		return Path.GetFullPath(Path.Combine(testParentFolder(), "dist"))

	def testParentFolder():
		folder = "."
		while not Directory.Exists(Path.Combine(folder, "tests")):
			folder = Path.Combine(folder, "..")
			assert Directory.Exists(folder)
		return folder

def generateTempJarWith(code as Module):
	jar = Path.GetTempFileName()
	boojayCompile(CompileUnit(code))
	generateJar(jar, "${type.FullName.Replace('.', '/')}.class" for type in code.Members)
	return jar

def booCompile(unit as CompileUnit):
	booCompile(unit, List[of ICompileUnit]())

def booCompile(unit as CompileUnit, *refs as (ICompileUnit)):
	compiler = newBooCompiler()
	result = compiler.Run(unit)
	assert 0 == len(result.Errors), result.Errors.ToString(true) + unit.ToCodeString()

def newBooCompiler():
	compiler = BooCompiler(CompilerParameters(true))
	compiler.Parameters.OutputType = CompilerOutputType.Auto
	compiler.Parameters.Pipeline = Boo.Lang.Compiler.Pipelines.CompileToMemory()

	return compiler

def runTestWithJar(test as Module, jar as Module):
	generatedJar = generateTempJarWith(jar)
	jarCompileUnit = JarTypeSystemProvider().ForJar(generatedJar)
	unit = CompileUnit(test)
	try:
		boojayCompile(unit, jarCompileUnit)
		className = moduleClassFor(test)
		print JavaClassRunner.run(className, Path.GetFullPath(generatedJar))
	except e:
		raise e.ToString() + unit.ToCodeString()

def moduleClassFor(module as Module):
	return module.FullName.Replace("-", "_").Replace("$", "_") + "Module"

def quote(arg as string):
	return '"' + arg + '"'

namespace Boojay.Compilation.Tests

import System
import System.IO
import System.Diagnostics

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

import Boojay.Compilation
import Boojay.Compilation.TypeSystem

static class JavaClassRunner:
	def run(className as string, *jars as (string)):
		classPath = (ProjectFolders.binFolder(), ProjectFolders.distFolder() + "/boojay.lang.jar") + jars

		exitCode as int, output, error as string = runp("java", "-cp ${quote(join(classPath, Path.PathSeparator))} ${className}")

		if exitCode != 0: raise output + "\n" + error
		return output

	def runp(filename as string, arguments as string):
		p = System.Diagnostics.Process()
		p.StartInfo.Arguments = arguments
		p.StartInfo.CreateNoWindow = true
		p.StartInfo.UseShellExecute = false
		p.StartInfo.RedirectStandardOutput = true
		p.StartInfo.RedirectStandardInput = true
		p.StartInfo.RedirectStandardError = true
		p.StartInfo.FileName = filename

		result = ""
		p.OutputDataReceived += def(sender, e as System.Diagnostics.DataReceivedEventArgs):
			result += e.Data + "\n"

		p.Start()
		p.BeginOutputReadLine()
		p.WaitForExit()

		exitCode = p.ExitCode
		error = p.StandardError.ReadToEnd()

		p.Close()

		return (exitCode, result, error)

static class ProjectFolders:
	def binFolder():
		return Path.GetFullPath(Path.Combine(testParentFolder(), "bin"))

	def distFolder():
		return Path.GetFullPath(Path.Combine(testParentFolder(), "dist"))

	def testParentFolder():
		folder = "."
		while not Directory.Exists(Path.Combine(folder, "tests")):
			folder = Path.Combine(folder, "..")
			assert Directory.Exists(folder)
		return folder

def generateTempJarWith(code as Module):
	jar = Path.GetTempFileName()
	boojayCompile(CompileUnit(code))
	generateJar(jar, "${type.FullName.Replace('.', '/')}.class" for type in code.Members)
	return jar

def booCompile(unit as CompileUnit):
	booCompile(unit, List[of ICompileUnit]())

def booCompile(unit as CompileUnit, *refs as (ICompileUnit)):
	compiler = newBooCompiler()
	result = compiler.Run(unit)
	assert 0 == len(result.Errors), result.Errors.ToString(true) + unit.ToCodeString()

def newBooCompiler():
	compiler = BooCompiler(CompilerParameters(true))
	compiler.Parameters.OutputType = CompilerOutputType.Auto
	compiler.Parameters.Pipeline = Boo.Lang.Compiler.Pipelines.CompileToMemory()

	return compiler

def runTestWithJar(test as Module, jar as Module):
	generatedJar = generateTempJarWith(jar)
	jarCompileUnit = JarTypeSystemProvider().ForJar(generatedJar)
	unit = CompileUnit(test)
	try:
		boojayCompile(unit, jarCompileUnit)
		className = moduleClassFor(test)
		print JavaClassRunner.run(className, Path.GetFullPath(generatedJar))
	except e:
		raise e.ToString() + unit.ToCodeString()

def moduleClassFor(module as Module):
	return module.FullName.Replace("-", "_").Replace("$", "_") + "Module"

def quote(arg as string):
	return '"' + arg + '"'


Extend => AddRange

Extend => AddRange

namespace Boo.Adt

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

macro data:
"""
Produces a complete data type hierarchy from a declaration.

All the types produced are immutable (unless instructed otherwise) and have
meaningful implementations for Equals, GetHashCode and ToString.

Usage:

	data Expression = Const(Value as int) | Add(Left, Right) // omitted types assumed to be Expression

	data SingleValue(Value as int)

	data TypeWithMutableField(@MutableValue as int) // @ makes the field mutable
"""

	DataMacroExpansion(data)

class DataMacroExpansion:

	_module as TypeDefinition
	_superType as TypeDefinition
	_superTypeRef as TypeReference
	_defaultTypeRef as TypeReference

	def constructor(node as MacroStatement):

		assert 1 == len(node.Arguments)
		_module = enclosingModule(node)

		match node.Arguments[0]:
			case [| $left = $right |]:
				assert node.Body.IsEmpty
				_superType = createBaseType(left)
				expandDataConstructors(right)

			case [| $(ctor=MethodInvocationExpression()) < $(superCtor=MethodInvocationExpression()) |]:
				_defaultTypeRef = SimpleTypeReference("object")
				_superType = ClassDefinition()
				_superTypeRef = TypeReference.Lift(superCtor.Target)
				expandDataConstructorWithSuperCtor(ctor, superCtor, node.Body)

			case [| $(ctor=MethodInvocationExpression()) < $superType |]:
				_superTypeRef = TypeReference.Lift(superType)
				_superType = ClassDefinition()
				expandDataConstructorWithBody(ctor, node.Body)

			case ctor=MethodInvocationExpression():
				_superType = [|
					class object:
						pass
				|]
				expandDataConstructorWithBody(ctor, node.Body)

	def createBaseType(node as Expression):
		type = superTypeForExpression(node)
		type.LexicalInfo = node.LexicalInfo
		registerType(type)
		return type

	def abstractType(name as string):
		type = [|
			partial abstract class $name:
				pass
		|]
		return type

	def superTypeForExpression(node as Expression):
		match node:
			case ReferenceExpression(Name: name):
				return abstractType(name)

			case [| $(ReferenceExpression(Name: name)) < $(ReferenceExpression(Name: superType)) |]:
				type = [|
					partial abstract class $name($superType):
						pass
				|]
				return type

			case mie=MethodInvocationExpression(Target: ReferenceExpression(Name: name)):
				type = abstractType(name)
				fields = fieldsFrom(mie)
				type.Members.AddRange(fields)
				type.Members.Add(constructorForFields(fields))
				return type

			case gre=SlicingExpression(
						Target: ReferenceExpression(Name: name)):
				type = [|
					partial abstract class $name[of T]:
						pass
				|]
				type.GenericParameters.Clear()
				for index in gre.Indices:
					match index:
						case Slice(
							Begin: ReferenceExpression(Name: name),
							End: null,
							Step: null):
							type.GenericParameters.Add(
								GenericParameterDeclaration(Name: name))
				return type

	def expandDataConstructors(node as Expression):
		match node:
			case [| $left | $right |]:
				expandDataConstructors(left)
				expandDataConstructors(right)
			case MethodInvocationExpression():
				expandDataConstructor(node)

	def expandDataConstructorWithBody(ctor as Expression, body as Block):
		expandDataConstructor(ctor).Members.AddRange(TypeMember.Lift(body))

	def expandDataConstructorWithSuperCtor(ctor as Expression, superCtor as Expression, body as Block):
		superFields = fieldsFrom(superCtor)
		superFieldNames = array(f.Name for f in superFields)
		ctorFields = fieldsFrom(ctor)
		fields = array(f for f in ctorFields if f.Name not in superFieldNames)
		expandDataConstructorWithFields(ctor, ctorFields, fields, superFields).Members.AddRange(TypeMember.Lift(body))

	def expandDataConstructor(node as MethodInvocationExpression):
		fields = fieldsFrom(node)
		superFields = fieldsOf(_superType).ToArray()
		ctorFields = superFields + fields
		return expandDataConstructorWithFields(node, ctorFields, fields, superFields)

	def expandDataConstructorWithFields(node as MethodInvocationExpression, ctorFields as (Field), fields as (Field), superFields as Field*):
		type = dataConstructorTypeForExpression(node.Target)
		type.LexicalInfo = node.LexicalInfo
		type.Members.AddRange(fields)
		type.Members.Add(toStringForType(type))
		type.Members.Add(equalsForType(type))

		ctor = constructorDeclarationFor(ctorFields)
		for field in fields: ctor.Body.Add([| self.$(field.Name) = $field |])
		addSuperInvocationTo ctor, superFields

		type.Members.Add(ctor)
		for ctor in constructorsWithDefaultValues(fields):
			type.Members.Add(ctor)

		registerType(type)
		return type

	def addSuperInvocationTo(ctor as Constructor, superFields as Field*):
		superInvocation = [| super() |]
		for field in superFields:
			superInvocation.Arguments.Add(ReferenceExpression(field.Name))
		ctor.Body.Insert(0, superInvocation)

	def dataConstructorTypeForExpression(node as Expression):
		match node:
			case ReferenceExpression(Name: name):
				type = [|
					partial class $name($(superTypeRef())):
						pass
				|]
				for arg in _superType.GenericParameters:
					type.GenericParameters.Add(
								GenericParameterDeclaration(Name: arg.Name))
				return type

	def equalsForType(type as TypeDefinition):

		allFields = List(fieldsIncludingBaseType(type))
		if len(allFields) == 0:
			method = [|
				override def Equals(o):
					if o is null: return false
					return self.GetType() is o.GetType()
			|]
			return method

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

		for field as Field in allFields:
			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 fieldsIncludingBaseType(type):
			if comma: items.Add([| ", " |])
			items.Add(toStringForField(field))

			comma = true

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

	def toStringForField(field as Field):
		return [| Boo.Adt.adtFieldToString(self.$(field.Name)) |]

	def fieldsIncludingBaseType(type as TypeDefinition):
		return fieldsOf(_superType).Concat(fieldsOf(type))

	def fieldsOf(type as TypeDefinition):
		return type.Members.OfType of Field()

	def constructorForFields(fields as (Field)):
		ctor = constructorDeclarationFor(fields)
		for p in ctor.Parameters:
			ctor.Body.Add([| self.$(p.Name) = $p |])
		return ctor

	def constructorDeclarationFor(fields as (Field)):
		ctor = [|
			def constructor():
				pass
		|]
		for f in fields:
			ctor.Parameters.Add(ParameterDeclaration(Name: f.Name, Type: f.Type))
		ctor.Parameters.HasParamArray = len(fields) > 0 and fields[-1].ContainsAnnotation("*")
		return ctor

	def constructorsWithDefaultValues(fields as (Field)):

		for i in range(len(fields)-1, -1):
			if defaultValueOf(fields[i]) is null:
				break

			requiredFields = fields[:i]
			optionalFields = fields[i:]

			ctor = constructorDeclarationFor(requiredFields)
			baseCtorInvocation = [| self() |]
			for p in ctor.Parameters:
				baseCtorInvocation.Arguments.Add([| $p |])
			for f in optionalFields:
				baseCtorInvocation.Arguments.Add(defaultValueOf(f))
			ctor.Body.Add(baseCtorInvocation)
			yield ctor

	def defaultValueOf(f as Field) as Expression:
		return f["DefaultValue"]

	def fieldsFrom(node as MethodInvocationExpression):
		return array(fieldFrom(expression) for expression in node.Arguments)

	def fieldFrom(node as Expression) as Field:
		match node:
			case [| *$(ReferenceExpression(Name: name)) as $(arrayType = ArrayTypeReference()) |]:
				return arrayField(name, arrayType)
			case [| *$(ReferenceExpression(Name: name)) |]:
				return arrayField(name, ArrayTypeReference(superTypeRef()))
			case [| $(ReferenceExpression(Name: name)) as $type |]:
				return fieldWith(name, type)
			case [| $declaration = $defaultValue |]:
				f = fieldFrom(declaration)
				f.Annotate("DefaultValue", defaultValue)
				return f
			case ReferenceExpression(Name: name):
				return fieldWith(name, defaultTypeRef())

	def defaultTypeRef():
		return _defaultTypeRef or superTypeRef()

	def arrayField(name as string, arrayType as ArrayTypeReference):
		field = fieldWith(name, arrayType)
		field.Annotate("*")
		return field

	def superTypeRef():
		if _superTypeRef is not null:
			return _superTypeRef
		return TypeReference.Lift(_superType)

	def fieldWith(name as string, type as TypeReference):
		if name.StartsWith("@"): // mutable field
			return [|
				public $(fieldName(name)) as $type
			|]
		return [|
			public final $name as $type
		|]

	def fieldName(name as string):
		return (name[1:] if name.StartsWith("@") else name)

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

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

def adtFieldToString(v):
	if v is null: return "null"
	if v isa System.Array: return "[$(join(v, ', '))]"
	return v.ToString()

namespace Boo.Adt

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

macro data:
"""
Produces a complete data type hierarchy from a declaration.

All the types produced are immutable (unless instructed otherwise) and have
meaningful implementations for Equals, GetHashCode and ToString.

Usage:

	data Expression = Const(Value as int) | Add(Left, Right) // omitted types assumed to be Expression

	data SingleValue(Value as int)

	data TypeWithMutableField(@MutableValue as int) // @ makes the field mutable
"""

	DataMacroExpansion(data)

class DataMacroExpansion:

	_module as TypeDefinition
	_superType as TypeDefinition
	_superTypeRef as TypeReference
	_defaultTypeRef as TypeReference

	def constructor(node as MacroStatement):

		assert 1 == len(node.Arguments)
		_module = enclosingModule(node)

		match node.Arguments[0]:
			case [| $left = $right |]:
				assert node.Body.IsEmpty
				_superType = createBaseType(left)
				expandDataConstructors(right)

			case [| $(ctor=MethodInvocationExpression()) < $(superCtor=MethodInvocationExpression()) |]:
				_defaultTypeRef = SimpleTypeReference("object")
				_superType = ClassDefinition()
				_superTypeRef = TypeReference.Lift(superCtor.Target)
				expandDataConstructorWithSuperCtor(ctor, superCtor, node.Body)

			case [| $(ctor=MethodInvocationExpression()) < $superType |]:
				_superTypeRef = TypeReference.Lift(superType)
				_superType = ClassDefinition()
				expandDataConstructorWithBody(ctor, node.Body)

			case ctor=MethodInvocationExpression():
				_superType = [|
					class object:
						pass
				|]
				expandDataConstructorWithBody(ctor, node.Body)

	def createBaseType(node as Expression):
		type = superTypeForExpression(node)
		type.LexicalInfo = node.LexicalInfo
		registerType(type)
		return type

	def abstractType(name as string):
		type = [|
			partial abstract class $name:
				pass
		|]
		return type

	def superTypeForExpression(node as Expression):
		match node:
			case ReferenceExpression(Name: name):
				return abstractType(name)

			case [| $(ReferenceExpression(Name: name)) < $(ReferenceExpression(Name: superType)) |]:
				type = [|
					partial abstract class $name($superType):
						pass
				|]
				return type

			case mie=MethodInvocationExpression(Target: ReferenceExpression(Name: name)):
				type = abstractType(name)
				fields = fieldsFrom(mie)
				type.Members.Extend(fields)
				type.Members.Add(constructorForFields(fields))
				return type

			case gre=SlicingExpression(
						Target: ReferenceExpression(Name: name)):
				type = [|
					partial abstract class $name[of T]:
						pass
				|]
				type.GenericParameters.Clear()
				for index in gre.Indices:
					match index:
						case Slice(
							Begin: ReferenceExpression(Name: name),
							End: null,
							Step: null):
							type.GenericParameters.Add(
								GenericParameterDeclaration(Name: name))
				return type

	def expandDataConstructors(node as Expression):
		match node:
			case [| $left | $right |]:
				expandDataConstructors(left)
				expandDataConstructors(right)
			case MethodInvocationExpression():
				expandDataConstructor(node)

	def expandDataConstructorWithBody(ctor as Expression, body as Block):
		expandDataConstructor(ctor).Members.Extend(TypeMember.Lift(body))

	def expandDataConstructorWithSuperCtor(ctor as Expression, superCtor as Expression, body as Block):
		superFields = fieldsFrom(superCtor)
		superFieldNames = array(f.Name for f in superFields)
		ctorFields = fieldsFrom(ctor)
		fields = array(f for f in ctorFields if f.Name not in superFieldNames)
		expandDataConstructorWithFields(ctor, ctorFields, fields, superFields).Members.Extend(TypeMember.Lift(body))

	def expandDataConstructor(node as MethodInvocationExpression):
		fields = fieldsFrom(node)
		superFields = fieldsOf(_superType).ToArray()
		ctorFields = superFields + fields
		return expandDataConstructorWithFields(node, ctorFields, fields, superFields)

	def expandDataConstructorWithFields(node as MethodInvocationExpression, ctorFields as (Field), fields as (Field), superFields as Field*):
		type = dataConstructorTypeForExpression(node.Target)
		type.LexicalInfo = node.LexicalInfo
		type.Members.Extend(fields)
		type.Members.Add(toStringForType(type))
		type.Members.Add(equalsForType(type))

		ctor = constructorDeclarationFor(ctorFields)
		for field in fields: ctor.Body.Add([| self.$(field.Name) = $field |])
		addSuperInvocationTo ctor, superFields

		type.Members.Add(ctor)
		for ctor in constructorsWithDefaultValues(fields):
			type.Members.Add(ctor)

		registerType(type)
		return type

	def addSuperInvocationTo(ctor as Constructor, superFields as Field*):
		superInvocation = [| super() |]
		for field in superFields:
			superInvocation.Arguments.Add(ReferenceExpression(field.Name))
		ctor.Body.Insert(0, superInvocation)

	def dataConstructorTypeForExpression(node as Expression):
		match node:
			case ReferenceExpression(Name: name):
				type = [|
					partial class $name($(superTypeRef())):
						pass
				|]
				for arg in _superType.GenericParameters:
					type.GenericParameters.Add(
								GenericParameterDeclaration(Name: arg.Name))
				return type

	def equalsForType(type as TypeDefinition):

		allFields = List(fieldsIncludingBaseType(type))
		if len(allFields) == 0:
			method = [|
				override def Equals(o):
					if o is null: return false
					return self.GetType() is o.GetType()
			|]
			return method

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

		for field as Field in allFields:
			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 fieldsIncludingBaseType(type):
			if comma: items.Add([| ", " |])
			items.Add(toStringForField(field))

			comma = true

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

	def toStringForField(field as Field):
		return [| Boo.Adt.adtFieldToString(self.$(field.Name)) |]

	def fieldsIncludingBaseType(type as TypeDefinition):
		return fieldsOf(_superType).Concat(fieldsOf(type))

	def fieldsOf(type as TypeDefinition):
		return type.Members.OfType of Field()

	def constructorForFields(fields as (Field)):
		ctor = constructorDeclarationFor(fields)
		for p in ctor.Parameters:
			ctor.Body.Add([| self.$(p.Name) = $p |])
		return ctor

	def constructorDeclarationFor(fields as (Field)):
		ctor = [|
			def constructor():
				pass
		|]
		for f in fields:
			ctor.Parameters.Add(ParameterDeclaration(Name: f.Name, Type: f.Type))
		ctor.Parameters.HasParamArray = len(fields) > 0 and fields[-1].ContainsAnnotation("*")
		return ctor

	def constructorsWithDefaultValues(fields as (Field)):

		for i in range(len(fields)-1, -1):
			if defaultValueOf(fields[i]) is null:
				break

			requiredFields = fields[:i]
			optionalFields = fields[i:]

			ctor = constructorDeclarationFor(requiredFields)
			baseCtorInvocation = [| self() |]
			for p in ctor.Parameters:
				baseCtorInvocation.Arguments.Add([| $p |])
			for f in optionalFields:
				baseCtorInvocation.Arguments.Add(defaultValueOf(f))
			ctor.Body.Add(baseCtorInvocation)
			yield ctor

	def defaultValueOf(f as Field) as Expression:
		return f["DefaultValue"]

	def fieldsFrom(node as MethodInvocationExpression):
		return array(fieldFrom(expression) for expression in node.Arguments)

	def fieldFrom(node as Expression) as Field:
		match node:
			case [| *$(ReferenceExpression(Name: name)) as $(arrayType = ArrayTypeReference()) |]:
				return arrayField(name, arrayType)
			case [| *$(ReferenceExpression(Name: name)) |]:
				return arrayField(name, ArrayTypeReference(superTypeRef()))
			case [| $(ReferenceExpression(Name: name)) as $type |]:
				return fieldWith(name, type)
			case [| $declaration = $defaultValue |]:
				f = fieldFrom(declaration)
				f.Annotate("DefaultValue", defaultValue)
				return f
			case ReferenceExpression(Name: name):
				return fieldWith(name, defaultTypeRef())

	def defaultTypeRef():
		return _defaultTypeRef or superTypeRef()

	def arrayField(name as string, arrayType as ArrayTypeReference):
		field = fieldWith(name, arrayType)
		field.Annotate("*")
		return field

	def superTypeRef():
		if _superTypeRef is not null:
			return _superTypeRef
		return TypeReference.Lift(_superType)

	def fieldWith(name as string, type as TypeReference):
		if name.StartsWith("@"): // mutable field
			return [|
				public $(fieldName(name)) as $type
			|]
		return [|
			public final $name as $type
		|]

	def fieldName(name as string):
		return (name[1:] if name.StartsWith("@") else name)

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

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

def adtFieldToString(v):
	if v is null: return "null"
	if v isa System.Array: return "[$(join(v, ', '))]"
	return v.ToString()


apply type inference to for iterators (fixes tests/integration/chars.js in strict mode)

namespace UnityScript.Steps

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

import Boo.Lang.Environments

import UnityScript.Core
import UnityScript.Macros
import UnityScript.TypeSystem

class ProcessUnityScriptMethods(ProcessMethodBodiesWithDuckTyping):

	deferred IEnumerable_GetEnumerator = Types.IEnumerable.GetMethod("GetEnumerator");

	deferred IEnumerator_MoveNext = Types.IEnumerator.GetMethod("MoveNext");

	deferred IEnumerator_get_Current = Types.IEnumerator.GetProperty("Current").GetGetMethod();

	deferred _StartCoroutine = NameResolutionService.ResolveMethod(UnityScriptTypeSystem.ScriptBaseType, "StartCoroutine_Auto")

	deferred _UnityRuntimeServices_GetEnumerator = ResolveUnityRuntimeMethod("GetEnumerator")

	deferred _UnityRuntimeServices_Update = ResolveUnityRuntimeMethod("Update")

	deferred _UnityRuntimeServices_GetTypeOf = ResolveUnityRuntimeMethod("GetTypeOf")

	_implicit = false

	override def Initialize(context as CompilerContext):
		super(context)

		// don't transform
		//     foo == null
		// into:
		//     foo is null
		// but into:
		//     foo.Equals(null)
		self.OptimizeNullComparisons = false

	def ResolveUnityRuntimeMethod(name as string):
		return NameResolutionService.ResolveMethod(UnityRuntimeServicesType, name)

	def ResolveUnityRuntimeField(name as string):
		return NameResolutionService.ResolveField(UnityRuntimeServicesType, name)

	deferred UnityRuntimeServicesType = TypeSystemServices.Map(UnityScript.Lang.UnityRuntimeServices)

	UnityScriptTypeSystem as UnityScript.TypeSystem.UnityScriptTypeSystem:
		get: return self.TypeSystemServices

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

	override def GetGeneratorReturnType(generator as InternalMethod):
		return TypeSystemServices.IEnumeratorType

	override protected def MemberNotFound(node as MemberReferenceExpression, ns as INamespace):
		if Strict:
			super(node, ns)
		else:
			BindQuack(node)

	override protected def LocalToReuseFor(d as Declaration):
		if DeclarationAnnotations.ShouldForceNewVariableFor(d):
			AssertUniqueLocal(d)
			return null
		return super(d)

	override def OnModule(module as Module):
		preserving _activeModule, Parameters.Strict, _implicit, my(UnityDowncastPermissions).Enabled:
			EnterModuleContext(module)
			super(module)

	override def VisitMemberPreservingContext(node as TypeMember):

		module = node.EnclosingModule
		if module is _activeModule:
			super(node)
			return

		preserving _activeModule, Parameters.Strict, _implicit, my(UnityDowncastPermissions).Enabled:
			EnterModuleContext(module)
			super(node)

	private def EnterModuleContext(module as Module):
		_activeModule = module
		Parameters.Strict = Pragmas.IsEnabledOn(module, Pragmas.Strict)
		_implicit = Pragmas.IsEnabledOn(module, Pragmas.Implicit)
		my(UnityDowncastPermissions).Enabled = Pragmas.IsEnabledOn(module, Pragmas.Downcast)

	_activeModule as Module

	Strict:
		get: return Parameters.Strict

	override def OnMethod(node as Method):
		super(node)
		CheckForEmptyCoroutine(node)
		return if Parameters.OutputType == CompilerOutputType.Library
		CheckEntryPoint(node)

	def CheckForEmptyCoroutine(node as Method):
		if not IsEmptyCoroutine(node):
			return
		node.Body.Add([| return $(EmptyEnumeratorReference) |])

	def IsEmptyCoroutine(node as Method):
		entity as InternalMethod = GetEntity(node)
		return entity.ReturnType is GetGeneratorReturnType(entity) and HasNeitherReturnNorYield(node)

	deferred EmptyEnumeratorReference = CodeBuilder.CreateMemberReference(ResolveUnityRuntimeField("EmptyEnumerator"))

	def CheckEntryPoint(node as Method):
		if not node.IsStatic: return
		if not node.IsPublic: return
		if node.Name != "Main": return
		if GetType(node.ReturnType) is not TypeSystemServices.VoidType: return

		ContextAnnotations.SetEntryPoint(_context, node)

	override def ProcessAutoLocalDeclaration(node as BinaryExpression, reference as ReferenceExpression):
		if (Strict and not _implicit) and not IsCompilerGenerated(reference):
			EmitUnknownIdentifierError(reference, reference.Name)
		else:
			super(node, reference)

	def IsCompilerGenerated(reference as ReferenceExpression):
		return reference.Name.Contains('$')

	override protected def ProcessBuiltinInvocation(node as MethodInvocationExpression, function as BuiltinFunction):
		if function is UnityScriptTypeSystem.UnityScriptEval:
			EvalAnnotation.Mark(_currentMethod.Method)
			BindExpressionType(node, TypeSystemServices.ObjectType)
			return
		if function is UnityScriptTypeSystem.UnityScriptTypeof:
			ProcessTypeofBuiltin(node);
			return
		super(node, function)

	private def ProcessTypeofBuiltin(node as MethodInvocationExpression):
		if node.Arguments.Count != 1:
			Error(node, CompilerError("UCE0001", node.Target.LexicalInfo, "'typeof' takes a single argument.", null))
			return

		type = node.Arguments[0].Entity as IType
		if type is not null:
			node.ParentNode.Replace(node, CodeBuilder.CreateTypeofExpression(type))
			return

		node.Target = CodeBuilder.CreateReference(_UnityRuntimeServices_GetTypeOf)
		BindExpressionType(node, TypeSystemServices.TypeType)

	override protected def ProcessMethodInvocation(node as MethodInvocationExpression, method as IMethod):
	"""
	Automatically detects coroutine invocations in assignments and as standalone
	expressions and generates StartCoroutine invocations.
	"""
		super(node, method)

		if not IsPossibleStartCoroutineInvocation(node):
			return

		if method.IsStatic: return

		tss = self.UnityScriptTypeSystem
		if not tss.IsScriptType(method.DeclaringType): return
		if not tss.IsGenerator(method): return

		parentNode = node.ParentNode
		parentNode.Replace(
			node,
			CodeBuilder.CreateMethodInvocation(
				TargetForStartCoroutineInvocation(node, method),
				_StartCoroutine,
				node))

	def TargetForStartCoroutineInvocation(node as MethodInvocationExpression, method as IMethod):
		target = cast(MemberReferenceExpression, node.Target).Target
		if target isa SuperLiteralExpression: // super becomes self for coroutine invocation
			return CodeBuilder.CreateSelfReference(target.LexicalInfo, method.DeclaringType)
		return target.CloneNode()

	override def ProcessStaticallyTypedAssignment(node as BinaryExpression):
		TryToResolveAmbiguousAssignment(node)
		ApplyImplicitArrayConversion(node)
		if ValidateAssignment(node):
			BindExpressionType(node, GetExpressionType(node.Right))
		else:
			Error(node)

	def ApplyImplicitArrayConversion(node as BinaryExpression):
		left = GetExpressionType(node.Left)
		if not left.IsArray: return

		right = GetExpressionType(node.Right)
		if right is not TypeSystemServices.Map(UnityScript.Lang.Array): return

		node.Right = CodeBuilder.CreateCast(left,
						CodeBuilder.CreateMethodInvocation(
							node.Right,
							ResolveMethod(right, "ToBuiltin"),
							CodeBuilder.CreateTypeofExpression(left.ElementType)))

	override def OnForStatement(node as ForStatement):
		assert 1 == len(node.Declarations)
		Visit(node.Iterator)
		if NeedsUpdateableIteration(node):
			ProcessUpdateableIteration(node)
		else:
			ProcessNormalIteration(node)

	def ProcessNormalIteration(node as ForStatement):
		node.Iterator = ProcessIterator(node.Iterator, node.Declarations)
		VisitForStatementBlock(node)

	def ProcessUpdateableIteration(node as ForStatement):
		originalIterator = node.Iterator
		newIterator = CodeBuilder.CreateMethodInvocation(_UnityRuntimeServices_GetEnumerator, node.Iterator)
		newIterator.LexicalInfo = LexicalInfo(node.Iterator.LexicalInfo)
		node.Iterator = newIterator
		ProcessDeclarationForIterator(node.Declarations[0], GetEnumeratorItemType(GetExpressionType(originalIterator)))
		VisitForStatementBlock(node)
		TransformIteration(node)

	def TransformIteration(node as ForStatement):
		iterator = CodeBuilder.DeclareLocal(
						_currentMethod.Method,
						_context.GetUniqueName("iterator"),
						TypeSystemServices.IEnumeratorType)
		iterator.IsUsed = true
		body = Block(node.LexicalInfo)
		body.Add(
			CodeBuilder.CreateAssignment(
				node.LexicalInfo,
				CodeBuilder.CreateReference(iterator),
				node.Iterator))

		// while __iterator.MoveNext():
		ws = WhileStatement(node.LexicalInfo)
		ws.Condition = CodeBuilder.CreateMethodInvocation(
						CodeBuilder.CreateReference(iterator),
						IEnumerator_MoveNext)

		current = CodeBuilder.CreateMethodInvocation(
							CodeBuilder.CreateReference(iterator),
							IEnumerator_get_Current)

		//	item = __iterator.Current
		loopVariable as InternalLocal = TypeSystemServices.GetEntity(node.Declarations[0])
		ws.Block.Add(
				CodeBuilder.CreateAssignment(
					node.LexicalInfo,
					CodeBuilder.CreateReference(loopVariable),
					current))
		ws.Block.Add(node.Block)

		LoopVariableUpdater(self, _context, iterator, loopVariable).Visit(node)

		body.Add(ws)
		node.ParentNode.Replace(node, body)

	def NeedsUpdateableIteration(node as ForStatement):
		iteratorType = GetExpressionType(node.Iterator)
		if iteratorType.IsArray: return false
		return true

	class LoopVariableUpdater(DepthFirstVisitor):

		_parent as ProcessUnityScriptMethods
		_context as CompilerContext
		_iteratorVariable as IEntity
		_loopVariable as IEntity
		_found as bool

		def constructor(parent as ProcessUnityScriptMethods, context as CompilerContext, iteratorVariable as IEntity, loopVariable as IEntity):
			_parent = parent
			_context = context
			_iteratorVariable = iteratorVariable
			_loopVariable = loopVariable

		override def OnExpressionStatement(node as ExpressionStatement):
			_found = false
			Visit(node.Expression)
			if not _found: return

			parentNode = node.ParentNode

			codeBuilder = _context.CodeBuilder
			block = Block(node.LexicalInfo)
			block.Add(node)
			block.Add(
				codeBuilder.CreateMethodInvocation(
					_parent._UnityRuntimeServices_Update,
					codeBuilder.CreateReference(_iteratorVariable),
					codeBuilder.CreateReference(_loopVariable)))

			parentNode.Replace(node, block)

		override def OnReferenceExpression(node as ReferenceExpression):
			if _found: return

			referent = node.Entity
			_found = referent is _loopVariable

namespace UnityScript.Steps

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

import Boo.Lang.Environments

import UnityScript.Core
import UnityScript.Macros
import UnityScript.TypeSystem

class ProcessUnityScriptMethods(ProcessMethodBodiesWithDuckTyping):

	deferred IEnumerable_GetEnumerator = Types.IEnumerable.GetMethod("GetEnumerator");

	deferred IEnumerator_MoveNext = Types.IEnumerator.GetMethod("MoveNext");

	deferred IEnumerator_get_Current = Types.IEnumerator.GetProperty("Current").GetGetMethod();

	deferred _StartCoroutine = NameResolutionService.ResolveMethod(UnityScriptTypeSystem.ScriptBaseType, "StartCoroutine_Auto")

	deferred _UnityRuntimeServices_GetEnumerator = ResolveUnityRuntimeMethod("GetEnumerator")

	deferred _UnityRuntimeServices_Update = ResolveUnityRuntimeMethod("Update")

	deferred _UnityRuntimeServices_GetTypeOf = ResolveUnityRuntimeMethod("GetTypeOf")

	_implicit = false

	override def Initialize(context as CompilerContext):
		super(context)

		// don't transform
		//     foo == null
		// into:
		//     foo is null
		// but into:
		//     foo.Equals(null)
		self.OptimizeNullComparisons = false

	def ResolveUnityRuntimeMethod(name as string):
		return NameResolutionService.ResolveMethod(UnityRuntimeServicesType, name)

	def ResolveUnityRuntimeField(name as string):
		return NameResolutionService.ResolveField(UnityRuntimeServicesType, name)

	deferred UnityRuntimeServicesType = TypeSystemServices.Map(UnityScript.Lang.UnityRuntimeServices)

	UnityScriptTypeSystem as UnityScript.TypeSystem.UnityScriptTypeSystem:
		get: return self.TypeSystemServices

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

	override def GetGeneratorReturnType(generator as InternalMethod):
		return TypeSystemServices.IEnumeratorType

	override protected def MemberNotFound(node as MemberReferenceExpression, ns as INamespace):
		if Strict:
			super(node, ns)
		else:
			BindQuack(node)

	override protected def LocalToReuseFor(d as Declaration):
		if DeclarationAnnotations.ShouldForceNewVariableFor(d):
			AssertUniqueLocal(d)
			return null
		return super(d)

	override def OnModule(module as Module):
		preserving _activeModule, Parameters.Strict, _implicit, my(UnityDowncastPermissions).Enabled:
			EnterModuleContext(module)
			super(module)

	override def VisitMemberPreservingContext(node as TypeMember):

		module = node.EnclosingModule
		if module is _activeModule:
			super(node)
			return

		preserving _activeModule, Parameters.Strict, _implicit, my(UnityDowncastPermissions).Enabled:
			EnterModuleContext(module)
			super(node)

	private def EnterModuleContext(module as Module):
		_activeModule = module
		Parameters.Strict = Pragmas.IsEnabledOn(module, Pragmas.Strict)
		_implicit = Pragmas.IsEnabledOn(module, Pragmas.Implicit)
		my(UnityDowncastPermissions).Enabled = Pragmas.IsEnabledOn(module, Pragmas.Downcast)

	_activeModule as Module

	Strict:
		get: return Parameters.Strict

	override def OnMethod(node as Method):
		super(node)
		CheckForEmptyCoroutine(node)
		return if Parameters.OutputType == CompilerOutputType.Library
		CheckEntryPoint(node)

	def CheckForEmptyCoroutine(node as Method):
		if not IsEmptyCoroutine(node):
			return
		node.Body.Add([| return $(EmptyEnumeratorReference) |])

	def IsEmptyCoroutine(node as Method):
		entity as InternalMethod = GetEntity(node)
		return entity.ReturnType is GetGeneratorReturnType(entity) and HasNeitherReturnNorYield(node)

	deferred EmptyEnumeratorReference = CodeBuilder.CreateMemberReference(ResolveUnityRuntimeField("EmptyEnumerator"))

	def CheckEntryPoint(node as Method):
		if not node.IsStatic: return
		if not node.IsPublic: return
		if node.Name != "Main": return
		if GetType(node.ReturnType) is not TypeSystemServices.VoidType: return

		ContextAnnotations.SetEntryPoint(_context, node)

	override def ProcessAutoLocalDeclaration(node as BinaryExpression, reference as ReferenceExpression):
		if (Strict and not _implicit) and not IsCompilerGenerated(reference):
			EmitUnknownIdentifierError(reference, reference.Name)
		else:
			super(node, reference)

	def IsCompilerGenerated(reference as ReferenceExpression):
		return reference.Name.Contains('$')

	override protected def ProcessBuiltinInvocation(node as MethodInvocationExpression, function as BuiltinFunction):
		if function is UnityScriptTypeSystem.UnityScriptEval:
			EvalAnnotation.Mark(_currentMethod.Method)
			BindExpressionType(node, TypeSystemServices.ObjectType)
			return
		if function is UnityScriptTypeSystem.UnityScriptTypeof:
			ProcessTypeofBuiltin(node);
			return
		super(node, function)

	private def ProcessTypeofBuiltin(node as MethodInvocationExpression):
		if node.Arguments.Count != 1:
			Error(node, CompilerError("UCE0001", node.Target.LexicalInfo, "'typeof' takes a single argument.", null))
			return

		type = node.Arguments[0].Entity as IType
		if type is not null:
			node.ParentNode.Replace(node, CodeBuilder.CreateTypeofExpression(type))
			return

		node.Target = CodeBuilder.CreateReference(_UnityRuntimeServices_GetTypeOf)
		BindExpressionType(node, TypeSystemServices.TypeType)

	override protected def ProcessMethodInvocation(node as MethodInvocationExpression, method as IMethod):
	"""
	Automatically detects coroutine invocations in assignments and as standalone
	expressions and generates StartCoroutine invocations.
	"""
		super(node, method)

		if not IsPossibleStartCoroutineInvocation(node):
			return

		if method.IsStatic: return

		tss = self.UnityScriptTypeSystem
		if not tss.IsScriptType(method.DeclaringType): return
		if not tss.IsGenerator(method): return

		parentNode = node.ParentNode
		parentNode.Replace(
			node,
			CodeBuilder.CreateMethodInvocation(
				TargetForStartCoroutineInvocation(node, method),
				_StartCoroutine,
				node))

	def TargetForStartCoroutineInvocation(node as MethodInvocationExpression, method as IMethod):
		target = cast(MemberReferenceExpression, node.Target).Target
		if target isa SuperLiteralExpression: // super becomes self for coroutine invocation
			return CodeBuilder.CreateSelfReference(target.LexicalInfo, method.DeclaringType)
		return target.CloneNode()

	override def ProcessStaticallyTypedAssignment(node as BinaryExpression):
		TryToResolveAmbiguousAssignment(node)
		ApplyImplicitArrayConversion(node)
		if ValidateAssignment(node):
			BindExpressionType(node, GetExpressionType(node.Right))
		else:
			Error(node)

	def ApplyImplicitArrayConversion(node as BinaryExpression):
		left = GetExpressionType(node.Left)
		if not left.IsArray: return

		right = GetExpressionType(node.Right)
		if right is not TypeSystemServices.Map(UnityScript.Lang.Array): return

		node.Right = CodeBuilder.CreateCast(left,
						CodeBuilder.CreateMethodInvocation(
							node.Right,
							ResolveMethod(right, "ToBuiltin"),
							CodeBuilder.CreateTypeofExpression(left.ElementType)))

	override def OnForStatement(node as ForStatement):
		assert 1 == len(node.Declarations)
		Visit(node.Iterator)
		if NeedsUpdateableIteration(node):
			ProcessUpdateableIteration(node)
		else:
			ProcessNormalIteration(node)

	def ProcessNormalIteration(node as ForStatement):
		node.Iterator = ProcessIterator(node.Iterator, node.Declarations)
		VisitForStatementBlock(node)

	def ProcessUpdateableIteration(node as ForStatement):
		newIterator = CodeBuilder.CreateMethodInvocation(_UnityRuntimeServices_GetEnumerator, node.Iterator)
		newIterator.LexicalInfo = LexicalInfo(node.Iterator.LexicalInfo)
		node.Iterator = newIterator
		ProcessDeclarationForIterator(node.Declarations[0], TypeSystemServices.ObjectType)
		VisitForStatementBlock(node)
		TransformIteration(node)

	def TransformIteration(node as ForStatement):
		iterator = CodeBuilder.DeclareLocal(
						_currentMethod.Method,
						_context.GetUniqueName("iterator"),
						TypeSystemServices.IEnumeratorType)
		iterator.IsUsed = true
		body = Block(node.LexicalInfo)
		body.Add(
			CodeBuilder.CreateAssignment(
				node.LexicalInfo,
				CodeBuilder.CreateReference(iterator),
				node.Iterator))

		// while __iterator.MoveNext():
		ws = WhileStatement(node.LexicalInfo)
		ws.Condition = CodeBuilder.CreateMethodInvocation(
						CodeBuilder.CreateReference(iterator),
						IEnumerator_MoveNext)

		current = CodeBuilder.CreateMethodInvocation(
							CodeBuilder.CreateReference(iterator),
							IEnumerator_get_Current)

		//	item = __iterator.Current
		loopVariable as InternalLocal = TypeSystemServices.GetEntity(node.Declarations[0])
		ws.Block.Add(
				CodeBuilder.CreateAssignment(
					node.LexicalInfo,
					CodeBuilder.CreateReference(loopVariable),
					current))
		ws.Block.Add(node.Block)

		LoopVariableUpdater(self, _context, iterator, loopVariable).Visit(node)

		body.Add(ws)
		node.ParentNode.Replace(node, body)

	def NeedsUpdateableIteration(node as ForStatement):
		iteratorType = GetExpressionType(node.Iterator)
		if iteratorType.IsArray: return false
		return true

	class LoopVariableUpdater(DepthFirstVisitor):

		_parent as ProcessUnityScriptMethods
		_context as CompilerContext
		_iteratorVariable as IEntity
		_loopVariable as IEntity
		_found as bool

		def constructor(parent as ProcessUnityScriptMethods, context as CompilerContext, iteratorVariable as IEntity, loopVariable as IEntity):
			_parent = parent
			_context = context
			_iteratorVariable = iteratorVariable
			_loopVariable = loopVariable

		override def OnExpressionStatement(node as ExpressionStatement):
			_found = false
			Visit(node.Expression)
			if not _found: return

			parentNode = node.ParentNode

			codeBuilder = _context.CodeBuilder
			block = Block(node.LexicalInfo)
			block.Add(node)
			block.Add(
				codeBuilder.CreateMethodInvocation(
					_parent._UnityRuntimeServices_Update,
					codeBuilder.CreateReference(_iteratorVariable),
					codeBuilder.CreateReference(_loopVariable)))

			parentNode.Replace(node, block)

		override def OnReferenceExpression(node as ReferenceExpression):
			if _found: return

			referent = node.Entity
			_found = referent is _loopVariable


If present, Use the MONO_EXECUTABLE env var to pick the right mono runtime for launching us.exe inside tests.

namespace UnityScript.Tests

import System
import NUnit.Framework
import Boo.Lang.Useful

[TestFixture]
class UsTestFixture:

	[Test]
	def NoWarn():
		argv = (
			"-r:${GetAssemblyLocation()}",
			"-b:UnityScript.Tests.MonoBehaviour",
			"-m:Awake",
			"-nowarn:BCW0016",
			ResolvePath("warnings-1.js"), )
		AssertSuccessfulCompilation(argv)

	[Test]
	def ExeTarget():
		argv = (
			"-r:${GetAssemblyLocation()}",
			"-b:UnityScript.Tests.MonoBehaviour",
			"-m:Awake",
			"-target:exe",
			ResolvePath("target-exe.js"), )
		AssertSuccessfulCompilation(argv)

	[Test]
	def Pragmas():
		argv = (
			"-r:${GetAssemblyLocation()}",
			"-b:UnityScript.Tests.MonoBehaviour",
			"-m:Awake",
			"-pragmas:strict,implicit",
			ResolvePath("pragmas-1.js"), )
		AssertSuccessfulCompilation(argv)

	[Test]
	def WarningsAndErrorsReportCorrectFileNames():
		argv = (
			"-r:${GetAssemblyLocation()}",
			"-b:UnityScript.Tests.MonoBehaviour",
			"-m:Awake",
			ResolvePath("errors-1.js"), )
		AssertUnknownIdentifierErrorMessageAndExitCode(argv)

	[Test]
	def AcceptsMultipleReferences():
		argv = (
			"-r:${GetAssemblyLocation()}",
			"-r:${GetAssemblyLocation()}",
			"-b:UnityScript.Tests.MonoBehaviour",
			"-m:Awake",
			ResolvePath("errors-1.js"), )
		AssertUnknownIdentifierErrorMessageAndExitCode(argv)

	[Test]
	def EvalCanBeDisabled():
		message = "eval is not available on this platform"
		argv = (
			"-r:${GetAssemblyLocation()}",
			"-b:UnityScript.Tests.MonoBehaviour",
			"-m:Awake",
			'"-disable-eval:' + message + '"',
			path = ResolvePath("eval-can-be-disabled.js"))

		expected = "$path(2,2): UCE0008: $message"
		AssertErrorMessageAndExitCode(expected, argv)

	def ResolvePath(fname as string):
		return "${AbstractCompilerTestFixture.BasePath}/tests/us/${fname}"

	def AssertUnknownIdentifierErrorMessageAndExitCode(argv as (string)):
		expected = """
		${ResolvePath('errors-1.js')}(2,4): BCE0005: Unknown identifier: 'undefinedNoPathNameError'.
		"""
		AssertErrorMessageAndExitCode(expected, argv)

	def AssertErrorMessageAndExitCode(expected as string, argv as (string)):
		exitCode, output as string = ExecuteUs(argv)
		Assert.AreEqual(255, exitCode)
		Assert.AreEqual(expected.Trim(), output.Trim())

	def AssertSuccessfulCompilation(argv as (string)):
		exitCode, output as string = ExecuteUs(argv)
		Assert.AreEqual(0, exitCode, output)
		assert output.Trim().StartsWith("Successfully compiled")

	def ExecuteUs(argv as (string)):
		if PlatformInformation.IsMono:
			monoexe = System.Environment.GetEnvironmentVariable ("MONO_EXECUTABLE")
			if (monoexe == null):
				monoexe = "mono"
			p = shellp(monoexe, UsExePath + " ${join(argv)}")
		else:
			p = shellp(UsExePath, join(argv))

		output = p.StandardOutput.ReadToEnd()
		p.WaitForExit()
		return p.ExitCode, output

	static def shellp(filename as string, arguments as string):
		p = System.Diagnostics.Process()
		p.StartInfo.Arguments = arguments
		p.StartInfo.CreateNoWindow = true
		p.StartInfo.UseShellExecute = false
		p.StartInfo.RedirectStandardOutput = true
		p.StartInfo.RedirectStandardInput = true
		p.StartInfo.RedirectStandardError = true
		p.StartInfo.FileName = filename
		p.Start()
		return p

	UsExePath:
		get: return typeof(us.CommandLineOptions).Module.FullyQualifiedName

namespace UnityScript.Tests

import System
import NUnit.Framework
import Boo.Lang.Useful

[TestFixture]
class UsTestFixture:

	[Test]
	def NoWarn():
		argv = (
			"-r:${GetAssemblyLocation()}",
			"-b:UnityScript.Tests.MonoBehaviour",
			"-m:Awake",
			"-nowarn:BCW0016",
			ResolvePath("warnings-1.js"), )
		AssertSuccessfulCompilation(argv)

	[Test]
	def ExeTarget():
		argv = (
			"-r:${GetAssemblyLocation()}",
			"-b:UnityScript.Tests.MonoBehaviour",
			"-m:Awake",
			"-target:exe",
			ResolvePath("target-exe.js"), )
		AssertSuccessfulCompilation(argv)

	[Test]
	def Pragmas():
		argv = (
			"-r:${GetAssemblyLocation()}",
			"-b:UnityScript.Tests.MonoBehaviour",
			"-m:Awake",
			"-pragmas:strict,implicit",
			ResolvePath("pragmas-1.js"), )
		AssertSuccessfulCompilation(argv)

	[Test]
	def WarningsAndErrorsReportCorrectFileNames():
		argv = (
			"-r:${GetAssemblyLocation()}",
			"-b:UnityScript.Tests.MonoBehaviour",
			"-m:Awake",
			ResolvePath("errors-1.js"), )
		AssertUnknownIdentifierErrorMessageAndExitCode(argv)

	[Test]
	def AcceptsMultipleReferences():
		argv = (
			"-r:${GetAssemblyLocation()}",
			"-r:${GetAssemblyLocation()}",
			"-b:UnityScript.Tests.MonoBehaviour",
			"-m:Awake",
			ResolvePath("errors-1.js"), )
		AssertUnknownIdentifierErrorMessageAndExitCode(argv)

	[Test]
	def EvalCanBeDisabled():
		message = "eval is not available on this platform"
		argv = (
			"-r:${GetAssemblyLocation()}",
			"-b:UnityScript.Tests.MonoBehaviour",
			"-m:Awake",
			'"-disable-eval:' + message + '"',
			path = ResolvePath("eval-can-be-disabled.js"))

		expected = "$path(2,2): UCE0008: $message"
		AssertErrorMessageAndExitCode(expected, argv)

	def ResolvePath(fname as string):
		return "${AbstractCompilerTestFixture.BasePath}/tests/us/${fname}"

	def AssertUnknownIdentifierErrorMessageAndExitCode(argv as (string)):
		expected = """
		${ResolvePath('errors-1.js')}(2,4): BCE0005: Unknown identifier: 'undefinedNoPathNameError'.
		"""
		AssertErrorMessageAndExitCode(expected, argv)

	def AssertErrorMessageAndExitCode(expected as string, argv as (string)):
		exitCode, output as string = ExecuteUs(argv)
		Assert.AreEqual(255, exitCode)
		Assert.AreEqual(expected.Trim(), output.Trim())

	def AssertSuccessfulCompilation(argv as (string)):
		exitCode, output as string = ExecuteUs(argv)
		Assert.AreEqual(0, exitCode, output)
		assert output.Trim().StartsWith("Successfully compiled")

	def ExecuteUs(argv as (string)):
		if PlatformInformation.IsMono:
			p = shellp("mono", UsExePath + " ${join(argv)}")
		else:
			p = shellp(UsExePath, join(argv))

		output = p.StandardOutput.ReadToEnd()
		p.WaitForExit()
		return p.ExitCode, output

	static def shellp(filename as string, arguments as string):
		p = System.Diagnostics.Process()
		p.StartInfo.Arguments = arguments
		p.StartInfo.CreateNoWindow = true
		p.StartInfo.UseShellExecute = false
		p.StartInfo.RedirectStandardOutput = true
		p.StartInfo.RedirectStandardInput = true
		p.StartInfo.RedirectStandardError = true
		p.StartInfo.FileName = filename
		p.Start()
		return p

	UsExePath:
		get: return typeof(us.CommandLineOptions).Module.FullyQualifiedName


simpler version

simpler version

namespace Boo.OMeta.Tests

import Boo.OMeta
import Boo.Lang.PatternMatching
import Boo.Adt
import NUnit.Framework

data Exp = Const(value as int) | Sum(left as Exp, right as Exp)

[TestFixture]
class ObjectMatchingTest:

	[Test]
	def PropertyPatternMatching():

		ometa ConstList:
			option ParseTree
			parse = ++(Const(value) ^ value)

		match ConstList().parse(OMetaInput.For([Const(1), Const(42)])):
			case SuccessfulMatch(Input, Value):
				assert Input.IsEmpty
				Assert.AreEqual([1, 42], Value)

	[Test]
	def PropertyParsing():
		ometa Evaluator:
			eval = const | sum
			const = Const(value) ^ value
			sum = Sum(left: eval >> l as int, right: eval >> r as int) ^ (l + r)

		match Evaluator().eval(OMetaInput.Singleton(Sum(Const(21), Sum(Const(11), Const(10))))):
			case SuccessfulMatch(Input, Value):
				assert Input.IsEmpty
				Assert.AreEqual(42, Value)

namespace Boo.OMeta.Tests

import Boo.OMeta
import Boo.Lang.PatternMatching
import Boo.Adt
import NUnit.Framework

data Exp = Const(value as int) | Sum(left as Exp, right as Exp)

[TestFixture]
class ObjectMatchingTest:

	[Test]
	def PropertyPatternMatching():

		ometa ConstList:
			option ParseTree
			parse = ++(Const(value) ^ value)

		match ConstList().parse(OMetaInput.For([Const(1), Const(42)])):
			case SuccessfulMatch(Input, Value):
				assert Input.IsEmpty
				Assert.AreEqual([1, 42], Value)

	[Test]
	def PropertyParsing():
		ometa Evaluator:
			eval = const | sum
			const = Const(value) ^ value
			sum = Sum(left: eval >> l, right: eval >> r) ^ add(l, r)
			def add(x as int, y as int):
				return x + y

		match Evaluator().eval(OMetaInput.Singleton(Sum(Const(21), Sum(Const(11), Const(10))))):
			case SuccessfulMatch(Input, Value):
				assert Input.IsEmpty
				Assert.AreEqual(42, Value)


Boo if elif else 사용 구문 보정.

Boo if elif else 사용 구문 보정.

import UnityEngine

class TextVisibleControl (MonoBehaviour):
	public objText_Editor as GameObject
	public objText_Window as GameObject
	public objText_iOS as GameObject
	public objText_Android as GameObject

	def Start ():
		if Application.isEditor:
			objText_Editor.SetActive(true)

		// No 'switch' in Boo
		if RuntimePlatform.Android == Application.platform:
    		objText_Android.SetActive(true) // Will Show On Android Build
    	if RuntimePlatform.IPhonePlayer == Application.platform:
    		objText_iOS.SetActive(true) // Will Show On iOS Build
    	else
    		objText_Window.SetActive(true) // Will Show On exe Build

	def Update ():
		pass

import UnityEngine

class TextVisibleControl (MonoBehaviour):
	public objText_Editor as GameObject
	public objText_Window as GameObject
	public objText_iOS as GameObject
	public objText_Android as GameObject

	def Start ():
		if Application.isEditor:
			objText_Editor.SetActive(true)

		// No 'switch' in Boo
		if RuntimePlatform.WindowsPlayer == Application.platform:
    		objText_Window.SetActive(true) // Will Show On exe Build
    	elif RuntimePlatform.IPhonePlayer == Application.platform:
    		objText_iOS.SetActive(true) // Will Show On exe Build
    	if RuntimePlatform.Android == Application.platform:
    		objText_Android.SetActive(true) // Will Show On exe Build

	def Update ():
		pass