develooper Front page | perl.perl5.porters | Postings from April 2004

more B::Concise stuff

Thread Next
From:
Jim Cromie
Date:
April 22, 2004 00:47
Subject:
more B::Concise stuff
Message ID:
40877946.8060905@divsol.com
folks,

attached patch has following adjustments to B::Concise and its tests.
its not quite ready for prime-time, I solicit your able assistance in 
resolving
its bugs.

1. split option-handling in compile out to compileOpts,
and call it a 2nd time within the Asub built by compile. 

This allows $walker to change its rendering style on same code.

  $walker = compile(sub {$a=$b+42});

  for $s (qw( -concise -linenoise -debug -terse )) {
      for $mode (qw( -basic -exec )) {

          $walker->($s, $mode);
      }
  }

Using this, Ive added a bunch of tests (now 142) to concise.t ,
some of which have tickled a sequencing bug, either new or old.

Its always the GOTO line, and is thus -exec dependent.
Sometimes a dash is rendered, sometimes its a number.
(the number looks wrong - in sample below, it goes to an sassign-op)

It shows up with all styles; -debug, -terse, -linenoise, -concise.
theyre all TODOd.

not ok 129 - -concise-exec VS -exec/-concise are the same # TODO goto - 
bug, sometimes goto 'assign'
# Failed at ext/B/t/concise.t line 304
#      got 'B::Concise::compile(CODE(0x820159c))
#            goto 6
# 1  <;> nextstate(main -691 concise.t:109) v
# 2  <#> gvsv[*b] s
# 3  <$> const[IV 42] s
# 4  <2> add[t3] sK/2
# 5  <#> gvsv[*a] s
# 6  <2> sassign sKS/2
# 7  <1> leavesub[1 ref] K/REFC,1
# '
# expected 'B::Concise::compile(CODE(0x820159c))
#            goto -
# 1  <;> nextstate(main -691 concise.t:109) v
# 2  <#> gvsv[*b] s
# 3  <$> const[IV 42] s
# 4  <2> add[t3] sK/2
# 5  <#> gvsv[*a] s
# 6  <2> sassign sKS/2
# 7  <1> leavesub[1 ref] K/REFC,1


2. stickiness tweaks.

I added $do_main to persistent rendering-state.  and added a -nomain
flag to complement -main.  This was just cleaner wrt 1, and simplifies
explaining whats sticky and whats not.
Also added a -nobanner, and inverted meaning of -banner, which restores 
default.

3. pod tweaks.

shuffled ABBREVIATIONS above FORMAT SPECS
more likely to be useful to a novice.  and a few extra words elsewhere.

4. EXPORT_TAGS

our %EXPORT_TAGS =
   ( :io    => [qw( walk_output compile reset_sequence )],
     :style    => [qw( add_style set_style_standard )],
     :cb    => [qw( add_callback )],
     :mech    => [qw( concise_subref concise_cv concise_main )],  );

5.  #Var

=item B<#>I<Var>

Generates a tag-value form of itself for display. 
IIT, its a 1 line addtion to fmt_line, and does s/#Var/ Var => #var/g,
and the #var is then handled as before.

I use this in a 'rebug' style in concise_stash.t,
which isnt part of MANIFEST cuz it doesnt test anything (yet),
it just prints .......


6. handle STASHREFs as args.

Formerly, passing a hashref was an error (due to my original patch),
now it calls concise_stashref, which walks the hash, and calls 
concise_subref
on {CODE} objects.

I call this 'splaying' a package (it needs a name so as not to be 
ambiguous).
Remember what you did to that frog in high school biology ?
Now you can (in principle) do it to packages.

ext/B/t/concise_stash.t is not in Manifest, so not part of testing,
because its still is quite broken in situations;

here it fails on a number of subs, but succeeds on others.
I dont see the difference.

FUNC: *main::B::main_root
err err: coderef has no START
 on B::CV=SCALAR(0x8249ff8) at ../lib/B/Concise.pm line 145.
FUNC: *main::B::main_start
err err: coderef has no START
 on B::CV=SCALAR(0x8249200) at ../lib/B/Concise.pm line 145.
FUNC: *main::B::minus_c
err err: coderef has no START
 on B::CV=SCALAR(0x82d9eac) at ../lib/B/Concise.pm line 145.
FUNC: *main::B::objsym
h  <1> leavesub[1 ref] K/REFC,1 ->(end)
1        <;> nextstate(main::B -400 B.pm:161) v/2 ->2
2                 <#> gv[*_] s ->3
7        <;> nextstate(main::B -399 B.pm:162) v/2 ->8
err  on B::CV=SCALAR(0x8249ff8) at ../lib/B/Concise.pm line 145.
FUNC: *main::B::opnumber
err err: coderef has no START
 on B::CV=SCALAR(0x82d6eb8) at ../lib/B/Concise.pm line 145.


but if you run it, you'll see REAMS of optree rendering..
tips on what above errors mean are welcome.

I think theres a deeper vein here;

concise_stash.t combines splaying a package with callback based
filtering (itself a combo of a new -scope style, and a callback which
operates on that style only).

This could have interesting applications, esp if a good
filters are defined.  The -scope one sucks, but its just an example
of how one can filter out large chunks of a STASH rendering.

Since callbacks get the OP in @_, your filter is free to follow the chain,
and see if it qualifies for whatever you're after.


7.  CALLBACK CHANGES


Formerly, callbacks were dispatched by concise_op, immediately b4
calling fmt_line.  I moved the dispatch into fmt_line, and added an $op
argument.

Now callbacks have chance to act on goto lines (inserted by B::OP::concise)
The improvement is best seen when using callback-based filtering; once youve
suppressed lots of opcodes, the goto lines start to dominate the output,
and they provide no info without the suppressed opcodes they jump to.

Note that bug 1 was there b4 I did this change.


8. Subtle GOTO tweak.

B::OP::concise, when in -exec mode, inserts synthetic 'goto' ops (see 7).
these 'op's *now* have a 'goto' property (visible as #goto in 
style-templates).

The special 'goto' property makes special callback handling easy,
as done in  optree_goto.t:

the callback clears #goto if its eq '-', undoing the default-fill 
provided by seq().
the 'egoto' style uses (?(   blah #goto )?)   conditional fill pattern 
to supress entire line
when #goto is unknown.

the conditional-fill could be used in EXISTING style templates, unless 
of course
goto '-' tells you something that I dont appreciate.

This doesnt 'fix' the goto-bug seen in 1; that error is a falsely 
'known' sequence,
not an unknown one.  It would hide it however, which is one reason its 
not in B/Concise.pm

I cant help but entertain the idea of inserting more synthetic ops, for 
other
modes (ex -basic), where other chain discontinuties exist.  Anyone see any
value in this ?

9. Finally, something I did broke showlex.t;

[jimc@harpo t]$ ./perl ../ext/B/t/showlex.t
1..1
# [Use of uninitialized value in concatenation (.) or string at 
../lib/B/Concise.pm line 603.
-e syntax OK
Pad of lexical names for comppadlist has 2 entries
0: SPECIAL #1 &PL_sv_undef
1: PVNV (0x81a7e68) @one
Pad of lexical values for comppadlist has 2 entries
0: SPECIAL #1 &PL_sv_undef
1: 0

        that last line should be more like;
1: PVNV (0x81bf828) @arr

it appears that @ and % are somehow trashed and replaced by 0, where 
they should
be AV HV repectively.   Im suspicious of the fmt_line / callbacks changes,
but Ive never used Showlex, so Im gonna punt for now...



OTHER THINGS NOT YET FINISHED / UNDER CONSIDERATION

1. add #goto in B::Concise, add pod, drop the '-' default to ease 
conditional-fill usage.

I thought about converting goto into a 'suffix', such that ;

# k          <@> print vK
# l          <0> unstack v
#                Goto m
# o      <2> leaveloop vK/2
# p      <0> unstack s
#            Goto q

might become, instead;

# k          <@> print vK
# l          <0> unstack v    then  Goto m
# o      <2> leaveloop vK/2
# p      <0> unstack s      then    Goto q

this could be done by playing with conditional line endings / or rather, 
beginnings.
(fmt-line already removes \n,  then conditionally readds, allowing blank 
line supression.)

conversely, I thought about adding a <}> to the style, to complement 
lines like
    # e      <{> enteriter(next->l last->o redo->f) lKS
but this seems unnecessary

2. -banner vs -nobanner vs -bannergen=coderef

I dont like the stringified coderef I put in, as it complicates compares,
but I did it to allow visual inspection and identification, however clumsy.
a simpler cookie sequence-gen would be a min-change enhancement.

Im hoping I can decide to shoot that feature b4 5.10, if someone else
doesnt 1st, with a better idea.

a bannergen coderef would be nice, and handy for converting
optreeCheck %args to a name-label for the tests.
but no user-supplied function can access the my @rendering-state.

I may hardwire one thats a good enough compromise.

3. replace guts of compileOpts with Getopt::* code.

I looked briefly, didnt see easy use which kept current -option scheme.
--mode=exec --style=debug would be a trivial usage, but isnt back-compat.
Thump me if Ive missed something, like Getopt::Long working with single
dashes, or some good scheme to sacrifice back-compatibility.


4.  More optree_*.t  files

Theres lots of opportunity to add tests, both good ones,
ones with some training and insight value, and some that
dont really achieve anything, and are bloat.

If any of you have a particular area of interest, Id love some
short code snippets that exersize them. (see 5 too). Email me here or 
offlist,
and Ill convert them to files.  Suggest a good optree_X.t name too !

I looked briefly at camel3.ch1 for samples, but theres a lot
of examples there, probably overkill for optimization regression..
I didnt start to fill in the test results.

5.  testfile support.

using checkOptree() is reasonable, but its still pretty tedious to
pastein checkOptree synopsis, pastein some testcode, run,
paste-in results as a reference, retest, switch platforms (T->nT),
and repeat.

Ive written code to convert simple example files (each with multiple
example paragraph chunks), into optree_* like files,
but its not in this patch, as its still messy, and doesnt address
the diff3-merge of T,nT tests.

for example, the following will be converted and sent RSN.

[jimc@harpo bconcise]$ more f_map
#!perl
# examples shamelessly snatched from perldoc -f map

# translates a list of numbers to the corresponding characters.
@chars = map(chr, @nums);

%hash = map { getkey($_) => $_ } @array;

{ %hash = ();   foreach $_ (@array) { $hash{getkey($_)} = $_;    }}

%hash = map {  "\L$_", 1  } @array;  # perl guesses EXPR.  wrong

%hash = map { +"\L$_", 1  } @array;  # perl guesses BLOCK. right

%hash = map { ("\L$_", 1) } @array;  # this also works

%hash = map {  lc($_), 1  } @array;  # as does this.

%hash = map +( lc($_), 1 ), @array;  # this is EXPR and works!

%hash = map  ( lc($_), 1 ), @array;  # evaluates to (1, @array)

 @hashes = map +{ lc($_), 1 }, @array # EXPR, so needs , at end


this will be called optree_f_map.t.

BTW, should perldoc -f map/grep/sort  say stuff about optimizations,
efficiencies, warnings ?

-f grep is quite brief, with only 2 examples.

-f map, is better, as above.  Are there any boolean/scalar context tweaks
to add here, or to test for with optree_f_map ?

-f sort also good, but could use some 'Useless use of sort' examples,
inplace sorts, etc.

IMO, the -f pods should all probly say something about warnings
and/or errs they can throw, but this needs due consideration by the
Pod legislature, and setting of doc-standards.


ok, done prattling..

thx for reading
jimc.



Thread Next


nntp.perl.org: Perl Programming lists via nntp and http.
Comments to Ask Bjørn Hansen at ask@perl.org | Group listing | About