3 ms·
You are conflating, in a typical model/metamodel confusion, numbers in the data structures you are describing, with their machine representations that you are m
by HelloNurse 4y ago
You are conflating, in a typical model/metamodel confusion, numbers in the data structures you are describing, with their machine representations that you are modeling decently, and numbers in your language, which should probably be just integers without complications.
The former are are patterns in the data, e.g.
rpm = float(32, -1000~1000);
which specifies a subset of the 2^32 floating point values, and the latter are actual numbers, e.g.
identifier = 'a'~'z'{5~8};
which shouldn't worry about rounding, signed zero, NaN values etc.
What arithmetic do you expect to need, in practice, at each of the two levels?
> real: any value from the set of reals, including qnan and snan unless otherwise specified
You mean floating point, not actual real numbers. Then, even within the IEEE-754 options, you need to specify what variant of floating point.
Note that floating point constants by themselves have ambiguous type: 1.3e5 can be float(32...), float(64...), etc.
> Note: Calculations can produce a quiet NaN value under certain conditions in accordiance with the IEEE 754 specification. If different processing is required (such as traps or exceptions), this must be documented in your specification.
This means specifying what to do with NaN results and similar errors: a heavy burden for the user.
> unsigned: limited to positive integers and 0
> signed: limited to positive and negative integers, and 0 (but excluding -0)
These are floating point values pretending to be integers. You should have actual unlimited precision integers with constraints like explicit maximum and minimum values.
Moreover, "-0" is a IEEE-754 technical detail that has no place in a formal, abstract language.
- kstenerud 4y agoHmm good point. My plan was to allow concepts such as inf, NaN and negative 0 to be available in the abstract, and then convertible to a concrete implementation such as ieee754. But in actual fact it's mostly muddying the waters, and those kinds of values would be better represented as functions that produce ieee754 values rather than abstract concepts that don't really work abstractly anyway (I was thinking that as an abstract concept it could be passed to a general function for any given floating type implementation such as binary float, decimal float, bfloat, etc). >> unsigned: limited to positive integers and 0 > signed: limited to positive and negative integers, and 0 (but excluding -0) > These are floating point values pretending to be integers. You should have actual unlimited precision integers with constraints like explicit maximum and minimum values. The idea here is to have all numbers be treated as reals (in the mathematical sense) for abstract calculation purposes, and then use the pseudo-types "signed" and "unsigned" to represent common invariants on those reals (such as "can only be 0 or an integer" or "can only be 0 or a positive integer"). For example, ('a'~'z'{chars_per_record}){char_count / chars_per_record} (where char_count and chars_per_record are bound from another part of the document) is a common enough method used to envelope data in binary formats. But if char_count = 100 and chars_per_second = 3, you can't accept a fractional count (i.e. it would be an indication that the data in this document is corrupt or malformed). Only the functions `uint`, `sint`, and `float` would convert a number into an actual expression (provided their invariants are respected).
- HelloNurse 4y ago> The idea here is to have all numbers be treated as reals (in the mathematical sense) No. You can't represent, compare etc. most real numbers, so they aren't any good for computational purposes. Practically usable number types include integers and things that have sufficiently number-like behaviour (e.g. fields) and can be represented with a finite number of integers: rational numbers, rational numbers with field extensions, vector spaces, finite sets, intervals, etc. In a language for grammars you can probably stop at integers; general purpose programming languages might want more (for instance, Python has rational numbers) but advanced number types can usually be implemented with libraries.
- kstenerud 4y agoI think maybe I'm not understanding you correctly... In most cases for binary formats an integer type will be expected for 99% of cases. Something like `uint(8,a/b)` will only generate an alternates set within the realm of integers, so a rule containing such an expression as this could only match when this particular byte matches a/b, which can only happen when a/b results in an integer from 0 to 255. For all a/b where this isn't true, the rule will not match. But support for matching float encodings is still needed, such as for `reading = float(32,0~1);`, which would happily match an ieee754 32-bit binary float approximation of 0.3 or 0.8 or anything from 0 to 1 that can be represented in this float format.
- HelloNurse 4y agoYou are talking about the limited precision numbers in data, not about appropriate numbers for use in your language to express counts, repetitions, aggregate sizes etc. They are two related but categorically different kinds of entity, like screws and screwdrivers or sheet music and audio files. Grammar rules aren't supposed to work "for 99% of cases" depending on complex invisible constraints such as whether finite precision causes floating point arithmetic to depart from exact integer arithmetic.
- kstenerud 4y ago