<commit_before>namespace Boo.OMeta.Tests

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

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

[TestFixture]
class ObjectMatchingTest:
	
	[Test]
	def PropertyPatternMatching():
		ometa ConstList:
			option ParseTree
			parse = ++(Const(value) ^ value)
			
		match ConstList().parse(OMetaInput.For([Const(1), Const(42)])):
			case SuccessfulMatch(Input, Value):
				assert Input.IsEmpty
				Assert.AreEqual([1, 42], Value)
		
	[Test]
	def PropertyParsing():
		ometa Evaluator:
			eval = const | sum
			const = Const(value) ^ value
			sum = Sum(left: eval >> l as int, right: eval >> r as int) ^ (l + r)
				
		match Evaluator().eval(OMetaInput.Singleton(Sum(Const(21), Sum(Const(11), Const(10))))):
			case SuccessfulMatch(Input, Value):
				assert Input.IsEmpty
				Assert.AreEqual(42, Value)
				
	[Test]
	def StringFieldMatchingWithCustomRule():
			
		data Person(name)
		
		ometa JohnOrPaulMatcher:
			john = "John "
			paul = "Paul "
			john_or_paul = john | paul
			match = Person(name: string[john_or_paul] >> _)
			string[rule] = $(string_matching(rule, input, context))
		
		def john_or_paul(person): 
			return JohnOrPaulMatcher().match(OMetaInput.Singleton(person))
		
		match john_or_paul(Person("<NAME>")):
			case SuccessfulMatch(Input):
				assert Input.IsEmpty
				
		match john_or_paul(Person("<NAME>")):
			case SuccessfulMatch(Input):
				assert Input.IsEmpty
				
		match john_or_paul(Person("Eric")):
			case FailedMatch(Input):
				assert Input.Head == "Eric"
				
		match john_or_paul(Person(42)):
			case FailedMatch(Input, Failure: ObjectPatternFailure(Pattern)):
				assert Input.Head == 42
				assert Pattern == "'42' is not a string"
				
	static def string_matching(rule as string, input as OMetaInput, context as OMetaEvaluationContext):
		match input.Head:
			case s = string():
				match context.Eval(rule, OMetaInput.For(s)):
					case SuccessfulMatch():
						return SuccessfulMatch(input.Tail, input.Head)
					case FailedMatch(Failure):
						return FailedMatch(input, Failure)
			otherwise:
				return FailedMatch(input, ObjectPatternFailure("'$(input.Head)' is not a string"))<commit_msg>simplify custom rule application by moving it to the grammar definition<commit_after>namespace Boo.OMeta.Tests

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

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

[TestFixture]
class ObjectMatchingTest:
	
	[Test]
	def PropertyPatternMatching():
		ometa ConstList:
			option ParseTree
			parse = ++(Const(value) ^ value)
			
		match ConstList().parse(OMetaInput.For([Const(1), Const(42)])):
			case SuccessfulMatch(Input, Value):
				assert Input.IsEmpty
				Assert.AreEqual([1, 42], Value)
		
	[Test]
	def PropertyParsing():
		ometa Evaluator:
			eval = const | sum
			const = Const(value) ^ value
			sum = Sum(left: eval >> l as int, right: eval >> r as int) ^ (l + r)
				
		match Evaluator().eval(OMetaInput.Singleton(Sum(Const(21), Sum(Const(11), Const(10))))):
			case SuccessfulMatch(Input, Value):
				assert Input.IsEmpty
				Assert.AreEqual(42, Value)
				
	[Test]
	def StringFieldMatchingWithCustomRule():
			
		data Person(name)
		
		ometa JohnOrPaulMatcher:
					
			match = Person(name: string_matching[john_or_paul] >> _)
			john = "John "
			paul = "Paul "
			john_or_paul = john | paul
			
			string_matching[rule] = $(string_matching(rule, input))
			
			def string_matching(rule as string, input as OMetaInput):
				match input.Head:
					case s = string():
						match Apply(rule, OMetaInput.For(s)):
							case SuccessfulMatch():
								return SuccessfulMatch(input.Tail, input.Head)
							case FailedMatch(Failure):
								return FailedMatch(input, Failure)
					otherwise:
						return FailedMatch(input, ObjectPatternFailure("'$(input.Head)' is not a string"))
		
		def john_or_paul(person): 
			return JohnOrPaulMatcher().match(OMetaInput.Singleton(person))
		
		match john_or_paul(Person("<NAME>")):
			case SuccessfulMatch(Input):
				assert Input.IsEmpty
				
		match john_or_paul(Person("<NAME>")):
			case SuccessfulMatch(Input):
				assert Input.IsEmpty
				
		match john_or_paul(Person("Eric")):
			case FailedMatch(Input):
				assert Input.Head == "Eric"
				
		match john_or_paul(Person(42)):
			case FailedMatch(Input, Failure: ObjectPatternFailure(Pattern)):
				assert Input.Head == 42
				assert Pattern == "'42' is not a string"
{'fraction_non_alphanumeric': 0.12030242383811429, 'fraction_numerical': 0.008894818768067601, 'mean_word_length': 3.921225382932166, 'pattern_counts': {'":': 0, '<': 7, '<?xml version=': 0, '>': 19, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '5617701', 'n_tokens_mistral': 1816, 'n_tokens_neox': 1443, 'n_words': 358}