BadVPN – Blame information for rev 1

Subversion Repositories:
Rev:
Rev Author Line No. Line
1 office 1 <!DOCTYPE html>
2 <html>
3 <head>
4 <title>NCD in Javascript</title>
5 <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
6 </head>
7 <body>
8  
9 <script src="emncd.js"></script>
10  
11 <script>
12  
13 var cfunc_emncd_start = Module.cwrap('emncd_start', 'null', ['string']);
14 var cfunc_emncd_stop = Module.cwrap('emncd_stop', 'null', []);
15  
16 function on_start ()
17 {
18 var code = document.getElementById('codetext').value;
19  
20 var loglevel = 0;
21 for (i = 0; i <= 5; i++) {
22 if (document.getElementById('loglevel' + i).checked) {
23 loglevel = i;
24 }
25 }
26  
27 cfunc_emncd_start(code, loglevel);
28 }
29  
30 function on_stop ()
31 {
32 cfunc_emncd_stop();
33 }
34  
35 function load_example (num)
36 {
37 document.getElementById('codetext').value = document.getElementById('example' + num).value;
38 }
39  
40 </script>
41  
42 This is a quick port of my <a href="http://code.google.com/p/badvpn/wiki/NCD">NCD programming language</a>
43 to Javascript using the <a href="https://github.com/kripken/emscripten">Emscripten</a> compiler.
44 <br />
45  
46 Please open the Javascript console so you can see the output (Chrome: CTRL+Shift+J. Firefox: CTRL+Shift+K).
47 <br />
48  
49 <textarea id="example1" style="display:none;">
50 process hello {
51 println("hello, world");
52 exit("0");
53 }
54 </textarea>
55  
56 <textarea id="example2" style="display:none;">
57 process foo {
58 println("Starting up, please wait...");
59 rprintln("Goodbye World!");
60  
61 sleep("500", "300"); # sleeps 500ms on init and 300ms on deinit
62  
63 println("Hello World!");
64 rprintln("Shutting down, please wait...");
65 }
66 </textarea>
67  
68 <textarea id="example3" style="display:none;">
69 process hello {
70 var("0") ctr;
71  
72 blocker() blk;
73 blk->up();
74 blk->use();
75  
76 num_modulo(ctr, "3") m_three;
77 num_modulo(ctr, "5") m_five;
78 num_equal(m_three, "0") d_three;
79 num_equal(m_five, "0") d_five;
80 and(d_three, d_five) d_three_five;
81  
82 If (d_three_five) {
83 var("fizzbuzz") text;
84 } Elif (d_three) {
85 var("fizz") text;
86 } Elif (d_five) {
87 var("buzz") text;
88 } else {
89 var(ctr) text;
90 } branch;
91  
92 println(branch.text);
93  
94 num_add(ctr, "1") i;
95 num_modulo(i, "20") i;
96 ctr->set(i);
97  
98 sleep("100", "0");
99 blk->downup();
100  
101 }
102 </textarea>
103  
104 <textarea id="example4" style="display:none;">
105 process main {
106 var({"0", "1", "3", "2", "2", "3", "1", "1", "6", "end"}) list;
107 value(["1":"one", "2":"two", "3":"three"]) map;
108  
109 call("replace", {"_caller.list", "_caller.map"}) replace;
110  
111 to_string(replace.result) str;
112 println(str);
113 exit("0");
114 }
115  
116 template replace {
117 alias(_arg0) list;
118 alias(_arg1) map;
119  
120 value({}) new_list;
121 Foreach (list As elem) {
122 map->try_get(elem) y;
123 If (y.exists) {
124 new_list->insert(new_list.length, y);
125 } Else {
126 new_list->insert(new_list.length, elem);
127 };
128 };
129  
130 alias("new_list") result;
131 }
132 </textarea>
133  
134 <textarea id="example5" style="display:none;">
135 process hello {
136 println("Hello, NCD in Javascript!");
137 println("Will now wait 2 seconds.");
138 rprintln("Goodbye.");
139  
140 sleep("2000", "3000");
141 rprintln("Waiting 3 seconds before dying.");
142  
143 call("func", {"FirstArg", "SecondArg"});
144  
145 var({"one", "two", "three"}) list;
146 to_string(list) str;
147 println(str);
148  
149 Foreach (list As elem) {
150 println("start ", elem);
151 rprintln("stop ", elem);
152 };
153  
154 println("We're finished. Press \"Request termination\" to unwind us.");
155 rprintln("Terminating...");
156 }
157  
158 template func {
159 println("func here, my args are: ", _arg0, " ", _arg1);
160 rprintln("func going away");
161 }
162 </textarea>
163  
164 <textarea id="example6" style="display:none;">
165 process main {
166 # Turing machine specification.
167 var("B") blank;
168 var([
169 {"0", "0"}:{"0", "0", "right"},
170 {"0", "1"}:{"1", "x", "right"},
171 {"1", "1"}:{"1", "1", "right"},
172 {"1", "0"}:{"2", "0", "right"},
173 {"2", "0"}:{"2", "0", "right"},
174 {"2", "1"}:{"3", "1", "right"},
175 {"3", "1"}:{"3", "1", "right"},
176 {"3", "0"}:{"4", "1", "left"},
177 {"3", "B"}:{"4", "1", "left"},
178 {"4", "1"}:{"4", "1", "left"},
179 {"4", "0"}:{"5", "0", "left"},
180 {"5", "0"}:{"5", "0", "left"},
181 {"5", "1"}:{"6", "1", "left"},
182 {"5", "x"}:{"h", "x", "stay"},
183 {"6", "1"}:{"6", "1", "left"},
184 {"6", "x"}:{"0", "x", "right"},
185 {"6", "0"}:{"0", "0", "right"}
186 ]) rules;
187 var("0") initial_state;
188 var({}) initial_tape_left;
189 var({
190 "1", "1", "1", "1", "0", "0", "1", "1", "1", "1"
191 }) initial_tape_right;
192  
193 # Perform the computation, stopping when no rule matches.
194 call("turing", {blank, rules, initial_state, initial_tape_left, initial_tape_right}) results;
195  
196 # Print results.
197 to_string(results.tape_left) tape_left;
198 to_string(results.tape_right) tape_right;
199 to_string({results.side, results.pos}) head_pos;
200 to_string(results.state) head_state;
201 println("Tape L: ", tape_left);
202 println("Tape R: ", tape_right);
203 println("Head position: ", head_pos);
204 println("Head state: ", head_state);
205  
206 exit("0");
207 }
208  
209 template turing {
210 alias("_arg0") blank;
211 value(_arg1) rules;
212 alias("_arg2") initial_state;
213 alias("_arg3") initial_tape_left;
214 alias("_arg4") initial_tape_right;
215  
216 # Head state.
217 var(initial_state) state;
218  
219 # Tape. Positions go like this: ... L2 L1 L0 R0 R1 R2 ...
220 value(initial_tape_left) tape_left;
221 value(initial_tape_right) tape_right;
222  
223 # Make sure each side of the tape has at least one symbol so we can flip easily.
224 tape_left->insert(tape_left.length, blank);
225 tape_right->insert(tape_right.length, blank);
226  
227 # Head position.
228 var("right") side;
229 var("0") pos;
230  
231 # Enter loop.
232 blocker() loop_blk;
233 loop_blk->up();
234 loop_blk->use();
235  
236 # Get symbol under head.
237 concat("tape_", side) tape_name;
238 alias(tape_name) cur_tape;
239 cur_tape->get(pos) symbol;
240  
241 # Look for a matching rule.
242 rules->try_get({state, symbol}) rule;
243  
244 If (rule.exists) {
245 # Extract directions from rule.
246 rule->get("0") new_state;
247 rule->get("1") new_symbol;
248 rule->get("2") move;
249  
250 # Change head state.
251 state->set(new_state);
252  
253 # Replace symbol under head.
254 cur_tape->remove(pos);
255 cur_tape->insert(pos, new_symbol);
256  
257 # Branch based on how we move.
258 strcmp(move, side) is_outside;
259 strcmp(move, "stay") is_stay;
260 strcmp(pos, "0") is_zero;
261 If (is_outside) {
262 # Increment position.
263 num_add(pos, "1") new_pos;
264 pos->set(new_pos);
265  
266 # If the new position is out of range, extend tape.
267 strcmp(pos, cur_tape.length) need_extend;
268 If (need_extend) {
269 cur_tape->insert(pos, blank);
270 };
271 } elif (is_stay) {
272 # Nop.
273 getargs();
274 } elif (is_zero) {
275 # Flip side, leave pos at zero.
276 side->set(move);
277 } else {
278 # Decrement position.
279 num_subtract(pos, "1") new_pos;
280 pos->set(new_pos);
281 };
282  
283 # Continue loop.
284 loop_blk->downup();
285 };
286 }
287 </textarea>
288  
289 Examples:
290 <button onclick="load_example(1)">Hello World</button>
291 <button onclick="load_example(2)">Sleep</button>
292 <button onclick="load_example(3)">FizzBuzz</button>
293 <button onclick="load_example(4)">Replace</button>
294 <button onclick="load_example(5)">Foreach, call</button>
295 <button onclick="load_example(6)">Turing Machine</button>
296 <br />
297  
298 <textarea rows=30 cols=80 id="codetext">
299 process hello {
300 println("hello, world");
301 exit("0");
302 }
303 </textarea>
304 <br />
305  
306 Loglevel:
307 <input type="radio" name="loglevel" id="loglevel0"> None
308 <input type="radio" name="loglevel" id="loglevel1"> Error
309 <input type="radio" name="loglevel" id="loglevel2" checked> Warning
310 <input type="radio" name="loglevel" id="loglevel3"> Notice
311 <input type="radio" name="loglevel" id="loglevel4"> Info
312 <input type="radio" name="loglevel" id="loglevel5"> Debug <br />
313  
314 <button onclick="on_start()">Start NCD</button>
315 <button onclick="on_stop()">Request termination</button>
316 <br />
317 Note: if you get the interpreter stuck and unable to terminate, just refresh the page
318  
319 </body>
320 </html>