about summary refs log tree commit diff stats
path: root/html/072scenario_screen.cc.html
blob: 79cc604456c99a33385d5aa61762579d260f652b (plain) (blame)
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
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html>
<head>
<meta http-equiv="content-type" content="text/html; charset=UTF-8">
<title>~/Desktop/s/mu/072scenario_screen.cc</title>
<meta name="Generator" content="Vim/7.4">
<meta name="plugin-version" content="vim7.4_v1">
<meta name="syntax" content="cpp">
<meta name="settings" content="use_css,pre_wrap,no_foldcolumn,expand_tabs,prevent_copy=">
<meta name="colorscheme" content="minimal">
<style type="text/css">
<!--
pre { white-space: pre-wrap; font-family: monospace; color: #d0d0d0; background-color: #000000; }
body { font-family: monospace; color: #d0d0d0; background-color: #000000; }
* { font-size: 1em; }
.cSpecial { color: #008000; }
.Identifier { color: #008080; }
.Constant { color: #008080; }
.Comment { color: #8080ff; }
.Delimiter { color: #c000c0; }
.Special { color: #ff6060; }
.CommentedCode { color: #6c6c6c; }
.traceContains { color: #008000; }
-->
</style>

<script type='text/javascript'>
<!--

-->
</script>
</head>
<body>
<pre id='vimCodeElement'>
<span class="Comment">//: Clean syntax to manipulate and check the screen in scenarios.</span>
<span class="Comment">//: Instructions 'assume-screen' and 'screen-should-contain' implicitly create</span>
<span class="Comment">//: a variable called 'screen' that is accessible inside other 'run'</span>
<span class="Comment">//: instructions in the scenario.</span>

<span class="Delimiter">:(scenarios run_mu_scenario)</span>
<span class="Delimiter">:(scenario screen_in_scenario)</span>
scenario screen-in-scenario [
<span class="CommentedCode">#?   $start-tracing</span>
  assume-screen <span class="Constant">5</span>:literal/width<span class="Delimiter">,</span> <span class="Constant">3</span>:literal/height
  run [
    screen:address<span class="Special"> &lt;- </span>print-character screen:address<span class="Delimiter">,</span> <span class="Constant">97</span>:literal  <span class="Comment"># 'a'</span>
  ]
  screen-should-contain [
  <span class="Comment">#  01234</span>
    <span class="Delimiter">.</span>a    <span class="Delimiter">.</span>
    <span class="Delimiter">.</span>     <span class="Delimiter">.</span>
    <span class="Delimiter">.</span>     <span class="Delimiter">.</span>
  ]
<span class="CommentedCode">#?   $exit</span>
]

<span class="Delimiter">:(scenario screen_in_scenario_error)</span>
<span class="CommentedCode">#? % cerr &lt;&lt; &quot;AAA\n&quot;;</span>
<span class="Special">% Hide_warnings = true;</span>
scenario screen-in-scenario-error [
  assume-screen <span class="Constant">5</span>:literal/width<span class="Delimiter">,</span> <span class="Constant">3</span>:literal/height
  run [
    screen:address<span class="Special"> &lt;- </span>print-character screen:address<span class="Delimiter">,</span> <span class="Constant">97</span>:literal  <span class="Comment"># 'a'</span>
  ]
  screen-should-contain [
  <span class="Comment">#  01234</span>
    <span class="Delimiter">.</span>b    <span class="Delimiter">.</span>
    <span class="Delimiter">.</span>     <span class="Delimiter">.</span>
    <span class="Delimiter">.</span>     <span class="Delimiter">.</span>
  ]
]
<span class="traceContains">+warn: expected screen location (0, 0) to contain 'b' instead of 'a'</span>

<span class="Delimiter">:(before &quot;End Globals&quot;)</span>
<span class="Comment">// Scenarios may not define default-space, so they should fit within the</span>
<span class="Comment">// initial area of memory reserved for tests. We'll put the predefined</span>
<span class="Comment">// variables available to them at the end of that region.</span>
const size_t Max_variables_in_scenarios = Reserved_for_tests-<span class="Constant">100</span><span class="Delimiter">;</span>
size_t Next_predefined_global_for_scenarios = Max_variables_in_scenarios<span class="Delimiter">;</span>
<span class="Delimiter">:(before &quot;End Setup&quot;)</span>
assert<span class="Delimiter">(</span>Next_predefined_global_for_scenarios &lt; Reserved_for_tests<span class="Delimiter">);</span>
<span class="Delimiter">:(after &quot;transform_all()&quot; following &quot;case RUN:&quot;)</span>
<span class="Comment">// There's a restriction on the number of variables 'run' can use, so that</span>
<span class="Comment">// it can avoid colliding with the dynamic allocator in case it doesn't</span>
<span class="Comment">// initialize a default-space.</span>
assert<span class="Delimiter">(</span>Name[tmp_recipe<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">)</span>][<span class="Constant">&quot;&quot;</span>] &lt; Max_variables_in_scenarios<span class="Delimiter">);</span>

<span class="Delimiter">:(before &quot;End Globals&quot;)</span>
<span class="Comment">// Scenario Globals.</span>
const size_t SCREEN = Next_predefined_global_for_scenarios++<span class="Delimiter">;</span>
<span class="Comment">// End Scenario Globals.</span>
<span class="Delimiter">:(before &quot;End Predefined Scenario Locals In Run&quot;)</span>
Name[tmp_recipe<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">)</span>][<span class="Constant">&quot;screen&quot;</span>] = SCREEN<span class="Delimiter">;</span>

<span class="Delimiter">:(before &quot;End Rewrite Instruction(curr)&quot;)</span>
<span class="Comment">// rewrite `assume-screen width, height` to</span>
<span class="Comment">// `screen:address &lt;- init-fake-screen width, height`</span>
<span class="CommentedCode">//? cout &lt;&lt; &quot;before: &quot; &lt;&lt; curr.to_string() &lt;&lt; '\n'; //? 1</span>
if <span class="Delimiter">(</span>curr<span class="Delimiter">.</span>name == <span class="Constant">&quot;assume-screen&quot;</span><span class="Delimiter">)</span> <span class="Delimiter">{</span>
  curr<span class="Delimiter">.</span>operation = Recipe_number[<span class="Constant">&quot;init-fake-screen&quot;</span>]<span class="Delimiter">;</span>
  assert<span class="Delimiter">(</span>curr<span class="Delimiter">.</span>products<span class="Delimiter">.</span>empty<span class="Delimiter">());</span>
  curr<span class="Delimiter">.</span>products<span class="Delimiter">.</span>push_back<span class="Delimiter">(</span>reagent<span class="Delimiter">(</span><span class="Constant">&quot;screen:address&quot;</span><span class="Delimiter">));</span>
  curr<span class="Delimiter">.</span>products<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">).</span>set_value<span class="Delimiter">(</span>SCREEN<span class="Delimiter">);</span>
<span class="CommentedCode">//? cout &lt;&lt; &quot;after: &quot; &lt;&lt; curr.to_string() &lt;&lt; '\n'; //? 1</span>
<span class="CommentedCode">//? cout &lt;&lt; &quot;AAA &quot; &lt;&lt; Recipe_number[&quot;init-fake-screen&quot;] &lt;&lt; '\n'; //? 1</span>
<span class="Delimiter">}</span>

<span class="Comment">//: screen-should-contain is a regular instruction</span>
<span class="Delimiter">:(before &quot;End Primitive Recipe Declarations&quot;)</span>
SCREEN_SHOULD_CONTAIN<span class="Delimiter">,</span>
<span class="Delimiter">:(before &quot;End Primitive Recipe Numbers&quot;)</span>
Recipe_number[<span class="Constant">&quot;screen-should-contain&quot;</span>] = SCREEN_SHOULD_CONTAIN<span class="Delimiter">;</span>
<span class="Delimiter">:(before &quot;End Primitive Recipe Implementations&quot;)</span>
case SCREEN_SHOULD_CONTAIN: <span class="Delimiter">{</span>
<span class="CommentedCode">//?   cout &lt;&lt; &quot;AAA\n&quot;; //? 1</span>
  check_screen<span class="Delimiter">(</span>current_instruction<span class="Delimiter">().</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">).</span>name<span class="Delimiter">);</span>
  <span class="Identifier">break</span><span class="Delimiter">;</span>
<span class="Delimiter">}</span>

<span class="Delimiter">:(code)</span>
void check_screen<span class="Delimiter">(</span>const string&amp; contents<span class="Delimiter">)</span> <span class="Delimiter">{</span>
<span class="CommentedCode">//?   cerr &lt;&lt; &quot;Checking screen\n&quot;; //? 1</span>
  assert<span class="Delimiter">(</span>!Current_routine<span class="Delimiter">-&gt;</span>calls<span class="Delimiter">.</span>front<span class="Delimiter">().</span>default_space<span class="Delimiter">);</span>  <span class="Comment">// not supported</span>
  index_t screen_location = Memory[SCREEN]<span class="Delimiter">;</span>
  int data_offset = find_element_name<span class="Delimiter">(</span>Type_number[<span class="Constant">&quot;screen&quot;</span>]<span class="Delimiter">,</span> <span class="Constant">&quot;data&quot;</span><span class="Delimiter">);</span>
  assert<span class="Delimiter">(</span>data_offset &gt;= <span class="Constant">0</span><span class="Delimiter">);</span>
  index_t screen_data_location = screen_location+data_offset<span class="Delimiter">;</span>  <span class="Comment">// type: address:array:character</span>
  index_t screen_data_start = Memory[screen_data_location]<span class="Delimiter">;</span>  <span class="Comment">// type: array:character</span>
  int width_offset = find_element_name<span class="Delimiter">(</span>Type_number[<span class="Constant">&quot;screen&quot;</span>]<span class="Delimiter">,</span> <span class="Constant">&quot;num-columns&quot;</span><span class="Delimiter">);</span>
  size_t screen_width = Memory[screen_location+width_offset]<span class="Delimiter">;</span>
  int height_offset = find_element_name<span class="Delimiter">(</span>Type_number[<span class="Constant">&quot;screen&quot;</span>]<span class="Delimiter">,</span> <span class="Constant">&quot;num-rows&quot;</span><span class="Delimiter">);</span>
  size_t screen_height = Memory[screen_location+height_offset]<span class="Delimiter">;</span>
  string expected_contents<span class="Delimiter">;</span>
  istringstream in<span class="Delimiter">(</span>contents<span class="Delimiter">);</span>
  in &gt;&gt; std::noskipws<span class="Delimiter">;</span>
  for <span class="Delimiter">(</span>index_t row = <span class="Constant">0</span><span class="Delimiter">;</span> row &lt; screen_height<span class="Delimiter">;</span> ++row<span class="Delimiter">)</span> <span class="Delimiter">{</span>
    skip_whitespace_and_comments<span class="Delimiter">(</span>in<span class="Delimiter">);</span>
    assert<span class="Delimiter">(</span>!in<span class="Delimiter">.</span>eof<span class="Delimiter">());</span>
    assert<span class="Delimiter">(</span>in<span class="Delimiter">.</span>get<span class="Delimiter">()</span> == <span class="Constant">'.'</span><span class="Delimiter">);</span>
    for <span class="Delimiter">(</span>index_t column = <span class="Constant">0</span><span class="Delimiter">;</span> column &lt; screen_width<span class="Delimiter">;</span> ++column<span class="Delimiter">)</span> <span class="Delimiter">{</span>
      assert<span class="Delimiter">(</span>!in<span class="Delimiter">.</span>eof<span class="Delimiter">());</span>
      expected_contents += in<span class="Delimiter">.</span>get<span class="Delimiter">();</span>
    <span class="Delimiter">}</span>
    assert<span class="Delimiter">(</span>in<span class="Delimiter">.</span>get<span class="Delimiter">()</span> == <span class="Constant">'.'</span><span class="Delimiter">);</span>
  <span class="Delimiter">}</span>
  skip_whitespace_and_comments<span class="Delimiter">(</span>in<span class="Delimiter">);</span>
<span class="CommentedCode">//?   assert(in.get() == ']');</span>
  trace<span class="Delimiter">(</span><span class="Constant">&quot;run&quot;</span><span class="Delimiter">)</span> &lt;&lt; <span class="Constant">&quot;checking screen size at &quot;</span> &lt;&lt; screen_data_start<span class="Delimiter">;</span>
<span class="CommentedCode">//?   cout &lt;&lt; expected_contents.size() &lt;&lt; '\n'; //? 1</span>
  if <span class="Delimiter">(</span>Memory[screen_data_start] &gt; static_cast&lt;signed&gt;<span class="Delimiter">(</span>expected_contents<span class="Delimiter">.</span>size<span class="Delimiter">()))</span>
    raise &lt;&lt; <span class="Constant">&quot;expected contents are larger than screen size &quot;</span> &lt;&lt; Memory[screen_data_start] &lt;&lt; <span class="cSpecial">'\n'</span><span class="Delimiter">;</span>
  ++screen_data_start<span class="Delimiter">;</span>  <span class="Comment">// now skip length</span>
  for <span class="Delimiter">(</span>index_t i = <span class="Constant">0</span><span class="Delimiter">;</span> i &lt; expected_contents<span class="Delimiter">.</span>size<span class="Delimiter">();</span> ++i<span class="Delimiter">)</span> <span class="Delimiter">{</span>
    trace<span class="Delimiter">(</span><span class="Constant">&quot;run&quot;</span><span class="Delimiter">)</span> &lt;&lt; <span class="Constant">&quot;checking location &quot;</span> &lt;&lt; screen_data_start+i<span class="Delimiter">;</span>
<span class="CommentedCode">//?     cerr &lt;&lt; &quot;comparing &quot; &lt;&lt; i/screen_width &lt;&lt; &quot;, &quot; &lt;&lt; i%screen_width &lt;&lt; &quot;: &quot; &lt;&lt; Memory[screen_data_start+i] &lt;&lt; &quot; vs &quot; &lt;&lt; (int)expected_contents.at(i) &lt;&lt; '\n'; //? 1</span>
    if <span class="Delimiter">((</span>!Memory[screen_data_start+i] &amp;&amp; !isspace<span class="Delimiter">(</span>expected_contents<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">)))</span>  <span class="Comment">// uninitialized memory =&gt; spaces</span>
        || <span class="Delimiter">(</span>Memory[screen_data_start+i] &amp;&amp; Memory[screen_data_start+i] != expected_contents<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">)))</span> <span class="Delimiter">{</span>
<span class="CommentedCode">//?       cerr &lt;&lt; &quot;CCC &quot; &lt;&lt; Trace_stream &lt;&lt; &quot; &quot; &lt;&lt; Hide_warnings &lt;&lt; '\n'; //? 1</span>
      if <span class="Delimiter">(</span>Current_scenario &amp;&amp; !Hide_warnings<span class="Delimiter">)</span> <span class="Delimiter">{</span>
        <span class="Comment">// genuine test in a mu file</span>
        raise &lt;&lt; <span class="Constant">&quot;</span><span class="cSpecial">\n</span><span class="Constant">F - &quot;</span> &lt;&lt; Current_scenario<span class="Delimiter">-&gt;</span>name &lt;&lt; <span class="Constant">&quot;: expected screen location (&quot;</span> &lt;&lt; i/screen_width &lt;&lt; <span class="Constant">&quot;, &quot;</span> &lt;&lt; i%screen_width &lt;&lt; <span class="Constant">&quot;) to contain '&quot;</span> &lt;&lt; expected_contents<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">)</span> &lt;&lt; <span class="Constant">&quot;' instead of '&quot;</span> &lt;&lt; static_cast&lt;char&gt;<span class="Delimiter">(</span>Memory[screen_data_start+i]<span class="Delimiter">)</span> &lt;&lt; <span class="Constant">&quot;'</span><span class="cSpecial">\n</span><span class="Constant">&quot;</span><span class="Delimiter">;</span>
        dump_screen<span class="Delimiter">();</span>
      <span class="Delimiter">}</span>
      else <span class="Delimiter">{</span>
        <span class="Comment">// just testing check_screen</span>
        raise &lt;&lt; <span class="Constant">&quot;expected screen location (&quot;</span> &lt;&lt; i/screen_width &lt;&lt; <span class="Constant">&quot;, &quot;</span> &lt;&lt; i%screen_width &lt;&lt; <span class="Constant">&quot;) to contain '&quot;</span> &lt;&lt; expected_contents<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">)</span> &lt;&lt; <span class="Constant">&quot;' instead of '&quot;</span> &lt;&lt; static_cast&lt;char&gt;<span class="Delimiter">(</span>Memory[screen_data_start+i]<span class="Delimiter">)</span> &lt;&lt; <span class="Constant">&quot;'</span><span class="cSpecial">\n</span><span class="Constant">&quot;</span><span class="Delimiter">;</span>
      <span class="Delimiter">}</span>
      if <span class="Delimiter">(</span>!Hide_warnings<span class="Delimiter">)</span> <span class="Delimiter">{</span>
        Passed = <span class="Constant">false</span><span class="Delimiter">;</span>
        ++Num_failures<span class="Delimiter">;</span>
      <span class="Delimiter">}</span>
      <span class="Identifier">return</span><span class="Delimiter">;</span>
    <span class="Delimiter">}</span>
  <span class="Delimiter">}</span>
<span class="Delimiter">}</span>

<span class="Delimiter">:(before &quot;End Primitive Recipe Declarations&quot;)</span>
_DUMP_SCREEN<span class="Delimiter">,</span>
<span class="Delimiter">:(before &quot;End Primitive Recipe Numbers&quot;)</span>
Recipe_number[<span class="Constant">&quot;$dump-screen&quot;</span>] = _DUMP_SCREEN<span class="Delimiter">;</span>
<span class="Delimiter">:(before &quot;End Primitive Recipe Implementations&quot;)</span>
case _DUMP_SCREEN: <span class="Delimiter">{</span>
  dump_screen<span class="Delimiter">();</span>
  <span class="Identifier">break</span><span class="Delimiter">;</span>
<span class="Delimiter">}</span>

<span class="Delimiter">:(code)</span>
void dump_screen<span class="Delimiter">()</span> <span class="Delimiter">{</span>
  assert<span class="Delimiter">(</span>!Current_routine<span class="Delimiter">-&gt;</span>calls<span class="Delimiter">.</span>front<span class="Delimiter">().</span>default_space<span class="Delimiter">);</span>  <span class="Comment">// not supported</span>
  index_t screen_location = Memory[SCREEN]<span class="Delimiter">;</span>
  int width_offset = find_element_name<span class="Delimiter">(</span>Type_number[<span class="Constant">&quot;screen&quot;</span>]<span class="Delimiter">,</span> <span class="Constant">&quot;num-columns&quot;</span><span class="Delimiter">);</span>
  size_t screen_width = Memory[screen_location+width_offset]<span class="Delimiter">;</span>
  int height_offset = find_element_name<span class="Delimiter">(</span>Type_number[<span class="Constant">&quot;screen&quot;</span>]<span class="Delimiter">,</span> <span class="Constant">&quot;num-rows&quot;</span><span class="Delimiter">);</span>
  size_t screen_height = Memory[screen_location+height_offset]<span class="Delimiter">;</span>
  int data_offset = find_element_name<span class="Delimiter">(</span>Type_number[<span class="Constant">&quot;screen&quot;</span>]<span class="Delimiter">,</span> <span class="Constant">&quot;data&quot;</span><span class="Delimiter">);</span>
  assert<span class="Delimiter">(</span>data_offset &gt;= <span class="Constant">0</span><span class="Delimiter">);</span>
  index_t screen_data_location = screen_location+data_offset<span class="Delimiter">;</span>  <span class="Comment">// type: address:array:character</span>
  index_t screen_data_start = Memory[screen_data_location]<span class="Delimiter">;</span>  <span class="Comment">// type: array:character</span>
<span class="CommentedCode">//?   cerr &lt;&lt; &quot;data start: &quot; &lt;&lt; screen_data_start &lt;&lt; '\n'; //? 1</span>
  assert<span class="Delimiter">(</span>Memory[screen_data_start] == screen_width*screen_height<span class="Delimiter">);</span>
  index_t curr = screen_data_start+<span class="Constant">1</span><span class="Delimiter">;</span>  <span class="Comment">// skip length</span>
  for <span class="Delimiter">(</span>index_t row = <span class="Constant">0</span><span class="Delimiter">;</span> row &lt; screen_height<span class="Delimiter">;</span> ++row<span class="Delimiter">)</span> <span class="Delimiter">{</span>
<span class="CommentedCode">//?     cerr &lt;&lt; curr &lt;&lt; &quot;:\n&quot;; //? 1</span>
    for <span class="Delimiter">(</span>index_t col = <span class="Constant">0</span><span class="Delimiter">;</span> col &lt; screen_width<span class="Delimiter">;</span> ++col<span class="Delimiter">)</span> <span class="Delimiter">{</span>
      cerr &lt;&lt; static_cast&lt;char&gt;<span class="Delimiter">(</span>Memory[curr]<span class="Delimiter">);</span>
      ++curr<span class="Delimiter">;</span>
    <span class="Delimiter">}</span>
    cerr &lt;&lt; <span class="cSpecial">'\n'</span><span class="Delimiter">;</span>
  <span class="Delimiter">}</span>
<span class="Delimiter">}</span>
</pre>
</body>
</html>
<!-- vim: set foldmethod=manual : -->