Skip to content

Commit 391db37

Browse files
committed
Refactor.
Pull code into subs, use keys instead of top level vars. Improve error reporting so that undocumented opcodes appear only once as errors no matter how many vms they are undocumented for.
1 parent fb2dbb0 commit 391db37

File tree

1 file changed

+88
-87
lines changed

1 file changed

+88
-87
lines changed

t/docs/opcodes.t

Lines changed: 88 additions & 87 deletions
Original file line numberDiff line numberDiff line change
@@ -1,109 +1,110 @@
11
#! nqp
22

3-
my @vms := nqp::list('parrot', 'jvm', 'moar');
4-
my %documented_ops := nqp::hash();
5-
for @vms -> $vm {
6-
%documented_ops{$vm} := nqp::hash();
7-
}
3+
my @*vms := nqp::list('parrot', 'jvm', 'moar');
84

9-
my @doc_lines := nqp::split("\n", nqp::readallfh(nqp::open("docs/ops.markdown","r")));
10-
my @opcode_vms := nqp::list();
11-
for @doc_lines -> $line {
12-
my $match := $line ~~ /^ '##' \s* <[a..zA..Z0..9_]>+ \s* ('`' .* '`')? /;
13-
if (?$match) {
14-
if (!?$match[0]) {
15-
@opcode_vms := nqp::clone(@vms);
16-
} else {
17-
@opcode_vms := nqp::list();
18-
if $match[0] ~~ /jvm/ {
19-
nqp::push(@opcode_vms,"jvm");
20-
}
21-
if $match[0] ~~ /parrot/ {
22-
nqp::push(@opcode_vms,"parrot");
23-
}
24-
if $match[0] ~~ /moar/ {
25-
nqp::push(@opcode_vms,"moar");
26-
}
27-
}
28-
}
29-
next unless $line ~~ / ^ '* ' .* '(' /;
30-
$line := nqp::substr2($line, 3);
31-
$line := nqp::split("(", $line)[0];
32-
for @opcode_vms -> $vm {
33-
%documented_ops{$vm}{$line} := 1 ;
34-
}
5+
my %documented_ops := find_documented_opcodes();
356

36-
}
7+
my %ops := hash_of_vms();
378

38-
my %jvm_ops := nqp::hash();
39-
my @jvm_lines := nqp::split("\n", nqp::readallfh(nqp::open("src/vm/jvm/QAST/Compiler.nqp","r")));
40-
for @jvm_lines -> $line {
41-
next unless $line ~~ / 'map_classlib_core_op' | 'add_core_op' | 'map_jvm_core_op' /;
42-
$line := nqp::split("'", $line)[1];
43-
next unless nqp::chars($line);
44-
%jvm_ops{$line} := 1;
45-
}
46-
47-
# These are harder to tease out of the definitions in java, so add them manually
48-
for <if unless while until repeat_while repeat_until> -> $op_name {
49-
%jvm_ops{$op_name} := 1;
50-
}
9+
%ops<jvm> := find_opcodes(
10+
:file("src/vm/jvm/QAST/Compiler.nqp"),
11+
:keywords(<map_classlib_core_op add_core_op map_jvm_core_op>)
12+
);
5113

52-
# All the jvm ops must be documented
14+
%ops<parrot> := find_opcodes(
15+
:file("src/vm/parrot/QAST/Operations.nqp"),
16+
:keywords(<add_core_op add_core_pirop_mapping>)
17+
);
5318

54-
for %jvm_ops -> $jvm_op {
55-
ok(%documented_ops<jvm>{$jvm_op}, "JVM op '$jvm_op' is documented");
56-
}
57-
58-
for %documented_ops<jvm> -> $doc_op {
59-
ok(%jvm_ops{$doc_op}, "documented op '$doc_op' exists in the JVM");
60-
}
19+
%ops<moar> := find_opcodes(
20+
:file("src/vm/moar/QAST/QASTOperationsMAST.nqp"),
21+
:keywords(<add_core_op add_core_moarop_mapping>)
22+
);
6123

62-
my %pvm_ops := nqp::hash();
63-
my @pvm_lines := nqp::split("\n", nqp::readallfh(nqp::open("src/vm/parrot/QAST/Operations.nqp","r")));
64-
for @pvm_lines -> $line {
65-
next unless $line ~~ / 'add_core_op' | 'add_core_pirop_mapping' /;
66-
$line := nqp::split("'", $line)[1];
67-
next unless nqp::chars($line);
68-
%pvm_ops{$line} := 1;
69-
}
70-
71-
# These are harder to tease out of the definitions in java, so add them manually
24+
# Most backends programmatically add these ops - to keep our cheating simple,
25+
# add them to each of the backends manually
7226
for <if unless while until repeat_while repeat_until> -> $op_name {
73-
%pvm_ops{$op_name} := 1;
27+
for @*vms -> $vm {
28+
%ops{$vm}{$op_name} := 1;
29+
}
7430
}
7531

76-
# All the pvm ops must be documented
77-
78-
for %pvm_ops -> $pvm_op {
79-
ok(%documented_ops<parrot>{$pvm_op}, "PVM op '$pvm_op' is documented");
32+
# Are ops that are implemented documented? Fail once per opcode
33+
my %combined_ops := nqp::hash();
34+
for @*vms -> $vm {
35+
for %ops{$vm} -> $op {
36+
if !%combined_ops{$op} {
37+
%combined_ops{$op} := nqp::list($vm);
38+
} else {
39+
nqp::push(%combined_ops{$op}, $vm);
40+
}
41+
}
8042
}
8143

82-
for %documented_ops<parrot> -> $doc_op {
83-
ok(%pvm_ops{$doc_op}, "documented op '$doc_op' exists in the PVM");
44+
for %combined_ops -> $opcode {
45+
my $vms := nqp::join(";", %combined_ops{$opcode});
46+
ok(%documented_ops<any>{$opcode}, "Opcode '$opcode' ($vms) is documented");
8447
}
8548

86-
my %mvm_ops := nqp::hash();
87-
my @mvm_lines := nqp::split("\n", nqp::readallfh(nqp::open("src/vm/moar/QAST/QASTOperationsMAST.nqp","r")));
88-
for @mvm_lines -> $line {
89-
next unless $line ~~ / 'add_core_op' | 'add_core_moarop_mapping' /;
90-
$line := nqp::split("'", $line)[1];
91-
next unless nqp::chars($line);
92-
%mvm_ops{$line} := 1;
49+
# Do documented opcodes actually exist? Fail once per vm if not.
50+
for @*vms -> $vm {
51+
for %documented_ops{$vm} -> $doc_op {
52+
ok(%ops{$vm}{$doc_op}, "documented op '$doc_op' exists in $vm");
53+
}
9354
}
9455

95-
# These are harder to tease out of the definitions in moar, so add them manually
96-
for <if unless while until repeat_while repeat_until> -> $op_name {
97-
%mvm_ops{$op_name} := 1;
56+
sub find_opcodes(:$file, :@keywords) {
57+
my %ops := nqp::hash();
58+
my @lines := nqp::split("\n", nqp::readallfh(nqp::open($file,"r")));
59+
for @lines -> $line {
60+
next unless $line ~~ / @keywords /;
61+
$line := nqp::split("'", $line)[1];
62+
next unless nqp::chars($line);
63+
%ops{$line} := 1;
64+
}
65+
return %ops;
9866
}
9967

100-
101-
# All the mvm ops must be documented
102-
103-
for %mvm_ops -> $mvm_op {
104-
ok(%documented_ops<moar>{$mvm_op}, "MOAR op '$mvm_op' is documented");
68+
sub hash_of_vms() {
69+
my %hash := nqp::hash();
70+
for @*vms -> $vm {
71+
%hash{$vm} := nqp::hash();
72+
}
73+
return %hash;
10574
}
10675

107-
for %documented_ops<moar> -> $doc_op {
108-
ok(%mvm_ops{$doc_op}, "documented op '$doc_op' exists in MOAR");
76+
sub find_documented_opcodes() {
77+
my %documented_ops := hash_of_vms();
78+
%documented_ops<any> := nqp::hash();
79+
80+
my @doc_lines := nqp::split("\n", nqp::readallfh(nqp::open("docs/ops.markdown","r")));
81+
my @opcode_vms := nqp::list();
82+
for @doc_lines -> $line {
83+
my $match := $line ~~ /^ '##' \s* <[a..zA..Z0..9_]>+ \s* ('`' .* '`')? /;
84+
if (?$match) {
85+
if (!?$match[0]) {
86+
@opcode_vms := nqp::clone(@*vms);
87+
} else {
88+
@opcode_vms := nqp::list();
89+
if $match[0] ~~ /jvm/ {
90+
nqp::push(@opcode_vms,"jvm");
91+
}
92+
if $match[0] ~~ /parrot/ {
93+
nqp::push(@opcode_vms,"parrot");
94+
}
95+
if $match[0] ~~ /moar/ {
96+
nqp::push(@opcode_vms,"moar");
97+
}
98+
}
99+
}
100+
next unless $line ~~ / ^ '* ' .* '(' /;
101+
$line := nqp::substr2($line, 3);
102+
$line := nqp::split("(", $line)[0];
103+
for @opcode_vms -> $vm {
104+
%documented_ops{$vm}{$line} := 1 ;
105+
}
106+
%documented_ops<any>{$line} := 1 ;
107+
108+
}
109+
return %documented_ops;
109110
}

0 commit comments

Comments
 (0)