From 29523c7eb665c942897833fd68d609b0d5651a6d Mon Sep 17 00:00:00 2001 From: "Kartik K. Agaram" Date: Sat, 30 Oct 2021 01:15:23 -0700 Subject: [PATCH] done with first draft of tutorial --- tutorial/converter2.mu | 17 +----- tutorial/counter.png | Bin 0 -> 10757 bytes tutorial/index.md | 114 +++++++++++++++++++++++++++++++++++++++++ tutorial/task13.mu | 5 ++ tutorial/task15.mu | 19 +++++++ vocabulary.md | 6 +++ 6 files changed, 145 insertions(+), 16 deletions(-) create mode 100644 tutorial/counter.png create mode 100644 tutorial/task13.mu create mode 100644 tutorial/task15.mu diff --git a/tutorial/converter2.mu b/tutorial/converter2.mu index c5dde9f5..ae445239 100644 --- a/tutorial/converter2.mu +++ b/tutorial/converter2.mu @@ -10,21 +10,6 @@ # error checking for input without hard-aborting fn main screen: (addr screen), keyboard: (addr keyboard), data-disk: (addr disk) { - # imgui approach - forever { - number-input fahrenheit, cursor-in-fahrenheit? - number-input celsius, cursor-in-celsius? - if (menu-key 9/tab "Tab" "switch sides") { # requires non-blocking input - cursor-in-celsius? <- not - cursor-in-fahrenheit? <- not - } - if (menu-key 0xa/newline "Enter" "convert") { - if cursor-in-fahrenheit - celsius = fahrenheit-to-celsius fahrenheit - else - fahrenheit = celsius-to-fahrenheit celsius - } - } # celsius numeric representation var zero: float var celsius/xmm1: float <- fahrenheit-to-celsius zero @@ -47,7 +32,7 @@ fn main screen: (addr screen), keyboard: (addr keyboard), data-disk: (addr disk) # event loop { # render - render-state celsius-input, fahrenheit-input, cursor-in-celsius? + render-state screen, celsius-input, fahrenheit-input, cursor-in-celsius? render-menu-bar screen # process a single keystroke $main:input: { diff --git a/tutorial/counter.png b/tutorial/counter.png new file mode 100644 index 0000000000000000000000000000000000000000..fa06caa7aea02cba1420e330c044b71e3c15fa64 GIT binary patch literal 10757 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 X_!77J)w>O^!|l&HovA(Tck{mim=3BY literal 0 HcmV?d00001 diff --git a/tutorial/index.md b/tutorial/index.md index 1a595ed3..f8f3bed3 100644 --- a/tutorial/index.md +++ b/tutorial/index.md @@ -500,3 +500,117 @@ arguments together. This is a good time to skim [Mu's vocabulary of functions for pixel graphics](https://github.com/akkartik/mu/blob/main/vocabulary.md#pixel-graphics). They're fun to play with. + +## Task 13: reading input from keyboard + +Read the section on [events](https://github.com/akkartik/mu/blob/main/vocabulary.md#events) +from Mu's vocabulary. Write a program to read a key from the keyboard. Mu +receives a keyboard object as the second argument of `main`: + +``` +fn main screen: (addr screen), keyboard: (addr keyboard) { + # TODO: read a key from keyboard +} +``` + +The _signature_ of `read-key` -- along with many other functions -- is in +[400.mu](https://github.com/akkartik/mu/blob/main/400.mu). + +One wrinkle in this problem is that `read-key` may not actually return a key. +You have to keep retrying until it does. You may have already encountered the +list of `loop` operations in the section on [branches](https://github.com/akkartik/mu/blob/main/mu.md#branches). +It might be a good time to refresh your knowledge there. + +## Task 14: streams and scanning input from the keyboard + +Check out the idiomatic way for processing text from the keyboard: + +``` +fn main screen: (addr screen), keyboard: (addr keyboard) { + var in-storage: (stream byte 0x80) + var in/esi: (addr stream byte) <- address in-storage + read-line-from-keyboard keyboard, in, screen, 0xf/fg 0/bg + { + var done?/eax: boolean <- stream-empty? in + compare done?, 0/false + break-if-!= + var g/eax: grapheme <- read-grapheme in + loop + } +} +``` + +Can you modify this program to print out the text read from keyboard a second +time? How about printing a space after every character (grapheme)? + +Now skim the section in the Mu reference on [streams](https://github.com/akkartik/mu/blob/main/mu.md#streams). +Does the above program make sense? + +## Task 15: generating cool patterns + +Back to drawing to screen. Here's a program that draws every pixel on `screen` +with a `color` equal to the value of its `x` coordinate. + +``` +fn main screen: (addr screen) { + var y/eax: int <- copy 0 + { + compare y, 0x300/screen-height=768 + break-if->= + var x/edx: int <- copy 0 + { + compare x, 0x400/screen-width=1024 + break-if->= + var color/ecx: int <- copy x + color <- and 0xff + pixel screen x, y, color + x <- increment + loop + } + y <- increment + loop + } +} +``` + +Before you run it, form a hypothesis about what the picture will look like. +The screen is 1024 pixels wide, but there are only 256 colors. What are the +implications of these facts? + +After you run this program, try to modify it so every pixel gets a `color` +equal to the sum of its `x` and `y` coordinates. Can you guess what pattern +will result? Play around with more complex formulae. I particularly like the +sum of squares of `x` and `y` coordinates. Check out the [Mandelbrot set](https://github.com/akkartik/mu/blob/main/apps/mandelbrot-silhouette.mu) +for a really complex example of this sort of _procedural graphics_. + +## Task 16: a simple app + +We now know how to read keys from keyboard and draw on the screen. Look at +[tutorial/counter.mu](https://github.com/akkartik/mu/blob/main/tutorial/counter.mu) +which implements a simple counter app. + +screenshot of the counter app + +Do all the parts make sense? Read the extensive vocabulary of functions for +[drawing text to screen](https://github.com/akkartik/mu/blob/main/vocabulary.md#events). + +--- + +Here's a more challenging problem. Build an app to convert celsius to +fahrenheit and vice versa. Two text fields, the `` key to move the cursor +between them, type in either field and hit `` to populate the other +field. + +After you build it, compare your solution with [tutorial/converter.mu](https://github.com/akkartik/mu/blob/main/tutorial/converter.mu). +A second version breaks the program down into multiple functions, in +[tutorial/converter2.mu](https://github.com/akkartik/mu/blob/main/tutorial/converter.mu). +Can you see how the two do the same thing? Which one do you like better? + +--- + +There's lots more programs in this repository. Look in the `apps/` directory. +Check out the Mu `shell/`, which persists data between runs to a separate data +disk. Hopefully this gives you some sense for how little software it takes to +build useful programs for yourself. Do you have any new ideas for programs to +write in Mu? [Tell me about them!](http://akkartik.name/about) I'd love to jam +with you. diff --git a/tutorial/task13.mu b/tutorial/task13.mu new file mode 100644 index 00000000..9a4bc7f2 --- /dev/null +++ b/tutorial/task13.mu @@ -0,0 +1,5 @@ +fn main screen: (addr screen), keyboard: (addr keyboard) { + var in-storage: (stream byte 0x80) + var in/esi: (addr stream byte) <- address in-storage + read-line-from-keyboard keyboard, in, screen, 0xf/fg 0/bg +} diff --git a/tutorial/task15.mu b/tutorial/task15.mu new file mode 100644 index 00000000..a53c2454 --- /dev/null +++ b/tutorial/task15.mu @@ -0,0 +1,19 @@ +fn main screen: (addr screen) { + var y/eax: int <- copy 0 + { + compare y, 0x300/screen-height=768 + break-if->= + var x/edx: int <- copy 0 + { + compare x, 0x400/screen-width=1024 + break-if->= + var color/ecx: int <- copy x + color <- and 0xff + pixel screen x, y, color + x <- increment + loop + } + y <- increment + loop + } +} diff --git a/vocabulary.md b/vocabulary.md index f2be5f1e..c7d0bd46 100644 --- a/vocabulary.md +++ b/vocabulary.md @@ -243,6 +243,10 @@ Assertions for tests: `read-key` reads a single key from the keyboard and returns it if it exists. Returns 0 if no key has been pressed. +`read-line-from-keyboard` reads keys from keyboard, echoes them to screen +(with given fg/bg colors) and accumulates them in a stream until it encounters +a newline. + `read-mouse-event` returns a recent change in x and y coordinate. `timer-counter` returns a monotonically increasing counter with some @@ -251,6 +255,8 @@ but can't make assumptions about how much time has passed. Mu doesn't currently support interrupt-based events. +We also don't yet have a fake keyboard. + #### persistent storage `read-ata-disk` synchronously reads a whole number of _sectors_ from a _disk_