Commit Graph

17 Commits

Author SHA1 Message Date
Christopher Haster
2fa968dd3f scripts: csv.py: Fixed divide-by-zero, return +-inf
This may make some mathematician mad, but these are informative scripts.
Returning +-inf is much more useful than erroring when dealing with
several hundred rows of results.

And hey, if it's good enough for IEEE 754, it's good enough for us :)

Also fixed a division operator mismatch in RFrac that was causing
problems.
2024-11-16 16:47:48 -06:00
Christopher Haster
5dc9eabbf7 scripts: csv.py: Fixed use of __div__ vs __truediv__
Not sure if this is an old habit from Python 2, or just because it looks
nicer next to __mul__, __mod__, etc, but in Python 3 this should be
__truediv__ (or __floordiv__), not __div__.
2024-11-16 16:38:36 -06:00
Christopher Haster
6714e2869f scripts: csv.py: Made RFloats independent from RInts
The only reason RFloats reused RInt's operator definitions was to save a
few keystrokes. But this dependency is unnecessary and will get in the
way if we ever add a script that only uses RFloats.
2024-11-16 16:10:59 -06:00
Christopher Haster
298441ae74 scripts: csv.py: Added help text over available field exprs
So now the available field exprs can be queried with --help-exprs:

  $ ./scripts/csv.py --help-exprs
  uops:
    +a                    Non-negation
    -a                    Negation
    !a                    1 if a is zero, otherwise 0
  bops:
    a * b                 Multiplication
    a / b                 Division
  ... snip ...

I was a bit torn on if this should be named --help-exprs or --list-exprs
to match test.py/bench.py, but decided on --help-exprs since it's
querying something "inside" the script, whereas test.py/bench.py's
--list-cases is querying something "outside" the script.

Internally this uses Python's docstrings, which is a nice language
feature to lean on.
2024-11-16 15:59:01 -06:00
Christopher Haster
690251c130 scripts: csv.py: Added float mod support
Mainly for consistency with int operators, though it's unclear if either
mod is useful in the context of csv.py and related scripts.

This may be worth reverting at some point.
2024-11-16 15:54:45 -06:00
Christopher Haster
effc959ea9 scripts: csv.py: Improved default typechecking in RExpr
Now, by default, an error is raised if any branch of an expr has an
inconsistent type.

This isn't always what we want. The ternary operator, for example,
doesn't really care if the condition's type doesn't match the branch
arms. But it's a good default, and special cases can always override the
type function with their own explicit typechecking.
2024-11-16 15:45:14 -06:00
Christopher Haster
f31f3fdd68 scripts: csv.py: Fixed missing fields going undetected
There's a bit of a push and pull when it comes to typechecking CSV
fields in our scripts. On one hand, we want the flexibility to accepts
scripts with various mismatched fields, on the other hand, we _really_
want to know if a typo caused a field to be quietly replaced with all
zeros...

I _think_ it's safe to say: if no fields across _all_ input files match
a requested field, we should error.

But I may end up wrong about this. Worst case we can always revert in
the future, maybe with an explicit flag to ignore missing fields.
2024-11-16 14:16:20 -06:00
Christopher Haster
103b251ad8 scripts: csv.py: Various tweaks/cleanup
- Updated the example in the header comment.

  The previous example was way old, from back when fields were separated
  by commas! Introduced in 20ec0be87 in 2022 according to git blame.

- Renamed a couple internal RExpr classes:

  - Not -> NotNot
  - And -> AndAnd
  - Or  -> OrOr
  - Ife -> IfElse

  This is mainly to leave room for bitwise operators in case we every
  want to add them.

- Added isinf, isnan, isint, etc:

  - isint(a)
  - isfloat(a)
  - isfrac(a)
  - isinf(a)
  - isnan(a)

  In theory useful for conditional exprs based on the field's type.

- Accept +-nan as a float literal.

  Niche, but seems necessary for completeness. Unfortunately this does
  mean a field named nan (or inf) may cause problems...
2024-11-16 14:15:36 -06:00
Christopher Haster
0ac326d9cb scripts: Reduced table name widths to 8 chars minimum
I still think the 24 (23+1) char minimum is a good default for 2 column
output such as help text, especially if you don't have automatic width
detection. But our result scripts need to be a bit more flexible.

Consider:

  $ make summary
                              code     data    stack  structs
  TOTAL                      68864        0     3744     1520

Vs:

  $ make summary
              code     data    stack  structs
  TOTAL      68864        0     3744     1520

Up until now we were just kind of working around this with cut -c 25- in
our Makefile, but now that our result scripts automatically scale the
table widths, they should really just default to whatever is the most
useful.
2024-11-16 13:39:42 -06:00
Christopher Haster
acf34dce2e scripts: csv.py: Fixed lingering undefined renames in diff mode
This lingering reference to renames was missed when refactoring.
2024-11-16 13:22:40 -06:00
Christopher Haster
4e5d1c5e7d scripts: csv.py: Frac expr tweaks
- Allow single-arg frac:

  - frac(a)    => a/a
  - frac(a, b) => a/b

  This was already supported internally.

- Implicitly cast to frac in frac ops:

  - ratio(3) => ratio(3/3) => 1.0 (100%)
  - total(3) => total(3/3) => 3

  This makes a bit more sense than erroring.
2024-11-16 13:16:22 -06:00
Christopher Haster
d4c835ba89 scripts: csv.py: Fixed divide by zero in ratio
This now returns 1.0 if the total part of the fraction is 0.

There may be a better way to handle this, but the intention is for 0/0
to map to 100% for thing like code coverage (cov.py), test coverage
(test.py), etc.
2024-11-16 13:07:35 -06:00
Christopher Haster
cc25b39926 scripts: csv.py: Fixed by exprs (-ba=b) when results are missing fields
This easily happens when merging csv scripts with different results,
such as code.py and stack.py by function names.
2024-11-16 13:06:31 -06:00
Christopher Haster
1712a5bd99 scripts: csv.py: Filled out remaining ops, dropped bitwise ops, cleanup
So csv.py should now be mostly feature complete, aside from bugs.

I ended up dropping most of the bitwise operations for now. I can't
really see them being useful since csv.py and related scripts are
usually operating on purely numerical data. Worst case we can always add
them back in at some point.

I also considered dropping the logical/ternary operators, but even
though I don't see an immediate use case, the flexibility
logical/ternary operators add to a language is too much to pass on.

Another interesting thing to note is the extension of all fold functions
to operate on exprs if more than one argument is provided:

- max(1)       => 1, fold=max
- max(1, 2)    => 2, fold=sum
- max(1, 2, 3) => 3, fold=sum

To be honest, this is mainly just to allow a binary max/min function
without awkward naming conflicts.

Other than those changes this was pretty simple fill-out-the-definition
work.
2024-11-16 12:34:56 -06:00
Christopher Haster
ac0aa3633e scripts: csv.py: RExpr decorators to help simplify func/uop/bop parsing
This was more tricky than expected since Python's class scope is so
funky (I just eneded up with using lazy cached __get__ functions that
scan the RExpr class for tagged members), but these decorators help avoid
repeated boilerplate for common expr patterns.

We can even deduplicate binary expr parsing without sacrificing
precedence.
2024-11-16 12:33:41 -06:00
Christopher Haster
4061891a02 scripts: csv.py: Adopting full expr parser for field exprs
This is a work-in-progress, but the general idea is to replace the
existing rename mechanic in csv.py with a full expr parser:

  $ ./scripts/csv.py input.csv -ba=x -fb=y+z

I've been putting this off for a while, as it feels like too big a jump
in complexity for what was intended to be a simple script. But
complexity is a bit funny in programming. Even if a full parser is more
difficult to implement, if it's the right grammar for the job, the
resulting script should end up both easier to understand and easier to
extend.

The original intention was that any sufficiently complicated math could
be implemented in ad-hoc Python scripts that operate directly on the CSV
files, but CSV parsing in Python is annoying enough that this never
really worked well.

But I'm probably overselling the complexity. This is classic CS stuff:

  1. build a syntax tree
  2. map symbols to input fields
  3. typecheck, fold, eval, etc

One neat thing is that in addition to providing type and eval
information, our exprs can also provide information on how to "fold" the
field after eval. This kicks in when merging muliple rows when grouping
by -b/--by, and for finding the TOTAL results.

This can be used to merge stack results correctly with max:

  $ ./scripts/csv.py stack.csv \
          -fframe='sum(frame)' -flimit='max(limit)'

Or can be used to find other interesting measurements:

  $ ./scripts/csv.py stack.csv \
          -favg='avg(frame)' -fstddev='stddev(frame)'

These changes also make the eval order of input/output fields much
stricter which is probably a good thing.

This should replace all of the somewhat hacky fake-expr flags in csv.py:

- --int     => -fa='int(b)'
- --float   => -fa='float(b)'
- --frac    => -fa='frac(b)'
- --sum     => -fa='sum(b)'
- --prod    => -fa='prod(b)'
- --min     => -fa='min(b)'
- --max     => -fa='max(b)'
- --avg     => -fa='avg(b)'
- --stddev  => -fa='stddev(b)'
- --gmean   => -fa='gmean(b)'
- --gstddev => -fa='gstddev(b)'

If you squint you might be able to see a pattern.
2024-11-16 11:46:18 -06:00
Christopher Haster
7cfcc1af1d scripts: Renamed summary.py -> csv.py
This seems like a more fitting name now that this script has evolved
into more of a general purpose high-level CSV tool.

Unfortunately this does conflict with the standard csv module in Python,
breaking every script that imports csv (which is most of them).
Fortunately, Python is flexible enough to let us remove the current
directory before imports with a bit of an ugly hack:

  # prevent local imports
  __import__('sys').path.pop(0)

These scripts are intended to be standalone anyways, so this is probably
a good pattern to adopt.
2024-11-09 12:31:16 -06:00