comparison Idea @ 0:d35df41eac69

Initial revision
author kono
date Thu, 13 Jan 2000 02:41:41 +0900
parents
children bf602558130d
comparison
equal deleted inserted replaced
-1:000000000000 0:d35df41eac69
1
2 Thu Nov 25 17:27:12 JST 1999
3
4 subroutine call がない
5 局所変数もない
6 その代わり、大域変数を多用する
7 大域変数のスコープは局所的
8 Fortran の用に局所変数は静的に取る
9 recursion する時には、自分で保存する
10 subroutine call時のレジスタのセーブも局所的に行う
11 それは、ちょっと変じゃない?
12 やっぱりデフォルトのフレームは持ち歩くか?
13
14 recursive call とそうでないのを区別するか?
15
16 fp は用意する方が良い
17
18 関数定義と同時に、それ専用のfpの構造体を用意する
19
20 C をcompileする時には、stackを持ち歩く
21 fp = (struct func_state *)stack
22 えっと、どこに代入するの? そういう問題もあるわけね。
23 じゃあ、fpは特別? それは気に入らないな。static
24 なfpにすれば良いわけね。
25
26 func(void *stack) {
27 static struct func_state {
28 static struct func_state *fp;
29 int local1;
30 brahbrah...
31 } func_state; // ここまで hidden
32 func_state.fp = (stack -= sizeof(struct func_state));
33 }
34
35 func_state をとってくる演算子があった方が良い? そうね。
36 func.state
37 ぐらい?
38
39 fp->local1 みたいなことだけするなら、C と同じになる。
40
41 call する時のarguemnt も、
42 static な func_state に置く
43 stack 上の func_state に置く
44 という二通りの選択肢がある。Cと互換なら、当然、後者。
45
46 Recursive なら後者だが、この言語は状態遷移を記述するから、static
47 なものでも良いはず。
48
49 Internal function は? あってもいいんだけど...
50
51 Recursive call する時には、 fp をsaveする必要があるね。
52 (--(struct func_state *)stack) = fp;
53 call callee(&fp->arg,continuation,stack);
54 call しても、戻って来ないから... continuation は一般的にはcode
55 だから... それは Internal function にするか。
56
57 continuation に一般的にcompileする方法を考えないといけないか。
58 self は必要なわけね?
59
60 言語の名前も考えないといかんなぁ。
61
62 C からのコンパイラも書かないといけないのか...
63
64 Mon Dec 13 18:53:04 JST 1999
65
66 compiler based で、内部で partial evaluation できる?
67
68 func をdatabaseとして扱えないなら、それはできない。
69
70 しかし、状態遷移としては取り扱える。
71
72 func.state
73 func.code
74
75 みたいな形にしてpartial evaluationすれば良い
76
77 でも止まるのか?
78
79 textual でない、中間的なコード表現があった方が良い? <-> interpreter?
80
81 Prolog ではなんでいけないの? --> Unification が重いから
82
83 Sat Nov 27 13:50:41 JST 1999
84
85 func.state とか作るのだったら、
86 struct {
87 struct {
88 int i;
89 } state;
90 state *code = {
91 i = i+1;
92 };
93 } name;
94 みたいな形で、それ自体を構造化すれば? で、代入すると部分評価される。
95 代入も可能。なるほど。
96 *name.code;
97 値はあるわけ? 値は &state でしょうね。
98 self があれば、
99 struct {
100 struct {
101 int i;
102 } state,
103 *code = {
104 self->i = self->i+1;
105 };
106 } name;
107 かな。self = state だよね。
108
109 union の拡張もあわせて議論すると...
110
111 Partial evalutator をセマンティクスや実行系にいれておくことは可能か?
112
113 byte code とか仮想マシンだったら可能。そうでない場合は?
114
115 いずれにせよ、構造体のタグのunique性を修正しないとだめだな。
116
117 ヘッダファイルはどうするの?
118
119 Mon Dec 13 18:53:18 JST 1999
120
121 library との整合性は?
122
123 exec sequence では、
124 (--(struct func_state *)stack) = fp;
125 call callee(&fp->arg);
126 という形でpointerだけ渡すの? それは変だよね。
127
128 値渡しにするとすれば、複数の値を渡せたほうが良い。
129
130 func(void *stack) {
131 static struct func_state {
132 static struct func_state *fp;
133 int local1;
134 brahbrah...
135 } func_state; // ここまで hidden
136 func_state.fp = (stack -= sizeof(struct func_state));
137 }
138
139 の引数自体が、構造体であるべき。
140
141 func(
142 struct void *stack
143 ) {
144 static struct func_state {
145 static struct func_state *fp;
146 int local1;
147 brahbrah...
148 } func_state; // ここまで hidden
149 func_state.fp = (stack -= sizeof(struct func_state));
150 }
151
152 で、構造体に register storage を許す。
153
154 func(
155 static struct argment {
156 register void *stack;
157 register void *continuation;
158 }
159 ) {
160 static struct func_state {
161 static struct func_state *fp;
162 int local1;
163 brahbrah...
164 } func_state; // ここまで hidden
165 func_state.fp = (stack -= sizeof(struct func_state));
166 }
167
168 すると、caller の方も、構造体を引数とするのが自然。
169
170 call caller(
171 static struct argment {
172 register void *stack;
173 register void *continuation;
174 } arg = {a,b};
175 )
176
177 みたいな。もちろん、この構造体はインタフェースと呼ばれる。
178
179 argument は、callee にあった方が良いけど、caller 側にあっても
180 良い。register なんかは、そう。
181
182 caller(interface caller_arg = {a,b,c})
183 みたいなsyntax かな。
184 caller->interface = {a,b,c};
185 *caller->code;
186 を、
187 caller(a,b,c);
188 と称する。
189
190 function には、interface と code と state があることになる。
191
192 state にアクセスする時のlockは? protected state? synchonized state かな?
193 もちろん、sequential implementatoinでは、そんなものはいらない。
194
195 function {
196 interface:
197 register int a;
198 register struct self self;
199 state:
200 int b;
201 serialized int c;
202 code:
203 b = a;
204 }
205
206 int にvoid value を定義する。実装は重くなるけど...
207
208 serialzed の semantics は?
209
210 もう少しmicro-Cに近く!
211
212 carring state と static state。
213
214 Mon Dec 13 19:42:41 JST 1999
215
216 interface に regsiter keyword を使うのは、あまりに
217 実装よりすぎる。でも、でないと状態にできない?
218 そんなことはないか。やっぱりcaller側のstatic 領域に
219 直接書き込む?
220
221 だとCより遅そう。でも、引数に40個とかかかれたら...
222
223 Wed Dec 15 14:09:49 JST 1999
224
225 C と互換にする?
226 goto function(argments);
227 goto *continuation(argments);
228 みたいな感じで。
229
230 stackの管理は? どうせ、library との互換はとらないと
231 いけないんだから...
232
233 local 変数がある場合は stack を動かす。でも、戻す奴がいない。
234 closure 化するか?
235
236 return した時の挙動が複雑になる。大域returnするわけだら。
237
238 argments をstatic 領域にかきこむ方式だと互換性がとれない。
239 stack 上の frmae pointer 上にないとダメだから。
240
241 両立させるのは無理か? つまり、これだと、呼び出された方の
242 frame semantics は、C と互換になる。だから、stackの直後に
243 frame pointer があると思っている (そうか? ) frame pointer
244 stack pointer に沿って移動した直後に、そこからのoffset
245 で引数を操作することになる。
246
247 つまり、それはだめだったことじゃない? つまり、goto だと、
248 frame pointer は、stack の直後とは限らないから。前の
249 frmae pointer 相対に引数にアクセスしてくれれば別だけどね。
250
251 stack に引数を積むのは容認して、goto の場合は、向こう側で
252 stack を畳むってのは? ということは、普通の関数と定義の
253 方法を変えるってことか。ま、悪くはないか。
254
255 すると、goto のsemantics は、C と互換になる。それを受ける
256 方が異なることをする。それは、なんかおかしいな。それに、
257 それだと関数呼び出しが軽くならない...
258
259 ということは、やはり、C のcall は、call funciton で
260 実現して、その他の呼び出しは、すべて、goto 扱いに
261 する方が正しいだろう。
262
263 問題は、この言語の関数をcallされた時だな。dual entry にして、
264 call の時と、goto の時を区別するか。
265 func: stack processing
266 func_goto: normal processing
267 ...
268 みたいな感じ。でも、return はないから...
269
270 このあたりも自分で記述できる言語であるべきだよね。その通り。
271 つまり、C とのstub も自分で記述すると言うことか。
272
273 protocol function {
274 interface c {
275 register "%esp" struct {
276 entry code ret(int);
277 void *fp;
278 } *sp;
279 register "%ebp" void *fp;
280 };
281 code function_code {
282 fp = sp;
283 sp += sizeof(struct local);
284 struct local *local = sp;
285
286 local->i = 1;
287 goto *fp->ret(local->i),sp=fp; // return(local->i);
288 };
289 }
290
291 みたいな感じでさ。さっすが、アセンブラ。いまいちreturnが汚いけど。
292 まぁ、return はそのままreturnでもいいけどさ。
293
294 あ、これは良いかも知れない。code が複数かけるから。
295
296 state 以外は、consitent state であることを保証しない。ってのは?
297 local 変数は使っても良いけど、call/goto の前後で、値を保証しないか...
298
299 うーん、だんだん炸裂してるなぁ。
300
301 だから、レジスタに対するマッピングの記述と、そうでない部分の
302 記述は分離するべきでしょうね。
303
304
305 全部一辺に実装するわけにはいかないからぁ...
306
307 Thu Dec 16 13:44:21 JST 1999
308
309 lock は状態遷移レベルで実現するのだから、self などを
310 使ってlockする必要はないはず。
311
312 全体の直列化は、状態遷移レベルで、
313 lock(storage) -> transition
314 みたいな形で記述すれば良い。この当たりを、どのように記述するかは
315 もう少し先送りしよう。
316
317
318 引数はレジスタ渡しにしよう。長い引数は、呼び出し側の領域への
319 ポインタとする。実装を規定しても良い。そうすれば、varargs
320 みたいなものはなくなる。だいたい、なんで、そんなものがいるんだろう?
321 配列を渡せばいいじゃん。
322
323 なので、引数は一つ(or 二つ)に限るという方法もある。
324
325 とすると、やはり、前もって静的領域や動的領域を確保することは
326 できない。
327
328 この言語では動的領域は自分で確保するわけだから、その点は問題ない。
329
330 Thu Dec 16 20:24:55 JST 1999
331
332 とすると関数呼び出しは、
333 # register save
334 # set 1st argument in register %eax
335 # set 2nd argument in register %ecx
336 # set extra aguments in save area
337 # set extra argument pointer in %edx
338 jmp function
339 という形式になるわけね。second を処理するのはめんどくさいから一つ
340 にしよう。
341
342 えーと、frame pointer はないけど、コンパイルの手順からすると
343 あった方が良い。しかし、frame pointer そのものをstatic
344 にとるのはまずい。だから、frame pointer がfirst argment
345 ということにする方が正しい。とすると引数は、さらに、その
346 後と言うわけか。
347 f(fp,argment)
348 fp を渡すのにさらにargment をレジスタで渡すのはおかしい。おかしいけど、
349 ま、良いか。
350
351 return しないなら、return type の定義をとるのは変だな。
352
353 f(fp,arg1,arg2,arg3) とすると、それぞれが決まったレジスタに入って、
354 多い分は配列にあると思われる。ふむふむ...
355 fp->xx
356 でアクセスすれば、そのまま局所変数になる。全部、配列で
357 送っても良い。
358
359 .set label,value
360
361 で as は値をセットするようですね。
362
363 関数コールの後は戻って来ないから後始末の心配はしなくてよい。
364 frame pointer を使ったら自分で面倒を見ること。
365
366 だと
367 a = atoi(s);
368 みたいなことはできない...
369
370 普通のCの定義と交じると間違いやすい。
371
372 とすると、struct と同様に、
373 protocol
374 code
375 interface
376 state
377 を用意するわけね。時間あるのかぁ?
378
379 とりあえず、register 渡しのfunction 定義とgoto文を実装する。
380
381 code name(register "%ebp" void *arg) {
382 goto name(arg);
383 }
384
385 ぐらいかな? で、first argment が必ずregisterにのるようにしないと
386 いけない。register storage class を入れて、
387 register "%ebp" void *arg
388 とかするわけね。
389
390 ってことは、まず、レジスタを実装しないといけないわけね。
391
392 で、stack を使った演算は、一応、そのままにする? それでも動くはず。
393 式の途中でgotoは使えないんだから、それでいいはず。
394
395 で、それから、これを拡張していく。
396
397 interface c {
398 register "%ebp" void *arg;
399 }
400 code name(interface c) {
401 goto name(c.arg); // c. は省略可能
402 }
403
404 とかね。さらに、
405
406 protocol name {
407 interface c {
408 register "%ebp" void *arg;
409 }
410 code name(interface c) {
411 goto name(arg);
412 }
413 code name1(interface c) {
414 goto name(arg);
415 }
416 }
417
418 などとするわけか。なんと、これが C と共存するわけね。うーん。
419
420 Fri Dec 31 11:44:03 JST 1999
421
422 code でなくて、別な名前のほうが良くない? segment? action?
423
424 レジスタ名が入るのは、やっぱりいや。optionalには許す。
425
426 interface は構造体のようなものだから... 構造体でいいんじゃない?
427 構造体の場合は... malloc する? う、うーん。malloc するとして、
428 いつfree するの?
429
430 再入するときには、壊れてていいんじゃない? multi-thread でなければね。
431 multi thread では、状態は、レジスタ経由または、thread local に持つ
432 必要がある。static は、だから thread local に持たなくてはならない。
433 大域変数に割り振っちゃだめ。でも、いまは、やめて
434
435 interface は、とりあえず、二つまでの値渡しにしよう。
436 self と arg
437 ですね。
438
439 もう少し拡張しやすいコンパイラがいいなぁ。
440
441 code name (c,a)
442 struct state *c; struct arg *a;
443 {
444 goto name(arg);
445 }
446
447 local 変数は? この互換性の問題かぁ。
448
449 KL/1 を意識して、interface は heap に置くことにしても良い。
450 GC は言語に入れておくべきだが、interfaceは machine independent
451 であるべき。だとすれば use/forget みたいものはいるだろう。
452 でも今のところは考える必要はない。
453
454 えーと、
455 code name (c,a)
456 struct state *c; struct arg *a;
457 {
458 int i;
459 goto name(arg);
460 }
461 の時の一時変数iはどうするの? 基本的にはレジスタ割り当てだけど...
462 使用させない? んー、大胆な御意見。まぁ、やっぱりheapに割り当てちゃう
463 のが簡単か。でも、どうせ抜ける時にはいらなくなるわけだから...
464
465 ほんらい、この変数は、次のcallでは必要無くなるのが普通。
466
467 とにかく、レジスタ変数は必要なんでしょう?
468
469 だから、GC と合わせて言語を設計すべきだよね。API を規定して、
470 異なるGCを選択できるようにする。
471
472 Sat Jan 1 22:40:22 JST 2000
473
474 とーにかく、 storage class regisgter を実装しよう。
475
476 stmode=REGISTER
477
478 で、local storage とおなじ扱いとする
479 static register? は、ない。
480
481 symbol table に storage class をたせば? dsp==EXTRN で判定しているから、
482 local 変数が36以上あるとおかしくなるぞ?
483
484 sc は GVAR/LVAR だけど、regsiter は LVAR の特殊な奴だから、
485 sc に入れるほうが正しいか...
486
487 Sun Jan 2 01:47:17 JST 2000
488
489 register 変数はできました。けど、regsiter を二つ使うと、
490 一杯になってしまうので、REGISTER6 でコンパイルしないと
491 結構ひどい。が、register 変数を%esi,%edi に割り当てれば
492 いいか。
493
494 Sun Jan 2 04:43:04 JST 2000
495
496 で、
497 code name (c,a)
498 struct state *c; struct arg *a;
499 {
500 goto name(c);
501 }
502 の一時変数無しは実装できます。引数は二つまでね。
503
504 .file "tmp.c"
505 .version "01.01"
506 gcc2_compiled.:
507 .text
508 #
509 # code name(c,a)
510 .align 2
511 .globl code
512 code:
513 .type code,@function
514 # struct state *c; struct arg *a;
515 # {
516 # goto name(c);
517 movl %esi,%esi
518 jmp name
519 _5:
520 .size code,_5-code
521 .ident "Micro-C compiled"
522
523 う、すごい。
524
525 goto 文がめんどくさい。stack をたたんで、jmp すれば
526 よいだけだが..
527
528 Sun Jan 2 11:17:50 JST 2000
529
530 普通のcallをcontinuation baseにすることができる?
531
532 Sun Jan 2 20:28:45 JST 2000
533
534 goto 文だけど、やはり、一度、expr で生成してから、top level
535 で jump code を生成しよう。
536
537 Tue Jan 4 03:32:55 JST 2000
538
539 code をtypeにしないと、
540 code *p;
541 とか書けないね。
542 int *p();
543 と同じだけどさ。
544
545
546 main(ac,av)
547 int ac;
548 char *av[];
549 {
550 goto code1(ac,av);
551 }
552
553 code code1(ac,av)
554 int ac;
555 char *av[];
556 {
557 if (ac)
558 goto code1(ac,av);
559 else
560 goto ac(ac,av);
561 }
562
563 Tue Jan 4 04:56:56 JST 2000
564
565 うーん、なんかレジスタにつむ順序が違う
566 これは、adecl がreverseにつむから。
567
568 code のretrun
569
570 やはりcodeはtypeにしないとだめ。
571
572 main()
573 {
574 goto code1();
575 }
576
577 とかだと、main に戻って来れない。もちろん、code1() 以降で、
578 return するわけにはいかない。(main の disp をcode1 は知り得ない)
579 goto label をcode1の引数に送れば?
580
581 main()
582 {
583 goto code1(ret);
584 ret:
585 }
586
587 これだと、ret がforward labelかどうか分からないけど?
588
589 code1 中で使う中間変数を stack 上にとるのは悪くない。しかし、それを
590 %ebp 経由でアクセスするということは、main の中間変数を壊すということ。
591 それを防ぐには、main 中のgoto codeで、%ebp を修正してやれば良い。
592 (今は戻って来ないので問題ない)
593
594 code1 のgoto では、戻って来ないから、その必要はない。しかし、
595 label をcode1 中で渡されると、ちょっと気まずい。
596
597 とすると、それは禁止して、main() 中でstackをたたんでからgotoするか?
598 そうすると、無限後退して、結局、帰れないことになる... うーん。
599
600 main() 中のlocal code を許せば、それは解決するが..
601
602 main()
603 {
604 goto code1(code2);
605 code code2() {
606 return;
607 }
608 }
609
610 みたいな感じ。でも、そうするとscope rule を変える必要があるので厳しい。
611 ま、悪くはないけどね。
612
613 continuation を明示する方法もある。
614
615 main()
616 {
617 goto code1(continuation);
618 }
619 code code1(ret)
620 code (*ret)();
621 {
622 goto *ret;
623 }
624
625 かな? call/cc ?
626
627 label へのgotoを許すのもいいけど、
628 でも、label を許すと、すごくspagettyにならない?
629
630
631 Tue Jan 4 11:47:24 JST 2000
632
633 contiunation じゃなくて、return keyword を使おう。
634 (実際、continuation と少し違うし)
635 type が少し変になるけど、まあ良い。
636
637 int
638 main()
639 {
640 goto code1(return);
641 }
642 code code1(ret)
643 code (*ret)(int);
644 {
645 goto *ret(3);
646 }
647
648 だな。prototype も付けないといけないか。
649
650 Tue Jan 4 12:21:44 JST 2000
651
652 これだとmethodがすべてstatic になってしまう。dynamic なmethod
653 呼び出しにするには? dipatcher を自分で作ることになる。かなり
654 めんどくさいが...
655
656 code method(obj,arg)
657 {
658 }
659
660 か、あるいは、inline にするか... #define のかわりに inline ねぇ。
661 これはあとで考えて良い。
662
663 Tue Jan 4 14:22:19 JST 2000
664
665 main の変数を書き潰すのと、gotgo (*reg)(123) での値は、
666 register 渡しで、current register にのらないので、
667 結局、return label は専用に作る必要がある。
668
669 Tue Jan 4 18:14:07 JST 2000
670
671 stack を継ぎ足して、呼び出す方式を取れば、call by value
672 のregister 渡しを制限する必要は無くなる。
673
674 複数の値を返すことも容易だ。
675
676 .file "tmp.c"
677 .version "01.01"
678 gcc2_compiled.:
679 .text
680 #
681 # code name(a,b,c,d,e,f)
682 .align 2
683 .globl code
684 code:
685 .type code,@function
686 # struct arg *a,*b,*c,*d,*e,*f;
687 # {
688 # int g;
689 # goto name(a,b,d,e,f);
690 jmp name
691 _5:
692 .size code,_5-code
693 .ident "Micro-C compiled"
694
695 おお?!
696 %esp new %esp = old %esp - 12 -4
697 %ebp-4 = g
698 %esi = a
699 %edi = b
700 %ebp = old %esp 0
701 %ebp+4 = c code_arg_offset=0
702 %ebp+8 = d
703 %ebp+12 = e
704 %ebp+16 = f
705
706 interface は付けよう! というか、
707 goto name(struct {xxxx})
708 みたいな感じで良いわけね。どれをregisterにいれるかと言う問題はあるが。
709
710 で、どうやってcallすればいいわけ? emit_pushするかわりにpush
711 する?
712
713 うう、これでは、だめか。code argument の数が変わると、
714 ebp をいちいち動かすことになる。そこにはold sp があるから
715 そいつもコピーする必要がある。
716
717 %esp new %esp = old %esp - 20
718 %ebp-20 = g
719 %esi = a
720 %edi = b
721 %ebp-16 = c code_arg_offset= -16 ((nargs-max_reg)*int_size)
722 %ebp-12 = d
723 %ebp-8 = e
724 %ebp-4 = f
725 %ebp = old %esp 0
726
727 そうか、function からcallする時には、local 変数を書き潰して良い。
728
729 # goto name(a,b,d,e,f);
730
731 %esp new %esp = old %esp - 20
732 %ebp-20 = g
733 %esi = a
734 %edi = b
735 %ebp-16 = c code_arg_offset= -16 ((nargs-max_reg)*int_size)
736 %ebp-12 = d
737 %ebp-8 = e
738 %ebp-4 = f
739 %ebp = old %esp 0 disp=0 (*)
740 local1 <----16 local variable
741 %edx -12 <- disp_offset
742 %ecx -8
743 %ebx -4
744 %ebp = %esp 0
745 %eip 4 <- arg_offset
746
747 となる。ということは、pushl %ebp は、間違い。
748
749 だけど、%ebp をそのまま使うのは良くない。disp_offset がかかっているから。
750 だから、もう一度 pushl %ebp したほうがよい。しかし、push する先は、
751 上の、(*)。
752 leave movl %ebp,%esp
753 popl %ebp
754 じゃなかったか?
755
756 Thu Jan 6 13:00:33 JST 2000
757
758 できたね。これでとりあえず動くはず。速度は問題だが...
759 あとは、
760 ANSI-C prototype
761 ANSI-C prototype check
762 Interface Definietion
763 GC support
764 Direct handling of Frame
765 だね。簡単に出来そう? たぶん...
766
767 Fri Jan 7 09:42:53 JST 2000
768
769 goto 文が動いてなかった。あと peep hole optimization version も
770 作るか?
771
772 continuation として label を送れるようにするべきか?
773 そうすると便利なんだけど、ちょっと、汚いプログラムが
774 出来るようになる。あと、送り側の環境(frame)を維持する
775 必要がある。ま、できなくはないか...
776
777 そうすると、label が値を持つようになる。
778 a = label:;
779 とか。うーん。label:(a,b,c) {}; みたいな形で、parallel 代入を許すと言う
780 手もあるね。
781
782 こちらの方がCとの相性は良いが... main() { label:(){ ... } }
783 みたいなnestを許すかどうかと言う問題がある。
784 変数の参照を許さなければ、特に問題はない。
785
786 a = label: は、二重の意味があるなぁ。
787
788 言語の名前。DinnerBell II とか? join も入れる?
789 code entry_a().entry_b() {}
790 ですか? parallel call も?
791
792 Fri Jan 7 19:53:53 JST 2000
793
794 いまのままだと return が環境を持ってないから、大域脱出できない。
795 まぁ、環境を入れてもいいんだけど、どこに置くかと言う問題が
796 あるね。
797
798 そうじゃなくて、return 側で判断するか?
799 retrun(ID)
800 みたいな形でIDで判断する。そうすれば、return 側でID
801 を見て判断できる。けど...
802
803 まぁ、はやり、環境を持って歩く方がいいかなぁ。でも、
804 引き渡しているから、二つ引き渡して、片方を使われたときに、
805 反対側が消えてしまうのはいたいよね。今のままならば、
806 そういうことは起こらない。
807
808 continuation 特有の問題を避けるなら、このままでもいいんだが...
809 contrinuation や環境は、このシステムでは自分で作ることが
810 できるからね。
811
812 そうなんだけど.... retlabel や retcont は実はオブジェクト
813 全体に一つあれば良い。
814
815 引数を渡すときに、そこに環境へのポインタをいれてやれば良いので、
816 解決は割と簡単だが、そうすると、例の構造体を引数で渡すと言う
817 問題を解決する必要がある。
818
819 でも、今の実装ならば、まったく同じ変数の構成ならばコピーは
820 実際には起こらないわけだから問題ないはず。特に、それを保証するために、
821 interface を実装する必要がある。
822
823 return ->
824 (void *)old bp
825 return address
826
827 bp を直接操作できるようにするといいんだけど....
828
829 Sat Jan 8 08:49:59 JST 2000
830
831 今は、code 内ではreturnできないわけだけど。実は、return って、
832 code return0(i) int i; { return(i); }
833 か? 今は禁止してないから書けちゃうよね。どういうcodeが出るんだろう?
834
835 doreturn() では retpending をセットしているだけだから、control=1
836 のまま。で、code の終りにくるのでエラーになる。checkret は、
837 statement の引数で判断するようにしたほうが合理的だろう。
838
839 大域脱出は結構根が深いよね。途中をスキップされてうれしいか?
840 destructor と同じで、途中のcodeは全部呼びたいのが普通だろう。
841
842 bp が同じになるまで return すれば良いわけだよね。
843 return と同じで、明示的に環境を引き渡すようにするか。
844 type は void * で良い?
845
846 return する時にstackの上限を越えているかどうかを自分でチェックする
847 必要があるね。誰にreturnするかをcodeで明示すれば良いわけだけど。
848
849 code return0(i) int i; { return(i); }
850
851 を許して、そこで、frame pointer を大域あるいは渡した引数と
852 比較して処理する?
853 code return0(i,env) int i; env *env; {
854 if (env==self) return(i);
855 }
856 あれ? これはおかしいよね。
857 code return0(i,env) int i; env *env; {
858 if (env!=self) {
859 env->return();
860 return(i);
861 }
862 }
863 も、なんか変だよなぁ。呼び出しと逆順に帰りたいわけだが...
864 実際、逆順には帰っているわけだよね。
865
866 return の中でこそこそ比較するという技もあるけど。
867
868 問題は、destructor に渡す情報だよね。もちろん、self で良いわけだが、
869 このあたりは、言語外の問題で、それを明示的にしたいから、この言語を
870 作っているわけなのだから、これを内部で処理するのはおかしい。
871
872 code return0(i) int i; { return(i); }
873
874 これだと、return の型が合わないと言う問題が生じるな。簡単には
875 チェックできない。
876 int
877 main() {
878 code a() {
879 }
880 code b() {
881 return(i);
882 }
883 }
884 にすれば、check はできるようになる。でも、これだと、
885 int
886 main() {
887 a: {
888 }
889 b: {
890 return(i);
891 }
892 }
893 と差がない。module 化を言語外でやるというのが主旨なのだから、これでは
894 まずい。これは高級アセンブラなのだから。
895
896 あそうか、return と、大域脱出時のabortとは、状況が違う。だから、
897 別なcode を呼び出さないとだめ。あるいは、値で区別するか。これは、
898 logic programming のfail/success と似ている。
899 main() { } abort { ... }
900 でもいいけど?
901 main() { code abort { ... }; code return { ... }}
902 かな?
903
904 本来、subroutine call自体が、かなりの省略形なわけだから、これは
905 仕方がない。今のままで通常のsubroutine callをシミュレートできるのか?
906 code (struct arg {...},void *sp) {
907 struct env;
908 push(sp,arg);
909 push(env,arg);
910 }
911 できるけど、ちょっと重い。やはり、frame pointer を直接操作しないと
912 だめ。
913
914 goto 文のほうに、env を一緒に送るものを作ったほうがいいのかも。
915 goto (*ret)(),environment;
916 かな。type は? (void *)?
917 goto ret(),environment;
918 にはならないの? そうすれば、自分でthreadを制御できる。environment
919 の正当性を評価しなくて良いの? まぁ、ねぇ。
920
921 これは実装は容易だが... goto といちいち書くのが本当にいいのか?
922 env に対するoperationがあった方がいいなぁ。push とか?
923
924 code return0(i) int i; { return(i); }
925
926 を認めれば、return 擬変数はいらなくなる。
927
928 でも、実は、return は、caller の引数の数と一致してないといけない
929 わけだから、 code return0(i) int i; { return(i); } はだめ。env
930 と一致してないといけない。ということは分離するとまずいんじゃない?
931 あれ? そんなはずないな。
932
933 Sun Jan 9 01:15:56 JST 2000
934
935 やはり、分離してはまずい。もともと、
936 goto func(arg);
937 自体が、
938 goto func(arg) with current.env
939 みたいなものだ。つまり、これは、DinnerBell の、
940 self message: arg
941 と同じ。self->func(arg); でも良い。が、function callと区別が付かないのは
942 良くない。
943
944 そうすると、type code はsize int でなくなる。
945 code *p = func;
946 ではいけなくて、
947 code p = {func,env};
948 でないといけない。実際、
949 goto func(arg)
950 では、current environment を pushl %ebp でstack = current env
951 に積んでいるわけだから。
952
953 いずれにせよ、
954 struct p = q;
955 は実装する必要がある。localな、
956 code p = {func,env};
957 も動くはずだが...
958
959 code (*p)();
960 goto (*p)(arg);
961
962 はだから少しおかしい。これは、goto がenv を補っていると考えるべき。
963
964 このようにすると、常に、
965 func,env
966 の組をcodeとみなすことになる。これは、object と呼ぶべきだ。
967 ただ、既存のobjectとは別だよな。actor の方が良い?
968
969 うーん、これでjoinを入れれば、完璧なDinnerBellだな。並列送信はないけど。
970
971 Sun Jan 9 01:40:05 JST 2000
972
973 local 変数の初期化はallocation の後に遅らせる必要がある。
974 nptr に入れられるはずだよね? nptr に初期化フラグを足すか?
975
976 文途中で出現するlocal変数の初期化。ちゃんと動いているの?
977
978 構造体のcopyは、lcheck を修正すべきでない。
979
980 Sun Jan 9 08:49:43 JST 2000
981
982 うーん、なんか修正が多いなぁ。あと、関数呼び出し、goto 文の
983 構造体への対応か。
984
985 goto (*code)();
986
987 が、self env を使うのか、code の先の値を使うのかを区別する
988 必要がある。もし*を使わないとするとlabel(FNAME)との区別が
989 つかないぞ。あ、でも、環境を持ち歩くことにしたから、label
990 へもjumpしようと思えばできるね。
991
992 並列送信はなくても、この構成ならばstatement単位の並列性を検出するのは
993 容易だろう。
994
995 やればできるけど、この修正の量だと1日じゃ終らないかなぁ。
996 不動小数点も入れるのでしょう?
997
998 Mon Jan 10 09:00:12 JST 2000
999
1000 引数に構造体を許すには、必ずANSI-Cにする必要がある。難しくは
1001 ないが...
1002
1003 goto 文には label, code, continuation の3つが来る。
1004 continuation = code + env
1005 | label +env
1006 なのだが、code/label では、env の内容が異なる。できれば面白いが、
1007 その価値はあるのか?
1008
1009 しかし、code , env を分離するとあまりに危険すぎる。どうせgoto
1010 が危険なんだからいいか? その方が簡単。簡単なら、そっちの方法を
1011 とるべきじゃない? うーん。
1012
1013 return の関数依存性はなくした方が良い。
1014 一つにするのは、pop の問題があるので良くないが...
1015
1016 そうか、ret をenvを指定して戻るようにしたから、leave する必要は
1017 なくなった。そして、push %ebp に相当する部分は、lea -disp(%ebp),%sp
1018 で消去されている。ということは、jump のfunction依存部分はいらない
1019 ということだね。
1020
1021 でも、汚いなぁ。read only属性をhardware supportできればなあ。
1022
1023 sched_yeilds() 相当を書けるかな? lock は?
1024
1025 一応、できたけど、やっぱり汚い。
1026
1027 Wed Jan 12 16:12:27 JST 2000
1028
1029 あは。ANSI prototype はめんどい。
1030 bexpr()
1031 で、関数での引数の順序と、そのあとの宣言の順序が変わることがある。
1032 そうすると、うしろの方が優先されてしまう。これは、こまる。
1033
1034 そうか、code_arg_offset のような方法だと、ANSI style では、
1035 困ってしまう。