diff options
-rw-r--r-- | subx/010---vm.cc (renamed from subx/010vm.cc) | 0 | ||||
-rw-r--r-- | subx/028translate.cc (renamed from subx/029translate.cc) | 65 | ||||
-rw-r--r-- | subx/029transforms.cc | 65 |
3 files changed, 65 insertions, 65 deletions
diff --git a/subx/010vm.cc b/subx/010---vm.cc index c467255b..c467255b 100644 --- a/subx/010vm.cc +++ b/subx/010---vm.cc diff --git a/subx/029translate.cc b/subx/028translate.cc index 1d5e940e..f3e30126 100644 --- a/subx/029translate.cc +++ b/subx/028translate.cc @@ -35,71 +35,6 @@ if (is_equal(argv[1], "translate")) { return 0; } -//: Ordering transforms is a well-known hard problem when building compilers. -//: In our case we also have the additional notion of layers. The ordering of -//: layers can have nothing in common with the ordering of transforms when -//: SubX is tangled and run. This can be confusing for readers, particularly -//: if later layers start inserting transforms at arbitrary points between -//: transforms introduced earlier. Over time adding transforms can get harder -//: and harder, having to meet the constraints of everything that's come -//: before. It's worth thinking about organization up-front so the ordering is -//: easy to hold in our heads, and it's obvious where to add a new transform. -//: Some constraints: -//: -//: 1. Layers force us to build SubX bottom-up; since we want to be able to -//: build and run SubX after stopping loading at any layer, the overall -//: organization has to be to introduce primitives before we start using -//: them. -//: -//: 2. Transforms usually need to be run top-down, converting high-level -//: representations to low-level ones so that low-level layers can be -//: oblivious to them. -//: -//: 3. When running we'd often like new representations to be checked before -//: they are transformed away. The whole reason for new representations is -//: often to add new kinds of automatic checking for our machine code -//: programs. -//: -//: Putting these constraints together, we'll use the following broad -//: organization: -//: -//: a) We'll divide up our transforms into "levels", each level consisting -//: of multiple transforms, and dealing in some new set of representational -//: ideas. Levels will be added in reverse order to the one their transforms -//: will be run in. -//: -//: To run all transforms: -//: Load transforms for level n -//: Load transforms for level n-1 -//: ... -//: Load transforms for level 2 -//: Run code at level 1 -//: -//: b) *Within* a level we'll usually introduce transforms in the order -//: they're run in. -//: -//: To run transforms for level n: -//: Perform transform of layer l -//: Perform transform of layer l+1 -//: ... -//: -//: c) Within a level it's often most natural to introduce a new -//: representation by showing how it's transformed to the level below. To -//: make such exceptions more obvious checks usually won't be first-class -//: transforms; instead code that keeps the program unmodified will run -//: within transforms before they mutate the program. -//: -//: Level l transforms programs -//: Level l+1 inserts checks to run *before* the transform of level l runs -//: -//: This may all seem abstract, but will hopefully make sense over time. The -//: goals are basically to always have a working program after any layer, to -//: have the order of layers make narrative sense, and to order transforms -//: correctly at runtime. -:(before "End One-time Setup") -// Begin Transforms -// End Transforms - :(code) // write out a program to a bare-bones ELF file void save_elf(const program& p, const char* filename) { diff --git a/subx/029transforms.cc b/subx/029transforms.cc new file mode 100644 index 00000000..9546ea91 --- /dev/null +++ b/subx/029transforms.cc @@ -0,0 +1,65 @@ +//: Ordering transforms is a well-known hard problem when building compilers. +//: In our case we also have the additional notion of layers. The ordering of +//: layers can have nothing in common with the ordering of transforms when +//: SubX is tangled and run. This can be confusing for readers, particularly +//: if later layers start inserting transforms at arbitrary points between +//: transforms introduced earlier. Over time adding transforms can get harder +//: and harder, having to meet the constraints of everything that's come +//: before. It's worth thinking about organization up-front so the ordering is +//: easy to hold in our heads, and it's obvious where to add a new transform. +//: Some constraints: +//: +//: 1. Layers force us to build SubX bottom-up; since we want to be able to +//: build and run SubX after stopping loading at any layer, the overall +//: organization has to be to introduce primitives before we start using +//: them. +//: +//: 2. Transforms usually need to be run top-down, converting high-level +//: representations to low-level ones so that low-level layers can be +//: oblivious to them. +//: +//: 3. When running we'd often like new representations to be checked before +//: they are transformed away. The whole reason for new representations is +//: often to add new kinds of automatic checking for our machine code +//: programs. +//: +//: Putting these constraints together, we'll use the following broad +//: organization: +//: +//: a) We'll divide up our transforms into "levels", each level consisting +//: of multiple transforms, and dealing in some new set of representational +//: ideas. Levels will be added in reverse order to the one their transforms +//: will be run in. +//: +//: To run all transforms: +//: Load transforms for level n +//: Load transforms for level n-1 +//: ... +//: Load transforms for level 2 +//: Run code at level 1 +//: +//: b) *Within* a level we'll usually introduce transforms in the order +//: they're run in. +//: +//: To run transforms for level n: +//: Perform transform of layer l +//: Perform transform of layer l+1 +//: ... +//: +//: c) Within a level it's often most natural to introduce a new +//: representation by showing how it's transformed to the level below. To +//: make such exceptions more obvious checks usually won't be first-class +//: transforms; instead code that keeps the program unmodified will run +//: within transforms before they mutate the program. +//: +//: Level l transforms programs +//: Level l+1 inserts checks to run *before* the transform of level l runs +//: +//: This may all seem abstract, but will hopefully make sense over time. The +//: goals are basically to always have a working program after any layer, to +//: have the order of layers make narrative sense, and to order transforms +//: correctly at runtime. + +:(before "End One-time Setup") +// Begin Transforms +// End Transforms |