├── .gitignore ├── archive ├── 0.vm.arc │ ├── charterm │ │ ├── planet-docs │ │ │ └── doc │ │ │ │ └── scribble-style.css │ │ ├── main.rkt │ │ ├── doc.scrbl │ │ ├── test-charterm.rkt │ │ └── info.rkt │ ├── x.mu │ ├── vimrc.vim │ ├── exuberant-ctags-rc │ ├── fork.mu │ ├── Readme.md │ ├── callcc.mu │ ├── factorial.mu │ ├── mu │ ├── edit.mu │ ├── load.arc │ ├── graphics.mu │ ├── blocking.arc.t │ ├── generic.mu │ ├── highlights │ ├── tangle.mu │ ├── stdin.mu │ ├── edit.arc.t │ ├── counters.mu │ ├── buffered-stdin.mu │ └── scratch.vim ├── 1.vm │ ├── cleave │ │ └── Readme │ ├── termbox │ │ ├── Readme │ │ └── COPYING │ ├── example1.mu │ ├── x.mu │ ├── sandbox │ │ ├── tmux.conf │ │ ├── mu_run │ │ └── Readme.md │ ├── args.mu │ ├── mu │ ├── fork.mu │ ├── mutable.mu │ ├── git_log_filtered │ ├── immutable-error.mu │ ├── copy_mu │ ├── console.mu │ ├── new_lesson │ ├── snapshot_lesson │ ├── clean │ ├── build_and_test_until │ ├── exuberant_ctags_rc │ ├── 086scenario_console_test.mu │ ├── factorial.mu │ ├── real-files.mu │ ├── continuation1.mu │ ├── static-dispatch.mu │ ├── cannot_write_tests_for │ ├── display.mu │ ├── filesystem.mu │ ├── http-client.mu │ ├── continuation3.mu │ ├── tangle.mu │ ├── continuation2.mu │ ├── 058to_text.cc │ ├── counters.mu │ ├── screen.mu │ ├── http-server.mu │ ├── 067random.cc │ ├── 083scenario_screen_test.mu │ ├── channel.mu │ ├── continuation4.mu │ ├── continuation5.mu │ ├── 051scenario_test.mu │ ├── relayout │ ├── 059to_text.mu │ ├── build0 │ ├── 013update_operation.cc │ ├── vimrc.vim │ ├── 015literal_noninteger.cc │ └── edit │ │ └── Readme.md ├── 2.transect │ ├── Readme │ ├── factorial.k2 │ ├── ex3.k2 │ ├── ex6.k2 │ ├── ex5.k2 │ ├── compiler2 │ ├── ex4.k2 │ ├── ex8.k2 │ ├── compiler6 │ ├── compiler5 │ ├── compiler7 │ ├── ex7.k2 │ └── compiler8 └── Readme.md ├── linux ├── mu ├── hex ├── pack ├── assort ├── braces ├── calls ├── dquotes ├── sigils ├── tests ├── survey_elf ├── labels_baremetal ├── survey_baremetal ├── help ├── apps │ ├── raytracing │ │ ├── README.md │ │ ├── vimrc.vim │ │ ├── color.h │ │ ├── 1.cc │ │ ├── ray.h │ │ ├── 1.mu │ │ ├── ray.mu │ │ ├── 1.cc.0 │ │ └── color.mu │ ├── advent2020 │ │ └── vimrc.vim │ ├── hello.mu │ ├── ex1.mu │ ├── ex2.mu │ ├── ex2.subx │ ├── ex3.mu │ ├── ex1.subx │ ├── ex3.2.mu │ ├── ex4.subx │ ├── ex14.subx │ ├── ex13.subx │ ├── tui.mu │ ├── ex6.subx │ ├── print-file.mu │ ├── parse-int.mu │ ├── ex3.subx │ ├── texture.mu │ ├── factorial.mu │ ├── ex5.subx │ └── ex12.subx ├── tile │ ├── vimrc.vim │ └── README.md ├── browse │ ├── vimrc.vim │ └── README.md ├── bootstrap │ ├── bootstrap │ ├── clean │ ├── 031transforms.cc │ ├── test_layers │ ├── build_and_test_until │ ├── tools │ │ └── enumerate.cc │ ├── 021div.cc │ └── README.md ├── 200.txt ├── translate ├── translate_emulated ├── 401test.mu ├── translate_debug ├── 100.txt ├── 307size.subx ├── 315slice.subx ├── subx-params.subx ├── 407right-justify.mu ├── 314divide.subx ├── 408float.mu ├── 410file.mu ├── 308allocate-array.subx ├── branches.mu ├── 406int32.mu ├── 300.txt ├── translate_subx_emulated ├── mu-init-test.subx ├── translate_subx ├── 402time.mu └── translate_subx_debug ├── sib.pdf ├── misc_checks.subx ├── modrm.pdf ├── html ├── ex3.png ├── life.png ├── rpn5.png ├── ex2.mu.png ├── trace.png ├── control0.png ├── control1.png ├── encoding.png ├── 20210624-shell.png ├── archive │ └── 2.vm │ │ ├── edit.png │ │ ├── f2c-1.png │ │ ├── f2c-2.png │ │ ├── fork.png │ │ ├── tangle.png │ │ ├── example1.png │ │ ├── mutable.png │ │ ├── factorial.png │ │ ├── resources.png │ │ ├── fake-console.png │ │ ├── fake-keyboard.png │ │ ├── tracing-test.png │ │ ├── chessboard-test.png │ │ ├── expected-result.png │ │ ├── factorial-test.png │ │ ├── immutable-error.png │ │ ├── tmux-vim-sandbox.png │ │ ├── unexpected-result.png │ │ ├── f2c-1.mu │ │ ├── f2c-2.mu │ │ ├── resources.mu │ │ └── tracing-test.mu └── apps │ └── *.subx.html ├── cheatsheet.pdf ├── editor ├── README.md ├── VSCode │ ├── .vscodeignore │ ├── language-configuration.json │ ├── .vscode │ │ └── launch.json │ └── package.json ├── atom │ ├── README.md │ ├── package.json │ ├── styles │ │ └── styles.less │ └── grammars │ │ └── subx.json ├── mu.nanorc ├── mu.ctags ├── subx.nanorc ├── Mu.tmbundle │ └── info.plist ├── mu.dte ├── editor.md ├── subx.dte ├── subx.gedit ├── mulisp.vim └── subx.el ├── tutorial ├── task1.png ├── task2.png ├── task3.png ├── counter.png ├── task4-initial.png ├── task8c.mu ├── vimrc.vim ├── task2.mu ├── task6.mu ├── task8a.mu ├── task8b.mu ├── task12.mu ├── task4.mu ├── task1.mu ├── task4-solution.mu ├── task5.mu ├── task9.mu ├── task15.mu ├── task11.mu ├── task9-solution.mu ├── task12-solution.mu ├── task5-solution.mu ├── task7.mu ├── task7-solution.mu ├── task11-solution.mu ├── add2.mu ├── c2f.mu ├── converter.html ├── task6-error-runbook.txt └── counter.mu ├── help ├── tools ├── vga_palette.png ├── update_signatures ├── termbox │ ├── Readme │ └── COPYING ├── regs.mu ├── image-data ├── mu-init-minify.subx ├── browse_trace ├── create_container ├── expand_string_handle ├── test_treeshake_translate └── README.md ├── apps ├── vimrc.vim ├── ex1.mu ├── ex8.mu ├── ex4.mu ├── ex5.mu ├── ex2.mu ├── ex12.mu ├── ex3.mu ├── ex14.mu ├── ex13.mu ├── ex7.mu ├── ex10.mu ├── ex6.mu └── ex9.mu ├── shell ├── vimrc.vim ├── main.mu └── read.mu ├── browse-slack ├── vimrc.vim └── README.md ├── 319timer.subx ├── 312copy.subx ├── .gitattributes ├── 314divide.subx ├── 517random.mu ├── 318debug-counter.subx ├── 308allocate-array.subx ├── 503manhattan-line.mu ├── misc_checks ├── mu-init.subx ├── 506math.mu ├── 104test.subx ├── 408float.mu ├── 510disk.mu ├── 516read-line.mu └── 502test.mu /.gitignore: -------------------------------------------------------------------------------- 1 | a.* 2 | *.img 3 | labels 4 | -------------------------------------------------------------------------------- /archive/0.vm.arc/charterm/planet-docs/doc/scribble-style.css: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /linux/mu: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/akkartik/mu/HEAD/linux/mu -------------------------------------------------------------------------------- /sib.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/akkartik/mu/HEAD/sib.pdf -------------------------------------------------------------------------------- /linux/hex: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/akkartik/mu/HEAD/linux/hex -------------------------------------------------------------------------------- /linux/pack: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/akkartik/mu/HEAD/linux/pack -------------------------------------------------------------------------------- /misc_checks.subx: -------------------------------------------------------------------------------- 1 | == code 0x00000000 2 | 3 | == data 0x80000000 4 | -------------------------------------------------------------------------------- /modrm.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/akkartik/mu/HEAD/modrm.pdf -------------------------------------------------------------------------------- /html/ex3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/akkartik/mu/HEAD/html/ex3.png -------------------------------------------------------------------------------- /html/life.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/akkartik/mu/HEAD/html/life.png -------------------------------------------------------------------------------- /html/rpn5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/akkartik/mu/HEAD/html/rpn5.png -------------------------------------------------------------------------------- /linux/assort: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/akkartik/mu/HEAD/linux/assort -------------------------------------------------------------------------------- /linux/braces: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/akkartik/mu/HEAD/linux/braces -------------------------------------------------------------------------------- /linux/calls: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/akkartik/mu/HEAD/linux/calls -------------------------------------------------------------------------------- /linux/dquotes: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/akkartik/mu/HEAD/linux/dquotes -------------------------------------------------------------------------------- /linux/sigils: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/akkartik/mu/HEAD/linux/sigils -------------------------------------------------------------------------------- /linux/tests: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/akkartik/mu/HEAD/linux/tests -------------------------------------------------------------------------------- /cheatsheet.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/akkartik/mu/HEAD/cheatsheet.pdf -------------------------------------------------------------------------------- /editor/README.md: -------------------------------------------------------------------------------- 1 | Syntax highlighting configuration for various editors. 2 | -------------------------------------------------------------------------------- /html/ex2.mu.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/akkartik/mu/HEAD/html/ex2.mu.png -------------------------------------------------------------------------------- /html/trace.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/akkartik/mu/HEAD/html/trace.png -------------------------------------------------------------------------------- /html/control0.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/akkartik/mu/HEAD/html/control0.png -------------------------------------------------------------------------------- /html/control1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/akkartik/mu/HEAD/html/control1.png -------------------------------------------------------------------------------- /html/encoding.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/akkartik/mu/HEAD/html/encoding.png -------------------------------------------------------------------------------- /linux/survey_elf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/akkartik/mu/HEAD/linux/survey_elf -------------------------------------------------------------------------------- /tutorial/task1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/akkartik/mu/HEAD/tutorial/task1.png -------------------------------------------------------------------------------- /tutorial/task2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/akkartik/mu/HEAD/tutorial/task2.png -------------------------------------------------------------------------------- /tutorial/task3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/akkartik/mu/HEAD/tutorial/task3.png -------------------------------------------------------------------------------- /archive/1.vm/cleave/Readme: -------------------------------------------------------------------------------- 1 | Tool to construct compilation units out of Mu's layers. 2 | -------------------------------------------------------------------------------- /tutorial/counter.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/akkartik/mu/HEAD/tutorial/counter.png -------------------------------------------------------------------------------- /help: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # Some minimal online help. 3 | 4 | linux/bootstrap/bootstrap help $* 5 | -------------------------------------------------------------------------------- /html/20210624-shell.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/akkartik/mu/HEAD/html/20210624-shell.png -------------------------------------------------------------------------------- /linux/labels_baremetal: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/akkartik/mu/HEAD/linux/labels_baremetal -------------------------------------------------------------------------------- /linux/survey_baremetal: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/akkartik/mu/HEAD/linux/survey_baremetal -------------------------------------------------------------------------------- /tools/vga_palette.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/akkartik/mu/HEAD/tools/vga_palette.png -------------------------------------------------------------------------------- /html/archive/2.vm/edit.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/akkartik/mu/HEAD/html/archive/2.vm/edit.png -------------------------------------------------------------------------------- /html/archive/2.vm/f2c-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/akkartik/mu/HEAD/html/archive/2.vm/f2c-1.png -------------------------------------------------------------------------------- /html/archive/2.vm/f2c-2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/akkartik/mu/HEAD/html/archive/2.vm/f2c-2.png -------------------------------------------------------------------------------- /html/archive/2.vm/fork.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/akkartik/mu/HEAD/html/archive/2.vm/fork.png -------------------------------------------------------------------------------- /html/archive/2.vm/tangle.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/akkartik/mu/HEAD/html/archive/2.vm/tangle.png -------------------------------------------------------------------------------- /linux/help: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # Some minimal online help. 3 | 4 | linux/bootstrap/bootstrap help $* 5 | -------------------------------------------------------------------------------- /tutorial/task4-initial.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/akkartik/mu/HEAD/tutorial/task4-initial.png -------------------------------------------------------------------------------- /html/archive/2.vm/example1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/akkartik/mu/HEAD/html/archive/2.vm/example1.png -------------------------------------------------------------------------------- /html/archive/2.vm/mutable.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/akkartik/mu/HEAD/html/archive/2.vm/mutable.png -------------------------------------------------------------------------------- /apps/vimrc.vim: -------------------------------------------------------------------------------- 1 | " when opening files in this directory, load vimrc from cwd (top-level) 2 | source vimrc.vim 3 | -------------------------------------------------------------------------------- /editor/VSCode/.vscodeignore: -------------------------------------------------------------------------------- 1 | .vscode/** 2 | .vscode-test/** 3 | .gitignore 4 | vsc-extension-quickstart.md 5 | -------------------------------------------------------------------------------- /html/archive/2.vm/factorial.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/akkartik/mu/HEAD/html/archive/2.vm/factorial.png -------------------------------------------------------------------------------- /html/archive/2.vm/resources.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/akkartik/mu/HEAD/html/archive/2.vm/resources.png -------------------------------------------------------------------------------- /linux/apps/raytracing/README.md: -------------------------------------------------------------------------------- 1 | Exercises from https://raytracing.github.io/books/RayTracingInOneWeekend.html 2 | -------------------------------------------------------------------------------- /shell/vimrc.vim: -------------------------------------------------------------------------------- 1 | " when opening files in this directory, load vimrc from cwd (top-level) 2 | source vimrc.vim 3 | -------------------------------------------------------------------------------- /html/archive/2.vm/fake-console.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/akkartik/mu/HEAD/html/archive/2.vm/fake-console.png -------------------------------------------------------------------------------- /html/archive/2.vm/fake-keyboard.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/akkartik/mu/HEAD/html/archive/2.vm/fake-keyboard.png -------------------------------------------------------------------------------- /html/archive/2.vm/tracing-test.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/akkartik/mu/HEAD/html/archive/2.vm/tracing-test.png -------------------------------------------------------------------------------- /linux/tile/vimrc.vim: -------------------------------------------------------------------------------- 1 | " when opening files in this directory, load vimrc from cwd (top-level) 2 | source vimrc.vim 3 | -------------------------------------------------------------------------------- /tutorial/task8c.mu: -------------------------------------------------------------------------------- 1 | fn f -> _/eax: int { 2 | return 3 3 | } 4 | 5 | fn main { 6 | var x/ecx: int <- f 7 | } 8 | -------------------------------------------------------------------------------- /tutorial/vimrc.vim: -------------------------------------------------------------------------------- 1 | " when opening files in this directory, load vimrc from cwd (top-level) 2 | source vimrc.vim 3 | -------------------------------------------------------------------------------- /browse-slack/vimrc.vim: -------------------------------------------------------------------------------- 1 | " when opening files in this directory, load vimrc from cwd (top-level) 2 | source vimrc.vim 3 | -------------------------------------------------------------------------------- /html/archive/2.vm/chessboard-test.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/akkartik/mu/HEAD/html/archive/2.vm/chessboard-test.png -------------------------------------------------------------------------------- /html/archive/2.vm/expected-result.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/akkartik/mu/HEAD/html/archive/2.vm/expected-result.png -------------------------------------------------------------------------------- /html/archive/2.vm/factorial-test.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/akkartik/mu/HEAD/html/archive/2.vm/factorial-test.png -------------------------------------------------------------------------------- /html/archive/2.vm/immutable-error.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/akkartik/mu/HEAD/html/archive/2.vm/immutable-error.png -------------------------------------------------------------------------------- /html/archive/2.vm/tmux-vim-sandbox.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/akkartik/mu/HEAD/html/archive/2.vm/tmux-vim-sandbox.png -------------------------------------------------------------------------------- /linux/browse/vimrc.vim: -------------------------------------------------------------------------------- 1 | " when opening files in this directory, load vimrc from cwd (top-level) 2 | source vimrc.vim 3 | -------------------------------------------------------------------------------- /html/archive/2.vm/unexpected-result.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/akkartik/mu/HEAD/html/archive/2.vm/unexpected-result.png -------------------------------------------------------------------------------- /linux/apps/advent2020/vimrc.vim: -------------------------------------------------------------------------------- 1 | " when opening files in this directory, load vimrc from cwd (top-level) 2 | source vimrc.vim 3 | -------------------------------------------------------------------------------- /linux/apps/raytracing/vimrc.vim: -------------------------------------------------------------------------------- 1 | " when opening files in this directory, load vimrc from cwd (top-level) 2 | source vimrc.vim 3 | -------------------------------------------------------------------------------- /tutorial/task2.mu: -------------------------------------------------------------------------------- 1 | fn test-1 { 2 | check-ints-equal 1, 2, "F - test-1" 3 | } 4 | 5 | fn main { 6 | # do nothing 7 | } 8 | -------------------------------------------------------------------------------- /archive/0.vm.arc/charterm/main.rkt: -------------------------------------------------------------------------------- 1 | #lang racket/base 2 | (require "charterm.rkt") 3 | (provide (all-from-out "charterm.rkt")) 4 | -------------------------------------------------------------------------------- /tools/update_signatures: -------------------------------------------------------------------------------- 1 | grep -h '^sig \|^fn ' [0-9]*.mu |grep -v 'fn test-' |sed 's/^fn /sig /' |sed 's/ {$//' > signatures.mu 2 | -------------------------------------------------------------------------------- /tutorial/task6.mu: -------------------------------------------------------------------------------- 1 | fn main { 2 | var m: int 3 | var r/edx: int <- copy 0 4 | # insert a single statement below 5 | 6 | } 7 | -------------------------------------------------------------------------------- /editor/atom/README.md: -------------------------------------------------------------------------------- 1 | ## Syntax highlighting for the Atom editor 2 | 3 | Copy or symlink this directory into `~/.atom/packages/subx`. 4 | -------------------------------------------------------------------------------- /tools/termbox/Readme: -------------------------------------------------------------------------------- 1 | Fork of https://github.com/nsf/termbox as of 2015-06-05 2 | git hash 252bef01264a2aeef22ebe5bae0b5893a58947f3 3 | -------------------------------------------------------------------------------- /archive/1.vm/termbox/Readme: -------------------------------------------------------------------------------- 1 | Fork of https://github.com/nsf/termbox as of 2015-06-05 2 | git hash 252bef01264a2aeef22ebe5bae0b5893a58947f3 3 | -------------------------------------------------------------------------------- /tutorial/task8a.mu: -------------------------------------------------------------------------------- 1 | fn f a: int { 2 | } 3 | 4 | fn main { 5 | f 0 6 | var r/eax: int <- copy 3 7 | f r 8 | var m: int 9 | f m 10 | } 11 | -------------------------------------------------------------------------------- /tutorial/task8b.mu: -------------------------------------------------------------------------------- 1 | fn f -> _/eax: int { 2 | var result/ecx: int <- copy 0 3 | return result 4 | } 5 | 6 | fn main { 7 | var x/eax: int <- f 8 | } 9 | -------------------------------------------------------------------------------- /linux/bootstrap/bootstrap: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # Run SubX VM, first compiling if necessary. 3 | set -e 4 | 5 | $(dirname $0)/build 6 | 7 | $(dirname $0)/bootstrap_bin "$@" 8 | -------------------------------------------------------------------------------- /archive/1.vm/example1.mu: -------------------------------------------------------------------------------- 1 | def main [ 2 | local-scope 3 | a:num <- add 2, 2 4 | a <- multiply a, 3 5 | # uncomment the next line to see the output 6 | # $print a 7 | ] 8 | -------------------------------------------------------------------------------- /archive/1.vm/x.mu: -------------------------------------------------------------------------------- 1 | # example program: add two numbers 2 | 3 | def main [ 4 | 11:num <- copy 1 5 | 12:num <- copy 3 6 | 13:num <- add 11:num, 12:num 7 | $dump-memory 8 | ] 9 | -------------------------------------------------------------------------------- /archive/0.vm.arc/x.mu: -------------------------------------------------------------------------------- 1 | (function main [ 2 | (x:integer <- copy 1:literal) 3 | (y:integer <- copy 3:literal) 4 | (z:integer <- add x:integer y:integer) 5 | ($dump-memory) 6 | ]) 7 | -------------------------------------------------------------------------------- /linux/bootstrap/clean: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | set -e 3 | 4 | set -v 5 | rm -rf bootstrap.cc bootstrap_bin* *_list 6 | rm -rf .until 7 | rm -rf tools/enumerate tools/tangle tools/*_list tools/*.dSYM 8 | -------------------------------------------------------------------------------- /linux/200.txt: -------------------------------------------------------------------------------- 1 | Layers in the 2xx series are in bare SubX, without any syntax sugar. They are 2 | intended to be used by various syntax-sugar phases: 3 | sigils.subx 4 | calls.subx 5 | braces.subx 6 | -------------------------------------------------------------------------------- /archive/1.vm/sandbox/tmux.conf: -------------------------------------------------------------------------------- 1 | # Hotkey for running Mu over tmux 2 | # Assumes exactly two panes, with vim running on the left side and `./mu sandbox` running on the right side. 3 | bind-key -n F4 run mu_run 4 | -------------------------------------------------------------------------------- /linux/translate: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # Translate a given Mu program into an ELF binary on Linux. 3 | 4 | set -e 5 | 6 | cat $* [0-9]*.mu |./mu > a.subx 7 | 8 | ./translate_subx [0-9]*.subx mu-init.subx a.subx 9 | -------------------------------------------------------------------------------- /archive/1.vm/args.mu: -------------------------------------------------------------------------------- 1 | # To provide commandline args to a Mu program, use '--'. In this case: 2 | # $ ./mu args.mu -- abc 3 | # abc 4 | def main text:text [ 5 | local-scope 6 | load-inputs 7 | $print text 10/newline 8 | ] 9 | -------------------------------------------------------------------------------- /editor/VSCode/language-configuration.json: -------------------------------------------------------------------------------- 1 | { 2 | "comments": { 3 | "lineComment": "#" 4 | }, 5 | "brackets": [ 6 | ["{", "}"], 7 | ["[", "]"], 8 | ["(", ")"] 9 | ] 10 | } 11 | -------------------------------------------------------------------------------- /html/archive/2.vm/f2c-1.mu: -------------------------------------------------------------------------------- 1 | # c = (f-32) * 5/9 2 | def fahrenheit-to-celsius f:number -> c:number [ 3 | local-scope 4 | load-ingredients 5 | tmp:number <- subtract f, 32 6 | tmp <- multiply tmp, 5 7 | c <- divide tmp, 9 8 | ] 9 | -------------------------------------------------------------------------------- /linux/apps/hello.mu: -------------------------------------------------------------------------------- 1 | # Meaningless conventional example. 2 | # 3 | # To run: 4 | # $ ./translate apps/hello.mu 5 | # $ ./a.elf 6 | 7 | fn main -> _/ebx: int { 8 | print-string 0/screen, "Hello world!\n" 9 | return 0 10 | } 11 | -------------------------------------------------------------------------------- /archive/1.vm/mu: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # Run interpreter, first compiling if necessary. 3 | set -e 4 | 5 | ./build3 && ./mu_bin "$@" 6 | 7 | # Scenarios considered: 8 | # ./mu 9 | # ./mu --help 10 | # ./mu test 11 | # ./mu test file1.mu 12 | -------------------------------------------------------------------------------- /editor/mu.nanorc: -------------------------------------------------------------------------------- 1 | # include this file in your ~/.nanorc 2 | 3 | syntax "mu" "\.mu$" 4 | # tests 5 | color green "\ x:&:num [ 10 | local-scope 11 | load-inputs 12 | *x <- copy 34 13 | ] 14 | -------------------------------------------------------------------------------- /html/archive/2.vm/f2c-2.mu: -------------------------------------------------------------------------------- 1 | # c = (f-32) * 5/9 2 | def fahrenheit-to-celsius [ 3 | local-scope 4 | f:number <- next-ingredient 5 | tmp:number <- subtract f, 32 6 | tmp <- multiply tmp, 5 7 | c:number <- divide tmp, 9 8 | return c 9 | ] 10 | -------------------------------------------------------------------------------- /tools/regs.mu: -------------------------------------------------------------------------------- 1 | type bar { 2 | x: int 3 | y: boolean 4 | } 5 | 6 | fn foo { 7 | var a/eax: int <- copy 0 8 | var a/ecx: int <- copy 0 9 | var a/edx: int <- copy 0 10 | var a/ebx: int <- copy 0 11 | var a/esi: int <- copy 0 12 | var a/edi: int <- copy 0 13 | } 14 | -------------------------------------------------------------------------------- /linux/translate_emulated: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # Translate a Mu program using emulated mode on Linux or BSD or Mac. 3 | 4 | set -e 5 | set -v 6 | 7 | cat $* [0-9]*.mu |bootstrap/bootstrap run ./mu > a.subx 8 | 9 | ./translate_subx_emulated [0-9]*.subx mu-init.subx a.subx 10 | -------------------------------------------------------------------------------- /319timer.subx: -------------------------------------------------------------------------------- 1 | == code 2 | 3 | timer-counter: # -> _/eax: int 4 | # . prologue 5 | 55/push-ebp 6 | 89/<- %ebp 4/r32/esp 7 | # 8 | 8b/-> *Timer-counter 0/r32/eax 9 | $timer-counter:end: 10 | # . epilogue 11 | 89/<- %esp 5/r32/ebp 12 | 5d/pop-to-ebp 13 | c3/return 14 | -------------------------------------------------------------------------------- /archive/1.vm/git_log_filtered: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # Show the log while skipping unimportant directories. 3 | # 4 | # I usually run this through an alias local to this repo: 5 | # $ git config alias.ll '!./git_log_filtered' 6 | # $ git ll --stat 7 | set -e 8 | 9 | git log $* -- . ":(exclude)html" 10 | -------------------------------------------------------------------------------- /archive/1.vm/immutable-error.mu: -------------------------------------------------------------------------------- 1 | # compare mutable.mu 2 | 3 | def main [ 4 | local-scope 5 | x:&:num <- new number:type 6 | foo x 7 | ] 8 | 9 | def foo x:&:num [ 10 | local-scope 11 | load-inputs 12 | *x <- copy 34 # will cause an error because x is immutable in this function 13 | ] 14 | -------------------------------------------------------------------------------- /archive/0.vm.arc/vimrc.vim: -------------------------------------------------------------------------------- 1 | syntax sync minlines=999 2 | 3 | function! HighlightMuInArc() 4 | set ft=mu 5 | syntax keyword muHack begin | highlight link muHack CommentedCode 6 | syntax match muHack "[()]" | highlight link muHack CommentedCode 7 | endfunction 8 | autocmd BufRead,BufNewFile *.mu call HighlightMuInArc() 9 | -------------------------------------------------------------------------------- /archive/2.transect/Readme: -------------------------------------------------------------------------------- 1 | Abortive series of attempts at building a bootstrappable low-level language. 2 | Type-checked, but feasible to implement in some sort of notation for machine 3 | code (like SubX). 4 | 5 | The latest version is in compiler10. But it doesn't account for checking 6 | how programs allocate registers. 7 | -------------------------------------------------------------------------------- /html/archive/2.vm/resources.mu: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | assume-resources [ 6 | # contents for a local file 7 | [/foo/bar] <- [ 8 | |def| # lines delimited by '|' 9 | ] 10 | 11 | # contents for a URL 12 | [example.com/foo/bar] <- [ 13 | |abc| 14 | ] 15 | ] 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /html/archive/2.vm/tracing-test.mu: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | run [ 5 | result:boolean <- equal [abc], [abcd] # lengths differ 6 | ] 7 | trace-should-contain [ 8 | equal: comparing lengths 9 | ] 10 | trace-should-not-contain [ 11 | equal: comparing characters 12 | ] 13 | 14 | 15 | 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /linux/401test.mu: -------------------------------------------------------------------------------- 1 | # Some helpers for Mu tests. 2 | 3 | fn check val: boolean, msg: (addr array byte) { 4 | var tmp/eax: int <- copy val 5 | check-ints-equal tmp, 1, msg 6 | } 7 | 8 | fn check-not val: boolean, msg: (addr array byte) { 9 | var tmp/eax: int <- copy val 10 | check-ints-equal tmp, 0, msg 11 | } 12 | -------------------------------------------------------------------------------- /archive/0.vm.arc/charterm/doc.scrbl: -------------------------------------------------------------------------------- 1 | #lang scribble/manual 2 | @; THIS-FILE-WAS-GENERATED-BY-MCFLY-TOOLS (planet neil/mcfly-tools:1:=12) 3 | @(require (for-syntax racket/base) 4 | (for-template racket/base) 5 | (planet neil/mcfly:1:3/mcfly-scribble) 6 | (planet neil/mcfly:1:3/mcfly-expand)) 7 | @(mcfly-expand "charterm.rkt") 8 | -------------------------------------------------------------------------------- /archive/0.vm.arc/exuberant-ctags-rc: -------------------------------------------------------------------------------- 1 | --langdef=mu 2 | --langmap=mu:.mu 3 | --regex-mu=/^\(function[ \t]+([^ \t\[]+)/\1/d,definition/ 4 | --regex-mu=/^\(recipe[ \t]+([^ \t\[]+)/\1/d,definition/ 5 | --regex-mu=/^\(and-record[ \t]+([^ \t\[]+)/\1/t,type/ 6 | --regex-mu=/^\(address[ \t]+([^ \t\[]+)/\1/t,type/ 7 | --regex-mu=/^\(array[ \t]+([^ \t\[]+)/\1/t,type/ 8 | -------------------------------------------------------------------------------- /312copy.subx: -------------------------------------------------------------------------------- 1 | == code 2 | 3 | copy-array-object: # src: (addr array T), dest-ah: (addr handle array T) 4 | # . prologue 5 | 55/push-ebp 6 | 89/<- %ebp 4/r32/esp 7 | # 8 | (copy-array Heap *(ebp+8) *(ebp+0xc)) 9 | $copy-array-object:end: 10 | # . epilogue 11 | 89/<- %esp 5/r32/ebp 12 | 5d/pop-to-ebp 13 | c3/return 14 | -------------------------------------------------------------------------------- /apps/ex1.mu: -------------------------------------------------------------------------------- 1 | # The simplest possible bare-metal program. 2 | # 3 | # To build a disk image: 4 | # ./translate apps/ex1.mu # emits code.img 5 | # To run: 6 | # qemu-system-i386 code.img 7 | # 8 | # Expected output: blank screen with no errors 9 | 10 | fn main screen: (addr screen), keyboard: (addr keyboard), data-disk: (addr disk) { 11 | } 12 | -------------------------------------------------------------------------------- /linux/translate_debug: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # Translate given Mu files with debug information on Linux. 3 | # 4 | # (You _could_ do something similar on other platforms using emulation. But I 5 | # often find that to be too slow.) 6 | 7 | set -e 8 | 9 | cat $* [0-9]*.mu |./mu > a.subx 10 | 11 | ./translate_subx_debug [0-9]*.subx mu-init.subx a.subx 12 | -------------------------------------------------------------------------------- /tutorial/task12.mu: -------------------------------------------------------------------------------- 1 | fn main screen: (addr screen) { 2 | draw-line screen, 0x100/x1 0x100/y1, 0x300/x2 0x100/y2, 3/color=green 3 | draw-line screen, 0x100/x1 0x200/y1, 0x300/x2 0x200/y2, 3/color=green 4 | draw-line screen, 0x100/x1 0x100/y1, 0x100/x2 0x200/y2, 3/color=green 5 | draw-line screen, 0x300/x1 0x100/y1, 0x300/x2 0x200/y2, 3/color=green 6 | } 7 | -------------------------------------------------------------------------------- /tutorial/task4.mu: -------------------------------------------------------------------------------- 1 | fn the-answer -> _/eax: int { 2 | var result/eax: int <- copy 0 3 | # insert your statement below { 4 | 5 | # } 6 | return result 7 | } 8 | 9 | fn test-the-answer { 10 | var result/eax: int <- the-answer 11 | check-ints-equal result, 0x2a, "F - the-answer should return 42, but didn't" 12 | } 13 | 14 | fn main { 15 | } 16 | -------------------------------------------------------------------------------- /linux/100.txt: -------------------------------------------------------------------------------- 1 | We're now past C++ bootstrap. 2 | 3 | Layers in the 1xx series are in bare SubX, without any syntax sugar. They are 4 | intended to be used by the phases of the self-hosted translator to replicate 5 | the functionality of the C++ bootstrap: 6 | hex.subx 7 | survey_elf.subx 8 | pack.subx 9 | dquotes.subx 10 | assort.subx 11 | tests.subx 12 | -------------------------------------------------------------------------------- /tutorial/task1.mu: -------------------------------------------------------------------------------- 1 | # Draw a single line of ASCII text. 2 | # 3 | # To build a disk image: 4 | # ./translate tutorial/task1.mu # emits code.img 5 | # To run: 6 | # qemu-system-i386 code.img 7 | 8 | fn main screen: (addr screen) { 9 | var dummy/eax: int <- draw-text-rightward screen, "hello from baremetal Mu!", 0x10/x, 0x400/xmax, 0x10/y, 0xa/fg, 0/bg 10 | } 11 | -------------------------------------------------------------------------------- /linux/bootstrap/031transforms.cc: -------------------------------------------------------------------------------- 1 | :(before "End Types") 2 | typedef void (*transform_fn)(program&); 3 | :(before "End Globals") 4 | vector Transform; 5 | 6 | :(before "End transform(program& p)") 7 | for (int t = 0; t < SIZE(Transform); ++t) 8 | (*Transform.at(t))(p); 9 | 10 | :(before "End One-time Setup") 11 | // Begin Transforms 12 | // End Transforms 13 | -------------------------------------------------------------------------------- /tutorial/task4-solution.mu: -------------------------------------------------------------------------------- 1 | fn the-answer -> _/eax: int { 2 | var result/eax: int <- copy 0 3 | # insert your statement below { 4 | result <- copy 0x2a 5 | # } 6 | return result 7 | } 8 | 9 | fn test-the-answer { 10 | var result/eax: int <- the-answer 11 | check-ints-equal result, 0x2a, "F - the-answer should return 42, but didn't." 12 | } 13 | 14 | fn main { 15 | } 16 | -------------------------------------------------------------------------------- /tools/image-data: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # Create a disk image containing some (text) data. 3 | 4 | if [ $# -eq 0 ] 5 | then 6 | echo "Fill disk of some capacity (in ~1 MB units) from stdin" 7 | echo "usage: image-data capacity" 8 | exit 1 9 | fi 10 | 11 | dd if=/dev/zero of=data.img count=$(($1*2016)) # 32 tracks * 63 sectors/track of 512-byte sectors 12 | dd of=data.img conv=notrunc 13 | -------------------------------------------------------------------------------- /linux/307size.subx: -------------------------------------------------------------------------------- 1 | # Size of an array in bytes. 2 | 3 | == code 4 | 5 | size: # in: (addr array _) -> result/eax: int 6 | # . prologue 7 | 55/push-ebp 8 | 89/<- %ebp 4/r32/esp 9 | # eax = in 10 | 8b/-> *(ebp+8) 0/r32/eax 11 | # 12 | 8b/-> *eax 0/r32/eax 13 | $size:end: 14 | # . epilogue 15 | 89/<- %esp 5/r32/ebp 16 | 5d/pop-to-ebp 17 | c3/return 18 | -------------------------------------------------------------------------------- /apps/ex8.mu: -------------------------------------------------------------------------------- 1 | # Demo of floating-point support. 2 | # 3 | # To build a disk image: 4 | # ./translate apps/ex8.mu # emits code.img 5 | # To run: 6 | # qemu-system-i386 code.img 7 | # You shouldn't see any exceptions. 8 | 9 | fn main screen: (addr screen), keyboard: (addr keyboard), data-disk: (addr disk) { 10 | var n/eax: int <- copy 0 11 | var result/xmm0: float <- convert n 12 | } 13 | -------------------------------------------------------------------------------- /archive/1.vm/copy_mu: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env zsh 2 | # Copy binaries across mu directories for different students on a single 3 | # server, so we only need to build them once. 4 | 5 | cp -r $1/enumerate/enumerate $2/enumerate 6 | cp -r $1/cleave/cleave $2/cleave 7 | rm -rf $2/.build 8 | cp -r $1/.build $2 9 | cp -r $1/mu_bin $2 10 | cd $2 11 | ./mu # couple of things still get recompiled, but should now be quick 12 | -------------------------------------------------------------------------------- /linux/apps/ex1.mu: -------------------------------------------------------------------------------- 1 | # First example: return the answer to the Ultimate Question of Life, the 2 | # Universe, and Everything. 3 | # 4 | # Same as https://www.muppetlabs.com/~breadbox/software/tiny/teensy.html 5 | # 6 | # To run: 7 | # $ ./translate apps/ex1.mu 8 | # $ ./a.elf 9 | # Expected result: 10 | # $ echo $? 11 | # 42 12 | 13 | fn main -> _/ebx: int { 14 | return 0x2a # Mu requires hexadecimal 15 | } 16 | -------------------------------------------------------------------------------- /tutorial/task5.mu: -------------------------------------------------------------------------------- 1 | fn foo -> _/eax: int { 2 | var x: int 3 | # statement 1: store 3 in x 4 | # statement 2: define a new variable 'y' in register eax and store 4 in it 5 | # statement 3: add y to x, storing the result in x 6 | return x 7 | } 8 | 9 | fn test-foo { 10 | var result/eax: int <- foo 11 | check-ints-equal result, 7, "F - foo should return 7, but didn't" 12 | } 13 | 14 | fn main { 15 | } 16 | -------------------------------------------------------------------------------- /tutorial/task9.mu: -------------------------------------------------------------------------------- 1 | fn f -> _/eax: int { 2 | return 2 3 | } 4 | 5 | fn g -> _/eax: int { 6 | return 3 7 | } 8 | 9 | fn add-f-and-g -> _/eax: int { 10 | var x/eax: int <- f 11 | var y/eax: int <- g 12 | x <- add y 13 | return x 14 | } 15 | 16 | fn test-add-f-and-g { 17 | var result/eax: int <- add-f-and-g 18 | check-ints-equal result, 5, "F - test-add-f-and-g\n" 19 | } 20 | 21 | fn main { 22 | } 23 | -------------------------------------------------------------------------------- /editor/subx.nanorc: -------------------------------------------------------------------------------- 1 | # include this file in your ~/.nanorc 2 | 3 | syntax "subx" "\.subx$" 4 | # function definitions 5 | color yellow "^[a-z][^ ]*:" 6 | # global variables 7 | color red "^[A-Z][^ ]*:" 8 | # tests 9 | color green "^test-[^ ]*:" 10 | # strings literals 11 | color cyan ""([^"\]|\\.)+"" 12 | # comments 13 | comment "#" 14 | color brightblue "# - .*" 15 | color blue "#.*$" 16 | color brightblack "# \. .*" 17 | -------------------------------------------------------------------------------- /archive/1.vm/console.mu: -------------------------------------------------------------------------------- 1 | # example program: reading events from keyboard or mouse 2 | # 3 | # Keeps printing 'a' until you press a key or click on the mouse. 4 | 5 | def main [ 6 | local-scope 7 | open-console 8 | { 9 | e:event, found?:bool <- check-for-interaction 10 | break-if found? 11 | print-character-to-display 97, 7/white 12 | loop 13 | } 14 | close-console 15 | $print e, 10/newline 16 | ] 17 | -------------------------------------------------------------------------------- /archive/1.vm/new_lesson: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # Run this before running './mu edit' or './mu sandbox' to make sure you don't 3 | # lose any work. 4 | # 5 | # You'll be editing code in lesson/recipes.mu, and any sandboxes you create 6 | # will be in lesson/0, lesson/1, etc., from top to bottom. 7 | 8 | set -e 9 | 10 | mkdir lesson 11 | cd lesson 12 | git init 13 | echo '**/.*.swp' > .gitignore 14 | git add . 15 | git commit -m 0 16 | -------------------------------------------------------------------------------- /linux/apps/ex2.mu: -------------------------------------------------------------------------------- 1 | # Add 3 and 4, and return the result in the exit code. 2 | # 3 | # To run: 4 | # $ ./translate apps/ex2.mu 5 | # $ ./a.elf 6 | # Expected result: 7 | # $ echo $? 8 | # 7 9 | 10 | fn main -> _/ebx: int { 11 | var result/eax: int <- do-add 3 4 12 | return result 13 | } 14 | 15 | fn do-add a: int, b: int -> _/eax: int { 16 | var result/ecx: int <- copy a 17 | result <- add b 18 | return result 19 | } 20 | -------------------------------------------------------------------------------- /archive/1.vm/snapshot_lesson: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # Hacky little helper called from edit/ and sandbox/ apps to save a snapshot 3 | # of lesson/ using git. 4 | set -e 5 | 6 | test -d lesson/.git || exit 0 # give up if it's not a git repo 7 | 8 | cd lesson 9 | # explicitly say '--all' for git 1.9 10 | git add --all . 11 | # bug in git: git diff -q messes up --exit-code 12 | git diff HEAD --exit-code >/dev/null || git commit -a -m . >/dev/null 13 | -------------------------------------------------------------------------------- /linux/315slice.subx: -------------------------------------------------------------------------------- 1 | == code 2 | 3 | # variant of slice-to-string intended to be called from Mu 4 | # Mu doesn't yet expose allocation-descriptors 5 | _slice-to-string: # in: (addr slice), out: (addr handle array byte) 6 | # . prologue 7 | 55/push-ebp 8 | 89/<- %ebp 4/r32/esp 9 | # 10 | (slice-to-string Heap *(ebp+8) *(ebp+0xc)) 11 | # . epilogue 12 | 89/<- %esp 5/r32/ebp 13 | 5d/pop-to-ebp 14 | c3/return 15 | -------------------------------------------------------------------------------- /tutorial/task15.mu: -------------------------------------------------------------------------------- 1 | fn main screen: (addr screen) { 2 | var y/eax: int <- copy 0 3 | { 4 | compare y, 0x300/screen-height=768 5 | break-if->= 6 | var x/edx: int <- copy 0 7 | { 8 | compare x, 0x400/screen-width=1024 9 | break-if->= 10 | var color/ecx: int <- copy x 11 | pixel screen x, y, color 12 | x <- increment 13 | loop 14 | } 15 | y <- increment 16 | loop 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /archive/1.vm/clean: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | set -e 3 | 4 | set -v 5 | rm -rf mu.cc core.mu mu_bin* *_list .build 6 | rm -rf termbox/*.o termbox/libtermbox.a 7 | rm -rf .until .quit 8 | test $# -gt 0 && exit 0 # convenience: 'clean top-level' to leave subsidiary tools alone 9 | rm -rf ../../linux/bootstrap/tools/enumerate ../../linux/bootstrap/tools/tangle ../../linux/bootstrap/tools/*_list cleave/cleave cleave/cleave.dSYM ../../linux/bootstrap/tools/*.dSYM 10 | -------------------------------------------------------------------------------- /tutorial/task11.mu: -------------------------------------------------------------------------------- 1 | fn difference a: int, b: int -> _/eax: int { 2 | } 3 | 4 | fn test-difference { 5 | var result/eax: int <- difference 5, 3 6 | check-ints-equal result, 2, "F - difference works" 7 | result <- difference 3, 5 8 | check-ints-equal result, 2, "F - difference is always positive" 9 | result <- difference 6, 6 10 | check-ints-equal result, 0, "F - difference can be 0" 11 | } 12 | 13 | fn main screen: (addr screen) { 14 | } 15 | -------------------------------------------------------------------------------- /tutorial/task9-solution.mu: -------------------------------------------------------------------------------- 1 | fn f -> _/eax: int { 2 | return 2 3 | } 4 | 5 | fn g -> _/eax: int { 6 | return 3 7 | } 8 | 9 | fn add-f-and-g -> _/eax: int { 10 | var _x/eax: int <- f 11 | var x/ecx: int <- copy _x 12 | var y/eax: int <- g 13 | x <- add y 14 | return x 15 | } 16 | 17 | fn test-add-f-and-g { 18 | var result/eax: int <- add-f-and-g 19 | check-ints-equal result, 5, "F - test-add-f-and-g\n" 20 | } 21 | 22 | fn main { 23 | } 24 | -------------------------------------------------------------------------------- /linux/apps/ex2.subx: -------------------------------------------------------------------------------- 1 | # Add 3 and 4, and return the result in the exit code. 2 | # 3 | # To run: 4 | # $ ./translate_subx 000init.subx apps/ex2.subx 5 | # $ ./a.elf 6 | # Expected result: 7 | # $ echo $? 8 | # 7 9 | 10 | == code 11 | 12 | Entry: 13 | # ebx = 3 14 | bb/copy-to-ebx 3/imm32 15 | # add 4 to ebx 16 | 81 0/subop/add 3/mod/direct 3/rm32/ebx 4/imm32 17 | # exit(ebx) 18 | e8/call syscall_exit/disp32 19 | 20 | # . . vim:nowrap:textwidth=0 21 | -------------------------------------------------------------------------------- /linux/apps/ex3.mu: -------------------------------------------------------------------------------- 1 | # Add the first 10 numbers, and return the result in the exit code. 2 | # 3 | # To run: 4 | # $ ./translate ex3.mu 5 | # $ ./a.elf 6 | # Expected result: 7 | # $ echo $? 8 | # 55 9 | 10 | fn main -> _/ebx: int { 11 | var result/ebx: int <- copy 0 12 | var i/eax: int <- copy 1 13 | { 14 | compare i, 0xa 15 | break-if-> 16 | result <- add i 17 | i <- increment 18 | loop 19 | } 20 | return result 21 | } 22 | -------------------------------------------------------------------------------- /archive/2.transect/factorial.k2: -------------------------------------------------------------------------------- 1 | # compute the factorial of 5, and return the result in the exit code 2 | 3 | fn factorial n : int -> result/EAX : int [ 4 | result/EAX <- copy 1 5 | { 6 | compare n, 1 7 | break-if <= 8 | var tmp/EBX : int 9 | tmp/EBX <- copy n 10 | tmp/EBX <- subtract 1 11 | var tmp2/EAX : int 12 | tmp2/EAX <- call factorial, tmp/EBX 13 | result/EAX <- multiply tmp2/EAX, n 14 | } 15 | return result/EAX 16 | ] 17 | -------------------------------------------------------------------------------- /archive/1.vm/sandbox/mu_run: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env zsh 2 | # Little bit of glue to support running Mu from Vim over tmux. 3 | 4 | export ALREADY_FOCUSED=0 5 | tmux list-panes |grep "^1.*active" -q && export ALREADY_FOCUSED=1 6 | if [[ $ALREADY_FOCUSED -eq 0 ]] 7 | then 8 | tmux select-pane -t 1 9 | fi 10 | 11 | tmux send-keys 'F4' 12 | 13 | if [[ $ALREADY_FOCUSED -eq 0 ]] 14 | then 15 | tmux last-pane 16 | fi 17 | 18 | exit 0 # avoid spurious error messages under tmux 19 | -------------------------------------------------------------------------------- /archive/Readme.md: -------------------------------------------------------------------------------- 1 | This directory contains earlier prototypes. 2 | 3 | * 0.vm.arc: an early prototype of a statement-oriented interpreted language 4 | built in Arc. Now has its own repo at 5 | [mu0](https://github.com/akkartik/mu0). 6 | 7 | * 1.vm: a statement-oriented interpreted language. Now has its own repo at 8 | [mu1](https://github.com/akkartik/mu1). 9 | 10 | * 2.transect: an abortive design for a safe low-level language with manual 11 | register allocation. 12 | -------------------------------------------------------------------------------- /tutorial/task12-solution.mu: -------------------------------------------------------------------------------- 1 | # Here's one way to draw a rectangle from the top-left corner of screen. 2 | # Lots of other solutions are possible. 3 | fn main screen: (addr screen) { 4 | draw-line screen, 1/x1 1/y1, 0x300/x2 1/y2, 3/color=green 5 | draw-line screen, 1/x1 0x200/y1, 0x300/x2 0x200/y2, 3/color=green 6 | draw-line screen, 1/x1 1/y1, 1/x2 0x200/y2, 3/color=green 7 | draw-line screen, 0x300/x1 1/y1, 0x300/x2 0x200/y2, 3/color=green 8 | } 9 | -------------------------------------------------------------------------------- /linux/apps/raytracing/color.h: -------------------------------------------------------------------------------- 1 | #ifndef COLOR_H 2 | #define COLOR_H 3 | 4 | #include "vec3.h" 5 | 6 | #include 7 | 8 | void write_color(std::ostream &out, color pixel_color) { 9 | // Write the translated [0,255] value of each color component. 10 | out << static_cast(255.999 * pixel_color.x()) << ' ' 11 | << static_cast(255.999 * pixel_color.y()) << ' ' 12 | << static_cast(255.999 * pixel_color.z()) << '\n'; 13 | } 14 | 15 | #endif 16 | -------------------------------------------------------------------------------- /editor/atom/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "subx", 3 | "version": "0.0.1", 4 | "description": "Syntax highlighting for SubX files in the Mu computing stack.", 5 | "author": "Kartik Agaram", 6 | "keywords": [ 7 | "language", 8 | "mu", 9 | "syntax", 10 | "highlighting" 11 | ], 12 | "repository": "https://github.com/akkartik/mu", 13 | "engines": { 14 | "atom": ">=1.0.0 <2.0.0" 15 | }, 16 | "dependencies": {} 17 | } 18 | -------------------------------------------------------------------------------- /linux/bootstrap/test_layers: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # Repeatedly stop building until successive layers, and run all tests built. 3 | # 4 | # Assumes .subx files all come after .cc files. 5 | 6 | set -e 7 | 8 | cd `dirname $0` 9 | # add C++ files one at a time 10 | for f in [0-9]*cc 11 | do 12 | echo "=== bootstrap $f" 13 | ./build_and_test_until $f 14 | done 15 | 16 | # build everything one last time 17 | ./clean 18 | ./build # build optimized since we'll be running it repeatedly below 19 | -------------------------------------------------------------------------------- /tutorial/task5-solution.mu: -------------------------------------------------------------------------------- 1 | fn foo -> _/eax: int { 2 | var x: int 3 | # statement 1: store 3 in x 4 | copy-to x, 3 5 | # statement 2: define a new variable 'y' in register eax and store 4 in it 6 | var y/eax: int <- copy 4 7 | # statement 3: add y to x, storing the result in x 8 | add-to x, y 9 | return x 10 | } 11 | 12 | fn test-foo { 13 | var result/eax: int <- foo 14 | check-ints-equal result, 7, "F - foo should return 7, but didn't" 15 | } 16 | 17 | fn main { 18 | } 19 | -------------------------------------------------------------------------------- /linux/subx-params.subx: -------------------------------------------------------------------------------- 1 | # Various knobs for translating SubX programs using SubX. 2 | 3 | == data 4 | 5 | # largest segment that can be translated 6 | Segment-size: 7 | 0x300000/imm32/3MB 8 | 9 | # maximum size of input textual stream (spanning all segments) 10 | Input-size: 11 | 0x600000/imm32/6MB 12 | 13 | # number of labels we can translate to addresses 14 | Max-labels: 15 | 0x60000/imm32/16K-labels/384KB 16 | 17 | # capacity of trace-stream 18 | Trace-size: 19 | 0x200000/imm32/2MB 20 | -------------------------------------------------------------------------------- /tutorial/task7.mu: -------------------------------------------------------------------------------- 1 | fn foo -> _/eax: int { 2 | var x/edx: int <- copy 0 3 | # statement 1: store 3 in x 4 | copy-to x, 3 5 | # statement 2: define a new variable 'y' in register eax and store 4 in it 6 | var y/eax: int <- copy 4 7 | # statement 3: add y to x, storing the result in x 8 | add-to x, y 9 | return x 10 | } 11 | 12 | fn test-foo { 13 | var result/eax: int <- foo 14 | check-ints-equal result, 7, "F - foo should return 7, but didn't" 15 | } 16 | 17 | fn main { 18 | } 19 | -------------------------------------------------------------------------------- /archive/0.vm.arc/fork.mu: -------------------------------------------------------------------------------- 1 | (function main [ 2 | (fork thread2:fn) 3 | (default-space:space-address <- new space:literal 2:literal) 4 | (x:integer <- copy 34:literal) 5 | { begin 6 | (print-integer nil:literal/terminal x:integer) 7 | (loop) 8 | } 9 | ]) 10 | 11 | (function thread2 [ 12 | (default-space:space-address <- new space:literal 2:literal) 13 | (y:integer <- copy 35:literal) 14 | { begin 15 | (print-integer nil:literal/terminal y:integer) 16 | (loop) 17 | } 18 | ]) 19 | -------------------------------------------------------------------------------- /archive/1.vm/build_and_test_until: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # Run tests for just a subset of layers. 3 | # 4 | # Usage: 5 | # build_and_test_until [file prefix] [test name] 6 | # Provide the second arg to run just a single test. 7 | set -e 8 | 9 | # clean previous builds if they were building until a different layer 10 | touch .until 11 | PREV_UNTIL=`cat .until` 12 | if [ "$PREV_UNTIL" != $1 ] 13 | then 14 | ./clean top-level 15 | echo $1 > .until 16 | fi 17 | 18 | ./build3 --until $1 && ./mu_bin test $2 19 | -------------------------------------------------------------------------------- /archive/2.transect/ex3.k2: -------------------------------------------------------------------------------- 1 | # add the first 10 numbers, and return the result in the exit code 2 | 3 | fn main [ 4 | var result/EBX : int 5 | result/EBX <- copy 0 6 | var counter/ECX : int 7 | counter/ECX <- copy 1 8 | { 9 | compare counter/ECX, 10 10 | break-if > 11 | result/EBX <- add counter/ECX 12 | counter/ECX <- add 1 13 | loop 14 | } 15 | call exit, 1 16 | ] 17 | 18 | fn exit x : int [ 19 | code/EBX <- copy x 20 | code/EAX <- copy 1/exit 21 | syscall 22 | ] 23 | -------------------------------------------------------------------------------- /linux/bootstrap/build_and_test_until: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # Run tests for just a subset of layers. 3 | # 4 | # Usage: 5 | # build_and_test_until [file prefix] [test name] 6 | # Provide the second arg to run just a single test. 7 | set -e 8 | 9 | # clean previous builds if they were building until a different layer 10 | touch .until 11 | PREV_UNTIL=`cat .until` 12 | if [ "$PREV_UNTIL" != $1 ] 13 | then 14 | ./clean 15 | echo $1 > .until 16 | fi 17 | 18 | ./build --until $1 && ./bootstrap_bin test $2 19 | -------------------------------------------------------------------------------- /tutorial/task7-solution.mu: -------------------------------------------------------------------------------- 1 | fn foo -> _/eax: int { 2 | var x/edx: int <- copy 0 3 | # statement 1: store 3 in x 4 | x <- copy 3 5 | # statement 2: define a new variable 'y' in register eax and store 4 in it 6 | var y/eax: int <- copy 4 7 | # statement 3: add y to x, storing the result in x 8 | x <- add y 9 | return x 10 | } 11 | 12 | fn test-foo { 13 | var result/eax: int <- foo 14 | check-ints-equal result, 7, "F - foo should return 7, but didn't" 15 | } 16 | 17 | fn main { 18 | } 19 | -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | # hide from GitHub stats 2 | index.html linguist-generated=true 3 | html/** linguist-generated=true 4 | archive/** linguist-generated=true 5 | prototypes/** linguist-generated=true 6 | tools/iso/kernel.soso/** linguist-vendored 7 | # include the bulk of the repo with an approximately-correct language 8 | # just so it seems less like a purely C++ project 9 | # unfortunately Linguist won't accept a spec for my toy languages 10 | *.subx linguist-language=Assembly 11 | *.mu linguist-language=Forth 12 | -------------------------------------------------------------------------------- /314divide.subx: -------------------------------------------------------------------------------- 1 | == code 2 | 3 | integer-divide: # a: int, b: int -> quotient/eax: int, remainder/edx: int 4 | # . prologue 5 | 55/push-ebp 6 | 89/<- %ebp 4/r32/esp 7 | # eax = a 8 | 8b/-> *(ebp+8) 0/r32/eax 9 | # edx = all 0s or all 1s 10 | 99/sign-extend-eax-into-edx 11 | # quotient, remainder = divide eax by b 12 | f7 7/subop/divide-eax-edx-by *(ebp+0xc) 13 | $integer-divide:end: 14 | # . epilogue 15 | 89/<- %esp 5/r32/ebp 16 | 5d/pop-to-ebp 17 | c3/return 18 | -------------------------------------------------------------------------------- /linux/407right-justify.mu: -------------------------------------------------------------------------------- 1 | # print 'n' with enough leading spaces to be right-justified in 'width' 2 | fn print-int32-decimal-right-justified screen: (addr screen), n: int, _width: int { 3 | # tweak things for negative numbers 4 | var n-width/eax: int <- decimal-size n 5 | var width/ecx: int <- copy _width 6 | { 7 | compare n-width, width 8 | break-if->= 9 | print-code-point-utf8 screen, 0x20/space 10 | width <- decrement 11 | loop 12 | } 13 | print-int32-decimal screen, n 14 | } 15 | -------------------------------------------------------------------------------- /archive/2.transect/ex6.k2: -------------------------------------------------------------------------------- 1 | ## print out a (global variable) string to stdout 2 | 3 | var size : int = 14 4 | var x : (array character) = "hello, world!" 5 | 6 | fn main [ 7 | call write 1/stdout, x, size 8 | call exit, 0 9 | ] 10 | 11 | fn write fd : int, x : (address array byte), size : int [ 12 | EBX <- copy fd 13 | ECX <- copy x 14 | EDX <- copy size 15 | EAX <- copy 4/write 16 | syscall 17 | ] 18 | 19 | fn exit x : int [ 20 | code/EBX <- copy x 21 | code/EAX <- copy 1/exit 22 | syscall 23 | ] 24 | -------------------------------------------------------------------------------- /linux/314divide.subx: -------------------------------------------------------------------------------- 1 | == code 2 | 3 | integer-divide: # a: int, b: int -> quotient/eax: int, remainder/edx: int 4 | # . prologue 5 | 55/push-ebp 6 | 89/<- %ebp 4/r32/esp 7 | # eax = a 8 | 8b/-> *(ebp+8) 0/r32/eax 9 | # edx = all 0s or all 1s 10 | 99/sign-extend-eax-into-edx 11 | # quotient, remainder = divide eax by b 12 | f7 7/subop/divide-eax-edx-by *(ebp+0xc) 13 | $integer-divide:end: 14 | # . epilogue 15 | 89/<- %esp 5/r32/ebp 16 | 5d/pop-to-ebp 17 | c3/return 18 | -------------------------------------------------------------------------------- /linux/apps/raytracing/1.cc: -------------------------------------------------------------------------------- 1 | // https://raytracing.github.io/books/RayTracingInOneWeekend.html 2 | #include 3 | 4 | int main() { 5 | 6 | // Image 7 | 8 | const int image_width = 256; 9 | const int image_height = 256; 10 | 11 | // Render 12 | 13 | std::cout << "P3\n" << image_width << ' ' << image_height << "\n255\n"; 14 | 15 | for (int j = image_height-1; j >= 0; --j) 16 | for (int i = 0; i < image_width; ++i) 17 | std::cout << i << ' ' << j << " 64\n"; 18 | } 19 | -------------------------------------------------------------------------------- /linux/apps/ex1.subx: -------------------------------------------------------------------------------- 1 | # First example: return the answer to the Ultimate Question of Life, the 2 | # Universe, and Everything. 3 | # 4 | # Same as https://www.muppetlabs.com/~breadbox/software/tiny/teensy.html 5 | # 6 | # To run: 7 | # $ ./translate_subx 000init.subx apps/ex1.subx 8 | # $ ./a.elf 9 | # Expected result: 10 | # $ echo $? 11 | # 42 12 | 13 | == code 14 | 15 | Entry: 16 | # exit(42) 17 | bb/copy-to-ebx 0x2a/imm32 # 42 in hex 18 | e8/call syscall_exit/disp32 19 | 20 | # . . vim:nowrap:textwidth=0 21 | -------------------------------------------------------------------------------- /tools/mu-init-minify.subx: -------------------------------------------------------------------------------- 1 | # Initialize the minimal runtime for Mu programs without any tests. 2 | # 3 | # See translate_min for how this file is used. 4 | # 5 | # Mu programs start at a function called 'main' with this signature: 6 | # fn main screen: (addr screen), keyboard: (addr keyboard), data-disk: (addr disk) 7 | 8 | == code 9 | 10 | Entry: 11 | # initialize stack 12 | bd/copy-to-ebp 0/imm32 13 | # 14 | (main 0 0 Primary-bus-secondary-drive) 15 | 16 | # hang indefinitely 17 | { 18 | eb/jump loop/disp8 19 | } 20 | -------------------------------------------------------------------------------- /517random.mu: -------------------------------------------------------------------------------- 1 | fn next-random prev: int -> _/edi: int { 2 | # https://en.wikipedia.org/wiki/Linear_congruential_generator#Parameters_in_common_use 3 | var a/ecx: int <- copy 0x4b/75 4 | var c/edx: int <- copy 0x4a/74 5 | var m/ebx: int <- copy 0x10001 6 | var next/eax: int <- copy prev 7 | next <- multiply a 8 | next <- add c 9 | next <- remainder next, m 10 | return next 11 | } 12 | 13 | fn remainder a: int, b: int -> _/eax: int { 14 | var q/eax: int <- copy 0 15 | var r/edx: int <- copy 0 16 | q, r <- integer-divide a, b 17 | return r 18 | } 19 | -------------------------------------------------------------------------------- /linux/apps/raytracing/ray.h: -------------------------------------------------------------------------------- 1 | #ifndef RAY_H 2 | #define RAY_H 3 | 4 | #include "vec3.h" 5 | 6 | class ray { 7 | public: 8 | ray() {} 9 | ray(const point3& origin, const vec3& direction) 10 | : orig(origin), dir(direction) 11 | {} 12 | 13 | point3 origin() const { return orig; } 14 | vec3 direction() const { return dir; } 15 | 16 | point3 at(float t) const { 17 | return orig + t*dir; 18 | } 19 | 20 | public: 21 | point3 orig; 22 | vec3 dir; 23 | }; 24 | 25 | #endif 26 | -------------------------------------------------------------------------------- /archive/1.vm/exuberant_ctags_rc: -------------------------------------------------------------------------------- 1 | --langdef=mu 2 | --langmap=mu:.mu 3 | --regex-mu=/^def[ \t]+([^ \t]*)/\1/d,definition/ 4 | --regex-mu=/^def![ \t]+([^ \t]*)/\1/d,definition/ 5 | --regex-mu=/^recipe[ \t]+([^ \t]*)/\1/d,definition/ 6 | --regex-mu=/^recipe![ \t]+([^ \t]*)/\1/d,definition/ 7 | --regex-mu=/^type[ \t]+([^ \t]*)/\1/t,typeref/ 8 | --regex-mu=/^container[ \t]+([^ \t:]*)/\1/s,struct/ 9 | --regex-mu=/^exclusive-container[ \t]+([^ \t:]*)/\1/u,union/ 10 | --regex-mu=/$x/x/x/e/ --------- next option is for way-points in Mu 11 | --regex-mu=/^[ \t]*(<[^ \t]*>)/\1/d,definition/ 12 | -------------------------------------------------------------------------------- /apps/ex4.mu: -------------------------------------------------------------------------------- 1 | # Draw a character using the built-in font (GNU unifont) 2 | # 3 | # To build a disk image: 4 | # ./translate apps/ex4.mu # emits code.img 5 | # To run: 6 | # qemu-system-i386 code.img 7 | # 8 | # Expected output: letter 'A' in green near the top-left corner of screen 9 | 10 | fn main screen: (addr screen), keyboard: (addr keyboard), data-disk: (addr disk) { 11 | var dummy/eax: int <- draw-code-point screen, 0x41/A, 2/row, 1/col, 0xa/fg, 0/bg 12 | # wide glyph 13 | #? var dummy/eax: int <- draw-code-point screen, 0x1b/esc, 2/row, 1/col, 0xa/fg, 0/bg 14 | } 15 | -------------------------------------------------------------------------------- /editor/Mu.tmbundle/info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | contactEmailRot13 6 | zh.grkgzngr@nxxnegvx.pbz 7 | contactName 8 | Kartik Agaram 9 | description 10 | Bundle for Mu: https://github.com/akkartik/mu 11 | name 12 | Mu 13 | uuid 14 | 24559A54-666E-40D4-A561-C9A49DD9B675 15 | 16 | 17 | -------------------------------------------------------------------------------- /archive/0.vm.arc/charterm/test-charterm.rkt: -------------------------------------------------------------------------------- 1 | #lang racket/base 2 | ;; For legal info, see file "charterm.rkt". 3 | 4 | ;; (require (planet neil/charterm:1)) 5 | (require "charterm.rkt") 6 | 7 | (with-charterm 8 | (charterm-clear-screen) 9 | (charterm-cursor 10 5) 10 | (charterm-display "Hello, ") 11 | (charterm-bold) 12 | (charterm-display "you") 13 | (charterm-normal) 14 | (charterm-display ".") 15 | (charterm-cursor 1 1) 16 | (charterm-display "Press a key...") 17 | (let ((key (charterm-read-key))) 18 | (charterm-cursor 1 1) 19 | (charterm-clear-line) 20 | (printf "You pressed: ~S\r\n" key))) 21 | -------------------------------------------------------------------------------- /editor/mu.dte: -------------------------------------------------------------------------------- 1 | # Syntax highlighting for https://gitlab.com/craigbarnes/dte 2 | # 3 | # To install this file, symlink it to ~/.dte/syntax/mu 4 | # Then add this line to ~/.dte/rc: 5 | # ft mu mu 6 | 7 | syntax mu 8 | 9 | state start code 10 | char # comment 11 | char '"' string 12 | char -b a-z ident 13 | eat this 14 | 15 | state comment 16 | char "\n" start 17 | eat this 18 | 19 | state string 20 | char "\"" start string 21 | eat this 22 | 23 | state ident 24 | char -b a-z this 25 | inlist keyword start 26 | noeat start 27 | 28 | list keyword \ 29 | fn type var 30 | -------------------------------------------------------------------------------- /tools/browse_trace: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | set -e 3 | 4 | test "$CXX" || export CXX=c++ 5 | test "$CC" || export CC=cc 6 | test "$CFLAGS" || export CFLAGS="-g -O2" 7 | export CFLAGS="$CFLAGS -Wall -Wextra -ftrapv -fno-strict-aliasing" 8 | 9 | # build if doesn't exist 10 | [ ! -f `dirname $0`/browse_trace_bin ] && ( 11 | cd `dirname $0` 12 | [ ! -f termbox/libtermbox.a ] && ( 13 | cd termbox 14 | $CC $CFLAGS -c utf8.c 15 | $CC $CFLAGS -c termbox.c 16 | ar rcs libtermbox.a *.o 17 | ) 18 | $CXX $CFLAGS browse_trace.cc termbox/libtermbox.a -o browse_trace_bin 19 | ) 20 | 21 | `dirname $0`/browse_trace_bin $* 22 | -------------------------------------------------------------------------------- /tutorial/task11-solution.mu: -------------------------------------------------------------------------------- 1 | fn difference a: int, b: int -> _/eax: int { 2 | var result/eax: int <- copy a 3 | result <- subtract b 4 | compare result, 0 5 | { 6 | break-if->= 7 | result <- negate 8 | } 9 | return result 10 | } 11 | 12 | fn test-difference { 13 | var result/eax: int <- difference 5, 3 14 | check-ints-equal result, 2, "F - difference works" 15 | result <- difference 3, 5 16 | check-ints-equal result, 2, "F - difference is always positive" 17 | result <- difference 6, 6 18 | check-ints-equal result, 0, "F - difference can be 0" 19 | } 20 | 21 | fn main screen: (addr screen) { 22 | } 23 | -------------------------------------------------------------------------------- /editor/VSCode/.vscode/launch.json: -------------------------------------------------------------------------------- 1 | // A launch configuration that launches the extension inside a new window 2 | // Use IntelliSense to learn about possible attributes. 3 | // Hover to view descriptions of existing attributes. 4 | // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 5 | { 6 | "version": "0.2.0", 7 | "configurations": [ 8 | { 9 | "name": "Extension", 10 | "type": "extensionHost", 11 | "request": "launch", 12 | "args": [ 13 | "--extensionDevelopmentPath=${workspaceFolder}" 14 | ] 15 | } 16 | ] 17 | } -------------------------------------------------------------------------------- /tools/create_container: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # Start a Linux container containing the mu/ directory. 3 | # Useful on non-Linux platforms. 4 | # Run it from the top-level mu/ directory. 5 | 6 | docker run -it --name mu -v `pwd`:/mu abyssos/abyss:dev 7 | 8 | # On the first startup, you'll need to run the following commands: 9 | # apk add git nano libcxx-dev 10 | # cd /mu 11 | 12 | # Leaving this container will stop it. 13 | # Restart it with: 14 | # docker start mu 15 | # 16 | # Now you can connect to it anytime with: 17 | # docker exec -it mu sh 18 | # cd /mu 19 | # 20 | # Quite slow, though. Docker has to run a VM on other platforms. 21 | -------------------------------------------------------------------------------- /archive/1.vm/086scenario_console_test.mu: -------------------------------------------------------------------------------- 1 | # To check our support for consoles in scenarios, rewrite tests from 2 | # scenario_console.mu 3 | # Tests for console interface. 4 | 5 | scenario read-key-in-mu [ 6 | assume-console [ 7 | type [abc] 8 | ] 9 | run [ 10 | 1:char, 2:bool <- read-key console 11 | 3:char, 4:bool <- read-key console 12 | 5:char, 6:bool <- read-key console 13 | 7:char, 8:bool <- read-key console 14 | ] 15 | memory-should-contain [ 16 | 1 <- 97 # 'a' 17 | 2 <- 1 18 | 3 <- 98 # 'b' 19 | 4 <- 1 20 | 5 <- 99 # 'c' 21 | 6 <- 1 22 | 7 <- 0 # eof 23 | 8 <- 1 24 | ] 25 | ] 26 | -------------------------------------------------------------------------------- /linux/browse/README.md: -------------------------------------------------------------------------------- 1 | Render a subset of Markdown. 2 | 3 | To run: 4 | 5 | ``` 6 | $ cd linux 7 | $ ./translate browse.mu 8 | $ ./a.elf __text_file__ 9 | ``` 10 | 11 | Press 'q' to quit. All other keys scroll down. 12 | 13 | ## Format restrictions 14 | 15 | This is a fairly tiny subset of GitHub-Flavored Markdown. Things supported so 16 | far: 17 | 18 | * Newlines are mostly ignored. Double newlines are rendered (paragraphs). 19 | Newlines followed by indentation are rendered. 20 | * Paragraphs starting with runs of `#` represent headings. 21 | * Within a line, characters between `*`s or `_`s represent bolded text. No 22 | italics. 23 | -------------------------------------------------------------------------------- /318debug-counter.subx: -------------------------------------------------------------------------------- 1 | # A rudimentary counter that can be called from anywhere. 2 | 3 | == code 4 | 5 | count-event: 6 | # . prologue 7 | 55/push-ebp 8 | 89/<- %ebp 4/r32/esp 9 | # 10 | ff 0/subop/increment *Foo 11 | $count-event:end: 12 | # . epilogue 13 | 89/<- %esp 5/r32/ebp 14 | 5d/pop-to-ebp 15 | c3/return 16 | 17 | count-of-events: # -> _/eax: int 18 | # . prologue 19 | 55/push-ebp 20 | 89/<- %ebp 4/r32/esp 21 | # 22 | 8b/-> *Foo 0/r32/eax 23 | $count-of-events:end: 24 | # . epilogue 25 | 89/<- %esp 5/r32/ebp 26 | 5d/pop-to-ebp 27 | c3/return 28 | 29 | == data 30 | Foo: 31 | 0/imm32 32 | -------------------------------------------------------------------------------- /tutorial/add2.mu: -------------------------------------------------------------------------------- 1 | fn main screen: (addr screen), keyboard: (addr keyboard), data-disk: (addr disk) { 2 | var result/eax: int <- do-add 3, 4 3 | draw-int32-decimal-wrapping-right-then-down-from-cursor-over-full-screen screen, result, 3/fg=cyan 0/bg 4 | } 5 | 6 | fn do-add a: int, b: int -> _/eax: int { 7 | var result/eax: int <- copy a 8 | result <- add b 9 | return result 10 | } 11 | 12 | fn test-do-add { 13 | var observed/eax: int <- do-add 0, 0 14 | check-ints-equal observed, 0, "F - 0+0" 15 | observed <- do-add 3, 0 16 | check-ints-equal observed, 3, "F - 3+0" 17 | observed <- do-add 3, 2 18 | check-ints-equal observed, 5, "F - 3+2" 19 | } 20 | -------------------------------------------------------------------------------- /tutorial/c2f.mu: -------------------------------------------------------------------------------- 1 | fn main screen: (addr screen), keyboard: (addr keyboard), data-disk: (addr disk) { 2 | var result/eax: int <- do-add 3, 4 3 | draw-int32-decimal-wrapping-right-then-down-from-cursor-over-full-screen screen, result, 3/fg=cyan 0/bg 4 | } 5 | 6 | fn do-add a: int, b: int -> _/eax: int { 7 | var result/eax: int <- copy a 8 | result <- add b 9 | return result 10 | } 11 | 12 | fn test-do-add { 13 | var observed/eax: int <- do-add 0, 0 14 | check-ints-equal observed, 0, "F - 0+0" 15 | observed <- do-add 3, 0 16 | check-ints-equal observed, 3, "F - 3+0" 17 | observed <- do-add 3, 2 18 | check-ints-equal observed, 5, "F - 3+2" 19 | } 20 | -------------------------------------------------------------------------------- /archive/0.vm.arc/Readme.md: -------------------------------------------------------------------------------- 1 | Original prototype, last modified 2015-03-14 2 | 3 | First install [Racket](http://racket-lang.org) (just for this prototype; 4 | last tested with v6.3). Then: 5 | 6 | ```shell 7 | $ cd mu/archives/1.vm 8 | $ git clone http://github.com/arclanguage/anarki 9 | $ cd anarki 10 | $ git checkout d7290130a7 # last compatible snapshot 11 | $ cd .. 12 | $ ./mu test mu.arc.t # run tests 13 | ``` 14 | 15 | Example programs: 16 | 17 | ```shell 18 | $ ./mu factorial.mu # computes factorial of 5 19 | $ ./mu fork.mu # two threads print '33' and '34' forever 20 | $ ./mu channel.mu # two threads in a producer/consumer relationship 21 | ``` 22 | -------------------------------------------------------------------------------- /tools/expand_string_handle: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # Expand syntax sugar for SubX string literals and show the corresponding handle definition. 3 | # 4 | # The handle has a fake alloc-id; we're never going to try to reclaim global 5 | # variables, we just sometimes need handles in them to satisfy type constraints. 6 | 7 | INPUT=$(cat) 8 | echo " 0x11/imm32/alloc-id:fake:payload" 9 | echo " # \"$INPUT\"" 10 | 11 | # print length in bytes 12 | printf " 0x%x/imm32/size\n" $(echo -n $INPUT |wc -c) 13 | 14 | # print ascii codes for each character in hex 15 | echo -n " " 16 | for c in $(echo "$INPUT" |sed -e 's/./& /g') 17 | do 18 | echo -n " 0x$(printf '%x' "'$c")/$c" 19 | done 20 | echo 21 | -------------------------------------------------------------------------------- /archive/1.vm/factorial.mu: -------------------------------------------------------------------------------- 1 | # example program: compute the factorial of 5 2 | 3 | def main [ 4 | local-scope 5 | x:num <- factorial 5 6 | $print [result: ], x, [ 7 | ] 8 | ] 9 | 10 | def factorial n:num -> result:num [ 11 | local-scope 12 | load-inputs 13 | { 14 | # if n=0 return 1 15 | zero?:bool <- equal n, 0 16 | break-unless zero? 17 | return 1 18 | } 19 | # return n * factorial(n-1) 20 | x:num <- subtract n, 1 21 | subresult:num <- factorial x 22 | result <- multiply subresult, n 23 | ] 24 | 25 | # unit test 26 | scenario factorial-test [ 27 | run [ 28 | 1:num <- factorial 5 29 | ] 30 | memory-should-contain [ 31 | 1 <- 120 32 | ] 33 | ] 34 | -------------------------------------------------------------------------------- /archive/1.vm/real-files.mu: -------------------------------------------------------------------------------- 1 | # example program: read a character from one file and write it to another 2 | # BEWARE: this will modify your file system 3 | # before running it, put a character into /tmp/mu-x 4 | # after running it, check /tmp/mu-y 5 | 6 | def main [ 7 | local-scope 8 | f:num/file <- $open-file-for-reading [/tmp/mu-x] 9 | $print [file to read from: ], f, 10/newline 10 | c:char, eof?:bool <- $read-from-file f 11 | $print [copying ], c, 10/newline 12 | f <- $close-file f 13 | $print [file after closing: ], f, 10/newline 14 | f <- $open-file-for-writing [/tmp/mu-y] 15 | $print [file to write to: ], f, 10/newline 16 | $write-to-file f, c 17 | f <- $close-file f 18 | ] 19 | -------------------------------------------------------------------------------- /archive/0.vm.arc/callcc.mu: -------------------------------------------------------------------------------- 1 | ; in mu, call-cc (http://en.wikipedia.org/wiki/Call-with-current-continuation) 2 | ; is constructed out of a combination of two primitives: 3 | ; 'current-continuation', which returns a continuation, and 4 | ; 'continue-from', which takes a continuation to 5 | 6 | (function g [ 7 | (c:continuation <- current-continuation) ; <-- loop back to here 8 | (print-character nil:literal/terminal ((#\a literal))) 9 | (reply c:continuation) 10 | ]) 11 | 12 | (function f [ 13 | (c:continuation <- g) 14 | (reply c:continuation) 15 | ]) 16 | 17 | (function main [ 18 | (c:continuation <- f) 19 | (continue-from c:continuation) ; <-- ..when you hit this 20 | ]) 21 | -------------------------------------------------------------------------------- /shell/main.mu: -------------------------------------------------------------------------------- 1 | # Experimental Mu shell 2 | # Currently based on Lisp. 3 | 4 | fn main screen: (addr screen), keyboard: (addr keyboard), data-disk: (addr disk) { 5 | var env-storage: environment 6 | var env/esi: (addr environment) <- address env-storage 7 | initialize-environment env, 0x20/fake-screen-width, 8/fake-screen-height 8 | load-state env, data-disk 9 | { 10 | render-environment screen, env 11 | # no way to quit right now; just reboot 12 | { 13 | var key/eax: byte <- read-key keyboard 14 | compare key, 0 15 | loop-if-= 16 | var key/eax: code-point-utf8 <- copy key 17 | edit-environment env, key, data-disk 18 | } 19 | loop 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /apps/ex5.mu: -------------------------------------------------------------------------------- 1 | # Draw a single line of ASCII text using the built-in font (GNU unifont) 2 | # Also demonstrates bounds-checking _before_ drawing. 3 | # 4 | # To build a disk image: 5 | # ./translate apps/ex5.mu # emits code.img 6 | # To run: 7 | # qemu-system-i386 code.img 8 | # 9 | # Expected output: text in green near the top-left corner of screen 10 | 11 | fn main screen: (addr screen), keyboard: (addr keyboard), data-disk: (addr disk) { 12 | var dummy/eax: int <- draw-text-rightward screen, "hello from baremetal Mu!", 0x10/x, 0x400/xmax, 0x10/y, 0xa/fg, 0/bg 13 | dummy <- draw-text-rightward screen, "you shouldn't see this", 0x10/x, 0xa0/xmax, 0x30/y, 3/fg, 0/bg # xmax is too narrow 14 | } 15 | -------------------------------------------------------------------------------- /tutorial/converter.html: -------------------------------------------------------------------------------- 1 | 11 | 12 |
13 | = 14 |
15 | 16 | -------------------------------------------------------------------------------- /apps/ex2.mu: -------------------------------------------------------------------------------- 1 | # Test out the video mode by filling in the screen with pixels. 2 | # 3 | # To build a disk image: 4 | # ./translate apps/ex2.mu # emits code.img 5 | # To run: 6 | # qemu-system-i386 code.img 7 | 8 | fn main screen: (addr screen), keyboard: (addr keyboard), data-disk: (addr disk) { 9 | var y/eax: int <- copy 0 10 | { 11 | compare y, 0x300/screen-height=768 12 | break-if->= 13 | var x/edx: int <- copy 0 14 | { 15 | compare x, 0x400/screen-width=1024 16 | break-if->= 17 | var color/ecx: int <- copy x 18 | color <- and 0xff 19 | pixel screen x, y, color 20 | x <- increment 21 | loop 22 | } 23 | y <- increment 24 | loop 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /archive/1.vm/continuation1.mu: -------------------------------------------------------------------------------- 1 | # Example program showing that 'return-continuation-until-mark' can 'pause' a 2 | # function call, returning a continuation, and that calling the continuation 3 | # can 'resume' the paused function call. 4 | # 5 | # To run: 6 | # $ git clone https://github.com/akkartik/mu 7 | # $ cd mu 8 | # $ ./mu continuation1.mu 9 | # 10 | # Expected output: 11 | # 1 12 | 13 | def main [ 14 | local-scope 15 | k:continuation <- call-with-continuation-mark 100/mark, create-yielder 16 | x:num <- call k # should return 1 17 | $print x 10/newline 18 | ] 19 | 20 | def create-yielder -> n:num [ 21 | local-scope 22 | load-inputs 23 | return-continuation-until-mark 100/mark 24 | return 1 25 | ] 26 | -------------------------------------------------------------------------------- /archive/1.vm/static-dispatch.mu: -------------------------------------------------------------------------------- 1 | # Example program showing how multiple functions with the same name can 2 | # coexist, and how we select between them. 3 | # 4 | # Expected output: 5 | # 4 6 | # 7 7 | # 7 8 | 9 | def test a:num -> b:num [ 10 | local-scope 11 | load-inputs 12 | b <- add a, 1 13 | ] 14 | 15 | def test a:num, b:num -> c:num [ 16 | local-scope 17 | load-inputs 18 | c <- add a, b 19 | ] 20 | 21 | def main [ 22 | local-scope 23 | a:num <- test 3 # selects single-input version 24 | $print a, 10/newline 25 | b:num <- test 3, 4 # selects double-input version 26 | $print b, 10/newline 27 | c:num <- test 3, 4, 5 # prefers double- to single-input version 28 | $print c, 10/newline 29 | ] 30 | -------------------------------------------------------------------------------- /linux/apps/ex3.2.mu: -------------------------------------------------------------------------------- 1 | # Unnecessarily use an array to sum 1..10 2 | # 3 | # To run: 4 | # $ ./translate apps/ex3.2.mu 5 | # $ ./a.elf 6 | # $ echo $? 7 | # 55 8 | 9 | fn main -> _/ebx: int { 10 | # populate a 11 | var a: (array int 0xb) # 11; we waste index 0 12 | var i/ecx: int <- copy 1 13 | { 14 | compare i, 0xb 15 | break-if->= 16 | var x/eax: (addr int) <- index a, i 17 | copy-to *x, i 18 | i <- increment 19 | loop 20 | } 21 | # sum 22 | var result/edx: int <- copy 0 23 | i <- copy 1 24 | { 25 | compare i, 0xb 26 | break-if->= 27 | var x/eax: (addr int) <- index a, i 28 | result <- add *x 29 | i <- increment 30 | loop 31 | } 32 | return result 33 | } 34 | -------------------------------------------------------------------------------- /editor/VSCode/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "mu", 3 | "displayName": "Mu", 4 | "description": "Syntax Highlighting for the Mu language", 5 | "version": "0.0.1", 6 | "engines": { 7 | "vscode": "^1.62.0" 8 | }, 9 | "categories": [ 10 | "Programming Languages" 11 | ], 12 | "contributes": { 13 | "languages": [{ 14 | "id": "mu", 15 | "aliases": ["Mu", "mu"], 16 | "extensions": [".mu"], 17 | "configuration": "./language-configuration.json" 18 | }], 19 | "grammars": [{ 20 | "language": "mu", 21 | "scopeName": "source.mu", 22 | "path": "./syntaxes/Mu.tmLanguage" 23 | }] 24 | } 25 | } -------------------------------------------------------------------------------- /linux/408float.mu: -------------------------------------------------------------------------------- 1 | # Some quick-n-dirty ways to create floats. 2 | 3 | fn fill-in-rational _out: (addr float), nr: int, dr: int { 4 | var out/edi: (addr float) <- copy _out 5 | var result/xmm0: float <- convert nr 6 | var divisor/xmm1: float <- convert dr 7 | result <- divide divisor 8 | copy-to *out, result 9 | } 10 | 11 | fn fill-in-sqrt _out: (addr float), n: int { 12 | var out/edi: (addr float) <- copy _out 13 | var result/xmm0: float <- convert n 14 | result <- square-root result 15 | copy-to *out, result 16 | } 17 | 18 | fn rational nr: int, dr: int -> _/xmm0: float { 19 | var result/xmm0: float <- convert nr 20 | var divisor/xmm1: float <- convert dr 21 | result <- divide divisor 22 | return result 23 | } 24 | -------------------------------------------------------------------------------- /archive/0.vm.arc/factorial.mu: -------------------------------------------------------------------------------- 1 | (function factorial [ 2 | (default-space:space-address <- new space:literal 30:literal) 3 | (n:integer <- next-input) 4 | { begin 5 | ; if n=0 return 1 6 | (zero?:boolean <- equal n:integer 0:literal) 7 | (break-unless zero?:boolean) 8 | (reply 1:literal) 9 | } 10 | ; return n*factorial(n-1) 11 | (x:integer <- subtract n:integer 1:literal) 12 | (subresult:integer <- factorial x:integer) 13 | (result:integer <- multiply subresult:integer n:integer) 14 | (reply result:integer) 15 | ]) 16 | 17 | (function main [ 18 | (1:integer <- factorial 5:literal) 19 | ($print (("result: " literal))) 20 | (print-integer nil:literal/terminal 1:integer) 21 | ($print (("\n" literal))) 22 | ]) 23 | -------------------------------------------------------------------------------- /archive/0.vm.arc/mu: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # 3 | # To run a program: 4 | # $ mu [mu files] 5 | # To run a file of tests (in arc): 6 | # $ mu test [arc files] 7 | # To start an interactive session: 8 | # $ mu repl 9 | # 10 | # To mess with load levels and selectively run parts of the codebase, skip 11 | # this script and call load.arc directly. 12 | 13 | if [[ $1 == "test" ]] 14 | then 15 | shift 16 | ./anarki/arc load.arc "$@" # test currently assumed to be arc files rather than mu files 17 | elif [[ $1 == "repl" ]] 18 | then 19 | if [ "$(type rlwrap)" ] 20 | then 21 | rlwrap -C mu ./anarki/arc mu.arc 22 | else 23 | ./anarki/arc mu.arc 24 | fi 25 | else 26 | ./anarki/arc load.arc mu.arc -- "$@" # mu files from args 27 | fi 28 | -------------------------------------------------------------------------------- /archive/2.transect/ex5.k2: -------------------------------------------------------------------------------- 1 | # read a character from stdin, save it to a local on the stack, write it to stdout 2 | 3 | fn main [ 4 | var x : char 5 | call read 0/stdin, x, 1/size 6 | result/EBX <- call write 1/stdout, x, 1/size 7 | call exit-EBX 8 | ] 9 | 10 | fn read fd : int, x : (address array byte), size : int [ 11 | EBX <- copy fd 12 | ECX <- copy x 13 | EDX <- copy size 14 | EAX <- copy 3/read 15 | syscall 16 | ] 17 | 18 | fn write fd : int, x : (address array byte), size : int [ 19 | EBX <- copy fd 20 | ECX <- copy x 21 | EDX <- copy size 22 | EAX <- copy 4/write 23 | syscall 24 | ] 25 | 26 | # like exit, but assumes the code is already in EBX 27 | fn exit-EBX [ 28 | code/EAX <- copy 1/exit 29 | syscall 30 | ] 31 | -------------------------------------------------------------------------------- /browse-slack/README.md: -------------------------------------------------------------------------------- 1 | To try it out: 2 | 3 | 1. Import a tiny test Slack archive into the data disk by running: 4 | ``` 5 | tools/image-data 10 < browse-slack/test_data 6 | ``` 7 | 8 | 2. Build the code disk (on Linux; see the top-level Readme for other platforms) 9 | ``` 10 | ./translate browse-slack/*.mu 11 | ``` 12 | 13 | 3. Run the code and data disks: 14 | ``` 15 | qemu-system-i386 -m 2G -hda code.img -hdb path/to/data.img 16 | ``` 17 | 18 | You should now see some text and images in Qemu. For a real Slack archive, 19 | follow the instructions at the top of `browse-slack/convert_slack.py`. You'll 20 | also want to tweak the `sector-count` in browse-slack/main.mu which affects 21 | the number of sectors read from the data disk. 22 | -------------------------------------------------------------------------------- /linux/410file.mu: -------------------------------------------------------------------------------- 1 | fn read-lines in: (addr buffered-file), out: (addr handle array (handle array byte)) { 2 | var stream: (stream (handle array byte) 0x10) 3 | var stream-a/edi: (addr stream (handle array byte)) <- address stream 4 | var line: (stream byte 0x10) 5 | var line-a/esi: (addr stream byte) <- address line 6 | { 7 | clear-stream line-a 8 | read-line-buffered in, line-a 9 | var done?/eax: boolean <- stream-empty? line-a 10 | compare done?, 0/false 11 | break-if-!= 12 | #? print-string 0, "AAA\n" 13 | var h: (handle array byte) 14 | var ah/eax: (addr handle array byte) <- address h 15 | stream-to-array line-a, ah 16 | write-to-stream stream-a, ah 17 | loop 18 | } 19 | stream-to-array stream-a, out 20 | } 21 | -------------------------------------------------------------------------------- /archive/1.vm/cannot_write_tests_for: -------------------------------------------------------------------------------- 1 | 0. main's ingredients 2 | 1. assertion failures or errors inside scenarios 3 | 2. screen background color 4 | 3. has-more-events? 5 | 4. hide/show screen 6 | 5. more touch event types 7 | 6. sandbox isolation 8 | 7. errors in reading/writing files (missing directory, others?) 9 | 10 | termbox issues are implementation-specific and not worth testing: 11 | whether we clear junk from other processes 12 | latency in interpreting low-level escape characters 13 | 14 | calls to update-cursor are currently duplicated: 15 | render-all calls update-cursor to simplify testing 16 | event-loop needs to call update-cursor explicitly to backstop branches doing their own minimal rendering 17 | solution: update-cursor after minimal rendering 18 | -------------------------------------------------------------------------------- /archive/2.transect/compiler2: -------------------------------------------------------------------------------- 1 | to dereference a heap allocation 2 | copy handle to stack 3 | perform lookup to stack 4 | 5 | lookup x in *(ESP+4) of type (handle T) 6 | 7 | reg <- copy *(ESP+5) : (address T stack) 8 | payload alloc id <- copy *reg 9 | address alloc id <- copy *(ESP+4) 10 | compare payload alloc id, address alloc id 11 | jump if not equal to print stack trace and panic 12 | address <- add reg, 1 13 | 14 | types: 15 | 16 | address T reg 17 | address T stack 18 | address T heap 19 | address T global 20 | 21 | copy down this spectrum is not permitted, but up is. 22 | 23 | addresses aren't allowed in types, globals and on the heap. Only handles. 24 | addresses are only for temporary manipulations. 25 | 26 | 27 | *(address T) <- copy T 28 | -------------------------------------------------------------------------------- /archive/1.vm/display.mu: -------------------------------------------------------------------------------- 1 | # example program: managing the display 2 | 3 | def main [ 4 | open-console 5 | clear-display 6 | print-character-to-display 97, 1/red, 2/green 7 | 1:num/raw, 2:num/raw <- cursor-position-on-display 8 | wait-for-some-interaction 9 | clear-line-on-display 10 | move-cursor-on-display 0, 4 11 | print-character-to-display 98 12 | wait-for-some-interaction 13 | move-cursor-on-display 0, 0 14 | clear-line-on-display 15 | wait-for-some-interaction 16 | move-cursor-down-on-display 17 | wait-for-some-interaction 18 | move-cursor-right-on-display 19 | wait-for-some-interaction 20 | move-cursor-left-on-display 21 | wait-for-some-interaction 22 | move-cursor-up-on-display 23 | wait-for-some-interaction 24 | close-console 25 | ] 26 | -------------------------------------------------------------------------------- /linux/bootstrap/tools/enumerate.cc: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | using std::vector; 6 | #include 7 | using std::string; 8 | #include 9 | using std::cout; 10 | 11 | int main(int argc, const char* argv[]) { 12 | assert(argc == 3); 13 | assert(string(argv[1]) == "--until"); 14 | string last_file(argv[2]); 15 | 16 | dirent** files; 17 | int num_files = scandir(".", &files, NULL, alphasort); 18 | for (int i = 0; i < num_files; ++i) { 19 | string curr_file = files[i]->d_name; 20 | if (!isdigit(curr_file.at(0))) continue; 21 | if (!last_file.empty() && curr_file > last_file) break; 22 | cout << curr_file << '\n'; 23 | } 24 | // don't bother freeing files 25 | return 0; 26 | } 27 | -------------------------------------------------------------------------------- /308allocate-array.subx: -------------------------------------------------------------------------------- 1 | # 2-arg version of allocate-array. 2 | # Really only intended to be called from code generated by mu.subx. 3 | 4 | == code 5 | 6 | allocate-array2: # ad: (addr allocation-descriptor), array-len: int, elem-size: int, out: (addr handle array _) 7 | # . prologue 8 | 55/push-ebp 9 | 89/<- %ebp 4/r32/esp 10 | # . save registers 11 | 50/push-eax 12 | 52/push-edx 13 | # 14 | 8b/-> *(ebp+0xc) 0/r32/eax 15 | f7 4/subop/multiply-into-edx-eax *(ebp+0x10) 16 | # TODO: check edx for overflow 17 | (allocate-array *(ebp+8) %eax *(ebp+0x14)) 18 | $allocate-array2:end: 19 | # . restore registers 20 | 5a/pop-to-edx 21 | 58/pop-to-eax 22 | # . epilogue 23 | 89/<- %esp 5/r32/ebp 24 | 5d/pop-to-ebp 25 | c3/return 26 | -------------------------------------------------------------------------------- /linux/308allocate-array.subx: -------------------------------------------------------------------------------- 1 | # 2-arg version of allocate-array. 2 | # Really only intended to be called from code generated by mu.subx. 3 | 4 | == code 5 | 6 | allocate-array2: # ad: (addr allocation-descriptor), array-len: int, elem-size: int, out: (addr handle array _) 7 | # . prologue 8 | 55/push-ebp 9 | 89/<- %ebp 4/r32/esp 10 | # . save registers 11 | 50/push-eax 12 | 52/push-edx 13 | # 14 | 8b/-> *(ebp+0xc) 0/r32/eax 15 | f7 4/subop/multiply-into-edx-eax *(ebp+0x10) 16 | # TODO: check edx for overflow 17 | (allocate-array *(ebp+8) %eax *(ebp+0x14)) 18 | $allocate-array2:end: 19 | # . restore registers 20 | 5a/pop-to-edx 21 | 58/pop-to-eax 22 | # . epilogue 23 | 89/<- %esp 5/r32/ebp 24 | 5d/pop-to-ebp 25 | c3/return 26 | -------------------------------------------------------------------------------- /editor/atom/styles/styles.less: -------------------------------------------------------------------------------- 1 | atom-text-editor.editor { 2 | .syntax--source.syntax--subx { 3 | .syntax--header-comment.syntax--subx { 4 | color: #ccccff; 5 | } 6 | .syntax--comment-sub-1.syntax--subx { 7 | color: #888888; 8 | } 9 | .syntax--comment-sub-2.syntax--subx { 10 | color: #666666; 11 | } 12 | .syntax--comment.syntax--subx { 13 | color: #8888ff; 14 | } 15 | .syntax--strings.syntax--subx { 16 | color: cyan; 17 | } 18 | .syntax--function.syntax--subx { 19 | color: orange; 20 | } 21 | .syntax--global.syntax--subx { 22 | color: red; 23 | } 24 | .syntax--test.syntax--subx { 25 | color: #88ff88; 26 | } 27 | .syntax--label.syntax--subx { 28 | color: #448844; 29 | } 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /linux/apps/raytracing/1.mu: -------------------------------------------------------------------------------- 1 | # Listing 1 of https://raytracing.github.io/books/RayTracingInOneWeekend.html 2 | # (simplified) 3 | # 4 | # To run (on Linux): 5 | # $ git clone https://github.com/akkartik/mu 6 | # $ cd mu/linux 7 | # $ ./translate apps/raytracing/1.mu 8 | # $ ./a.elf > 1.ppm 9 | 10 | fn main -> _/ebx: int { 11 | print-string 0, "P3\n256 256\n255\n" 12 | var j/ecx: int <- copy 0xff 13 | { 14 | compare j, 0 15 | break-if-< 16 | var i/eax: int <- copy 0 17 | { 18 | compare i, 0xff 19 | break-if-> 20 | print-int32-decimal 0, i 21 | print-string 0, " " 22 | print-int32-decimal 0, j 23 | print-string 0, " 64\n" 24 | i <- increment 25 | loop 26 | } 27 | j <- decrement 28 | loop 29 | } 30 | return 0 31 | } 32 | -------------------------------------------------------------------------------- /archive/1.vm/filesystem.mu: -------------------------------------------------------------------------------- 1 | # example program: copy one file into another, character by character 2 | # BEWARE: this will modify your file system 3 | # before running it, put some text into /tmp/mu-x 4 | # after running it, check /tmp/mu-y 5 | 6 | def main [ 7 | local-scope 8 | source-file:&:source:char <- start-reading null/real-filesystem, [/tmp/mu-x] 9 | sink-file:&:sink:char, write-routine:num <- start-writing null/real-filesystem, [/tmp/mu-y] 10 | { 11 | c:char, done?:bool, source-file <- read source-file 12 | break-if done? 13 | sink-file <- write sink-file, c 14 | loop 15 | } 16 | close sink-file 17 | # make sure to wait for the file to be actually written to disk 18 | # (Mu practices structured concurrency: http://250bpm.com/blog:71) 19 | wait-for-routine write-routine 20 | ] 21 | -------------------------------------------------------------------------------- /linux/tile/README.md: -------------------------------------------------------------------------------- 1 | A programming environment that tries to [“stop drawing dead fish”](http://worrydream.com/#!/StopDrawingDeadFish). 2 | 3 | screenshot 4 | 5 | To run: 6 | 7 | ``` 8 | $ cd linux 9 | $ ./translate tile/*.mu 10 | $ ./a.elf screen 11 | ``` 12 | 13 | To run tests: 14 | 15 | ``` 16 | $ ./a.elf test 17 | ``` 18 | 19 | To run a conventional REPL (for debugging): 20 | 21 | ``` 22 | $ ./a.elf type 23 | ``` 24 | 25 | ## hacking 26 | 27 | This is just a prototype. There are no tests. 28 | 29 | To add a new primitive you'll need to hard-code it into the `evaluate` 30 | function (linux/tile/rpn.mu). 31 | 32 | There's also a second place you'll want to teach about predefined primitives: 33 | `bound-function?` (linux/tile/environment.mu) 34 | -------------------------------------------------------------------------------- /linux/apps/raytracing/ray.mu: -------------------------------------------------------------------------------- 1 | type ray { 2 | orig: vec3 # point 3 | dir: vec3 4 | } 5 | 6 | # A little different from the constructor at https://raytracing.github.io/books/RayTracingInOneWeekend.html 7 | # We immediately normalize the direction vector so we don't have to keep doing 8 | # so. 9 | fn initialize-ray _self: (addr ray), o: (addr vec3), d: (addr vec3) { 10 | var self/esi: (addr ray) <- copy _self 11 | var dest/eax: (addr vec3) <- get self, orig 12 | copy-object o, dest 13 | dest <- get self, dir 14 | vec3-unit d, dest 15 | } 16 | 17 | fn ray-at _self: (addr ray), t: float, out: (addr vec3) { 18 | var self/esi: (addr ray) <- copy _self 19 | var src/eax: (addr vec3) <- get self, dir 20 | copy-object src, out 21 | vec3-scale-up out, t 22 | src <- get self, orig 23 | vec3-add-to out, src 24 | } 25 | -------------------------------------------------------------------------------- /archive/1.vm/http-client.mu: -------------------------------------------------------------------------------- 1 | # example program: reading a URL over HTTP 2 | 3 | def main [ 4 | local-scope 5 | $print [aaa] 10/newline 6 | google:&:source:char <- start-reading-from-network null/real-resources, [google.com/] 7 | $print [bbb] 10/newline 8 | n:num <- copy 0 9 | buf:&:buffer:char <- new-buffer 30 10 | { 11 | c:char, done?:bool <- read google 12 | break-if done? 13 | n <- add n, 1 14 | buf <- append buf, c 15 | { 16 | _, a:num <- divide-with-remainder n, 100 17 | break-if a 18 | $print n 10/newline 19 | } 20 | loop 21 | } 22 | result:text <- buffer-to-array buf 23 | open-console 24 | clear-screen null/screen # non-scrolling app 25 | len:num <- length *result 26 | print null/real-screen, result 27 | wait-for-some-interaction 28 | close-console 29 | ] 30 | -------------------------------------------------------------------------------- /tools/test_treeshake_translate: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # Translate SubX programs using a minified translator. 3 | # Based on ntranslate. 4 | 5 | set -e 6 | 7 | ./build 8 | 9 | cat $* |apps/braces.treeshake.bin > a.braces 10 | 11 | cat a.braces |apps/calls.treeshake.bin > a.calls 12 | 13 | cat a.calls |apps/sigils.treeshake.bin > a.sigils 14 | 15 | cat a.sigils |apps/tests.treeshake.bin > a.tests 16 | 17 | cat a.tests |apps/assort.treeshake.bin > a.assort 18 | 19 | cat a.assort |apps/dquotes.treeshake.bin > a.dquotes 20 | 21 | cat a.dquotes |apps/assort.treeshake.bin > a.assort2 22 | 23 | cat a.assort2 |apps/pack.treeshake.bin > a.pack 24 | 25 | cat a.pack |apps/survey.treeshake.bin > a.survey 26 | 27 | cat a.survey |apps/hex.treeshake.bin > a.elf 28 | 29 | chmod +x a.elf 30 | -------------------------------------------------------------------------------- /apps/ex12.mu: -------------------------------------------------------------------------------- 1 | # Checking the timer. 2 | # 3 | # To build a disk image: 4 | # ./translate apps/ex12.mu # emits code.img 5 | # To run: 6 | # qemu-system-i386 code.img 7 | # 8 | # Expected output: text with slowly updating colors 9 | 10 | fn main screen: (addr screen), keyboard: (addr keyboard), data-disk: (addr disk) { 11 | var fg/ecx: int <- copy 0 12 | var prev-timer-counter/edx: int <- copy 0 13 | { 14 | var dummy/eax: int <- draw-text-rightward screen, "hello from baremetal Mu!", 0x10/x, 0x400/xmax, 0x10/y, fg, 0/bg 15 | # wait for timer to bump 16 | { 17 | var curr-timer-counter/eax: int <- timer-counter 18 | compare curr-timer-counter, prev-timer-counter 19 | loop-if-= 20 | prev-timer-counter <- copy curr-timer-counter 21 | } 22 | # switch color 23 | fg <- increment 24 | loop 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /503manhattan-line.mu: -------------------------------------------------------------------------------- 1 | fn draw-box-on-real-screen x1: int, y1: int, x2: int, y2: int, color: int { 2 | draw-horizontal-line-on-real-screen x1, x2, y1, color 3 | draw-vertical-line-on-real-screen x1, y1, y2, color 4 | draw-horizontal-line-on-real-screen x1, x2, y2, color 5 | draw-vertical-line-on-real-screen x2, y1, y2, color 6 | } 7 | 8 | fn draw-horizontal-line-on-real-screen x1: int, x2: int, y: int, color: int { 9 | var x/eax: int <- copy x1 10 | { 11 | compare x, x2 12 | break-if->= 13 | pixel-on-real-screen x, y, color 14 | x <- increment 15 | loop 16 | } 17 | } 18 | 19 | fn draw-vertical-line-on-real-screen x: int, y1: int, y2: int, color: int { 20 | var y/eax: int <- copy y1 21 | { 22 | compare y, y2 23 | break-if->= 24 | pixel-on-real-screen x, y, color 25 | y <- increment 26 | loop 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /linux/apps/raytracing/1.cc.0: -------------------------------------------------------------------------------- 1 | // https://raytracing.github.io/books/RayTracingInOneWeekend.html 2 | #include 3 | 4 | int main() { 5 | 6 | // Image 7 | 8 | const int image_width = 256; 9 | const int image_height = 256; 10 | 11 | // Render 12 | 13 | std::cout << "P3\n" << image_width << ' ' << image_height << "\n255\n"; 14 | 15 | for (int j = image_height-1; j >= 0; --j) { 16 | for (int i = 0; i < image_width; ++i) { 17 | auto r = double(i) / (image_width-1); 18 | auto g = double(j) / (image_height-1); 19 | auto b = 0.25; 20 | 21 | int ir = static_cast(255.999 * r); 22 | int ig = static_cast(255.999 * g); 23 | int ib = static_cast(255.999 * b); 24 | 25 | std::cout << ir << ' ' << ig << ' ' << ib << '\n'; 26 | } 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /apps/ex3.mu: -------------------------------------------------------------------------------- 1 | # Draw pixels in response to keyboard events, starting from the top-left 2 | # and in raster order. 3 | # 4 | # To build a disk image: 5 | # ./translate apps/ex3.mu # emits code.img 6 | # To run: 7 | # qemu-system-i386 code.img 8 | # 9 | # Expected output: a new green pixel starting from the top left corner of the 10 | # screen every time you press a key (letter or digit) 11 | 12 | fn main screen: (addr screen), keyboard: (addr keyboard), data-disk: (addr disk) { 13 | var x/ecx: int <- copy 0 14 | var y/edx: int <- copy 0 15 | { 16 | var key/eax: byte <- read-key keyboard 17 | compare key, 0 18 | loop-if-= # busy wait 19 | pixel-on-real-screen x, y, 0x31/green 20 | x <- increment 21 | compare x, 0x400/screen-width=1024 22 | { 23 | break-if-< 24 | y <- increment 25 | x <- copy 0 26 | } 27 | loop 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /archive/2.transect/ex4.k2: -------------------------------------------------------------------------------- 1 | ## read a character from stdin, save it to a global, write it to stdout 2 | 3 | # variables are always references 4 | # read their address with their names: x (can't write to their address) 5 | # read/write their contents with a lookup: *x 6 | var x : char 7 | 8 | fn main [ 9 | call read 0/stdin, x, 1/size 10 | result/EAX <- call write 1/stdout, x, 1/size 11 | call exit, result/EAX 12 | ] 13 | 14 | fn read fd : int, x : (address array byte), size : int [ 15 | EBX <- copy fd 16 | ECX <- copy x 17 | EDX <- copy size 18 | EAX <- copy 3/read 19 | syscall 20 | ] 21 | 22 | fn write fd : int, x : (address array byte), size : int [ 23 | EBX <- copy fd 24 | ECX <- copy x 25 | EDX <- copy size 26 | EAX <- copy 4/write 27 | syscall 28 | ] 29 | 30 | fn exit x : int [ 31 | code/EBX <- copy x 32 | code/EAX <- copy 1/exit 33 | syscall 34 | ] 35 | -------------------------------------------------------------------------------- /archive/0.vm.arc/edit.mu: -------------------------------------------------------------------------------- 1 | ; a screen is an array of pointers to lines, in turn arrays of characters 2 | 3 | (function new-screen [ 4 | (default-space:space-address <- new space:literal 30:literal) 5 | (nrows:integer <- next-input) 6 | (ncols:integer <- next-input) 7 | (result:screen-address <- new screen:literal nrows:integer) 8 | (rowidx:integer <- copy 0:literal) 9 | { begin 10 | (curr-line-address-address:line-address-address <- index-address result:screen-address/deref rowidx:integer) 11 | (curr-line-address-address:line-address-address/deref <- new line:literal ncols:integer) 12 | (curr-line-address:line-address <- copy curr-line-address-address:line-address-address/deref) 13 | (rowidx:integer <- add rowidx:integer 1:literal) 14 | (x:boolean <- not-equal rowidx:integer nrows:integer) 15 | (loop-if x:boolean) 16 | } 17 | (reply result:screen-address) 18 | ]) 19 | -------------------------------------------------------------------------------- /archive/1.vm/continuation3.mu: -------------------------------------------------------------------------------- 1 | # Example program showing that a function call can be 'paused' multiple times, 2 | # creating different continuation values. 3 | # 4 | # To run: 5 | # $ git clone https://github.com/akkartik/mu 6 | # $ cd mu 7 | # $ ./mu continuation3.mu 8 | # 9 | # Expected output: 10 | # caller 0 11 | # callee 0 12 | # caller 1 13 | # callee 1 14 | # caller 2 15 | # callee 2 16 | 17 | def main [ 18 | local-scope 19 | $print [caller 0] 10/newline 20 | k:continuation <- call-with-continuation-mark 100/mark, f 21 | $print [caller 1] 10/newline 22 | k <- call k 23 | $print [caller 2] 10/newline 24 | call k 25 | ] 26 | 27 | def f [ 28 | local-scope 29 | $print [callee 0] 10/newline 30 | return-continuation-until-mark 100/mark 31 | $print [callee 1] 10/newline 32 | return-continuation-until-mark 100/mark 33 | $print [callee 2] 10/newline 34 | ] 35 | -------------------------------------------------------------------------------- /archive/0.vm.arc/load.arc: -------------------------------------------------------------------------------- 1 | ; support for dividing arc files into sections of different level, and 2 | ; selectively loading just sections at or less than a given level 3 | 4 | ; usage: 5 | ; load.arc [level] [arc files] -- [mu files] 6 | 7 | (def selective-load (file (o level 999)) 8 | ;? (prn "loading @file at level @level") 9 | (fromfile file 10 | (whilet expr (read) 11 | ;? (prn car.expr) 12 | (if (is 'section expr.0) 13 | (when (<= expr.1 level) 14 | (each x (cut expr 2) 15 | (eval x))) 16 | (eval expr)) 17 | ;? (prn car.expr " done") 18 | ))) 19 | 20 | (= section-level 999) 21 | (point break 22 | (each x (map [fromstring _ (read)] cdr.argv) 23 | (if (isa x 'int) 24 | (= section-level x) 25 | (is '-- x) 26 | (break) ; later args are mu files 27 | :else 28 | (selective-load string.x section-level)))) 29 | -------------------------------------------------------------------------------- /tutorial/task6-error-runbook.txt: -------------------------------------------------------------------------------- 1 | If I encounter an error that looks like this: 2 | fn main: stmt copy: output 'm' not in a register 3 | 4 | then I should do the following: 5 | - find the function mentioned (here `main`); 6 | - look for a statement that contains the mentioned output (here `m`) before 7 | the `<-`; and 8 | - replace the statement with a version of the same instruction that writes 9 | to an inout in memory. (Here, replace `m <- copy` with `copy-to m`.) 10 | 11 | === 12 | 13 | If I encounter an error that looks like this: 14 | label table: get-slice: key not found: copy-to 15 | 16 | then I should do the following: 17 | - look for a statement with the same instruction (here `copy-to`) whose 18 | first inout is not a variable stored in memory; and 19 | - email Kartik (http://akkartik.name/contact) to ask why this message is so 20 | much less helpful then the previous one. 21 | -------------------------------------------------------------------------------- /archive/1.vm/tangle.mu: -------------------------------------------------------------------------------- 1 | # example program: constructing functions out of order 2 | # 3 | # We construct a factorial function with separate base and recursive cases. 4 | # Compare factorial.mu. 5 | # 6 | # This isn't a very tasteful example, just a basic demonstration of 7 | # possibilities. 8 | 9 | def factorial n:num -> result:num [ 10 | local-scope 11 | load-inputs 12 | 13 | ] 14 | 15 | after [ 16 | # if n=0 return 1 17 | return-unless n, 1 18 | ] 19 | 20 | after [ 21 | # return n * factorial(n - 1) 22 | { 23 | break-unless n 24 | x:num <- subtract n, 1 25 | subresult:num <- factorial x 26 | result <- multiply subresult, n 27 | return result 28 | } 29 | ] 30 | 31 | def main [ 32 | 1:num <- factorial 5 33 | # trailing space in next line is to help with syntax highlighting 34 | $print [result: ], 1:num, [ 35 | ] 36 | ] 37 | -------------------------------------------------------------------------------- /linux/branches.mu: -------------------------------------------------------------------------------- 1 | fn foo { 2 | $foo: { 3 | break-if-= 4 | break-if-= $foo 5 | break-if-!= 6 | break-if-!= $foo 7 | break-if-<= 8 | break-if-<= $foo 9 | break-if->= 10 | break-if->= $foo 11 | break-if-< 12 | break-if-< $foo 13 | break-if-> 14 | break-if-> $foo 15 | break-if-carry 16 | break-if-carry $foo 17 | break-if-overflow 18 | break-if-overflow $foo 19 | loop-if-= 20 | loop-if-= $foo 21 | loop-if-!= 22 | loop-if-!= $foo 23 | loop-if-<= 24 | loop-if-<= $foo 25 | loop-if->= 26 | loop-if->= $foo 27 | loop-if-< 28 | loop-if-< $foo 29 | loop-if-> 30 | loop-if-> $foo 31 | loop-if-carry 32 | loop-if-carry $foo 33 | loop-if-not-carry 34 | loop-if-not-carry $foo 35 | loop-if-overflow 36 | loop-if-overflow $foo 37 | loop-if-not-overflow 38 | loop-if-not-overflow $foo 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /linux/406int32.mu: -------------------------------------------------------------------------------- 1 | # Some slow but convenient helpers 2 | 3 | # slow, iterative shift-left instruction 4 | # preconditions: _nr >= 0, _dr > 0 5 | fn repeated-shift-left nr: int, dr: int -> _/eax: int { 6 | var result/eax: int <- copy nr 7 | { 8 | compare dr, 0 9 | break-if-<= 10 | result <- shift-left 1 11 | decrement dr 12 | loop 13 | } 14 | return result 15 | } 16 | 17 | # slow, iterative shift-right instruction 18 | # preconditions: _nr >= 0, _dr > 0 19 | fn repeated-shift-right nr: int, dr: int -> _/eax: int { 20 | var result/eax: int <- copy nr 21 | { 22 | compare dr, 0 23 | break-if-<= 24 | result <- shift-right 1 25 | decrement dr 26 | loop 27 | } 28 | return result 29 | } 30 | 31 | fn abs n: int -> _/eax: int { 32 | var result/eax: int <- copy n 33 | { 34 | compare n, 0 35 | break-if->= 36 | result <- negate 37 | } 38 | return result 39 | } 40 | -------------------------------------------------------------------------------- /archive/1.vm/continuation2.mu: -------------------------------------------------------------------------------- 1 | # Example program showing that a 'paused' continuation can be 'resumed' 2 | # multiple times from the same point (but with changes to data). 3 | # 4 | # To run: 5 | # $ git clone https://github.com/akkartik/mu 6 | # $ cd mu 7 | # $ ./mu continuation2.mu 8 | # 9 | # Expected output: 10 | # 1 11 | # 2 12 | # 3 13 | 14 | def main [ 15 | local-scope 16 | l:&:list:num <- copy null 17 | l <- push 3, l 18 | l <- push 2, l 19 | l <- push 1, l 20 | k:continuation <- call-with-continuation-mark 100/mark, create-yielder, l 21 | { 22 | x:num, done?:bool <- call k 23 | break-if done? 24 | $print x 10/newline 25 | loop 26 | } 27 | ] 28 | 29 | def create-yielder l:&:list:num -> n:num, done?:bool [ 30 | local-scope 31 | load-inputs 32 | return-continuation-until-mark 100/mark 33 | done? <- equal l, null 34 | return-if done?, 0/dummy 35 | n <- first l 36 | l <- rest l 37 | ] 38 | -------------------------------------------------------------------------------- /shell/read.mu: -------------------------------------------------------------------------------- 1 | fn read-cell in: (addr gap-buffer), out: (addr handle cell), trace: (addr trace) { 2 | # eagerly tokenize everything so that the phases are easier to see in the trace 3 | var tokens-storage: (stream token 0x10000) 4 | var tokens/edx: (addr stream token) <- address tokens-storage 5 | tokenize in, tokens, trace 6 | var error?/eax: boolean <- has-errors? trace 7 | compare error?, 0/false 8 | { 9 | break-if-= 10 | return 11 | } 12 | # insert more parens based on indentation 13 | var parenthesized-tokens-storage: (stream token 0x10000) 14 | var parenthesized-tokens/ecx: (addr stream token) <- address parenthesized-tokens-storage 15 | parenthesize tokens, parenthesized-tokens, trace 16 | var error?/eax: boolean <- has-errors? trace 17 | compare error?, 0/false 18 | { 19 | break-if-= 20 | return 21 | } 22 | parse-input parenthesized-tokens, out, trace 23 | transform-infix out, trace 24 | } 25 | -------------------------------------------------------------------------------- /archive/1.vm/058to_text.cc: -------------------------------------------------------------------------------- 1 | //: Primitive to convert any type to text (array of characters). 2 | //: Later layers will allow us to override this to do something smarter for 3 | //: specific types. 4 | 5 | :(before "End Primitive Recipe Declarations") 6 | TO_TEXT, 7 | :(before "End Primitive Recipe Numbers") 8 | put(Recipe_ordinal, "to-text", TO_TEXT); 9 | :(before "End Primitive Recipe Checks") 10 | case TO_TEXT: { 11 | if (SIZE(inst.ingredients) != 1) { 12 | raise << maybe(get(Recipe, r).name) << "'to-text' requires a single ingredient, but got '" << to_original_string(inst) << "'\n" << end(); 13 | break; 14 | } 15 | // can handle any type 16 | break; 17 | } 18 | :(before "End Primitive Recipe Implementations") 19 | case TO_TEXT: { 20 | products.resize(1); 21 | products.at(0).push_back(/*alloc id*/0); 22 | products.at(0).push_back(new_mu_text(inspect(current_instruction().ingredients.at(0), ingredients.at(0)))); 23 | break; 24 | } 25 | -------------------------------------------------------------------------------- /linux/apps/ex4.subx: -------------------------------------------------------------------------------- 1 | # Read a character from stdin, save it to a global, write it to stdout. 2 | # 3 | # To run: 4 | # $ ./translate_subx 000init.subx apps/ex4.subx 5 | # $ ./a.elf 6 | 7 | == data 8 | 9 | # the global variable we save to 10 | X: 11 | 0/imm32 # space for read() to write to 12 | 13 | == code 14 | 15 | Entry: 16 | # read(stdin, X, 1) 17 | # . fd = 0 (stdin) 18 | bb/copy-to-ebx 0/imm32 19 | # . data = X (location to write result to) 20 | b9/copy-to-ecx X/imm32 21 | # . size = 1 character 22 | ba/copy-to-edx 1/imm32 23 | # . syscall 24 | e8/call syscall_read/disp32 25 | 26 | # write(stdout, X, 1) 27 | # . fd = 1 (stdout) 28 | bb/copy-to-ebx 1/imm32 29 | # . initialize X (location to read from) 30 | b9/copy-to-ecx X/imm32 31 | # . size = 1 character 32 | ba/copy-to-edx 1/imm32 33 | # . syscall 34 | e8/call syscall_write/disp32 35 | 36 | # exit(ebx) 37 | e8/call syscall_exit/disp32 38 | 39 | # . . vim:nowrap:textwidth=0 40 | -------------------------------------------------------------------------------- /apps/ex14.mu: -------------------------------------------------------------------------------- 1 | # Unicode demo 2 | # 3 | # Mu can't read Unicode from keyboard yet, so we'll read utf-8 from disk and 4 | # print to screen. 5 | # 6 | # Steps for trying it out: 7 | # 1. Translate this example into a disk image code.img. 8 | # ./translate apps/ex14.mu 9 | # 2. Build a second disk image data.img containing some Unicode text. 10 | # dd if=/dev/zero of=data.img count=20160 11 | # echo 'நட' |dd of=data.img conv=notrunc 12 | # 3. Run: 13 | # qemu-system-i386 -hda code.img -hdb data.img 14 | # 15 | # Expected output: 'நட' in green near the top-left corner of screen 16 | 17 | fn main screen: (addr screen), keyboard: (addr keyboard), data-disk: (addr disk) { 18 | var text-storage: (stream byte 0x200) 19 | var text/esi: (addr stream byte) <- address text-storage 20 | load-sectors data-disk, 0/lba, 1/num-sectors, text 21 | var dummy/eax: int <- draw-stream-rightward screen, text, 0/x 0x80/xmax 0/y, 0xa/fg, 0/bg 22 | } 23 | -------------------------------------------------------------------------------- /linux/300.txt: -------------------------------------------------------------------------------- 1 | Layers in the 3xx series use all the available syntax sugar for SubX programs. 2 | Functions here can be called from Mu programs if they meet certain criteria: 3 | 4 | - There's a signature for them in 400.mu 5 | - Inouts on the stack, outputs in registers 6 | - Valid Mu types everywhere (Mu's type system isn't expressive enough for 7 | everything SubX does in rare situations.) 8 | - No way to for an `addr` to escape a function. No `(... addr ... addr ...)` 9 | inouts, and no `(... addr ...)` outputs. 10 | 11 | While functions _can_ be called, not all SubX functions meeting these criteria 12 | _should_ be called. In particular, avoid exporting functions that could be 13 | misused. A classic example is trying to add a `size-of` operator. If you're 14 | doing that you're likely going to rely on programmers to use it correctly. Mu 15 | tries to be idiot-proof. Even if SubX requires greater care, using SubX 16 | primitives from Mu should not. 17 | -------------------------------------------------------------------------------- /apps/ex13.mu: -------------------------------------------------------------------------------- 1 | # Load an image from disk and display it on screen. 2 | # 3 | # Build the code disk: 4 | # $ ./translate apps/ex13.mu # generates code.img 5 | # Load a pbm, pgm or ppm image (no more than 255 levels) in the data disk 6 | # $ dd if=/dev/zero of=data.img count=20160 7 | # $ dd if=___ of=data.img conv=notrunc 8 | # Run: 9 | # $ qemu-system-i386 -hda code.img -hdb data.img 10 | 11 | fn main screen: (addr screen), keyboard: (addr keyboard), data-disk: (addr disk) { 12 | var img-storage: image 13 | var img/esi: (addr image) <- address img-storage 14 | load-image img, data-disk 15 | render-image screen, img, 0/x, 0/y, 0x300/width, 0x300/height 16 | } 17 | 18 | fn load-image self: (addr image), data-disk: (addr disk) { 19 | var s-storage: (stream byte 0x200000) # 512 * 0x1000 sectors 20 | var s/ebx: (addr stream byte) <- address s-storage 21 | load-sectors data-disk, 0/lba, 0x1000/sectors, s 22 | initialize-image self, s 23 | } 24 | -------------------------------------------------------------------------------- /misc_checks: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # Hackily check for certain kinds of errors. 3 | # 4 | # We still rely exclusively on linux/bootstrap/bootstrap for some static 5 | # checks on bare SubX code that aren't implemented yet in the self-hosted 6 | # translator phases. 7 | # 8 | # However, boot.subx uses instructions that bootstrap doesn't recognize. So we 9 | # won't check it. 10 | 11 | set -e 12 | 13 | cat $* [0-9]*.mu |linux/mu > a.subx 14 | 15 | cat misc_checks.subx mu-init.subx [0-9]*.subx a.subx |linux/braces > a.braces 16 | cat a.braces |linux/calls > a.calls 17 | cat a.calls |linux/sigils > a.sigils 18 | 19 | CXXFLAGS=-g linux/bootstrap/bootstrap --debug translate a.sigils -o a.elf 20 | # Translation will never succeed, 21 | # but if we get to "missing reference to global" errors, they're expected and 22 | # we've gotten to the end of what bootstrap can check for us. 23 | -------------------------------------------------------------------------------- /archive/0.vm.arc/graphics.mu: -------------------------------------------------------------------------------- 1 | ; open a viewport, print coordinates of mouse clicks 2 | ; currently need to ctrl-c to exit after closing the viewport 3 | (function main [ 4 | (window-on (("practice" literal)) 300:literal 300:literal) 5 | { begin 6 | (pos:integer-integer-pair click?:boolean <- mouse-position) 7 | (loop-unless click?:boolean) 8 | (x:integer <- get pos:integer-integer-pair 0:offset) 9 | (y:integer <- get pos:integer-integer-pair 1:offset) 10 | ;? ($print (("AAA " literal))) 11 | ;? ($print x:integer) 12 | ;? ($print ((", " literal))) 13 | ;? ($print y:integer) 14 | ;? ($print (("\n" literal))) 15 | (print-integer nil:literal/terminal x:integer) 16 | (print-character nil:literal/terminal ((#\, literal))) 17 | (print-character nil:literal/terminal ((#\space literal))) 18 | (print-integer nil:literal/terminal y:integer) 19 | (print-character nil:literal/terminal ((#\newline literal))) 20 | (loop) 21 | } 22 | (window-off) 23 | ]) 24 | -------------------------------------------------------------------------------- /archive/1.vm/counters.mu: -------------------------------------------------------------------------------- 1 | # example program: maintain multiple counters with isolated lexical scopes 2 | # (spaces) 3 | 4 | def new-counter n:num -> default-space:space [ 5 | default-space <- new location:type, 30 6 | load-inputs # initialize n 7 | ] 8 | 9 | def increment-counter outer:space/names:new-counter, x:num -> n:num/space:1 [ 10 | local-scope 11 | load-inputs 12 | 0:space/names:new-counter <- copy outer # setup outer space; it *must* come from 'new-counter' 13 | n/space:1 <- add n/space:1, x 14 | ] 15 | 16 | def main [ 17 | local-scope 18 | # counter A 19 | a:space/names:new-counter <- new-counter 34 20 | # counter B 21 | b:space/names:new-counter <- new-counter 23 22 | # increment both by 2 but in different ways 23 | increment-counter a, 1 24 | b-value:num <- increment-counter b, 2 25 | a-value:num <- increment-counter a, 1 26 | # check results 27 | $print [Contents of counters], 10/newline 28 | $print [a: ], a-value, [ b: ], b-value, 10/newline 29 | ] 30 | -------------------------------------------------------------------------------- /editor/editor.md: -------------------------------------------------------------------------------- 1 | ## Getting your editor set up 2 | 3 | If you've read this far, it's time to set up your editor. Mu is really 4 | intended to be read interactively rather than on a browser. 5 | 6 | There is rudimentary syntax highlighting support for Mu and SubX files for 7 | various editors. Look for your editor in `mu.*` and `subx.*`, and follow the 8 | instructions within. 9 | 10 | The Vim files are most developed. In particular, I recommend some optional 11 | setup in subx.vim to use multiple colors for comments. 12 | 13 | If you use [`ctags`](http://ctags.sourceforge.net) for jumping easily 14 | from names to their definitions in your editor, set it up to load `mu.ctags`. 15 | For classic Exuberant Ctags, copy it into `~/.ctags`. For the newer Universal 16 | Ctags, copy it into `~/.ctags.d/mu.ctags`. 17 | 18 | [Here](https://lobste.rs/s/qglfdp/subx_minimalist_assembly_language_for#c_o9ddqk) 19 | are some tips on my setup for quickly finding the right opcode for any 20 | situation from within Vim. 21 | -------------------------------------------------------------------------------- /archive/1.vm/screen.mu: -------------------------------------------------------------------------------- 1 | # example program: managing the display using 'screen' objects 2 | 3 | # The zero screen below means 'use the real screen'. Tests can also use fake 4 | # screens. 5 | def main [ 6 | open-console 7 | clear-screen null/screen # non-scrolling app 8 | 10:char <- copy 97/a 9 | print null/screen, 10:char/a, 1/red, 2/green 10 | 1:num/raw, 2:num/raw <- cursor-position null/screen 11 | wait-for-event null/console 12 | clear-screen null/screen 13 | move-cursor null/screen, 0/row, 4/column 14 | 10:char <- copy 98/b 15 | print null/screen, 10:char 16 | wait-for-event null/console 17 | move-cursor null/screen, 0/row, 0/column 18 | clear-line null/screen 19 | wait-for-event null/console 20 | cursor-down null/screen 21 | wait-for-event null/console 22 | cursor-right null/screen 23 | wait-for-event null/console 24 | cursor-left null/screen 25 | wait-for-event null/console 26 | cursor-up null/screen 27 | wait-for-event null/console 28 | close-console 29 | ] 30 | -------------------------------------------------------------------------------- /linux/apps/ex14.subx: -------------------------------------------------------------------------------- 1 | # Multiply 2 numbers. 2 | # 3 | # To run: 4 | # $ ./translate_subx 000init.subx apps/ex14.subx 5 | # $ ./a.elf 6 | # Expected result: 7 | # $ echo $? 8 | # 6 9 | 10 | == code 11 | # instruction effective address register displacement immediate 12 | # . op subop mod rm32 base index scale r32 13 | # . 1-3 bytes 3 bits 2 bits 3 bits 3 bits 3 bits 2 bits 2 bits 0/1/2/4 bytes 0/1/2/4 bytes 14 | 15 | Entry: 16 | b8/copy-to-eax 1/imm32 17 | b9/copy-to-ecx 2/imm32 18 | bb/copy-to-ebx 3/imm32 19 | 20 | 69/multiply 3/mod/direct 1/rm32/ecx . . . 3/r32/ebx 3/imm32 # ebx = ecx * 3 21 | 22 | $exit: 23 | # exit(ebx) 24 | e8/call syscall_exit/disp32 25 | 26 | # . . vim:nowrap:textwidth=0 27 | -------------------------------------------------------------------------------- /mu-init.subx: -------------------------------------------------------------------------------- 1 | # Initialize the minimal runtime for Mu programs. 2 | # 3 | # See translate for how this file is used. 4 | # 5 | # Mu programs start at a function called 'main' with this signature: 6 | # fn main screen: (addr screen), keyboard: (addr keyboard), data-disk: (addr disk) 7 | # 8 | # All tests must pass first (the "power-on unit test"). 9 | 10 | == code 11 | 12 | Entry: 13 | # initialize stack 14 | bd/copy-to-ebp 0/imm32 15 | # 16 | #? (main 0 0 Primary-bus-secondary-drive) 17 | # always first run tests 18 | (run-tests) 19 | (num-test-failures) # => eax 20 | # call main if tests all passed 21 | { 22 | 3d/compare-eax-and 0/imm32 23 | 75/jump-if-!= break/disp8 24 | c7 0/subop/copy *Running-tests? 0/imm32/false 25 | (clear-real-screen) 26 | c7 0/subop/copy *Real-screen-cursor-x 0/imm32 27 | c7 0/subop/copy *Real-screen-cursor-y 0/imm32 28 | (main 0 0 Primary-bus-secondary-drive) 29 | } 30 | 31 | # hang indefinitely 32 | { 33 | eb/jump loop/disp8 34 | } 35 | -------------------------------------------------------------------------------- /archive/2.transect/ex8.k2: -------------------------------------------------------------------------------- 1 | # Example reading commandline arguments: compute length of first arg. 2 | 3 | fn main argc : int, argv : (array (ref array char)) -> [ 4 | var tmp : (index char) 5 | tmp <- index 1, %size(ref array char) 6 | var tmp2 : (address (ref array char)) 7 | tmp2 <- advance argv, tmp 8 | var s/EBX : (ref array char) 9 | s/EBX <- copy *tmp2 10 | var result/EAX : int 11 | result/EAX <- ascii_length s/EBX 12 | call exit, result/EAX 13 | ] 14 | 15 | fn ascii_length s : (ref array char) -> result : int [ 16 | var result/EBX : int 17 | result/EBX <- copy 0 18 | { 19 | var tmp0/EDI : (offset char) 20 | tmp0/EDI <- index result/EBX, %size(char) 21 | var tmp/EDX : (address char) 22 | tmp/EDX <- advance *s, tmp0/EDI 23 | var c/ECX : char 24 | c/ECX <- copy *tmp 25 | compare c/ECX, 0 26 | break-if-equal 27 | loop 28 | } 29 | return result/EBX 30 | ] 31 | 32 | fn exit x : int [ 33 | code/EBX <- copy x 34 | code/EAX <- copy 1/exit 35 | syscall 36 | ] 37 | -------------------------------------------------------------------------------- /archive/0.vm.arc/blocking.arc.t: -------------------------------------------------------------------------------- 1 | (selective-load "mu.arc" section-level) 2 | (set allow-raw-addresses*) 3 | 4 | (reset) 5 | (new-trace "blocking-example") 6 | (add-code 7 | '((function reader [ 8 | (default-space:space-address <- new space:literal 30:literal/capacity) 9 | (x:tagged-value 1:channel-address/space:global <- read 1:channel-address/space:global) 10 | ]) 11 | (function main [ 12 | (default-space:space-address <- new space:literal 30:literal/capacity) 13 | (1:channel-address <- init-channel 3:literal) 14 | (2:integer/routine <- fork-helper reader:fn default-space:space-address/globals 50:literal/limit) 15 | ; write nothing to the channel 16 | ;? (sleep until-routine-done:literal 2:integer/routine) 17 | ]))) 18 | ;? (= dump-trace* (obj whitelist '("schedule" "run"))) 19 | (run 'main) 20 | ;? (prn "completed:") 21 | ;? (each r completed-routines* 22 | ;? (prn " " r)) 23 | (when (ran-to-completion 'reader) 24 | (prn "F - reader waits for input")) 25 | 26 | (reset) 27 | -------------------------------------------------------------------------------- /linux/translate_subx_emulated: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # Translate given SubX files by running the self-hosted translator in emulated 3 | # mode on Linux or BSD or Mac. 4 | # 5 | # We _could_ generate traces here, but that's often extremely slow. 6 | 7 | set -e 8 | set -v 9 | 10 | cat $* |bootstrap/bootstrap run ./braces > a.braces 11 | cat a.braces |bootstrap/bootstrap run ./calls > a.calls 12 | cat a.calls |bootstrap/bootstrap run ./sigils > a.sigils 13 | cat a.sigils |bootstrap/bootstrap run ./tests > a.tests 14 | cat a.tests |bootstrap/bootstrap run ./assort > a.assort 15 | cat a.assort |bootstrap/bootstrap run ./dquotes > a.dquotes 16 | cat a.dquotes |bootstrap/bootstrap run ./assort > a.assort2 17 | cat a.assort2 |bootstrap/bootstrap run ./pack > a.pack 18 | cat a.pack |bootstrap/bootstrap run ./survey_elf > a.survey 19 | cat a.survey |bootstrap/bootstrap run ./hex > a.elf 20 | 21 | chmod +x a.elf 22 | -------------------------------------------------------------------------------- /506math.mu: -------------------------------------------------------------------------------- 1 | fn abs n: int -> _/eax: int { 2 | compare n, 0 3 | { 4 | break-if->= 5 | negate n 6 | } 7 | return n 8 | } 9 | 10 | fn sgn n: int -> _/eax: int { 11 | compare n, 0 12 | { 13 | break-if-<= 14 | return 1 15 | } 16 | { 17 | break-if->= 18 | return -1 19 | } 20 | return 0 21 | } 22 | 23 | fn shift-left-by n: int, bits: int -> _/eax: int { 24 | var i/eax: int <- copy bits 25 | { 26 | compare i, 0 27 | break-if-<= 28 | shift-left n, 1 29 | i <- decrement 30 | loop 31 | } 32 | return n 33 | } 34 | 35 | fn shift-right-by n: int, bits: int -> _/eax: int { 36 | var i/eax: int <- copy bits 37 | { 38 | compare i, 0 39 | break-if-<= 40 | shift-right n, 1 41 | i <- decrement 42 | loop 43 | } 44 | return n 45 | } 46 | 47 | fn clear-lowest-bits _n: (addr int), bits: int { 48 | var dest/edi: (addr int) <- copy _n 49 | var n/eax: int <- copy *dest 50 | n <- shift-right-by n, bits 51 | n <- shift-left-by n, bits 52 | copy-to *dest, n 53 | } 54 | -------------------------------------------------------------------------------- /archive/0.vm.arc/generic.mu: -------------------------------------------------------------------------------- 1 | ; To demonstrate generic functions, we'll construct a factorial function with 2 | ; separate base and recursive clauses. Compare factorial.mu. 3 | 4 | ; factorial n = n*factorial(n-1) 5 | (function factorial [ 6 | (default-space:space-address <- new space:literal 30:literal) 7 | (n:integer <- input 0:literal) 8 | (x:integer <- subtract n:integer 1:literal) 9 | (subresult:integer <- factorial x:integer) 10 | (result:integer <- multiply subresult:integer n:integer) 11 | (reply result:integer) 12 | ]) 13 | 14 | ; factorial 0 = 1 15 | (function factorial [ 16 | (default-space:space-address <- new space:literal 30:literal) 17 | (n:integer <- input 0:literal) 18 | { begin 19 | (zero?:boolean <- equal n:integer 0:literal) 20 | (break-unless zero?:boolean) 21 | (reply 1:literal) 22 | } 23 | ]) 24 | 25 | (function main [ 26 | (1:integer <- factorial 5:literal) 27 | ($print (("result: " literal))) 28 | (print-integer nil:literal/terminal 1:integer) 29 | ($print (("\n" literal))) 30 | ]) 31 | -------------------------------------------------------------------------------- /linux/bootstrap/021div.cc: -------------------------------------------------------------------------------- 1 | //: helper for division operations: sign-extend EAX into EDX 2 | 3 | :(before "End Initialize Op Names") 4 | put_new(Name, "99", "sign-extend EAX into EDX (cdq)"); 5 | 6 | :(code) 7 | void test_cdq() { 8 | Reg[EAX].i = 10; 9 | run( 10 | "== code 0x1\n" 11 | "99\n" 12 | ); 13 | CHECK_TRACE_CONTENTS( 14 | "run: sign-extend EAX into EDX\n" 15 | "run: EDX is now 0x00000000\n" 16 | ); 17 | } 18 | 19 | :(before "End Single-Byte Opcodes") 20 | case 0x99: { // sign-extend EAX into EDX 21 | trace(Callstack_depth+1, "run") << "sign-extend EAX into EDX" << end(); 22 | Reg[EDX].i = (Reg[EAX].i < 0) ? -1 : 0; 23 | trace(Callstack_depth+1, "run") << "EDX is now 0x" << HEXWORD << Reg[EDX].u << end(); 24 | break; 25 | } 26 | 27 | :(code) 28 | void test_cdq_negative() { 29 | Reg[EAX].i = -10; 30 | run( 31 | "== code 0x1\n" 32 | "99\n" 33 | ); 34 | CHECK_TRACE_CONTENTS( 35 | "run: sign-extend EAX into EDX\n" 36 | "run: EDX is now 0xffffffff\n" 37 | ); 38 | } 39 | -------------------------------------------------------------------------------- /104test.subx: -------------------------------------------------------------------------------- 1 | # Some helpers needed only because Mu doesn't support globals at the moment. 2 | 3 | == code 4 | 5 | count-test-failure: 6 | # . prologue 7 | 55/push-ebp 8 | 89/<- %ebp 4/r32/esp 9 | # 10 | ff 0/subop/increment *Num-test-failures 11 | $count-test-failure:end: 12 | # . epilogue 13 | 89/<- %esp 5/r32/ebp 14 | 5d/pop-to-ebp 15 | c3/return 16 | 17 | num-test-failures: # -> _/eax: int 18 | # . prologue 19 | 55/push-ebp 20 | 89/<- %ebp 4/r32/esp 21 | # 22 | 8b/-> *Num-test-failures 0/r32/eax 23 | $num-test-failures:end: 24 | # . epilogue 25 | 89/<- %esp 5/r32/ebp 26 | 5d/pop-to-ebp 27 | c3/return 28 | 29 | running-tests?: # -> _/eax: int 30 | # . prologue 31 | 55/push-ebp 32 | 89/<- %ebp 4/r32/esp 33 | # 34 | 8b/-> *Running-tests? 0/r32/eax 35 | $running-tests?:end: 36 | # . epilogue 37 | 89/<- %esp 5/r32/ebp 38 | 5d/pop-to-ebp 39 | c3/return 40 | 41 | == data 42 | 43 | Num-test-failures: 44 | 0/imm32 45 | 46 | Running-tests?: 47 | 1/imm32/true 48 | -------------------------------------------------------------------------------- /archive/0.vm.arc/highlights: -------------------------------------------------------------------------------- 1 | " vim: ft=vim 2 | " Data-flow highlighting: http://www.reddit.com/r/programming/comments/1w76um/coding_in_color/cezpios 3 | 4 | highlight highlight_97a5a5e3 ctermfg=205 5 | call matchadd('highlight_97a5a5e3', '\') 6 | highlight highlight_1f88e41c ctermfg=139 7 | call matchadd('highlight_1f88e41c', '\') 8 | highlight highlight_6da20a96 ctermfg=141 9 | call matchadd('highlight_6da20a96', '\') 10 | highlight highlight_ae83eebb ctermfg=149 11 | call matchadd('highlight_ae83eebb', 'curr-line-address-address') 12 | highlight highlight_bb695e14 ctermfg=36 13 | call matchadd('highlight_bb695e14', '\') 14 | highlight highlight_1e44ab4f ctermfg=208 15 | call matchadd('highlight_1e44ab4f', '\') 16 | highlight highlight_3323f077 ctermfg=208 17 | call matchadd('highlight_3323f077', '\') 18 | highlight highlight_74fc42b2 ctermfg=220 19 | call matchadd('highlight_74fc42b2', 'second-arg') 20 | highlight highlight_ff6f0571 ctermfg=220 21 | call matchadd('highlight_ff6f0571', 'second-arg-box') 22 | -------------------------------------------------------------------------------- /408float.mu: -------------------------------------------------------------------------------- 1 | # Some quick-n-dirty ways to create floats. 2 | 3 | fn fill-in-rational _out: (addr float), nr: int, dr: int { 4 | var out/edi: (addr float) <- copy _out 5 | var result/xmm0: float <- convert nr 6 | var divisor/xmm1: float <- convert dr 7 | result <- divide divisor 8 | copy-to *out, result 9 | } 10 | 11 | fn fill-in-sqrt _out: (addr float), n: int { 12 | var out/edi: (addr float) <- copy _out 13 | var result/xmm0: float <- convert n 14 | result <- square-root result 15 | copy-to *out, result 16 | } 17 | 18 | fn rational nr: int, dr: int -> _/xmm0: float { 19 | var result/xmm0: float <- convert nr 20 | var divisor/xmm1: float <- convert dr 21 | result <- divide divisor 22 | return result 23 | } 24 | 25 | # n/m rounded up 26 | fn scale-down-and-round-up n: int, m: int -> _/ecx: int { 27 | var result/ecx: int <- copy n 28 | result <- add m 29 | result <- decrement 30 | var result-f/xmm0: float <- convert result 31 | var m-f/xmm1: float <- convert m 32 | result-f <- divide m-f 33 | result <- truncate result-f 34 | return result 35 | } 36 | -------------------------------------------------------------------------------- /archive/1.vm/http-server.mu: -------------------------------------------------------------------------------- 1 | # example program: a single-request HTTP server 2 | # listen for connections from clients on a server socket 3 | # when a connection occurs, transfer it to a session socket 4 | # read from it using channels 5 | # write to it directly 6 | # 7 | # After running it, navigate to localhost:8080. Your browser should display 8 | # "SUCCESS!" and the server will terminate after one connection. 9 | 10 | def main [ 11 | local-scope 12 | socket:num <- $open-server-socket 8080/port 13 | $print [Mu socket creation returned ], socket, 10/newline 14 | return-unless socket 15 | session:num <- $accept socket 16 | contents:&:source:char, sink:&:sink:char <- new-channel 30 17 | sink <- start-running receive-from-socket session, sink 18 | query:text <- drain contents 19 | $print [Done reading from socket.], 10/newline 20 | write-to-socket session, [HTTP/1.0 200 OK 21 | Content-type: text/plain 22 | 23 | SUCCESS! 24 | ] 25 | $print 10/newline, [Wrote to and closing socket...], 10/newline 26 | session <- $close-socket session 27 | socket <- $close-socket socket 28 | ] 29 | -------------------------------------------------------------------------------- /editor/subx.dte: -------------------------------------------------------------------------------- 1 | # Syntax highlighting for https://gitlab.com/craigbarnes/dte 2 | # 3 | # To install this file, symlink it to ~/.dte/syntax/subx 4 | # Then add this line to ~/.dte/rc: 5 | # ft subx subx 6 | 7 | syntax subx 8 | 9 | # For improved colorization, add lines like these in your ~/.dte/rc (the 10 | # precise colors here assume the default color scheme in a 256-color terminal): 11 | # hi subx.comment0 25 underline 12 | # hi comment 25 13 | # hi subx.comment2 19 14 | # hi subx.comment3 245 15 | default comment subx.comment0 subx.comment2 subx.comment3 16 | 17 | state start code 18 | str "# . ." subx.comment3 19 | str "# ." subx.comment2 20 | str "# -" subx.comment0 21 | char # comment 22 | char '"' string 23 | eat this 24 | 25 | state comment 26 | char "\n" start 27 | eat this 28 | 29 | state subx.comment0 30 | char "\n" start 31 | eat this 32 | 33 | state subx.comment2 34 | char "\n" start 35 | eat this 36 | 37 | state subx.comment3 38 | char "\n" start 39 | eat this 40 | 41 | state string 42 | char "\"" start string 43 | eat this 44 | -------------------------------------------------------------------------------- /linux/mu-init-test.subx: -------------------------------------------------------------------------------- 1 | # Just a test stub for mu-init.subx 2 | # 3 | # Try it out like this: 4 | # $ ./translate_subx init.linux [0-9]*.subx mu-init.subx mu-init-test.subx 5 | # $ ./a.elf # should run all tests 6 | 7 | main: # args: (addr array (addr array byte)) -> result/ebx: int 8 | # . prologue 9 | 55/push-ebp 10 | 89/<- %ebp 4/r32/esp 11 | # . save registers 12 | 50/push-eax 13 | 56/push-esi 14 | # esi = args 15 | 8b/-> *(ebp+8) 6/r32/esi 16 | { 17 | # if (argc <= 1) break 18 | 81 7/subop/compare *esi 4/imm32 19 | 7e/jump-if-<= break/disp8 20 | # if (argv[1] != "test") break 21 | (string-equal? *(esi+8) "test") # => eax 22 | 3d/compare-eax-and 0/imm32 23 | 74/jump-if-= break/disp8 24 | # 25 | (run-tests) 26 | # return *Num-test-failures 27 | 8b/-> *Num-test-failures 3/r32/ebx 28 | eb/jump $main:end/disp8 29 | } 30 | $main:end: 31 | # . restore registers 32 | 5e/pop-to-esi 33 | 58/pop-to-eax 34 | # . epilogue 35 | 89/<- %esp 5/r32/ebp 36 | 5d/pop-to-ebp 37 | c3/return 38 | -------------------------------------------------------------------------------- /archive/1.vm/067random.cc: -------------------------------------------------------------------------------- 1 | :(before "End Primitive Recipe Declarations") 2 | REAL_RANDOM, 3 | :(before "End Primitive Recipe Numbers") 4 | put(Recipe_ordinal, "real-random", REAL_RANDOM); 5 | :(before "End Primitive Recipe Checks") 6 | case REAL_RANDOM: { 7 | break; 8 | } 9 | :(before "End Primitive Recipe Implementations") 10 | case REAL_RANDOM: { 11 | // todo: limited range of numbers, might be imperfectly random 12 | // todo: thread state in extra ingredients and products 13 | products.resize(1); 14 | products.at(0).push_back(rand()); 15 | break; 16 | } 17 | 18 | :(before "End Primitive Recipe Declarations") 19 | MAKE_RANDOM_NONDETERMINISTIC, 20 | :(before "End Primitive Recipe Numbers") 21 | put(Recipe_ordinal, "make-random-nondeterministic", MAKE_RANDOM_NONDETERMINISTIC); 22 | :(before "End Primitive Recipe Checks") 23 | case MAKE_RANDOM_NONDETERMINISTIC: { 24 | break; 25 | } 26 | :(before "End Primitive Recipe Implementations") 27 | case MAKE_RANDOM_NONDETERMINISTIC: { 28 | srand(time(NULL)); 29 | break; 30 | } 31 | 32 | // undo non-determinism in later tests 33 | :(before "End Reset") 34 | srand(0); 35 | -------------------------------------------------------------------------------- /archive/0.vm.arc/tangle.mu: -------------------------------------------------------------------------------- 1 | ; To demonstrate tangle directives, we'll construct a factorial function with 2 | ; separate base and recursive cases. Compare factorial.mu. 3 | ; This isn't a very realistic example, just a simple demonstration of 4 | ; possibilities. 5 | 6 | (function factorial [ 7 | (default-space:space-address <- new space:literal 30:literal) 8 | (n:integer <- next-input) 9 | { begin 10 | base-case 11 | } 12 | recursive-case 13 | ]) 14 | 15 | (after base-case [ 16 | ; if n=0 return 1 17 | (zero?:boolean <- equal n:integer 0:literal) 18 | (break-unless zero?:boolean) 19 | (reply 1:literal) 20 | ]) 21 | 22 | (after recursive-case [ 23 | ; return n*factorial(n-1) 24 | (x:integer <- subtract n:integer 1:literal) 25 | (subresult:integer <- factorial x:integer) 26 | (result:integer <- multiply subresult:integer n:integer) 27 | (reply result:integer) 28 | ]) 29 | 30 | (function main [ 31 | (1:integer <- factorial 5:literal) 32 | ($print (("result: " literal))) 33 | (print-integer nil:literal/terminal 1:integer) 34 | (print-character nil:literal/terminal ((#\newline literal))) 35 | ]) 36 | -------------------------------------------------------------------------------- /linux/apps/ex13.subx: -------------------------------------------------------------------------------- 1 | # Compare 3 and 3. 2 | # 3 | # To run: 4 | # $ ./translate_subx 000init.subx apps/ex13.subx 5 | # $ ./a.elf 6 | # Expected result: 7 | # $ echo $? 8 | # 1 9 | 10 | == code 11 | # instruction effective address register displacement immediate 12 | # . op subop mod rm32 base index scale r32 13 | # . 1-3 bytes 3 bits 2 bits 3 bits 3 bits 3 bits 2 bits 2 bits 0/1/2/4 bytes 0/1/2/4 bytes 14 | 15 | Entry: 16 | b8/copy-to-eax 3/imm32 17 | 3d/compare-eax-and 3/imm32 18 | 0f 94/set-if-= 3/mod/direct 3/rm32/ebx . . . . . . # set ebx to ZF 19 | 81 4/subop/and 3/mod/direct 3/rm32/ebx . . . . . 0xff/imm32 # AND with eax 20 | 21 | $exit: 22 | # exit(ebx) 23 | e8/call syscall_exit/disp32 24 | 25 | # . . vim:nowrap:textwidth=0 26 | -------------------------------------------------------------------------------- /linux/apps/tui.mu: -------------------------------------------------------------------------------- 1 | # Test some primitives for text-mode. 2 | # 3 | # To run: 4 | # $ ./translate apps/tui.mu 5 | # $ ./a.elf 6 | 7 | fn main -> _/ebx: int { 8 | var nrows/eax: int <- copy 0 9 | var ncols/ecx: int <- copy 0 10 | nrows, ncols <- screen-size 0 11 | enable-screen-grid-mode 12 | move-cursor 0/screen, 5/row, 0x22/col 13 | start-color 0/screen, 1/fg, 0x7a/bg 14 | start-blinking 0/screen 15 | print-string 0/screen, "Hello world!" 16 | reset-formatting 0/screen 17 | move-cursor 0/screen, 6/row, 0x22/col 18 | print-string 0/screen, "tty dimensions: " 19 | print-int32-hex 0/screen, nrows 20 | print-string 0/screen, " rows, " 21 | print-int32-hex 0/screen, ncols 22 | print-string 0/screen, " rows\n" 23 | 24 | print-string 0/screen, "press a key to see its code: " 25 | enable-keyboard-immediate-mode 26 | var x/eax: code-point-utf8 <- read-key-from-real-keyboard 27 | enable-keyboard-type-mode 28 | enable-screen-type-mode 29 | print-string 0/screen, "You pressed " 30 | var x-int/eax: int <- copy x 31 | print-int32-hex 0/screen, x-int 32 | print-string 0/screen, "\n" 33 | return 0 34 | } 35 | -------------------------------------------------------------------------------- /editor/atom/grammars/subx.json: -------------------------------------------------------------------------------- 1 | { 2 | "scopeName": "source.subx", 3 | "name": "SubX", 4 | "fileTypes": ["subx"], 5 | "patterns": [ 6 | { 7 | "name": "header-comment.subx", 8 | "match": "# - .*" 9 | }, 10 | { 11 | "name": "comment-sub-2.subx", 12 | "match": "# \\. \\. .*" 13 | }, 14 | { 15 | "name": "comment-sub-1.subx", 16 | "match": "# \\. .*" 17 | }, 18 | { 19 | "name": "comment.subx", 20 | "match": "#.*" 21 | }, 22 | { 23 | "name": "strings.subx", 24 | "match": "\"[^\"]*\"" 25 | }, 26 | { 27 | "name": "test.subx", 28 | "match": "^test-[^ ]*:" 29 | }, 30 | { 31 | "name": "global.subx", 32 | "match": "^[A-Z][^ ]*:" 33 | }, 34 | { 35 | "name": "function.subx", 36 | "match": "^[^_$ #][^ ]*:" 37 | }, 38 | { 39 | "name": "label.subx", 40 | "match": "^[_$][^ ]*:" 41 | } 42 | ] 43 | } 44 | -------------------------------------------------------------------------------- /archive/1.vm/083scenario_screen_test.mu: -------------------------------------------------------------------------------- 1 | # To check our support for screens in scenarios, rewrite tests from print.mu 2 | 3 | scenario print-character-at-top-left-2 [ 4 | local-scope 5 | assume-screen 3/width, 2/height 6 | run [ 7 | a:char <- copy 97/a 8 | screen <- print screen, a 9 | ] 10 | screen-should-contain [ 11 | .a . 12 | . . 13 | ] 14 | ] 15 | 16 | scenario clear-line-erases-printed-characters-2 [ 17 | local-scope 18 | assume-screen 5/width, 3/height 19 | # print a character 20 | a:char <- copy 97/a 21 | screen <- print screen, a 22 | # move cursor to start of line 23 | screen <- move-cursor screen, 0/row, 0/column 24 | run [ 25 | screen <- clear-line screen 26 | ] 27 | screen-should-contain [ 28 | . . 29 | . . 30 | . . 31 | ] 32 | ] 33 | 34 | scenario scroll-screen [ 35 | local-scope 36 | assume-screen 3/width, 2/height 37 | run [ 38 | a:char <- copy 97/a 39 | move-cursor screen, 1/row, 2/column 40 | screen <- print screen, a 41 | screen <- print screen, a 42 | ] 43 | screen-should-contain [ 44 | . a. 45 | .a . 46 | ] 47 | ] 48 | -------------------------------------------------------------------------------- /archive/2.transect/compiler6: -------------------------------------------------------------------------------- 1 | == Goal 2 | 3 | A memory-safe language with a simple translator to x86 that can be feasibly written in x86. 4 | 5 | == Definitions of terms 6 | 7 | Memory-safe: it should be impossible to: 8 | a) create a pointer out of arbitrary data, or 9 | b) to access heap memory after it's been freed. 10 | 11 | Simple: do all the work in a 2-pass translator: 12 | Pass 1: check each instruction's types in isolation. 13 | Pass 2: emit code for each instruction in isolation. 14 | 15 | == types 16 | 17 | int 18 | char 19 | (address _) 20 | (array _ n) 21 | (ref _) 22 | 23 | addresses can't be saved to stack or global, 24 | or included in compound types 25 | or used across a call (to eliminate possibility of free) 26 | 27 | : (address T) <- advance : (array T), : (index T) 28 | 29 | arrays require a size 30 | (ref array _) may not include a size 31 | 32 | == open questions 33 | Is argv an address? 34 | Global variables are easiest to map to addresses. 35 | Ideally we'd represent 'indirect' as a '*' and we could just count to make 36 | sure that an instruction never has more than one '*'. 37 | -------------------------------------------------------------------------------- /linux/apps/raytracing/color.mu: -------------------------------------------------------------------------------- 1 | type rgb { 2 | # components normalized to within [0.0, 1.0] 3 | r: float 4 | g: float 5 | b: float 6 | } 7 | 8 | # print translating to [0, 256) 9 | fn print-rgb screen: (addr screen), _c: (addr rgb) { 10 | var c/esi: (addr rgb) <- copy _c 11 | var xn: float 12 | var xn-addr/ecx: (addr float) <- address xn 13 | fill-in-rational xn-addr, 0x3e7ff, 0x3e8 # 255999 / 1000 14 | # print 255.999 * c->r 15 | var result/xmm0: float <- copy xn 16 | var src-addr/eax: (addr float) <- get c, r 17 | result <- multiply *src-addr 18 | var result-int/edx: int <- truncate result 19 | print-int32-decimal screen, result-int 20 | print-string screen, " " 21 | # print 255.999 * c->g 22 | src-addr <- get c, g 23 | result <- copy xn 24 | result <- multiply *src-addr 25 | result-int <- truncate result 26 | print-int32-decimal screen, result-int 27 | print-string screen, " " 28 | # print 255.999 * c->b 29 | src-addr <- get c, b 30 | result <- copy xn 31 | result <- multiply *src-addr 32 | result-int <- truncate result 33 | print-int32-decimal screen, result-int 34 | print-string screen, "\n" 35 | } 36 | -------------------------------------------------------------------------------- /tools/termbox/COPYING: -------------------------------------------------------------------------------- 1 | Copyright (C) 2010-2013 nsf 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy 4 | of this software and associated documentation files (the "Software"), to deal 5 | in the Software without restriction, including without limitation the rights 6 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | copies of the Software, and to permit persons to whom the Software is 8 | furnished to do so, subject to the following conditions: 9 | 10 | The above copyright notice and this permission notice shall be included in 11 | all copies or substantial portions of the Software. 12 | 13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 | THE SOFTWARE. 20 | -------------------------------------------------------------------------------- /archive/1.vm/termbox/COPYING: -------------------------------------------------------------------------------- 1 | Copyright (C) 2010-2013 nsf 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy 4 | of this software and associated documentation files (the "Software"), to deal 5 | in the Software without restriction, including without limitation the rights 6 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | copies of the Software, and to permit persons to whom the Software is 8 | furnished to do so, subject to the following conditions: 9 | 10 | The above copyright notice and this permission notice shall be included in 11 | all copies or substantial portions of the Software. 12 | 13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 | THE SOFTWARE. 20 | -------------------------------------------------------------------------------- /editor/subx.gedit: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | text/x-subx;text/x-subxsrc 6 | *.subx 7 | 8 | 9 | 20 | 21 | 49 | 50 | 51 | https://github.com/akkartik/mu/blob/main/apps/*.subx 52 |
53 | 1 
54 | 
55 | 56 | 57 | 58 | -------------------------------------------------------------------------------- /linux/apps/ex12.subx: -------------------------------------------------------------------------------- 1 | # Example showing mmap syscall. 2 | # Create a new segment using mmap, save the address, write to it. 3 | # 4 | # To run: 5 | # $ ./translate_subx 000init.subx apps/ex12.subx 6 | # $ ./a.elf 7 | # You shouldn't get a segmentation fault. 8 | 9 | == code 10 | # instruction effective address register displacement immediate 11 | # . op subop mod rm32 base index scale r32 12 | # . 1-3 bytes 3 bits 2 bits 3 bits 3 bits 3 bits 2 bits 2 bits 0/1/2/4 bytes 0/1/2/4 bytes 13 | 14 | Entry: 15 | # mmap(Mmap-new-segment->len) 16 | bb/copy-to-ebx Mmap-new-segment/imm32 17 | e8/call syscall_mmap/disp32 18 | 19 | # write to *eax to check that we have access to the newly-allocated segment 20 | c7 0/subop/copy 0/mod/direct 0/rm32/eax . . . . . 0x34/imm32 # copy to *eax 21 | 22 | # exit(eax) 23 | 89/copy 3/mod/direct 3/rm32/ebx . . . 0/r32/eax . . # copy eax to ebx 24 | e8/call syscall_exit/disp32 25 | 26 | == data 27 | 28 | # various constants used here were found in the Linux sources (search for file mman-common.h) 29 | Mmap-new-segment: # type mmap_arg_struct 30 | # addr 31 | 0/imm32 32 | # len 33 | 0x100/imm32 34 | # protection flags 35 | 3/imm32 # PROT_READ | PROT_WRITE 36 | # sharing flags 37 | 0x22/imm32 # MAP_PRIVATE | MAP_ANONYMOUS 38 | # fd 39 | -1/imm32 # since MAP_ANONYMOUS is specified 40 | # offset 41 | 0/imm32 # since MAP_ANONYMOUS is specified 42 | 43 | # . . vim:nowrap:textwidth=0 44 | --------------------------------------------------------------------------------