### ----------------------------------------------------
### -- ASTQuery
### -- Licenses: Artistic-2.0
### -- Authors: Fernando Corrêa de Oliveira
### -- File: t/02-ASTQuery.rakutest
### ----------------------------------------------------
use experimental :rakuast;
use ASTQuery;
use ASTQuery::Matcher;
use Test;

ok &ast-matcher;
ok &ast-query;

for %(
	"RakuAST::Node" => %(
		meth  => "classes",
		value => Array[ASTQuery::Matcher::ASTClass(Any)].new("RakuAST::Node"),
	),
	".conditional" => %(
		meth  => "groups",
		value => Array[ASTQuery::Matcher::ASTGroup(Any)].new("conditional"),
	),
	"#blablabla" => %(
		meth  => "ids",
		value => ["blablabla", ],
	),
	"[attribute]" => %(
		meth  => "atts",
		value => %(attribute => True),
	),
	"RakuAST::Node > RakuAST::Node" => %(
		meth  => "child",
		value => ast-matcher("RakuAST::Node"),
	),
	"RakuAST::Node >> RakuAST::Node" => %(
		meth  => "gchild",
		value => ast-matcher("RakuAST::Node"),
	),
	"RakuAST::Node >>> RakuAST::Node" => %(
		meth  => "descendant",
		value => ast-matcher("RakuAST::Node"),
	),
	"RakuAST::Node < RakuAST::Node" => %(
		meth  => "parent",
		value => ast-matcher("RakuAST::Node"),
	),
	"RakuAST::Node << RakuAST::Node" => %(
		meth  => "gparent",
		value => ast-matcher("RakuAST::Node"),
	),
	"RakuAST::Node <<< RakuAST::Node" => %(
		meth  => "ascendant",
		value => ast-matcher("RakuAST::Node"),
	),
	'$name' => %(
		meth  => "name",
		value => "name",
	),
).kv -> $selector, %h (Str :$meth, :$value) {
	my $matcher = ast-matcher($selector);
	isa-ok $matcher, ASTQuery::Matcher, "isa-ok: " ~ %h.gist;
	is-deeply $matcher."$meth"(), $value, "is-deeply: " ~ %h.gist;
}

for %(
	Q|42| => %(
		matcher => Q|RakuAST::IntLiteral|,
		list    => [
			RakuAST::IntLiteral.new(42)
		],
		hash    => %(),
	),
	Q|42, 13, 3| => %(
		matcher => Q|RakuAST::IntLiteral|,
		list    => [
			RakuAST::IntLiteral.new(42),
			RakuAST::IntLiteral.new(13),
			RakuAST::IntLiteral.new(3),
		],
		hash    => %(),
	),
	Q|42, 13, 3| => %(
		matcher => Q|.int|,
		list    => [
			RakuAST::IntLiteral.new(42),
			RakuAST::IntLiteral.new(13),
			RakuAST::IntLiteral.new(3),
		],
		hash    => %(),
	),
	Q|42, 13, 3| => %(
		matcher => Q|#42|,
		list    => [
			RakuAST::IntLiteral.new(42),
		],
		hash    => %(),
	),
	Q|42, 13, 3| => %(
		matcher => Q|[value=42]|,
		list    => [
			RakuAST::IntLiteral.new(42),
		],
		hash    => %(),
	),
	Q|42, 13, 3| => %(
		matcher => Q|.int$test|,
		list    => [
			RakuAST::IntLiteral.new(42),
			RakuAST::IntLiteral.new(13),
			RakuAST::IntLiteral.new(3),
		],
		hash    => %(
			:test[
				RakuAST::IntLiteral.new(42),
				RakuAST::IntLiteral.new(13),
				RakuAST::IntLiteral.new(3),
			]
		),
	),
	Q|say 42| => %(
		matcher => Q|.call >> .int$integer|,
		list    => [
			RakuAST::Call::Name::WithoutParentheses.new(
				name => RakuAST::Name.from-identifier("say"),
				args => RakuAST::ArgList.new(
					RakuAST::IntLiteral.new(42),
				)
			)
		],
		hash    => %(
			:integer( RakuAST::IntLiteral.new(42) )
		),
	),
).kv -> Str $ast, % (Str :$matcher, :@list, :%hash) {
	diag "$ast ~~ $matcher";
	is-deeply ast-query($ast.AST, ast-matcher $matcher),
		ASTQuery::Match.new(
			:@list,
			:%hash,
			:matcher(ast-matcher $matcher),
			:ast($ast.AST),
		)
	;
	is-deeply ast-query($ast.AST, $matcher),
		ASTQuery::Match.new(
			:@list,
			:%hash,
			:matcher(ast-matcher $matcher),
			:ast($ast.AST),
		)
	;
}

done-testing


