https://github.com/akkartik/mu/blob/master/subx/000organization.cc

      1 //: You guessed right: the '000' prefix means you should start reading here.
      2 //:
      3 //: This project is set up to load all files with a numeric prefix. Just
      4 //: create a new file and start hacking.
      5 //:
      6 //: The first few files (00*) are independent of what this program does, an
      7 //: experimental skeleton that will hopefully make it both easier for others to
      8 //: understand and more malleable, easier to rewrite and remould into radically
      9 //: different shapes without breaking in subtle corner cases. The premise is
     10 //: that understandability and rewrite-friendliness are related in a virtuous
     11 //: cycle. Doing one well makes it easier to do the other.
     12 //:
     13 //: Lower down, this file contains a legal, bare-bones C++ program. It doesn't
     14 //: do anything yet; subsequent files will contain :(...) directives to insert
     15 //: lines into it. For example:
     16 //:   :(after "more events")
     17 //: This directive means: insert the following lines after a line in the
     18 //: program containing the words "more events".
     19 //:
     20 //: A simple tool is included to 'tangle' all the files together in sequence
     21 //: according to their directives into a single source file containing all the
     22 //: code for the project, and then feed the source file to the compiler.
     23 //: (It'll drop these comments starting with a '//:' prefix that only make
     24 //: sense before tangling.)
     25 //:
     26 //: Directives free up the programmer to order code for others to read rather
     27 //: than as forced by the computer or compiler. Each individual feature can be
     28 //: organized in a self-contained 'layer' that adds code to many different data
     29 //: structures and functions all over the program. The right decomposition into
     30 //: layers will let each layer make sense in isolation.
     31 //:
     32 //:   "If I look at any small part of it, I can see what is going on -- I don't
     33 //:   need to refer to other parts to understand what something is doing.
     34 //:
     35 //:   If I look at any large part in overview, I can see what is going on -- I
     36 //:   don't need to know all the details to get it.
     37 //:
     38 //:   Every level of detail is as locally coherent and as well thought-out as
     39 //:   any other level."
     40 //:
     41 //:       -- Richard Gabriel, "The Quality Without A Name"
     42 //:          (http://dreamsongs.com/Files/PatternsOfSoftware.pdf, page 42)
     43 //:
     44 //: Directives are powerful; they permit inserting or modifying any point in
     45 //: the program. Using them tastefully requires mapping out specific lines as
     46 //: waypoints for future layers to hook into. Often such waypoints will be in
     47 //: comments, capitalized to hint that other layers rely on their presence.
     48 //:
     49 //: A single waypoint might have many different code fragments hooking into
     50 //: it from all over the codebase. Use 'before' directives to insert
     51 //: code at a location in order, top to bottom, and 'after' directives to
     52 //: insert code in reverse order. By convention waypoints intended for insertion
     53 //: before begin with 'End'. Notice below how the layers line up above the "End
     54 //: Foo" waypoint.
     55 //:
     56 //:   File 001          File 002                File 003
     57 //:   ============      ===================     ===================
     58 //:   // Foo
     59 //:   ------------
     60 //:              <----  :(before "End Foo")
     61 //:                     ....
     62 //:                     ...
     63 //:   ------------
     64 //:              <----------------------------  :(before "End Foo")
     65 //:                                             ....
     66 //:                                             ...
     67 //:   // End Foo
     68 //:   ============
     69 //:
     70 //: Here's part of a layer in color: http://i.imgur.com/0eONnyX.png. Directives
     71 //: are shaded dark.
     72 //:
     73 //: Layers do more than just shuffle code around. In a well-organized codebase
     74 //: it should be possible to stop loading after any file/layer, build and run
     75 //: the program, and pass all tests for loaded features. (Relevant is
     76 //: http://youtube.com/watch?v=c8N72t7aScY, a scene from "2001: A Space
     77 //: Odyssey".) Get into the habit of running the included script called
     78 //: 'test_layers' before you commit any changes.
     79 //:
     80 //: This 'subsetting guarantee' ensures that this directory contains a
     81 //: cleaned-up narrative of the evolution of this codebase. Organizing
     82 //: autobiographically allows newcomers to rapidly orient themselves, reading
     83 //: the first few files to understand a simple gestalt of a program's core
     84 //: purpose and features, and later gradually working their way through other
     85 //: features as the need arises.
     86 //:
     87 //: Programmers shouldn't need to understand everything about a program to
     88 //: hack on it. But they shouldn't be prevented from a thorough understanding
     89 //: of each aspect either. The goal of layers is to reward curiosity.
     90
     91 // Includes
     92 // End Includes
     93
     94 // Types
     95 // End Types
     96
     97 // Function prototypes are auto-generated in the 'build' script; define your
     98 // functions in any order. Just be sure to declare each function header all on
     99 // one line, ending with the '{'. Our auto-generation scripts are too minimal
    100 // and simple-minded to handle anything else.
    101 #include "function_list"  // by convention, files ending with '_list' are auto-generated
    102
    103 // Globals
    104 //
    105 // All statements in this section should always define a single variable on a
    106 // single line. The 'build' script will simple-mindedly auto-generate extern
    107 // declarations for them. Remember to define (not just declare) constants with
    108 // extern linkage in this section, since C++ global constants have internal
    109 // linkage by default.
    110 //
    111 // End Globals
    112
    113 int main(int argc, char* argv[]) {
    114   atexit(reset);
    115   // we require a 32-bit little-endian system
    116   assert(sizeof(int) == 4);
    117   assert(sizeof(float) == 4);
    118   assert_little_endian();
    119
    120   // End One-time Setup
    121
    122   // Commandline Parsing
    123   // End Commandline Parsing
    124
    125   // End Main
    126
    127   return 0;
    128 }
    129
    130 // Unit Tests
    131 // End Unit Tests
    132
    133 //: our first directive; insert the following headers at the start of the program
    134 :(before "End Includes")
    135 #include <assert.h>
    136 #include <stdlib.h>
    137
    138 //: Without directives or with the :(code) directive, lines get added at the
    139 //: end.
    140 //:
    141 //: Regardless of where functions are defined, we can call them anywhere we
    142 //: like as long as we format the function header in a specific way: put it
    143 //: all on a single line without indent, end the line with ') {' and no
    144 //: trailing whitespace. As long as functions uniformly start this way, our
    145 //: 'build' script contains a little command to automatically generate
    146 //: declarations for them.
    147 :(code)
    148 void reset() {
    149   // End Reset
    150 }
    151
    152 void assert_little_endian() {
    153   const int x = 1;
    154   const char* y = reinterpret_cast<const char*>(&x);
    155   if (*y != 1) {
    156     cerr << "SubX requires a little-endian processor. Do you have Intel (or AMD or Atom) inside?\n";
    157     exit(1);
    158   }
    159 }
    160 :(before "End Includes")
    161 #include<iostream>
    162 using std::cerr;