932 - clean up comments in the tangled c++
This commit is contained in:
parent
b589f25a00
commit
3c435756bc
|
@ -1,86 +1,89 @@
|
|||
// You guessed right: the '000' prefix means you should start reading here.
|
||||
//
|
||||
// This project is setup to load all files with a numeric prefix. Just create
|
||||
// a new file and start hacking.
|
||||
//
|
||||
// The first few files (00*) are independent of what this program does, an
|
||||
// experimental skeleton that will hopefully make it both easier for others to
|
||||
// understand and more malleable, easier to rewrite and remould into radically
|
||||
// different shapes without breaking in subtle corner cases. The premise is
|
||||
// that understandability and rewrite-friendliness are related in a virtuous
|
||||
// cycle. Doing one well makes it easier to do the other.
|
||||
//
|
||||
// Lower down, this file contains a legal, bare-bones C++ program. It doesn't
|
||||
// do anything yet; subsequent files will add behaviors by inserting lines
|
||||
// into it with directives like:
|
||||
// :(after "more events")
|
||||
// This will insert the following lines after a line in the program containing
|
||||
// the words "more events".
|
||||
//
|
||||
// Directives free up the programmer to order code for others to read rather
|
||||
// than as forced by the computer or compiler. Each individual feature can be
|
||||
// organized in a self-contained 'layer' that adds code to many different data
|
||||
// structures and functions all over the program. The right decomposition into
|
||||
// layers will let each layer make sense in isolation.
|
||||
//
|
||||
// "If I look at any small part of it, I can see what is going on -- I don't
|
||||
// need to refer to other parts to understand what something is doing.
|
||||
//
|
||||
// If I look at any large part in overview, I can see what is going on -- I
|
||||
// don't need to know all the details to get it.
|
||||
//
|
||||
// Every level of detail is as locally coherent and as well thought-out as
|
||||
// any other level."
|
||||
//
|
||||
// -- Richard Gabriel, "The Quality Without A Name"
|
||||
// (http://dreamsongs.com/Files/PatternsOfSoftware.pdf, page 42)
|
||||
//
|
||||
// Directives are powerful; they permit inserting or modifying any point in
|
||||
// the program. Using them tastefully requires mapping out specific lines as
|
||||
// waypoints for future layers to hook into. Often such waypoints will be in
|
||||
// comments, capitalized to hint that other layers rely on their presence.
|
||||
//
|
||||
// A single waypoint might have many different code fragments hooking into
|
||||
// it from all over the codebase. Use 'before' directives to insert
|
||||
// code at a location in order, top to bottom, and 'after' directives to
|
||||
// insert code in reverse order. By convention waypoints intended for insertion
|
||||
// before begin with 'End'. Notice below how the layers line up above the "End
|
||||
// Foo" waypoint.
|
||||
//
|
||||
// File 001 File 002 File 003
|
||||
// ============ =================== ===================
|
||||
// // Foo
|
||||
// ------------
|
||||
// <---- :(before "End Foo")
|
||||
// ....
|
||||
// ...
|
||||
// ------------
|
||||
// <---------------------------- :(before "End Foo")
|
||||
// ....
|
||||
// ...
|
||||
// // End Foo
|
||||
// ============
|
||||
//
|
||||
// Here's part of a layer in color: http://i.imgur.com/0eONnyX.png. Directives
|
||||
// are shaded dark. Notice the references to waypoints lower down in this
|
||||
// file.
|
||||
//
|
||||
// Layers do more than just shuffle code around. Past the initial skeleton of
|
||||
// this program (currently 00*-02*), it ought to be possible to stop loading
|
||||
// after any file/layer, build and run the program, and pass all tests for
|
||||
// loaded features. (Relevant is http://youtube.com/watch?v=c8N72t7aScY, a
|
||||
// scene from "2001: A Space Odyssey".)
|
||||
//
|
||||
// This 'subsetting guarantee' ensures that this directory contains a
|
||||
// cleaned-up narrative of the evolution of this codebase. Organizing
|
||||
// autobiographically allows a newcomer to rapidly orient himself, reading the
|
||||
// first few files to understand a simple gestalt of a program's core purpose
|
||||
// and features, and later gradually working his way through other features as
|
||||
// the need arises. Each step should be as simple as possible (but no simpler).
|
||||
//
|
||||
// Programmers shouldn't need to understand everything about a program to hack
|
||||
// on it. But they shouldn't be prevented from a thorough understanding of
|
||||
// each aspect either. The goal of layers is to reward curiosity.
|
||||
//: You guessed right: the '000' prefix means you should start reading here.
|
||||
//:
|
||||
//: This project is setup to load all files with a numeric prefix. Just create
|
||||
//: a new file and start hacking.
|
||||
//:
|
||||
//: The first few files (00*) are independent of what this program does, an
|
||||
//: experimental skeleton that will hopefully make it both easier for others to
|
||||
//: understand and more malleable, easier to rewrite and remould into radically
|
||||
//: different shapes without breaking in subtle corner cases. The premise is
|
||||
//: that understandability and rewrite-friendliness are related in a virtuous
|
||||
//: cycle. Doing one well makes it easier to do the other.
|
||||
//:
|
||||
//: Lower down, this file contains a legal, bare-bones C++ program. It doesn't
|
||||
//: do anything yet; subsequent files will add behaviors by inserting lines
|
||||
//: into it with directives like:
|
||||
//: :(after "more events")
|
||||
//: This will insert the following lines after a line in the program containing
|
||||
//: the words "more events".
|
||||
//: A simple tool will 'tangle' these files according to the directives, though
|
||||
//: it'll drop these comments starting with a '//:' prefix that only make sense
|
||||
//: in the context of layers.
|
||||
//:
|
||||
//: Directives free up the programmer to order code for others to read rather
|
||||
//: than as forced by the computer or compiler. Each individual feature can be
|
||||
//: organized in a self-contained 'layer' that adds code to many different data
|
||||
//: structures and functions all over the program. The right decomposition into
|
||||
//: layers will let each layer make sense in isolation.
|
||||
//:
|
||||
//: "If I look at any small part of it, I can see what is going on -- I don't
|
||||
//: need to refer to other parts to understand what something is doing.
|
||||
//:
|
||||
//: If I look at any large part in overview, I can see what is going on -- I
|
||||
//: don't need to know all the details to get it.
|
||||
//:
|
||||
//: Every level of detail is as locally coherent and as well thought-out as
|
||||
//: any other level."
|
||||
//:
|
||||
//: -- Richard Gabriel, "The Quality Without A Name"
|
||||
//: (http://dreamsongs.com/Files/PatternsOfSoftware.pdf, page 42)
|
||||
//:
|
||||
//: Directives are powerful; they permit inserting or modifying any point in
|
||||
//: the program. Using them tastefully requires mapping out specific lines as
|
||||
//: waypoints for future layers to hook into. Often such waypoints will be in
|
||||
//: comments, capitalized to hint that other layers rely on their presence.
|
||||
//:
|
||||
//: A single waypoint might have many different code fragments hooking into
|
||||
//: it from all over the codebase. Use 'before' directives to insert
|
||||
//: code at a location in order, top to bottom, and 'after' directives to
|
||||
//: insert code in reverse order. By convention waypoints intended for insertion
|
||||
//: before begin with 'End'. Notice below how the layers line up above the "End
|
||||
//: Foo" waypoint.
|
||||
//:
|
||||
//: File 001 File 002 File 003
|
||||
//: ============ =================== ===================
|
||||
//: // Foo
|
||||
//: ------------
|
||||
//: <---- :(before "End Foo")
|
||||
//: ....
|
||||
//: ...
|
||||
//: ------------
|
||||
//: <---------------------------- :(before "End Foo")
|
||||
//: ....
|
||||
//: ...
|
||||
//: // End Foo
|
||||
//: ============
|
||||
//:
|
||||
//: Here's part of a layer in color: http://i.imgur.com/0eONnyX.png. Directives
|
||||
//: are shaded dark. Notice the references to waypoints lower down in this
|
||||
//: file.
|
||||
//:
|
||||
//: Layers do more than just shuffle code around. Past the initial skeleton of
|
||||
//: this program (currently 00*-02*), it ought to be possible to stop loading
|
||||
//: after any file/layer, build and run the program, and pass all tests for
|
||||
//: loaded features. (Relevant is http://youtube.com/watch?v=c8N72t7aScY, a
|
||||
//: scene from "2001: A Space Odyssey".)
|
||||
//:
|
||||
//: This 'subsetting guarantee' ensures that this directory contains a
|
||||
//: cleaned-up narrative of the evolution of this codebase. Organizing
|
||||
//: autobiographically allows a newcomer to rapidly orient himself, reading the
|
||||
//: first few files to understand a simple gestalt of a program's core purpose
|
||||
//: and features, and later gradually working his way through other features as
|
||||
//: the need arises. Each step should be as simple as possible (but no simpler).
|
||||
//:
|
||||
//: Programmers shouldn't need to understand everything about a program to hack
|
||||
//: on it. But they shouldn't be prevented from a thorough understanding of
|
||||
//: each aspect either. The goal of layers is to reward curiosity.
|
||||
|
||||
// Includes
|
||||
// End Includes
|
||||
|
@ -102,5 +105,5 @@ void setup() {
|
|||
// End Setup
|
||||
}
|
||||
|
||||
// Without directives or with the :(code) directive, lines get added at the
|
||||
// end.
|
||||
//: Without directives or with the :(code) directive, lines get added at the
|
||||
//: end.
|
||||
|
|
167
cpp/002trace
167
cpp/002trace
|
@ -1,87 +1,86 @@
|
|||
// The goal of this skeleton is to make programs more easy to understand and
|
||||
// more malleable, easy to rewrite in radical ways without accidentally
|
||||
// breaking some corner case. Tests further both goals. They help
|
||||
// understandability by letting one make small changes and get feedback. What
|
||||
// if I wrote this line like so? What if I removed this function call, is it
|
||||
// really necessary? Just try it, see if the tests pass. Want to explore
|
||||
// rewriting this bit in this way? Tests put many refactorings on a firmer
|
||||
// footing.
|
||||
//
|
||||
// But the usual way we write tests seems incomplete. Refactorings tend to
|
||||
// work in the small, but don't help with changes to function boundaries. If
|
||||
// you want to extract a new function you have to manually test-drive it to
|
||||
// create tests for it. If you want to inline a function its tests are no
|
||||
// longer valid. In both cases you end up having to reorganize code as well as
|
||||
// tests, an error-prone activity.
|
||||
//
|
||||
// This file tries to fix this problem by supporting domain-driven testing
|
||||
// rather than coverage-driven testing. The goal isn't to test all possible
|
||||
// paths in the code any longer, but to focus on the domain of inputs the
|
||||
// program should work on. All tests invoke the program in a single way: by
|
||||
// calling run() with different inputs. The program operates on the input and
|
||||
// logs _facts_ it deduces to a trace:
|
||||
// trace("label") << "fact 1: " << val;
|
||||
//
|
||||
// The tests check for facts:
|
||||
// :(scenario foo)
|
||||
// 34 # call run() with this input
|
||||
// +label: fact 1: 34 # trace should have logged this at the end
|
||||
// -label: fact 1: 35 # trace should never contain such a line
|
||||
//
|
||||
// Since we never call anything but the run() function directly, we never have
|
||||
// to rewrite the tests when we reorganize the internals of the program. We
|
||||
// just have to make sure our rewrite deduces the same facts about the domain,
|
||||
// and that's something we're going to have to do anyway.
|
||||
//
|
||||
// To avoid the combinatorial explosion of integration tests, we organize the
|
||||
// program into different layers, and each fact is logged to the trace with a
|
||||
// specific label. Individual tests can focus on specific labels. In essence,
|
||||
// validating the facts logged with a specific label is identical to calling
|
||||
// some internal subsystem.
|
||||
//
|
||||
// Traces interact salubriously with layers. Thanks to our ordering
|
||||
// directives, each layer can contain its own tests. They may rely on other
|
||||
// layers, but when a test fails its usually due to breakage in the same
|
||||
// layer. When multiple tests fail, it's usually useful to debug the very
|
||||
// first test to fail. This is in contrast with the traditional approach,
|
||||
// where changes can cause breakages in faraway subsystems, and picking the
|
||||
// right test to debug can be an important skill to pick up.
|
||||
//
|
||||
// A final wrinkle is for recursive functions; it's often useful to segment
|
||||
// calls of different depth in the trace:
|
||||
// +eval/1: => 34 # the topmost call to eval should have logged this line
|
||||
// (look at new_trace_frame below)
|
||||
//
|
||||
// To build robust tests, trace facts about your domain rather than details of
|
||||
// how you computed them.
|
||||
//
|
||||
// More details: http://akkartik.name/blog/tracing-tests
|
||||
//
|
||||
// ---
|
||||
//
|
||||
// Between layers and domain-driven testing, programming starts to look like a
|
||||
// fundamentally different activity. Instead of a) superficial, b) local rules
|
||||
// on c) code [like http://blog.bbv.ch/2013/06/05/clean-code-cheat-sheet],
|
||||
// we allow programmers to engage with the a) deep, b) global structure of the
|
||||
// c) domain. If you can systematically track discontinuities in the domain
|
||||
// you don't care if the code used gotos as long as it passed the tests. If
|
||||
// tests become more robust to run it becomes easier to try out radically
|
||||
// different implementations for the same program. If code is super-easy to
|
||||
// rewrite, it becomes less important what indentation style it uses, or that
|
||||
// the objects are appropriately encapsulated, or that the functions are
|
||||
// referentially transparent.
|
||||
//
|
||||
// Instead of plumbing, programming becomes building and gradually refining a
|
||||
// map of the environment the program must operate under. Whether a program is
|
||||
// 'correct' at a given point in time is a red herring; what matters is
|
||||
// avoiding regression by monotonically nailing down the more 'eventful' parts
|
||||
// of the terrain. It helps readers new and old and rewards curiosity to
|
||||
// organize large programs in self-similar hiearchies of example scenarios
|
||||
// colocated with the code that makes them work.
|
||||
//
|
||||
// "Programming properly should be regarded as an activity by which
|
||||
// programmers form a mental model, rather than as production of a program."
|
||||
// -- Peter Naur (http://alistair.cockburn.us/ASD+book+extract%3A+%22Naur,+Ehn,+Musashi%22)
|
||||
//: The goal of this skeleton is to make programs more easy to understand and
|
||||
//: more malleable, easy to rewrite in radical ways without accidentally
|
||||
//: breaking some corner case. Tests further both goals. They help
|
||||
//: understandability by letting one make small changes and get feedback. What
|
||||
//: if I wrote this line like so? What if I removed this function call, is it
|
||||
//: really necessary? Just try it, see if the tests pass. Want to explore
|
||||
//: rewriting this bit in this way? Tests put many refactorings on a firmer
|
||||
//: footing.
|
||||
//:
|
||||
//: But the usual way we write tests seems incomplete. Refactorings tend to
|
||||
//: work in the small, but don't help with changes to function boundaries. If
|
||||
//: you want to extract a new function you have to manually test-drive it to
|
||||
//: create tests for it. If you want to inline a function its tests are no
|
||||
//: longer valid. In both cases you end up having to reorganize code as well as
|
||||
//: tests, an error-prone activity.
|
||||
//:
|
||||
//: This file tries to fix this problem by supporting domain-driven testing
|
||||
//: We try to focus on the domain of inputs the program should work on. All
|
||||
//: tests invoke the program in a single way: by calling run() with different
|
||||
//: inputs. The program operates on the input and logs _facts_ it deduces to a
|
||||
//: trace:
|
||||
//: trace("label") << "fact 1: " << val;
|
||||
//:
|
||||
//: The tests check for facts:
|
||||
//: :(scenario foo)
|
||||
//: 34 # call run() with this input
|
||||
//: +label: fact 1: 34 # trace should have logged this at the end
|
||||
//: -label: fact 1: 35 # trace should never contain such a line
|
||||
//:
|
||||
//: Since we never call anything but the run() function directly, we never have
|
||||
//: to rewrite the tests when we reorganize the internals of the program. We
|
||||
//: just have to make sure our rewrite deduces the same facts about the domain,
|
||||
//: and that's something we're going to have to do anyway.
|
||||
//:
|
||||
//: To avoid the combinatorial explosion of integration tests, we organize the
|
||||
//: program into different layers, and each fact is logged to the trace with a
|
||||
//: specific label. Individual tests can focus on specific labels. In essence,
|
||||
//: validating the facts logged with a specific label is identical to calling
|
||||
//: some internal subsystem.
|
||||
//:
|
||||
//: Traces interact salubriously with layers. Thanks to our ordering
|
||||
//: directives, each layer can contain its own tests. They may rely on other
|
||||
//: layers, but when a test fails its usually due to breakage in the same
|
||||
//: layer. When multiple tests fail, it's usually useful to debug the very
|
||||
//: first test to fail. This is in contrast with the traditional approach,
|
||||
//: where changes can cause breakages in faraway subsystems, and picking the
|
||||
//: right test to debug can be an important skill to pick up.
|
||||
//:
|
||||
//: A final wrinkle is for recursive functions; it's often useful to segment
|
||||
//: calls of different depth in the trace:
|
||||
//: +eval/1: => 34 # the topmost call to eval should have logged this line
|
||||
//: (look at new_trace_frame below)
|
||||
//:
|
||||
//: To build robust tests, trace facts about your domain rather than details of
|
||||
//: how you computed them.
|
||||
//:
|
||||
//: More details: http://akkartik.name/blog/tracing-tests
|
||||
//:
|
||||
//: ---
|
||||
//:
|
||||
//: Between layers and domain-driven testing, programming starts to look like a
|
||||
//: fundamentally different activity. Instead of a) superficial, b) local rules
|
||||
//: on c) code [like http://blog.bbv.ch/2013/06/05/clean-code-cheat-sheet],
|
||||
//: we allow programmers to engage with the a) deep, b) global structure of the
|
||||
//: c) domain. If you can systematically track discontinuities in the domain
|
||||
//: you don't care if the code used gotos as long as it passed the tests. If
|
||||
//: tests become more robust to run it becomes easier to try out radically
|
||||
//: different implementations for the same program. If code is super-easy to
|
||||
//: rewrite, it becomes less important what indentation style it uses, or that
|
||||
//: the objects are appropriately encapsulated, or that the functions are
|
||||
//: referentially transparent.
|
||||
//:
|
||||
//: Instead of plumbing, programming becomes building and gradually refining a
|
||||
//: map of the environment the program must operate under. Whether a program is
|
||||
//: 'correct' at a given point in time is a red herring; what matters is
|
||||
//: avoiding regression by monotonically nailing down the more 'eventful' parts
|
||||
//: of the terrain. It helps readers new and old and rewards curiosity to
|
||||
//: organize large programs in self-similar hiearchies of example scenarios
|
||||
//: colocated with the code that makes them work.
|
||||
//:
|
||||
//: "Programming properly should be regarded as an activity by which
|
||||
//: programmers form a mental model, rather than as production of a program."
|
||||
//: -- Peter Naur (http://alistair.cockburn.us/ASD+book+extract%3A+%22Naur,+Ehn,+Musashi%22)
|
||||
|
||||
:(before "int main")
|
||||
// End Tracing // hack to ensure most code in this layer comes before anything else
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
// Some common includes needed all over the place.
|
||||
// More tightly-targeted includes show up in other files.
|
||||
//: Some common includes needed all over the place.
|
||||
//: More tightly-targeted includes show up in other files.
|
||||
|
||||
:(before "End Includes")
|
||||
#include<assert.h>
|
||||
|
|
10
cpp/010vm
10
cpp/010vm
|
@ -56,7 +56,7 @@ unordered_map<int, int> Memory;
|
|||
Memory.clear();
|
||||
|
||||
:(after "Types")
|
||||
// Types encode how the numbers stored in different parts of memory are
|
||||
// Mu types encode how the numbers stored in different parts of memory are
|
||||
// interpreted. A location tagged as a 'character' type will interpret the
|
||||
// number 97 as the letter 'a', while a different location of type 'integer'
|
||||
// would not.
|
||||
|
@ -74,14 +74,14 @@ void setup_types() {
|
|||
Type.clear(); Type_number.clear();
|
||||
Type_number["literal"] = 0;
|
||||
Next_type_number = 1;
|
||||
// Mu Types.
|
||||
// Mu Types Initialization.
|
||||
int integer = Type_number["integer"] = Next_type_number++;
|
||||
Type[integer].size = 1;
|
||||
int address = Type_number["address"] = Next_type_number++;
|
||||
Type[address].size = 1;
|
||||
int boolean = Type_number["boolean"] = Next_type_number++;
|
||||
Type[boolean].size = 1;
|
||||
// End Mu Types.
|
||||
// End Mu Types Initialization.
|
||||
}
|
||||
:(before "End Setup")
|
||||
setup_types();
|
||||
|
@ -127,8 +127,10 @@ void setup_recipes() {
|
|||
|
||||
|
||||
|
||||
//: Helpers
|
||||
|
||||
:(code)
|
||||
// Helpers
|
||||
// indent members to avoid generating prototypes for them
|
||||
instruction::instruction() :is_label(false), operation(IDLE) {}
|
||||
void instruction::clear() { is_label=false; label.clear(); operation=IDLE; ingredients.clear(); products.clear(); }
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
// It's often convenient to express recipes in a textual fashion.
|
||||
//: It's often convenient to express recipes in a textual fashion.
|
||||
:(scenarios add_recipes)
|
||||
:(scenario first_recipe)
|
||||
recipe main [
|
||||
|
|
32
cpp/012run
32
cpp/012run
|
@ -19,7 +19,7 @@ recipe main [
|
|||
|
||||
:(before "End Types")
|
||||
// Book-keeping while running a recipe.
|
||||
// Later layers will change this.
|
||||
//: Later layers will change this.
|
||||
struct routine {
|
||||
recipe_number running_recipe;
|
||||
size_t running_at;
|
||||
|
@ -27,11 +27,6 @@ struct routine {
|
|||
};
|
||||
|
||||
:(code)
|
||||
void run(string form) {
|
||||
vector<recipe_number> recipes_added = add_recipes(form);
|
||||
run(recipes_added.front());
|
||||
}
|
||||
|
||||
void run(recipe_number r) {
|
||||
run(routine(r));
|
||||
}
|
||||
|
@ -59,9 +54,9 @@ void run(routine rr) {
|
|||
}
|
||||
}
|
||||
|
||||
// Some helpers.
|
||||
// We'll need to override these later as we change the definition of routine.
|
||||
// Important that they return referrences into the routine.
|
||||
//: Some helpers.
|
||||
//: We'll need to override these later as we change the definition of routine.
|
||||
//: Important that they return referrences into the routine.
|
||||
inline size_t& running_at(routine& rr) {
|
||||
return rr.running_at;
|
||||
}
|
||||
|
@ -92,6 +87,25 @@ if (argc > 1) {
|
|||
dump_memory();
|
||||
}
|
||||
|
||||
//: helper for tests
|
||||
|
||||
:(before "End Globals")
|
||||
vector<recipe_number> recipes_added_by_test;
|
||||
|
||||
:(code)
|
||||
void run(string form) {
|
||||
vector<recipe_number> tmp = add_recipes(form);
|
||||
recipes_added_by_test.insert(recipes_added_by_test.end(), tmp.begin(), tmp.end());
|
||||
run(recipes_added_by_test.front());
|
||||
}
|
||||
|
||||
:(before "End Setup")
|
||||
for (size_t i = 0; i < recipes_added_by_test.size(); ++i) {
|
||||
Recipe_number.erase(Recipe[recipes_added_by_test[i]].name);
|
||||
Recipe.erase(recipes_added_by_test[i]);
|
||||
}
|
||||
recipes_added_by_test.clear();
|
||||
|
||||
:(code)
|
||||
vector<int> read_memory(reagent x) {
|
||||
//? cout << "read_memory: " << x.to_string() << '\n'; //? 1
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
// Support for records.
|
||||
:(before "End Mu Types")
|
||||
//: Support for records.
|
||||
:(before "End Mu Types Initialization")
|
||||
// We'll use this record as a running example, with two integer fields
|
||||
int point = Type_number["point"] = Next_type_number++;
|
||||
Type[point].size = 2;
|
||||
|
@ -73,7 +73,7 @@ recipe main [
|
|||
+run: product 0 is 35
|
||||
+mem: storing in location 15
|
||||
|
||||
:(before "End Mu Types")
|
||||
:(before "End Mu Types Initialization")
|
||||
// A more complex record, containing another record.
|
||||
int point_integer = Type_number["point-integer"] = Next_type_number++;
|
||||
Type[point_integer].size = 2;
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
//: Instructions can read from addresses pointing at other locations using the
|
||||
//: 'deref' property.
|
||||
:(scenario "copy_indirect")
|
||||
# Instructions can read from addresses pointing at other locations using the 'deref' property.
|
||||
recipe main [
|
||||
1:address:integer <- copy 2:literal
|
||||
2:integer <- copy 34:literal
|
||||
|
@ -29,8 +30,9 @@ vector<int> read_memory(reagent x) {
|
|||
return result;
|
||||
}
|
||||
|
||||
//: similarly, write to addresses pointing at other locations using the
|
||||
//: 'deref' property
|
||||
:(scenario "store_indirect")
|
||||
# similarly, write to addresses pointing at other locations using the 'deref' property
|
||||
recipe main [
|
||||
1:address:integer <- copy 2:literal
|
||||
1:address:integer/deref <- copy 34:literal
|
||||
|
@ -95,8 +97,8 @@ reagent deref(reagent x) {
|
|||
return result;
|
||||
}
|
||||
|
||||
//: 'get' can read from record address
|
||||
:(scenario "get_indirect")
|
||||
# 'get' can read from record address
|
||||
recipe main [
|
||||
1:integer <- copy 2:literal
|
||||
2:integer <- copy 34:literal
|
||||
|
|
11
cpp/019array
11
cpp/019array
|
@ -1,13 +1,14 @@
|
|||
// Support for arrays.
|
||||
:(before "End Mu Types")
|
||||
// We'll use this array as a running example:
|
||||
//: Support for arrays.
|
||||
:(before "End Mu Types Initialization")
|
||||
//: We'll use this array as a running example:
|
||||
int integer_array = Type_number["integer-array"] = Next_type_number++;
|
||||
Type[integer_array].is_array = true;
|
||||
Type[integer_array].element.push_back(integer);
|
||||
|
||||
//: Arrays can be copied around with a single instruction just like integers,
|
||||
//: no matter how large they are.
|
||||
|
||||
:(scenario copy_array)
|
||||
# Arrays can be copied around with a single instruction just like integers,
|
||||
# no matter how large they are.
|
||||
recipe main [
|
||||
1:integer <- copy 3:literal
|
||||
2:integer <- copy 14:literal
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
// So far the recipes we define can't run each other. Let's change that.
|
||||
//: So far the recipes we define can't run each other. Let's change that.
|
||||
:(scenario "calling_recipe")
|
||||
recipe main [
|
||||
f
|
||||
|
@ -27,6 +27,7 @@ struct routine {
|
|||
calls.push(call(r));
|
||||
}
|
||||
};
|
||||
//: now update routine's helpers
|
||||
:(replace{} "inline size_t& running_at(routine& rr)")
|
||||
inline size_t& running_at(routine& rr) {
|
||||
return rr.calls.top().pc;
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
// Calls can take ingredients just like primitives. To access a recipe's
|
||||
// ingredients, use 'next_ingredient'.
|
||||
//: Calls can take ingredients just like primitives. To access a recipe's
|
||||
//: ingredients, use 'next_ingredient'.
|
||||
:(scenario "next_ingredient")
|
||||
recipe main [
|
||||
f 2:literal
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
// Calls can also generate results, using 'reply'.
|
||||
//: Calls can also generate results, using 'reply'.
|
||||
:(scenario "reply")
|
||||
recipe main [
|
||||
3:integer, 4:integer <- f 2:literal
|
||||
|
|
|
@ -5,7 +5,7 @@ mu: makefile tangle/tangle mu.cc
|
|||
# To see what the program looks like after all layers have been applied, read
|
||||
# mu.cc
|
||||
mu.cc: 0*
|
||||
./tangle/tangle --until 999 > mu.cc
|
||||
./tangle/tangle --until 999 |grep -v "^\s*//:" > mu.cc
|
||||
@make autogenerated_lists >/dev/null
|
||||
|
||||
tangle/tangle:
|
||||
|
|
Loading…
Reference in New Issue