https://github.com/akkartik/mu/blob/main/linux/bootstrap/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 //: More information: http://akkartik.name/post/wart-layers
     92
     93 // Includes
     94 // End Includes
     95
     96 // Types
     97 // End Types
     98
     99 // Function prototypes are auto-generated in the 'build' script; define your
    100 // functions in any order. Just be sure to declare each function header all on
    101 // one line, ending with the '{'. Our auto-generation scripts are too minimal
    102 // and simple-minded to handle anything else.
    103 #include "function_list"  // by convention, files ending with '_list' are auto-generated
    104
    105 // Globals
    106 //
    107 // All statements in this section should always define a single variable on a
    108 // single line. The 'build' script will simple-mindedly auto-generate extern
    109 // declarations for them. Remember to define (not just declare) constants with
    110 // extern linkage in this section, since C++ global constants have internal
    111 // linkage by default.
    112 //
    113 // End Globals
    114
    115 int main(int argc, char* argv[]) {
    116   atexit(reset);
    117   // we require a 32-bit little-endian system
    118   assert(sizeof(int) == 4);
    119   assert(sizeof(float) == 4);
    120   assert_little_endian();
    121
    122   // End One-time Setup
    123
    124   // Commandline Parsing
    125   // End Commandline Parsing
    126
    127   // End Main
    128
    129   return 0;
    130 }
    131
    132 // Unit Tests
    133 // End Unit Tests
    134
    135 //: our first directive; insert the following headers at the start of the program
    136 :(before "End Includes")
    137 #include <assert.h>
    138 #include <stdlib.h>
    139
    140 //: Without directives or with the :(code) directive, lines get added at the
    141 //: end.
    142 //:
    143 //: Regardless of where functions are defined, we can call them anywhere we
    144 //: like as long as we format the function header in a specific way: put it
    145 //: all on a single line without indent, end the line with ') {' and no
    146 //: trailing whitespace. As long as functions uniformly start this way, our
    147 //: 'build' script contains a little command to automatically generate
    148 //: declarations for them.
    149 :(code)
    150 void reset() {
    151   // End Reset
    152 }
    153
    154 void assert_little_endian() {
    155   const int x = 1;
    156   const char* y = reinterpret_cast<const char*>(&x);
    157   if (*y != 1) {
    158     cerr << "SubX requires a little-endian processor. Do you have Intel (or AMD or Atom) inside?\n";
    159     exit(1);
    160   }
    161 }
    162 :(before "End Includes")
    163 #include<iostream>
    164 using std::cerr;