Skip to content

Commit

Permalink
Rewrite find-definition to be single-pass
Browse files Browse the repository at this point in the history
  • Loading branch information
Mouq committed Jun 18, 2014
1 parent 877d74b commit 4877afe
Showing 1 changed file with 68 additions and 66 deletions.
134 changes: 68 additions & 66 deletions htmlify.p6
Expand Up @@ -258,97 +258,99 @@ multi write-type-source($doc) {
spurt "html/$what/$podname.html", p2h($pod, $what);
}

sub find-definitions (:$pod, :$*origin, :$dr) {
my $*old-level = Inf;
my $*created;

my sub add-new (*%_) {
$*created = $dr.add-new(
:$*name,
:subkinds($*what),
:$*origin,
sub find-definitions (:$pod, :$origin, :$dr, :$min-level = -1) {
# Run through the pod content, and look for headings.
# If a heading is a definition, like "class FooBar", process
# the class and give the rest of the pod to find-definitions,
# which will return how far the definition of "class FooBar" extends.
my @c := $pod ~~ Positional ?? @$pod !! $pod.content;
my int $i = 0;

my sub add-new (:$name, :$subkinds, *%_) {
say " Found definition of $subkinds $name in $origin.name().";

my $created = $dr.add-new(
:$origin,
:pod[],
:!pod-is-complete,
:$name,
:$subkinds,
|%_
);

# Preform sub-parse, checking for definitions elsewhere in the pod
# And updating $i to be after the places we've already searched
my int $new-i = $i + find-definitions :pod(@c[$i+1..*]), :origin($created), :$dr, :min-level(@c[$i].level);

@c[$i].content[0] = pod-link "$subkinds $name",
$created.url ~ "#$origin.human-kind() $origin.name()".subst(:g, /\s+/, '_');

my $chunk = $created.pod.push: @c[$i..$new-i];

$i = $new-i;

if $subkinds eq 'routine' {
# Determine proper subkinds
my Str @subkinds = first-code-block($chunk)\
.match(:g, /:s ^ 'multi'? (sub|method)»/)\
.>>[0]>>.Str.Set.list;

note "The subkinds of routine $created.name() in $origin.name() cannot be determined."
unless @subkinds;

$created.subkinds = @subkinds;
$created.categories = @subkinds;
}
if $subkinds 'method' {
%methods-by-type{$origin.name}.push: $chunk;
write-qualified-method-call(
:$name,
:pod($chunk),
:type($origin.name),
);
}
}

# Run through the pod content, and look for headings.
# If a heading is a definition, like "class FooBar", process
# the class and slurp up the pod until the next heading at
# the same or lower level.
for $pod ~~ Positional ?? @$pod !! $pod.content -> $c {
if $c ~~ Pod::Heading and $c.level <= $*old-level {
# Finalize our new definition
chunk-finished if $*created;
my int $len = +@c;
while $i < $len {
my $c := @c[$i];
if $c ~~ Pod::Heading {
return $i if $c.level <= $min-level;

# Is this new header a definition?
# If so, begin processing it.
# If not, skip to the next heading.
next unless $c.content[0].content[0] ~~ Str
and 2 == my @words = $c.content[0].content[0].words;
my ($*what, $*name) = @words;
given $*what {
$i = $i + 1 and next unless $c.content[0].content[0] ~~ Str
and 2 == my @words = $c.content[0].content[0].words;

my ($what, $name) = @words;
given $what {
when / ^ [in | pre | post | circum | postcircum ] fix | listop / {
add-new :kind<routine>
:$name
:subkinds($what)
:categories<operator>
}
when 'sub'|'method'|'term'|'routine' {
add-new :kind<routine>
:categories($*what)
:$name
:subkinds($what)
:categories($what)
}
when 'class'|'role' {
add-new :kind<type>;
add-new :kind<type>
:$name
:subkinds($what)
}
default {
next
$i = $i + 1 and next
}
}
# We made it this far, so it's a valid definition
say " Found definition of $*what $*name in $*origin.name().";
$*old-level = $c.level;

$c.content[0] = pod-link "$*what $*name",
$*created.url ~ "#$*origin.human-kind() $*origin.name()".subst(:g, /\s+/, '_');

$*created.pod.push: $c;
} elsif $*created {
# Slurp up pod content within the same level as our definition
$*created.pod.push: $c;
}
$i = $i + 1;
}
# Finalize our new definition if we haven't already
chunk-finished if $*created;

my sub chunk-finished () {
my $chunk = $*created.pod;

if $*created.subkinds eq 'routine' {
# Determine proper subkinds
my Str @subkinds = first-code-block($chunk)\
.match(:g, /:s ^ 'multi'? (sub|method)»/)\
.>>[0]>>.Str.Set.list;

note "The subkinds of routine $*created.name() in $*origin.name() cannot be determined."
unless @subkinds;

$*created.subkinds = @subkinds;
$*created.categories = @subkinds;
}
if $*created.subkinds 'method' {
%methods-by-type{$*origin.name}.push: $chunk;
write-qualified-method-call(
:name($*created.name),
:pod($chunk),
:type($*origin.name),
);
}

find-definitions :pod($chunk[1..*]), :origin($*created), :$dr;

$*old-level = Inf;
undefine $*created;
}
return $i;
}

sub write-type-graph-images(:$force) {
Expand Down

0 comments on commit 4877afe

Please sign in to comment.