summary refs log tree commit diff stats
path: root/uml/128002.diagram
blob: 3c359d4240e9db499293f2221b4b39ece9f06838 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
format 70

classcanvas 128002 class_ref 128002 // Displayable
  draw_all_relations default hide_attributes default hide_operations default hide_getset_operations default show_members_full_definition default show_members_visibility default show_members_stereotype default show_members_multiplicity default show_members_initialization default show_attribute_modifiers default member_max_width 0 show_parameter_dir default show_parameter_name default package_name_in_tab default class_drawing_mode default drawing_language default show_context_mode default auto_label_position default show_relation_modifiers default show_relation_visibility default show_infonote default shadow default show_stereotype_properties default
  xyz 301.407 212.109 2000
end
classcanvas 128130 class_ref 128130 // UI
  draw_all_relations default hide_attributes default hide_operations default hide_getset_operations default show_members_full_definition default show_members_visibility default show_members_stereotype default show_members_multiplicity default show_members_initialization default show_attribute_modifiers default member_max_width 0 show_parameter_dir default show_parameter_name default package_name_in_tab default class_drawing_mode default drawing_language default show_context_mode default auto_label_position default show_relation_modifiers default show_relation_visibility default show_infonote default shadow default show_stereotype_properties default
  xyz 240.852 390.327 2000
end
classcanvas 128258 class_ref 128258 // DefaultUI
  draw_all_relations default hide_attributes default hide_operations default hide_getset_operations default show_members_full_definition default show_members_visibility default show_members_stereotype default show_members_multiplicity default show_members_initialization default show_attribute_modifiers default member_max_width 0 show_parameter_dir default show_parameter_name default package_name_in_tab default class_drawing_mode default drawing_language default show_context_mode default auto_label_position default show_relation_modifiers default show_relation_visibility default show_infonote default shadow default show_stereotype_properties default
  xyz 217.717 473.896 2000
end
classcanvas 128642 class_ref 128386 // DisplayableContainer
  draw_all_relations default hide_attributes default hide_operations default hide_getset_operations default show_members_full_definition default show_members_visibility default show_members_stereotype default show_members_multiplicity default show_members_initialization default show_attribute_modifiers default member_max_width 0 show_parameter_dir default show_parameter_name default package_name_in_tab default class_drawing_mode default drawing_language default show_context_mode default auto_label_position default show_relation_modifiers default show_relation_visibility default show_infonote default shadow default show_stereotype_properties default
  xyz 224.704 309.894 2006
end
classcanvas 129410 class_ref 135042 // TitleBar
  draw_all_relations default hide_attributes default hide_operations default hide_getset_operations default show_members_full_definition default show_members_visibility default show_members_stereotype default show_members_multiplicity default show_members_initialization default show_attribute_modifiers default member_max_width 0 show_parameter_dir default show_parameter_name default package_name_in_tab default class_drawing_mode default drawing_language default show_context_mode default auto_label_position default show_relation_modifiers default show_relation_visibility default show_infonote default shadow default show_stereotype_properties default
  xyz 629.233 351.65 2000
end
classcanvas 129666 class_ref 135170 // FileList
  draw_all_relations default hide_attributes default hide_operations default hide_getset_operations default show_members_full_definition default show_members_visibility default show_members_stereotype default show_members_multiplicity default show_members_initialization default show_attribute_modifiers default member_max_width 0 show_parameter_dir default show_parameter_name default package_name_in_tab default class_drawing_mode default drawing_language default show_context_mode default auto_label_position default show_relation_modifiers default show_relation_visibility default show_infonote default shadow default show_stereotype_properties default
  xyz 539.259 352.907 2000
end
classcanvas 129922 class_ref 135298 // FileListContainer
  draw_all_relations default hide_attributes default hide_operations default hide_getset_operations default show_members_full_definition default show_members_visibility default show_members_stereotype default show_members_multiplicity default show_members_initialization default show_attribute_modifiers default member_max_width 0 show_parameter_dir default show_parameter_name default package_name_in_tab default class_drawing_mode default drawing_language default show_context_mode default auto_label_position default show_relation_modifiers default show_relation_visibility default show_infonote default shadow default show_stereotype_properties default
  xyz 471.3 421.8 2000
end
classcanvas 131970 class_ref 135426 // Console
  draw_all_relations default hide_attributes default hide_operations default hide_getset_operations default show_members_full_definition default show_members_visibility default show_members_stereotype default show_members_multiplicity default show_members_initialization default show_attribute_modifiers default member_max_width 0 show_parameter_dir default show_parameter_name default package_name_in_tab default class_drawing_mode default drawing_language default show_context_mode default auto_label_position default show_relation_modifiers default show_relation_visibility default show_infonote default shadow default show_stereotype_properties default
  xyz 722.435 351.987 2000
end
note 132738 "Only one instance, since it initializes curses!"
  xyzwh 68 390 2012 89 113
classcanvas 132994 class_ref 141954 // FileManagerAware
  draw_all_relations default hide_attributes default hide_operations default hide_getset_operations default show_members_full_definition default show_members_visibility default show_members_stereotype default show_members_multiplicity default show_members_initialization default show_attribute_modifiers default member_max_width 0 show_parameter_dir default show_parameter_name default package_name_in_tab default class_drawing_mode default drawing_language default show_context_mode default auto_label_position default show_relation_modifiers default show_relation_visibility default show_infonote default shadow default show_stereotype_properties default
  xyz 138 98 2000
end
classcanvas 133122 class_ref 142082 // SettingsAware
  draw_all_relations default hide_attributes default hide_operations default hide_getset_operations default show_members_full_definition default show_members_visibility default show_members_stereotype default show_members_multiplicity default show_members_initialization default show_attribute_modifiers default member_max_width 0 show_parameter_dir default show_parameter_name default package_name_in_tab default class_drawing_mode default drawing_language default show_context_mode default auto_label_position default show_relation_modifiers default show_relation_visibility default show_infonote default shadow default show_stereotype_properties default
  xyz 153 151 2000
end
classcanvas 133250 class_ref 142210 // EnvironmentAware
  draw_all_relations default hide_attributes default hide_operations default hide_getset_operations default show_members_full_definition default show_members_visibility default show_members_stereotype default show_members_multiplicity default show_members_initialization default show_attribute_modifiers default member_max_width 0 show_parameter_dir default show_parameter_name default package_name_in_tab default class_drawing_mode default drawing_language default show_context_mode default auto_label_position default show_relation_modifiers default show_relation_visibility default show_infonote default shadow default show_stereotype_properties default
  xyz 134 50 2005
end
classcanvas 134530 class_ref 156034 // Widget
  draw_all_relations default hide_attributes default hide_operations default hide_getset_operations default show_members_full_definition default show_members_visibility default show_members_stereotype default show_members_multiplicity default show_members_initialization default show_attribute_modifiers default member_max_width 0 show_parameter_dir default show_parameter_name default package_name_in_tab default class_drawing_mode default drawing_language default show_context_mode default auto_label_position default show_relation_modifiers default show_relation_visibility default show_infonote default shadow default show_stereotype_properties default
  xyz 600 232 2000
end
note 136962 "Defines no methods, just for classification"
  xyzwh 608 99 2000 135 77
relationcanvas 128386 relation_ref 128002 // <generalisation>
  decenter_begin 529
  from ref 128258 z 2001 to ref 128130
  no_role_a no_role_b
  no_multiplicity_a no_multiplicity_b
end
relationcanvas 128898 relation_ref 128386 // <generalisation>
  decenter_begin 625
  decenter_end 339
  from ref 128642 z 2007 to ref 128002
  no_role_a no_role_b
  no_multiplicity_a no_multiplicity_b
end
relationcanvas 130178 relation_ref 135554 // <generalisation>
  decenter_end 715
  from ref 129922 z 2007 to point 349 395
  line 132610 z 2007 to ref 128642
  no_role_a no_role_b
  no_multiplicity_a no_multiplicity_b
end
relationcanvas 130562 relation_ref 135810 // <aggregation>
  decenter_begin 693
  from ref 129922 z 2001 to ref 129666
  no_role_a no_role_b
  no_multiplicity_a no_multiplicity_b
end
relationcanvas 130690 relation_ref 135938 // <aggregation>
  decenter_begin 720
  decenter_end 495
  from ref 128642 z 2007 to ref 128002
  no_role_a no_role_b
  no_multiplicity_a no_multiplicity_b
end
relationcanvas 132354 relation_ref 128258 // <generalisation>
  decenter_begin 487
  decenter_end 205
  from ref 128130 z 2007 to ref 128642
  no_role_a no_role_b
  no_multiplicity_a no_multiplicity_b
end
relationcanvas 133378 relation_ref 142850 // <generalisation>
  decenter_begin 505
  from ref 128002 z 2006 to point 348 66
  line 133762 z 2006 to ref 133250
  no_role_a no_role_b
  no_multiplicity_a no_multiplicity_b
end
relationcanvas 133506 relation_ref 142978 // <generalisation>
  decenter_begin 313
  from ref 128002 z 2001 to point 329 115
  line 133890 z 2001 to ref 132994
  no_role_a no_role_b
  no_multiplicity_a no_multiplicity_b
end
relationcanvas 134274 relation_ref 149634 // <generalisation>
  decenter_begin 116
  from ref 128002 z 2001 to point 307 168
  line 134402 z 2001 to ref 133122
  no_role_a no_role_b
  no_multiplicity_a no_multiplicity_b
end
relationcanvas 134658 relation_ref 170754 // <generalisation>
  decenter_end 708
  from ref 134530 z 2001 to ref 128002
  no_role_a no_role_b
  no_multiplicity_a no_multiplicity_b
end
relationcanvas 134786 relation_ref 170882 // <generalisation>
  from ref 131970 z 2001 to ref 134530
  no_role_a no_role_b
  no_multiplicity_a no_multiplicity_b
end
relationcanvas 134914 relation_ref 171010 // <generalisation>
  from ref 129410 z 2001 to ref 134530
  no_role_a no_role_b
  no_multiplicity_a no_multiplicity_b
end
relationcanvas 135042 relation_ref 171138 // <generalisation>
  from ref 129666 z 2001 to ref 134530
  no_role_a no_role_b
  no_multiplicity_a no_multiplicity_b
end
relationcanvas 135938 relation_ref 171266 // <generalisation>
  decenter_begin 333
  from ref 129922 z 2001 to point 517 316
  line 136066 z 2001 to ref 134530
  no_role_a no_role_b
  no_multiplicity_a no_multiplicity_b
end
relationcanvas 136194 relation_ref 178178 // <aggregation>
  from ref 128258 z 2001 to point 366 492
  line 136706 z 2001 to point 456 291
  line 136834 z 2001 to ref 134530
  no_role_a no_role_b
  no_multiplicity_a no_multiplicity_b
end
line 132866 -_-_
  from ref 132738 z 2013 to ref 128130
line 137090 -_-_
  from ref 136962 z 2001 to ref 134530
end
tik.name/post/tracing-tests)) 1. Organizing code and tests in layers of functionality, so that outsiders can build simple and successively more complex versions of a project, gradually enabling more peripheral features. Think of it as a cleaned-up `git log` for the project. ([More information.](http://akkartik.name/post/wart-layers)) Since I don't understand how Linux and other modern platforms work, Mu is built on an idealized VM while I learn. Eventually the plan is to transplant what I learn back to Linux. To minimize my workload, Mu doesn't have a high-level language yet. Instead, I've been programming directly in the VM's idealized assembly language. I expected this to be painful, but it's had some surprising benefits. First, programs as lists of instructions seem to be easier for non-programmers to comprehend than programs as trees of expressions. Second, I've found that Literate Programming using layers makes assembly much more ergonomic. Third, labels for gotos turn out to be great waypoints to insert code at from future layers; when I tried to divide C programs into layers, I sometimes had to split statements in two so I could insert code between them. High level languages today seem to provide three kinds of benefits: expressiveness (e.g. nested expressions, classes), safety (e.g. type checking) and automation (e.g. garbage collection). Mu gives up some expressiveness by not providing recursive expressions, but still supports lexical scope, generic types, and higher-order functions. It provides strong memory safety in spite of having manual memory management and supporting full-scale pointer operations (albeit at the cost of some runtime checks). *Taking Mu for a spin* Mu is currently implemented in C++ and requires a Unix-like environment. It's been tested on Ubuntu, Mac OS X and OpenBSD; on x86, x86\_64 and ARMv7; and on recent versions of GCC and Clang. Since it uses no bleeding-edge language features and has no exotic dependencies, it should work with most reasonable versions, compilers or processors. [![Build Status](https://api.travis-ci.org/akkartik/mu.svg)](https://travis-ci.org/akkartik/mu) Running Mu will always recompile it if necessary: ```shell $ cd mu $ ./mu ``` As a simple example, here's a program with some arithmetic: <img alt='code example' src='html/example1.png'> As I said before, Mu functions are lists of instructions, one to a line. Each instruction operates on some *ingredients* and returns some *products*. ``` [products] <- instruction [ingredients] ``` Result and ingredient *reagents* cannot contain instructions or infix expressions. On the other hand, you can have any number of them. In particular, you can have any number of products. For example, you can perform integer division as follows: ``` quotient:number, remainder:number <- divide-with-remainder 11, 3 ``` Each reagent consists of a name and its type, separated by a colon. You only have to specify the type the first time you mention a name, but you can be more explicit if you choose. Types can be multiple words and even arbitrary trees, like: ```nim x:array:number:3 # x is an array of 3 numbers y:list:number # y is a list of numbers # ':' is just syntactic sugar {z: (map (address array character) (list number))} # map from string to list of numbers ``` Try out the program now: ```shell $ ./mu example1.mu $ ``` Not much to see yet, since it doesn't print anything. To print the result, try adding the instruction `$print a` to the function. --- Here's a second example, of a function that can take ingredients: <img alt='fahrenheit to celsius' src='html/f2c-1.png'> Functions can specify headers showing their expected ingredients and products, separated by `->` (unlike the `<-` in calls). Once defined, functions can be called just like primitives. No need to mess with a `CALL` instruction or push/pop arguments to the stack. Since Mu is a low-level VM language, it provides extra control at the cost of verbosity. Using `local-scope`, you have explicit control over stack frames to isolate your functions in a type-safe manner. You can also create more sophisticated setups like closures. One consequence of this extra control: you have to explicitly `load-ingredients` after you set up the stack. An alternative syntax is what the above example is converted to internally: <img alt='fahrenheit to celsius desugared' src='html/f2c-2.png'> The header gets dropped after checking types at call-sites, and after replacing `load-ingredients` with explicit instructions to load each ingredient separately, and to explicitly return products to the caller. After this translation functions are once again just lists of instructions. This alternative syntax isn't just an implementation detail. I've actually found it easier to teach functions to non-programmers by starting with this syntax, so that they can visualize a pipe from caller to callee, and see the names of variables get translated one by one through the pipe. --- A third example, this time illustrating conditionals: <img alt='factorial example' src='html/factorial.png'> In spite of how it looks, this is still just a list of instructions and labels. Internally, the instructions `break` and `loop` get converted to `jump` instructions to after the enclosing `}` or `{` labels, respectively. Try out the factorial program now: ```shell $ ./mu factorial.mu result: 120 # factorial of 5 ``` You can also run its unit tests: ```shell $ ./mu test factorial.mu ``` Here's what one of the tests inside `factorial.mu` looks like: <img alt='test example' src='html/factorial-test.png'> Every test conceptually spins up a really lightweight virtual machine, so you can do things like check the value of specific locations in memory. You can also print to screen and check that the screen contains what you expect at the end of a test. For example, you've seen earlier how `chessboard.mu` checks the initial position of a game of chess (delimiting the edges of the screen with dots): <img alt='screen test' src='html/chessboard-test.png'> Similarly you can fake the keyboard to pretend someone typed something: <img alt='fake keyboard' src='html/fake-keyboard.png'> ..or clicked somewhere: <img alt='fake console (keyboard, mouse, ..)' src='html/fake-console.png'> A fake file-system can map arbitrary paths to contents: <img alt='fake file-system' src='html/fake-filesystem.png'> As we add network support, graphics, audio, and so on, we'll augment scenarios with corresponding abilities. --- Mu assumes that all ingredients passed in to functions are immutable by default -- *unless* they are also products. So this program will throw an error: <img alt='immutable ingredient triggering an error' width='75%' src='html/immutable-error.png'> To modify `foo`'s ingredient, you have to add it to the list of products returned: <img alt='mutable ingredient' width='75%' src='html/mutable.png'> The names of the variables are important here: a function that takes an (immutable) address and returns a different one is different from a function that takes a mutable address (and also returns it). Immutability checks can be annoying sometimes, but the benefit they provide is that you always know what a function modifies just by looking at its header. They provide all the benefits of [referential transparency](https://en.wikipedia.org/wiki/Referential_transparency) that we typically associate with (particularly purely functional) high-level languages -- but without giving up the flexibility to imperatively modify variables willy-nilly. --- You can append arbitrary properties to reagents besides types and spaces. Just separate them with slashes. ```nim x:array:number:3/uninitialized y:string/tainted:yes z:number/assign-once:true/assigned:false ``` Most properties are meaningless to Mu, and it'll silently skip them when running, but they are fodder for *meta-programs* to check or modify your programs, a task other languages typically hide from their programmers. For example, where other programmers are restricted to the checks their type system permits and forces them to use, you'll learn to create new checks that make sense for your specific program. If it makes sense to perform different checks in different parts of your program, you'll be able to do that. You can imagine each reagent as a table, rows separated by slashes, columns within a row separated by colons. So the last example above would become something like this: ``` z : integer / assign-once : true / assigned : false ``` --- An alternative way to define factorial is by inserting labels and later inserting code at them. <img alt='literate programming' src='html/tangle.png'> (You'll find this version in `tangle.mu`.) By convention we use the prefix '+' to indicate function-local label names you can jump to, and surround in '<>' global label names for inserting code at. --- Another example, this time with concurrency: <img alt='forking concurrent routines' src='html/fork.png'> ```shell $ ./mu fork.mu ``` Notice that it repeatedly prints either '34' or '35' at random. Hit ctrl-c to stop. [Yet another example](http://akkartik.github.io/mu/html/channel.mu.html) forks two 'routines' that communicate over a channel: ```shell $ ./mu channel.mu produce: 0 produce: 1 produce: 2 produce: 3 consume: 0 consume: 1 consume: 2 produce: 4 consume: 3 consume: 4 # The exact order above might shift over time, but you'll never see a number # consumed before it's produced. ``` Channels are the unit of synchronization in Mu. Blocking on a channel is the only way for the OS to put a task to sleep. The plan is to do all I/O over channels. Routines are expected to communicate purely by message passing, though nothing stops them from sharing memory since all routines share a common address space. However, idiomatic Mu will make it hard to accidentally read or clobber random memory locations. Bounds checking is baked deeply into the semantics, and pointers can never be invalidated. --- Mu has a programming environment: ```shell $ ./mu edit ``` Screenshot: <img alt='programming environment' src='html/edit.png'> You write functions on the left and try them out in *sandboxes* on the right. Hit F4 to rerun all sandboxes with the latest version of the code. More details: http://akkartik.name/post/mu. Beware, it won't save your edits by default. But if you create a sub-directory called `lesson/` under `mu/` it will. If you turn that directory into a git repo with `git init`, it will also back up your changes each time you hit F4. Use the provided `new_lesson` script to take care of these details. Once you have a sandbox you can click on its result to mark it as expected: <img alt='expected result' src='html/expected-result.png'> Later if the result changes it'll be flagged in red to draw your attention to it. Thus, manually tested sandboxes become reproducible automated tests. <img alt='unexpected result' src='html/unexpected-result.png'> Another feature: Clicking on the code in a sandbox expands its trace for you to browse. To add to the trace, use `stash`. For example: ```nim stash [first ingredient is], x ``` Invaluable for understanding complex control flow without cluttering up the screen. --- If you're still reading, here are some more things to check out: a) Look at the [chessboard program](http://akkartik.github.io/mu/html/chessboard.mu.html) for a more complex example where I write tests showing blocking reads from the keyboard and what gets printed to the screen -- things we don't typically associate with automated tests. b) Try skimming the [colorized source code](https://akkartik.github.io/mu). I'd like it to eventually be possible to get a pretty good sense for how things work just by skimming the files in order, skimming the top of each file and ignoring details lower down. Tell me how successful my efforts are. c) Try running the tests: ```shell $ ./mu test ``` The next major milestone on Mu's roadmap is dependency-injected interfaces for the network. **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. - Rust for demonstrating that a system-programming language can be safe.