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

Revision 129, 66.4 kB (checked in by gnue, 7 months ago)

bug fix "get-path"(kNBCGetPath) B field.
"get-path" B field is zero or one.

Line 
1/*------------------------------------------------------------------------*/
2/**
3 * @file    NewtBC.c
4 * @brief   バイトコードの生成
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 <stdio.h>
15#include <stdlib.h>
16
17#include "NewtCore.h"
18#include "NewtBC.h"
19#include "NewtVM.h"
20#include "NewtIO.h"
21#include "NewtMem.h"
22
23
24/* 型宣言 */
25
26/// バイトコード環境
27typedef struct nbc_env_t    nbc_env_t;
28
29/// バイトコード環境(構造体定義)
30struct nbc_env_t {
31    nbc_env_t * parent;         ///< 呼出し元環境
32
33    newtStack   bytecode;       ///< バイトコードバッファ
34    newtStack   breakstack;     ///< ブレークスタック
35    newtStack   onexcpstack;    ///< 例外スタック
36
37    newtRefVar  func;           ///< 関数オブジェクト
38    newtRefVar  literals;       ///< 関数オブジェクトのリテラルフレーム
39    newtRefVar  argFrame;       ///< 関数オブジェクトのフレーム
40    newtRefVar  constant;       ///< 定数フレーム
41};
42
43
44/// 関数命令テーブル構造体
45typedef struct {
46    char *      name;       ///< 関数名
47    int32_t     numArgs;    ///< 引数の数
48    int16_t     b;          ///< バイトコード
49    newtRefVar  sym;        ///< シンボル
50} freq_func_t;
51
52
53/* 関数プロトタイプ */
54#define ENV_BC(env)             ((uint8_t*)env->bytecode.stackp)                ///< バイトコード
55#define ENV_CX(env)             (env->bytecode.sp)                              ///< コードインデックス(プログラムカウンタ)
56#define BC                      ENV_BC(newt_bc_env)                             ///< 作成中のバイトコード
57#define CX                      ENV_CX(newt_bc_env)                             ///< 作成中のコードインデックス(プログラムカウンタ)
58#define BREAKSTACK              ((uint32_t*)newt_bc_env->breakstack.stackp)     ///< ブレークスタック
59#define BREAKSP                 (newt_bc_env->breakstack.sp)                    ///< ブレークスタックのスタックポインタ
60#define ONEXCPSTACK             ((uint32_t*)newt_bc_env->onexcpstack.stackp)    ///< 例外スタック
61#define ONEXCPSP                (newt_bc_env->onexcpstack.sp)                   ///< 例外スタックのスタックポインタ
62#define LITERALS                (newt_bc_env->literals)                         ///< 作成中関数オブジェクトのリテラル
63#define ARGFRAME                (newt_bc_env->argFrame)                         ///< 作成中関数オブジェクトの引数フレーム
64#define CONSTANT                (newt_bc_env->constant)                         ///< 定数フレーム
65
66#define NBCAddLiteral(r)        NBCAddLiteralEnv(newt_bc_env, r)                ///< リテラルリストにオブジェクトを追加
67#define NBCGenCode(a, b)        NBCGenCodeEnv(newt_bc_env, a, b)                ///< バイトコードを生成
68#define NBCGenCodeL(a, r)       NBCGenCodeEnvL(newt_bc_env, a, r)               ///< リテラルなオペデータのバイトコードを生成
69#define NBCGenPushLiteral(r)    NBCGenPushLiteralEnv(newt_bc_env, r)            ///< リテラルをプッシュするバイトコードを生成
70
71#define NBCGenBC_op(stree, r)   NBCGenBC_stmt(stree, r, true)                   ///< 引数のバイトコードを生成する
72#define NBCGenFreq(b)           NBCGenCode(kNBCFreqFunc, b)                     ///< 関数命令のバイトコードを生成する
73
74
75#if 0
76#pragma mark -
77#pragma mark *** ローカル変数
78#endif
79
80
81/* ローカル変数 */
82
83/// バイドコード環境
84static nbc_env_t *  newt_bc_env;
85
86/// 関数命令テーブル
87static freq_func_t freq_func_tb[] =
88    {
89//      {"aref",            2,  kNBCAref,           0},
90//      {"setAref",         3,  kNBCSetAref,        0},
91        {"BAnd",            2,  kNBCBitAnd,         0},
92        {"BOr",             2,  kNBCBitOr,          0},
93        {"BNot",            1,  kNBCBitNot,         0},
94        {"Length",          1,  kNBCLength,         0},
95        {"Clone",           1,  kNBCClone,          0},
96        {"SetClass",        2,  kNBCSetClass,       0},
97        {"AddArraySlot",    2,  kNBCAddArraySlot,   0},
98        {"Stringer",        1,  kNBCStringer,       0},
99        {"ClassOf",         1,  kNBCClassOf,        0},
100
101        // end
102        {NULL,              0,  0,                  0}
103    };
104
105
106#if 0
107#pragma mark -
108#endif
109
110/* 関数プロトタイプ */
111static int16_t          NBCAddLiteralEnv(nbc_env_t * env, newtRefArg r);
112static void             NBCGenCodeEnv(nbc_env_t * env, uint8_t a, int16_t b);
113static void             NBCGenCodeEnvL(nbc_env_t * env, uint8_t a, newtRefArg r);
114static int16_t          NBCGenPushLiteralEnv(nbc_env_t * env, newtRefArg r);
115
116static void             NBCGenPUSH(newtRefArg r);
117static void             NBCGenGetVar(nps_syntax_node_t * stree, newtRefArg r);
118static void             NBCGenCallFn(newtRefArg fn, int16_t numArgs);
119static int16_t          NBCMakeFnArgFrame(newtRefArg argFrame, nps_syntax_node_t * stree, nps_node_t r, bool * indefiniteP);
120static int16_t          NBCMakeFnArgs(newtRefArg fn, nps_syntax_node_t * stree, nps_node_t r);
121static nbc_env_t *      NBCMakeFnEnv(nps_syntax_node_t * stree, nps_node_t args);
122static uint32_t         NBCGenBranch(uint8_t a);
123static void             NBCDefLocal(newtRefArg type, newtRefArg r, bool init);
124static void             NBCBackPatch(uint32_t cx, int16_t b);
125static void             NBCPushBreakStack(uint32_t cx);
126static void             NBCBreakBackPatchs(uint32_t loop_head, uint32_t cx);
127static void             NBCPushOnexcpStack(uint32_t cx);
128static void             NBCOnexcpBackPatchs(uint32_t try_head, uint32_t cx);
129static void             NBCGenOnexcpPC(int32_t pc);
130static void             NBCGenOnexcpBranch(void);
131static void             NBCOnexcpBackPatchL(uint32_t sp, int32_t pc);
132
133static newtRef          NBCMakeFn(nbc_env_t * env);
134static void             NBCInitFreqFuncTable(void);
135static nbc_env_t *      NBCEnvNew(nbc_env_t * parent);
136static void             NBCEnvFree(nbc_env_t * env);
137static newtRef          NBCFnDone(nbc_env_t ** envP);
138
139static void             NBCGenBC_stmt(nps_syntax_node_t * stree, nps_node_t r, bool ret);
140static void             NBCGenConstant(nps_syntax_node_t * stree, nps_node_t r);
141static void             NBCGenGlobalVar(nps_syntax_node_t * stree, nps_node_t r);
142static void             NBCGenLocalVar(nps_syntax_node_t * stree, nps_node_t type, nps_node_t r);
143static bool             NBCTypeValid(nps_node_t type);
144static int16_t          NBCGenTryPre(nps_syntax_node_t * stree, nps_node_t r);
145static int16_t          NBCGenTryPost(nps_syntax_node_t * stree, nps_node_t r, uint32_t * onexcpspP);
146static void             NBCGenTry(nps_syntax_node_t * stree, nps_node_t expr, nps_node_t onexception_list);
147static void             NBCGenIfThenElse(nps_syntax_node_t * stree, nps_node_t cond, nps_node_t thenelse, bool ret);
148static void             NBCGenAnd(nps_syntax_node_t * stree, nps_node_t op1, nps_node_t op2);
149static void             NBCGenOr(nps_syntax_node_t * stree, nps_node_t op1, nps_node_t op2);
150static void             NBCGenLoop(nps_syntax_node_t * stree, nps_node_t expr);
151static newtRef          NBCMakeTempSymbol(newtRefArg index, newtRefArg val, char * s);
152static void             NBCGenFor(nps_syntax_node_t * stree, nps_node_t r, nps_node_t expr);
153static void             NBCGenForeach(nps_syntax_node_t * stree, nps_node_t r, nps_node_t expr);
154static void             NBCGenWhile(nps_syntax_node_t * stree, nps_node_t cond, nps_node_t expr);
155static void             NBCGenRepeat(nps_syntax_node_t * stree, nps_node_t expr, nps_node_t cond);
156static void             NBCGenBreak(nps_syntax_node_t * stree, nps_node_t expr);
157static void             NBCGenStringer(nps_syntax_node_t * stree, nps_node_t op1, nps_node_t op2, char * dlmt);
158static void             NBCGenAsign(nps_syntax_node_t * stree, nps_node_t lvalue, nps_node_t expr, bool ret);
159static void             NBCGenExists(nps_syntax_node_t * stree, nps_node_t r);
160static void             NBCGenReceiver(nps_syntax_node_t * stree, nps_node_t r);
161static void             NBCGenMethodExists(nps_syntax_node_t * stree, nps_node_t receiver, nps_node_t name);
162static void             NBCGenFn(nps_syntax_node_t * stree, nps_node_t args, nps_node_t expr);
163static void             NBCGenGlobalFn(nps_syntax_node_t * stree, nps_node_t name, nps_node_t fn);
164static void             NBCGenCall(nps_syntax_node_t * stree, nps_node_t name, nps_node_t args);
165static void             NBCGenInvoke(nps_syntax_node_t * stree, nps_node_t fn, nps_node_t args);
166static void             NBCGenFunc2(nps_syntax_node_t * stree, newtRefArg name, nps_node_t op1, nps_node_t op2);
167static void             NBCGenSend(nps_syntax_node_t * stree, uint32_t code, nps_node_t receiver, nps_node_t r);
168static void             NBCGenResend(nps_syntax_node_t * stree, uint32_t code, nps_node_t name, nps_node_t args);
169static void             NBCGenMakeArray(nps_syntax_node_t * stree, nps_node_t klass, nps_node_t r);
170static void             NBCGenMakeFrame(nps_syntax_node_t * stree, nps_node_t r);
171static void             NVCGenNoResult(bool ret);
172static void             NBCGenSyntaxCode(nps_syntax_node_t * stree, nps_syntax_node_t * node, bool ret);
173static int16_t          NBCCountNumArgs(nps_syntax_node_t * stree, nps_node_t r);
174static newtRef          NBCGenMakeFrameSlots_sub(nps_syntax_node_t * stree, nps_node_t r);
175static newtRef          NBCGenMakeFrameSlots(nps_syntax_node_t * stree, nps_node_t r);
176static void             NBCGenBC_sub(nps_syntax_node_t * stree, uint32_t n, bool ret);
177
178
179#if 0
180#pragma mark -
181#endif
182/*------------------------------------------------------------------------*/
183/** リテラルリストにオブジェクトを追加する
184 *
185 * @param env       [in] バイトコード環境
186 * @param r         [in] オブジェクト
187 *
188 * @return          追加された位置
189 */
190
191int16_t NBCAddLiteralEnv(nbc_env_t * env, newtRefArg r)
192{
193    int16_t b;
194
195    b = NewtArrayLength(env->literals);
196    NcAddArraySlot(env->literals, r);
197
198    return b;
199}
200
201
202/*------------------------------------------------------------------------*/
203/** バイトコードを生成
204 *
205 * @param env       [in] バイトコード環境
206 * @param a         [in] 命令
207 * @param b         [in] オペデータ
208 *
209 * @return          なし
210 */
211
212void NBCGenCodeEnv(nbc_env_t * env, uint8_t a, int16_t b)
213{
214    uint8_t *   bc;
215    uint32_t    cx;
216
217    cx = ENV_CX(env);
218
219    if (! NewtStackExpand(&env->bytecode, cx + 3))
220        return;
221
222    bc = ENV_BC(env);
223
224    if (a == kNBCFieldMask)
225        b = 1;
226
227    if (a != kNBCFieldMask &&
228        ((a & kNBCFieldMask) == a ||
229        (b != kNBCFieldMask && (b & kNBCFieldMask) == b)))
230    {
231        bc[cx++] = a | b;
232    }
233    else
234    {
235        bc[cx++] = a | kNBCFieldMask;
236        bc[cx++] = b >> 8;
237        bc[cx++] = b & 0xff;
238    }
239
240    ENV_CX(env) = cx;
241}
242
243
244/*------------------------------------------------------------------------*/
245/** リテラルなオペデータのバイトコードを生成
246 *
247 * @param env       [in] バイトコード環境
248 * @param a         [in] 命令
249 * @param r         [in] オブジェクト
250 *
251 * @return          なし
252 */
253
254void NBCGenCodeEnvL(nbc_env_t * env, uint8_t a, newtRefArg r)
255{
256    newtRefVar  obj;
257    int16_t b = 0;
258
259    obj = NewtPackLiteral(r);
260
261    // リテラルを検索
262    b = NewtFindArrayIndex(env->literals, obj, 0);
263
264    if (b == -1) // リテラルに追加
265        b = NBCAddLiteralEnv(env, obj);
266
267    NBCGenCodeEnv(env, a, b);
268}
269
270
271/*------------------------------------------------------------------------*/
272/** リテラルをプッシュするバイトコードを生成
273 *
274 * @param env       [in] バイトコード環境
275 * @param r         [in] オブジェクト
276 *
277 * @return          リテラルリストの位置
278 */
279
280int16_t NBCGenPushLiteralEnv(nbc_env_t * env, newtRefArg r)
281{
282    newtRefVar  obj;
283    int16_t b;
284
285    obj = NewtPackLiteral(r);
286    b = NBCAddLiteralEnv(env, obj);
287
288    NBCGenCodeEnv(env, kNBCPush, b);
289
290    return b;
291}
292
293
294#if 0
295#pragma mark -
296#endif
297/*------------------------------------------------------------------------*/
298/** オブジェクトをプッシュするバイトコードを生成
299 *
300 * @param r         [in] オブジェクト
301 *
302 * @return          なし
303 */
304
305void NBCGenPUSH(newtRefArg r)
306{
307    switch (NewtGetRefType(r, false))
308    {
309        case kNewtInt30:
310            {
311                int32_t n;
312
313                n = NewtRefToInteger(r);
314
315                if (-8192 <= n && n <= 8191)
316                    NBCGenCode(kNBCPushConstant, r);
317                else
318                    NBCGenCodeL(kNBCPush, r);
319            }
320            break;
321
322        case kNewtNil:
323        case kNewtTrue:
324        case kNewtUnbind:
325            NBCGenCode(kNBCPushConstant, r);
326            break;
327
328        case kNewtCharacter:
329        case kNewtSpecial:
330        case kNewtMagicPointer:
331            if ((r & 0xffff0000) == 0)
332                NBCGenCode(kNBCPushConstant, r);
333            else
334                NBCGenCodeL(kNBCPush, r);
335            break;
336
337        case kNewtPointer:
338        default:
339            NBCGenCodeL(kNBCPush, r);
340            break;
341    }
342}
343
344
345/*------------------------------------------------------------------------*/
346/** 変数を取得するバイトコードを生成
347 *
348 * @param stree     [in] 構文木
349 * @param r         [in] 変数名オブジェクト
350 *
351 * @return          なし
352 */
353
354void NBCGenGetVar(nps_syntax_node_t * stree, newtRefArg r)
355{
356    if (NewtHasSlot(CONSTANT, r))
357    {
358        // 定数の場合
359        newtRefVar  c;
360
361        c = NcGetSlot(CONSTANT, r);
362
363        if (! NPSRefIsSyntaxNode(c) && NewtRefIsLiteral(c))
364            NBCGenPUSH(c);
365        else
366            NBCGenBC_op(stree, c);
367    }
368    else
369    {
370        int16_t b;
371
372        // ローカル変数を検索
373        b = NewtFindSlotIndex(ARGFRAME, r);
374   
375        if (b != -1)
376            NBCGenCode(kNBCGetVar, b);
377        else
378            NBCGenCodeL(kNBCFindVar, r);
379    }
380}
381
382
383/*------------------------------------------------------------------------*/
384/** 関数呼出しのバイトコードを生成
385 *
386 * @param fn        [in] 関数オブジェクト
387 * @param numArgs   [in] 引数の数
388 *
389 * @return          なし
390 */
391
392void NBCGenCallFn(newtRefArg fn, int16_t numArgs)
393{
394    int i;
395
396    // freq-func の場合
397    for (i = 0; freq_func_tb[i].name != NULL; i++)
398    {
399        if (NewtRefEqual(fn, freq_func_tb[i].sym))
400        {
401            if (numArgs != freq_func_tb[i].numArgs)
402            {
403                NBError(kNErrWrongNumberOfArgs);
404                return;
405            }
406
407            NBCGenFreq(freq_func_tb[i].b);
408            return;
409        }
410    }
411
412    // call function
413    NBCGenPUSH(fn);
414    NBCGenCode(kNBCCall, numArgs);
415}
416
417
418/*------------------------------------------------------------------------*/
419/** 関数の引数フレームを作成する
420 *
421 * @param argFrame      [in] 引数フレーム
422 * @param stree         [in] 構文木
423 * @param r             [in] 構文木ノード
424 * @param indefiniteP   [out]不定長フラグ
425 *
426 * @return          引数の数
427 */
428
429int16_t NBCMakeFnArgFrame(newtRefArg argFrame, nps_syntax_node_t * stree, nps_node_t r, bool * indefiniteP)
430{
431    int16_t numArgs = 1;
432
433    if (r == kNewtRefUnbind)
434        return 0;
435
436    if (*indefiniteP == true)
437    {
438        NBError(kNErrSyntaxError);
439        return 0;
440    }
441
442    if (NPSRefIsSyntaxNode(r))
443    {
444        nps_syntax_node_t * node;
445
446        node = &stree[NPSRefToSyntaxNode(r)];
447
448        switch (node->code)
449        {
450            case kNPSCommaList:
451                numArgs = NBCMakeFnArgFrame(argFrame, stree, node->op1, indefiniteP)
452                            + NBCMakeFnArgFrame(argFrame, stree, node->op2, indefiniteP);
453                break;
454
455            case kNPSArg:
456                // type (node->op1) はとりあえず無視
457                NcSetSlot(argFrame, node->op2, kNewtRefUnbind);
458                break;
459
460            case kNPSIndefinite:
461                // 不定長
462                NcSetSlot(argFrame, node->op1, kNewtRefUnbind);
463                *indefiniteP = true;
464                numArgs = 0;
465                break;
466
467            default:
468                NBError(kNErrSyntaxError);
469                break;
470        }
471    }
472    else
473    {
474        NcSetSlot(argFrame, r, kNewtRefUnbind);
475    }
476
477    return numArgs;
478}
479
480
481/*------------------------------------------------------------------------*/
482/** 関数オブジェクトの引数を作成する
483 *
484 * @param fn        [in] 関数オブジェクト
485 * @param stree     [in] 構文木
486 * @param r         [in] 構文木ノード
487 *
488 * @return          引数の数
489 */
490
491int16_t NBCMakeFnArgs(newtRefArg fn, nps_syntax_node_t * stree, nps_node_t r)
492{
493    int16_t numArgs = 0;
494
495    if (r != kNewtRefUnbind)
496    {
497        newtRefVar  argFrame;
498        bool        indefinite = false;
499
500        argFrame = NcGetSlot(fn, NSSYM0(argFrame));
501        numArgs = NBCMakeFnArgFrame(argFrame, stree, r, &indefinite);
502
503        if (0 < numArgs)
504            NcSetSlot(fn, NSSYM0(numArgs), NewtMakeInteger(numArgs));
505 
506        if (indefinite)
507            NcSetSlot(fn, NSSYM0(indefinite), kNewtRefTRUE);
508    }
509
510    return numArgs;
511}
512
513
514/*------------------------------------------------------------------------*/
515/** 関数のバイトコード環境を作成する
516 *
517 * @param stree     [in] 構文木
518 * @param args      [in] 引数
519 *
520 * @return          バイトコード環境
521 */
522
523nbc_env_t * NBCMakeFnEnv(nps_syntax_node_t * stree, nps_node_t args)
524{
525    newt_bc_env = NBCEnvNew(newt_bc_env);
526
527    if (newt_bc_env != NULL)
528        NBCMakeFnArgs(newt_bc_env->func, stree, args);
529
530    return newt_bc_env;
531}
532
533
534/*------------------------------------------------------------------------*/
535/** 分岐命令のバイトコードを生成
536 *
537 * @param a         [in] 命令
538 *
539 * @return          バイトコードの位置
540 */
541
542uint32_t NBCGenBranch(uint8_t a)
543{
544    uint32_t    cx;
545
546    cx = CX;
547    NBCGenCode(a, 0xffff);  // 0xffff is dummy
548
549    return cx;
550}
551
552
553#if 0
554#pragma mark -
555#endif
556/*------------------------------------------------------------------------*/
557/** ローカル変数を定義するバイトコードを生成
558 *
559 * @param type      [in] 変数の型
560 * @param r         [in] 変数名シンボル
561 * @param init      [in] 初期化
562 *
563 * @return          なし
564 *
565 * @note            もし init が true ならば初期化するバイトコードを生成する
566 *                  現在のバージョンでは type は完全に無視される
567 */
568
569void NBCDefLocal(newtRefArg type, newtRefArg r, bool init)
570{
571    NcSetSlot(ARGFRAME, r, kNewtRefUnbind);
572
573    if (init)
574    {
575        int16_t b;
576   
577        // ローカル変数を検索
578        b = NewtFindSlotIndex(ARGFRAME, r);
579
580        if (b != -1)
581            NBCGenCode(kNBCSetVar, b);
582        else
583            NewtFprintf(stderr, "Not inpriment");
584    }
585}
586
587
588#if 0
589#pragma mark -
590#endif
591/*------------------------------------------------------------------------*/
592/** バイトコードをバックパッチする
593 *
594 * @param cx        [in] バックパッチする位置
595 * @param b         [in] バックパッチするオペデータ
596 *
597 * @return          なし
598 *
599 * @note                分岐命令やループ命令などすぐにオペデータが決定しない場合に使う
600 */
601
602void NBCBackPatch(uint32_t cx, int16_t b)
603{
604    BC[cx + 1] = b >> 8;
605    BC[cx + 2] = b & 0xff;
606}
607
608
609/*------------------------------------------------------------------------*/
610/** ブレーク命令の位置をスタックする
611 *
612 * @param cx        [in] ブレーク命令の位置
613 *
614 * @return          なし
615 *
616 * @note                バックパッチのために覚えておく
617 */
618
619void NBCPushBreakStack(uint32_t cx)
620{
621    if (BREAKSTACK == NULL)
622        NewtStackSetup(&newt_bc_env->breakstack, NEWT_POOL, sizeof(uint32_t), NEWT_NUM_BREAKSTACK);
623
624    if (! NewtStackExpand(&newt_bc_env->breakstack, BREAKSP + 1))
625        return;
626
627    BREAKSTACK[BREAKSP] = cx;
628    BREAKSP++;
629}
630
631
632/*------------------------------------------------------------------------*/
633/** ループ内のブレーク命令をバックパッチする
634 *
635 * @param loop_head [in] ループの開始位置
636 * @param cx        [in] ループの終わり位置
637 *
638 * @return          なし
639 */
640
641void NBCBreakBackPatchs(uint32_t loop_head, uint32_t cx)
642{
643    uint32_t    branch;
644
645    for (; 0 < BREAKSP; BREAKSP--)
646    {
647        branch = BREAKSTACK[BREAKSP - 1];
648
649        if (branch < loop_head)
650            break;
651
652        NBCBackPatch(branch, cx);   // ブランチをバックパッチ
653    }
654}
655
656
657#if 0
658#pragma mark -
659#endif
660/*------------------------------------------------------------------------*/
661/** 例外処理命令の位置をスタックする
662 *
663 * @param cx        [in] 例外処理命令の位置
664 *
665 * @return          なし
666 *
667 * @note                バックパッチのために覚えておく
668 */
669
670void NBCPushOnexcpStack(uint32_t cx)
671{
672    if (ONEXCPSTACK == NULL)
673        NewtStackSetup(&newt_bc_env->onexcpstack, NEWT_POOL, sizeof(uint32_t), NEWT_NUM_ONEXCPSTACK);
674
675    if (! NewtStackExpand(&newt_bc_env->onexcpstack, ONEXCPSP + 1))
676        return;
677
678    ONEXCPSTACK[ONEXCPSP] = cx;
679    ONEXCPSP++;
680}
681
682
683/*------------------------------------------------------------------------*/
684/** TRY文内のブレーク命令をバックパッチする
685 *
686 * @param try_head  [in] TRY文の開始位置
687 * @param cx        [in] TRY文の終わり位置
688 *
689 * @return          なし
690 */
691
692void NBCOnexcpBackPatchs(uint32_t try_head, uint32_t cx)
693{
694    uint32_t    branch;
695
696    for (; 0 < ONEXCPSP; ONEXCPSP--)
697    {
698        branch = ONEXCPSTACK[ONEXCPSP - 1];
699
700        if (branch < try_head)
701            break;
702
703        NBCBackPatch(branch, cx);   // ブランチをバックパッチ
704    }
705}
706
707
708/*------------------------------------------------------------------------*/
709/** 例外処理命令のバイトコードを生成する
710 *
711 * @param pc        [in] 例外処理命令のプログラムカウンタ
712 *
713 * @return          なし
714 */
715
716void NBCGenOnexcpPC(int32_t pc)
717{
718    newtRefVar  r;
719    int16_t b;
720
721    r = NewtMakeInteger(pc);
722    b = NBCGenPushLiteral(r);
723
724    NBCPushOnexcpStack(b);  // バックパッチのためにスタックにプッシュする
725}
726
727
728/*------------------------------------------------------------------------*/
729/** 例外処理内のブレーク命令のバイトコードを生成する
730 *
731 * @return          なし
732 */
733
734void NBCGenOnexcpBranch(void)
735{
736    uint32_t    cx;
737   
738    cx = NBCGenBranch(kNBCBranch);  // ブランチ
739    NBCPushOnexcpStack(cx);         // バックパッチのためにスタックにプッシュする
740}
741
742
743/*------------------------------------------------------------------------*/
744/** バックパッチ時に例外処理シンボルをリテラルリストに登録する
745 *
746 * @param sp        [in] 例外処理命令スタックのスタックポインタ
747 * @param pc        [in] 例外処理命令のプログラムカウンタ
748 *
749 * @return          なし
750 */
751
752void NBCOnexcpBackPatchL(uint32_t sp, int32_t pc)
753{
754    newtRefVar  r;
755
756    if (ONEXCPSTACK == NULL || ONEXCPSP <= sp)
757        return;
758
759    r = NewtMakeInteger(pc);
760    NewtSetArraySlot(LITERALS, ONEXCPSTACK[sp], r);
761}
762
763
764#if 0
765#pragma mark -
766#endif
767/*------------------------------------------------------------------------*/
768/** 関数オブジェクトを作成する
769 *
770 * @param env       [in] バイトコード環境
771 *
772 * @return          関数オブジェクト
773 */
774
775newtRef NBCMakeFn(nbc_env_t * env)
776{
777    newtRefVar  fnv[] = {
778                            NS_CLASS,               NSSYM0(CodeBlock),
779                            NSSYM0(instructions),   kNewtRefNIL,
780                            NSSYM0(literals),       kNewtRefNIL,
781                            NSSYM0(argFrame),       kNewtRefNIL,
782                            NSSYM0(numArgs),        kNewtRefNIL
783                        };
784
785    newtRefVar  afv[] = {
786                            NSSYM0(_nextArgFrame),  kNewtRefNIL,
787                            NSSYM0(_parent),        kNewtRefNIL,
788                            NSSYM0(_implementor),   kNewtRefNIL
789                        };
790
791    newtRefVar  fn;
792    int32_t numArgs = 0;
793
794    // literals
795    env->literals = NewtMakeArray(NSSYM0(literals), 0);
796
797    // argFrame
798    env->argFrame = NewtMakeFrame2(sizeof(afv) / (sizeof(newtRefVar) * 2), afv);
799
800    // function
801    fn = NewtMakeFrame2(sizeof(fnv) / (sizeof(newtRefVar) * 2), fnv);
802
803//    NcSetClass(fn, NSSYM0(CodeBlock));
804    NcSetSlot(fn, NSSYM0(instructions), kNewtRefNIL);
805    NcSetSlot(fn, NSSYM0(literals), env->literals);
806    NcSetSlot(fn, NSSYM0(argFrame), env->argFrame);
807    NcSetSlot(fn, NSSYM0(numArgs), NewtMakeInteger(numArgs));
808
809    env->func = fn;
810
811    // constant
812    if (env->parent)
813    {   // 親があれば定数フレームを共有する
814        env->constant = env->parent->constant;
815    }
816    else
817    {   // 親がなければ新規に定数フレームを作成
818        env->constant = NcMakeFrame();
819    }
820
821    return fn;
822}
823
824
825/*------------------------------------------------------------------------*/
826/** 関数命令テーブルを初期化する
827 *
828 * @return          なし
829 */
830
831void NBCInitFreqFuncTable(void)
832{
833    int i;
834
835    for (i = 0; freq_func_tb[i].name != NULL; i++)
836    {
837        freq_func_tb[i].sym = NewtMakeSymbol(freq_func_tb[i].name);
838    }
839}
840
841
842/*------------------------------------------------------------------------*/
843/** バイトコード環境を作成する
844 *
845 * @param parent    [in] 呼出し元のバイトコード環境
846 *
847 * @return          バイトコード環境
848 */
849
850nbc_env_t * NBCEnvNew(nbc_env_t * parent)
851{
852    nbc_env_t * env;
853
854    env = (nbc_env_t *)NewtMemCalloc(NEWT_POOL, 1, sizeof(nbc_env_t));
855
856    if (env != NULL)
857    {
858        env->parent = parent;
859        NewtStackSetup(&env->bytecode, NEWT_POOL, sizeof(uint8_t), NEWT_NUM_BYTECODE);
860
861        NBCMakeFn(env);
862    }
863
864    return env;
865}
866
867
868/*------------------------------------------------------------------------*/
869/** バイトコード環境を解放する
870 *
871 * @param env       [in] バイトコード環境
872 *
873 * @return          なし
874 */
875
876void NBCEnvFree(nbc_env_t * env)
877{
878    if (env != NULL)
879    {
880        NewtStackFree(&env->bytecode);
881        NewtStackFree(&env->breakstack);
882        NewtStackFree(&env->onexcpstack);
883
884        NewtMemFree(env);
885    }
886}
887
888
889/*------------------------------------------------------------------------*/
890/** 関数オブジェクトの生成を終了する
891 *
892 * @param envP      [in] バイトコード環境へのポインタ
893 *
894 * @return          関数オブジェクト
895 */
896
897newtRef NBCFnDone(nbc_env_t ** envP)
898{
899    nbc_env_t * env = *envP;
900    newtRefVar  fn = kNewtRefNIL;
901
902    if (env != NULL)
903    {
904        newtRefVar  instr;
905        newtRefVar  literals;
906
907        NBCGenCodeEnv(env, kNBCReturn, 0);
908
909        fn = env->func;
910        instr = NewtMakeBinary(kNewtRefNIL, ENV_BC(env), ENV_CX(env), true);
911        NcSetSlot(fn, NSSYM0(instructions), instr);
912   
913        literals = NcGetSlot(fn, NSSYM0(literals));
914
915        if (NewtRefIsNotNIL(literals) && NcLength(literals) == 0)
916            NcSetSlot(fn, NSSYM0(literals), kNewtRefNIL);
917
918        *envP = env->parent;
919        NBCEnvFree(env);
920    }
921
922    return fn;
923}
924
925
926/*------------------------------------------------------------------------*/
927/** バイトコード生成のための初期化
928 *
929 * @return          なし
930 */
931
932void NBCInit(void)
933{
934    NBCInitFreqFuncTable();
935    newt_bc_env = NBCEnvNew(NULL);
936}
937
938
939/*------------------------------------------------------------------------*/
940/** バイトコード生成の後始末
941 *
942 * @return          なし
943 */
944
945void NBCCleanup(void)
946{
947    nbc_env_t * env;
948
949    while (newt_bc_env != NULL)
950    {
951        env = newt_bc_env;
952        newt_bc_env = env->parent;
953        NBCEnvFree(env);
954    }
955}
956
957
958#if 0
959#pragma mark -
960#endif
961/*------------------------------------------------------------------------*/
962/** 文のバイトコードを生成する
963 *
964 * @param stree     [in] 構文木
965 * @param r         [in] 構文木ノード
966 * @param ret       [in] 戻り値の有無
967 *
968 * @return          なし
969 */
970
971void NBCGenBC_stmt(nps_syntax_node_t * stree, nps_node_t r, bool ret)
972{
973    if (NPSRefIsSyntaxNode(r))
974    {
975        NBCGenBC_sub(stree, NPSRefToSyntaxNode(r), ret);
976        return;
977    }
978
979    if (r != kNewtRefUnbind)
980        NBCGenPUSH(r);
981}
982
983
984/*------------------------------------------------------------------------*/
985/** 定数のバイトコードを生成する
986 *
987 * @param stree     [in] 構文木
988 * @param r         [in] 構文木ノード
989 *
990 * @return          なし
991 */
992
993void NBCGenConstant(nps_syntax_node_t * stree, nps_node_t r)
994{
995    if (NPSRefIsSyntaxNode(r))
996    {
997        nps_syntax_node_t * node;
998
999        node = &stree[NPSRefToSyntaxNode(r)];
1000
1001        switch (node->code)
1002        {
1003            case kNPSCommaList:
1004                NBCGenConstant(stree, node->op1);
1005                NBCGenConstant(stree, node->op2);
1006                break;
1007
1008            case kNPSAsign:
1009                // node->op2 がオブジェクトでない場合の処理を行うこと
1010                NcSetSlot(CONSTANT, node->op1, node->op2);
1011                break;
1012        }
1013    }
1014    else
1015    {
1016        NBError(kNErrSyntaxError);
1017    }
1018}
1019
1020
1021/*------------------------------------------------------------------------*/
1022/** グローバル変数のバイトコードを生成する
1023 *
1024 * @param stree     [in] 構文木
1025 * @param r         [in] 構文木ノード
1026 *