root/NEWT0/trunk/src/newt_core/NewtVM.c

Revision 127, 92.8 kB (checked in by gnue, 7 months ago)

bug fix for revision 117(Make initialization via NBCInit explizit to allow repeated calls of NBCGenBC)

Line 
1/*------------------------------------------------------------------------*/
2/**
3 * @file    NewtVM.c
4 * @brief   VM
5 *
6 * @author  M.Nukui
7 * @date    2003-11-07
8 *
9 * Copyright (C) 2003-2004 M.Nukui All rights reserved.
10 */
11
12
13/* ヘッダファイル */
14#include <stdlib.h>
15#include <stdarg.h>
16
17#include "NewtErrs.h"
18#include "NewtVM.h"
19#include "NewtBC.h"
20#include "NewtGC.h"
21#include "NewtMem.h"
22#include "NewtEnv.h"
23#include "NewtObj.h"
24#include "NewtFns.h"
25#include "NewtStr.h"
26#include "NewtFile.h"
27#include "NewtIO.h"
28#include "NewtPrint.h"
29#include "NewtNSOF.h"
30#include "NewtPkg.h"
31
32
33/* 型宣言 */
34typedef void(*instruction_t)(int16_t b);            ///< 命令セット
35typedef void(*simple_instruction_t)(void);          ///< シンプル命令
36typedef newtRef(*nvm_func_t)();                     ///< ネイティブ関数
37
38
39/* グローバル変数 */
40vm_env_t    vm_env;
41
42
43#if 0
44#pragma mark -
45#endif
46
47
48/* マクロ */
49
50#define START_LOCALARGS     3                                       ///< ローカル引数の開始位置
51
52
53#define BC                  (vm_env.bc)                             ///< バイトコード
54#define BCLEN               (vm_env.bclen)                          ///< バイトコード長
55
56#define CALLSTACK           ((vm_reg_t *)vm_env.callstack.stackp)   ///< 呼出しスタック
57#define CALLSP              (vm_env.callstack.sp)                   ///< 呼出しスタックのスタックポインタ
58#define EXCPSTACK           ((vm_excp_t *)vm_env.excpstack.stackp)  ///< 例外スタック
59#define EXCPSP              (vm_env.excpstack.sp)                   ///< 例外スタックのスタックポインタ
60#define CURREXCP            (vm_env.currexcp)                       ///< 現在の例外
61
62#define REG                 (vm_env.reg)                            ///< レジスタ
63#define STACK               ((newtRef *)vm_env.stack.stackp)        ///< スタック
64
65#define FUNC                ((REG).func)                            ///< 実行中の関数
66#define PC                  ((REG).pc)                              ///< プログラムカウンタ
67#define SP                  ((REG).sp)                              ///< スタックポインタ
68#define LOCALS              ((REG).locals)                          ///< ローカルフレーム
69#define RCVR                ((REG).rcvr)                            ///< レシーバ
70#define IMPL                ((REG).impl)                            ///< インプリメンタ
71
72
73#if 0
74#pragma mark -
75#endif
76
77
78/* 関数プロトタイプ */
79
80static newtErr      NVMGetExceptionErrCode(newtRefArg r, bool dump);
81static newtRef      NVMMakeExceptionFrame(newtRefArg name, newtRefArg data);
82static void         NVMClearCurrException(void);
83
84static void         NVMSetFn(newtRefArg fn);
85static void         NVMNoStackFrameForReturn(void);
86
87static void         reg_rewind(int32_t sp);
88static void         reg_pop(void);
89static void         reg_push(int32_t sp);
90static void         reg_save(int32_t sp);
91
92static newtRef      stk_pop0(void);
93static newtRef      stk_pop(void);
94static void         stk_pop_n(int32_t n, newtRef a[]);
95static void         stk_remove(uint16_t n);
96static newtRef      stk_top(void);
97static void         stk_push(newtRefArg value);
98static void         stk_push_varg(int argc, va_list ap);
99static void         stk_push_array(newtRefVar argArray);
100
101static bool         excp_push(newtRefArg sym, newtRefArg pc);
102static void         excp_pop(void);
103static vm_excp_t *  excp_top(void);
104static void         excp_pop_handlers(void);
105
106static newtRef      liter_get(int16_t n);
107
108static newtRef      iter_new(newtRefArg r, newtRefArg deeply);
109static void         iter_next(newtRefArg iter);
110static bool         iter_done(newtRefArg iter);
111
112static newtRef      NVMMakeArgsArray(uint16_t numArgs);
113static void         NVMBindArgs(uint16_t numArgs);
114static void         NVMThrowBC(newtErr err, newtRefArg value, int16_t pop, bool push);
115static newtErr      NVMFuncCheck(newtRefArg fn, int16_t numArgs);
116static void         NVMCallNativeFn(newtRefArg fn, int16_t numArgs);
117static void         NVMCallNativeFunc(newtRefArg fn, newtRefArg rcvr, int16_t numArgs);
118static void         NVMFuncCall(newtRefArg fn, int16_t numArgs);
119static void         NVMMessageSend(newtRefArg impl, newtRefArg receiver, newtRefArg fn, int16_t numArgs);
120
121static newtRef      vm_send(int16_t b, newtErr * errP);
122static newtRef      vm_resend(int16_t b, newtErr * errP);
123
124static void         si_pop(void);
125static void         si_dup(void);
126static void         si_return(void);
127static void         si_pushself(void);
128static void         si_set_lex_scope(void);
129static void         si_iternext(void);
130static void         si_iterdone(void);
131static void         si_pop_handlers(void);
132
133static void         fn_add(void);
134static void         fn_subtract(void);
135static void         fn_aref(void);
136static void         fn_set_aref(void);
137static void         fn_equals(void);
138static void         fn_not(void);
139static void         fn_not_equals(void);
140static void         fn_multiply(void);
141static void         fn_divide(void);
142static void         fn_div(void);
143static void         fn_less_than(void);
144static void         fn_greater_than(void);
145static void         fn_greater_or_equal(void);
146static void         fn_less_or_equal(void);
147static void         fn_bit_and(void);
148static void         fn_bit_or(void);
149static void         fn_bit_not(void);
150static void         fn_new_iterator(void);
151static void         fn_length(void);
152static void         fn_clone(void);
153static void         fn_set_class(void);
154static void         fn_add_array_slot(void);
155static void         fn_stringer(void);
156static void         fn_has_path(void);
157static void         fn_classof(void);
158
159static void         is_dummy(int16_t b);
160static void         is_simple_instructions(int16_t b);
161static void         is_push(int16_t b);
162static void         is_push_constant(int16_t b);
163static void         is_call(int16_t b);
164static void         is_invoke(int16_t b);
165static void         is_send(int16_t b);
166static void         is_send_if_defined(int16_t b);
167static void         is_resend(int16_t b);
168static void         is_resend_if_defined(int16_t b);
169static void         is_branch(int16_t b);
170static void         is_branch_if_true(int16_t b);
171static void         is_branch_if_false(int16_t b);
172static void         is_find_var(int16_t b);
173static void         is_get_var(int16_t b);
174static void         is_make_frame(int16_t b);
175static void         is_make_array(int16_t b);
176static void         is_get_path(int16_t b);
177static void         is_set_path(int16_t b);
178static void         is_set_var(int16_t b);
179static void         is_find_and_set_var(int16_t b);
180static void         is_incr_var(int16_t b);
181static void         is_branch_if_loop_not_done(int16_t b);
182static void         is_freq_func(int16_t b);
183static void         is_new_handlers(int16_t b);
184
185static void         NVMDumpInstResult(FILE * f);
186static void         NVMDumpInstCode(FILE * f, uint8_t * bc, uint32_t pc, uint16_t len);
187
188static void         vm_env_push(vm_env_t * next);
189static void         vm_env_pop(void);
190
191static void         NVMInitREG(void);
192static void         NVMInitSTACK(void);
193static void         NVMCleanSTACK(void);
194
195static void         NVMInitGlobalFns0(void);
196static void         NVMInitGlobalFns1(void);
197static void         NVMInitExGlobalFns(void);
198static void         NVMInitDebugGlobalFns(void);
199static void         NVMInitGlobalFns(void);
200
201static void         NVMInitGlobalVars(void);
202
203static void         NVMLoop(uint32_t callsp);
204
205static newtRef      NVMInterpret2(nps_syntax_node_t * stree, uint32_t numStree, newtErr * errP);
206
207static newtRef      NVMFuncCallWithValist(newtRefArg fn, int argc, va_list ap);
208static newtRef      NVMMessageSendWithValist(newtRefArg impl, newtRefArg receiver, newtRefArg fn, int argc, va_list ap);
209
210
211/* ローカル変数 */
212
213/// シンプル命令テーブル
214static simple_instruction_t simple_instructions[] =
215            {
216                si_pop,             // 000 pop
217                si_dup,             // 001 dup
218                si_return,          // 002 return
219                si_pushself,        // 003 push-self
220                si_set_lex_scope,   // 004 set-lex-scope
221                si_iternext,        // 005 iter-next
222                si_iterdone,        // 006 iter-done
223                si_pop_handlers     // 007 000 001 pop-handlers
224            };
225
226
227/// 関数命令テーブル
228static simple_instruction_t fn_instructions[] =
229            {
230                fn_add,                 //  0 add               |+|
231                fn_subtract,            //  1 subtract          |-|
232                fn_aref,                //  2 aref              aref
233                fn_set_aref,            //  3 set-aref          setAref
234                fn_equals,              //  4 equals            |=|
235                fn_not,                 //  5 not               |not|
236                fn_not_equals,          //  6 not-equals        |<>|
237                fn_multiply,            //  7 multiply          |*|
238                fn_divide,              //  8 divide            |/|
239                fn_div,                 //  9 div               |div|
240                fn_less_than,           // 10 less-than         |<|
241                fn_greater_than,        // 11 greater-than      |>|
242                fn_greater_or_equal,    // 12 greater-or-equal  |>=|
243                fn_less_or_equal,       // 13 less-or-equal     |<=|
244                fn_bit_and,             // 14 bit-and           BAnd
245                fn_bit_or,              // 15 bit-or            BOr
246                fn_bit_not,             // 16 bit-not           BNot
247                fn_new_iterator,        // 17 new-iterator      newIterator
248                fn_length,              // 18 length            Length
249                fn_clone,               // 19 clone             Clone
250                fn_set_class,           // 20 set-class         SetClass
251                fn_add_array_slot,      // 21 add-array-slot    AddArraySlot
252                fn_stringer,            // 22 stringer          Stringer
253                fn_has_path,            // 23 has-path          none
254                fn_classof              // 24 class-of          ClassOf
255            };
256
257/// 命令セットテーブル
258static instruction_t    is_instructions[] =
259            {
260                is_simple_instructions,     // 00x simple instructions
261                is_dummy,                   // 01x
262                is_dummy,                   // 02x
263                is_push,                    // 03x push
264                is_push_constant,           // 04x (B signed) push-constant
265                is_call,                    // 05x call
266                is_invoke,                  // 06x invoke
267                is_send,                    // 07x send
268                is_send_if_defined,         // 10x send-if-defined
269                is_resend,                  // 11x resend
270                is_resend_if_defined,       // 12x resend-if-defined
271                is_branch,                  // 13x branch
272                is_branch_if_true,          // 14x branch-if-true
273                is_branch_if_false,         // 15x branch-if-false
274                is_find_var,                // 16x find-var
275                is_get_var,                 // 17x get-var
276                is_make_frame,              // 20x make-frame
277                is_make_array,              // 21x make-array
278                is_get_path,                // 220/221 get-path
279                is_set_path,                // 230/231 set-path
280                is_set_var,                 // 24x set-var
281                is_find_and_set_var,        // 25x find-and-set-var
282                is_incr_var,                // 26x incr-var
283                is_branch_if_loop_not_done, // 27x branch-if-loop-not-done
284                is_freq_func,               // 30x freq-func
285                is_new_handlers             // 31x new-handlers
286            };
287
288/// シンプル命令名テーブル
289static char *   simple_instruction_names[] =
290            {
291                "pop",              // 000 pop
292                "dup",              // 001 dup
293                "return",           // 002 return
294                "push-self",        // 003 push-self
295                "set-lex-scope",    // 004 set-lex-scope
296                "iter-next",        // 005 iter-next
297                "iter-done",        // 006 iter-done
298                "pop-handlers"      // 007 000 001 pop-handlers
299            };
300
301/// 関数命令名テーブル
302static char *   fn_instruction_names[] =
303            {
304                "add",              //  0 add       |+|
305                "subtract",         //  1 subtract      |-|
306                "aref",             //  2 aref      aref
307                "set-aref",         //  3 set-aref      setAref
308                "equals",           //  4 equals        |=|
309                "not",              //  5 not       |not|
310                "not-equals",       //  6 not-equals    |<>|
311                "multiply",         //  7 multiply      |*|
312                "divide",           //  8 divide        |/|
313                "div",              //  9 div       |div|
314                "less-than",        // 10 less-than     |<|
315                "greater-than",     // 11 greater-than  |>|
316                "greateror-equal"// 12 greater-or-equal  |>=|
317                "lessor-equal",     // 13 less-or-equal |<=|
318                "bit-and",          // 14 bit-and       BAnd
319                "bit-or",           // 15 bit-or        BOr
320                "bit-not",          // 16 bit-not       BNot
321                "new-iterator",     // 17 new-iterator  newIterator
322                "length",           // 18 length        Length
323                "clone",            // 19 clone     Clone
324                "set-class",        // 20 set-class     SetClass
325                "add-array-slot",   // 21 add-array-slot    AddArraySlot
326                "stringer",         // 22 stringer      Stringer
327                "has-path",         // 23 has-path      none
328                "class-of"          // 24 class-of      ClassOf
329            };
330
331/// 命令セット名テーブル
332static char *   vm_instruction_names[] =
333            {
334                "simple-instructions",      // 00x simple instructions
335                NULL,                       // 01x
336                NULL,                       // 02x
337                "push",                     // 03x push
338                "push-constant",            // 04x (B signed) push-constant
339                "call",                     // 05x call
340                "invoke",                   // 06x invoke
341                "send",                     // 07x send
342                "send-if-defined",          // 10x send-if-defined
343                "resend",                   // 11x resend
344                "resend-if-defined",        // 12x resend-if-defined
345                "branch",                   // 13x branch
346                "branch-if-true",           // 14x branch-if-true
347                "branch-if-false",          // 15x branch-if-false
348                "find-var",                 // 16x find-var
349                "get-var",                  // 17x get-var
350                "make-frame",               // 20x make-frame
351                "make-array",               // 21x make-array
352                "get-path",                 // 220/221 get-path
353                "set-path",                 // 230/231 set-path
354                "set-var",                  // 24x set-var
355                "find-and-set-var",         // 25x find-and-set-var
356                "incr-var",                 // 26x incr-var
357                "branch-if-loop-not-done"// 27x branch-if-loop-not-done
358                "freq-func",                // 30x freq-func
359                "new-handlers"              // 31x new-handlers
360            };
361
362
363#if 0
364#pragma mark -
365#endif
366
367
368/*------------------------------------------------------------------------*/
369/** self を取得
370 *
371 * @return          self
372 */
373
374newtRef NVMSelf(void)
375{
376    return RCVR;
377}
378
379
380/*------------------------------------------------------------------------*/
381/** 現在の関数オブジェクトを取得する
382 *
383 * @return      現在の関数オブジェクト
384 */
385newtRef NVMCurrentFunction(void)
386{
387    return FUNC;
388}
389
390
391/*------------------------------------------------------------------------*/
392/** 現在のインプリメンタを取得する
393 *
394 * @return      現在のインプリメンタ
395 */
396newtRef NVMCurrentImplementor(void)
397{
398    return IMPL;
399}
400
401
402/*------------------------------------------------------------------------*/
403/** 変数の存在チェック
404 *
405 * @param name      [in] 変数シンボル
406 *
407 * @retval          true        変数が存在する
408 * @retval          false       変数が存在しない
409 */
410
411bool NVMHasVar(newtRefArg name)
412{
413    if (NewtHasLexical(LOCALS, name))
414        return true;
415
416    if (NewtHasVariable(RCVR, name))
417        return true;
418
419    if (NewtHasGlobalVar(name))
420        return true;
421
422    return false;
423}
424
425
426/*------------------------------------------------------------------------*/
427/** 例外フレームからエラーコードを取得する
428 *
429 * @param r     [in] 変数シンボル
430 * @param dump  [in] ダンプフラグ
431 *
432 * @return      エラーコード
433 */
434
435newtErr NVMGetExceptionErrCode(newtRefArg r, bool dump)
436{
437    newtRefVar  err;
438
439    if (NewtRefIsNIL(r))
440        return kNErrNone;
441
442    if (dump)
443        NewtPrintObject(stderr, r);
444
445    err = NcGetSlot(r, NSSYM0(error));
446
447    if (NewtRefIsNotNIL(err))
448        return NewtRefToInteger(err);
449
450    return kNErrBadExceptionName;
451}
452
453
454/*------------------------------------------------------------------------*/
455/** 例外フレームを作成する
456 *
457 * @param name  [in] シンボル
458 * @param data  [in] データ
459 *
460 * @return      例外フレーム
461 */
462
463newtRef NVMMakeExceptionFrame(newtRefArg name, newtRefArg data)
464{
465    newtRefVar  r;
466
467    r = NcMakeFrame();
468    NcSetSlot(r, NSSYM0(name), name);
469
470    if (NewtHasSubclass(name, NSSYM0(type.ref)))
471        NcSetSlot(r, NSSYM0(data), data);
472    else if (NewtHasSubclass(name, NSSYM0(ext.ex.msg)))
473        NcSetSlot(r, NSSYM0(message), data);
474    else
475        NcSetSlot(r, NSSYM0(error), data);
476
477    return r;
478}
479
480
481/*------------------------------------------------------------------------*/
482/** 例外を発生させる
483 *
484 * @param name  [in] シンボル
485 * @param data  [in] 例外フレーム
486 *
487 * @return      なし
488 */
489
490void NVMThrowData(newtRefArg name, newtRefArg data)
491{
492    vm_excp_t * excp;
493    uint32_t    i;
494
495    // 例外処理中ならクリアする
496    NVMClearCurrException();
497
498    CURREXCP = data;
499
500    for (i = EXCPSP; 0 < i; i--)
501    {
502        excp = &EXCPSTACK[i - 1];
503
504        if (NewtHasSubclass(name, excp->sym))
505        {
506            reg_rewind(excp->callsp);
507            PC = excp->pc;
508            return;
509        }
510    }
511
512    NVMNoStackFrameForReturn();
513}
514
515
516/*------------------------------------------------------------------------*/
517/** 例外を発生させる
518 *
519 * @param name  [in] シンボル
520 * @param data  [in] データ
521 *
522 * @return      なし
523 */
524
525void NVMThrow(newtRefArg name, newtRefArg data)
526{
527    newtRefVar  r;
528
529    r = NVMMakeExceptionFrame(name, data);
530    NVMThrowData(name, r);
531}
532
533
534/*------------------------------------------------------------------------*/
535/** rethrow する
536 *
537 * @return      なし
538 */
539
540void NVMRethrow(void)
541{
542    if (NewtRefIsNotNIL(CURREXCP))
543    {
544        newtRefVar  currexcp;
545        newtRefVar  name;
546
547        currexcp = CURREXCP;
548        name = NcGetSlot(currexcp, NSSYM0(name));
549
550//        excp_pop_handlers();
551        NVMThrowData(name, currexcp);
552    }
553}
554
555
556/*------------------------------------------------------------------------*/
557/** 現在の例外を取得する
558 *
559 * @return      例外フレーム
560 */
561
562newtRef NVMCurrentException(void)
563{
564    return CURREXCP;
565}
566
567
568/*------------------------------------------------------------------------*/
569/** 例外が発生していたら例外スタックをクリアする
570 *
571 * @return      なし
572 */
573
574void NVMClearCurrException(void)
575{
576    if (NewtRefIsNotNIL(CURREXCP))
577    {
578        excp_pop_handlers();
579        CURREXCP = kNewtRefUnbind;
580    }
581}
582
583
584/*------------------------------------------------------------------------*/
585/** 現在の例外をクリアする
586 *
587 * @return      なし
588 *
589 * @note        ネイティブ関数で例外処理を行うために使用
590 */
591
592void NVMClearException(void)
593{
594    CURREXCP = kNewtRefUnbind;
595}
596
597
598#if 0
599#pragma mark -
600#endif
601/*------------------------------------------------------------------------*/
602/** 関数オブジェクトを現在の実行関数にする
603 *
604 * @param fn    [in] 関数オブジェクト
605 *
606 * @return      なし
607 */
608
609void NVMSetFn(newtRefArg fn)
610{
611    FUNC = fn;
612
613    if (NewtRefIsNIL(FUNC) || ! NewtRefIsCodeBlock(FUNC))
614    {
615        BC = NULL;
616        BCLEN = 0;
617    }
618    else
619    {
620        newtRefVar  instr;
621
622        instr = NcGetSlot(FUNC, NSSYM0(instructions));
623        BC = NewtRefToBinary(instr);
624        BCLEN = NewtLength(instr);
625    }
626}
627
628
629/*------------------------------------------------------------------------*/
630/** 戻る関数スタックがない場合の処理
631 *
632 * @return      なし
633 */
634
635void NVMNoStackFrameForReturn(void)
636{
637    BC = NULL;
638    BCLEN = 0;
639    CALLSP = 0;
640}
641
642
643#if 0
644#pragma mark *** 呼出しスタック
645#endif
646/*------------------------------------------------------------------------*/
647/** レジスタの巻き戻し
648 *
649 * @param sp    [in] 呼出しスタックのスタックポインタ
650 *
651 * @return      なし
652 */
653
654void reg_rewind(int32_t sp)
655{
656    if (sp == CALLSP)
657        return;
658
659    if (sp < CALLSP)
660    {
661        CALLSP = sp;
662        REG = CALLSTACK[CALLSP];
663        NVMSetFn(FUNC);
664    }
665    else
666    {
667        NVMNoStackFrameForReturn();
668    }
669}
670
671
672/*------------------------------------------------------------------------*/
673/** レジスタのポップ
674 *
675 * @return          なし
676 */
677
678void reg_pop(void)
679{
680    reg_rewind(CALLSP - 1);
681}
682
683
684/*------------------------------------------------------------------------*/
685/** レジスタのプッシュ
686 *
687 * @param sp        [in] スタックポインタ
688 *
689 * @return          なし
690 */
691
692void reg_push(int32_t sp)
693{
694    if (! NewtStackExpand(&vm_env.callstack, CALLSP + 1))
695        return;
696
697    CALLSTACK[CALLSP] = REG;
698    CALLSTACK[CALLSP].sp = sp;
699    CALLSP++;
700}
701
702
703/*------------------------------------------------------------------------*/
704/** レジスタの保存
705 *
706 * @param sp        [in] スタックポインタ
707 *
708 * @return          なし
709 */
710
711void reg_save(int32_t sp)
712{
713//    PC++;
714    reg_push(sp);
715}
716
717
718#if 0
719#pragma mark *** スタック
720#endif
721/*------------------------------------------------------------------------*/
722/** スタックのポップ
723 *
724 * @return          オブジェクト
725 */
726
727newtRef stk_pop0(void)
728{
729    newtRefVar  x = kNewtRefUnbind;
730
731    if (0 < SP)
732    {
733        SP--;
734        x = STACK[SP];
735    }
736
737    return x;
738}
739
740
741/*------------------------------------------------------------------------*/
742/** スタックのポップ(マジックポインタ参照を解決)
743 *
744 * @return          オブジェクト
745 */
746
747newtRef stk_pop(void)
748{
749    return NcResolveMagicPointer(stk_pop0());
750}
751
752
753/*------------------------------------------------------------------------*/
754/** スタックを n個ポップ
755 *
756 * @param n         [in] ポップする数
757 * @param a         [out]ポップしたオブジェクトを格納する配列
758 *
759 * @return          なし
760 */
761
762void stk_pop_n(int32_t n, newtRef a[])
763{
764    for (n--; 0 <= n; n--)
765    {
766        a[n] = stk_pop();
767    }
768}
769
770
771/*------------------------------------------------------------------------*/
772/** スタックを n個削除
773 *
774 * @return          なし
775 */
776
777void stk_remove(uint16_t n)
778{
779    if (n < SP)
780        SP -= n;
781    else
782        SP = 0;
783}
784
785
786/*------------------------------------------------------------------------*/
787/** スタックの先頭データを取出す
788 *
789 * @return          オブジェクト
790 */
791
792newtRef stk_top(void)
793{
794    if (0 < SP)
795        return STACK[SP - 1];
796    else
797        return kNewtRefNIL;
798}
799
800
801/*------------------------------------------------------------------------*/
802/** スタックにオブジェクトをプッシュ
803 *
804 * @param value     [in] オブジェクト
805 *
806 * @return          なし
807 */
808
809void stk_push(newtRefArg value)
810{
811    if (! NewtStackExpand(&vm_env.stack, SP + 1))
812        return;
813
814    STACK[SP] = value;
815    SP++;
816}
817
818
819/*------------------------------------------------------------------------*/
820/** 可変引数をスタックにプッシュする
821 *
822 * @param argc      [in] 引数の数
823 * @param ap        [in] 可変引数
824 *
825 * @return          なし
826 */
827
828void stk_push_varg(int argc, va_list ap)
829{
830    int     i;
831
832    for (i = 0; i < argc; i++)
833    {
834        stk_push(va_arg(ap, newtRefArg));
835    }
836}
837
838
839/*------------------------------------------------------------------------*/
840/** 配列の要素をスタックにプッシュする
841 *
842 * @param argArray  [in] 引数配列
843 *
844 * @return          なし
845 */
846
847void stk_push_array(newtRefVar argArray)
848{
849    int     numArgs;
850    int     i;
851
852    numArgs = NewtArrayLength(argArray);
853
854    for (i = 0; i < numArgs; i++)
855    {
856        stk_push(NewtGetArraySlot(argArray, i));
857    }
858}
859
860
861#if 0
862#pragma mark *** 例外ハンドラスタック
863#endif
864/*------------------------------------------------------------------------*/
865/** 例外スタックにプッシュ
866 *
867 * @param sym       [in] 例外シンボル
868 * @param pc        [in] プログラムカウンタ
869 *
870 * @retval          true    スタックされた
871 * @retval          false   スタックされなかった
872 */
873
874bool excp_push(newtRefArg sym, newtRefArg pc)
875{
876    vm_excp_t * excp;
877
878    if (! NewtRefIsSymbol(sym))
879        return false;
880
881    if (! NewtRefIsInteger(pc))
882        return false;