akkartik / mu

Soul of a tiny new machine. More thorough tests → More comprehensible and rewrite-friendly software → More resilient society.
http://akkartik.name/akkartik-convivial-20200607.pdf
Other
1.38k stars 47 forks source link

exercise: reimplement print-int-decimal #20

Closed akkartik closed 5 years ago

akkartik commented 5 years ago

To see the failing tests:

$ ./subx translate 0*.subx -o a.elf  &&  ./subx run a.elf test

Feel free to push changes to this branch as you like. You may want to work on #21 and #22 first.

When (when!) you need to debug things, go back and reread https://github.com/akkartik/mu/blob/master/subx/Readme.md#a-few-hints-for-debugging. And, of course, feel free to email me.

charles-l commented 5 years ago

Well, I thought I had a pretty nice implementation going until I had to make it deal with negative numbers :P

Hoarding one register the whole time to store one bit of information (whether the number is negative) feels pretty wasteful, but I couldn't find anywhere else to store it. I thought of potentially trying to store it in the ZF flag or something, but that would require juggling stuff in and out of the ZF flag before comparisons...

akkartik commented 5 years ago

I went through similar "stages of grief". You should look at my solution now if you haven't already. I paid for the sign with an extra load rather than an extra register. Not sure if that's good or bad.. But performance isn't that important /shrug.

akkartik commented 5 years ago

I have to keep reminding myself that I'm trying to reduce instructions just as a heuristic keeping things simple. But it's easy to fall into the trap of thinking about performance.

akkartik commented 5 years ago

I'll check out your code in a few hours but if you're ready for more I recommend the prerequisite B PR/branch. I've been working on A. You may want to read up on slices in the Readme, and in layer 72.

This is no longer just exercises!

charles-l commented 5 years ago

I have to keep reminding myself that I'm trying to reduce instructions just as a heuristic keeping things simple. But it's easy to fall into the trap of thinking about performance.

Ugg, I struggle with this constantly. As a performance junkie, I have a bad habit of obsessing over code's performance before writing it. Writing the simplest, most straightforward code often yields better results (in terms of both performance, and maintainability).

I recommend the prerequisite B PR/branch. I've been working on A. You may want to read up on slices in the Readme, and in layer 72.

This is no longer just exercises!

Alright! I'll start working on it this weekend.

akkartik commented 5 years ago

I just looked at your solution. Most interesting. I was pushing the digits as integers on the stack, and saving the sentinel as an address, where you save the digits as characters in the first place. Saves you a register since the sentinel is just plain 0. I also end up having this magic constant -3 which is '-' - '0', just so it prints out a '-' once you add '0' to it. That seems overly clever.

Nice work! Thank you for the ideas.

akkartik commented 5 years ago

Alright I'm merging this. I like your version better.

akkartik commented 5 years ago

Just realized my version had a bug that yours doesn't: My first loop was a while..do rather than do..while, and as a result it didn't handle 0 correctly. Thanks again!

Now adding a test for this bug to master.

akkartik commented 5 years ago

Done: https://github.com/akkartik/mu/commit/2d61d10eca7b7858588a4aa0eb40a7952120f527

I did find one out-of-bounds bug: https://github.com/akkartik/mu/commit/c4c30c7dc92ad8f5c00bf8facaa089b4ed9cab53

I also added another bounds check: https://github.com/akkartik/mu/commit/8591331a7f674d71c50ea0f560e1412d56001801