use v6.e.PREVIEW; use Test; plan 7; my $ast; my $deparsed; my $raku; sub ast(RakuAST::Node:D $node --> Nil) { $ast := $node; $deparsed := $node.DEPARSE; $raku := 'use experimental :rakuast; ' ~ $node.raku; diag $deparsed.chomp; } # NOTE: always using scope "my" for these tests to prevent redefined # errors. subtest 'Simplest subset Foo' => { # my subset Foo ast RakuAST::Type::Subset.new( scope => 'my', name => RakuAST::Name.from-identifier("Foo") ); is-deeply $deparsed, 'my subset Foo', 'deparse'; for 'AST', EVAL($ast), 'Str', EVAL($deparsed), 'Raku', EVAL(EVAL $raku) -> $type, $subset { is-deeply $subset.^name, "Foo", "$type: is name ok"; is-deeply $subset.^refinee, Any, "$type: is refinee ok"; is-deeply $subset.^refinement, Mu, "$type: is refinement ok"; ok 42 ~~ $subset, "$type: subset accepts 42"; ok "foo" ~~ $subset, "$type: subset accepts foo"; ok Any ~~ $subset, "$type: subset accepts Any"; nok Mu ~~ $subset, "$type: subset does not accept Mu"; } } subtest 'Simple subset Foo of Int' => { # my subset Foo ast RakuAST::Type::Subset.new( scope => 'my', name => RakuAST::Name.from-identifier("Foo"), of => RakuAST::Trait::Of.new( RakuAST::Type::Simple.new( RakuAST::Name.from-identifier("Int") ) ) ); is-deeply $deparsed, 'my subset Foo of Int', 'deparse'; for 'AST', EVAL($ast), 'Str', EVAL($deparsed), 'Raku', EVAL(EVAL $raku) -> $type, $subset { is-deeply $subset.^name, "Foo", "$type: is name ok"; is-deeply $subset.^refinee, Int, "$type: is refinee ok"; is-deeply $subset.^refinement, Mu, "$type: is refinement ok"; ok 42 ~~ $subset, "$type: subset accepts 42"; nok "foo" ~~ $subset, "$type: subset does not accept foo"; nok Any ~~ $subset, "$type: subset does not accept Any"; } } subtest 'Subset with a where block' => { # my subset Foo of Int where { $_ %% 2 } ast RakuAST::Type::Subset.new( scope => 'my', name => RakuAST::Name.from-identifier("Foo"), of => RakuAST::Trait::Of.new( RakuAST::Type::Simple.new( RakuAST::Name.from-identifier("Int") ) ), where => RakuAST::Block.new( body => RakuAST::Blockoid.new( RakuAST::StatementList.new( RakuAST::Statement::Expression.new( expression => RakuAST::ApplyInfix.new( left => RakuAST::Var::Lexical.new('$_'), infix => RakuAST::Infix.new('%%'), right => RakuAST::IntLiteral.new(2) ) ) ) ) ) ); is-deeply $deparsed, q:to/CODE/.chomp, 'deparse'; my subset Foo of Int where { $_ %% 2 } CODE for 'AST', EVAL($ast), 'Str', EVAL($deparsed), 'Raku', EVAL(EVAL $raku) -> $type, $subset { is-deeply $subset.^name, "Foo", "$type: is name ok"; is-deeply $subset.^refinee, Int, "$type: is refinee ok"; isa-ok $subset.^refinement, Block, "$type: is refinement ok"; ok 42 ~~ $subset, "$type: subset accepts 42"; nok 41 ~~ $subset, "$type: subset does not accept 41"; nok "foo" ~~ $subset, "$type: subset does not accept foo"; nok Any ~~ $subset, "$type: subset does not accept Any"; } } subtest 'Subset with a where pointy block' => { # my subset Foo of Int where -> $a { $a %% 2 } ast RakuAST::Type::Subset.new( scope => 'my', name => RakuAST::Name.from-identifier("Foo"), of => RakuAST::Trait::Of.new( RakuAST::Type::Simple.new( RakuAST::Name.from-identifier("Int") ) ), where => RakuAST::PointyBlock.new( signature => RakuAST::Signature.new( parameters => ( RakuAST::Parameter.new( target => RakuAST::ParameterTarget::Var.new('$a') ), ) ), body => RakuAST::Blockoid.new( RakuAST::StatementList.new( RakuAST::Statement::Expression.new( expression => RakuAST::ApplyInfix.new( left => RakuAST::Var::Lexical.new('$a'), infix => RakuAST::Infix.new('%%'), right => RakuAST::IntLiteral.new(2) ) ) ) ) ) ); is-deeply $deparsed, q:to/CODE/.chomp, 'deparse'; my subset Foo of Int where -> $a { $a %% 2 } CODE for 'AST', EVAL($ast), 'Str', EVAL($deparsed), 'Raku', EVAL(EVAL $raku) -> $type, $subset { is-deeply $subset.^name, "Foo", "$type: is name ok"; is-deeply $subset.^refinee, Int, "$type: is refinee ok"; isa-ok $subset.^refinement, Block, "$type: is refinement ok"; ok 42 ~~ $subset, "$type: subset accepts 42"; nok 41 ~~ $subset, "$type: subset does not accept 41"; nok "foo" ~~ $subset, "$type: subset does not accept foo"; nok Any ~~ $subset, "$type: subset does not accept Any"; } } subtest 'Subset with a where whatevercode' => { # my subset Foo of Int where * %% 2 ast RakuAST::Type::Subset.new( scope => 'my', name => RakuAST::Name.from-identifier("Foo"), of => RakuAST::Trait::Of.new( RakuAST::Type::Simple.new( RakuAST::Name.from-identifier("Int") ) ), where => RakuAST::ApplyInfix.new( left => RakuAST::Term::Whatever.new, infix => RakuAST::Infix.new('%%'), right => RakuAST::IntLiteral.new(2) ) ); is-deeply $deparsed, 'my subset Foo of Int where * %% 2', 'deparse'; for 'AST', EVAL($ast), 'Str', EVAL($deparsed), 'Raku', EVAL(EVAL $raku) -> $type, $subset { is-deeply $subset.^name, "Foo", "$type: is name ok"; is-deeply $subset.^refinee, Int, "$type: is refinee ok"; isa-ok $subset.^refinement, WhateverCode, "$type: is refinement ok"; ok 42 ~~ $subset, "$type: subset accepts 42"; nok 41 ~~ $subset, "$type: subset does not accept 41"; nok "foo" ~~ $subset, "$type: subset does not accept foo"; nok Any ~~ $subset, "$type: subset does not accept Any"; } } subtest 'Subset with a where literal' => { # my subset Foo where 42 ast RakuAST::Type::Subset.new( scope => 'my', name => RakuAST::Name.from-identifier("Foo"), where => RakuAST::IntLiteral.new(42) ); is-deeply $deparsed, 'my subset Foo where 42', 'deparse'; for 'AST', EVAL($ast), 'Str', EVAL($deparsed), 'Raku', EVAL(EVAL $raku) -> $type, $subset { is-deeply $subset.^name, "Foo", "$type: is name ok"; is-deeply $subset.^refinee, Any, "$type: is refinee ok"; isa-ok $subset.^refinement, Block, "$type: is refinement ok"; ok 42 ~~ $subset, "$type: subset accepts 42"; nok 41 ~~ $subset, "$type: subset does not accept 41"; nok "foo" ~~ $subset, "$type: subset does not accept foo"; } } subtest 'Subset with a where regex' => { # my subset Foo where / 42/ ast RakuAST::Type::Subset.new( scope => 'my', name => RakuAST::Name.from-identifier("Foo"), where => RakuAST::QuotedRegex.new( body => RakuAST::Regex::Literal.new('42') ) ); is-deeply $deparsed, 'my subset Foo where / 42/', 'deparse'; for 'AST', EVAL($ast), 'Str', EVAL($deparsed), 'Raku', EVAL(EVAL $raku) -> $type, $subset { is-deeply $subset.^name, "Foo", "$type: is name ok"; is-deeply $subset.^refinee, Any, "$type: is refinee ok"; isa-ok $subset.^refinement, Block, "$type: is refinement ok"; ok 42 ~~ $subset, "$type: subset accepts 42"; nok 41 ~~ $subset, "$type: subset does not accept 41"; nok "foo" ~~ $subset, "$type: subset does not accept foo"; } } # vim: expandtab shiftwidth=4