-
Notifications
You must be signed in to change notification settings - Fork 2
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
interpreter: represent all numbers as rationals #119
base: main
Are you sure you want to change the base?
Conversation
To not lose information for rationals that don't have a (finite) string representation, |
Move the implementation of the `languages` macro into a procedure and emit a call to that procedure from the `languages` macro. This addresses two problems: 1. it eliminates the very high compile-time overhead (~1.5 seconds for `source.nim`) to that `newLit` + sem + evaluate has 2. it doesn't require a manual implementation of `newLit` for `Rational` and `Int128` (both whose fields are not exported)
All processing of numbers, which previously accessed the `.sym` field, are changed to use `.num`. The `rationals` API is extended with some conversion-related procedures.
Integer-type patterns now only match for integer values, as they should.
Concrete function are faster to type check, and this also prevents bugs by passing unsupported values to the arithmetic operators.
The operator is named `div` now.
It's used to conveniently created fractions (both proper and improper).
The resulting denominator must always be positive.
It still assumed that rational numbers were stored as strings.
`newLit` cannot be used with `Node` anymore. The same solution as with the `lanugage` macro is used, that is, actual processing/production is factored into its own procedure, which the macro then emits a call to.
Only `FloatVal` with an integer argument was erroneously considered a value.
It would have also been possible to render fractions with no finite decimal number representation as |
On my machine, the compile time savings are at around 1 second, which is quite good. |
The former two are needed by a fix for rationals, the latter one is added for completeness' sake.
Due to signed division using recursion and unary `-` for negative numbers not always resulting in positive values (unless treating the result as unsigned), `x div low(Int128)` led to infinite recursion. `divMod` is rewritten to not use recursion, fixing the problem.
The `reduced` implementation had the same issues as `divMod` for `Int128`, that is, I didn't consider `not isNeg(-x)` doesn't always hold true when `isNeg(x)`. The procedure is changed to not use recursion and division is changed to always be unsigned (because it's faster).
I've fixed an edge case with signed 128-bit integer division and @saem: The PR is ready for review now, but please don't merge it yet. I want to first make sure that everything still works after #127 has been merged. |
Okay, back to a draft it goes. Rational numbers (for usage as the numerical value representation in the interpreter) needs arbitrary precision to be practically useful. My previous plan was to first merge rational number support and then implement and use some simple bignum library in post, but I'm almost done with implementing the bignum module already, so there's no point in merging a (mostly) useless rational number library first. |
Summary
interpreter
FloatVal
not being considered values in the sourcelanguage definition
language
andterm
macroinvocations
Details
Rational
type, implemented as a numerator/denominator pairRational
Rational
s inNode
. All usage sites ofNode
expecting numbers stored as strings in
.sym
are updatedz
pattern matching in the interpreter to only match integernumbers
newLit
usage fromlanguage
andterm
;newLit
cannot beused anymore, as the fields of
Rational
(stored inNode
) are notexported. The actual processing is factored into normal procedures
taking a
NimNode
as input, with the macros then emitting a call tothe respective procedures, passing the quoted macro argument along
rat
(instead of type variables) as the parameter type for somebuilt-in functions, to improve type checking precision and type
inference
divMod
, due tolow(Int128)
notbeing considered
The
newLit
usage majorly contributed to compile times, because:newLit
call itself has to process a large amount of datamacros need to be sem-checked again and - if appearing in a
const
context - compiled for and evaluated with the VMRemoving the
newLit
usage therefore significantly decreases compiletimes.
To-Do