awesome! wouldn’t this be, like, the first major non-linus “non-canonical” change or addition to dialog?
I believe so! And it was easier than I’d feared.
Though this only applied to the Z-machine backend, I didn’t have to touch anything in the actual Dialog parser or Å-machine code.
if you placed the white between the green and the red, your example will be purrfect !
best regards from Italy,
dott. Piergiorgio.
I like it too and think a new name would be unnecessarily confusing.
I feel like this has the obvious downside of making the documentation harder to use. What is the upside?
All right, I’ve submitted a pull request. This one’s a pretty easy change because it’s not actually altering the language at all, it’s just an improvement to the compiler. But now a couple new questions come up:
- Should we increment the compiler minor version number when we merge in a new feature?
- What should we do about the documentation? It wouldn’t be that hard to reverse-engineer Linus’s HTML and CSS style and get Pandoc or something to output it, so that’s my vote.
- If something requires an extension to the Å-machine, how will that be handled?
My next order of business will probably be making it combine styles properly on the Z-machine, because that’s similarly a compiler improvement but not a language change, and it relies on Z-machine assembly which I know. But after that I’d like to add seeding the RNG and measuring the size of the current div, and both of those will require small adjustments to the Å-machine (they’re not supported by the current instruction set).
I’m influenced by how it works in Inform6, so my suggestions are…
The minor version number should be bumped up now to 04
, i.e. 0m_04_0_46
and stay there until there is an “official” new release. In the meantime builds should display that this is an active version in development.
C:\Users\heasm>dialogc -V
Dialog compiler 0m/04 (in development)
Major version updates are reserved for when backward compability is broken, meaning when old code no longer is sure to compile with the new compiler.
Changes could be documented as release notes for the new version (readme.txt
) in the already established format. The documentation/addendum then only needs an update when there is a new “official” release, and we can punt on it for the moment.
If the Å-machine needs update to support changes, file them as issues in that repository and write in release notes for Dialog that this change don’t work Å-machines, version XX and older.
Exciting!
Every time we merge seems like overkill, but maybe we’ll evolve to that if adding features becomes infrequent. I don’t offhand have an opinion on a versioning strategy, but Henrik’s seems fine.
Generally in favour of trying to keep the documentation in sync with our changes. The existing HTML does not look like the worst thing to hand-edit as long as we’re only making minor changes, so that’s where I’d probably start… does feel like we’d want to switch to pandoc or similar if we start making wider changes however.
For some reason I find the idea of changing the Å-machine way more serious than changing Dialog itself? I suppose it forces anyone who wants to use the community Dialog fork to also use the community Å-machine, and I don’t know how much enthusiasm folks here have for adding new features to the Commodore 64 interpreter… I’ll have to reflect on this!
The VM_INFO
opcode allows for testing capabilities in the way of Glulx’s @gestalt
. So some features could be safely added and used only in updated interpreters, depending on how the new feature would work. Or at the very least the storyfile could test and then show an error message if an essential extension isn’t supported.
Regarding going beyond the 14-bit limit. Would it not be possible to include an optional library that can do some maths with bigger (or negative) numbers? To keep the language itself more compatible with all possible past and future backends/platforms even if it instead uses up maybe two numbers behind the scenes to represent one bigger (signed) number.
Could even be a more generic maths-library with other things that most games might not need, but can be useful to have available in a standard way. Many programming languages have something like that (e.g. python’s math module).
Using integers beyond more “human-countable” (or however to describe it; values that tend to show up in real life that you experience around you in the real every day world) values in my experience is rather rare in i-f in general. Not that I have any data to back that up.
That’s definitely possible, and wouldn’t require any compiler adjustments! The only question is whether it would get unbearably slow, or unbearably memory-intensive.
But I’ve been considering making a library like that for a while, which would handle negative numbers as well, probably representing everything in base 128 (since 1282 < 214, so there’d be no risk of multiplication overflowing). Basically represent a number as a list, where the first element is either +
or -
for the sign, then a series of “digits” in base 128.
Or perhaps base 100, which would make printing these values a lot easier. The underlying math would be basically the same either way.
I did exactly that in Advent 2.5 big numbers (decimal coded centesimal arithmetic, similar to BCD). It gets very memory intensive with recursive implementation of math operations.
Hm. I’ve been toying with this a bit, and trying to use tail recursion as much as possible to avoid that; or is it the storage that’s the problem, rather than the call stack?
The big numbers are stored and manipulated in lists. When they are passed up and down the recursion storage space blows up the heap usage, regardless of the tail recursion.
It is not that bad though, if one is willing to limit the maximum for the big numbers to 32 or 64 bits iirc. As the digits are increasing, so does the recursion depth and heap usage.
Here’s what I’ve currently been playing with:
A bignum is a list of base-100 digits, stored least-significant first, plus a sign marker.
(bignum [+/- | $])
Comparisons are a bit annoying, but not too bad.
([- | $] is less than [+ | $])
([- | $Left] is less than [- | $Right])
([+ | $Right] is less than [+ | $Left])
([+ | $Left] is less than [+ | $Right])
(length of $Left into $L1)
(length of $Right into $L2)
($L1 < $L2)
([+ | $Left] is less than [+ | $Right])
(length of $Left into $L)
(length of $Right into $L) %% Same length
($Left is digitwise less than $Right)
@($Left is greater than $Right) %% No need to write that all out again, the compiler can rearrange it for us
($Right is less than $Left)
([$L | $Rest] is digitwise less than [$R | $Rest]) %% If all the rest is the same, compare the current digit
($L < $R)
([$ | $Left] is digitwise less than [$ | $Right]) %% Otherwise, recurse
($Left is digitwise less than $Right)
Then addition and subtraction are straightforward enough:
%% For addition, delegate to a subroutine that doesn't have to care about sign
([+ | $A] + [+ | $B] into [+ | $AB])
($A + $B into $AB carrying 0)
([- | $A] + [- | $B] into [- | $AB])
($A + $B into $AB carrying 0)
%% And convert opposite-sign addition into subtraction
([+ | $A] + [- | $B] into $Out)
([+ | $A] - [+ | $B] into $Out)
([- | $A] + [+ | $B] into $Out)
([- | $A] - [- | $B] into $Out)
([$A | $AMore] + [$B | $BMore] into [$AB | $ABMore] carrying $Carry)
($A plus $B into $Tmp)
($Tmp plus $Carry into $Total)
($Total divided by 100 into $NewCarry)
($Total modulo 100 into $AB)
($AMore + $BMore into $ABMore carrying $NewCarry)
([] + [$B | $BMore] into [$AB | $ABMore] carrying $Carry)
($B plus $Carry into $Total)
($Total divided by 100 into $NewCarry)
($Total modulo 100 into $AB)
([] + $BMore into $ABMore carrying $NewCarry)
((nonempty $A) + [] into $AB carrying $Carry) %% Let's not duplicate all that code
([] + $A into $AB carrying $Carry)
([] + [] into [] carrying 0) %% No final zeroes allowed!
([] + [] into [$Carry] carrying $Carry)
%% Convert opposite-sign subtraction into addition
([+ | $A] - [- $B] into [+ | $AB])
($A + $B into $AB carrying 0)
([- | $A] - [+ $B] into [- | $AB])
($A + $B into $AB carrying 0)
%% Flip negatives to positives temporarily to simplify implementation
([- | $A] - [- $B] into $AB)
([+ | $A] - [+ | $B] into $BA)
(negate $BA into $AB)
%% Also ensure the minuend is always greater than the subtrahend
($A - $B into $AB)
($A is less than $B)
($B - $A into $BA)
(negate $BA into $AB)
%% Now, finally, we know things have been simplified appropriately
([+ | $A] - [+ | $B] into [+ | $AB]) %% Result will be positive because we've guaranteed that inputs are positive and A > B
($A - $B into $Tmp borrowing 0)
(remove final zeroes from $Tmp into $AB)
([$A | $AMore] - [$B | $BMore] into [$AB | $ABMore] borrowing $Borrow)
($B plus $Borrow into $Subtrahend) %% Total amount to remove
(if) ($Subtrahend > $A) (then)
($A plus 100 into $Minuend)
($NewBorrow = 1)
(else)
($Minuend = $A)
($NewBorrow = 0)
(endif)
($Minuend minus $Subtrahend into $AB)
($AMore - $BMore into $ABMore borrowing $NewBorrow)
([$A | $AMore] - [] into [$AB | $ABMore] borrowing $Borrow)
(if) ($Borrow > $A) (then)
($A plus 100 into $Minuend)
($NewBorrow = 1)
(else)
($Minuend = $A)
($NewBorrow = 0)
(endif)
($Minuend minus $Borrow into $AB)
($AMore - [] into $ABMore borrowing $NewBorrow)
([] - [] into [] borrowing 0) %% Final borrow should always be zero
(I haven’t found a really efficient way to remove final zeroes yet. It’s a bit of a sticking point.)
Printing:
(print bignum [+])
0
(print bignum [+ | $List])
(print digit list $List)
(print bignum [- | $List])
- (no space)
(print digit list $List)
(print digit list [$Single]) %% No leading zeroes for a single digit
$Single
(no space)
(print digit list [$Digit | $Rest])
(print digit list $Rest) %% Recurse before printing, so the last (i.e. most significant) digit gets printed first
(if) ($Digit = 0) (then)
00
(elseif) ($Digit < 10) (then)
0 (no space) $Digit
(else)
$Digit
(endif)
(no space)
And converting to and from these:
%% Converting to and from different bases, as a general-purpose thing - note that this returns the least significant digit first, so reverse it afterward if needed!
($Number in base $Base is [$Number])
($Number < $Base)
($Number in base $Base is [$Digit | $Rest])
($Number modulo $Base into $Digit)
($Number divided by $Base into $Next)
($Next in base $Base is $Rest)
%% And the inverse operation
([$Number] from base $ into $Number)
([$Number|$Rest] from base $Base into $Out) %% TODO - can this be done with tail recursion somehow?
($Rest from base $Base into $Tmp1)
($Tmp1 times $Base into $Tmp2)
($Number plus $Tmp2 into $Out)
The last bit is meant to be general-purpose, as a way of implementing e.g. bitwise operations. But the heap usage is likely to become a problem if so.
You can also use 100s complement to implement negative numbers and subtraction.
The handling of “human-countable” numbers, as defined by you, has a well-known classical implementation, the BCD (Binary Coded Decimal) format & math.
Best regards from Italy,
dott. Piergiorgio.
I’ve changed the ruleset for the Main branch so updates need to come from pull requests and require at least one reviewer. I also accepted the first pull request from @Draconis as a test. There’s also a new PR waiting for review that bump up the VERSION and adds a placeholder to the readme.txt. According to the new rules, I can’t accept my own PR, so time for you, my fellow contributors…
Hi everybody!
Long time no see.
I was always meaning to get back to Dialog development after a short break, but somehow I kept getting caught up in other projects. And I kept meaning to get back to it, and time kept passing… you know the feeling, I’m sure. I’ve also been feeling increasingly bad about letting the community down.
But I’ve just read through this thread (thanks for the nudge, Ben Kirwin!) and I’m very happy to see that people have taken action where I’ve just been postponing. I get good vibes from the discussion, and I think you’re on the right track. Some of you are even talking about trying to keep it in the spirit of my original vision, which I appreciate a lot on a personal level.
While I still care a lot about Dialog, I can no longer ignore the fact that it’s best for the project if I hand over the day-to-day feature development and maintenance to the community. You have my blessing to keep working on it, and to keep the Dialog name if and while it seems appropriate; if you feel that the project is drifting very far from the original spirit of the language, a fork and rename might be called for. I can weigh in on that decision if it ever becomes an issue. But I’m also curious to see how the language will evolve under the guidance of other creative minds.
If for some reason this community effort breaks down into conflicts and bickering, I’d like to think I have the moral right to step in and arbitrate. But the project is open source, so you can actually already do as you please. =)
Regarding versioning, I ask that major version 0 remains my personal release branch, in case I want to build upon my own codebase. You can hop over to a fresh start with 1a. Increment the letter with language changes, and ask me before going to 2.
The Dialog Manual is generated from a custom source format, so I would advise against editing the HTML directly. I should probably release the source for it, but I don’t want to commit to doing it soon; I fear I’ll procrastinate again and hold you back. Perhaps an addendum is the way to go in the meantime.
I have test cases, but some of them are based on code snippets that people have sent me in private, and I can’t redistribute those. So I would have to sort through the test cases manually. Again, I hesitate to promise anything because it would only get procrastinated. Consider building a new set of test cases, and I can integrate mine with yours later.
I’ve also made some local unreleased optimizations to the compiler, but those should be possible to integrate at a later point.
Thanks for being such a wonderful community! I feel good about entrusting Dialog in your care.
Now back to lurking (and turning old computers into musical instruments)!
Best regards,
Linus
It’s great to hear from you again, and I’m glad our adjustments so far haven’t departed too much from your goals for the language!
We would of course always appreciate your help if you want to jump back into development; you understand the codebase a lot better than any of us, and things like why having too many dictionary words in a wordmap crashes the interpreter with an illegal object number would probably be a lot clearer to you than to us. But we also, of course, understand not having infinite time for an infinite number of projects!