Exemple #1
0
// 比較演算
static void genCmpExpr(int node, struct Expr* c) {
  int lval = syGetLVal(node);                     // 左辺
  int rval = syGetRVal(node);                     // 右辺
  boolean swap = false;

  if (evalDepth(lval) < evalDepth(rval)) {        // 右辺が左辺より
    int tmp = lval;                               //   多くスタックを使うなら
    lval = rval;                                  //     左右の辺を入れ換える
    rval = tmp;
    swap = true;
  }
    
  // 両辺を処理する
  genExpr(lval, c);                               // 左辺を評価し値をロード
  genExpr(rval, c);                               // 右辺を評価し値をロード

  int typ = syGetType(node);                      // 演算の種類により命令を出力
  if (swap) {                                     //   左右の辺が交換済みなら
    if      (typ==SyGT)  vmLt();                  //     GT( >  ) は LT( <  )
    else if (typ==SyGE)  vmLe();                  //     GE( >= ) は LE( <= )
    else if (typ==SyLT)  vmGt();                  //     LT( <  ) は GT( >  )
    else if (typ==SyLE)  vmGe();                  //     LE( <= ) は GE( >= )
    else if (typ==SyEQU) vmEq();                  //     EQ( == ) はそのまま
    else if (typ==SyNEQ) vmNe();                  //     NE( != ) はそのまま
    else error("バグ...genCmpExpr(1)");
  } else {
    if      (typ==SyGT)  vmGt();                  //     GT       ( >  )
    else if (typ==SyGE)  vmGe();                  //     GE       ( >= )
    else if (typ==SyLT)  vmLt();                  //     LT       ( <  )
    else if (typ==SyLE)  vmLe();                  //     LE       ( <= )
    else if (typ==SyEQU) vmEq();                  //     EQ       ( == )
    else if (typ==SyNEQ) vmNe();                  //     NE       ( != )
    else error("バグ...genCmpExpr(2)");
  }
}
Exemple #2
0
// 二項演算の基本形 (数値演算に使用)
static void gen2OpExpr(int node, struct Expr* c) {
  int typ  = syGetType(node);                     // 演算の種類
  int lval = syGetLVal(node);                     // 左辺
  int rval = syGetRVal(node);                     // 右辺
  boolean swap = false;

  if (isCommutativeOp(typ) &&                     // 左右を可換な演算で右辺が
      evalDepth(lval) < evalDepth(rval)) {        //   多くのスタックを使うなら
    int tmp = lval;                               // 左右の辺を入れ換える
    lval = rval;
    rval = tmp;
    swap = true;
  }

  // 両辺を処理する
  genExpr(lval, c);                               // 左辺を評価し値をロード
  genExpr(rval, c);                               // 右辺を評価し値をロード

  if (typ==SyADD)       vmAdd();                  //     ADD    (足し算)
  else if (typ==SySUB)  vmSub();                  //     SUB    (引き算)
  else if (typ==SySHL)  vmShl();                  //     SHL    (左シフト)
  else if (typ==SySHR)  vmShr();                  //     SHR    (右シフト)
  else if (typ==SyBAND) vmBAnd();                 //     BAND   (ビット毎AND)
  else if (typ==SyBXOR) vmBXor();                 //     BXOR   (ビット毎XOR)
  else if (typ==SyBOR)  vmBOr();                  //     BOR    (ビット毎OR)
  else if (typ==SyMUL)  vmMul();                  //     MUL    (掛け算)
  else if (typ==SyDIV)  vmDiv();                  //     DIV    (割り算)
  else if (typ==SyMOD)  vmMod();                  //     MOD    (余り)
  else error("バグ...gen2OpExpr");
}
Exemple #3
0
// 後置演算(配列アクセス)
static void genIdxExpr(int node, struct Expr* c, int place) {
  int lval = syGetLVal(node);                     // 左辺
  int rval = syGetRVal(node);                     // 右辺

  genExpr(lval, c);                               // 左辺を評価し値をロード
  genExpr(rval, c);                               // 右辺を評価し値をロード

  c->place=place;                                // ワード配列/バイト配列
}
Exemple #4
0
// 単項演算
static void gen1OpExpr(int node, struct Expr* c) {
  genExpr(syGetLVal(node), c);                    // 式を評価しスタックに積む

  int typ = syGetType(node);                      // 演算の種類により命令を出力
  if      (typ == SyNEG)  vmNeg();                //     NEG  (2の補数)
  else if (typ == SyNOT)  vmNot();                //     NOT  (論理の否定)
  else if (typ == SyBNOT) vmBNot();               //     BNOT (1の補数)
  else if (typ == SyCHR)  vmChr();                //     CHR  (文字型への変換)
  else if (typ == SyBOOL) vmBool();               //     BOOL (論理型への変換)
  else error("バグ...gen1OpExpr");
}
Exemple #5
0
// return 文
static void genRet(int node) {
  if (syGetLVal(node)!=SyNULL) {                  // 返す値があれば
    struct Expr *c = newExpr();                   //   Expr を割り当て
    genExpr(syGetLVal(node), c);                  //   返す式を処理し値をロード
    vmMReg();                                     //     ハードウェアレジスタに
    free(c);                                      //       移動する
  }
  int root = syGetRoot();
  if (root!=node && syGetRVal(root)!=node) {      // 関数の最後の文でないなら
    if (retLab==-1) retLab = newLab();            //   ラベルを割り当て
    vmJmp(retLab);                                //   そこにジャンプする
  }
}
Exemple #6
0
// 後置演算(構造体アクセス)
static void genDotExpr(int node, struct Expr* c) {
  int lval = syGetLVal(node);                     // 構造体アドレス
  int rval = syGetRVal(node);                     //   定数ノードに名前表の
  int idx  = syGetLVal(rval);                     //     インデクスが入っている

  genExpr(lval, c);                               // 左辺を評価し値をロード

  // 2項演算に分類しているので式の体裁を整える
  c->place = CNST;                                // 定数値として
  c->value = ntGetCnt(idx);                       //   フィールドオフセットを
  load(c);                                        //     ロードする
  c->place = STKW;                                // ワード配列と同様な扱い
}
Exemple #7
0
// 論理演算子(&& と ||)の処理
static int genLogExpr(int node, struct Expr *c, int left,
		      struct Label *lab1, struct Label *lab2) {
  int curOp = syGetType(node);                    // 現在の演算子

  // 左辺を処理する
  int lNode = syGetLVal(node);                    // 左に進む場合のノード
  int lOp = syGetType(lNode);                     // 左の演算子
  if (lOp==SyOR || lOp==SyAND) {                  // 左に論理式が続く場合
    struct Label *labN = newLabel(left+1);        //   新しいラベルを準備
    if (lOp == curOp)                             //   同じ演算子なら
      genLogExpr(lNode, c, left+1, lab1, labN);   //     このように ^^;;;
    else                                          //   そうでなければ
      genLogExpr(lNode, c, left+1, labN, lab1);   //     このように ^^;;;
    printLab(labN->no);                           //   no が -1 以外なら印刷
    free(labN);
  } else {                                        // 左辺が論理式以外の場合
    genExpr(lNode, c);                            //   論理値を求め
    boolJmp(curOp==SyOR, c, lab1);                //   条件ジャンプ命令を生成
  }

  // 右辺を処理する
  int rNode = syGetRVal(node);                    // 右に進む場合のノード
  int rrNode = rNode;                             // 最後(最も右)の項
  int rOp = syGetType(rNode);                     // 右の演算子
  if (rOp==SyOR || rOp==SyAND) {                  // 右に論理式が続く場合
    if (rOp == curOp)                             //   同じ演算子なら
      rrNode=genLogExpr(rNode,c,left,lab1,lab2);  //     このように ^^;;;
    else                                          //   そうでなければ
      rrNode=genLogExpr(rNode,c,left,lab2,lab1);  //     このように ^^;;;
  } else if (left>=2) {                           // 式の最後の項以外なら
    genExpr(rNode, c);                            //   論理値を求め
    if (lab1->left == left)                       //   lab1 の直前の項なら
      boolJmp(curOp!=SyOR, c, lab2);              //   逆の条件で lab2 へ飛ぶ
    else
      boolJmp(curOp==SyOR, c, lab1);              //   条件ジャンプ命令を生成
  } // else { }              // 式の最後の項は特別なので呼び出し側で処理する
  return rrNode;
}
Exemple #8
0
// genLogExpr を使用して論理値を求める
static void genLOpExpr(int node, struct Expr* c) {
  int op   = syGetType(node);                     // 論理和か論理積か
  int lab0 = newLab();                            // 論理式の最後
  struct Label *lab1 = newLabel(0);               // 途中で結果が出たとき
  struct Label *lab2 = newLabel(1);               // 途中で結果が出たとき

  int rNode = genLogExpr(node, c, 1, lab2, lab1); // コード生成
  genExpr(rNode, c);                              // 最後の項の論理値を求める

  if (op==SyOR)                                   // || なら
    vmBoolOR(lab2->no, lab1->no, lab0);           //   BOOLOR マクロ命令を生成
  else                                            // && なら
    vmBoolAND(lab2->no, lab1->no, lab0);          //   BOOLAND マクロ命令を生成

  free(lab1);
  free(lab2);
}
Exemple #9
0
/// 関数の実引数をスタックに積む
static int genArgs(int node, struct Expr* c) {
  int n = 0;                                      // 引数の個数を数えるカウンタ
  while (node!=SyNULL) {                          // 引数がある間
    int typ  = syGetType(node);
    int exp;
    if (typ == SySEMI) {                          // リストなら
      exp  = syGetRVal(node);                     //   右側に式
      node = syGetLVal(node);                     //   次は左に進む
    } else {                                      // リスト以外(式)なら
      exp  = node;                                //   自身が式
      node = SyNULL;                              //   次は無い
    }
    genExpr(exp, c);                              // 引数を評価しスタックに積む
    vmArg();                                      // 引数値を引数領域に移動
    n = n + 1;                                    // 引数の個数をカウント
  }
  return n;                                       // 引数の個数を返す
}
Exemple #10
0
/* Generate code for expressions appearing as actual parameters.
 * Recursive method pushes actuals in reverse order.
 */
void genActuals(node *actualList, decldesc *formal)
{
    // use recursive strategy:
    // if the lists are NULL, we're done
    // otherwise, call genActuals recursively with the rests of
    // both lists (which will generate code to push the parameters
    // in reverse order)
    // then, generate code to compute the current actual
    // - it it's an array parameter, need to adjust the displacement again
    //   since the called function thinks the lowbound is 0
    // - if it's a refparam (which includes arrays), call computeAddress
    // finally, push the actual on the stack
    
    if (!actualList) return;
    node *actual = actualList->internal.child[0];
    node *nextActualList = actualList->internal.child[1];
    decldesc *formalList = formal->formal.formallink;
    int line = actual->unk.line;
    int typesize;
    typedesc* type0;

    if (actualList->internal.child[1] != NULL ) {
        genActuals(nextActualList, formalList);
    }

    opdesc *op0 = genExpr(actual);

    //if it's an array
    if (actual->unk.type == Nident && actual->ident.decl->var.vartype->isArray == TRUE) {
        
        type0 = actual->ident.decl->var.vartype;  
        typesize = type0->typespec == integer ? INTSIZE : BOOLSIZE;
        // adjust the base address if lowbound != 0
        op0->disp -= typesize * type0->lowbound;
    } 
    if(formal->formal.valparam == FALSE)
        //if it's a ref param
        op0 = computeAddress(op0, line);
    //push onto the stack
    outputCmd("pushl", line);
    outputOp(op0);
    freeOp(op0);
}
Exemple #11
0
/* generate code for a return statement */
void genReturn(node *stmt, codelabel *next)
{

    if(stmt->internal.child[0]) {
        opdesc *op = genExpr(stmt->internal.child[0]);
        op = forceToSpecificReg(op, eax, stmt->unk.line);
        freeOp(op);
    }

    if (next != &funend) {
        outputCmd("jmp", stmt->internal.line);
        outputLabel(&funend);
    } else {
        outputCmd(NULL, stmt->internal.line); /* do nothing -- fall through */
    }

    // Note that you don't need to output a "jmp"
    // statement if next is the same as &funend
}
Exemple #12
0
/* generate code for an assignment statement */
void genAssign(node *stmt)
{
    node *var = stmt->internal.child[0];
    node *expr = stmt->internal.child[1];

    assert (stmt->unk.type == Nassign || stmt->unk.type == Ndecl);

    if (expr == NULL)
        return; /* declaration without assignment */
    
    opdesc *value = genExpr(expr);
    opdesc *target = genVar(var);
    if (isMemloc(value))
        value = forceToReg(value, stmt->internal.line);
    outputCmd("movl", stmt->internal.line);
    outputOp(value);
    outputOp(target);
    freeOp(value);
    freeOp(target);
}
Exemple #13
0
// 条件式の生成(条件式(node)を評価し true/false なら lab へジャンプする)
static void genCnd(int node, boolean tf, struct Label *jmpLab) {
  struct Expr *c = newExpr();                     // Expr を割り当てる
  struct Label *nxtLab = newLabel(2);             //  式の直後用ラベル
  int op = syGetType(node);
  if (op==SyOR) {                                 // 条件式は論理和
    if (tf) {                                     // true で jmpLab へジャンプ
      genLogExpr(node, c, 2, jmpLab, nxtLab);     //  || 式が false 時に直後へ
    } else {                                      // false で jmpLab へジャンプ
      genLogExpr(node, c, 2, nxtLab, jmpLab);     //  || 式が true 時に直後へ
    }
  } else if (op==SyAND) {                         // 条件式は論理積
    if (tf) {                                     // true で jmpLab へジャンプ
      genLogExpr(node, c, 2, nxtLab, jmpLab);     //  && 式が true 時に直後へ
    } else {                                      // true で jmpLabへジャンプ
      genLogExpr(node, c, 2, jmpLab, nxtLab);     //  && 式が false 時に直後へ
    }
  } else {
    genExpr(node, c);                             // 条件式を評価する
    boolJmp(tf, c, jmpLab);                       // 条件ジャンプ命令を生成
  }
  printLab(nxtLab->no);                           // 使用されていればラベル生成
  free(nxtLab);                                   // Label を解放
  free(c);                                        // Expr を解放
}
Exemple #14
0
/*
 * PreProcess - pre-process source file
 */
vi_rc PreProcess( const char *fn, sfile **sf, labels *lab )
{
    GENERIC_FILE        gf;
    int                 i, token, k, len;
    sfile               *tsf;
    char                tmp[MAX_SRC_LINE], tmp2[MAX_SRC_LINE];
    char                tmp3[MAX_SRC_LINE];
    bool                ret;
#ifdef VICOMP
    bool                AppendingFlag = FALSE;
#else
    #define             AppendingFlag   EditFlags.Appending
#endif

    /*
     * get source file
     */
#ifdef VICOMP
    ret = SpecialOpen( fn, &gf );
#else
    if( EditFlags.CompileScript ) {
        EditFlags.OpeningFileToCompile = TRUE;
        ret = SpecialOpen( fn, &gf, FALSE );
        EditFlags.OpeningFileToCompile = FALSE;
    } else {
        ret = SpecialOpen( fn, &gf, EditFlags.BoundData );
    }
#endif
    if( !ret ) {
        return( ERR_FILE_NOT_FOUND );
    }

    /*
     * init control
     */
    CSInit();
    CurrentSrcLine = 0L;

    tsf = MemAlloc( sizeof( sfile ) );
    tsf->next = NULL;
    tsf->prev = NULL;
    tsf->arg1 = NULL;
    tsf->arg2 = NULL;
    tsf->data = NULL;
    tsf->token = SRC_T_NULL;
    *sf = tmpTail = tsf;
    cLab = lab;

    /*
     * set up error handler
     */
    i = setjmp( genExit );
    if( i != 0 ) {
        SpecialFclose( &gf );
        return( (vi_rc)i );
    }

    /*
     * process each line
     */
    while( SpecialFgets( tmp, MAX_SRC_LINE - 1, &gf ) >= 0 ) {

        /*
         * prepare this line
         */
        CurrentSrcLine++;
#ifndef VICOMP
        if( !EditFlags.ScriptIsCompiled ) {
#endif
            RemoveLeadingSpaces( tmp );
            k = strlen( tmp );
            memcpy( tmp3, tmp, k + 1 );
            if( (len = NextWord1( tmp, tmp2 )) <= 0 ) {
                continue;
            }
            if( tmp2[0] == '#' ) {
                continue;
            }
            hasVar = FALSE;
            for( i = 0; i < k; i++ ){
                if( tmp3[i] == '%' ) {
                    hasVar = TRUE;
                    break;
                }
            }

            /*
             * if we are appending (ie, an append token was encounterd
             * before, stop tokenizing
             */
            if( !AppendingFlag ) {
                token = Tokenize( SourceTokens, tmp2, TRUE );
#ifndef VICOMP
                if( token == SRC_T_VBJ__ ) {
                    EditFlags.ScriptIsCompiled = TRUE;
                    continue;
                }
#endif
            } else {
                token = TOK_INVALID;
            }
#ifndef VICOMP
        } else {
            len = NextWord1( tmp, tmp2 );
            hasVar = (bool) tmp2[0] - '0';
            token = atoi( &tmp2[1] );
        }
#endif
        /*
         * process recognized tokens
         */
        if( token != TOK_INVALID ) {

            RemoveLeadingSpaces( tmp );
            if( token > SRC_T_NULL ) {
                genItem( token, tmp );
                continue;
            }

            /*
             * get parm
             */
            AddString( &CurrentSrcData, tmp );
            freeSrcData = TRUE;

            /*
             * process token
             */
            switch( token ) {
            case SRC_T_EXPR:
                genExpr();
                break;
            case SRC_T_LABEL:
                GenLabel( tmp );
                break;
            case SRC_T_IF:
                CSIf();
                break;
            case SRC_T_QUIF:
                CSQuif();
                break;
            case SRC_T_ELSEIF:
                CSElseIf();
                break;
            case SRC_T_ELSE:
                CSElse();
                break;
            case SRC_T_ENDIF:
                CSEndif();
                break;
            case SRC_T_LOOP:
                CSLoop();
                break;
            case SRC_T_ENDLOOP:
            case SRC_T_ENDWHILE:
                CSEndLoop();
                break;
            case SRC_T_WHILE:
                CSWhile();
                break;
            case SRC_T_UNTIL:
                CSUntil();
                break;
            case SRC_T_BREAK:
                CSBreak();
                break;
            case SRC_T_CONTINUE:
                CSContinue();
                break;
            default:
                genItem( token, NULL );
                if( token == SRC_T_GOTO ) {
#ifndef VICOMP
                    if( EditFlags.ScriptIsCompiled ) {
                        NextWord1( CurrentSrcData, tmp );
                        tmpTail->branchcond = atoi( CurrentSrcData );
                        strcpy( CurrentSrcData, tmp );
                    } else {
#endif
                        tmpTail->branchcond = COND_JMP;
#ifndef VICOMP
                    }
#endif
                }
                tmpTail->data = CurrentSrcData;
                freeSrcData = FALSE;
                break;
            }
            if( freeSrcData ) {
                MemFree( CurrentSrcData );
            }
        /*
         * set all other tokens to be processed at run time
         */
        } else {
#ifndef VICOMP
            if( EditFlags.ScriptIsCompiled ) {
                RemoveLeadingSpaces( tmp );
                genItem( token, tmp );
                continue;
            }
#endif
            if( !AppendingFlag ) {
                token = Tokenize( TokensCmdLine, tmp2, TRUE );
            } else {
                token = TOK_INVALID;
            }
            switch( token ) {
            case PCL_T_COMMANDWINDOW:
            case PCL_T_STATUSWINDOW:
            case PCL_T_COUNTWINDOW:
            case PCL_T_EDITWINDOW:
            case PCL_T_EXTRAINFOWINDOW:
            case PCL_T_FILECWINDOW:
            case PCL_T_LINENUMBERWINDOW:
            case PCL_T_DIRWINDOW:
            case PCL_T_FILEWINDOW:
            case PCL_T_SETWINDOW:
            case PCL_T_SETVALWINDOW:
            case PCL_T_MESSAGEWINDOW:
            case PCL_T_MENUWINDOW:
            case PCL_T_MENUBARWINDOW:
            case PCL_T_ENDWINDOW:
            case PCL_T_SETCOLOR:
            case PCL_T_MATCH:
            case PCL_T_DIMENSION:
            case PCL_T_BORDER:
            case PCL_T_HILIGHT:
            case PCL_T_TEXT:
            case PCL_T_ALIAS:
            case PCL_T_ABBREV:
            case PCL_T_MENU:
            case PCL_T_MENUITEM:
            case PCL_T_ENDMENU:
            case PCL_T_WHITESPACE:
            case PCL_T_SELECTION:
            case PCL_T_EOFTEXT:
            case PCL_T_KEYWORD:
            case PCL_T_OCTAL:
            case PCL_T_HEX:
            case PCL_T_INTEGER:
            case PCL_T_CHAR:
            case PCL_T_PREPROCESSOR:
            case PCL_T_SYMBOL:
            case PCL_T_INVALIDTEXT:
            case PCL_T_IDENTIFIER:
            case PCL_T_JUMPLABEL:
            case PCL_T_COMMENT:
            case PCL_T_FLOAT:
            case PCL_T_STRING:
            case PCL_T_VARIABLE:
            case PCL_T_FILETYPESOURCE:
            case PCL_T_ENDFILETYPESOURCE:
            case PCL_T_LOCATE:
            case PCL_T_MAP:
            case PCL_T_MAP_DMT:

            case PCL_T_MENUFILELIST:
            case PCL_T_MENULASTFILES:

            case PCL_T_DEFAULTWINDOW:
            case PCL_T_ACTIVEMENUWINDOW:
            case PCL_T_GREYEDMENUWINDOW:
            case PCL_T_ACTIVEGREYEDMENUWINDOW:
                RemoveLeadingSpaces( tmp );
                token += SRC_T_NULL + 1;
                genItem( token, tmp );
                break;

            case PCL_T_SET:
                token += SRC_T_NULL + 1;
#ifdef VICOMP
                WorkLine->data[0] = 0;
                Set( tmp );
                genItem( token, WorkLine->data );
#else
                if( EditFlags.CompileScript ) {
                    vi_rc   rc;

                    WorkLine->data[0] = 0;
                    rc = Set( tmp );
                    if( rc != ERR_NO_ERR ) {
                        Error( GetErrorMsg( rc ) );
                    }
                    genItem( token, WorkLine->data );
                } else {
                    genItem( token, tmp );
                }
#endif
                break;

            default:
                if( AppendingFlag ) {
                    if( tmp3[0] == '.' && tmp3[1] == 0 ) {
                        AppendingFlag = FALSE;
                    }
                } else if( token == TOK_INVALID ) {
                    /*
                     * see if the current token is a Ex token.  If
                     * it isn't, then see if the next one is
                     * (i.e., look for <n> append)
                     */
                    token = Tokenize( TokensEx, tmp2, FALSE );
                    if( token == TOK_INVALID ) {
                        if( NextWord1( tmp, tmp2 ) >= 0 ) {
                            token = Tokenize( TokensEx, tmp2, FALSE );
                            if( token == EX_T_APPEND ) {
                                AppendingFlag = TRUE;
                            }
                        }
                    }
                }
                if( tmp3[0] == '>' ) {
                    tmp3[0] = ' ';
                }
                genItem( TOK_INVALID, tmp3 );
                break;
            }
        }

    }

    SpecialFclose( &gf );
    AppendingFlag = FALSE;
    return( CSFini() );

} /* PreProcess */
Exemple #15
0
// 代入式
static void genAsExpr(int node, struct Expr* c) {
  genExpr(syGetRVal(node), c);                    // 右辺を評価しスタックに積む
  genBoolExpr(syGetLVal(node), c);                // 左辺(代入先)を評価する
  store(c);                                       //     ST  左辺
  c->place = STKD;                                // まだ値はスタックに残る
}