Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
A
Actor Framework
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Operations
Operations
Metrics
Environments
Analytics
Analytics
CI / CD
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
cpp-libs
Actor Framework
Commits
daa5a857
Commit
daa5a857
authored
Sep 05, 2013
by
Dominik Charousset
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
improved pattern matching unit test
parent
622f6303
Changes
1
Hide whitespace changes
Inline
Side-by-side
Showing
1 changed file
with
327 additions
and
297 deletions
+327
-297
unit_testing/test_match.cpp
unit_testing/test_match.cpp
+327
-297
No files found.
unit_testing/test_match.cpp
View file @
daa5a857
...
...
@@ -47,310 +47,340 @@ void foobar(index_token<Pos, Max>) {
foobar
(
index_token
<
Pos
+
1
,
Max
>
{});
}
void
test_simple_guards
()
{
auto
ascending
=
[](
int
a
,
int
b
,
int
c
)
->
bool
{
return
a
<
b
&&
b
<
c
;
};
auto
expr0_a
=
gcall
(
ascending
,
_x1
,
_x2
,
_x3
);
CPPA_CHECK
(
ge_invoke
(
expr0_a
,
1
,
2
,
3
));
CPPA_CHECK
(
!
ge_invoke
(
expr0_a
,
3
,
2
,
1
));
int
ival0
=
2
;
auto
expr0_b
=
gcall
(
ascending
,
_x1
,
std
::
ref
(
ival0
),
_x2
);
CPPA_CHECK
(
ge_invoke
(
expr0_b
,
1
,
3
));
++
ival0
;
CPPA_CHECK
(
!
ge_invoke
(
expr0_b
,
1
,
3
));
auto
expr0_c
=
gcall
(
ascending
,
10
,
_x1
,
30
);
CPPA_CHECK
(
!
ge_invoke
(
expr0_c
,
10
));
CPPA_CHECK
(
ge_invoke
(
expr0_c
,
11
));
// user-defined expressions using '+', '<', '%'
auto
expr1
=
_x1
+
_x2
;
auto
expr2
=
_x1
+
_x2
<
_x3
;
auto
expr3
=
_x1
%
_x2
==
0
;
CPPA_CHECK_EQUAL
((
ge_invoke
(
expr1
,
2
,
3
)),
5
);
CPPA_CHECK
(
expr2
(
1
,
2
,
4
));
CPPA_CHECK_EQUAL
((
ge_invoke
(
expr1
,
std
::
string
{
"1"
},
std
::
string
{
"2"
})),
"12"
);
CPPA_CHECK
(
expr3
(
100
,
2
));
// user-defined expressions using '||'
auto
expr4
=
_x1
==
"-h"
||
_x1
==
"--help"
;
CPPA_CHECK
(
ge_invoke
(
expr4
,
string
(
"-h"
)));
CPPA_CHECK
(
ge_invoke
(
expr4
,
string
(
"--help"
)));
CPPA_CHECK
(
!
ge_invoke
(
expr4
,
string
(
"-g"
)));
}
int
main
()
{
CPPA_TEST
(
test_match
);
/* test guard evaluation */
{
// ascending values
auto
ascending
=
[](
int
a
,
int
b
,
int
c
)
->
bool
{
return
a
<
b
&&
b
<
c
;
};
auto
expr0_a
=
gcall
(
ascending
,
_x1
,
_x2
,
_x3
);
CPPA_CHECK
(
ge_invoke
(
expr0_a
,
1
,
2
,
3
));
CPPA_CHECK
(
!
ge_invoke
(
expr0_a
,
3
,
2
,
1
));
int
ival0
=
2
;
auto
expr0_b
=
gcall
(
ascending
,
_x1
,
std
::
ref
(
ival0
),
_x2
);
CPPA_CHECK
(
ge_invoke
(
expr0_b
,
1
,
3
));
++
ival0
;
CPPA_CHECK
(
!
ge_invoke
(
expr0_b
,
1
,
3
));
auto
expr0_c
=
gcall
(
ascending
,
10
,
_x1
,
30
);
CPPA_CHECK
(
!
ge_invoke
(
expr0_c
,
10
));
CPPA_CHECK
(
ge_invoke
(
expr0_c
,
11
));
// user-defined expressions using '+', '<', '%'
auto
expr1
=
_x1
+
_x2
;
auto
expr2
=
_x1
+
_x2
<
_x3
;
auto
expr3
=
_x1
%
_x2
==
0
;
CPPA_CHECK_EQUAL
((
ge_invoke
(
expr1
,
2
,
3
)),
5
);
CPPA_CHECK
(
expr2
(
1
,
2
,
4
));
CPPA_CHECK_EQUAL
((
ge_invoke
(
expr1
,
std
::
string
{
"1"
},
std
::
string
{
"2"
})),
"12"
);
CPPA_CHECK
(
expr3
(
100
,
2
));
// user-defined expressions using '||'
auto
expr4
=
_x1
==
"-h"
||
_x1
==
"--help"
;
CPPA_CHECK
(
ge_invoke
(
expr4
,
string
(
"-h"
)));
CPPA_CHECK
(
ge_invoke
(
expr4
,
string
(
"--help"
)));
CPPA_CHECK
(
!
ge_invoke
(
expr4
,
string
(
"-g"
)));
}
/* guard expressions on containers */
{
auto
expr5
=
_x1
.
starts_with
(
"--"
);
CPPA_CHECK
(
ge_invoke
(
expr5
,
string
(
"--help"
)));
CPPA_CHECK
(
!
ge_invoke
(
expr5
,
string
(
"-help"
)));
// container search (x in y)
vector
<
string
>
vec1
{
"hello"
,
"world"
};
auto
expr6
=
_x1
.
in
(
vec1
);
CPPA_CHECK
(
ge_invoke
(
expr6
,
string
(
"hello"
)));
CPPA_CHECK
(
ge_invoke
(
expr6
,
string
(
"world"
)));
CPPA_CHECK
(
!
ge_invoke
(
expr6
,
string
(
"hello world"
)));
auto
expr7
=
_x1
.
in
(
std
::
ref
(
vec1
));
CPPA_CHECK
(
ge_invoke
(
expr7
,
string
(
"hello"
)));
CPPA_CHECK
(
ge_invoke
(
expr7
,
string
(
"world"
)));
CPPA_CHECK
(
!
ge_invoke
(
expr7
,
string
(
"hello world"
)));
vec1
.
emplace_back
(
"hello world"
);
CPPA_CHECK
(
!
ge_invoke
(
expr6
,
string
(
"hello world"
)));
CPPA_CHECK
(
ge_invoke
(
expr7
,
string
(
"hello world"
)));
// container search (x in y) for initializer lists
auto
expr11
=
_x1
.
in
({
"one"
,
"two"
});
CPPA_CHECK
(
ge_invoke
(
expr11
,
string
(
"one"
)));
CPPA_CHECK
(
ge_invoke
(
expr11
,
string
(
"two"
)));
CPPA_CHECK
(
!
ge_invoke
(
expr11
,
string
(
"three"
)));
// container search (x not in y)
auto
expr12
=
_x1
.
not_in
({
"hello"
,
"world"
});
CPPA_CHECK
(
ge_invoke
(
expr12
,
string
(
"foo"
)));
CPPA_CHECK
(
!
ge_invoke
(
expr12
,
string
(
"hello"
)));
// user-defined function to evaluate whether container is sorted
std
::
vector
<
int
>
expr21_vec_a
{
1
,
2
,
3
};
std
::
vector
<
int
>
expr21_vec_b
{
1
,
0
,
2
};
auto
expr21
=
gcall
(
vec_sorted
,
_x1
);
CPPA_CHECK
(
ge_invoke
(
expr21
,
expr21_vec_a
));
CPPA_CHECK
(
!
ge_invoke
(
expr21
,
expr21_vec_b
));
auto
expr22
=
_x1
.
empty
()
&&
_x2
.
not_empty
();
CPPA_CHECK
(
ge_invoke
(
expr22
,
std
::
string
(
""
),
std
::
string
(
"abc"
)));
}
/* user-defined expressions */
{
int
ival
=
5
;
auto
expr8
=
_x1
==
ival
;
auto
expr9
=
_x1
==
std
::
ref
(
ival
);
CPPA_CHECK
(
ge_invoke
(
expr8
,
5
));
CPPA_CHECK
(
ge_invoke
(
expr9
,
5
));
ival
=
10
;
CPPA_CHECK
(
!
ge_invoke
(
expr9
,
5
));
CPPA_CHECK
(
ge_invoke
(
expr9
,
10
));
// user-defined expressions w/ wide range of operators
auto
expr13
=
_x1
*
_x2
<
_x3
-
_x4
;
CPPA_CHECK
(
ge_invoke
(
expr13
,
1
,
1
,
4
,
2
));
auto
expr14
=
_x1
+
_x2
;
static_assert
(
std
::
is_same
<
decltype
(
ge_invoke
(
expr14
,
1
,
2
)),
int
>::
value
,
"wrong return type"
);
CPPA_CHECK_EQUAL
((
ge_invoke
(
expr14
,
2
,
3
)),
5
);
auto
expr15
=
_x1
+
_x2
+
_x3
;
static_assert
(
std
::
is_same
<
decltype
(
ge_invoke
(
expr15
,
1
,
2
,
3
)),
int
>::
value
,
"wrong return type"
);
CPPA_CHECK_EQUAL
((
ge_invoke
(
expr15
,
7
,
10
,
25
)),
42
);
// user-defined operations on containers such as 'size' and 'front'
std
::
string
expr16_str
;
// = "expr16";
auto
expr16_a
=
_x1
.
size
();
auto
expr16_b
=
_x1
.
front
()
==
'e'
;
CPPA_CHECK_EQUAL
((
ge_invoke
(
expr16_b
,
expr16_str
)),
false
);
CPPA_CHECK_EQUAL
((
ge_invoke
(
expr16_a
,
expr16_str
)),
0
);
expr16_str
=
"expr16"
;
CPPA_CHECK_EQUAL
((
ge_invoke
(
expr16_b
,
expr16_str
)),
true
);
CPPA_CHECK_EQUAL
((
ge_invoke
(
expr16_a
,
expr16_str
)),
expr16_str
.
size
());
expr16_str
.
front
()
=
'_'
;
CPPA_CHECK_EQUAL
((
ge_invoke
(
expr16_b
,
expr16_str
)),
false
);
}
/* user-defined expressions using 'gref' */
{
int
expr17_value
=
42
;
auto
expr17
=
gref
(
expr17_value
)
==
42
;
CPPA_CHECK_EQUAL
(
ge_invoke
(
expr17
),
true
);
expr17_value
=
0
;
CPPA_CHECK_EQUAL
(
ge_invoke
(
expr17
),
false
);
int
expr18_value
=
42
;
auto
expr18_a
=
gref
(
expr18_value
)
==
42
;
CPPA_CHECK_EQUAL
(
ge_invoke
(
expr18_a
),
true
);
expr18_value
=
0
;
CPPA_CHECK_EQUAL
(
ge_invoke
(
expr18_a
),
false
);
auto
expr18_b
=
gref
(
expr18_value
)
==
_x1
;
auto
expr18_c
=
std
::
ref
(
expr18_value
)
==
_x1
;
CPPA_CHECK_EQUAL
((
ge_invoke
(
expr18_b
,
0
)),
true
);
CPPA_CHECK_EQUAL
((
ge_invoke
(
expr18_c
,
0
)),
true
);
bool
enable_case1
=
true
;
auto
expr19
=
(
on
<
anything
>
().
when
(
gref
(
enable_case1
)
==
false
)
>>
[]
{
return
1
;
},
on
<
anything
>
()
>>
[]
{
return
2
;
}
);
any_tuple
expr19_tup
=
make_cow_tuple
(
"hello guard!"
);
CPPA_CHECK_EQUAL
(
expr19
(
expr19_tup
),
2
);
partial_function
expr20
=
expr19
;
enable_case1
=
false
;
CPPA_CHECK
(
expr20
(
expr19_tup
)
==
make_any_tuple
(
1
));
partial_function
expr21
{
on
(
atom
(
"add"
),
arg_match
)
>>
[](
int
a
,
int
b
)
{
return
a
+
b
;
}
};
CPPA_CHECK
(
expr21
(
make_any_tuple
(
atom
(
"add"
),
1
,
2
))
==
make_any_tuple
(
3
));
CPPA_CHECK
(
!
expr21
(
make_any_tuple
(
atom
(
"sub"
),
1
,
2
)));
}
/* test 'match' function */
{
auto
res0
=
match
(
5
)
(
on_arg_match
.
when
(
_x1
<
6
)
>>
[
&
](
int
i
)
{
CPPA_CHECK_EQUAL
(
i
,
5
);
}
);
CPPA_CHECK
(
res0
);
auto
res1
=
match
(
"value=42"
)
(
on
(
kvp_split
).
when
(
_x1
.
not_empty
())
>>
[
&
](
const
vector
<
string
>&
vec
)
{
CPPA_CHECK_EQUAL
(
"value"
,
vec
[
0
]);
CPPA_CHECK_EQUAL
(
"42"
,
vec
[
1
]);
}
);
CPPA_CHECK
(
res1
);
auto
res2
=
match
(
"42"
)
(
on
(
toint
)
>>
[
&
](
int
i
)
{
CPPA_CHECK_EQUAL
(
42
,
i
);
}
);
CPPA_CHECK
(
res2
);
auto
res3
=
match
(
"abc"
)
(
on
<
string
>
().
when
(
_x1
==
"abc"
)
>>
[
&
]
{
}
);
CPPA_CHECK
(
res3
);
CPPA_CHECK
(
res3
.
is
<
void
>
());
// match vectors
auto
res4
=
match
(
std
::
vector
<
int
>
{
1
,
2
,
3
})
(
on
<
int
,
int
,
int
>
().
when
(
_x1
+
_x2
+
_x3
==
6
&&
_x2
(
is_even
)
&&
_x3
%
2
==
1
)
>>
[
&
]
{
}
);
CPPA_CHECK
(
res4
);
vector
<
string
>
vec
{
"a"
,
"b"
,
"c"
};
auto
res5
=
match
(
vec
)
(
on
(
"a"
,
"b"
,
val
<
string
>
)
>>
[](
string
&
)
->
string
{
return
"C"
;
}
);
CPPA_CHECK_EQUAL
(
res5
,
"C"
);
}
/* test 'match_each' */
{
string
sum
;
vector
<
string
>
sum_args
=
{
"-h"
,
"--version"
,
"-wtf"
};
auto
iter1
=
match_each
(
begin
(
sum_args
),
end
(
sum_args
))
(
on
<
string
>
().
when
(
_x1
.
in
({
"-h"
,
"--help"
}))
>>
[
&
](
const
string
&
s
)
{
sum
+=
s
;
},
on
<
string
>
().
when
(
_x1
==
"-v"
||
_x1
==
"--version"
)
>>
[
&
](
const
string
&
s
)
{
sum
+=
s
;
},
on
<
string
>
().
when
(
_x1
.
starts_with
(
"-"
))
>>
[
&
](
const
string
&
str
)
{
match_each
(
str
.
begin
()
+
1
,
str
.
end
())
(
on
<
char
>
().
when
(
_x1
.
in
({
'w'
,
't'
,
'f'
}))
>>
[
&
](
char
c
)
{
sum
+=
c
;
},
on
<
char
>
()
>>
CPPA_FAILURE_CB
(
"guard didn't match"
),
others
()
>>
CPPA_FAILURE_CB
(
"unexpected match"
)
);
}
);
CPPA_CHECK
(
iter1
==
end
(
sum_args
));
CPPA_CHECK_EQUAL
(
sum
,
"-h--versionwtf"
);
auto
iter2
=
match_each
(
begin
(
sum_args
),
end
(
sum_args
))
(
on
(
"-h"
)
>>
[]
{
}
);
CPPA_CHECK
(
iter2
==
(
begin
(
sum_args
)
+
1
));
}
/* test match_stream */
{
bool
success
=
false
;
istringstream
iss
(
"hello world"
);
success
=
match_stream
<
string
>
(
iss
)
(
on
(
"hello"
,
"world"
)
>>
CPPA_CHECKPOINT_CB
()
);
CPPA_CHECK_EQUAL
(
success
,
true
);
auto
extract_name
=
[](
const
string
&
kvp
)
->
optional
<
string
>
{
auto
vec
=
split
(
kvp
,
'='
);
if
(
vec
.
size
()
==
2
&&
vec
.
front
()
==
"--name"
)
return
vec
.
back
();
return
none
;
};
const
char
*
svec
[]
=
{
"-n"
,
"foo"
,
"--name=bar"
,
"-p"
,
"2"
};
success
=
match_stream
<
string
>
(
begin
(
svec
),
end
(
svec
))
(
(
on
(
"-n"
,
arg_match
)
||
on
(
extract_name
))
>>
[](
const
string
&
name
)
->
bool
{
CPPA_CHECK
(
name
==
"foo"
||
name
==
"bar"
);
return
name
==
"foo"
||
name
==
"bar"
;
},
on
(
"-p"
,
arg_match
)
>>
[
&
](
const
string
&
port
)
->
match_hint
{
auto
i
=
toint
(
port
);
if
(
i
)
{
CPPA_CHECK_EQUAL
(
*
i
,
2
);
return
match_hint
::
handle
;
}
else
return
match_hint
::
skip
;
},
on_arg_match
>>
[](
const
string
&
arg
)
->
match_hint
{
CPPA_FAILURE
(
"unexpected string: "
<<
arg
);
return
match_hint
::
skip
;
void
test_container_guards
()
{
auto
expr5
=
_x1
.
starts_with
(
"--"
);
CPPA_CHECK
(
ge_invoke
(
expr5
,
string
(
"--help"
)));
CPPA_CHECK
(
!
ge_invoke
(
expr5
,
string
(
"-help"
)));
// container search (x in y)
vector
<
string
>
vec1
{
"hello"
,
"world"
};
auto
expr6
=
_x1
.
in
(
vec1
);
CPPA_CHECK
(
ge_invoke
(
expr6
,
string
(
"hello"
)));
CPPA_CHECK
(
ge_invoke
(
expr6
,
string
(
"world"
)));
CPPA_CHECK
(
!
ge_invoke
(
expr6
,
string
(
"hello world"
)));
auto
expr7
=
_x1
.
in
(
std
::
ref
(
vec1
));
CPPA_CHECK
(
ge_invoke
(
expr7
,
string
(
"hello"
)));
CPPA_CHECK
(
ge_invoke
(
expr7
,
string
(
"world"
)));
CPPA_CHECK
(
!
ge_invoke
(
expr7
,
string
(
"hello world"
)));
vec1
.
emplace_back
(
"hello world"
);
CPPA_CHECK
(
!
ge_invoke
(
expr6
,
string
(
"hello world"
)));
CPPA_CHECK
(
ge_invoke
(
expr7
,
string
(
"hello world"
)));
// container search (x in y) for initializer lists
auto
expr11
=
_x1
.
in
({
"one"
,
"two"
});
CPPA_CHECK
(
ge_invoke
(
expr11
,
string
(
"one"
)));
CPPA_CHECK
(
ge_invoke
(
expr11
,
string
(
"two"
)));
CPPA_CHECK
(
!
ge_invoke
(
expr11
,
string
(
"three"
)));
// container search (x not in y)
auto
expr12
=
_x1
.
not_in
({
"hello"
,
"world"
});
CPPA_CHECK
(
ge_invoke
(
expr12
,
string
(
"foo"
)));
CPPA_CHECK
(
!
ge_invoke
(
expr12
,
string
(
"hello"
)));
// user-defined function to evaluate whether container is sorted
std
::
vector
<
int
>
expr21_vec_a
{
1
,
2
,
3
};
std
::
vector
<
int
>
expr21_vec_b
{
1
,
0
,
2
};
auto
expr21
=
gcall
(
vec_sorted
,
_x1
);
CPPA_CHECK
(
ge_invoke
(
expr21
,
expr21_vec_a
));
CPPA_CHECK
(
!
ge_invoke
(
expr21
,
expr21_vec_b
));
auto
expr22
=
_x1
.
empty
()
&&
_x2
.
not_empty
();
CPPA_CHECK
(
ge_invoke
(
expr22
,
std
::
string
(
""
),
std
::
string
(
"abc"
)));
}
void
test_user_defined_expressions
()
{
int
ival
=
5
;
auto
expr8
=
_x1
==
ival
;
auto
expr9
=
_x1
==
std
::
ref
(
ival
);
CPPA_CHECK
(
ge_invoke
(
expr8
,
5
));
CPPA_CHECK
(
ge_invoke
(
expr9
,
5
));
ival
=
10
;
CPPA_CHECK
(
!
ge_invoke
(
expr9
,
5
));
CPPA_CHECK
(
ge_invoke
(
expr9
,
10
));
// user-defined expressions w/ wide range of operators
auto
expr13
=
_x1
*
_x2
<
_x3
-
_x4
;
CPPA_CHECK
(
ge_invoke
(
expr13
,
1
,
1
,
4
,
2
));
auto
expr14
=
_x1
+
_x2
;
static_assert
(
std
::
is_same
<
decltype
(
ge_invoke
(
expr14
,
1
,
2
)),
int
>::
value
,
"wrong return type"
);
CPPA_CHECK_EQUAL
((
ge_invoke
(
expr14
,
2
,
3
)),
5
);
auto
expr15
=
_x1
+
_x2
+
_x3
;
static_assert
(
std
::
is_same
<
decltype
(
ge_invoke
(
expr15
,
1
,
2
,
3
)),
int
>::
value
,
"wrong return type"
);
CPPA_CHECK_EQUAL
((
ge_invoke
(
expr15
,
7
,
10
,
25
)),
42
);
// user-defined operations on containers such as 'size' and 'front'
std
::
string
expr16_str
;
// = "expr16";
auto
expr16_a
=
_x1
.
size
();
auto
expr16_b
=
_x1
.
front
()
==
'e'
;
CPPA_CHECK_EQUAL
((
ge_invoke
(
expr16_b
,
expr16_str
)),
false
);
CPPA_CHECK_EQUAL
((
ge_invoke
(
expr16_a
,
expr16_str
)),
0
);
expr16_str
=
"expr16"
;
CPPA_CHECK_EQUAL
((
ge_invoke
(
expr16_b
,
expr16_str
)),
true
);
CPPA_CHECK_EQUAL
((
ge_invoke
(
expr16_a
,
expr16_str
)),
expr16_str
.
size
());
expr16_str
.
front
()
=
'_'
;
CPPA_CHECK_EQUAL
((
ge_invoke
(
expr16_b
,
expr16_str
)),
false
);
}
void
test_gref
()
{
int
expr17_value
=
42
;
auto
expr17
=
gref
(
expr17_value
)
==
42
;
CPPA_CHECK_EQUAL
(
ge_invoke
(
expr17
),
true
);
expr17_value
=
0
;
CPPA_CHECK_EQUAL
(
ge_invoke
(
expr17
),
false
);
int
expr18_value
=
42
;
auto
expr18_a
=
gref
(
expr18_value
)
==
42
;
CPPA_CHECK_EQUAL
(
ge_invoke
(
expr18_a
),
true
);
expr18_value
=
0
;
CPPA_CHECK_EQUAL
(
ge_invoke
(
expr18_a
),
false
);
auto
expr18_b
=
gref
(
expr18_value
)
==
_x1
;
auto
expr18_c
=
std
::
ref
(
expr18_value
)
==
_x1
;
CPPA_CHECK_EQUAL
((
ge_invoke
(
expr18_b
,
0
)),
true
);
CPPA_CHECK_EQUAL
((
ge_invoke
(
expr18_c
,
0
)),
true
);
bool
enable_case1
=
true
;
auto
expr19
=
(
on
<
anything
>
().
when
(
gref
(
enable_case1
)
==
false
)
>>
[]
{
return
1
;
},
on
<
anything
>
()
>>
[]
{
return
2
;
}
);
any_tuple
expr19_tup
=
make_cow_tuple
(
"hello guard!"
);
CPPA_CHECK_EQUAL
(
expr19
(
expr19_tup
),
2
);
partial_function
expr20
=
expr19
;
enable_case1
=
false
;
CPPA_CHECK
(
expr20
(
expr19_tup
)
==
make_any_tuple
(
1
));
partial_function
expr21
{
on
(
atom
(
"add"
),
arg_match
)
>>
[](
int
a
,
int
b
)
{
return
a
+
b
;
}
};
CPPA_CHECK
(
expr21
(
make_any_tuple
(
atom
(
"add"
),
1
,
2
))
==
make_any_tuple
(
3
));
CPPA_CHECK
(
!
expr21
(
make_any_tuple
(
atom
(
"sub"
),
1
,
2
)));
}
void
test_match_function
()
{
auto
res0
=
match
(
5
)
(
on_arg_match
.
when
(
_x1
<
6
)
>>
[
&
](
int
i
)
{
CPPA_CHECK_EQUAL
(
i
,
5
);
}
);
CPPA_CHECK
(
res0
);
auto
res1
=
match
(
"value=42"
)
(
on
(
kvp_split
).
when
(
_x1
.
not_empty
())
>>
[
&
](
const
vector
<
string
>&
vec
)
{
CPPA_CHECK_EQUAL
(
"value"
,
vec
[
0
]);
CPPA_CHECK_EQUAL
(
"42"
,
vec
[
1
]);
}
);
CPPA_CHECK
(
res1
);
auto
res2
=
match
(
"42"
)
(
on
(
toint
)
>>
[
&
](
int
i
)
{
CPPA_CHECK_EQUAL
(
42
,
i
);
}
);
CPPA_CHECK
(
res2
);
auto
res3
=
match
(
"abc"
)
(
on
<
string
>
().
when
(
_x1
==
"abc"
)
>>
[
&
]
{
}
);
CPPA_CHECK
(
res3
);
CPPA_CHECK
(
res3
.
is
<
void
>
());
// match vectors
auto
res4
=
match
(
std
::
vector
<
int
>
{
1
,
2
,
3
})
(
on
<
int
,
int
,
int
>
().
when
(
_x1
+
_x2
+
_x3
==
6
&&
_x2
(
is_even
)
&&
_x3
%
2
==
1
)
>>
[
&
]
{
}
);
CPPA_CHECK
(
res4
);
vector
<
string
>
vec
{
"a"
,
"b"
,
"c"
};
auto
res5
=
match
(
vec
)
(
on
(
"a"
,
"b"
,
val
<
string
>
)
>>
[](
string
&
)
->
string
{
return
"C"
;
}
);
CPPA_CHECK_EQUAL
(
res5
,
"C"
);
}
void
test_match_each
()
{
string
sum
;
vector
<
string
>
sum_args
=
{
"-h"
,
"--version"
,
"-wtf"
};
auto
iter1
=
match_each
(
begin
(
sum_args
),
end
(
sum_args
))
(
on
<
string
>
().
when
(
_x1
.
in
({
"-h"
,
"--help"
}))
>>
[
&
](
const
string
&
s
)
{
sum
+=
s
;
},
on
<
string
>
().
when
(
_x1
==
"-v"
||
_x1
==
"--version"
)
>>
[
&
](
const
string
&
s
)
{
sum
+=
s
;
},
on
<
string
>
().
when
(
_x1
.
starts_with
(
"-"
))
>>
[
&
](
const
string
&
str
)
{
match_each
(
str
.
begin
()
+
1
,
str
.
end
())
(
on
<
char
>
().
when
(
_x1
.
in
({
'w'
,
't'
,
'f'
}))
>>
[
&
](
char
c
)
{
sum
+=
c
;
},
on
<
char
>
()
>>
CPPA_FAILURE_CB
(
"guard didn't match"
),
others
()
>>
CPPA_FAILURE_CB
(
"unexpected match"
)
);
}
);
CPPA_CHECK
(
iter1
==
end
(
sum_args
));
CPPA_CHECK_EQUAL
(
sum
,
"-h--versionwtf"
);
auto
iter2
=
match_each
(
begin
(
sum_args
),
end
(
sum_args
))
(
on
(
"-h"
)
>>
[]
{
}
);
CPPA_CHECK
(
iter2
==
(
begin
(
sum_args
)
+
1
));
}
void
test_match_stream
()
{
bool
success
=
false
;
istringstream
iss
(
"hello world"
);
success
=
match_stream
<
string
>
(
iss
)
(
on
(
"hello"
,
"world"
)
>>
CPPA_CHECKPOINT_CB
()
);
CPPA_CHECK_EQUAL
(
success
,
true
);
auto
extract_name
=
[](
const
string
&
kvp
)
->
optional
<
string
>
{
auto
vec
=
split
(
kvp
,
'='
);
if
(
vec
.
size
()
==
2
&&
vec
.
front
()
==
"--name"
)
return
vec
.
back
();
return
none
;
};
const
char
*
svec
[]
=
{
"-n"
,
"foo"
,
"--name=bar"
,
"-p"
,
"2"
};
success
=
match_stream
<
string
>
(
begin
(
svec
),
end
(
svec
))
(
(
on
(
"-n"
,
arg_match
)
||
on
(
extract_name
))
>>
[](
const
string
&
name
)
->
bool
{
CPPA_CHECK
(
name
==
"foo"
||
name
==
"bar"
);
return
name
==
"foo"
||
name
==
"bar"
;
},
on
(
"-p"
,
arg_match
)
>>
[
&
](
const
string
&
port
)
->
match_hint
{
auto
i
=
toint
(
port
);
if
(
i
)
{
CPPA_CHECK_EQUAL
(
*
i
,
2
);
return
match_hint
::
handle
;
}
);
CPPA_CHECK_EQUAL
(
success
,
true
);
}
// utility macro to identify invoked functors
else
return
match_hint
::
skip
;
},
on_arg_match
>>
[](
const
string
&
arg
)
->
match_hint
{
CPPA_FAILURE
(
"unexpected string: "
<<
arg
);
return
match_hint
::
skip
;
}
);
CPPA_CHECK_EQUAL
(
success
,
true
);
}
void
test_behavior
()
{
std
::
string
last_invoked_fun
;
# define bhvr_check(pf, tup, expected_result, str) { \
last_invoked_fun = ""; \
CPPA_CHECK_EQUAL(static_cast<bool>(pf(tup)), expected_result); \
CPPA_CHECK_EQUAL(last_invoked_fun, str); \
}
/* test if match hints are evaluated properly */
{
behavior
bhvr1
{
on
<
int
>
()
>>
[
&
](
int
i
)
->
match_hint
{
last_invoked_fun
=
"<int>@1"
;
return
(
i
==
42
)
?
match_hint
::
skip
:
match_hint
::
handle
;
},
on
<
float
>
()
>>
[
&
]
{
last_invoked_fun
=
"<float>@2"
;
},
on
<
int
>
()
>>
[
&
]
{
last_invoked_fun
=
"<int>@3"
;
},
others
()
>>
[
&
]
{
last_invoked_fun
=
"<*>@4"
;
}
};
bhvr_check
(
bhvr1
,
make_any_tuple
(
42
),
false
,
"<int>@1"
);
bhvr_check
(
bhvr1
,
make_any_tuple
(
24
),
true
,
"<int>@1"
);
bhvr_check
(
bhvr1
,
make_any_tuple
(
2.
f
),
true
,
"<float>@2"
);
bhvr_check
(
bhvr1
,
make_any_tuple
(
""
),
true
,
"<*>@4"
);
}
/* test or_else concatenation */
{
partial_function
pf0
{
on
<
int
,
int
>
()
>>
[
&
]
{
last_invoked_fun
=
"<int, int>@1"
;
},
on
<
float
>
()
>>
[
&
]
{
last_invoked_fun
=
"<float>@2"
;
}
};
auto
pf1
=
pf0
.
or_else
(
on
<
int
,
int
>
()
>>
[
&
]
{
last_invoked_fun
=
"<int, int>@3"
;
},
on
<
string
>
()
>>
[
&
]
{
last_invoked_fun
=
"<string>@4"
;
}
);
bhvr_check
(
pf0
,
make_any_tuple
(
1
,
2
),
true
,
"<int, int>@1"
);
bhvr_check
(
pf1
,
make_any_tuple
(
1
,
2
),
true
,
"<int, int>@1"
);
bhvr_check
(
pf0
,
make_any_tuple
(
"hi"
),
false
,
""
);
bhvr_check
(
pf1
,
make_any_tuple
(
"hi"
),
true
,
"<string>@4"
);
partial_function
pf11
{
on_arg_match
>>
[
&
](
int
)
{
last_invoked_fun
=
"<int>@1"
;
}
};
partial_function
pf12
{
on_arg_match
>>
[
&
](
int
)
{
last_invoked_fun
=
"<int>@2"
;
},
on_arg_match
>>
[
&
](
float
)
{
last_invoked_fun
=
"<float>@2"
;
}
};
auto
pf13
=
pf11
.
or_else
(
pf12
);
bhvr_check
(
pf13
,
make_any_tuple
(
42
),
true
,
"<int>@1"
);
bhvr_check
(
pf13
,
make_any_tuple
(
42.24
f
),
true
,
"<float>@2"
);
}
/* check result of pattern matching */
{
auto
res
=
match
(
make_any_tuple
(
42
,
4.2
f
))
(
on
(
42
,
arg_match
)
>>
[](
double
d
)
{
return
d
;
},
on
(
42
,
arg_match
)
>>
[](
float
f
)
{
return
f
;
}
);
CPPA_CHECK
(
res
&&
res
.
is
<
float
>
()
&&
get
<
float
>
(
res
)
==
4.2
f
);
auto
res2
=
match
(
make_any_tuple
(
23
,
4.2
f
))
(
on
(
42
,
arg_match
)
>>
[](
double
d
)
{
return
d
;
},
on
(
42
,
arg_match
)
>>
[](
float
f
)
{
return
f
;
}
);
CPPA_CHECK
(
!
res2
);
}
behavior
bhvr1
{
on
<
int
>
()
>>
[
&
](
int
i
)
->
match_hint
{
last_invoked_fun
=
"<int>@1"
;
return
(
i
==
42
)
?
match_hint
::
skip
:
match_hint
::
handle
;
},
on
<
float
>
()
>>
[
&
]
{
last_invoked_fun
=
"<float>@2"
;
},
on
<
int
>
()
>>
[
&
]
{
last_invoked_fun
=
"<int>@3"
;
},
others
()
>>
[
&
]
{
last_invoked_fun
=
"<*>@4"
;
}
};
bhvr_check
(
bhvr1
,
make_any_tuple
(
42
),
false
,
"<int>@1"
);
bhvr_check
(
bhvr1
,
make_any_tuple
(
24
),
true
,
"<int>@1"
);
bhvr_check
(
bhvr1
,
make_any_tuple
(
2.
f
),
true
,
"<float>@2"
);
bhvr_check
(
bhvr1
,
make_any_tuple
(
""
),
true
,
"<*>@4"
);
partial_function
pf0
{
on
<
int
,
int
>
()
>>
[
&
]
{
last_invoked_fun
=
"<int, int>@1"
;
},
on
<
float
>
()
>>
[
&
]
{
last_invoked_fun
=
"<float>@2"
;
}
};
auto
pf1
=
pf0
.
or_else
(
on
<
int
,
int
>
()
>>
[
&
]
{
last_invoked_fun
=
"<int, int>@3"
;
},
on
<
string
>
()
>>
[
&
]
{
last_invoked_fun
=
"<string>@4"
;
}
);
bhvr_check
(
pf0
,
make_any_tuple
(
1
,
2
),
true
,
"<int, int>@1"
);
bhvr_check
(
pf1
,
make_any_tuple
(
1
,
2
),
true
,
"<int, int>@1"
);
bhvr_check
(
pf0
,
make_any_tuple
(
"hi"
),
false
,
""
);
bhvr_check
(
pf1
,
make_any_tuple
(
"hi"
),
true
,
"<string>@4"
);
partial_function
pf11
{
on_arg_match
>>
[
&
](
int
)
{
last_invoked_fun
=
"<int>@1"
;
}
};
partial_function
pf12
{
on_arg_match
>>
[
&
](
int
)
{
last_invoked_fun
=
"<int>@2"
;
},
on_arg_match
>>
[
&
](
float
)
{
last_invoked_fun
=
"<float>@2"
;
}
};
auto
pf13
=
pf11
.
or_else
(
pf12
);
bhvr_check
(
pf13
,
make_any_tuple
(
42
),
true
,
"<int>@1"
);
bhvr_check
(
pf13
,
make_any_tuple
(
42.24
f
),
true
,
"<float>@2"
);
}
void
test_pattern_matching
()
{
auto
res
=
match
(
make_any_tuple
(
42
,
4.2
f
))
(
on
(
42
,
arg_match
)
>>
[](
double
d
)
{
return
d
;
},
on
(
42
,
arg_match
)
>>
[](
float
f
)
{
return
f
;
}
);
CPPA_CHECK
(
res
&&
res
.
is
<
float
>
()
&&
get
<
float
>
(
res
)
==
4.2
f
);
auto
res2
=
match
(
make_any_tuple
(
23
,
4.2
f
))
(
on
(
42
,
arg_match
)
>>
[](
double
d
)
{
return
d
;
},
on
(
42
,
arg_match
)
>>
[](
float
f
)
{
return
f
;
}
);
CPPA_CHECK
(
!
res2
);
}
void
test_wildcards
()
{
auto
expr
=
(
on
(
any_vals
,
arg_match
)
>>
[](
int
a
,
int
b
)
{
cout
<<
"invoked: "
<<
a
<<
", "
<<
b
<<
endl
;
}
);
CPPA_CHECK
(
expr
(
make_any_tuple
(
1
,
2
,
3
)));
CPPA_CHECK
(
expr
(
make_any_tuple
(
1
,
2
)));
partial_function
pf
=
expr
;
CPPA_CHECK
(
pf
(
make_any_tuple
(
1
,
2
)));
CPPA_CHECK
(
pf
(
make_any_tuple
(
1
,
2
,
3
)));
behavior
bhvr
=
expr
;
CPPA_CHECK
(
bhvr
(
make_any_tuple
(
1
,
2
)));
CPPA_CHECK
(
bhvr
(
make_any_tuple
(
1
,
2
,
3
)));
}
int
main
()
{
CPPA_TEST
(
test_match
);
test_wildcards
();
test_simple_guards
();
test_container_guards
();
test_user_defined_expressions
();
test_gref
();
test_match_function
();
test_match_each
();
test_match_stream
();
test_behavior
();
test_pattern_matching
();
return
CPPA_TEST_RESULT
();
}
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment