Skip to content

Commit

Permalink
Double dispatch on arithmetic & relational operations for number type…
Browse files Browse the repository at this point in the history
…s. (#377)

This PR uses the existing single-dispatch mechanism to implement
arithmetic & relational operators with double dispatch. As a result we
don't typically need to convert between number types. For instance, if
you add a `Nat` and an `Int` you get an `Int` as a result. The goal is
to always return the correct value or result according to mathematics,
so there is no danger of overflow or unexpected results. The output type
is chosen so that it is large enough to represent the outcome, e.g.
adding two `I64` will result in an `Int`, not an `I64`. Dividing two
integers results in a rational number (`Rat`). Floats are inexact, so
when you have an operation using floats (`F32` or `F64`) you will always
get a float as a result.

How double dispatch is implemented via single dispatch: The idea is to
turn a method on the top argument into a distinct method on the second
argument based on the top argument's type. If you look in `std.number`
you'll see how this was achieved. When calling `Int.+`, it pushes the
top number onto the `int` stack label and calls the `int+` method on the
second argument. When calling `Nat.+`, it pushes the top number onto the
`nat` stack label and calls the `nat+` method on the second argument.
Thus if you have a type implement `int+` and `nat+` it can adjust the
return types based on the value.

In addition, this PR also:

- Moves the number methods from `std.prelude` to `std.number`. You don't
need to import `std.number` directly.
- Adds a number type `Zero` which represents only the number 0.
- Adds a rational number type `Rat`.
- Adds a complex number type `Complex(a,b)`, parametrized on the types
for the real and imaginary components.
- Merges `USize` and `ISize` types as `Size`.
- Merges `UOffset` and `IOffset` types as `Offset`.
- Removes `UIndex`.
- Changes the types in std.posix to take advantage of resources a bit
better, and allow for error handling.
- Changes `==` to `=` (but `==` still works).
  • Loading branch information
typeswitch-dev authored Feb 23, 2025
1 parent 3381c2e commit 82fd7d7
Show file tree
Hide file tree
Showing 71 changed files with 21,933 additions and 15,773 deletions.
24 changes: 18 additions & 6 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -125,14 +125,26 @@ bin/mirth2debug: bin/mirth2debug.c
bin/mirth3debug: bin/mirth3debug.c
$(CC) -g -o bin/mirth3debug bin/mirth3debug.c

bin/mirth1.c: bin/mirth0 $(SRCS)
bin/mirth0 src/main.mth -o bin/mirth1.c
bin/mirth1-new.c: bin/mirth0 $(SRCS)
bin/mirth0 src/main.mth -o bin/mirth1-new.c

bin/mirth2.c: bin/mirth1 $(SRCS)
rm -f bin/mirth2.c && bin/mirth1 src/main.mth -o bin/mirth2.c
bin/mirth2-new.c: bin/mirth1 $(SRCS)
bin/mirth1 src/main.mth -o bin/mirth2-new.c

bin/mirth3.c: bin/mirth2 $(SRCS)
rm -f bin/mirth3.c && bin/mirth2 src/main.mth -o bin/mirth3.c
bin/mirth3-new.c: bin/mirth2 $(SRCS)
bin/mirth2 src/main.mth -o bin/mirth3-new.c

bin/mirth1.c: bin/mirth1-new.c
touch bin/mirth1-old.c
diff -q bin/mirth1-old.c bin/mirth1-new.c || (cp bin/mirth1-new.c bin/mirth1-old.c && cp bin/mirth1-new.c bin/mirth1.c)

bin/mirth2.c: bin/mirth2-new.c
touch bin/mirth2-old.c
diff -q bin/mirth2-old.c bin/mirth2-new.c || (cp bin/mirth2-new.c bin/mirth2-old.c && cp bin/mirth2-new.c bin/mirth2.c)

bin/mirth3.c: bin/mirth3-new.c
touch bin/mirth3-old.c
diff -q bin/mirth3-old.c bin/mirth3-new.c || (cp bin/mirth3-new.c bin/mirth3-old.c && cp bin/mirth3-new.c bin/mirth3.c)

bin/mirth1debug.c: bin/mirth0 $(SRCS)
bin/mirth0 --debug src/main.mth -o bin/mirth1debug.c
Expand Down
Loading

0 comments on commit 82fd7d7

Please sign in to comment.