about summary refs log tree commit diff stats
path: root/058shape_shifting_container.cc
diff options
context:
space:
mode:
authorKartik K. Agaram <vc@akkartik.com>2016-03-08 01:30:14 -0800
committerKartik K. Agaram <vc@akkartik.com>2016-03-08 01:46:47 -0800
commit1ead356219bb2eb59487d1012f837bd07ec336f5 (patch)
treeaf15f390b81e4d6b3e0940c5756a0d7fd1060bb5 /058shape_shifting_container.cc
parent27ba0937a3747684f299bb7a8b3cdd0fbb689db3 (diff)
downloadmu-1ead356219bb2eb59487d1012f837bd07ec336f5.tar.gz
2735 - define recipes using 'def'
I'm dropping all mention of 'recipe' terminology from the Readme. That
way I hope to avoid further bike-shedding discussions while I very
slowly decide on the right terminology with my students.

I could be smarter in my error messages and use 'recipe' when code uses
it and 'function' otherwise. But what about other words like ingredient?
It would all add complexity that I'm not yet sure is worthwhile. But I
do want separate experiences for veteran programmers reading about Mu on
github and for people learning programming using Mu.
Diffstat (limited to '058shape_shifting_container.cc')
-rw-r--r--058shape_shifting_container.cc34
1 files changed, 17 insertions, 17 deletions
diff --git a/058shape_shifting_container.cc b/058shape_shifting_container.cc
index 89460a8b..d8f3b001 100644
--- a/058shape_shifting_container.cc
+++ b/058shape_shifting_container.cc
@@ -5,7 +5,7 @@ container foo:_t [
   x:_t
   y:number
 ]
-recipe main [
+def main [
   1:foo:number <- merge 12, 13
   3:foo:point <- merge 14, 15, 16
 ]
@@ -21,7 +21,7 @@ container foo:_a:_b [
   x:_a
   y:_b
 ]
-recipe main [
+def main [
   1:foo:number:boolean <- merge 34, 1/true
 ]
 $error: 0
@@ -31,7 +31,7 @@ container foo:_a:_b [
   x:_a
   y:_b
 ]
-recipe main [
+def main [
   1:address:shared:array:character <- new [abc]
   # compound types for type ingredients
   {2: (foo number (address shared array character))} <- merge 34/x, 1:address:shared:array:character/y
@@ -47,7 +47,7 @@ container bar:_a:_b [
   # dilated element
   {data: (foo _a (address shared _b))}
 ]
-recipe main [
+def main [
   1:address:shared:array:character <- new [abc]
   2:bar:number:array:character <- merge 34/x, 1:address:shared:array:character/y
 ]
@@ -112,7 +112,7 @@ exclusive-container foo:_t [
   x:_t
   y:number
 ]
-recipe main [
+def main [
   1:foo:number <- merge 0/x, 34
   3:foo:point <- merge 0/x, 15, 16
   6:foo:point <- merge 1/y, 23
@@ -157,7 +157,7 @@ container foo:_t [
   x:_t
   y:number
 ]
-recipe main [
+def main [
   1:foo:point <- merge 14, 15, 16
   2:number <- get 1:foo:point, y:offset
 ]
@@ -178,7 +178,7 @@ container foo:_t [
   x:_t
   y:number
 ]
-recipe main [
+def main [
   1:foo:point <- merge 14, 15, 16
   2:point <- get 1:foo:point, x:offset
 ]
@@ -190,7 +190,7 @@ container foo:_t [
   x:_t
   y:number
 ]
-recipe main [
+def main [
   1:foo:address:point <- merge 34/unsafe, 48
   2:address:point <- get 1:foo:address:point, x:offset
 ]
@@ -205,7 +205,7 @@ container bar [
   x:foo:point
   y:number
 ]
-recipe main [
+def main [
   1:bar <- merge 14, 15, 16, 17
   2:number <- get 1:bar, 1:offset
 ]
@@ -216,7 +216,7 @@ container foo:_a:_b [
   x:_a
   y:_b
 ]
-recipe main [
+def main [
   1:address:shared:array:character <- new [abc]
   {2: (foo number (address shared array character))} <- merge 34/x, 1:address:shared:array:character/y
   3:address:shared:array:character <- get {2: (foo number (address shared array character))}, y:offset
@@ -488,7 +488,7 @@ container foo:_t [
   x:_t
   y:number
 ]
-recipe main [
+def main [
   10:foo:point <- merge 14, 15, 16
   1:number <- get 10:foo, 1:offset
 ]
@@ -501,7 +501,7 @@ container foo:_t [
   x:_t
   y:number
 ]
-recipe main [
+def main [
   10:foo:point <- merge 14, 15, 16
   1:address:number <- get-address 10:foo:point, 1:offset
 ]
@@ -528,7 +528,7 @@ exclusive-container bar [
   x:number
   y:number
 ]
-recipe main [
+def main [
   1:foo:bar <- merge 23, 1/y, 34
 ]
 +mem: storing 23 in location 1
@@ -546,7 +546,7 @@ exclusive-container bar [
   x:number
   y:number
 ]
-recipe main [
+def main [
   1:foo:bar <- merge 23, 1/y, 34, 35
 ]
 +error: main: too many ingredients in '1:foo:bar <- merge 23, 1/y, 34, 35'
@@ -560,7 +560,7 @@ container bar [
   x:number
   y:number
 ]
-recipe main [
+def main [
   1:foo:bar <- merge 1/y, 23, 34
 ]
 +mem: storing 1 in location 1
@@ -577,7 +577,7 @@ container bar [
   x:number
   y:number
 ]
-recipe main [
+def main [
   1:foo:bar <- merge 0/x, 23
 ]
 $error: 0
@@ -592,7 +592,7 @@ container bar [
   x:number
   y:number
 ]
-recipe main [
+def main [
   1:foo:bar <- merge 1/y, 23
 ]
 +error: main: too few ingredients in '1:foo:bar <- merge 1/y, 23'
e9616a77fc4e1c22e913308c8ea55ef05203211'>^
8e60380e ^



dad3bedd ^























8d72e565 ^
dad3bedd ^

c43b455d ^
dad3bedd ^







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152









                                                                       

                                                                                      
 








                                                                                                         





                                                                            
                                              

          

                                                                                                                
 







                                             








                                                                                                    
                                                 








                                                        
                                      
                                                                                   







                                                                                               






                                                         
 

























                                                                                         
                                                       
                                              



                                      
                                        



                                 























                                                                          
                                                                                                                                         

          
                        







                                                                                                                
//: when encountering other types, try to convert them to strings using
//: 'to-text'

:(scenarios transform)
:(scenario rewrite_stashes_to_text)
recipe main [
  local-scope
  n:number <- copy 34
  stash n
]
+transform: {stash_2_0: ("address" "array" "character")} <- to-text-line {n: "number"}
+transform: stash {stash_2_0: ("address" "array" "character")}

:(scenario rewrite_traces_to_text)
recipe main [
  local-scope
  n:number <- copy 34
  trace 2, [app], n
]
+transform: {trace_2_2: ("address" "array" "character")} <- to-text-line {n: "number"}
+transform: trace {2: "literal"}, {"app": "literal-string"}, {trace_2_2: ("address" "array" "character")}

//: special case: rewrite attempts to stash contents of most arrays to avoid
//: passing addresses around

:(scenario rewrite_stashes_of_arrays)
recipe main [
  local-scope
  n:address:array:number <- new number:type, 3
  stash *n
]
+transform: {stash_2_0: ("address" "array" "character")} <- array-to-text-line {n: ("address" "array" "number")}
+transform: stash {stash_2_0: ("address" "array" "character")}

:(scenario ignore_stashes_of_static_arrays)
recipe main [
  local-scope
  n:array:number:3 <- create-array
  stash n
]
+transform: stash {n: ("array" "number" "3")}

:(before "End Instruction Inserting/Deleting Transforms")
Transform.push_back(rewrite_stashes_to_text);

:(code)
void rewrite_stashes_to_text(recipe_ordinal r) {
  recipe& caller = get(Recipe, r);
  trace(9991, "transform") << "--- rewrite 'stash' instructions in recipe " << caller.name << end();
  // in recipes without named locations, 'stash' is still not extensible
  if (contains_numeric_locations(caller)) return;
  check_or_set_types_by_name(r);  // prerequisite
  rewrite_stashes_to_text(caller);
}

void rewrite_stashes_to_text(recipe& caller) {
  vector<instruction> new_instructions;
  for (int i = 0; i < SIZE(caller.steps); ++i) {
    instruction& inst = caller.steps.at(i);
    if (inst.name == "stash") {
      for (int j = 0; j < SIZE(inst.ingredients); ++j) {
        ostringstream ingredient_name;
        ingredient_name << "stash_" << i << '_' << j << ":address:array:character";
        rewrite_stash_to_text(inst.ingredients.at(j), new_instructions, ingredient_name.str());
      }
    }
    else if (inst.name == "trace") {
      for (int j = /*skip*/2; j < SIZE(inst.ingredients); ++j) {
        ostringstream ingredient_name;
        ingredient_name << "trace_" << i << '_' << j << ":address:array:character";
        rewrite_stash_to_text(inst.ingredients.at(j), new_instructions, ingredient_name.str());
      }
    }
    trace(9993, "transform") << to_string(inst) << end();
    new_instructions.push_back(inst);
  }
  caller.steps.swap(new_instructions);
}

// add an instruction to convert reagent 'r' to text in list 'out', then
// replace r with converted text
void rewrite_stash_to_text(reagent& r, vector<instruction>& out, const string& tmp_var) {
  if (!r.type) return;  // error; will be handled elsewhere
  if (is_literal(r)) return;
  if (is_mu_string(r)) return;
  // don't try to extend static arrays
  if (is_static_array(r)) return;
  instruction def;
  if (is_lookup_of_address_of_array(r)) {
    def.name = "array-to-text-line";
    reagent/*copy*/ tmp = r;
    drop_one_lookup(tmp);
    def.ingredients.push_back(tmp);
  }
  else {
    def.name = "to-text-line";
    def.ingredients.push_back(r);
  }
  def.products.push_back(reagent(tmp_var));
  trace(9993, "transform") << to_string(def) << end();
  out.push_back(def);
  r.clear();  // reclaim old memory
  r = reagent(tmp_var);
}

bool is_lookup_of_address_of_array(reagent/*copy*/ x) {
  if (x.type->name != "address") return false;
  if (!canonize_type(x)) return false;
  return x.type->name == "array";
}

bool is_static_array(const reagent& x) {
  // no canonize_type()
  return x.type->name == "array";
}

//: Make sure that the new system is strictly better than just the 'stash'
//: primitive by itself.

:(scenarios run)
:(scenario rewrite_stash_continues_to_fall_back_to_default_implementation)
# type without a to-text implementation
container foo [
  x:number
  y:number
]
recipe main [
  local-scope
  x:foo <- merge 34, 35
  stash x
]
+app: 34 35

:(before "End Primitive Recipe Declarations")
TO_TEXT,
:(before "End Primitive Recipe Numbers")
put(Recipe_ordinal, "to-text", TO_TEXT);
:(before "End Primitive Recipe Checks")
case TO_TEXT: {
  if (SIZE(inst.ingredients) != 1) {
    raise << maybe(get(Recipe, r).name) << "'to-text' requires a single ingredient, but got '" << inst.original_string << "'\n" << end();
    break;
  }
  // can handle any type
  break;
}
:(before "End Primitive Recipe Implementations")
case TO_TEXT: {
  products.resize(1);
  products.at(0).push_back(new_mu_string(print_mu(current_instruction().ingredients.at(0), ingredients.at(0))));
  break;
}