Commit Graph

8151 Commits

Author SHA1 Message Date
Kartik K. Agaram 9a5e94ce1f . 2021-04-21 19:44:06 -07:00
Kartik K. Agaram 25791d9032 opt: don't clear streams of bytes on the stack
All over the Mu code I reflexively initialize all variables just to keep
unsafe SubX easy to debug. However I don't really need to do this for safe
Mu code, since the type- and memory-safety already ensures we can't read
from streams beyond what we've written to them. For now I'll continue mostly
with the same approach, but with one exception for streams of bytes.

Mu programs often emit traces, and in doing so they often use temporary
streams of bytes that can get quite long. I'm hoping avoiding initializing
KBs of data all over the place will measurably speed up the Mu shell.
2021-04-21 19:30:28 -07:00
Kartik Agaram a8fb537a88 . 2021-04-21 08:28:00 -07:00
Kartik K. Agaram d27994a9d7 shell: show screen state during evaluation
All highly experimental. Current constraints:

* No tail recursion elimination
* No heap reuse
* Keep implementation simple

So it's slow, and I don't want to complicate it to speed it up. So I'm
investing in affordances to help deal with the slowness. However, in the
process I've taken the clean abstraction of a trace ("all you need to do
is add to the trace") and bolted on call counts and debug-prints as independent
mechanisms.
2021-04-21 00:25:06 -07:00
Kartik K. Agaram d604e68c2b . 2021-04-21 00:17:22 -07:00
Kartik K. Agaram 7b2d39b8d4 an interface approximating stack traces 2021-04-20 23:27:13 -07:00
Kartik K. Agaram fb34909b4e get bresenham line drawing working with a trace
(brline . (fn () (screen x0 y0 x1 y1 color)
                 ((fn (dx dy sx sy)
                    ((fn (err)
                       (brline1 screen x0 y0 x1 y1 dx dy sx sy err color))
                     (+ dx dy)))
                  (abs (- x1 x0))
                  (- 0 (abs (- y1 y0)))
                  (sgn (- x1 x0))
                  (sgn (- y1 y0)))))
    (brline1 . (fn () (screen x y xmax ymax dx dy sx sy err color)
                 (pixel screen x y color)
                 (if (andf (= x xmax) (= y ymax))
                   ()
                   ((fn (e2)
                      (brline1 screen
                        (if (>= e2 dy)
                          (+ x sx)
                          x)
                        (if (<= e2 dx)
                          (+ y sy)
                          y)
                        xmax
                        ymax
                        dx
                        dy
                        sx
                        sy
                        (+ err
                           (+
                             (if (>= e2 dy)
                               dy
                               0)
                             (if (<= e2 dx)
                               dx
                               0)))
                        color))
                    (* err 2)))))

sandbox: (brline screen 1 1 5 5 12)

There are two ideas stemming from this commit:
  - I need an extremely compact on-screen trace to underlie the trace UX
  - perhaps we should start truncating trace lines
2021-04-20 19:47:57 -07:00
Kartik K. Agaram fb3967876c deemphasize fn arg evaluation slightly 2021-04-19 21:19:56 -07:00
Kartik K. Agaram 34596b6ee9 reimplement pixel graphics
Before: we always drew pixels atop characters, and we only drew pixels
that were explicitly requested.

After: we always draw pixels atop characters, and we only draw pixels that
don't have color 0.

Both semantics should be identical as long as pixels are never drawn atop
characters.
2021-04-19 21:05:57 -07:00
Kartik K. Agaram c22874a97f . 2021-04-19 10:47:30 -07:00
Kartik K. Agaram 1114442c23 . 2021-04-19 10:47:30 -07:00
Kartik K. Agaram 8e38b86ab0 add some checks
Even if they duplicate lower-level ones, we have an opportunity for better
error messages. Any time I see a hard-to-debug error message, I should
be asking myself, "what higher-level primitive should catch and improve
this error?"
2021-04-19 10:47:30 -07:00
Kartik K. Agaram f5ece0451b start cleaning up pixel graphics
Filling pixels isn't a rare corner case. I'm going to switch to a dense
rather than sparse representation for pixels, but callers will have to
explicitly request the additional memory.
2021-04-19 10:47:30 -07:00
Kartik K. Agaram 5c5bca9df5 re-enable tests
Disabled in commit 1354161a3, and then I forgot about them for a while.
2021-04-18 23:26:38 -07:00
Kartik K. Agaram 53b56c67a9 Revert "allow drawing all pixels"
It causes us to run out of memory during tests.
2021-04-18 23:25:26 -07:00
Kartik K. Agaram ad46997f95 . 2021-04-18 23:10:01 -07:00
Kartik K. Agaram 2f10bc7302 fix a bug in loading code disk 2021-04-18 23:09:09 -07:00
Kartik K. Agaram 8c7aaa6b96 revert experiment: expand heap
There are several things in the codebase right now that don't seem sustainable.
I need to take them out and bring them back in more gradually.
2021-04-18 11:56:10 -07:00
Kartik K. Agaram 6e6e840e88 experiment: expand heap 2021-04-18 11:56:10 -07:00
Kartik K. Agaram d94821d301 some primitives for monitoring code integrity 2021-04-18 11:56:10 -07:00
Kartik K. Agaram d0804ac04b update the memory map 2021-04-18 09:06:20 -07:00
Kartik K. Agaram e5adb2239c . 2021-04-17 23:59:30 -07:00
Kartik K. Agaram 97df52bf2f shell: ctrl-r runs on real screen without a trace
We run out of memory fairly early in the course of drawing a chessboard
on the whole screen.
2021-04-17 23:52:52 -07:00
Kartik K. Agaram c11ea74442 . 2021-04-17 22:53:45 -07:00
Kartik K. Agaram 1c7799486d allow drawing all pixels
So far we aren't running out of memory. Might as well loosen our belts.
2021-04-17 22:37:29 -07:00
Kartik K. Agaram 8be6fe2485 bump up the token limit again
Current state of code in the Mu computer:
  (
    (globals . (
      (hline1 . (fn () (screen y lo hi color)
                  (if (>= lo hi)
                    ()
                    ((fn ()
                       (pixel screen lo y color)
                       (hline1 screen y (+ lo 1) hi color))))))
      (vline1 . (fn () (screen x lo hi color)
                  (if (>= lo hi)
                    ()
                    ((fn ()
                       (pixel screen x lo color)
                       (vline1 screen x (+ lo 1) hi color))))))
      (hline . (fn () (screen y color)
                 (hline1 screen y 0 (width screen) color)))
      (vline . (fn () (screen y color)
                 (vline1 screen y 0 (height screen) color)))
      (andf . (fn () (a b)
                (if a
                  (if b
                    1
                    ())
                  ())))
      (brline . (fn () (screen x0 y0 x1 y1 color)
                   ((fn (dx dy sx sy)
                      ((fn (err)
                         (brline1 screen x0 y0 x1 y1 dx dy sx sy err color))
                       (+ dx dy)))
                    (abs (- x1 x0))
                    (- 0 (abs (- y1 y0)))
                    (sgn (- x1 x0))
                    (sgn (- y1 y0)))))
      (brline1 . (fn () (screen x y xmax ymax dx dy sx sy err color)
                   (pixel screen x y color)
                   (if (andf (= x xmax) (= y ymax))
                     ()
                     ((fn (e2)
                        (brline1 screen
                          (if (>= e2 dy)
                            (+ x sx)
                            x)
                          (if (<= e2 dx)
                            (+ y sy)
                            y)
                          xmax
                          ymax
                          dx
                          dy
                          sx
                          sy
                          (+ err
                             (+
                               (if (>= e2 dy)
                                 dy
                                 0)
                               (if (<= e2 dx)
                                 dx
                                 0)))
                          color))
                      (* err 2)))))
      (read_line_2 . (fn () (keyboard stream)
                       ((fn (c)
                         (if (= c 10)
                           stream
                           (if (= c 0)
                             stream
                             (read_line_2 keyboard (write stream c)))))
                        (key keyboard))))
      (read_line . (fn () (keyboard)
                     (read_line_2 keyboard (stream))))
      (fill_rect . (fn () (screen x1 y1 x2 y2 fill_color)
                     (if (>= y1 y2)
                       ()
                       ((fn ()
                          (hline1 screen y1 x1 x2 fill_color)
                          (fill_rect screen x1 (+ y1 1) x2 y2 fill_color))))))
      (chessboard . (fn () (screen px)
                      (chessboard1 screen px 0 15)))
      (chessboard1 . (fn () (screen px y color)
                      (if (>= y (height screen))
                        ()
                        ((fn ()
                           (chessboard2 screen px y 0 color)
                           (chessboard1 screen px (+ y px) (- 15 color)))))))
      (chessboard2 . (fn () (screen px y x color)
                      (if (>= x (width screen))
                        ()
                        ((fn ()
                           (fill_rect screen x y (+ x px) (+ y px) color)
                           (chessboard2 screen px y (+ x px) (- 15 color)))))))
    ))
    (sandbox . (chessboard screen 8))
  )
2021-04-17 22:35:35 -07:00
Kartik K. Agaram c026dba006 shell: reenable the trace
We now have a couple of protections:
  - if we get close to running out of space in the trace we drop in an
    error
  - if we run out of space in the trace we stop trying to append
  - if there are errors we cancel future evaluations

This is already much nicer. You can't do much on the Mu computer, but at
least it gracefully gives up and shows its limitations. On my computer
the Mu shell tries to run computations for about 20s before giving up.
That seems at the outer limit of what interactivity supports. If things
take too long, test smaller chunks.
2021-04-17 22:33:28 -07:00
Kartik K. Agaram 60cab88ace evaluating fns is too similar to its input
When I edit disk images directly, it's easy to forget a pair of parens.
Then the first expression of the body never executes.
2021-04-17 20:58:36 -07:00
Kartik K. Agaram 568eb7328f write-multiple support
Is flush-ata-cache even needed? Reading the ATA 5 spec more closely, it
looks like it's only required by ATAPI devices! (Packet Interface is what
the 'PI' stands for!) And it's unclear if my driver actually supports ATAPI
at the moment.
2021-04-17 20:20:25 -07:00
Kartik K. Agaram 18e8ee4e16 start flushing the ATA disk cache
"Make sure to do a Cache Flush (ATA command 0xE7) after each write command
completes."
  https://wiki.osdev.org/index.php?title=ATA_PIO_Mode&oldid=25664#Writing_28_bit_LBA
2021-04-17 19:49:50 -07:00
Kartik K. Agaram 31a2c8aac6 starting write-multiple support 2021-04-17 19:45:41 -07:00
Kartik K. Agaram 1154db7a74 load sandbox even if there are no globals 2021-04-17 19:35:02 -07:00
Kartik K. Agaram 412ec38f30 heh, the current state actually overflows 2KB
It only works because the part that's truncated is cleanly the sandbox.

I need better error-checking in `read`.
2021-04-17 09:09:32 -07:00
Kartik K. Agaram 5908943f47 Bresenham line-drawing now working
I can't run tests right now, and the trace is disabled. Still, progress.

https://merveilles.town/@akkartik/106081486035689980

Current state of the disk image:
  (
    (globals . (
      (hline1 . (fn () (screen y lo hi)
                  (if (>= lo hi)
                    ()
                    ((fn ()
                       (pixel screen lo y 12)
                       (hline1 screen y (+ lo 1) hi))))))
      (vline1 . (fn () (screen x lo hi)
                  (if (>= lo hi)
                    ()
                    ((fn ()
                       (pixel screen x lo 12)
                       (vline1 screen x (+ lo 1) hi))))))
      (hline . (fn () (screen y)
                 (hline1 screen y 0 (width screen))))
      (vline . (fn () (screen y)
                 (vline1 screen y 0 (height screen))))
      (andf . (fn () (a b)
                (if a
                  (if b
                    1
                    ())
                  ())))
      (brline . (fn () (screen x0 y0 x1 y1)
                   ((fn (dx dy sx sy)
                      ((fn (err)
                         (brline1 screen x0 y0 x1 y1 dx dy sx sy err))
                       (+ dx dy)))
                    (abs (- x1 x0))
                    (- 0 (abs (- y1 y0)))
                    (sgn (- x1 x0))
                    (sgn (- y1 y0)))))
      (brline1 . (fn () (screen x y xmax ymax dx dy sx sy err)
                   (pixel screen x y 12)
                   (if (andf (= x xmax) (= y ymax))
                     ()
                     ((fn (e2)
                        (brline1 screen
                          (if (>= e2 dy)
                            (+ x sx)
                            x)
                          (if (<= e2 dx)
                            (+ y sy)
                            y)
                          xmax
                          ymax
                          dx
                          dy
                          sx
                          sy
                          (+ err
                             (+
                               (if (>= e2 dy)
                                 dy
                                 0)
                               (if (<= e2 dx)
                                 dx
                                 0)))))
                      (* err 2)))))
    ))
    (sandbox . (brline screen 1 1 5 5))
  )
2021-04-17 09:01:22 -07:00
Kartik K. Agaram 1354161a36 tmp: debugging why brline prints no pixels
Among other things, we turned off the trace to significantly speed up the
debug cycle.

State as of https://merveilles.town/@akkartik/106079258606146213

Ohhh, as I save the commit I notice a big problem: I've been editing the
disk image directly because writes to the Mu disk lose indentation. But
I've been forgetting that the state in the Mu disk needs to be pre-evaluated.
So function bindings need extra parens for the environment. The `pixel`
calls in the previous commit message are the first statement in the body,
and they aren't actually considered part of the body right now. No wonder
they don't run.

There are lots of other problems, but this will clarify a lot.
2021-04-17 08:34:48 -07:00
Kartik K. Agaram 1a74c3a1e6 loosening a few more buffers
Mu computer now has more code in it:

  (
    (globals . (
      (hline1 . (fn () (screen y lo hi) (if (>= lo hi) () ((fn () (pixel screen lo y 12) (hline1 screen y (+ lo 1) hi))))))
      (vline1 . (fn () (screen x lo hi) (if (>= lo hi) () ((fn () (pixel screen x lo 12) (vline1 screen x (+ lo 1) hi))))))
      (hline . (fn () (screen y) (hline1 screen y 0 (width screen))))
      (vline . (fn () (screen y) (vline1 screen y 0 (height screen))))
      (andf . (fn (a b)
                (if a
                  (if b
                    1
                    ())
                  ())))
      (brline . (fn (screen x0 y0 x1 y1)
                   ((fn (dx dy sx sy)
                      ((fn (err)
                         (brline1 screen x0 y0 x1 y1 dx dy sx sy err))
                       (+ dx dy)))
                    (abs (- x1 x0))
                    (- 0 (abs (- y1 y0)))
                    (sgn (- x1 x0))
                    (sgn (- y1 y0)))))
      (brline1 . (fn (screen x y xmax ymax dx dy sx sy err)
                   (pixel screen x y 12)
                   (if (andf (= x xmax) (= y ymax))
                     ()
                     ((fn (e2)
                        (brline1 screen
                          (if (>= e2 dy)
                            (+ x sx)
                            x)
                          (if (<= e2 dx)
                            (+ y sy)
                            y)
                          xmax
                          ymax
                          dx
                          dy
                          sx
                          sy
                          (+ err
                             (+
                               (if (>= e2 dy)
                                 dy
                                 0)
                               (if (<= e2 dx)
                                 dx
                                 0)))))
                      (* err 2)))))
    ))
    (sandbox . (brline screen 1 1 5 5))
  )
2021-04-17 08:29:43 -07:00
Kartik K. Agaram 6d9a1e6abc . 2021-04-17 08:23:55 -07:00
Kartik K. Agaram 33f5eb632a new primitives: abs, sgn 2021-04-16 20:40:02 -07:00
Kartik K. Agaram f774677854 . 2021-04-16 20:26:56 -07:00
Kartik K. Agaram f66de61392 handle drawing 16*4 = 64 pixels
Previously we'd only drawn 8*5 = 40 pixels.

Current contents of data.img:

  (
    (globals . (
      (hline . (fn () (screen y) (hline1 screen y 0 (width screen))))
      (hline1 . (fn () (screen y lo hi) (if (>= lo hi) () ((fn () (pixel screen lo y 12) (hline1 screen y (+ lo 1) hi))))))
      (vline1 . (fn () (screen x lo hi) (if (>= lo hi) () ((fn () (pixel screen x lo 12) (vline1 screen x (+ lo 1) hi))))))
    ))
    (sandbox . (vline1 screen 5 0 (height screen)))
  )
2021-04-16 20:26:56 -07:00
Kartik K. Agaram 21a6f5539b data.img now has more than one sector of data 2021-04-16 20:26:56 -07:00
Kartik K. Agaram cec0d9553b open question: animations in the fake screen
Right now we just render the state of the screen at the end of an evaluation.
2021-04-15 23:20:00 -07:00
Kartik K. Agaram 6aedf5dc59 . 2021-04-15 23:17:15 -07:00
Kartik K. Agaram 735636c7da . 2021-04-15 23:15:47 -07:00
Kartik K. Agaram c975f29a0c . 2021-04-15 23:12:46 -07:00
Kartik K. Agaram df9c71eff0 shell: horline working now
And we give a high-level error when the pixel buffer fills up.
2021-04-15 23:09:13 -07:00
Kartik K. Agaram 6392f1fde9 first session programming _within_ the Mu computer
I tried building a function to draw a horizontal line across the screen.
Here's what I have in data.txt:

  (
    (globals . (
      (horline . (fn () (screen y)
                    (horline_1 screen y 0 (width screen))))
      (horline_1 . (fn () (screen y lo hi)
                      (if (>= lo hi)
                        ()
                        ((fn ()
                          (pixel screen lo y 12)
                          (horline_1 screen y (+ lo 1) hi))))))
    ))
    (sandbox . (horline_1 screen 0 0 20))
  )

$ dd if=/dev/zero of=data.img count=20160
$ cat data.txt |dd of=data.img conv=notrunc
$ ./translate shell/*.mu  &&  qemu-system-i386 -hda disk.img -hdb data.img

Result: I can't call (horline screen 0) over a fake screen of width 40.
Some stream overflows somewhere after all the tweaks to various fixed-size
buffers scattered throughout the app. Calling horline_1 gets to a 'hi'
column of 20, but not to 30.
2021-04-15 22:56:59 -07:00
Kartik K. Agaram de993bc0cd shell: primitives for screen size 2021-04-15 22:00:03 -07:00
Kartik K. Agaram 5b20f177b6 shell: restore bindings after restart 2021-04-15 21:40:48 -07:00
Kartik K. Agaram 9d367ec2ed shell: start persisting global bindings 2021-04-15 21:05:55 -07:00