Subject: RE: [rohc] Re: FW: [tcpm] WG last-call of TCP header compression

From: "Finking, Robert" <[email-masked]>
Date: Mon, 26 Sep 2005 11:10:03 +0100

Hi Joe, All,

Here are my comments. First off, whereas comments on the TCP ID tend to
affect only that draft, any changes to the FN will of course affect both
drafts therefore my comments are all subject to the opinions of authors
of both IDs, who I will refer to simply as "the authors" below.

Regards

Raffles

> Sure - the high order 'bit' of feedback on the formal notation:
> 
> I find header layout diagrams useful, and wish that the
> current notation would add to what they communicate.
> 
> In their current form, they don't - the biggest example of
> this is the use of structured comments _outside the language 
> spec_ that indicate basically what header layouts would 
> (bitfield size and order in a single place). It would be nice 
> if the current notation could be 'compiled' into the layout 
> diagrams (at least), but that seems to be hard to do in its 
> current form.

Actually it can be compiled, though AFAIK the layout diagram generator
was never produced. Note though that it should be entirely possible
technically to add this facility to the existing parser. The question of
whether or not to include the bit field descriptions as part of the
notation was a hotly debated topic, which I personally am reluctant to
open up again, having reached a consensus. Opinions please.

> 
> As I hinted originally, it's not at all evident that this
> 50-page document - a prerequisite to the TCP doc - makes any 
> of the TCP doc easier to understand or implement.
> 
> My personal impression is that this notation hurts more than
> it helps, and should not be pursued further.

The benefit is a formal specification, which should help reduce
unintentional ambiguities in the TCP draft, such as have plagued 3095.
We have also included ASCII diagrams in the TCP draft to improve
readability, so hopefully you have the best of both worlds.

> Some additional comments noted on a second pass; some of
> these may be redundant with those previously noted:
> 
> - - the notation is BNF-like in some places (::=), C-like in
> others, and decidedly bizarre (IMO) in others (===). If there 
> is a reason this doesn't look basically like a combination of 
> C-structures and C-code (maybe, *gasp*, C++ -like?), a case 
> needs to be made.

It's not an imperative language. Actually it looks like prolog, on which
it was originally based. I think it would be confusing to make it look
too C-like because if you read a relational spec like this with an
imperative mind, you are going to find it hard to grok =)
 
> - - keywords are very hard to distinguish from variable
> names; the use of structured keywords (co_format_a, 
> co_format_b, etc.) is extraordinarily cumbersome, esp. since 
> it can be easily replaced by a structure (co_format[a], 
> co_format[b], e.g.)

There aren't any "variables", and very few keywords. "co_format" is not
a keyword. I personally don't see any benefit in making "co_format" into
a keyword. Opinions please.

> 
> - - it doesn't seem that control fields can be conditional -
> is there a reason?

All fields can be conditional, just put them in a packet format with a
guard condition on it. See 'A.9  Use Of "let" Statements As
Conditionals' for an example of a conditional control field.

> - - the notation appears to imply that there is a 1:1
> correlation between compressed and uncompressed messages; is 
> this necessary, and does it inhibit some forms of compression 
> (e.g., ACK compression could be performed by an intermediary)

There is a 1:1 relationship, but of course there is no reason that the
compressed message has to have any content. It is up to the profile
writer to provide a framework which won't send empty packets
unnecessarily, but from the FN's point of view zero length compressed
packets are the answer - it would be worth the draft explaining this
explicitly I think.

> 
> - - the use of control fields, which have no uncompressed
> value, should not need to be explained - it should be 
> highlighted in the structure. right now, the only way to find 
> such fields is exhaustive search of the structure.

That's true, we did originally require such fields to be declared, but
see comment below.

> 
> - - some of the terms are obscure, e.g. why use
> "uncompressed_value" as a function rather than the obvious 
> term "constant" or "fixed"? or "irregular" vs. the term "raw" 
> or "uncompressed"? "log2" really means "bitsize", since it is 
> more like ceil(log2(N)).

As my old boss would say "it's historical". These terms have been
inherited by the FN because they're the terms used by ROHC in general.
Yes it may be good to use nicer terms, but it's beyond the scope of the
FN draft. One specific, "value" encoding is the normal name used in ROHC
for "uncompressed_value" (or constant) fields. However, we need to be
able to differentiate between fields which have a constant value in the
compressed 
header and those which have a constant value in the uncompressed header,
hence the prefix.

> 
> - - the discussion of the IP checksum on page 12 fails to
> indicate what fields the checksum is inferred from; that 
> seems more important than the opaque function 
> "inferred_ip_v4_header_checksum" - which isn't listed as 
> taking arguments.

inferred_ip_v4_header_checksum is not part of the FN.
It is up to the profile writer to define this (section 3.3):

   the meaning of
   "inferred_ip_v4_header_checksum" is not defined in the ROHC-FN
   library of encoding methods...  Its
   definition can be given either using plain English text or using the
   formal notation as part of the profile definition itself.

> - - 4.1 talks about the spec being written in 7-bit ASCII;
> it's in 8-bit (in Internet RFCs), although it uses a subset 
> of values from 7-bit ASCII.

OK =) I think this is understood to be the meaning!

> 
> - - 4.2 should indicate whether 'alphabetic' is case
> sensitive or not; later it specifies that constants must use 
> uppercase and others must use lowercase; this is archaic, IMO.
> 

OK

> - - in 4.2.2 it makes no sense that bits on the wire are 
> always interpreted as unsigned, but the notation supports 
> negative values. They should be consistent. and if the value 
> is -1, then it should evaluate to -1.
 
It may not be intuitive, but it does make sense, and is in fact
necessary. Without this combination, you either waste bytes in
the compressed header, or end up with a broken FN. Perhaps we
need more explanation here. We'd taken the view that the reader
just needed to know how things stood.

> - - in 4.5, why is the example of tcp_list_length illegal? 
> would it be illegal if it were:
> 	tcp_list_length:uncomp_value ::= (data_offset + 20) / 4;
> if so, why is the notation so pedantic here, and allows 
> inferences elsewhere about value/size?

It's not about inferences, which are fine (and a key part of
the power of the notation), it's about the fact that you're
passing the ::= operator the wrong kind of arguments. ::=
takes a field and an encoding method. In 4.5, ::= is given
a field and a value, in you example above, ::= is given two
values - they're just the wrong kinds of argument (if you
want to look at it that way). The underlying reason why
you can't though is already in the draft in section 4.5:

   expressions cannot be used as encoding methods directly
   because they do not completely characterise a field.  Expressions
   only specify a single value whereas a field is made up of several
   values: its attributes.

Remember that a field is not a variable and it does not contain
just a single value. This is an important point, so we should
endeavour to explain it better.

> 
> - - 4.5.1 "-10" is "negative ten" commonly; the term 'minus' 
> usually refers to the infix binary operator, not the prefix 
> unary operator

In the UK at least, we say 'minus ten' for both, and never
'negative ten' - is that how it is written in the US? More
importantly, does it cause confusion?

> 
> - - 4.3.5 should discuss whether these logical operations are 
> short-circuit or not

No, there is no such thing as short circuit in a declarative
environment (this is the sort of thing that motivates not
following a C like syntax, which leads to thinking about the
language in an imperative manner). It may be worth adding
some explicit text to clarify that this isn't an imperative
language like C e.g. to section 4.

> 
> - - 4.5.4 it seems odd to round to negative infinity, esp. 
> since the document goes to great lengths to explain that 
> values are unsigned. why not say 'round to zero'? and even if 
> signed values are used, why is round to negative infinity 
> useful or appropriate?

<LOL I wish somebody could come up with some good text for this>
Because "round to zero" is incorrect. The document goes to lengths
to explain that bits on the wire are to be interpreted as unsigned,
however we're not dealing with bits on the wire here, so they can
go negative. The original wording was just "rounded down" IIRC. All
the extra bits were added because people didn't understand what was
meant by "down" or what "next integer" meant.

> - - 4.5.5. what can be tested - only values, or formats too?
 
  "...which take integer arguments"

Do we need to make an explicit note somewhere that formats are
not integers? ;-)

> - - 4.6 the use of the "until EOL" comment character is OK, 
> but there should be an alternative which allows blocks of 
> code to be commented out as well (a paired comment delimiter)

We did have /* */ comments as well as %, but removed them because
they never got used in practice. (not to mention it helped
the language look less C-like)

> 
> - - 4.7.1 why is it not easier to say the following, esp. if 
> the length of the field is already constrained?
> 
> 	field:uncomp_value ::= 3;

That would be

      let (field:uncomp_value == 3)

(see earlier comments on ::= for why), and if the length was
already constrained then yes that would be just as easy to do.
However, typically the way the length gets constrained in the
first place is by the encoding method you use. If you just
specify the value here, what is it that is going to constrain
the length of the field? It might be worth making this explicit
in the draft, that uncompressed field lengths are almost
exclusively constrained by the encoding method used to encode
them. The only other way is to specify the length using a
let statement.

> 
> I.e., why do you need both the uncomp_value selector and the 
> uncompressed_value function?

one is just an attribute, the other is an encoding method that
describes how to map between the compressed and uncompressed
attributes of the field. One is a value, the other is a
relationship. It's the same reason you need both a compiler
and object code - don't know if that example helps!

> 
> - - 4.7.2 why are quotes even needed? and why are only binary 
> strings allowed? i.e., why not use the notation consistently:
> 
> 	discriminator ::= 0b01101;
> 
Because ::= takes an encoding method as it's right hand argument,
not a value.
I can see a theme developing here! We clearly need to clarify
this issue!

> - - 4.7.4 static seems to apply (IMO) to all headers in the 
> flow, not just 'the same as for a previous header in the flow'.

No, see below.

> 
> - - 4.8 why is 'let' needed? why not just allow as above - 
> i.e., the use of the selector to indicate that only this 
> portion is set?
> 
> 	field:uncomp_value ::= 3;
> 

Because ::= takes a field and an encoding method as its
arguments. Overloading it would cause confusion - it
is important when reading the FN to keep hold of the
relationship between fields, encoding methods and attributes.

> also, this section says that lets must be used only inside a 
> field encodings list, but also discusses the use of boolean 
> expressions.
> 
> Huh?
> 
> why not use an 'if' or 'test', like other modern notations?

Because they are imperative: 'if' is a one way operation. The
whole point about the FN is that it describes a two way relationship.
At one end of the link, the "let" will be an assignment, at the other
it will be a conditional. The correct term to use would actually be
"unify", but most people are probably not familiar with that! That is,
make this expression true if possible (which may involve binding
values) otherwise fail.

> 
> - - 4.9.5 as with the TCP doc, the IP ID cannot be valid if 
> it is zero; this should be omitted from the discussion

Whether or not an IP ID of zero is officially valid, zero IP IDs
do occur in real flows, and make a good real world example.
This document is not protocol specific - any examples are
included only to illustrate the notation. Suggestions on
how to improve the example whilst still illustrating the
point are welcome of course!

> 
> - - A.3 "using this simple scheme" - the fixed values are per 
> flow, or per protocol? if the latter, they MUST be dependent 
> on the version number of the protocol

Per flow.

> 
> - - A.5 the example should use version numbers; otherwise, 
> what happens when a new version appears?

It does, the format specifies the version number - need
to clarify this. (or is that not what you meant?)

> 
> - - pg 44 discussion on using 0 vs. 01 - 'care' shouldn't be 
> needed; the notation should suggest this.

OK, that's an interesting one - you're saying it should be a
feature of the FN that it's illegal to specify two packet
formats which are ambiguous. This sounds like a simple to
add and excellent addition. Need to engage my brain as to
whether it reduces to the halting problem however - thoughts
please people.

> 
> 
> draft-ietf-rohc-formal-notation-09.txt
> 
> Overall comments:
> 
> 	the notation description is easy to read,

Thanks =) It hasn't always been thus.

> but has areas that
> 	don't make sense:
> 		- if every header has two (uncompressed, compressed)
> 		or three (+ control) parts, why not define the structure
> 		that way? right now it looks too much like free-form
> 		C structures on which you impose rules, but it is hard
> 		to _see_ whether the rules are followed

see answer to next point

> 		- if there are alternate formats, why not list them
> 		as alternates (using BNF "|") rather than new names?
> 		i.e., why use co_format as a prefix, rather than
> 		say:
> 
> 			header === {
> 				<base format>
> 				COMPRESSED
> 				cf1 = ...
> 				cf2 = ...
> 			}

Whilst I can see that the above suggestion would make things a bit
easier for the unacquainted reader, we've discussed this sort of thing
endlessly. I don't know about the authors, but I feel that the
advantages to be had by making such a change at this stage are probably
not significant enough to carry out because of the scale of the change
they would cause in both the FN and TCP IDs (not to mention the offline
verification tools)

> 
> 	the examples tend to show the exceptions rather than the rules;
> 	get the base rules out, then show exceptions

The idea was that the "base rules" are clearly defined in English and it
is (usually) only the exceptional cases that need an example to
illustrate them - the non-exceptional cases often being very trivial.
However it is a good point to review - thanks.

> 
> 	there should, IMO, be exactly one way to describe things
> 	in the basic language; having equivalent expressions is a
> 	good way to end up with incomparable alternates

Can you be more specific - what in particular are you thinking of?

> 
> MAJOR QUESTIONS:
> 
> *notation appears to ignore reordering?
> 
> 	mentions loss and corruption, but not reordering
> 
> *is there any notion of keeping multiple states
> 	i.e., keeping K parallel interleaved streams -
> 	which can tolerate reordering up to K-1 packets,
> 	but which are all associated with a single stream?

State management is outside the scope of the FN, which is after all just
a notation. It is up to the framework used to implement a profile to
handle issues like reordering, and up to the profile writer to make sure
that the compressed packet formats have enough information in them to
allow them to be reordered. The FN is merely a vehicle to describe those
formats. We should perhaps make this clearer though and in particular
address reordering in the text.

> 
> *4.9.4.2
> 	if the compressor can pick any format that succeeds,
> 	does this mean it cannot pick the 'better' format, for
> 	some definition of 'better'? (shorter, uses more recent
> 	context, etc.)

Sounds like that needs clarifying! No, it is simply a statement that to
provide a valid implementation of a profile, it is not necessary that
your compressor is even close to optimal, only that it produces packets
which the compressor can decompress. Of course an optimal compressor
would be sufficient also. This is typical compressor design: specify the
decompressor and the compressor can do whatever it likes; provided it
fits with the definition of the decompressor. Of course you would like
to aim for an efficient implementation, but the FN does not require it.

> 
> MINOR OBSERVATIONS and QUESTIONS:
> 
> 4.9.2.1
> 	discusses LSB-ish fields of seq nums, but suggests the
> 	field be split into two, rather than LSB-encoded
> 	this is a poor example, IMO

Neither this example, nor any other in the normative part of the ID are
intended to suggest how to encode packet formats. This is not the intent
of the draft at all, but rather to describe the FN. Perhaps it is worth
saying this explicitly. This example is contrived to illustrate the fact

 "that the arrangement of fields specified in the
  uncompressed field order list is up to the notator.  Any arrangement
  of fields that correctly describes the content of the uncompressed
  header may be chosen"

Suggestions please for a better example to illustrate this point, or if
it is thought that this point does not need to be exemplified, please
shout.

> 
> 4.7.4
> 	*static is defined as 'same as previous packet's value',
> 	but should be 'constant within a flow'

No.

> 	the two do not seem the same - are IDs static if prev
> 	packet's 'more fragments' bit==1?
> 

Agreed, they certainly don't mean the same. The description
in the draft is correct. So lets question the name "static"?
Perhaps we should change it to "unchanged" if people
think the motivation is sufficient. Opinions please. Regarding
the "more fragments bit", if you fragment a TCP packet, the
first one has an IP/TCP header on it, but the subsequent ones
have only an IP header. Thus the TCP profile wouldn't be used
for anything other than the first fragment. However to answer
the spirit of your question, "yes". If you had a field that
took the values 3 9 7 2 2 2 2 6 4 3 8 in successive packets
in a flow then after the first time when the field has a
value of 2, you could encode it with static encoding for the
next three headers in the flow. We should explain this better
- thanks.

> 
> notation comment
> 	::= is EBNF - it might be useful to use something that
> 	indicates that the encoding is bidirectional, and which
> 	is the larger, e.g., <=-> or <<--> or somesuch

Agreed. However I don't think it is sufficiently important to
change at this stage. Speaking for myself, it's on of those things
that you notice when you first read the notation, but quickly
forget. Most importantly I don't think it causes confusion -
it's not like you suddenly thing you're reading EBNF.

> 
> 	the way in which control_field_3 is different should be
> 	more readily apparent from the syntax (sec 3.2)

Agreed, it was for a time. However we changed it
to be like this because it made it easier to notate that
way. This is one of the few changes which we made solely out of
experience of using the notation (for the TCP draft).

> 	constants are defined and structures defined using the
> 	same operator (=)

That's true, but the context makes it clear which is which. Most
languages overload symbols here and there. FWIW there is a parser
available for the FN. Since it was produced by a couple of members of
the RoHC group, I'm assuming they'd have shouted up if the = overloading
had caused any problems.

> 
> 	log2(w) seems misnamed; bitsize(w) is more descriptive

Agreed. I'm happy with this change if the authors are happy.

> 
> 	are boolean operators short-circuit? (doesn't matter
> 	if there are no side-effects)

  "ROHC-FN is a
   referentially transparent, declarative language with no side
effects." (section 4)

> 
> 	why do compressed values have shortcuts of 'xx', where
> 	there is no shortcut for uncompressed values?

Because usage showed that it was useful to have such a shorthand for
compressed values, since the most common use for the compressed value
encoding was for encoding huffman codes (or similar), which by their
nature are best viewed in binary. The same does not apply to
uncompressed values.

> 
> 	irregular seems an odd term; why not just indicate the
> 	length and let the encoding be left absent?

Because irregular encoding binds four attributes, not just uncompressed
length:

   the value of "expression" binds with the both the
   "uncomp_length" and "comp_length" attributes of the field, and the
   "comp_value" and "uncomp_value" attributes are bound to each other.

> 
> 	it would be useful to define CRC as taking a list of
> 	polynomials as an argument, or provide an equivalence macro
> 	(sec 4.7.6)

The bit pattern specifies the polynomial - or is that not what you were
after - can you expand?

> 
> 	why have LETs and encoding methods? why not define one, and
> 	let there be an optional macro that equates the two? (4.8)

Because let statements are very low level, binding one parameter at a
time. Structures are effectively the macros which you are after. Each of
the library of encoding methods could theoretically be defined as a
structure containing the appropriate let statements (though we'd have to
expose the context as field attributes to do so). We did start off down
this route, but quickly realised that it didn't help the reader.

Feedback please

Raffles

_______________________________________________
Rohc mailing list
[email-masked]
https://www1.ietf.org/mailman/listinfo/rohc

---

From: Joe Touch <[email-masked]>
Date: Mon, 26 Sep 2005 09:11:04 -0700

Hi, Robert,

Some notes below...

>>Sure - the high order 'bit' of feedback on the formal notation:
...
> readability, so hopefully you have the best of both worlds.

I and others who I have shown the doc to here at ISI felt that the
notation rendered the document much more obscure. It was the notation
itself that lent obscurity.

> imperative mind, you are going to find it hard to grok =)

This is a specification. In specifications, language is usually
imperative pseudocode or EBNF. It's confusing to use prolog as
pseudocode in this case because you're not doing unification. While that
explains some of the notation, it doesn't make a good case for it.

I don't understand the term 'relational spec'; prolog is a logic
language. Although it shares some heritige with relational databases,
neither is relevant to specification notation, except in an obscure
academic sense.

If there's a good case for a prolog-like way to specify packet formats,
then that case should be made elsewhere before it is used in this
community; in 5-10 years, when people read these RFCs, it's not clear
they will care why it's hard to understand, only THAT it's hard to
understand.

If, however,, the idea is that "prolog will make things easier to
understand X", I'm a disbeliever, for all values of X ;-)

> a keyword. Opinions please.

Sorry for being slopping with the term 'variable' - let's call them
'structure element names', which are just created tokens. Keywords are
reserved tokens.

And co_format IS a keyword - it's a _required_ keyword-as-prefix to a
token. If you used co_format_blue as a field element name, it ought to
be an error.

> Conditionals' for an example of a conditional control field.

Later I wonder why 'let' is used there rather than 'if', but this
underscores the complexity - a key feature explained in an appendix?

> packets are the answer - it would be worth the draft explaining this

1:0 is easy; it's the 3:2 relationships that are going to be harder to
explain here. In particular, thinks like TCP Boston which does FEC,
which is a kind of N:M expansion (which is a kind of compression, FWIW).

> header and those which have a constant value in the uncompressed header,

The FN is a new notation; if you want others to invest in reading it in
order to appreciate other specs (e.g., TCP compression), it ought to be
comprehensible by itself. 'Historical' baggage must be discarded where
it makes the notation hard to understand by itself, IMO.

>    formal notation as part of the profile definition itself.

Yeah, but it's not in this doc. If your goal is to show what a complete
spec is, you need to include it - even as an example of what level of
description needs to be included.

> takes a field and an encoding method. 

That, FWIW, looks like an object imperative to me ;-)

> In 4.5, ::= is given

A clearer explanation is that tcp_list_length, like all fields, is an
object with both a length and a value. In which case, it should be
possible to do both assignments at once:

	tcp_list_length ::= ((data_offset + 20) / 4, 20);

Which would mean its value would be (data_offset + 20) / 4,
and its length 20. (or pick whatever OO notation you prefer).

> importantly, does it cause confusion?

No problem;; I don't think it's confusing, and I wasn't aware of the
cultural difference.

> language like C e.g. to section 4.

That's not sufficient - you also need to highlight the difference in
places like this. I don't think it's unreasonable to define how logical
operators work when they're used anyway, the confusion between C and
Prolog notwithstanding.

> meant by "down" or what "next integer" meant.

OK - so I understand that this isn't 'on the wire' use, but I would
still expect such rounding to go toward zero. What is the reason to go
toward negative infinity

> Do we need to make an explicit note somewhere that formats are

Why not? What are they?

>       let (field:uncomp_value == 3)

let is a test; this looks like an IF statement as well. This is
continuing to be confusing.

> them. The only other way is to specify the length using a

"almost exclusively" is worrisome. That's a lot of wiggle room for a spec!

> and object code - don't know if that example helps!

Not really. ;-) That sounds academic; I need a reason the FN needs the two.

> I can see a theme developing here! We clearly need to clarify

I'm really confused if you think that 0b01101 is a value, and '01101' is
an encoding !

> relationship between fields, encoding methods and attributes.

It's already confusing in this regard - there are places where it's
allowed and places where it's not, and doesn't appear as rigorous (quite
the contrary) from my perspective.

> make this expression true if possible (which may involve binding

Oh, it's NOT unification ;-) That would be REALLY bad.

It may be assign at one side and a test at the other, but again that is
very confusing. It's not clear at all what level of subtlty is being
communicated here.

> do occur in real flows, and make a good real world example.

So do bugs, but a spec of how a correctly operating protocol works
should not include bugs except as errors.

> point are welcome of course!

It'd be easier to just omit the possibility of a zero IP ID. I.e., the
example ought to describe correct operation, not just extant errant
implementations.

> whether it reduces to the halting problem however - thoughts

It seems like a compiler ought to be able to help here - although prolog
isn't a compiled language, and I could see unification trundling off
into oblivion on this one... ;-)

> they would cause in both the FN and TCP IDs (not to mention the offline

I would have preferred that 'easier to the unaquainted reader' would
drive this process - that's the point of a notation in this sort of spec
anyway. If only aquainted readers will use it, then it sounds like a
research project, not a standard and we need not spend as many cycles
tweaking it.

> Can you be more specific - what in particular are you thinking of?

This refers to the difference between the function (uncompressed_value)
and the object element (uncomp_value), etc.

> address reordering in the text.

The FN doesn't describe state or dependencies thereof? Then how can it
be sufficient to implement an encoder or decoder?

> to aim for an efficient implementation, but the FN does not require it.

OK.

> saying this explicitly. This example is contrived to illustrate the fact

If you don't describe how to encode packet formats, you can't make
interoperating implementations.

>>	but should be 'constant within a flow'

How so? When would it be different?

> next three headers in the flow. We should explain this better

I never thought of MF as static, which may be the problem. This might be
a good example.

> the RoHC group, I'm assuming they'd have shouted up if the = overloading

The context may make it clear for the parser, but the point of the
notation at some level is human readability too...

>>	if there are no side-effects 
> 
>   "ROHC-FN is a

Legally correct, but people don't keep stacks that deep. I.e., it's
useful to remind people, esp. in places such as where boolean operators
are mentioned, what is true and why...

>    "comp_value" and "uncomp_value" attributes are bound to each other.

If that's the goal, it's somewhat opaque.

> The bit pattern specifies the polynomial - or is that not what you were

Telling me '010100' isn't the same as telling me the polynomial in
polynomial form. There's a parser after all! Give the author/reader the
option of specifying the polynomial as "x^7+x^4+x^3" or somesuch...

> this route, but quickly realised that it didn't help the reader.

It'd be useful to get more input from outside readers. I suspect the
current notion of what 'helps the reader' might be somewhat local, and I
hope that the goal of the notation is to be useful to outsiders too.

(I hope this all helps, as well).

Joe