about summary refs log tree commit diff stats
path: root/subx/examples/ex7.subx
Commit message (Collapse)AuthorAgeFilesLines
* 4973Kartik Agaram2019-02-151-3/+4
| | | | | Support immediate operands in the data segment in all the ways we support them in the code segment.
* 4893Kartik Agaram2018-12-301-2/+2
|
* 4824Kartik Agaram2018-12-031-7/+7
|
* 4808 - clean up comments in all subx filesKartik Agaram2018-11-301-10/+11
|
* 4802Kartik Agaram2018-11-301-4/+4
| | | | | | | | | | | | | | | | Some automated commenting cleanup. Still needs more careful manual scanning. sed -i 's/^# 1-3/# . 1-3/' *.subx */*.subx sed -i 's/^# op/# . op/' *.subx */*.subx sed -i 's/# vim/# . . vim/' *.subx */*.subx sed -i 's/^ # push args/ # . . push args/' *.subx */*.subx sed -i 's/^ # discard args/ # . . discard args/' *.subx */*.subx sed -i 's/^ # call/ # . . call/' *.subx */*.subx sed -i 's/^ # prolog/ # . prolog/' *.subx */*.subx sed -i 's/^ # epilog/ # . epilog/' *.subx */*.subx sed -i 's/^ # save registers/ # . save registers/' *.subx */*.subx sed -i 's/^ # restore registers/ # . restore registers/' *.subx */*.subx sed -i 's/ operand / register /' *.subx */*.subx
* 4801Kartik Agaram2018-11-301-61/+61
| | | | Reindent all SubX code to make some room for the new comment style.
* 4780Kartik Agaram2018-11-261-0/+1
|
* 4757Kartik Agaram2018-11-201-25/+25
| | | | | | Let's start highlighting all global variables in Red. Assembly programming has a tendency to over-use them. They're a necessary evil, but we should minimize the number of functions that access them.
* 4698Kartik Agaram2018-10-141-9/+9
|
* 4669Kartik Agaram2018-10-051-7/+7
|
* 4668Kartik Agaram2018-10-051-29/+29
|
* 4662Kartik Agaram2018-10-051-1/+1
|
* 4644Kartik Agaram2018-10-011-14/+14
|
* 4643Kartik Agaram2018-10-011-2/+2
|
* 4639Kartik Agaram2018-10-011-3/+3
|
* 4624Kartik Agaram2018-09-301-1/+1
| | | | | | | | Start requiring a '-o' flag to designate the output binary when translating. Things currently get funky if you pass in multiple inputs, but that's ok. This is the first step to supporting multiple input files for a single output binary.
* 4581Kartik Agaram2018-09-211-9/+9
| | | | | | | | | | | | Even more cuddling. We want to keep lines short where the opcode and operands are self-explanatory. If there are any implicit registers, etc., we'll continue to do the table layout. The first two columns look messy now; let's see how this goes. Maybe I'll give up on the tabular layout altogether, just string args with a single space.
* 4564Kartik Agaram2018-09-201-4/+4
|
* 4561Kartik Agaram2018-09-201-21/+21
|
* 4535 - support for global variable namesKartik Agaram2018-09-011-34/+38
|
* 4531 - automatically compute segment addressesKartik Agaram2018-09-011-1/+1
|
* 4530 - create an apps/ directoryKartik Agaram2018-09-011-52/+87
|
* 4529 - move examples to a sub-directoryKartik Agaram2018-09-011-0/+64
m; no need to snapshot :(before "End Reset") Types_by_space.clear(); :(before "End transform_all") Types_by_space.clear(); :(before "End Types") struct name_lt { bool operator()(const reagent& a, const reagent& b) const { return a.name < b.name; } }; :(code) void check_or_set_types_by_name(const recipe_ordinal r) { recipe& caller = get(Recipe, r); trace(9991, "transform") << "--- deduce types for recipe " << caller.name << end(); for (int i = 0; i < SIZE(caller.steps); ++i) { instruction& inst = caller.steps.at(i); for (int in = 0; in < SIZE(inst.ingredients); ++in) check_or_set_type(inst.ingredients.at(in), caller); for (int out = 0; out < SIZE(inst.products); ++out) check_or_set_type(inst.products.at(out), caller); } } void check_or_set_type(reagent& curr, const recipe& caller) { if (is_literal(curr)) return; if (is_integer(curr.name)) return; // no type-checking for raw locations set<reagent, name_lt>& known_types = Types_by_space[owning_recipe(curr, caller.ordinal)]; deduce_missing_type(known_types, curr, caller); check_type(known_types, curr, caller); } void deduce_missing_type(set<reagent, name_lt>& known_types, reagent& x, const recipe& caller) { // Deduce Missing Type(x, caller) if (x.type) return; if (is_jump_target(x.name)) { x.type = new type_tree("label"); return; } if (known_types.find(x) == known_types.end()) return; const reagent& exemplar = *known_types.find(x); x.type = new type_tree(*exemplar.type); trace(9992, "transform") << x.name << " <= " << names_to_string(x.type) << end(); // spaces are special; their type includes their /names property if (is_mu_space(x) && !has_property(x, "names")) { if (!has_property(exemplar, "names")) { raise << maybe(caller.name) << "missing /names property for space variable '" << exemplar.name << "'\n" << end(); return; } x.properties.push_back(pair<string, string_tree*>("names", new string_tree(*property(exemplar, "names")))); } } void check_type(set<reagent, name_lt>& known_types, const reagent& x, const recipe& caller) { if (is_literal(x)) return; if (!x.type) return; // might get filled in by other logic later if (is_jump_target(x.name)) { if (!x.type->atom || x.type->name != "label") raise << maybe(caller.name) << "non-label '" << x.name << "' must begin with a letter\n" << end(); return; } if (known_types.find(x) == known_types.end()) { trace(9992, "transform") << x.name << " => " << names_to_string(x.type) << end(); known_types.insert(x); } if (!types_strictly_match(known_types.find(x)->type, x.type)) { raise << maybe(caller.name) << "'" << x.name << "' used with multiple types\n" << end(); raise << " " << to_string(known_types.find(x)->type) << " vs " << to_string(x.type) << '\n' << end(); return; } if (is_mu_array(x)) { if (!x.type->right) { raise << maybe(caller.name) << "'" << x.name << ": can't be just an array. What is it an array of?\n" << end(); return; } if (!x.type->right->right) { raise << caller.name << " can't determine the size of array variable '" << x.name << "'. Either allocate it separately and make the type of '" << x.name << "' an address, or specify the length of the array in the type of '" << x.name << "'.\n" << end(); return; } } } recipe_ordinal owning_recipe(const reagent& x, recipe_ordinal r) { for (int s = space_index(x); s > 0; --s) { if (!contains_key(Surrounding_space, r)) break; // error raised elsewhere r = Surrounding_space[r]; } return r; } :(scenario transform_fills_in_missing_types) def main [ x:num <- copy 11 y:num <- add x, 1 ] # x is in location 2, y in location 3 +mem: storing 12 in location 3 :(scenario transform_fills_in_missing_types_in_product) def main [ x:num <- copy 11 x <- copy 12 ] # x is in location 2 +mem: storing 12 in location 2 :(scenario transform_fills_in_missing_types_in_product_and_ingredient) def main [ x:num <- copy 11 x <- add x, 1 ] # x is in location 2 +mem: storing 12 in location 2 :(scenario transform_fills_in_missing_label_type) def main [ jump +target 1:num <- copy 0 +target ] -mem: storing 0 in location 1 :(scenario transform_fails_on_missing_types_in_first_mention) % Hide_errors = true; def main [ x <- copy 1 x:num <- copy 2 ] +error: main: missing type for 'x' in 'x <- copy 1' :(scenario transform_fails_on_wrong_type_for_label) % Hide_errors = true; def main [ +foo:num <- copy 34 ] +error: main: non-label '+foo' must begin with a letter :(scenario typo_in_address_type_fails) % Hide_errors = true; def main [ y:&:charcter <- new character:type *y <- copy 67 ] +error: main: unknown type charcter in 'y:&:charcter <- new character:type' :(scenario array_type_without_size_fails) % Hide_errors = true; def main [ x:@:num <- merge 2, 12, 13 ] +error: main can't determine the size of array variable 'x'. Either allocate it separately and make the type of 'x' an address, or specify the length of the array in the type of 'x'. :(scenarios transform) :(scenario transform_checks_types_of_identical_reagents_in_multiple_spaces) def foo [ # dummy ] def main [ local-scope 0:space/names:foo <- copy null # specify surrounding space x:bool <- copy true x:num/space:1 <- copy 34 x/space:1 <- copy 35 ] $error: 0 :(scenario transform_handles_empty_reagents) % Hide_errors = true; def main [ add * ] +error: illegal name '*' # no crash :(scenario transform_checks_types_in_surrounding_spaces) % Hide_errors = true; # 'x' is a bool in foo's space def foo [ local-scope x:bool <- copy false return default-space/names:foo ] # try to read 'x' as a num in foo's space def main [ local-scope 0:space/names:foo <- foo x:num/space:1 <- copy 34 ] error: foo: 'x' used with multiple types