Fix for WSABooParserTestFixture.method_declaration_in_macro_application, method_declarations_in_nested_macro_application

namespace Boo.OMeta.Parser

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

import System.Globalization

macro infix:

	l, op, r = infix.Arguments

	return ExpressionStatement([| $l = ((($l >> l, $op >> op, $r >> r) ^ newInfixExpression(op, l, r)) | $r) |])

macro infixr:

	l, op, r = infixr.Arguments

	return ExpressionStatement([| $l = ((($r >> l, $op >> op, $l >> r) ^ newInfixExpression(op, l, r)) | $r) |])

macro prefix:

	rule, op, next = prefix.Arguments

	return ExpressionStatement([| $rule = ($op >> op, $rule >> e) ^ newPrefixExpression(op, e) | $next |])

macro list_of:
"""
Generates rules for lists of the given expression.

	list_of expression

Expands to something that matches:

	expression (COMMA expression)+
"""

	if len(list_of.Arguments) == 2:
		rule, separator = list_of.Arguments
	else:
		rule, separator = list_of.Arguments[0], [| COMMA |]

	block as Block = list_of.ParentNode

	listRuleName = ReferenceExpression(Name: "${rule}_list")
	listRule = [| $listRuleName = ((($rule >> first), ++(($separator, $rule >> e) ^ e) >> rest) ^ prepend(first, rest)) | ($rule >> v ^ [v]) |]
	block.Add(listRule)

	optionalRuleName = ReferenceExpression(Name: "optional_${rule}_list")
	optionalListRule = [| $optionalRuleName = $listRuleName | ("" ^ []) |]
	block.Add(optionalListRule)

ometa BooParser < WhitespaceSensitiveTokenizer:

	tokens:
		qq_begin = "[|"
		qq_end = "|]"
		splice_begin = "$"
		equality = "=="
		inequality = "!="
		assign = "="
		assign_inplace = "+=" | "-=" | "*=" | "/=" | "%=" | "^=" | "&=" | "|=" | "<<=" | ">>="
		xor = "^"
		increment = "++"
		decrement = "--"
		plus = "+"
		minus = "-"
		exponentiation = "**"
		star = "*"
		division = "/"
		modulus = "%"
		ones_complement = "~"
		bitwise_shift_left = "<<"
		bitwise_shift_right = ">>"
		greater_than_eq = ">="
		greater_than = ">"
		less_than_eq = "<="
		less_than = "<"
		semicolon = ";"
		bitwise_and = "&"
		bitwise_or = "|"
		hexnum = ("0x", ++(hex_digit | digit) >> ds) ^ makeString(ds)
		num = ++digit
		colon = ":"
		dot = "."
		comma = ","
		lparen = "(", enterWhitespaceAgnosticRegion
		rparen = ")", leaveWhitespaceAgnosticRegion
		lbrack = "[", enterWhitespaceAgnosticRegion
		rbrack = "]", leaveWhitespaceAgnosticRegion
		lbrace = "{", enterWhitespaceAgnosticRegion
		rbrace = "}", leaveWhitespaceAgnosticRegion

		kw = (keywords >> value, ~(letter | digit | '_')) ^ value
		tdq = '"""'
		dq = '"'
		sq = "'"

		id = ((letter | '_') >> p, --(letter | digit | '_') >> s) ^ makeString(p, s)

	space = line_continuation | multi_line_comment | line_comment | super

	sqs = (SQ, --( sqs_esc | (~('\'' | '\\' | '\r' | '\n'), _)) >> s, SQ) ^ makeString(s)

	dqs = (DQ, --( dqs_esc | (~('"' | '\\' | '\r' | '\n'), _)) >> s, DQ) ^ makeString(s)

	tqs = (TDQ, --(~tdq, ( (('\\', '$') ^ '$')| _)) >> s, TDQ) ^ makeString(s)

	sqs_esc =  '\\', ( sesc | '\'' )

	dqs_esc = '\\', ( sesc | '"' | '$')

	sesc =  ("r" ^ "\r") | ("n" ^ "\n") | ("t" ^ "\t") | ("a" ^ "\a") | ("b" ^ "\b") | ("f" ^ "\f") \
		| ("0" ^ "\0") | ("\\" ^ "\\") \
		| ("u", (hex_digit >> h1, hex_digit >> h2, hex_digit >> h3, hex_digit >> h4) ^ getUnicodeChar([h1, h2, h3, h4]))

	empty_line = ending_spaces, newline

	ending_spaces = --end_space >> value ^ value

	end_space =  semicolon | space

	line_continuation = "\\", newline

	multi_line_comment = "/*", --(~"*/", (multi_line_comment | _)), "*/"

	line_comment = ('#' | "//"), --(~newline, _)

	hex_digit = _ >> c as char and ((c >= char('a') and c <= char('f')) or (c >= char('A') and c <= char('F')))

	keywords "abstract", "and", "as", "callable", "cast", "class", "constructor", "def", "do", "elif", "else", \
		"ensure", "enum", "event", "except", "failure", "false", "final", "for", "from", "goto", "if", "import", \
		"interface", "internal", "in", "isa", "is", "namespace", "not", "null", "of", "or", "override", \
		"pass", "private", "protected", "public", "raise", "return", "self", "static", "struct", "super", \
		"then", "transient", "true", "try", "typeof", "unless", "virtual", "while", "yield"

	keyword[expected] = ((KW >> t) and (expected is tokenValue(t))) ^ t

	module = (
		--EOL,
		((tqs >> s , EOL) | ""),
		--EOL,
		((namespace_declaration >> ns , EOL) | ""),
		--import_declaration >> ids,
		--module_member >> members,
		--stmt >> stmts,
		--EOL
	) ^ newModule(ns, s, ids, members, stmts)

	namespace_declaration = (NAMESPACE, qualified_name)

	import_declaration = ( (IMPORT, qualified_name >> qn), (((FROM, (dqs | sqs | qualified_name)) | "") >> assembly), ( (AS, ID) | "") >> alias, eol) ^ newImport(qn, assembly, alias)

	qualified_name = (ID >> qualifier, --((DOT, id >> n) ^ n) >> suffix)^ buildQName(qualifier, suffix)

	module_member = assembly_attribute | type_def | method | (~(~~(ID, AS), stmt_declaration), ~stmt_expression, ~stmt_goto, stmt_macro)

	type_def = class_def | struct_def | interface_def | enum_def | callable_def

	callable_def = (member_modifiers >> mod, CALLABLE, ID >> name, optional_generic_parameters >> genericParameters , method_parameters >> parameters, optional_type >> type, eol) ^ newCallable(mod, name, genericParameters, parameters, type)

	class_def = (
		attributes >> attrs,
		member_modifiers >> mod,
		CLASS, ID >> className, optional_generic_parameters >> genericParameters, super_types >> superTypes, begin_block, class_body >> body, end_block
	) ^ newClass(attrs, mod, className, genericParameters, superTypes, body)

	struct_def = (
		attributes >> attrs,
		member_modifiers >> mod,
		STRUCT, ID >> structName, optional_generic_parameters >> genericParameters, super_types >> superTypes, begin_block, struct_body >> body, end_block
	) ^ newStruct(attrs, mod, structName, genericParameters, superTypes, body)

	interface_def = (
		attributes >> attrs,
		member_modifiers >> mod,
		INTERFACE, ID >> name, optional_generic_parameters >> genericParameters, super_types >> superTypes, begin_block, interface_body >> body, end_block
	) ^ newInterface(attrs, mod, name, genericParameters, superTypes, body)

	enum_def = (
		attributes >> attrs,
		member_modifiers >> mod,
		ENUM, ID >> name, begin_block, enum_body >> body, end_block
	) ^ newEnum(attrs, mod, name, body)

	enum_body = (++enum_field >> fields ^ fields) | (PASS, eol ^ null)

	enum_field = (attributes >> attrs, ID >> name, ((ASSIGN, expression >> e) | ""), eol) ^ newEnumField(attrs, name, e)

	super_types = ((LPAREN, optional_type_reference_list >> types, RPAREN) ^ types) | ""

	class_body = no_member | (++class_member >> members ^ members)

	struct_body = no_member | (++struct_member >> members ^ members)

	interface_body = no_member | (++interface_member >> members ^ members)

	no_member = (PASS, eol) ^ null

	class_member = type_def | property_def | constructor_method | method | field | event_def

	struct_member = constructor_method | method | field

	interface_member = property_def | method_signature

	event_def = (
		attributes >> attrs,
		member_modifiers >> mod,
		EVENT, ID >> name, optional_type >> type, eol
	) ^ newEvent(attrs, mod, name, type)

	property_def = (
		attributes >> attrs,
		member_modifiers >> mod,
		ID >> name, property_parameters >> parameters, optional_type >> type,
		begin_block,
		(
			(property_getter >> pg, property_setter >> ps)
			| (property_setter >> ps, property_getter >> pg)
			| (property_setter >> ps)
			| (property_getter >> pg)
		),
		end_block
	) ^ newProperty(attrs, mod, name, parameters, type, pg, ps)

	method_signature = (
		attributes >> attrs,
		member_modifiers >> mod,
		DEF, ID >> name,
		optional_generic_parameters >> genericParameters,
		method_parameters >> parameters,
		attributes >> returnTypeAttributes, optional_type >> type, eol
	) ^ newGenericMethod(attrs, mod, name, genericParameters, parameters, returnTypeAttributes, type, null)

	property_parameters = ((LBRACK, parameter_list >> parameters, RBRACK) | "") ^ parameters

	property_getter = accessor["get"]

	property_setter = accessor["set"]

	accessor[key] = (
		attributes >> attrs,
		member_modifiers >> mod,
		(ID >> name and (tokenValue(name) == key)),
		block >> body
	) ^ newMethod(attrs, mod, name, [[],null], null, null, body)

	field = (
		attributes >> attrs,
		member_modifiers >> mod,
		ID >> name, optional_type >> type, field_initializer >> initializer
	) ^ newField(attrs, mod, name, type, initializer)

	field_initializer = (ASSIGN, block_expression) | ((ASSIGN, rvalue >> v, eol) ^ v) | eol

	member_modifiers = --(
		(PRIVATE ^ TypeMemberModifiers.Private)
		| (PUBLIC ^ TypeMemberModifiers.Public)
		| (INTERNAL ^ TypeMemberModifiers.Internal)
		| (PROTECTED ^ TypeMemberModifiers.Protected)
		| (FINAL ^ TypeMemberModifiers.Final)
		| (STATIC ^ TypeMemberModifiers.Static)
		| (VIRTUAL ^ TypeMemberModifiers.Virtual)
		| (OVERRIDE ^ TypeMemberModifiers.Override)
		| (TRANSIENT ^ TypeMemberModifiers.Transient)
		| (ABSTRACT ^ TypeMemberModifiers.Abstract)
	) >> all ^ all

	method = (
		attributes >> attrs,
		member_modifiers >> mod,
		DEF, ID >> name,
		optional_generic_parameters >> genericParameters,
		method_parameters >> parameters,
		attributes >> returnTypeAttributes, optional_type >> type,
		block >> body
	) ^ newGenericMethod(attrs, mod, name, genericParameters, parameters, returnTypeAttributes, type, body)

	constructor_method = (
		attributes >> attrs,
		member_modifiers >> mod,
		DEF, CONSTRUCTOR,
		optional_generic_parameters >> genericParameters,
		method_parameters >> parameters,
		block >> body
	) ^ newConstructor(attrs, mod, genericParameters, parameters, body)

	method_parameters = (LPAREN, \
				((parameter_list >> parameters, COMMA, param_array >> paramArray) | (param_array >> paramArray) | (optional_parameter_list >> parameters) ), \
				RPAREN) ^ [parameters, paramArray]

	param_array = ((attributes >> attrs, STAR, ID >> name, optional_array_type >> type) ^ newParameterDeclaration(attrs, name, type))

	optional_array_type = (AS, type_reference_array) | ""

	optional_generic_parameters = generic_parameters | ""

	generic_parameters = (LBRACK, (OF | ""), generic_parameter_list >> parameters, RBRACK) ^ parameters

	generic_parameter = (ID >> name, optional_generic_parameter_constraints >> genericParameterConstraints) ^ newGenericParameterDeclaration(name, genericParameterConstraints)

	optional_generic_parameter_constraints = generic_parameter_constraints | ""

	generic_parameter_constraints = (LPAREN, generic_parameter_constraint_list >> constraints, RPAREN) ^ constraints

	generic_parameter_constraint = ( (CLASS | STRUCT | CONSTRUCTOR) >> constraint ^ newGenericParameterConstraint(constraint) ) | type_reference

	list_of generic_parameter_constraint

	list_of generic_parameter

	list_of parameter

	assembly_attribute = (
		LBRACK, (ID >> name and (tokenValue(name) == "assembly")), COLON,
		attribute_list >> value,
		RBRACK, eol) ^ value

	attributes = --((LBRACK, attribute_list >> value, RBRACK, --EOL) ^ value) >> all ^ all

	attribute = (qualified_name >> name, optional_invocation_arguments >> args) ^ newAttribute(name, args)

	list_of attribute

	parameter = (attributes >> attrs, ID >> name, optional_type >> type) ^ newParameterDeclaration(attrs, name, type)

	optional_type = (AS, type_reference) | ""

	block = empty_block | multi_line_block | single_line_block

	empty_block = (begin_block, (PASS, eol), end_block) ^ Block()

	multi_line_block = ((begin_block_with_doc >> doc | begin_block), ++stmt >> stmts, end_block)  ^ newBlock(stmts, doc)

	macro_block = empty_block | multi_line_macro_block

	multi_line_macro_block = ((begin_block_with_doc >> doc | begin_block), ++(stmt | type_member_stmt) >> stmts, end_block)  ^ newBlock(stmts, doc)

	type_member_stmt = (type_def | method) >> tm ^ TypeMemberStatement(TypeMember: tm)

	single_line_block = (COLON, stmt_line >> line) ^ newBlock(line, null)

	begin_block = COLON, INDENT

	begin_block_with_doc = (COLON,
		--EOL,
		tqs >> s,
		INDENT) ^ s

	end_block = DEDENT

	stmt = stmt_block | stmt_line

	stmt_line = (~~(ID, AS), stmt_declaration) \
		| stmt_expression \
		| stmt_goto \
		| stmt_macro \
		| stmt_return \
		| stmt_yield \
		| stmt_raise \
		| stmt_unpack \
		| stmt_try

	stmt_unpack = (declaration_list >> declarations, ASSIGN, rvalue >> e, stmt_modifier >> m) ^ newUnpackStatement(declarations, e, m)

	stmt_raise = (RAISE, expression >> e, stmt_modifier >> m) ^ RaiseStatement(Exception: e, Modifier: m)

	stmt_macro = (ID >> name, optional_assignment_list >> args, ((macro_block >> b) | (stmt_modifier >> m))) ^ newMacro(name, args, b, m)

	stmt_yield = (YIELD, assignment >> e, stmt_modifier >> m) ^ YieldStatement(Expression: e, Modifier: m)

	stmt_modifier = (((stmt_modifier_node | "") >> value, (eol|SEMICOLON)) ^ value)

	stmt_try = (TRY, block >> protectedBlock, \
		optional_exception_handler_list >> handlers, \
		((FAILURE, block >> failureBlock) | ""), \
		((ENSURE, block >> ensureBlock) | "")) ^ newTryStatement(protectedBlock, handlers, failureBlock, ensureBlock)

	exception_handler = (EXCEPT, (declaration | "") >> d, block >> b) ^ ExceptionHandler(Block: b, Declaration: d)

	list_of exception_handler

	stmt_goto = ((GOTO, ID >> label, stmt_modifier >> m) ^ newGotoStatement(label, m)) | ((COLON, ID >> label, eol) ^ LabelStatement(Name: tokenValue(label)))

	stmt_modifier_node = (
		stmt_modifier_type >> t,
		assignment >> e
	) ^ newStatementModifier(t, e)

	stmt_modifier_type = (IF ^ StatementModifierType.If) | (UNLESS ^ StatementModifierType.Unless)

	stmt_declaration = (declaration >> d,
			(ASSIGN, block_expression >> e)
			| ((ASSIGN, rvalue >> e), eol)
			| eol
		) ^ newDeclarationStatement(d, e)

	declaration = (ID >> name, optional_type >> typeRef) ^ newDeclaration(name, typeRef)

	stmt_block = stmt_if | stmt_unless | stmt_for | stmt_while

	stmt_for = (FOR, declaration_list >> dl, IN, rvalue >> e, block >> body, or_block >> orBlock, then_block >> thenBlock) ^ newForStatement(dl, e, body, orBlock, thenBlock)

	stmt_while = (WHILE, assignment >> e, block >> body, or_block >> orBlock, then_block >> thenBlock) ^ newWhileStatement(e, body, orBlock, thenBlock)

	or_block = ((OR, block >> orBlock) ^ orBlock) | ( "" ^ null)

	then_block = ((THEN, block >> thenBlock) ^ thenBlock) | ( "" ^ null)

	stmt_if = (IF, assignment >> e, block >> trueBlock, false_block >> falseBlock) ^ newIfStatement(e, trueBlock, falseBlock)

	stmt_unless	= (UNLESS, assignment >> e, block >> condition) ^ newUnlessStatement(e, condition)

	false_block = ((ELIF, assignment >> e, block >> trueBlock, false_block >> falseBlock) ^ newBlock(newIfStatement(e, trueBlock, falseBlock), null)) | \
		((ELSE, block >> falseBlock) ^ falseBlock) | ( "" ^ null)

	stmt_return = (
		RETURN, ((optional_assignment >> e, stmt_modifier >> m) | (block_expression >> e))
		) ^ ReturnStatement(Expression: e, Modifier: m)

	optional_assignment = assignment | ""

	stmt_expression_block = (expression >> l, (ASSIGN | ASSIGN_INPLACE) >> op, block_expression >> r) ^ ExpressionStatement(newInfixExpression(op, l, r))

	block_expression = invocation_with_block | closure_block | dsl_friendly_invocation

	invocation_with_block = (member_reference >> e and (e isa MethodInvocationExpression), \
		(closure_block | (block >> b ^ newBlockExpression([[], null], b))) >> c ^ newInvocationWithBlock(e, c) )

	dsl_friendly_invocation = (member_reference >> e and ((e isa MemberReferenceExpression) or (e isa ReferenceExpression)), \
		(block) >> c) ^ newInvocation(e, [BlockExpression(Body: c)], null)

	closure_block = ((DEF | DO), optional_parameters >> parameters, block >> body) ^ newBlockExpression(parameters, body)

	optional_parameters = method_parameters | ("" ^ [[], null])

	stmt_expression = stmt_expression_block \
		| ((block_expression >> e) ^ ExpressionStatement(Expression: e)) \
		| (((multi_assignment | assignment) >> e and (not (e isa ReferenceExpression or e isa MemberReferenceExpression)), \
			stmt_modifier >> m) ^ ExpressionStatement(Expression: e, Modifier: m))

	multi_assignment = (expression >> l, ASSIGN >> op, rvalue >> r) ^ newInfixExpression(op, l, r)

	rvalue = assignment_list >> items ^ newRValue(items)

	list_of assignment

	infixr assignment, (ASSIGN | ASSIGN_INPLACE), expression

	expression = generator_expression | conditional_expression

	generator_expression = (
		or_expression >> projection,
		++generator_expression_body >> body
	) ^ newGeneratorExpression(projection, body)

	generator_expression_body = (FOR, declaration_list >> dl, IN, conditional_expression >> e, optional_filter >> f) ^ newGeneratorExpressionBody(dl, e, f)

	optional_filter = ((stmt_modifier_type >> t, or_expression >> e) ^ newStatementModifier(t, e)) | ""

	conditional_expression = (
		(or_expression >> trueValue, IF, conditional_expression >> condition, ELSE, conditional_expression >> falseValue) ^  newConditionalExpression(condition, trueValue, falseValue)
	) | or_expression

	infix or_expression, OR, and_expression

	infix and_expression, AND, not_expression

	prefix not_expression, NOT, explode_operator

	prefix explode_operator, STAR , membership_expression

	infix membership_expression, (IN | ((NOT, IN) ^ makeToken("not in"))), identity_test_expression

	infix identity_test_expression, (((IS, NOT) ^ makeToken("is not")) | IS), isa_expression

	isa_expression = (comparison >> l, ISA >> op, type_reference >> type) ^ newInfixExpression(op, l, newTypeofExpression(type))  | comparison

	infix comparison, (EQUALITY | INEQUALITY | GREATER_THAN | GREATER_THAN_EQ | LESS_THAN | LESS_THAN_EQ), bitwise_or_expression

	infix bitwise_or_expression, BITWISE_OR, bitwise_xor_expression

	infix bitwise_xor_expression, XOR, bitwise_and_expression

	infix bitwise_and_expression, BITWISE_AND, term

	infix term, (PLUS | MINUS), factor

	infix factor, (STAR | DIVISION | MODULUS), bitwise_shift_expression

	infix bitwise_shift_expression, (BITWISE_SHIFT_LEFT | BITWISE_SHIFT_RIGHT), signalled_expression

	prefix signalled_expression, (MINUS | INCREMENT | DECREMENT), ones_complement_expression

	prefix ones_complement_expression, ONES_COMPLEMENT, exponentiation_expression

	infix exponentiation_expression, EXPONENTIATION, try_cast

	try_cast = ((try_cast >> e, AS, type_reference >> typeRef) ^ TryCastExpression(Target: e, Type: typeRef)) | cast_operator

	cast_operator = ((cast_operator >> e, CAST, type_reference >> typeRef) ^ CastExpression(Target: e, Type: typeRef)) | member_reference

	member_reference = (((member_reference >> e, DOT, ID >> name) ^ newMemberReference(e, name)) | slicing) >> e, (INCREMENT | DECREMENT | "") >> postOp ^ addSuffixUnaryOperator(e, postOp)

	slicing = ((member_reference >> e, LBRACK, slice_list >> indices, RBRACK) ^ newSlicing(e, indices)) | invocation

	slice = (
			(
				(COLON ^ OmittedExpression.Default) >> begin,
				(expression | ("" ^ OmittedExpression.Default)) >> end,
				(omitted_expression | "") >> step
			)
			|
			(
				expression >> begin,
				((omitted_expression >> end,
					((omitted_expression >> step) | ""))
				| "")
			)
		) ^ newSlice(begin, end, step)

	list_of expression

	list_of declaration

	list_of type_reference

	list_of slice

	omitted_expression = (COLON, expression) | (COLON ^ OmittedExpression.Default)

	invocation = at_operator | collection_initialization | invocation_expression | atom

	at_operator = ("@", invocation_arguments >> args) ^ newInvocation(ReferenceExpression("@"), args, null)

	invocation_expression = (member_reference >> target, optional_generic_arguments >> generic_args, invocation_arguments >> args) ^ newInvocation(target, args, generic_args)

	invocation_arguments = (LPAREN, optional_invocation_argument_list >> args, RPAREN) ^ args

	optional_invocation_arguments = invocation_arguments | ""

	invocation_argument = named_argument | assignment

	list_of invocation_argument

	named_argument = (ID >> name, COLON, assignment >> value) ^ newNamedArgument(name, value)

	type_reference = (type_reference_splice \
		| type_reference_generic_definition \
		| type_reference_generic \
		| type_reference_simple \
		| type_reference_array \
		| type_reference_callable) >> t, --star >> s ^ checkEnumerableTypeShortcut(t, s)

	type_reference_splice = SPLICE_BEGIN, atom >> e ^ SpliceTypeReference(Expression: e)

	splice_expression = SPLICE_BEGIN, atom >> e ^ SpliceExpression(Expression: e)

	type_reference_generic_definition = (qualified_name >> qname, generic_placeholders >> placeholders) ^ newGenericTypeDefinitionReference(qname, placeholders)

	generic_placeholders = ((LBRACK, OF, STAR_list >> placeholders, RBRACK) ^ placeholders) | ( (OF, STAR_list >> placeholders) ^ placeholders)

	list_of STAR

	type_reference_generic = (qualified_name >> qname, generic_arguments >> args) ^ newGenericTypeReference(qname, args)

	generic_arguments = ((LBRACK, (OF | ""), type_reference_list >> args, RBRACK) ^ args) \
		| ((OF, type_reference >> arg) ^ [arg])

	optional_generic_arguments = generic_arguments | ""

	type_reference_callable = (
		CALLABLE, LPAREN, \
		((type_reference_list >> params, COMMA, param_array_reference >> paramArray) | (param_array_reference >> paramArray) | (optional_type_reference_list >> params) ), \
		RPAREN, optional_type >> type
	) ^ newCallableTypeReference(params, paramArray, type) | ((CALLABLE)^ SimpleTypeReference("callable"))

	param_array_reference = ((STAR, type_reference >> type) ^ newParameterDeclaration(null, makeToken("arg0"), type))

	type_reference_array = (LPAREN, ranked_type_reference >> tr, RPAREN) ^ tr

	type_reference_simple = (qualified_name >> qname) ^ SimpleTypeReference(Name: qname)

	atom = time_span | float | integer | boolean | reference | array_literal | list_literal \
		| string_interpolation | string_literal | reg_exp_string | null_literal | parenthesized_expression  \
		| self_literal | super_literal | quasi_quote | closure | hash_literal \
		| type_literal | splice_expression

	type_literal = (TYPEOF, LPAREN, type_reference >> type, RPAREN) ^ newTypeofExpression(type)

	closure = (LBRACE, closure_parameters >> parameters, closure_stmt_list >> body, RBRACE) ^ newBlockExpression(parameters, newBlock(body, null))

	closure_parameters = ((optional_parameter_list >> parameters, BITWISE_OR) ^ [parameters, null]) | ("" ^ [[],null])

	list_of closure_stmt, SEMICOLON

	closure_stmt = closure_stmt_expression | closure_stmt_macro | closure_stmt_return | closure_stmt_raise | closure_stmt_unpack

	closure_stmt_macro = (ID >> name, assignment_list >> args, closure_stmt_modifier >> m) ^ newMacro(name, args, null, m)

	closure_stmt_modifier = stmt_modifier_node | ~~(RBRACE | SEMICOLON)

	closure_stmt_return = (RETURN, (rvalue | "") >> e, closure_stmt_modifier >> m) ^ ReturnStatement(Expression: e, Modifier: m)

	closure_stmt_raise = (RAISE, expression >> e, closure_stmt_modifier >> m) ^ RaiseStatement(Exception: e, Modifier: m)

	closure_stmt_expression = (assignment >> e, closure_stmt_modifier >> m) ^ ExpressionStatement(Expression: e, Modifier: m)

	closure_stmt_unpack = (declaration_list >> declarations, ASSIGN, rvalue >> e, closure_stmt_modifier >> m) ^ newUnpackStatement(declarations, e, m)

	optional_stmt_modifier_node = stmt_modifier_node | ""

	quasi_quote = quasi_quote_member | quasi_quote_module | quasi_quote_expression | quasi_quote_stmt

	quasi_quote_module = (QQ_BEGIN, INDENT, module >> m, DEDENT, QQ_END) ^ newQuasiquoteBlock(m)

	quasi_quote_member = (QQ_BEGIN, INDENT, class_member >> m, DEDENT, QQ_END) ^ newQuasiquoteBlock(m)

	quasi_quote_expression = (QQ_BEGIN, rvalue >> s, QQ_END) ^ newQuasiquoteExpression(s)

	quasi_quote_stmt = (QQ_BEGIN, (qq_return | qq_macro) >> s, QQ_END) ^ newQuasiquoteExpression(s)

	qq_return = (RETURN, optional_assignment >> e, optional_stmt_modifier_node >> m) ^ ReturnStatement(Expression: e, Modifier: m)

	qq_macro = (ID >> name, assignment_list >> args, optional_stmt_modifier_node >> m) ^ newMacro(name, args, null, m)

	parenthesized_expression = (LPAREN, assignment >> e, RPAREN) ^ e

	null_literal = NULL ^ [| null |]

	super_literal = SUPER ^ [| super |]

	self_literal = SELF ^ [| self |]

	string_literal = string_interpolation| ( ((tqs | dqs | sqs) >> s) ^ newStringLiteral(s))

	string_interpolation = (
		DQ,
		--(
			((++(~('"' | '$'), string_char) >> s) ^ StringLiteralExpression(makeString(s)))
			| (('${', expression >> v, --space, '}') ^ v)
			| ('$', atom)
			) >> items,
		DQ) ^ newStringInterpolation(items)

	reg_exp_string = ( (((~"/*","/") | "@/"), (--(~"/", _) >> s), "/")  ) ^ RELiteralExpression(makeString("/", s, "/"))

	string_char = ('\\', ('\\' | '$')) | (~'\\', _)

	array_literal = array_literal_empty | array_literal_single | array_literal_multi

	array_literal_empty = (LPAREN, array_literal_type >> type, COMMA, RPAREN) ^ newArrayLiteral(type, [])

	array_literal_single = (LPAREN, array_literal_type >> type, assignment >> e, COMMA, RPAREN) ^ newArrayLiteral(type, [e])

	array_literal_multi = (LPAREN, array_literal_type >> type, assignment >> e, ++(COMMA, assignment) >> tail, (COMMA | ""), RPAREN) ^ newArrayLiteral(type, prepend(e, tail))

	array_literal_type = ((OF, ranked_type_reference >> type, COLON) | "") ^ type

	ranked_type_reference = ((type_reference >> type), ((COMMA,  integer >> rank) | "")) ^ ArrayTypeReference(ElementType: type, Rank: rank)

	list_literal = (LBRACK, optional_expression_list >> items, optional_comma, RBRACK) ^ newListLiteral(items)

	hash_literal = (LBRACE, optional_expression_pair_list >> items, optional_comma, RBRACE) ^ newHashLiteral(items)

	initialization_list_literal = (LBRACE, optional_expression_list >> items, optional_comma, RBRACE) ^ newListLiteral(items)

	collection_initialization = invocation_expression >> e, (initialization_list_literal | hash_literal) >> i ^ newCollectionInitialization(e, i)

	optional_comma = COMMA | ""

	expression_pair = (assignment >> first, COLON, assignment >> second) ^ ExpressionPair(First: first, Second: second)

	list_of expression_pair

	reference = ID >> r ^ newReference(r)

	time_span = ((integer | float) >> f, ("ms" | 's' | 'm' | 'h' | 'd') >> tu) ^ newTimeSpanLiteral(f, tu)

	integer = ((MINUS | "") >> sign, NUM >> n and (IsValidLong(sign, n)), ("L" | "l" | "") >> suffix ^ newInteger(sign, n, NumberStyles.AllowLeadingSign, suffix)) \
		| ((MINUS | "") >> sign, (HEXNUM >> n and (IsValidHexLong(sign, n))), ("L" | "l" | "") >> suffix ^ newInteger(sign, n, NumberStyles.HexNumber, suffix))

	float = ( (fractional_constant >> n, (exponent_part | "") >> e , floating_suffix ) ^ newFloat(makeString(n,e))) | ((NUM >> n, exponent_part >> e, floating_suffix)  ^ newFloat(makeString(tokenValue(n),e)))

	fractional_constant = ((NUM >> a , DOT , NUM >> b) ^ makeString(tokenValue(a),".",tokenValue(b))) | ( (DOT , NUM >> b) ^ makeString(".",tokenValue(b)) ) | ( (NUM >> a , DOT, ~(ID)) ^ makeString(tokenValue(a), ".") )

	exponent_part = ( ("e" | "E") , exposignopt >> e , NUM >> d ) ^ makeString("e", e, tokenValue(d))

	exposignopt = ( (PLUS | MINUS) >> e ^ makeString(tokenValue(e)) ) | ""

	floating_suffix = "f" | "l" | "F" | "L" | ""

	boolean = true_literal | false_literal

	true_literal = TRUE ^ [| true |]

	false_literal = FALSE ^ [| false |]

	eol = (++EOL | ~_) ^ null

namespace Boo.OMeta.Parser

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

import System.Globalization

macro infix:

	l, op, r = infix.Arguments

	return ExpressionStatement([| $l = ((($l >> l, $op >> op, $r >> r) ^ newInfixExpression(op, l, r)) | $r) |])

macro infixr:

	l, op, r = infixr.Arguments

	return ExpressionStatement([| $l = ((($r >> l, $op >> op, $l >> r) ^ newInfixExpression(op, l, r)) | $r) |])

macro prefix:

	rule, op, next = prefix.Arguments

	return ExpressionStatement([| $rule = ($op >> op, $rule >> e) ^ newPrefixExpression(op, e) | $next |])

macro list_of:
"""
Generates rules for lists of the given expression.

	list_of expression

Expands to something that matches:

	expression (COMMA expression)+
"""

	if len(list_of.Arguments) == 2:
		rule, separator = list_of.Arguments
	else:
		rule, separator = list_of.Arguments[0], [| COMMA |]

	block as Block = list_of.ParentNode

	listRuleName = ReferenceExpression(Name: "${rule}_list")
	listRule = [| $listRuleName = ((($rule >> first), ++(($separator, $rule >> e) ^ e) >> rest) ^ prepend(first, rest)) | ($rule >> v ^ [v]) |]
	block.Add(listRule)

	optionalRuleName = ReferenceExpression(Name: "optional_${rule}_list")
	optionalListRule = [| $optionalRuleName = $listRuleName | ("" ^ []) |]
	block.Add(optionalListRule)

ometa BooParser < WhitespaceSensitiveTokenizer:

	tokens:
		qq_begin = "[|"
		qq_end = "|]"
		splice_begin = "$"
		equality = "=="
		inequality = "!="
		assign = "="
		assign_inplace = "+=" | "-=" | "*=" | "/=" | "%=" | "^=" | "&=" | "|=" | "<<=" | ">>="
		xor = "^"
		increment = "++"
		decrement = "--"
		plus = "+"
		minus = "-"
		exponentiation = "**"
		star = "*"
		division = "/"
		modulus = "%"
		ones_complement = "~"
		bitwise_shift_left = "<<"
		bitwise_shift_right = ">>"
		greater_than_eq = ">="
		greater_than = ">"
		less_than_eq = "<="
		less_than = "<"
		semicolon = ";"
		bitwise_and = "&"
		bitwise_or = "|"
		hexnum = ("0x", ++(hex_digit | digit) >> ds) ^ makeString(ds)
		num = ++digit
		colon = ":"
		dot = "."
		comma = ","
		lparen = "(", enterWhitespaceAgnosticRegion
		rparen = ")", leaveWhitespaceAgnosticRegion
		lbrack = "[", enterWhitespaceAgnosticRegion
		rbrack = "]", leaveWhitespaceAgnosticRegion
		lbrace = "{", enterWhitespaceAgnosticRegion
		rbrace = "}", leaveWhitespaceAgnosticRegion

		kw = (keywords >> value, ~(letter | digit | '_')) ^ value
		tdq = '"""'
		dq = '"'
		sq = "'"

		id = ((letter | '_') >> p, --(letter | digit | '_') >> s) ^ makeString(p, s)

	space = line_continuation | multi_line_comment | line_comment | super

	sqs = (SQ, --( sqs_esc | (~('\'' | '\\' | '\r' | '\n'), _)) >> s, SQ) ^ makeString(s)

	dqs = (DQ, --( dqs_esc | (~('"' | '\\' | '\r' | '\n'), _)) >> s, DQ) ^ makeString(s)

	tqs = (TDQ, --(~tdq, ( (('\\', '$') ^ '$')| _)) >> s, TDQ) ^ makeString(s)

	sqs_esc =  '\\', ( sesc | '\'' )

	dqs_esc = '\\', ( sesc | '"' | '$')

	sesc =  ("r" ^ "\r") | ("n" ^ "\n") | ("t" ^ "\t") | ("a" ^ "\a") | ("b" ^ "\b") | ("f" ^ "\f") \
		| ("0" ^ "\0") | ("\\" ^ "\\") \
		| ("u", (hex_digit >> h1, hex_digit >> h2, hex_digit >> h3, hex_digit >> h4) ^ getUnicodeChar([h1, h2, h3, h4]))

	empty_line = ending_spaces, newline

	ending_spaces = --end_space >> value ^ value

	end_space =  semicolon | space

	line_continuation = "\\", newline

	multi_line_comment = "/*", --(~"*/", (multi_line_comment | _)), "*/"

	line_comment = ('#' | "//"), --(~newline, _)

	hex_digit = _ >> c as char and ((c >= char('a') and c <= char('f')) or (c >= char('A') and c <= char('F')))

	keywords "abstract", "and", "as", "callable", "cast", "class", "constructor", "def", "do", "elif", "else", \
		"ensure", "enum", "event", "except", "failure", "false", "final", "for", "from", "goto", "if", "import", \
		"interface", "internal", "in", "isa", "is", "namespace", "not", "null", "of", "or", "override", \
		"pass", "private", "protected", "public", "raise", "return", "self", "static", "struct", "super", \
		"then", "transient", "true", "try", "typeof", "unless", "virtual", "while", "yield"

	keyword[expected] = ((KW >> t) and (expected is tokenValue(t))) ^ t

	module = (
		--EOL,
		((tqs >> s , EOL) | ""),
		--EOL,
		((namespace_declaration >> ns , EOL) | ""),
		--import_declaration >> ids,
		--module_member >> members,
		--stmt >> stmts,
		--EOL
	) ^ newModule(ns, s, ids, members, stmts)

	namespace_declaration = (NAMESPACE, qualified_name)

	import_declaration = ( (IMPORT, qualified_name >> qn), (((FROM, (dqs | sqs | qualified_name)) | "") >> assembly), ( (AS, ID) | "") >> alias, eol) ^ newImport(qn, assembly, alias)

	qualified_name = (ID >> qualifier, --((DOT, id >> n) ^ n) >> suffix)^ buildQName(qualifier, suffix)

	module_member = assembly_attribute | type_def | method | (~(~~(ID, AS), stmt_declaration), ~stmt_expression, ~stmt_goto, stmt_macro)

	type_def = class_def | struct_def | interface_def | enum_def | callable_def

	callable_def = (member_modifiers >> mod, CALLABLE, ID >> name, optional_generic_parameters >> genericParameters , method_parameters >> parameters, optional_type >> type, eol) ^ newCallable(mod, name, genericParameters, parameters, type)

	class_def = (
		attributes >> attrs,
		member_modifiers >> mod,
		CLASS, ID >> className, optional_generic_parameters >> genericParameters, super_types >> superTypes, begin_block, class_body >> body, end_block
	) ^ newClass(attrs, mod, className, genericParameters, superTypes, body)

	struct_def = (
		attributes >> attrs,
		member_modifiers >> mod,
		STRUCT, ID >> structName, optional_generic_parameters >> genericParameters, super_types >> superTypes, begin_block, struct_body >> body, end_block
	) ^ newStruct(attrs, mod, structName, genericParameters, superTypes, body)

	interface_def = (
		attributes >> attrs,
		member_modifiers >> mod,
		INTERFACE, ID >> name, optional_generic_parameters >> genericParameters, super_types >> superTypes, begin_block, interface_body >> body, end_block
	) ^ newInterface(attrs, mod, name, genericParameters, superTypes, body)

	enum_def = (
		attributes >> attrs,
		member_modifiers >> mod,
		ENUM, ID >> name, begin_block, enum_body >> body, end_block
	) ^ newEnum(attrs, mod, name, body)

	enum_body = (++enum_field >> fields ^ fields) | (PASS, eol ^ null)

	enum_field = (attributes >> attrs, ID >> name, ((ASSIGN, expression >> e) | ""), eol) ^ newEnumField(attrs, name, e)

	super_types = ((LPAREN, optional_type_reference_list >> types, RPAREN) ^ types) | ""

	class_body = no_member | (++class_member >> members ^ members)

	struct_body = no_member | (++struct_member >> members ^ members)

	interface_body = no_member | (++interface_member >> members ^ members)

	no_member = (PASS, eol) ^ null

	class_member = type_def | property_def | constructor_method | method | field | event_def

	struct_member = constructor_method | method | field

	interface_member = property_def | method_signature

	event_def = (
		attributes >> attrs,
		member_modifiers >> mod,
		EVENT, ID >> name, optional_type >> type, eol
	) ^ newEvent(attrs, mod, name, type)

	property_def = (
		attributes >> attrs,
		member_modifiers >> mod,
		ID >> name, property_parameters >> parameters, optional_type >> type,
		begin_block,
		(
			(property_getter >> pg, property_setter >> ps)
			| (property_setter >> ps, property_getter >> pg)
			| (property_setter >> ps)
			| (property_getter >> pg)
		),
		end_block
	) ^ newProperty(attrs, mod, name, parameters, type, pg, ps)

	method_signature = (
		attributes >> attrs,
		member_modifiers >> mod,
		DEF, ID >> name,
		optional_generic_parameters >> genericParameters,
		method_parameters >> parameters,
		attributes >> returnTypeAttributes, optional_type >> type, eol
	) ^ newGenericMethod(attrs, mod, name, genericParameters, parameters, returnTypeAttributes, type, null)

	property_parameters = ((LBRACK, parameter_list >> parameters, RBRACK) | "") ^ parameters

	property_getter = accessor["get"]

	property_setter = accessor["set"]

	accessor[key] = (
		attributes >> attrs,
		member_modifiers >> mod,
		(ID >> name and (tokenValue(name) == key)),
		block >> body
	) ^ newMethod(attrs, mod, name, [[],null], null, null, body)

	field = (
		attributes >> attrs,
		member_modifiers >> mod,
		ID >> name, optional_type >> type, field_initializer >> initializer
	) ^ newField(attrs, mod, name, type, initializer)

	field_initializer = (ASSIGN, block_expression) | ((ASSIGN, rvalue >> v, eol) ^ v) | eol

	member_modifiers = --(
		(PRIVATE ^ TypeMemberModifiers.Private)
		| (PUBLIC ^ TypeMemberModifiers.Public)
		| (INTERNAL ^ TypeMemberModifiers.Internal)
		| (PROTECTED ^ TypeMemberModifiers.Protected)
		| (FINAL ^ TypeMemberModifiers.Final)
		| (STATIC ^ TypeMemberModifiers.Static)
		| (VIRTUAL ^ TypeMemberModifiers.Virtual)
		| (OVERRIDE ^ TypeMemberModifiers.Override)
		| (TRANSIENT ^ TypeMemberModifiers.Transient)
		| (ABSTRACT ^ TypeMemberModifiers.Abstract)
	) >> all ^ all

	method = (
		attributes >> attrs,
		member_modifiers >> mod,
		DEF, ID >> name,
		optional_generic_parameters >> genericParameters,
		method_parameters >> parameters,
		attributes >> returnTypeAttributes, optional_type >> type,
		block >> body
	) ^ newGenericMethod(attrs, mod, name, genericParameters, parameters, returnTypeAttributes, type, body)

	constructor_method = (
		attributes >> attrs,
		member_modifiers >> mod,
		DEF, CONSTRUCTOR,
		optional_generic_parameters >> genericParameters,
		method_parameters >> parameters,
		block >> body
	) ^ newConstructor(attrs, mod, genericParameters, parameters, body)

	method_parameters = (LPAREN, \
				((parameter_list >> parameters, COMMA, param_array >> paramArray) | (param_array >> paramArray) | (optional_parameter_list >> parameters) ), \
				RPAREN) ^ [parameters, paramArray]

	param_array = ((attributes >> attrs, STAR, ID >> name, optional_array_type >> type) ^ newParameterDeclaration(attrs, name, type))

	optional_array_type = (AS, type_reference_array) | ""

	optional_generic_parameters = generic_parameters | ""

	generic_parameters = (LBRACK, (OF | ""), generic_parameter_list >> parameters, RBRACK) ^ parameters

	generic_parameter = (ID >> name, optional_generic_parameter_constraints >> genericParameterConstraints) ^ newGenericParameterDeclaration(name, genericParameterConstraints)

	optional_generic_parameter_constraints = generic_parameter_constraints | ""

	generic_parameter_constraints = (LPAREN, generic_parameter_constraint_list >> constraints, RPAREN) ^ constraints

	generic_parameter_constraint = ( (CLASS | STRUCT | CONSTRUCTOR) >> constraint ^ newGenericParameterConstraint(constraint) ) | type_reference

	list_of generic_parameter_constraint

	list_of generic_parameter

	list_of parameter

	assembly_attribute = (
		LBRACK, (ID >> name and (tokenValue(name) == "assembly")), COLON,
		attribute_list >> value,
		RBRACK, eol) ^ value

	attributes = --((LBRACK, attribute_list >> value, RBRACK, --EOL) ^ value) >> all ^ all

	attribute = (qualified_name >> name, optional_invocation_arguments >> args) ^ newAttribute(name, args)

	list_of attribute

	parameter = (attributes >> attrs, ID >> name, optional_type >> type) ^ newParameterDeclaration(attrs, name, type)

	optional_type = (AS, type_reference) | ""

	block = empty_block | multi_line_block_with_doc | multi_line_block | single_line_block

	empty_block = (begin_block, (PASS, eol), end_block) ^ Block()

	multi_line_block = (begin_block, ++stmt >> stmts, end_block)  ^ newBlock(stmts, null)

	multi_line_block_with_doc = (begin_block_with_doc >> doc, ++stmt >> stmts, end_block)  ^ newBlock(stmts, doc)

	single_line_block = (COLON, stmt_line >> line) ^ newBlock(line, null)

	begin_block = COLON, INDENT

	begin_block_with_doc = (COLON,
		--EOL,
		tqs >> s,
		INDENT) ^ s

	end_block = DEDENT

	stmt = stmt_block | stmt_line

	stmt_line = (~~(ID, AS), stmt_declaration) \
		| stmt_expression \
		| stmt_goto \
		| stmt_macro \
		| stmt_return \
		| stmt_yield \
		| stmt_raise \
		| stmt_unpack \
		| stmt_try

	stmt_unpack = (declaration_list >> declarations, ASSIGN, rvalue >> e, stmt_modifier >> m) ^ newUnpackStatement(declarations, e, m)

	stmt_raise = (RAISE, expression >> e, stmt_modifier >> m) ^ RaiseStatement(Exception: e, Modifier: m)

	stmt_macro = (ID >> name, optional_assignment_list >> args, ((block >> b) | (stmt_modifier >> m))) ^ newMacro(name, args, b, m)

	stmt_yield = (YIELD, assignment >> e, stmt_modifier >> m) ^ YieldStatement(Expression: e, Modifier: m)

	stmt_modifier = (((stmt_modifier_node | "") >> value, (eol|SEMICOLON)) ^ value)

	stmt_try = (TRY, block >> protectedBlock, \
		optional_exception_handler_list >> handlers, \
		((FAILURE, block >> failureBlock) | ""), \
		((ENSURE, block >> ensureBlock) | "")) ^ newTryStatement(protectedBlock, handlers, failureBlock, ensureBlock)

	exception_handler = (EXCEPT, (declaration | "") >> d, block >> b) ^ ExceptionHandler(Block: b, Declaration: d)

	list_of exception_handler

	stmt_goto = ((GOTO, ID >> label, stmt_modifier >> m) ^ newGotoStatement(label, m)) | ((COLON, ID >> label, eol) ^ LabelStatement(Name: tokenValue(label)))

	stmt_modifier_node = (
		stmt_modifier_type >> t,
		assignment >> e
	) ^ newStatementModifier(t, e)

	stmt_modifier_type = (IF ^ StatementModifierType.If) | (UNLESS ^ StatementModifierType.Unless)

	stmt_declaration = (declaration >> d,
			(ASSIGN, block_expression >> e)
			| ((ASSIGN, rvalue >> e), eol)
			| eol
		) ^ newDeclarationStatement(d, e)

	declaration = (ID >> name, optional_type >> typeRef) ^ newDeclaration(name, typeRef)

	stmt_block = stmt_if | stmt_unless | stmt_for | stmt_while

	stmt_for = (FOR, declaration_list >> dl, IN, rvalue >> e, block >> body, or_block >> orBlock, then_block >> thenBlock) ^ newForStatement(dl, e, body, orBlock, thenBlock)

	stmt_while = (WHILE, assignment >> e, block >> body, or_block >> orBlock, then_block >> thenBlock) ^ newWhileStatement(e, body, orBlock, thenBlock)

	or_block = ((OR, block >> orBlock) ^ orBlock) | ( "" ^ null)

	then_block = ((THEN, block >> thenBlock) ^ thenBlock) | ( "" ^ null)

	stmt_if = (IF, assignment >> e, block >> trueBlock, false_block >> falseBlock) ^ newIfStatement(e, trueBlock, falseBlock)

	stmt_unless	= (UNLESS, assignment >> e, block >> condition) ^ newUnlessStatement(e, condition)

	false_block = ((ELIF, assignment >> e, block >> trueBlock, false_block >> falseBlock) ^ newBlock(newIfStatement(e, trueBlock, falseBlock), null)) | \
		((ELSE, block >> falseBlock) ^ falseBlock) | ( "" ^ null)

	stmt_return = (
		RETURN, ((optional_assignment >> e, stmt_modifier >> m) | (block_expression >> e))
		) ^ ReturnStatement(Expression: e, Modifier: m)

	optional_assignment = assignment | ""

	stmt_expression_block = (expression >> l, (ASSIGN | ASSIGN_INPLACE) >> op, block_expression >> r) ^ ExpressionStatement(newInfixExpression(op, l, r))

	block_expression = invocation_with_block | closure_block | dsl_friendly_invocation

	invocation_with_block = (member_reference >> e and (e isa MethodInvocationExpression), \
		(closure_block | (block >> b ^ newBlockExpression([[], null], b))) >> c ^ newInvocationWithBlock(e, c) )

	dsl_friendly_invocation = (member_reference >> e and ((e isa MemberReferenceExpression) or (e isa ReferenceExpression)), \
		(block) >> c) ^ newInvocation(e, [BlockExpression(Body: c)], null)

	closure_block = ((DEF | DO), optional_parameters >> parameters, block >> body) ^ newBlockExpression(parameters, body)

	optional_parameters = method_parameters | ("" ^ [[], null])

	stmt_expression = stmt_expression_block \
		| ((block_expression >> e) ^ ExpressionStatement(Expression: e)) \
		| (((multi_assignment | assignment) >> e and (not (e isa ReferenceExpression or e isa MemberReferenceExpression)), \
			stmt_modifier >> m) ^ ExpressionStatement(Expression: e, Modifier: m))

	multi_assignment = (expression >> l, ASSIGN >> op, rvalue >> r) ^ newInfixExpression(op, l, r)

	rvalue = assignment_list >> items ^ newRValue(items)

	list_of assignment

	infixr assignment, (ASSIGN | ASSIGN_INPLACE), expression

	expression = generator_expression | conditional_expression

	generator_expression = (
		or_expression >> projection,
		++generator_expression_body >> body
	) ^ newGeneratorExpression(projection, body)

	generator_expression_body = (FOR, declaration_list >> dl, IN, conditional_expression >> e, optional_filter >> f) ^ newGeneratorExpressionBody(dl, e, f)

	optional_filter = ((stmt_modifier_type >> t, or_expression >> e) ^ newStatementModifier(t, e)) | ""

	conditional_expression = (
		(or_expression >> trueValue, IF, conditional_expression >> condition, ELSE, conditional_expression >> falseValue) ^  newConditionalExpression(condition, trueValue, falseValue)
	) | or_expression

	infix or_expression, OR, and_expression

	infix and_expression, AND, not_expression

	prefix not_expression, NOT, explode_operator

	prefix explode_operator, STAR , membership_expression

	infix membership_expression, (IN | ((NOT, IN) ^ makeToken("not in"))), identity_test_expression

	infix identity_test_expression, (((IS, NOT) ^ makeToken("is not")) | IS), isa_expression

	isa_expression = (comparison >> l, ISA >> op, type_reference >> type) ^ newInfixExpression(op, l, newTypeofExpression(type))  | comparison

	infix comparison, (EQUALITY | INEQUALITY | GREATER_THAN | GREATER_THAN_EQ | LESS_THAN | LESS_THAN_EQ), bitwise_or_expression

	infix bitwise_or_expression, BITWISE_OR, bitwise_xor_expression

	infix bitwise_xor_expression, XOR, bitwise_and_expression

	infix bitwise_and_expression, BITWISE_AND, term

	infix term, (PLUS | MINUS), factor

	infix factor, (STAR | DIVISION | MODULUS), bitwise_shift_expression

	infix bitwise_shift_expression, (BITWISE_SHIFT_LEFT | BITWISE_SHIFT_RIGHT), signalled_expression

	prefix signalled_expression, (MINUS | INCREMENT | DECREMENT), ones_complement_expression

	prefix ones_complement_expression, ONES_COMPLEMENT, exponentiation_expression

	infix exponentiation_expression, EXPONENTIATION, try_cast

	try_cast = ((try_cast >> e, AS, type_reference >> typeRef) ^ TryCastExpression(Target: e, Type: typeRef)) | cast_operator

	cast_operator = ((cast_operator >> e, CAST, type_reference >> typeRef) ^ CastExpression(Target: e, Type: typeRef)) | member_reference

	member_reference = (((member_reference >> e, DOT, ID >> name) ^ newMemberReference(e, name)) | slicing) >> e, (INCREMENT | DECREMENT | "") >> postOp ^ addSuffixUnaryOperator(e, postOp)

	slicing = ((member_reference >> e, LBRACK, slice_list >> indices, RBRACK) ^ newSlicing(e, indices)) | invocation

	slice = (
			(
				(COLON ^ OmittedExpression.Default) >> begin,
				(expression | ("" ^ OmittedExpression.Default)) >> end,
				(omitted_expression | "") >> step
			)
			|
			(
				expression >> begin,
				((omitted_expression >> end,
					((omitted_expression >> step) | ""))
				| "")
			)
		) ^ newSlice(begin, end, step)

	list_of expression

	list_of declaration

	list_of type_reference

	list_of slice

	omitted_expression = (COLON, expression) | (COLON ^ OmittedExpression.Default)

	invocation = at_operator | collection_initialization | invocation_expression | atom

	at_operator = ("@", invocation_arguments >> args) ^ newInvocation(ReferenceExpression("@"), args, null)

	invocation_expression = (member_reference >> target, optional_generic_arguments >> generic_args, invocation_arguments >> args) ^ newInvocation(target, args, generic_args)

	invocation_arguments = (LPAREN, optional_invocation_argument_list >> args, RPAREN) ^ args

	optional_invocation_arguments = invocation_arguments | ""

	invocation_argument = named_argument | assignment

	list_of invocation_argument

	named_argument = (ID >> name, COLON, assignment >> value) ^ newNamedArgument(name, value)

	type_reference = (type_reference_splice \
		| type_reference_generic_definition \
		| type_reference_generic \
		| type_reference_simple \
		| type_reference_array \
		| type_reference_callable) >> t, --star >> s ^ checkEnumerableTypeShortcut(t, s)

	type_reference_splice = SPLICE_BEGIN, atom >> e ^ SpliceTypeReference(Expression: e)

	splice_expression = SPLICE_BEGIN, atom >> e ^ SpliceExpression(Expression: e)

	type_reference_generic_definition = (qualified_name >> qname, generic_placeholders >> placeholders) ^ newGenericTypeDefinitionReference(qname, placeholders)

	generic_placeholders = ((LBRACK, OF, STAR_list >> placeholders, RBRACK) ^ placeholders) | ( (OF, STAR_list >> placeholders) ^ placeholders)

	list_of STAR

	type_reference_generic = (qualified_name >> qname, generic_arguments >> args) ^ newGenericTypeReference(qname, args)

	generic_arguments = ((LBRACK, (OF | ""), type_reference_list >> args, RBRACK) ^ args) \
		| ((OF, type_reference >> arg) ^ [arg])

	optional_generic_arguments = generic_arguments | ""

	type_reference_callable = (
		CALLABLE, LPAREN, \
		((type_reference_list >> params, COMMA, param_array_reference >> paramArray) | (param_array_reference >> paramArray) | (optional_type_reference_list >> params) ), \
		RPAREN, optional_type >> type
	) ^ newCallableTypeReference(params, paramArray, type) | ((CALLABLE)^ SimpleTypeReference("callable"))

	param_array_reference = ((STAR, type_reference >> type) ^ newParameterDeclaration(null, makeToken("arg0"), type))

	type_reference_array = (LPAREN, ranked_type_reference >> tr, RPAREN) ^ tr

	type_reference_simple = (qualified_name >> qname) ^ SimpleTypeReference(Name: qname)

	atom = time_span | float | integer | boolean | reference | array_literal | list_literal \
		| string_interpolation | string_literal | reg_exp_string | null_literal | parenthesized_expression  \
		| self_literal | super_literal | quasi_quote | closure | hash_literal \
		| type_literal | splice_expression

	type_literal = (TYPEOF, LPAREN, type_reference >> type, RPAREN) ^ newTypeofExpression(type)

	closure = (LBRACE, closure_parameters >> parameters, closure_stmt_list >> body, RBRACE) ^ newBlockExpression(parameters, newBlock(body, null))

	closure_parameters = ((optional_parameter_list >> parameters, BITWISE_OR) ^ [parameters, null]) | ("" ^ [[],null])

	list_of closure_stmt, SEMICOLON

	closure_stmt = closure_stmt_expression | closure_stmt_macro | closure_stmt_return | closure_stmt_raise | closure_stmt_unpack

	closure_stmt_macro = (ID >> name, assignment_list >> args, closure_stmt_modifier >> m) ^ newMacro(name, args, null, m)

	closure_stmt_modifier = stmt_modifier_node | ~~(RBRACE | SEMICOLON)

	closure_stmt_return = (RETURN, (rvalue | "") >> e, closure_stmt_modifier >> m) ^ ReturnStatement(Expression: e, Modifier: m)

	closure_stmt_raise = (RAISE, expression >> e, closure_stmt_modifier >> m) ^ RaiseStatement(Exception: e, Modifier: m)

	closure_stmt_expression = (assignment >> e, closure_stmt_modifier >> m) ^ ExpressionStatement(Expression: e, Modifier: m)

	closure_stmt_unpack = (declaration_list >> declarations, ASSIGN, rvalue >> e, closure_stmt_modifier >> m) ^ newUnpackStatement(declarations, e, m)

	optional_stmt_modifier_node = stmt_modifier_node | ""

	quasi_quote = quasi_quote_member | quasi_quote_module | quasi_quote_expression | quasi_quote_stmt

	quasi_quote_module = (QQ_BEGIN, INDENT, module >> m, DEDENT, QQ_END) ^ newQuasiquoteBlock(m)

	quasi_quote_member = (QQ_BEGIN, INDENT, class_member >> m, DEDENT, QQ_END) ^ newQuasiquoteBlock(m)

	quasi_quote_expression = (QQ_BEGIN, rvalue >> s, QQ_END) ^ newQuasiquoteExpression(s)

	quasi_quote_stmt = (QQ_BEGIN, (qq_return | qq_macro) >> s, QQ_END) ^ newQuasiquoteExpression(s)

	qq_return = (RETURN, optional_assignment >> e, optional_stmt_modifier_node >> m) ^ ReturnStatement(Expression: e, Modifier: m)

	qq_macro = (ID >> name, assignment_list >> args, optional_stmt_modifier_node >> m) ^ newMacro(name, args, null, m)

	parenthesized_expression = (LPAREN, assignment >> e, RPAREN) ^ e

	null_literal = NULL ^ [| null |]

	super_literal = SUPER ^ [| super |]

	self_literal = SELF ^ [| self |]

	string_literal = string_interpolation| ( ((tqs | dqs | sqs) >> s) ^ newStringLiteral(s))

	string_interpolation = (
		DQ,
		--(
			((++(~('"' | '$'), string_char) >> s) ^ StringLiteralExpression(makeString(s)))
			| (('${', expression >> v, --space, '}') ^ v)
			| ('$', atom)
			) >> items,
		DQ) ^ newStringInterpolation(items)

	reg_exp_string = ( (((~"/*","/") | "@/"), (--(~"/", _) >> s), "/")  ) ^ RELiteralExpression(makeString("/", s, "/"))

	string_char = ('\\', ('\\' | '$')) | (~'\\', _)

	array_literal = array_literal_empty | array_literal_single | array_literal_multi

	array_literal_empty = (LPAREN, array_literal_type >> type, COMMA, RPAREN) ^ newArrayLiteral(type, [])

	array_literal_single = (LPAREN, array_literal_type >> type, assignment >> e, COMMA, RPAREN) ^ newArrayLiteral(type, [e])

	array_literal_multi = (LPAREN, array_literal_type >> type, assignment >> e, ++(COMMA, assignment) >> tail, (COMMA | ""), RPAREN) ^ newArrayLiteral(type, prepend(e, tail))

	array_literal_type = ((OF, ranked_type_reference >> type, COLON) | "") ^ type

	ranked_type_reference = ((type_reference >> type), ((COMMA,  integer >> rank) | "")) ^ ArrayTypeReference(ElementType: type, Rank: rank)

	list_literal = (LBRACK, optional_expression_list >> items, optional_comma, RBRACK) ^ newListLiteral(items)

	hash_literal = (LBRACE, optional_expression_pair_list >> items, optional_comma, RBRACE) ^ newHashLiteral(items)

	initialization_list_literal = (LBRACE, optional_expression_list >> items, optional_comma, RBRACE) ^ newListLiteral(items)

	collection_initialization = invocation_expression >> e, (initialization_list_literal | hash_literal) >> i ^ newCollectionInitialization(e, i)

	optional_comma = COMMA | ""

	expression_pair = (assignment >> first, COLON, assignment >> second) ^ ExpressionPair(First: first, Second: second)

	list_of expression_pair

	reference = ID >> r ^ newReference(r)

	time_span = ((integer | float) >> f, ("ms" | 's' | 'm' | 'h' | 'd') >> tu) ^ newTimeSpanLiteral(f, tu)

	integer = ((MINUS | "") >> sign, NUM >> n and (IsValidLong(sign, n)), ("L" | "l" | "") >> suffix ^ newInteger(sign, n, NumberStyles.AllowLeadingSign, suffix)) \
		| ((MINUS | "") >> sign, (HEXNUM >> n and (IsValidHexLong(sign, n))), ("L" | "l" | "") >> suffix ^ newInteger(sign, n, NumberStyles.HexNumber, suffix))

	float = ( (fractional_constant >> n, (exponent_part | "") >> e , floating_suffix ) ^ newFloat(makeString(n,e))) | ((NUM >> n, exponent_part >> e, floating_suffix)  ^ newFloat(makeString(tokenValue(n),e)))

	fractional_constant = ((NUM >> a , DOT , NUM >> b) ^ makeString(tokenValue(a),".",tokenValue(b))) | ( (DOT , NUM >> b) ^ makeString(".",tokenValue(b)) ) | ( (NUM >> a , DOT, ~(ID)) ^ makeString(tokenValue(a), ".") )

	exponent_part = ( ("e" | "E") , exposignopt >> e , NUM >> d ) ^ makeString("e", e, tokenValue(d))

	exposignopt = ( (PLUS | MINUS) >> e ^ makeString(tokenValue(e)) ) | ""

	floating_suffix = "f" | "l" | "F" | "L" | ""

	boolean = true_literal | false_literal

	true_literal = TRUE ^ [| true |]

	false_literal = FALSE ^ [| false |]

	eol = (++EOL | ~_) ^ null


better test

better test

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

"""
op_Equality(self as string, rhs as char)
True
op_Equality(self as string, rhs as char)
False
op_Equality(self as char, rhs as string)
op_Equality(self as string, rhs as char)
True
"""
internal def op_Equality(self as string, rhs as char):
	print "op_Equality(self as string, rhs as char)"
	return len(self) == 1 and self[0] == rhs

internal def op_Equality(self as char, rhs as string):
	print "op_Equality(self as char, rhs as string)"
	return rhs == self

print "a" == char('a')
print "ab" == char('a')
print char('a') == "a"

"""
True
False
True
"""
internal def op_Equality(self as string, rhs as char):
	return len(self) == 1 and self[0] == rhs

internal def op_Equality(self as char, rhs as string):
	return rhs == self

print "a" == char('a')
print "ab" == char('a')
print char('a') == "a"


add Extension attribute to Boo.Lang.Extensions so gmcs can treat EnvironmentExtensions methods as extension methods

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

namespace Boo.Lang.Environments

import System.Runtime.CompilerServices

[Extension]
[CompilerGlobalScope]
static class EnvironmentExtensions:

	[Extension] def Run(this as IEnvironment, action as System.Action):
	"""
	Runs the given action in this environment.
	"""
		ActiveEnvironment.With(this, { action() })

	[Extension] def Invoke[of TResult](this as IEnvironment, function as System.Func of TResult):
	"""
	Invokes the given function in this environment and returns the result.
	"""
		invoker = FunctionInvoker of TResult(Function: function)
		ActiveEnvironment.With(this, invoker.Action)
		return invoker.Result

	internal class FunctionInvoker[of TResult]:
	"""workaround for compiler not supporting closures capturing generic parameters"""
		public Function as System.Func of TResult
		public Result as TResult
		def Action():
			Result = Function()

[assembly: Extension]


update runtime method overloading test

update runtime method overloading test

"""
int: 10
str: bar baz
int: 10
str: bar baz
"""

def foo(a as int):
	print "int: $a"
def foo(b as string, c as string):
	print "str: $b $c"

foo(10)
foo('bar', 'baz')

# Test runtime overload dispatching
js `exports.foo(10)`
js `exports.foo('bar', 'baz')`

"""
int: 10
str: bar baz
int: 10
str: bar baz
"""

def foo(a as int):
	print "int: $a"
def foo(b as string, c as string):
	print "str: $b $c"

foo(10)
foo('bar', 'baz')

# Test runtime overload dispatching
`exports.foo(10)`
`exports.foo('bar', 'baz')`


Update build script to call dotnet tooling

include "build_support.boo"

solution = "MarkEmbling.PostcodesIO.sln"
configuration = "Release"

target default, (clean, restore, compile, test):
  pass

desc "Cleans the solution"
target clean:
  exec("dotnet clean --configuration ${configuration}")

desc "Restore packages"
target restore:
  exec("dotnet restore")

desc "Compiles the solution"
target compile, (clean, restore):
  exec("dotnet build --configuration ${configuration}")

desc "Executes the tests"
target test, (compile):
  exec("dotnet test tests/MarkEmbling.PostcodesIO.Tests/MarkEmbling.PostcodesIO.Tests.csproj --configuration ${configuration} --no-build")

desc "Publishes the NuGet packages"
target publish, (compile, test):
  with FileList("src/MarkEmbling.PostcodesIO/bin/${configuration}"):
    .Include("*.nupkg")
    .ForEach def(file):
      filename = Path.GetFileName(file.FullName)
      if prompt("Publish ${filename}...?"):
        exec("dotnet nuget push \"${file.FullName}\" --source https://www.nuget.org")

include "build_support.boo"

solution = "MarkEmbling.PostcodesIO.sln"
configuration = "release"
test_assembly = "tests/MarkEmbling.PostcodesIO.Tests/bin/${configuration}/MarkEmbling.PostcodesIO.Tests.dll"
bin_path = "build/bin"

target default, (compile, test, prep):
  pass

desc "Compiles the solution"
target compile:
  rmdir("src/MarkEmbling.PostcodesIO/bin/${configuration}")
  msbuild(file: solution, configuration: configuration, version: "4.0")

desc "Executes the tests"
target test, (compile):
  with nunit(assembly: test_assembly, toolPath: "packages/NUnit.ConsoleRunner.3.4.1/tools/nunit3-console.exe")

desc "Copies the binaries to the 'build/bin' directory"
target prep, (compile, test):
  rmdir(bin_path)

  with FileList("src/MarkEmbling.PostcodesIO/bin/${configuration}"):
    .Include("*.{dll,exe,config,nupkg}")
    .ForEach def(file):
      file.CopyToDirectory(bin_path)

desc "Publishes the NuGet packages"
target publish, (prep):
  with FileList(bin_path):
    .Include("*.nupkg")
    .ForEach def(file):
      filename = Path.GetFileName(file.FullName)
      if prompt("Publish ${filename}...?"):
        exec(".nuget/NuGet.exe", "push \"${file.FullName}\" -Source https://nuget.org/api/v2/package")


unused import

unused import

namespace us

import System
import System.Reflection
import Boo.Lang.Compiler

def Main([required] argv as (string)) as int:
	try:
		return run(argv)
	except x:
		print "Error:", x
	return 255

def getAssemblyTitle():
	return cast(AssemblyTitleAttribute, getAssemblyAttribute(AssemblyTitleAttribute)).Title

def getAssemblyVersion():
	return Assembly.GetExecutingAssembly().GetName().Version

def getAssemblyCopyright():
	return cast(AssemblyCopyrightAttribute, getAssemblyAttribute(AssemblyCopyrightAttribute)).Copyright

def getAssemblyAttribute(type as System.Type):
	return Attribute.GetCustomAttribute(Assembly.GetExecutingAssembly(), type)

def compile(options as CommandLineOptions):
	compiler = UnityScriptCompilerFactory.FromCommandLineOptions(options)
	results = compiler.Run()
	if len(results.Errors):
		print results.Errors.ToString(options.Verbose)
		return 255
	else:
		if options.Execute:
			execute(results, options.MainMethod)
		else:
			print results.Warnings.ToString() if len(results.Warnings)
			print "Successfully compiled '${len(compiler.Parameters.Input)}' file(s) to '${results.GeneratedAssemblyFileName}'."
	return 0

def execute(result as CompilerContext, mainMethod as string):
	for type in result.GeneratedAssembly.GetTypes():
		method = type.GetMethod(mainMethod)
		if method is not null:
			method.Invoke(type(), (,))

def banner():
	print "${getAssemblyTitle()} - ${getAssemblyVersion()} ${getAssemblyCopyright()}"
	print

def run(argv as (string)):
	options = parseCommandLineOptions(argv)
	if options.IsValid and not options.DoHelp:
		try:
			return compile(options)
		except x as ApplicationException:
			print "ERROR:", x.Message
		except x:
			print "ERROR:", x
	else:
		usage(options)

	return 255

def parseCommandLineOptions(argv as (string)):
	return CommandLineOptions(*argv)

def usage(options as CommandLineOptions):
	banner()
	options.PrintOptions()

namespace us

import System
import System.Reflection
import System.IO
import Boo.Lang.Compiler

def Main([required] argv as (string)) as int:
	try:
		return run(argv)
	except x:
		print "Error:", x
	return 255

def getAssemblyTitle():
	return cast(AssemblyTitleAttribute, getAssemblyAttribute(AssemblyTitleAttribute)).Title

def getAssemblyVersion():
	return Assembly.GetExecutingAssembly().GetName().Version

def getAssemblyCopyright():
	return cast(AssemblyCopyrightAttribute, getAssemblyAttribute(AssemblyCopyrightAttribute)).Copyright

def getAssemblyAttribute(type as System.Type):
	return Attribute.GetCustomAttribute(Assembly.GetExecutingAssembly(), type)

def compile(options as CommandLineOptions):
	compiler = UnityScriptCompilerFactory.FromCommandLineOptions(options)
	results = compiler.Run()
	if len(results.Errors):
		print results.Errors.ToString(options.Verbose)
		return 255
	else:
		if options.Execute:
			execute(results, options.MainMethod)
		else:
			print results.Warnings.ToString() if len(results.Warnings)
			print "Successfully compiled '${len(compiler.Parameters.Input)}' file(s) to '${results.GeneratedAssemblyFileName}'."
	return 0

def execute(result as CompilerContext, mainMethod as string):
	for type in result.GeneratedAssembly.GetTypes():
		method = type.GetMethod(mainMethod)
		if method is not null:
			method.Invoke(type(), (,))

def banner():
	print "${getAssemblyTitle()} - ${getAssemblyVersion()} ${getAssemblyCopyright()}"
	print

def run(argv as (string)):
	options = parseCommandLineOptions(argv)
	if options.IsValid and not options.DoHelp:
		try:
			return compile(options)
		except x as ApplicationException:
			print "ERROR:", x.Message
		except x:
			print "ERROR:", x
	else:
		usage(options)

	return 255

def parseCommandLineOptions(argv as (string)):
	return CommandLineOptions(*argv)

def usage(options as CommandLineOptions):
	banner()
	options.PrintOptions()


StartColumn -> Column

StartColumn -> Column

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

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

namespace BooExplorer

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

class TaskList(DockContent):

	_list as ListView
	_main as MainForm

	def constructor(main as MainForm):
		_main = main
		_list = ListView(Dock: DockStyle.Fill,
						View: View.Details,
						FullRowSelect: true,
						GridLines: true,
						Click: _list_Click)

		_list.Columns.Add("line"       , 50, HorizontalAlignment.Left)
		_list.Columns.Add("column"     , 50, HorizontalAlignment.Left)
		_list.Columns.Add("code"       , 75, HorizontalAlignment.Left)
		_list.Columns.Add("description", 500, HorizontalAlignment.Left)
		_list.Columns.Add("module"     , 150, HorizontalAlignment.Left)

		SuspendLayout()

		Controls.Add(_list)
		self.HideOnClose = true
		self.AllowRedocking = true
		self.DockableAreas = (
					DockAreas.Float |
					DockAreas.DockBottom |
					DockAreas.DockTop |
					DockAreas.DockLeft |
					DockAreas.DockRight)
		self.ClientSize = System.Drawing.Size(295, 347)
		self.ShowHint = DockState.DockBottom
		self.Text = "Task List"

		ResumeLayout(false)

	def Clear():
		_list.Items.Clear()

	def Update(errors as CompilerErrorCollection):
		_list.BeginUpdate()
		_list.Items.Clear()
		try:
			for error in errors:
				self.AddCompilerError(error)
		ensure:
			_list.EndUpdate()

	def AddCompilerError(error as CompilerError):
		item = _list.Items.Add(error.LexicalInfo.Line.ToString())
		item.SubItems.AddRange((
				error.LexicalInfo.Column.ToString(),
				error.Code,
				error.Message,
				error.LexicalInfo.FileName))
		item.Tag = error

	def _list_Click(sender, args as EventArgs):
		selected = _list.SelectedItems
		return unless len(selected) > 0

		error as CompilerError = selected[0].Tag
		fname = error.LexicalInfo.FileName
		if File.Exists(fname):
			document as BooEditor = _main.OpenDocument(fname)
			document.GoTo(error.LexicalInfo.Line-1)

	override protected def GetPersistString():
		return "TaskList|"

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

namespace BooExplorer

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

class TaskList(DockContent):

	_list as ListView
	_main as MainForm

	def constructor(main as MainForm):
		_main = main
		_list = ListView(Dock: DockStyle.Fill,
						View: View.Details,
						FullRowSelect: true,
						GridLines: true,
						Click: _list_Click)

		_list.Columns.Add("line"       , 50, HorizontalAlignment.Left)
		_list.Columns.Add("column"     , 50, HorizontalAlignment.Left)
		_list.Columns.Add("code"       , 75, HorizontalAlignment.Left)
		_list.Columns.Add("description", 500, HorizontalAlignment.Left)
		_list.Columns.Add("module"     , 150, HorizontalAlignment.Left)

		SuspendLayout()

		Controls.Add(_list)
		self.HideOnClose = true
		self.AllowRedocking = true
		self.DockableAreas = (
					DockAreas.Float |
					DockAreas.DockBottom |
					DockAreas.DockTop |
					DockAreas.DockLeft |
					DockAreas.DockRight)
		self.ClientSize = System.Drawing.Size(295, 347)
		self.ShowHint = DockState.DockBottom
		self.Text = "Task List"

		ResumeLayout(false)

	def Clear():
		_list.Items.Clear()

	def Update(errors as CompilerErrorCollection):
		_list.BeginUpdate()
		_list.Items.Clear()
		try:
			for error in errors:
				self.AddCompilerError(error)
		ensure:
			_list.EndUpdate()

	def AddCompilerError(error as CompilerError):
		item = _list.Items.Add(error.LexicalInfo.Line.ToString())
		item.SubItems.AddRange((
				error.LexicalInfo.StartColumn.ToString(),
				error.Code,
				error.Message,
				error.LexicalInfo.FileName))
		item.Tag = error

	def _list_Click(sender, args as EventArgs):
		selected = _list.SelectedItems
		return unless len(selected) > 0

		error as CompilerError = selected[0].Tag
		fname = error.LexicalInfo.FileName
		if File.Exists(fname):
			document as BooEditor = _main.OpenDocument(fname)
			document.GoTo(error.LexicalInfo.Line-1)

	override protected def GetPersistString():
		return "TaskList|"


Boo.Lang.Useful was not being strongly signed

git-svn-id: fcce7d6ce0ac15bf24f68871b5145d46fc068279@2024 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.Reflection
import System.Runtime.CompilerServices

[assembly: AssemblyTitle("Boo Language Useful Library")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("boo - an extensible programming language for the CLI")]
[assembly: AssemblyCopyright("(C) 2003-2005 Rodrigo Barreto de Oliveira")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
[assembly: AssemblyVersion("1.0.0.0")]
[assembly: AssemblyKeyFile("../src/boo.snk")]

#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.Reflection
import System.Runtime.CompilerServices

[assembly: AssemblyTitle("Boo Language Useful Library")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("boo - an extensible programming language for the CLI")]
[assembly: AssemblyCopyright("(C) 2003-2005 Rodrigo Barreto de Oliveira")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
[assembly: AssemblyVersion("1.0.0.0")]
#[assembly: AssemblyKeyFile("../src/boo.snk")]


fix for Eval

fix for Eval

namespace UnityScript.Steps

import System
import Boo.Lang.Compiler.Ast
import Boo.Lang.Compiler.Steps
import Boo.Lang.Compiler.TypeSystem
import Boo.Lang.Compiler.TypeSystem.Internal
import Boo.Lang.Compiler.TypeSystem.Builders
import UnityScript.Scripting

class ProcessEvalInvocations(AbstractVisitorCompilerStep):

	static final ContainsEvalAnnotation = object()

	static def Mark(node as Method):
		AnnotateEval(node.DeclaringType)
		AnnotateEval(node)

	static def IsMarked(node as Node):
		return node.ContainsAnnotation(ContainsEvalAnnotation)

	static private def AnnotateEval(node as Node):
		if IsMarked(node): return
		node.Annotate(ContainsEvalAnnotation)

	static final Evaluator_Eval = typeof(Evaluator).GetMethod("Eval")

	_currentMethod as InternalMethod
	_evaluationContextLocal as InternalLocal

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

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

	override def OnMethod(node as Method):

		if not IsMarked(node): return

		_currentMethod = GetEntity(node)

		evaluationContextType = DefineEvaluationContext()
		initialization = PrepareEvaluationContextInitialization(evaluationContextType)
		Visit(node.Body)
		node.Body.Insert(0, initialization)

	override def OnReferenceExpression(node as ReferenceExpression):
		entity = node.Entity as IInternalEntity
		if entity is null: return

		field = GetEvaluationContextField(entity.Node)
		if field is null: return

		node.ParentNode.Replace(
			node,
			CreateEvaluationContextFieldReference(field))

	def DefineEvaluationContext():

		builder = CodeBuilder.CreateClass(Context.GetUniqueName("EvaluationContext"), TypeMemberModifiers.Public)
		builder.AddBaseType(Map(EvaluationContext))

		ChainConstructorsFromBaseType(builder)
		AddLocalVariablesAsFields(builder)

		CurrentTypeNode.Members.Add(builder.ClassDefinition)
		return builder.Entity

	def PrepareEvaluationContextInitialization(evaluationContextType as IType):

		_evaluationContextLocal = CodeBuilder.DeclareTempLocal(CurrentMethodNode, evaluationContextType)

		initializationBlock = Block()

		// $context = EvaluationContext(...)
		initializationBlock.Add(
			CodeBuilder.CreateAssignment(
				CreateEvaluationContextReference(),
				CodeBuilder.CreateConstructorInvocation(
					ConstructorTakingNArgumentsFor(evaluationContextType, 1),
					GetSelfReferenceIfInInstanceMethod())))

		for parameter in CurrentMethodNode.Parameters:
			// $context.param = param
			initializationBlock.Add(
				CodeBuilder.CreateAssignment(
					CreateEvaluationContextFieldReference(GetEvaluationContextField(parameter)),
					CodeBuilder.CreateReference(parameter)))

		return initializationBlock

	def GetSelfReferenceIfInInstanceMethod():
		if _currentMethod.IsStatic: return CodeBuilder.CreateNullLiteral()
		return CodeBuilder.CreateSelfReference(CurrentType)

	def CreateEvaluationContextFieldReference(field as InternalField):
		return CodeBuilder.CreateMemberReference(
						CreateEvaluationContextReference(),
						field)

	def CreateEvaluationContextReference():
		return CodeBuilder.CreateReference(_evaluationContextLocal)

	def ReplaceEvalByEvaluatorEval(node as MethodInvocationExpression):
		node.ParentNode.Replace(node, CreateEvaluatorInvocation(node))

	def CreateEvaluatorInvocation(node as MethodInvocationExpression):
		return CodeBuilder.CreateMethodInvocation(
				Evaluator_Eval,
				CreateEvaluationContextReference(),
				node.Arguments[0])

	def AddLocalVariablesAsFields(builder as BooClassBuilder):
		for local in CurrentMethodNode.Locals:
			localEntity as InternalLocal = GetEntity(local)
			if localEntity.IsPrivateScope: continue
			field = builder.AddPublicField(localEntity.Name, localEntity.Type)
			SetEvaluationContextField(local, GetEntity(field))

		for parameter in CurrentMethodNode.Parameters:
			parameterEntity as InternalParameter = GetEntity(parameter)
			field = builder.AddPublicField(parameterEntity.Name, parameterEntity.Type)
			SetEvaluationContextField(parameter, GetEntity(field))

	def ChainConstructorsFromBaseType(builder as BooClassBuilder):
		for superCtor in builder.Entity.BaseType.GetConstructors():
			superInvocationStmt = CodeBuilder.CreateSuperConstructorInvocation(superCtor)
			superInvocation = superInvocationStmt.Expression as MethodInvocationExpression

			ctor = builder.AddConstructor()
			for superParam in superCtor.GetParameters():
				ctorParam = ctor.AddParameter(superParam.Name, superParam.Type)
				superInvocation.Arguments.Add(CodeBuilder.CreateReference(ctorParam))

			ctor.Body.Add(superInvocationStmt)

	override def LeaveClassDefinition(node as ClassDefinition):
		if not IsMarked(node): return

		ImplementIEvaluationDomainProvider(node)

	override def LeaveMethodInvocationExpression(node as MethodInvocationExpression):
		if not IsEvalInvocation(node): return

		ReplaceEvalByEvaluatorEval(node)

	def IsEvalInvocation(node as MethodInvocationExpression):
		return node.Target.Entity is UnityScriptTypeSystem.UnityScriptEval

	def ImplementIEvaluationDomainProvider(node as ClassDefinition):
		node.BaseTypes.Add(CodeBuilder.CreateTypeReference(IEvaluationDomainProvider))
		ImplementGetEvaluationDomain(node)
		ImplementGetImports(node)

	def StringArray():
		return Map(typeof((string)))

	def ImplementGetImports(node as ClassDefinition):
		builder = AddVirtualMethod(node, "GetImports", StringArray())
		builder.Body.Add(ReturnStatement(CreateImportsArray(node)))

	def CreateImportsArray(node as ClassDefinition):
		items = ExpressionCollection()
		for i in node.EnclosingModule.Imports:
			items.Add(CodeBuilder.CreateStringLiteral(i.Namespace))
		return CodeBuilder.CreateArray(StringArray(), items)

	def ImplementGetEvaluationDomain(node as ClassDefinition):
		evaluationDomainType = Map(EvaluationDomain)
		domainField = CodeBuilder.CreateField(Context.GetUniqueName("domain"), evaluationDomainType)
		node.Members.Add(domainField)

		builder = AddVirtualMethod(node, "GetEvaluationDomain", evaluationDomainType)

		// if _domain is null: _domain = EvaluationDomain()
		ifDomainField = IfStatement(TrueBlock: Block())
		ifDomainField.Condition = CodeBuilder.CreateBoundBinaryExpression(
			TypeSystemServices.BoolType,
			BinaryOperatorType.ReferenceEquality,
			CodeBuilder.CreateReference(domainField),
			CodeBuilder.CreateNullLiteral())
		ifDomainField.TrueBlock.Add(
			CodeBuilder.CreateFieldAssignment(
				domainField,
				CodeBuilder.CreateConstructorInvocation(ConstructorTakingNArgumentsFor(evaluationDomainType, 0))))

		builder.Body.Add(ifDomainField)

		// return _domain
		builder.Body.Add(ReturnStatement(CodeBuilder.CreateReference(domainField)))

	def ConstructorTakingNArgumentsFor(type as IType, arguments as int):
		for ctor in type.GetConstructors():
			return ctor if len(ctor.GetParameters()) == arguments
		raise "no constructor in $type taking $arguments arguments"

	def AddVirtualMethod(node as ClassDefinition, name as string, returnType as IType):
		builder = BooMethodBuilder(
						CodeBuilder,
						name,
						returnType,
						TypeMemberModifiers.Public|TypeMemberModifiers.Virtual)
		node.Members.Add(builder.Method)
		return builder

	def Map(type as System.Type):
		return TypeSystemServices.Map(type)

	CurrentType:
		get: return _currentMethod.DeclaringType

	CurrentTypeNode:
		get: return CurrentMethodNode.DeclaringType

	CurrentMethodNode:
		get: return _currentMethod.Method

	CurrentMethodBody:
		get: return CurrentMethodNode.Body

	def SetEvaluationContextField(node as Node, field as InternalField):
		node["EvaluationContextField"] = field

	def GetEvaluationContextField(node as Node) as InternalField:
		return node["EvaluationContextField"]

namespace UnityScript.Steps

import System
import Boo.Lang.Compiler.Ast
import Boo.Lang.Compiler.Steps
import Boo.Lang.Compiler.TypeSystem
import Boo.Lang.Compiler.TypeSystem.Internal
import Boo.Lang.Compiler.TypeSystem.Builders
import UnityScript.Scripting

class ProcessEvalInvocations(AbstractVisitorCompilerStep):

	static final ContainsEvalAnnotation = object()

	static def Mark(node as Method):
		AnnotateEval(node.DeclaringType)
		AnnotateEval(node)

	static def IsMarked(node as Node):
		return node.ContainsAnnotation(ContainsEvalAnnotation)

	static private def AnnotateEval(node as Node):
		if IsMarked(node): return
		node.Annotate(ContainsEvalAnnotation)

	static final Evaluator_Eval = typeof(Evaluator).GetMethod("Eval")

	_currentMethod as InternalMethod
	_evaluationContextLocal as InternalLocal

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

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

	override def OnMethod(node as Method):

		if not IsMarked(node): return

		_currentMethod = GetEntity(node)

		evaluationContextType = DefineEvaluationContext()
		initialization = PrepareEvaluationContextInitialization(evaluationContextType)
		Visit(node.Body)
		node.Body.Insert(0, initialization)

	override def OnReferenceExpression(node as ReferenceExpression):
		entity = node.Entity as IInternalEntity
		if entity is null: return

		field = GetEvaluationContextField(entity.Node)
		if field is null: return

		node.ParentNode.Replace(
			node,
			CreateEvaluationContextFieldReference(field))

	def DefineEvaluationContext():

		builder = CodeBuilder.CreateClass(Context.GetUniqueName("EvaluationContext"), TypeMemberModifiers.Public)
		builder.AddBaseType(Map(EvaluationContext))

		ChainConstructorsFromBaseType(builder)
		AddLocalVariablesAsFields(builder)

		CurrentTypeNode.Members.Add(builder.ClassDefinition)
		return builder.Entity

	def PrepareEvaluationContextInitialization(evaluationContextType as IType):

		_evaluationContextLocal = CodeBuilder.DeclareTempLocal(CurrentMethodNode, evaluationContextType)

		initializationBlock = Block()

		// $context = EvaluationContext(...)
		initializationBlock.Add(
			CodeBuilder.CreateAssignment(
				CreateEvaluationContextReference(),
				CodeBuilder.CreateConstructorInvocation(
					DefaultConstructorFor(evaluationContextType),
					GetSelfReferenceIfInInstanceMethod())))

		for parameter in CurrentMethodNode.Parameters:
			// $context.param = param
			initializationBlock.Add(
				CodeBuilder.CreateAssignment(
					CreateEvaluationContextFieldReference(GetEvaluationContextField(parameter)),
					CodeBuilder.CreateReference(parameter)))

		return initializationBlock

	def GetSelfReferenceIfInInstanceMethod():
		if _currentMethod.IsStatic: return CodeBuilder.CreateNullLiteral()
		return CodeBuilder.CreateSelfReference(CurrentType)

	def CreateEvaluationContextFieldReference(field as InternalField):
		return CodeBuilder.CreateMemberReference(
						CreateEvaluationContextReference(),
						field)

	def CreateEvaluationContextReference():
		return CodeBuilder.CreateReference(_evaluationContextLocal)

	def ReplaceEvalByEvaluatorEval(node as MethodInvocationExpression):
		node.ParentNode.Replace(node, CreateEvaluatorInvocation(node))

	def CreateEvaluatorInvocation(node as MethodInvocationExpression):
		return CodeBuilder.CreateMethodInvocation(
				Evaluator_Eval,
				CreateEvaluationContextReference(),
				node.Arguments[0])

	def AddLocalVariablesAsFields(builder as BooClassBuilder):
		for local in CurrentMethodNode.Locals:
			localEntity as InternalLocal = GetEntity(local)
			if localEntity.IsPrivateScope: continue
			field = builder.AddPublicField(localEntity.Name, localEntity.Type)
			SetEvaluationContextField(local, GetEntity(field))

		for parameter in CurrentMethodNode.Parameters:
			parameterEntity as InternalParameter = GetEntity(parameter)
			field = builder.AddPublicField(parameterEntity.Name, parameterEntity.Type)
			SetEvaluationContextField(parameter, GetEntity(field))

	def ChainConstructorsFromBaseType(builder as BooClassBuilder):
		for superCtor in builder.Entity.BaseType.GetConstructors():
			superInvocationStmt = CodeBuilder.CreateSuperConstructorInvocation(superCtor)
			superInvocation = superInvocationStmt.Expression as MethodInvocationExpression

			ctor = builder.AddConstructor()
			for superParam in superCtor.GetParameters():
				ctorParam = ctor.AddParameter(superParam.Name, superParam.Type)
				superInvocation.Arguments.Add(CodeBuilder.CreateReference(ctorParam))

			ctor.Body.Add(superInvocationStmt)

	override def LeaveClassDefinition(node as ClassDefinition):
		if not IsMarked(node): return

		ImplementIEvaluationDomainProvider(node)

	override def LeaveMethodInvocationExpression(node as MethodInvocationExpression):
		if not IsEvalInvocation(node): return

		ReplaceEvalByEvaluatorEval(node)

	def IsEvalInvocation(node as MethodInvocationExpression):
		return node.Target.Entity is UnityScriptTypeSystem.UnityScriptEval

	def ImplementIEvaluationDomainProvider(node as ClassDefinition):
		node.BaseTypes.Add(CodeBuilder.CreateTypeReference(IEvaluationDomainProvider))
		ImplementGetEvaluationDomain(node)
		ImplementGetImports(node)

	def StringArray():
		return Map(typeof((string)))

	def ImplementGetImports(node as ClassDefinition):
		builder = AddVirtualMethod(node, "GetImports", StringArray())
		builder.Body.Add(ReturnStatement(CreateImportsArray(node)))

	def CreateImportsArray(node as ClassDefinition):
		items = ExpressionCollection()
		for i in node.EnclosingModule.Imports:
			items.Add(CodeBuilder.CreateStringLiteral(i.Namespace))
		return CodeBuilder.CreateArray(StringArray(), items)

	def ImplementGetEvaluationDomain(node as ClassDefinition):
		evaluationDomainType = Map(EvaluationDomain)
		domainField = CodeBuilder.CreateField(Context.GetUniqueName("domain"), evaluationDomainType)
		node.Members.Add(domainField)

		builder = AddVirtualMethod(node, "GetEvaluationDomain", evaluationDomainType)

		// if _domain is null: _domain = EvaluationDomain()
		ifDomainField = IfStatement(TrueBlock: Block())
		ifDomainField.Condition = CodeBuilder.CreateBoundBinaryExpression(
			TypeSystemServices.BoolType,
			BinaryOperatorType.ReferenceEquality,
			CodeBuilder.CreateReference(domainField),
			CodeBuilder.CreateNullLiteral())
		ifDomainField.TrueBlock.Add(
			CodeBuilder.CreateFieldAssignment(
				domainField,
				CodeBuilder.CreateConstructorInvocation(DefaultConstructorFor(evaluationDomainType))))

		builder.Body.Add(ifDomainField)

		// return _domain
		builder.Body.Add(ReturnStatement(CodeBuilder.CreateReference(domainField)))

	def DefaultConstructorFor(type as IType):
		first, = type.GetConstructors()
		return first

	def AddVirtualMethod(node as ClassDefinition, name as string, returnType as IType):
		builder = BooMethodBuilder(
						CodeBuilder,
						name,
						returnType,
						TypeMemberModifiers.Public|TypeMemberModifiers.Virtual)
		node.Members.Add(builder.Method)
		return builder

	def Map(type as System.Type):
		return TypeSystemServices.Map(type)

	CurrentType:
		get: return _currentMethod.DeclaringType

	CurrentTypeNode:
		get: return CurrentMethodNode.DeclaringType

	CurrentMethodNode:
		get: return _currentMethod.Method

	CurrentMethodBody:
		get: return CurrentMethodNode.Body

	def SetEvaluationContextField(node as Node, field as InternalField):
		node["EvaluationContextField"] = field

	def GetEvaluationContextField(node as Node) as InternalField:
		return node["EvaluationContextField"]


marking Type method in IConstructor

marking Type method in IConstructor

namespace Boojay.Compilation.TypeSystem

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

import org.objectweb.asm

class JarConstructor(IConstructor):
	_declaringType as IType
	_access as int

	def constructor(declaringType as IType, access as int):
		_declaringType = declaringType
		_access = access

	IsPublic as bool:
		get: return (_access & Opcodes.ACC_PUBLIC) != 0

	IsPrivate as bool:
		get: return (_access & Opcodes.ACC_PRIVATE) != 0

	IsStatic as bool:
		get: return (_access & Opcodes.ACC_STATIC) != 0

	EntityType:
		get: return EntityType.Constructor

	Type:
		get: raise "Tenho que implementar"

	Name:
		get: return "constructor"

	FullName:
		get: return "${_declaringType.FullName}.${Name}"

	DeclaringType:
		get: return _declaringType

	def GetParameters():
		return array[of IParameter](0)

namespace Boojay.Compilation.TypeSystem

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

import org.objectweb.asm

class JarConstructor(IConstructor):
	_declaringType as IType
	_access as int

	def constructor(declaringType as IType, access as int):
		_declaringType = declaringType
		_access = access

	IsPublic as bool:
		get: return (_access & Opcodes.ACC_PUBLIC) != 0

	IsPrivate as bool:
		get: return (_access & Opcodes.ACC_PRIVATE) != 0

	IsStatic as bool:
		get: return (_access & Opcodes.ACC_STATIC) != 0

	EntityType:
		get: return EntityType.Constructor

	Name:
		get: return "constructor"

	FullName:
		get: return "${_declaringType.FullName}.${Name}"

	DeclaringType:
		get: return _declaringType

	def GetParameters():
		return array[of IParameter](0)


prefer pattern matching over sequence of ifs and casts

namespace UnityScript.Steps

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

def IsRhsOfAssignment(node as Expression):
	match node.ParentNode:
		case BinaryExpression(Operator: BinaryOperatorType.Assign, Right: rhs) and rhs is node:
			return true
		otherwise:
			return false

def IsPossibleStartCoroutineInvocationForm(node as MethodInvocationExpression):
	match node:
		case Node(ParentNode: ExpressionStatement() | YieldStatement()) or IsRhsOfAssignment(node):
			return true
		otherwise:
			return false

def SetScriptClass(context as CompilerContext, klass as ClassDefinition):
	context["ScriptClass"] = klass

def GetScriptClass(context as CompilerContext) as ClassDefinition:
	return context["ScriptClass"]

def ConstructorTakingNArgumentsFor(type as IType, arguments as int):
	for ctor in type.GetConstructors():
		return ctor if len(ctor.GetParameters()) == arguments
	raise "no constructor in $type taking $arguments arguments"

namespace UnityScript.Steps

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

def IsRhsOfAssignment(node as Expression):
	be = node.ParentNode as BinaryExpression
	if be is null: return false
	if be.Operator != BinaryOperatorType.Assign: return false
	return be.Right is node

def IsPossibleStartCoroutineInvocation(node as MethodInvocationExpression):
	if node.ParentNode isa ExpressionStatement: return true
	if node.ParentNode isa YieldStatement: return true
	return IsRhsOfAssignment(node)

def SetScriptClass(context as CompilerContext, klass as ClassDefinition):
	context["ScriptClass"] = klass

def GetScriptClass(context as CompilerContext) as ClassDefinition:
	return context["ScriptClass"]

def ConstructorTakingNArgumentsFor(type as IType, arguments as int):
	for ctor in type.GetConstructors():
		return ctor if len(ctor.GetParameters()) == arguments
	raise "no constructor in $type taking $arguments arguments"


${} interpolation is deprecated

${} interpolation is deprecated

namespace UnityScript.Core

import Boo.Lang.Compiler.Ast

static class UnityScriptCompilerErrors:

	def SemicolonExpected(location as LexicalInfo):
		return CreateError("UCE0001", location, "';' expected. Insert a semicolon at the end.")

	def UnknownPragma(location as LexicalInfo, pragma as string):
		return CreateError("UCE0002", location, "Unknown pragma '${pragma}'.")

	def InvalidPropertySetter(location as LexicalInfo):
		return CreateError("UCE0003", location, "Property setter must have a single argument named 'value'.")

	def InvalidPropertyGetter(location as LexicalInfo):
		return CreateError("UCE0004", location, "Property getter cannot declare any arguments.")

	def InterfaceExpected(location as LexicalInfo, typeName as string):
		return CreateError("UCE0005", location, "'$typeName' is not an interface. 'implements' can only be used with interfaces. Did you mean 'extends'?")

	def ClassExpected(location as LexicalInfo, typeName as string):
		return CreateError("UCE0006", location, "'$typeName' is not a class. 'extends' can only be used with classes. Did you mean 'implements'?")

	def KeywordCannotBeUsedAsAnIdentifier(location as LexicalInfo, keyword as string):
		return CreateError("UCE0007", location, "Reserved keyword '$keyword' cannot be used as an identifier.")

	private def CreateError(code as string, location as LexicalInfo, message as string):
		return Boo.Lang.Compiler.CompilerError(code, location, message, null)

namespace UnityScript.Core

import Boo.Lang.Compiler.Ast

static class UnityScriptCompilerErrors:

	def SemicolonExpected(location as LexicalInfo):
		return CreateError("UCE0001", location, "';' expected. Insert a semicolon at the end.")

	def UnknownPragma(location as LexicalInfo, pragma as string):
		return CreateError("UCE0002", location, "Unknown pragma '${pragma}'.")

	def InvalidPropertySetter(location as LexicalInfo):
		return CreateError("UCE0003", location, "Property setter must have a single argument named 'value'.")

	def InvalidPropertyGetter(location as LexicalInfo):
		return CreateError("UCE0004", location, "Property getter cannot declare any arguments.")

	def InterfaceExpected(location as LexicalInfo, typeName as string):
		return CreateError("UCE0005", location, "'${typeName}' is not an interface. 'implements' can only be used with interfaces. Did you mean 'extends'?")

	def ClassExpected(location as LexicalInfo, typeName as string):
		return CreateError("UCE0006", location, "'${typeName}' is not a class. 'extends' can only be used with classes. Did you mean 'implements'?")

	def KeywordCannotBeUsedAsAnIdentifier(location as LexicalInfo, keyword as string):
		return CreateError("UCE0007", location, "Reserved keyword '${keyword}' cannot be used as an identifier.")

	private def CreateError(code as string, location as LexicalInfo, message as string):
		return Boo.Lang.Compiler.CompilerError(code, location, message, null)