Mercurial > hg > Members > nobuyasu > SampleSource
comparison WindowsOnly/WinScript2/vm.h @ 0:db40c85cad7a default tip
upload sample source
author | nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp> |
---|---|
date | Mon, 09 May 2011 03:11:59 +0900 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
-1:000000000000 | 0:db40c85cad7a |
---|---|
1 #ifndef __VM_H__ | |
2 #define __VM_H__ | |
3 | |
4 #include <vector> | |
5 #include "vm_value.h" | |
6 | |
7 #ifdef _MSC_VER | |
8 // | |
9 // VS2008では、セキュアライブラリ関数(*_s)を使うよう警告が出ます。 | |
10 // ここでは、一般化(gcc等の対応)のため、旧ライブラリを使用しているので、 | |
11 // 警告を抑止しています。 | |
12 // | |
13 #pragma warning(disable: 4996) | |
14 #endif | |
15 | |
16 #define VM_ENUMDEF | |
17 enum { | |
18 #include "vm_code.h" | |
19 VM_MAXCOMMAND, | |
20 } ; | |
21 #undef VM_ENUMDEF | |
22 | |
23 int VmMessageBox(const char *title, const char *message); | |
24 void VmMoveTo(int dc, int x, int y); | |
25 void VmLineTo(int dc, int x, int y); | |
26 void VmSetColor(int dc, int r, int g, int b); | |
27 int VmGetDC(); | |
28 void VmReleaseDC(int hdc); | |
29 | |
30 namespace vm { | |
31 | |
32 enum { | |
33 SYS_TOSTR, | |
34 SYS_MESSAGE_BOX, | |
35 SYS_MOVE_TO, | |
36 SYS_LINE_TO, | |
37 SYS_SET_COLOR, | |
38 SYS_GET_DC, | |
39 SYS_RELEASE_DC, | |
40 } ; | |
41 | |
42 class data { | |
43 public: | |
44 enum { | |
45 ON_CREATE, // WM_CREATE | |
46 ON_DESTROY, // WM_DESTROY | |
47 ON_PAINT, // WM_PAINT | |
48 ON_LBUTTONDOWN, // WM_LBUTTONDOWN | |
49 ON_LBUTTONUP, // WM_LBUTTONUP | |
50 ON_MOUSEMOVE, // WM_MOUSEMOVE | |
51 MAX_ENTRY_POINT // エントリーポイントの数 | |
52 } ; | |
53 | |
54 public: | |
55 data(): command_(0), text_buffer_(0) | |
56 { | |
57 } | |
58 ~data() | |
59 { | |
60 delete[] command_; | |
61 delete[] text_buffer_; | |
62 } | |
63 | |
64 public: | |
65 unsigned char *command_; // コマンドテーブル | |
66 char *text_buffer_; // テキストデータ | |
67 int command_size_; // コマンドサイズ | |
68 int text_size_; // テキストサイズ | |
69 int value_size_; // グローバル変数サイズ | |
70 int entry_point_[MAX_ENTRY_POINT]; // 開始位置 | |
71 } ; | |
72 | |
73 | |
74 // 0除算例外 | |
75 class devide_by_zero: public std::exception { | |
76 public: | |
77 const char *what() const throw() | |
78 { | |
79 return "devide by zero"; | |
80 } | |
81 } ; | |
82 | |
83 // 仮想マシン | |
84 class vcpu { | |
85 public: | |
86 const static int STACK_SIZE = 1000; | |
87 const static int global_flag = 0x4000000; | |
88 const static int global_mask = 0x3ffffff; | |
89 | |
90 public: | |
91 vcpu() | |
92 { | |
93 } | |
94 ~vcpu() | |
95 { | |
96 } | |
97 | |
98 // int run(); | |
99 int call(data &program, int entry) | |
100 { | |
101 return internal_call(program, entry, 0, 0); | |
102 } | |
103 | |
104 int call(data &program, int entry, int arg1) | |
105 { | |
106 int arg[] = { arg1 }; | |
107 return internal_call(program, entry, arg, 1); | |
108 } | |
109 | |
110 int call(data &program, int entry, int arg1, int arg2) | |
111 { | |
112 int arg[] = { arg1, arg2 }; | |
113 return internal_call(program, entry, arg, 2); | |
114 } | |
115 | |
116 int call(data &program, int entry, int arg1, int arg2, int arg3) | |
117 { | |
118 int arg[] = { arg1, arg2, arg3 }; | |
119 return internal_call(program, entry, arg, 3); | |
120 } | |
121 | |
122 private: | |
123 int internal_call(data &program, int entry, int *arg, int narg); | |
124 | |
125 private: | |
126 // 定数Push | |
127 void PushConst(int val) | |
128 { | |
129 push(val); | |
130 } | |
131 | |
132 // 文字定数Push | |
133 void PushString(int val) | |
134 { | |
135 push(std::string(text_buffer_ + val)); | |
136 } | |
137 | |
138 // 変数Push | |
139 void PushValue(int val) | |
140 { | |
141 push(global_value[val]); | |
142 } | |
143 | |
144 // ローカル変数Push | |
145 void PushLocal(int val) | |
146 { | |
147 push(stack[val + stack_base]); | |
148 } | |
149 | |
150 // 配列からPush | |
151 void PushArray(int val) | |
152 { | |
153 int index = top().i_; pop(); | |
154 push(global_value[val + index]); | |
155 } | |
156 | |
157 // ローカルの配列からPush | |
158 void PushLocalArray(int val) | |
159 { | |
160 int index = top().i_; pop(); | |
161 push(stack[val + stack_base + index]); | |
162 } | |
163 | |
164 // ローカル変数(参照)Push | |
165 void PushLocalRef(int val) | |
166 { | |
167 int addr = stack[val + stack_base].i_; | |
168 push(ref_to_value(addr)); | |
169 } | |
170 | |
171 // ローカルの配列(参照)からPush | |
172 void PushLocalArrayRef(int val) | |
173 { | |
174 int addr = stack[val + stack_base].i_; | |
175 int index = top().i_; pop(); | |
176 push(ref_to_value(addr + index)); | |
177 } | |
178 | |
179 // アドレスをPush | |
180 void PushAddr(int val) | |
181 { | |
182 if ((val & global_flag) == 0) // local | |
183 val += + stack_base; | |
184 push(val); | |
185 } | |
186 | |
187 // 配列のアドレスをPush | |
188 void PushArrayAddr(int val) | |
189 { | |
190 if ((val & global_flag) == 0) // local | |
191 val += + stack_base; | |
192 int index = top().i_; pop(); | |
193 push(val + index); | |
194 } | |
195 | |
196 // 変数にPop | |
197 void PopValue(int val) | |
198 { | |
199 global_value[val] = top(); pop(); | |
200 } | |
201 | |
202 // ローカル変数にPop | |
203 void PopLocal(int val) | |
204 { | |
205 stack[val + stack_base] = top(); pop(); | |
206 } | |
207 | |
208 // 配列変数にPop | |
209 void PopArray(int val) | |
210 { | |
211 int index = top().i_; pop(); | |
212 global_value[val + index] = top(); pop(); | |
213 } | |
214 | |
215 // ローカルの配列変数にPop | |
216 void PopLocalArray(int val) | |
217 { | |
218 int index = top().i_; pop(); | |
219 stack[val + stack_base + index] = top(); pop(); | |
220 } | |
221 | |
222 // ローカル変数(参照)にPop | |
223 void PopLocalRef(int val) | |
224 { | |
225 int addr = stack[val + stack_base].i_; | |
226 set_ref(addr, top()); pop(); | |
227 } | |
228 | |
229 // ローカルの配列変数(参照)にPop | |
230 void PopLocalArrayRef(int val) | |
231 { | |
232 int addr = stack[val + stack_base].i_; | |
233 int index = top().i_; pop(); | |
234 set_ref(addr + index, top()); pop(); | |
235 } | |
236 | |
237 // ローカル変数を確保 | |
238 void OpAllocStack(int val) | |
239 { | |
240 stack.resize(stack_base + val); | |
241 } | |
242 | |
243 // 空Pop(スタックトップを捨てる) | |
244 void OpPop() | |
245 { | |
246 pop(); | |
247 } | |
248 | |
249 // 単項マイナス | |
250 void OpNeg() | |
251 { | |
252 top().i_ = -top().i_; | |
253 } | |
254 | |
255 // == | |
256 void OpEq() | |
257 { | |
258 int rhs = top().i_; pop(); | |
259 int lhs = top().i_; pop(); | |
260 push(lhs == rhs); | |
261 } | |
262 | |
263 // != | |
264 void OpNe() | |
265 { | |
266 int rhs = top().i_; pop(); | |
267 int lhs = top().i_; pop(); | |
268 push(lhs != rhs); | |
269 } | |
270 | |
271 // > | |
272 void OpGt() | |
273 { | |
274 int rhs = top().i_; pop(); | |
275 int lhs = top().i_; pop(); | |
276 push(lhs > rhs); | |
277 } | |
278 | |
279 // >= | |
280 void OpGe() | |
281 { | |
282 int rhs = top().i_; pop(); | |
283 int lhs = top().i_; pop(); | |
284 push(lhs >= rhs); | |
285 } | |
286 | |
287 // < | |
288 void OpLt() | |
289 { | |
290 int rhs = top().i_; pop(); | |
291 int lhs = top().i_; pop(); | |
292 push(lhs < rhs); | |
293 } | |
294 | |
295 // <= | |
296 void OpLe() | |
297 { | |
298 int rhs = top().i_; pop(); | |
299 int lhs = top().i_; pop(); | |
300 push(lhs <= rhs); | |
301 } | |
302 | |
303 // && | |
304 void OpLogAnd() | |
305 { | |
306 int rhs = top().i_; pop(); | |
307 int lhs = top().i_; pop(); | |
308 push(lhs && rhs); | |
309 } | |
310 | |
311 // || | |
312 void OpLogOr() | |
313 { | |
314 int rhs = top().i_; pop(); | |
315 int lhs = top().i_; pop(); | |
316 push(lhs || rhs); | |
317 } | |
318 | |
319 // & | |
320 void OpAnd() | |
321 { | |
322 int rhs = top().i_; pop(); | |
323 int lhs = top().i_; pop(); | |
324 push(lhs & rhs); | |
325 } | |
326 | |
327 // | | |
328 void OpOr() | |
329 { | |
330 int rhs = top().i_; pop(); | |
331 int lhs = top().i_; pop(); | |
332 push(lhs | rhs); | |
333 } | |
334 | |
335 // << | |
336 void OpLeftShift() | |
337 { | |
338 int rhs = top().i_; pop(); | |
339 int lhs = top().i_; pop(); | |
340 push(lhs << rhs); | |
341 } | |
342 | |
343 // >> | |
344 void OpRightShift() | |
345 { | |
346 int rhs = top().i_; pop(); | |
347 int lhs = top().i_; pop(); | |
348 push(lhs >> rhs); | |
349 } | |
350 | |
351 // + | |
352 void OpAdd() | |
353 { | |
354 int rhs = top().i_; pop(); | |
355 int lhs = top().i_; pop(); | |
356 push(lhs + rhs); | |
357 } | |
358 | |
359 // - | |
360 void OpSub() | |
361 { | |
362 int rhs = top().i_; pop(); | |
363 int lhs = top().i_; pop(); | |
364 push(lhs - rhs); | |
365 } | |
366 | |
367 // * | |
368 void OpMul() | |
369 { | |
370 int rhs = top().i_; pop(); | |
371 int lhs = top().i_; pop(); | |
372 push(lhs * rhs); | |
373 } | |
374 | |
375 // / | |
376 void OpDiv() | |
377 { | |
378 int rhs = top().i_; pop(); | |
379 if (rhs == 0) | |
380 throw devide_by_zero(); | |
381 int lhs = top().i_; pop(); | |
382 push(lhs / rhs); | |
383 } | |
384 | |
385 // % | |
386 void OpMod() | |
387 { | |
388 int rhs = top().i_; pop(); | |
389 if (rhs == 0) | |
390 throw devide_by_zero(); | |
391 int lhs = top().i_; pop(); | |
392 push(lhs % rhs); | |
393 } | |
394 | |
395 // 文字列の== | |
396 void OpStrEq() | |
397 { | |
398 const std::string &rhs = text(top()); pop(); | |
399 const std::string &lhs = text(top()); pop(); | |
400 | |
401 push(lhs == rhs); | |
402 } | |
403 | |
404 // 文字列の!= | |
405 void OpStrNe() | |
406 { | |
407 const std::string &rhs = text(top()); pop(); | |
408 const std::string &lhs = text(top()); pop(); | |
409 | |
410 push(lhs != rhs); | |
411 } | |
412 | |
413 // 文字列の> | |
414 void OpStrGt() | |
415 { | |
416 const std::string &rhs = text(top()); pop(); | |
417 const std::string &lhs = text(top()); pop(); | |
418 | |
419 push(lhs > rhs); | |
420 } | |
421 | |
422 // 文字列の>= | |
423 void OpStrGe() | |
424 { | |
425 const std::string &rhs = text(top()); pop(); | |
426 const std::string &lhs = text(top()); pop(); | |
427 | |
428 push(lhs >= rhs); | |
429 } | |
430 | |
431 // 文字列の< | |
432 void OpStrLt() | |
433 { | |
434 const std::string &rhs = text(top()); pop(); | |
435 const std::string &lhs = text(top()); pop(); | |
436 | |
437 push(lhs < rhs); | |
438 } | |
439 | |
440 // 文字列の<= | |
441 void OpStrLe() | |
442 { | |
443 const std::string &rhs = text(top()); pop(); | |
444 const std::string &lhs = text(top()); pop(); | |
445 | |
446 push(lhs <= rhs); | |
447 } | |
448 | |
449 // 文字列の+ | |
450 void OpStrAdd() | |
451 { | |
452 const std::string &rhs = text(top()); pop(); | |
453 const std::string &lhs = text(top()); pop(); | |
454 | |
455 push(lhs + rhs); | |
456 } | |
457 | |
458 // 無条件ジャンプ | |
459 void OpJmp(int val) | |
460 { | |
461 jmp(val); | |
462 } | |
463 | |
464 // 真の時ジャンプ | |
465 void OpJmpC(int val) | |
466 { | |
467 int cond = top().i_; pop(); | |
468 if (cond) | |
469 jmp(val); | |
470 } | |
471 | |
472 // 偽の時ジャンプ | |
473 void OpJmpNC(int val) | |
474 { | |
475 int cond = top().i_; pop(); | |
476 if (!cond) | |
477 jmp(val); | |
478 } | |
479 | |
480 // switch文用特殊判定 | |
481 void OpTest(int val) | |
482 { | |
483 int value = top().i_; pop(); | |
484 if (value == top().i_) { | |
485 pop(); | |
486 jmp(val); | |
487 } | |
488 } | |
489 | |
490 // 関数コール | |
491 void OpCall(int val) | |
492 { | |
493 push(stack_base); | |
494 push(addr()); // リターンアドレスをPush | |
495 stack_base = stack.size(); // スタックベース更新 | |
496 jmp(val); | |
497 } | |
498 | |
499 // 引数なしリターン | |
500 void OpReturn() | |
501 { | |
502 stack.resize(stack_base); // ローカル変数排除 | |
503 int addr = top().i_; pop(); | |
504 stack_base = top().i_; pop(); | |
505 int arg_count = top().i_; pop(); | |
506 stack.pop(arg_count); | |
507 jmp(addr); | |
508 } | |
509 | |
510 // 引数付きリターン | |
511 void OpReturnV() | |
512 { | |
513 vm::value result = top(); pop(); | |
514 stack.resize(stack_base); // ローカル変数排除 | |
515 int addr = top().i_; pop(); | |
516 stack_base = top().i_; pop(); | |
517 int arg_count = top().i_; pop(); | |
518 stack.pop(arg_count); | |
519 push(result); | |
520 jmp(addr); | |
521 } | |
522 | |
523 // 仮想CPUプログラム停止 | |
524 void OpHalt() | |
525 { | |
526 } | |
527 | |
528 // システムコール(組み込み関数) | |
529 void OpSysCall(int val) | |
530 { | |
531 pop(); // arg_count | |
532 switch (val) { | |
533 case SYS_TOSTR: | |
534 sys_tostr(); | |
535 break; | |
536 case SYS_MESSAGE_BOX: | |
537 sys_message_box(); | |
538 break; | |
539 case SYS_MOVE_TO: | |
540 sys_move_to(); | |
541 break; | |
542 case SYS_LINE_TO: | |
543 sys_line_to(); | |
544 break; | |
545 case SYS_SET_COLOR: | |
546 sys_set_color(); | |
547 break; | |
548 case SYS_GET_DC: | |
549 sys_get_dc(); | |
550 break; | |
551 case SYS_RELEASE_DC: | |
552 sys_release_dc(); | |
553 break; | |
554 } | |
555 } | |
556 | |
557 // システムコール(MessageBox) | |
558 void sys_message_box() | |
559 { | |
560 const std::string message = text(top()); pop(); | |
561 const std::string title = text(top()); pop(); | |
562 | |
563 push(VmMessageBox(title.c_str(), message.c_str())); | |
564 } | |
565 | |
566 // システムコール(MoveTo) | |
567 void sys_move_to() | |
568 { | |
569 int y = top().i_; pop(); | |
570 int x = top().i_; pop(); | |
571 int dc = top().i_; pop(); | |
572 | |
573 VmMoveTo(dc, x, y); | |
574 } | |
575 | |
576 // システムコール(LineTo) | |
577 void sys_line_to() | |
578 { | |
579 int y = top().i_; pop(); | |
580 int x = top().i_; pop(); | |
581 int dc = top().i_; pop(); | |
582 | |
583 VmLineTo(dc, x, y); | |
584 } | |
585 | |
586 // システムコール(SetColor) | |
587 void sys_set_color() | |
588 { | |
589 int b = top().i_; pop(); | |
590 int g = top().i_; pop(); | |
591 int r = top().i_; pop(); | |
592 int dc = top().i_; pop(); | |
593 | |
594 VmSetColor(dc, r, g, b); | |
595 } | |
596 | |
597 // システムコール(GetDC) | |
598 void sys_get_dc() | |
599 { | |
600 push(VmGetDC()); | |
601 } | |
602 | |
603 // システムコール(ReleaseDC) | |
604 void sys_release_dc() | |
605 { | |
606 int dc = top().i_; pop(); | |
607 VmReleaseDC(dc); | |
608 } | |
609 | |
610 // システムコール(数値を文字列に変換) | |
611 void sys_tostr() | |
612 { | |
613 int v = top().i_; pop(); | |
614 char str[16]; | |
615 sprintf(str, "%d", v); | |
616 push(std::string(str)); // 戻り値はスタックに入れる | |
617 } | |
618 | |
619 private: | |
620 int value() { int v = *(int *)command_ptr_; command_ptr_ += 4; return v; } | |
621 int addr() const { return (int)(command_ptr_ - command_); } | |
622 void jmp(int addr) { command_ptr_ = command_ + addr; } | |
623 void push(int v) { stack.push(vm::value(v)); } | |
624 void push(const std::string &v) { stack.push(vm::value(v)); } | |
625 void push(const vm::value &v) { stack.push(v); } | |
626 void pop() { stack.pop(); } | |
627 const vm::value &top() const { return stack.top(); } | |
628 vm::value &top() { return stack.top(); } | |
629 std::string text(const vm::value &v) { return v.s_->str_; } | |
630 const vm::value &ref_to_value(int addr) const | |
631 { | |
632 if (addr & global_flag) | |
633 return global_value[addr & global_mask]; | |
634 return stack[addr]; | |
635 } | |
636 void set_ref(int addr, const vm::value &v) | |
637 { | |
638 if (addr & global_flag) | |
639 global_value[addr & global_mask] = v; | |
640 else | |
641 stack[addr] = v; | |
642 } | |
643 | |
644 private: | |
645 unsigned char *command_; | |
646 unsigned char *command_ptr_; | |
647 int command_size_; | |
648 char *text_buffer_; | |
649 int text_size_; | |
650 | |
651 vm::stack<vm::value, STACK_SIZE> stack; | |
652 std::vector<vm::value> global_value; | |
653 int stack_base; | |
654 } ; | |
655 | |
656 } | |
657 | |
658 #endif |