diff options
author | Kartik K. Agaram <vc@akkartik.com> | 2014-11-24 23:59:55 -0800 |
---|---|---|
committer | Kartik K. Agaram <vc@akkartik.com> | 2014-11-25 00:42:20 -0800 |
commit | 14b33e59a528b996f682110564182524d1503e91 (patch) | |
tree | f1a84fa1aabc0ad291998bc0c1333c84e6cf4552 /Readme | |
parent | c1b2f17fcf02ce40aaf345880d928f6ee540f80e (diff) | |
download | mu-14b33e59a528b996f682110564182524d1503e91.tar.gz |
324 - more elaboration in Readme
I have different prose in Readme and at the top of the tests. Let's see how hard they are to manage over time.
Diffstat (limited to 'Readme')
-rw-r--r-- | Readme | 165 |
1 files changed, 143 insertions, 22 deletions
diff --git a/Readme b/Readme index 2d6a3f93..acdd8573 100644 --- a/Readme +++ b/Readme @@ -1,4 +1,25 @@ -Mu: a world where any manual test can be easily automated +Mu: making programs easier to understand in the large + +Imagine a world where you can: + + a) think of a tiny improvement to a program you use, clone its sources, + orient yourself on its organization and make your tiny improvement, all in a + single afternoon. + + b) Record your program as it runs, and easily convert arbitrary logs of runs + into reproducible automatic tests. + + c) Answer arbitrary what-if questions about a codebase by trying out changes + and seeing what tests fail, confident that *every* scenario previous authors + have considered has been encoded as a test. + + d) Build first simple and successively more complex versions of a program so + you can stage your learning. + +I think all these abilities might be strongly correlated; not only are they +achievable with a few common concepts, but you can't easily attack one of them +without also chasing after the others. In this world, any manual test can be +easily automated: keyboard input printing to screen @@ -8,8 +29,32 @@ Mu: a world where any manual test can be easily automated fault tolerance ... -Collecting all possible scenarios considered will hopefully make the global -structure of programs more apparent. More details: http://akkartik.github.io/mu +I hope to attain this world by creating a comprehensive library of fakes and +hooks for the entire software stack, at all layers of abstraction (programming +language, OS, standard libraries, application libraries). + +To reduce my workload and get to a proof-of-concept quickly, this is a very +*alien* software stack. I've stolen ideas from lots of previous systems, but +it's not like anything you're used to. The 'OS' will lack virtual memory, user +accounts, any unprivileged mode, address space isolation, and many other +features. + +To avoid building a compiler I'm going to do all my programming in (virtual +machine) assembly. To keep assembly from getting too painful I'm going to +pervasively use one trick: load-time directives to let me order code however I +want, and to write boilerplate once and insert it in multiple places. If +you're familiar with literate programming or aspect-oriented programming, +these directives may seem vaguely familiar. If you're not, think of them as a +richer interface for function inlining. + +Trading off notational convenience for tests may seem regressive, but I +suspect high-level languages aren't particularly helpful in understanding +large codebases. No matter how good a notation is, it can only let you see a +tiny fraction of a large program at a time. Logs, on the other hand, can let +you zoom out and take in an entire *run* at a glance, making them a superior +unit of comprehension. If I'm right, it makes sense to prioritize the right +*tactile* interface for working with and getting feedback on large programs +before we invest in the *visual* tools for making them concise. == Taking mu for a spin @@ -18,20 +63,49 @@ Prerequisites: Racket from http://racket-lang.org $ cd mu $ git clone http://github.com/arclanguage/anarki -Now try a test program. - - $ cat x.mu # simple example to add two numbers - (main - ((x integer) <- copy (1 literal)) - ((y integer) <- copy (3 literal)) - ((z integer) <- add (x integer) (y integer)) - ) - - $ ./anarki/arc mu.arc x.mu - #hash((1 . 1) (2 . 3) (3 . 4)) # state of simulated memory after executing x.mu - -Location z contains the sum of locations x and y. -(You have to imagine that location 3 maps to 'z' for now, sorry..) +As a sneak peek, here's how you compute factorial in mu (lines starting with +semi-colons are comments): + + def factorial [ + ; allocate some space for local variables + default-scope/scope-address <- new scope/literal 30/literal + ; receive args from caller in a queue + n/integer <- arg + { + ; if n=0 return 1 + zero?/boolean <- eq n/integer, 0/literal + break-unless zero?/boolean + reply 1/literal + } + ; return n*factorial(n-1) + tmp1/integer <- sub n/integer 1/literal + tmp2/integer <- factorial tmp1/integer + result/integer <- mul tmp2/integer, n/integer + reply result/integer + ] + +The grammar is extremely simple. All you have are statements and blocks. +Statements are either labels or instructions of the form: + + oarg1, oarg2, oarg3, ... <- OP arg1, arg2, arg3, ... + +Input and output args have to be simple; no sub-expressions are permitted. But +you can have any number of them. Each arg can have any number of bits of +metadata like the types above, separated by slashes. Anybody can write tools +to statically analyze or verify programs using new metadata. Or they can just +be documentation; any metadata the system doesn't recognize gets silently +ignored. + +Try this program out now: + + $ ./anarki/arc mu.arc factorial.mu + result: 120 # factorial of 5 + ... # ignore the memory dump for now + +(The code in factorial.mu looks different from the idealized syntax above. +We'll get to an actual parser in time.) + +--- Another example, this time with concurrency. @@ -40,12 +114,59 @@ Another example, this time with concurrency. Notice that it repeatedly prints either '34' or '35' at random. Hit ctrl-c to stop. -== Now dive in +--- Try running the tests: $ ./anark/arc mu.arc.t - #t # all tests passed! - -Now start reading mu.arc.t. A colorized copy of it is at mu.arc.t.html and -http://akkartik.github.io/mu. + $ # all tests passed! + +Now start reading mu.arc.t to see how it works. A colorized copy of it is at +mu.arc.t.html and http://akkartik.github.io/mu. + +You might also want to peek in the .traces directory, which automatically +includes logs for each test showing you just how it ran on my machine. If mu +eventually gets complex enough that you have trouble running examples, these +logs might help figure out if my system is somehow different from yours or if +I've just been insufficiently diligent and my documentation is out of date. + +The immediate goal of mu is to build up towards an environment for parsing and +visualizing these traces in a hierarchical manner, and to easily turn traces +into reproducible tests by flagging inputs entering the log and outputs +leaving it. The former will have to be faked in, and the latter will want to +be asserted on, to turn a trace into a test. + +== Credits + +Mu builds on many ideas that have come before, especially: + +- Peter Naur (http://alistair.cockburn.us/ASD+book+extract%3A+%22Naur,+Ehn,+Musashi%22) + for articulating the paramount problem of programming: communicating a + codebase to others; +- Christopher Alexander (http://www.amazon.com/Notes-Synthesis-Form-Harvard-Paperbacks/dp/0674627512) + and Richard Gabriel (http://dreamsongs.net/Files/PatternsOfSoftware.pdf) for + the intellectual tools for reasoning about the higher order design of a + codebase; +- Unix and C for showing us how to co-evolve language and OS, and for teaching + the (much maligned, misunderstood and underestimated) value of concise + *implementation* in addition to a clean interface; +- Donald Knuth's literate programming (http://www.literateprogramming.com/knuthweb.pdf) + for liberating "code for humans to read" from the tyranny of compiler order; +- David Parnas (http://www.cs.umd.edu/class/spring2003/cmsc838p/Design/criteria.pdf) + and others for highlighting the value of separating concerns and stepwise + refinement; +- Lisp (http://www.paulgraham.com/rootsoflisp.html) for showing the power of + dynamic languages, late binding and providing the right primitives a la + carte, especially lisp macros; +- The folklore of debugging by print and the trace facility in many lisp + systems; +- Automated tests for showing the value of developing programs inside an + elaborate harness; +- Python doctest (http://docs.python.org/2/library/doctest.html) for + exemplifying interactive documentation that doubles as tests; +- ReStructuredText (https://en.wikipedia.org/wiki/ReStructuredText) + and its antecedents (https://en.wikipedia.org/wiki/Setext) for showing that + markup can be clean; +- BDD for challenging us all to write tests at a higher level; +- JavaScript and CSS for demonstrating the power of a DOM for complex + structured documents. |