source: dev/trunk/ab5.0/abdev/BasicCompiler32/Compile_Statement.cpp @ 465

Last change on this file since 465 was 465, checked in by dai_9181, 16 years ago

Messenger/ErrorMessengerクラスを導入。SetError関数によるエラー生成を廃止した。

File size: 33.3 KB
Line 
1#include "stdafx.h"
2
3#include <LexicalScope.h>
4#include <Compiler.h>
5
6#include "../BasicCompiler_Common/common.h"
7#include "Opcode.h"
8
9void OpcodeOthers( const char *Command ){
10    int i,i2;
11
12    char leftTerm[8192];
13    int lastParePos = 0;
14    for(i=0;;i++){
15        if(Command[i]=='\"'){
16            //ダブルクォートは不正なのでエラー扱い
17            leftTerm[i]=0;
18            compiler.errorMessenger.Output(3,leftTerm,cp);
19            return;
20        }
21
22        if(Command[i]=='('){
23            lastParePos = i;
24            i2=GetStringInPare(leftTerm+i,Command+i);
25            i+=i2-1;
26            continue;
27        }
28        if(Command[i]=='['){
29            i2=GetStringInBracket(leftTerm+i,Command+i);
30            i+=i2-1;
31            continue;
32        }
33        if(Command[i]=='\0'){
34            leftTerm[i] = 0;
35            break;
36        }
37
38        if( IsNumCalcMark( Command, i ) ){
39            leftTerm[i] = 0;
40            break;
41        }
42
43        leftTerm[i]=Command[i];
44    }
45    if(!(
46        IsVariableTopChar(leftTerm[0])||
47        leftTerm[0]=='.'||
48        (leftTerm[0]==1&&leftTerm[1]==ESC_PSMEM)
49        )){
50        compiler.errorMessenger.Output(1,NULL,cp);
51        return;
52    }
53
54
55    if(Command[i]=='\0' && lastParePos == 0){
56        //////////////////////////////
57        // パラメータ無しのマクロ検索
58        //////////////////////////////
59
60        const UserProc *pUserProc = GetSubHash(Command);
61
62        //GetSubHash内でエラー提示が行われた場合
63        if(pUserProc==(UserProc *)-1) return;
64
65        if(pUserProc==0){
66            char temporary[VN_SIZE];
67            lstrcpy(temporary,Command);
68
69            CharUpper(temporary);
70            pUserProc=GetSubHash(temporary);
71
72            //GetSubHash内でエラー提示が行われた場合
73            if(pUserProc==(UserProc *)-1) return;
74        }
75
76        if(pUserProc){
77            if( !pUserProc->IsMacro() ){
78                compiler.errorMessenger.Output(10,Command,cp);
79            }
80
81            Opcode_CallProc("",pUserProc,0,"");
82
83            return;
84        }
85    }
86    else if(IsNumCalcMark(Command,i)){
87        //代入演算
88        OpcodeCalc(Command);
89        return;
90    }
91
92    Type resultType;
93    bool isLiteral, isNeedHeapFreeStructure = false;
94    bool result = TermOpe( leftTerm, Type(), resultType, isLiteral, isNeedHeapFreeStructure, NULL, true );
95    if( result ){
96
97        /////////////////////
98        // 戻り値の処理
99        /////////////////////
100
101        if( resultType.IsReal() ){
102            //fstp st(0)
103            compiler.codeGenerator.PutOld(
104                (char)0xDD,
105                (char)0xD8
106            );
107        }
108        else if( resultType.IsStruct() ){
109            //mov ebx,eax
110            compiler.codeGenerator.op_mov_RR(REG_EBX,REG_EAX);
111
112            FreeTempObject(REG_EBX,&resultType.GetClass());
113        }
114
115        return;
116    }
117
118    // どこにも当てはまらなかったため、失敗
119    compiler.errorMessenger.Output(1,NULL,cp);
120}
121
122void OpcodeIf(char *Parameter){
123    int i,i2;
124    Type tempType;
125
126    for(i=0;;i++){
127        if(Parameter[i]=='\0'){
128            compiler.errorMessenger.Output(21,NULL,cp);
129            return;
130        }
131        if(Parameter[i]==1&&Parameter[i+1]==ESC_THEN){
132            Parameter[i]=0;
133            break;
134        }
135    }
136
137    const PertialSchedule *pIfPertialSchedule = NULL;
138    if( !NumOpe(Parameter,Type(DEF_BOOLEAN),tempType) ){
139        //NumOpe内でエラー
140    }
141    else if( tempType.IsDouble() ){
142        //fld qword ptr[esp]
143        compiler.codeGenerator.op_fld_ptr_esp(DEF_DOUBLE);
144
145        //push 0
146        compiler.codeGenerator.op_push_V(0);
147
148        //fild dword ptr[esp]
149        compiler.codeGenerator.op_fld_ptr_esp(DEF_LONG);
150
151        //add esp,sizeof(double)+sizeof(long)
152        compiler.codeGenerator.op_add_esp(sizeof(double)+sizeof(long));
153
154        //fcompp
155        compiler.codeGenerator.op_fcompp();
156
157        //fnstsw ax
158        compiler.codeGenerator.op_fnstsw_ax();
159
160        //test ah,40
161        compiler.codeGenerator.op_test_ah( (char)0x40 );
162
163        //jne (endif、または else まで)
164        pIfPertialSchedule = compiler.codeGenerator.op_jne( 0, sizeof(long), true );
165    }
166    else if( tempType.IsSingle() ){
167        //fld dword ptr[esp]
168        compiler.codeGenerator.op_fld_ptr_esp(DEF_SINGLE);
169
170        //push 0
171        compiler.codeGenerator.op_push_V(0);
172
173        //fild dword ptr[esp]
174        compiler.codeGenerator.op_fld_ptr_esp(DEF_LONG);
175
176        //add esp,sizeof(float)+sizeof(long)
177        compiler.codeGenerator.op_add_esp(sizeof(float)+sizeof(long));
178
179        //fcompp
180        compiler.codeGenerator.op_fcompp();
181
182        //fnstsw ax
183        compiler.codeGenerator.op_fnstsw_ax();
184
185        //test ah,40
186        compiler.codeGenerator.op_test_ah( (char)0x40 );
187
188        //jne (endif、または else まで)
189        pIfPertialSchedule = compiler.codeGenerator.op_jne( 0, sizeof(long), true );
190    }
191    else if( tempType.Is64() ){
192        //64ビット型
193
194        //pop eax
195        compiler.codeGenerator.op_pop(REG_EAX);
196
197        //pop ebx
198        compiler.codeGenerator.op_pop(REG_EBX);
199
200        //cmp eax,0
201        compiler.codeGenerator.op_cmp_value( sizeof(long), REG_EAX, 0 );
202
203        //jne
204        const PertialSchedule *pTempPertialSchedule1 = compiler.codeGenerator.op_jne( 0, sizeof(char), true );
205
206        //cmp ebx,0
207        compiler.codeGenerator.op_cmp_value( sizeof(long), REG_EBX, 0 );
208
209        //jne
210        const PertialSchedule *pTempPertialSchedule2 = compiler.codeGenerator.op_jne( 0, sizeof(char), true );
211
212        //jmp (endif、または else までジャンプ)
213        pIfPertialSchedule = compiler.codeGenerator.op_jmp( 0, sizeof(long), true );
214
215        compiler.codeGenerator.opfix_JmpPertialSchedule( pTempPertialSchedule1 );
216        compiler.codeGenerator.opfix_JmpPertialSchedule( pTempPertialSchedule2 );
217    }
218    else{
219        //32ビット型
220
221        //pop eax
222        compiler.codeGenerator.op_pop(REG_EAX);
223
224        //cmp eax,0
225        compiler.codeGenerator.op_cmp_value( sizeof(long), REG_EAX, 0 );
226
227        //je (endif、または else まで条件ジャンプ)
228        pIfPertialSchedule = compiler.codeGenerator.op_je( 0, sizeof(long), true );
229    }
230
231
232    /////////////////////////
233    // If内をコード化
234    /////////////////////////
235
236    //レキシカルスコープをレベルアップ
237    compiler.codeGenerator.lexicalScopes.Start(
238        compiler.codeGenerator.GetNativeCodeSize(),
239        LexicalScope::SCOPE_TYPE_IF
240    );
241
242    i2=CompileBuffer(ESC_ENDIF,0);
243
244    //レキシカルスコープをレベルダウン
245    compiler.codeGenerator.lexicalScopes.End();
246
247
248    if( pIfPertialSchedule == NULL ) return;
249
250    if(i2==ESC_ELSE){
251        //jmp (endifまで)
252        const PertialSchedule *pTempPertialSchedule = compiler.codeGenerator.op_jmp( 0, sizeof(long), true );
253
254        compiler.codeGenerator.opfix_JmpPertialSchedule( pIfPertialSchedule );
255
256
257        /////////////////////////
258        // Else内をコード化
259        /////////////////////////
260
261        //レキシカルスコープをレベルアップ
262        compiler.codeGenerator.lexicalScopes.Start(
263            compiler.codeGenerator.GetNativeCodeSize(),
264            LexicalScope::SCOPE_TYPE_IF
265        );
266
267        CompileBuffer(ESC_ENDIF,0);
268
269        //レキシカルスコープをレベルダウン
270        compiler.codeGenerator.lexicalScopes.End();
271
272
273        compiler.codeGenerator.opfix_JmpPertialSchedule( pTempPertialSchedule );
274    }
275    else{
276        compiler.codeGenerator.opfix_JmpPertialSchedule( pIfPertialSchedule );
277    }
278}
279
280int GetLabelAddress(char *LabelName,int LineNum){
281    if(LabelName){
282        BOOST_FOREACH( const GotoLabel &label, compiler.codeGenerator.gotoLabels )
283        {
284            if( label.name.size() > 0 )
285            {
286                if( label.name == LabelName )
287                {
288                    return label.address;
289                }
290            }
291        }
292    }
293    else{
294        BOOST_FOREACH( const GotoLabel &label, compiler.codeGenerator.gotoLabels )
295        {
296            if( label.name.size() == 0 )
297            {
298                if( label.line == LineNum )
299                {
300                    return label.address;
301                }
302            }
303        }
304    }
305    return -1;
306}
307void OpcodeGoto(char *Parameter){
308    extern HANDLE hHeap;
309    int i,LineNum;
310
311    if(Parameter[0]=='*'){
312        i=GetLabelAddress(Parameter+1,0);
313
314        if( i == -1 )
315        {
316            //jmp ...(schedule)
317            compiler.codeGenerator.op_jmp_goto_schedule( (const std::string)(Parameter + 1), 0, cp );
318        }
319        else
320        {
321            //jmp ...
322            compiler.codeGenerator.op_jmp(
323                i-compiler.codeGenerator.GetNativeCodeSize(),
324                sizeof(long),
325                false,
326                true
327            );
328        }
329    }
330    else{
331        LineNum=atoi(Parameter);
332        i=GetLabelAddress(0,LineNum);
333
334        if( i == -1 )
335        {
336            //jmp ...(schedule)
337            compiler.codeGenerator.op_jmp_goto_schedule( "", LineNum, cp );
338        }
339        else
340        {
341            //jmp ...
342            compiler.codeGenerator.op_jmp(
343                i-compiler.codeGenerator.GetNativeCodeSize(),
344                sizeof(long),
345                false,
346                true
347            );
348        }
349    }
350}
351void OpcodeWhile(char *Parameter){
352    extern HANDLE hHeap;
353
354    //Continueアドレスのバックアップとセット
355    compiler.codeGenerator.ContinueAreaBegin();
356
357    if(!Parameter[0]) compiler.errorMessenger.Output(10,"While",cp);
358
359    const PertialSchedule *pWhilePertialSchedule = NULL;
360    Type tempType;
361    if( !NumOpe(Parameter,Type(),tempType) ){
362        //ダミー
363    }
364    else if( tempType.IsDouble() ){
365        //fld qword ptr[esp]
366        compiler.codeGenerator.op_fld_ptr_esp(DEF_DOUBLE);
367
368        //push 0
369        compiler.codeGenerator.op_push_V(0);
370
371        //fild dword ptr[esp]
372        compiler.codeGenerator.op_fld_ptr_esp(DEF_LONG);
373
374        //add esp,sizeof(double)+sizeof(long)
375        compiler.codeGenerator.op_add_esp(sizeof(double)+sizeof(long));
376
377        //fcompp
378        compiler.codeGenerator.op_fcompp();
379
380        //fnstsw ax
381        compiler.codeGenerator.op_fnstsw_ax();
382
383        //test ah,40
384        compiler.codeGenerator.op_test_ah( (char)0x40 );
385
386        //jne (Wend まで)
387        pWhilePertialSchedule = compiler.codeGenerator.op_jne( 0, sizeof(long), true );
388    }
389    else if( tempType.IsSingle() ){
390        //fld dword ptr[esp]
391        compiler.codeGenerator.op_fld_ptr_esp(DEF_SINGLE);
392
393        //push 0
394        compiler.codeGenerator.op_push_V(0);
395
396        //fild dword ptr[esp]
397        compiler.codeGenerator.op_fld_ptr_esp(DEF_LONG);
398
399        //add esp,sizeof(float)+sizeof(long)
400        compiler.codeGenerator.op_add_esp(sizeof(float)+sizeof(long));
401
402        //fcompp
403        compiler.codeGenerator.op_fcompp();
404
405        //fnstsw ax
406        compiler.codeGenerator.op_fnstsw_ax();
407
408        //test ah,40h
409        compiler.codeGenerator.op_test_ah( (char)0x40 );
410
411        //jne (Wend まで)
412        pWhilePertialSchedule = compiler.codeGenerator.op_jne( 0, sizeof(long), true );
413    }
414    else if( tempType.Is64() ){
415        //64ビット型
416
417        //pop eax
418        compiler.codeGenerator.op_pop(REG_EAX);
419
420        //pop ebx
421        compiler.codeGenerator.op_pop(REG_EBX);
422
423        //cmp eax,0
424        compiler.codeGenerator.op_cmp_value( sizeof(long), REG_EAX, 0 );
425
426        //jne
427        const PertialSchedule *pTempPertialSchedule1 = compiler.codeGenerator.op_jne( 0, sizeof(char), true );
428
429        //cmp ebx,0
430        compiler.codeGenerator.op_cmp_value( sizeof(long), REG_EBX, 0 );
431
432        //jne
433        const PertialSchedule *pTempPertialSchedule2 = compiler.codeGenerator.op_jne( 0, sizeof(char), true );
434
435        //jmp (Wendまでジャンプ)
436        pWhilePertialSchedule = compiler.codeGenerator.op_jmp( 0, sizeof(long), true );
437
438        compiler.codeGenerator.opfix_JmpPertialSchedule( pTempPertialSchedule1 );
439        compiler.codeGenerator.opfix_JmpPertialSchedule( pTempPertialSchedule2 );
440    }
441    else{
442        //その他整数型
443
444        //pop eax
445        compiler.codeGenerator.op_pop(REG_EAX);
446
447        //cmp eax,0
448        compiler.codeGenerator.op_cmp_value( sizeof(long), REG_EAX, 0 );
449
450        //je (Wend まで)
451        pWhilePertialSchedule = compiler.codeGenerator.op_je( 0, sizeof(long), true );
452    }
453
454    //レキシカルスコープをレベルアップ
455    compiler.codeGenerator.lexicalScopes.Start( compiler.codeGenerator.GetNativeCodeSize(), LexicalScope::SCOPE_TYPE_WHILE );
456
457    //While内をコンパイル
458    CompileBuffer(0,COM_WEND);
459
460    compiler.codeGenerator.lexicalScopes.CallDestructorsOfScopeEnd();
461
462    //jmp ...
463    compiler.codeGenerator.op_jmp_continue();
464
465    //レキシカルスコープをレベルダウン
466    compiler.codeGenerator.lexicalScopes.End();
467
468    if( pWhilePertialSchedule )
469    {
470        compiler.codeGenerator.opfix_JmpPertialSchedule( pWhilePertialSchedule );
471    }
472
473    compiler.codeGenerator.ContinueAreaEnd();
474}
475
476char szNextVariable[VN_SIZE];
477void OpcodeFor(char *Parameter){
478    extern HANDLE hHeap;
479    int i,i2;
480    char temporary[VN_SIZE],variable[VN_SIZE],JudgeNum[VN_SIZE],StepNum[VN_SIZE];
481
482    //第1パラメータを取得
483    i=GetOneParameter(Parameter,0,temporary);
484    if(!Parameter[i]){
485        compiler.errorMessenger.Output(12,"For",cp);
486        goto ErrorStep;
487    }
488
489    for(i2=0;;i2++){
490        if(temporary[i2]=='='){
491            variable[i2]=0;
492
493            //カウンタ初期化
494            OpcodeCalc(temporary);
495            break;
496        }
497        if(temporary[i2]=='\0'){
498            compiler.errorMessenger.Output(12,"For",cp);
499            goto ErrorStep;
500        }
501        variable[i2]=temporary[i2];
502    }
503
504    //jmp ...
505    const PertialSchedule *pTempPertialSchedule = compiler.codeGenerator.op_jmp( 0, sizeof(long), true );
506
507    //Continueアドレスのバックアップとセット
508    compiler.codeGenerator.ContinueAreaBegin();
509
510    //第2パラメータを取得(to~)
511    i=GetOneParameter(Parameter,i,JudgeNum);
512
513    //第3パラメータを取得(step~)
514    if(Parameter[i]){
515        i=GetOneParameter(Parameter,i,StepNum);
516        if(Parameter[i]) compiler.errorMessenger.Output(12,"For",cp);
517    }
518    else lstrcpy(StepNum,"1");
519
520    //カウンタを増加させる
521    sprintf(temporary,"%s=(%s)+(%s)",variable,variable,StepNum);
522    OpcodeCalc(temporary);
523
524    compiler.codeGenerator.opfix_JmpPertialSchedule( pTempPertialSchedule );
525
526    //増加か減少かを区別する
527    sprintf(temporary,"(%s)>=0",StepNum);
528    NumOpe(temporary,Type(),Type());
529
530    //pop eax
531    compiler.codeGenerator.op_pop(REG_EAX);
532
533    //cmp eax,0
534    compiler.codeGenerator.op_cmp_value( sizeof(long), REG_EAX, 0 );
535
536    //je [カウンタ減少の場合の判定]
537    pTempPertialSchedule = compiler.codeGenerator.op_je( 0, sizeof(long), true );
538
539    //判定(カウンタ増加の場合)
540    sprintf(temporary,"%s<=(%s)",variable,JudgeNum);
541    NumOpe(temporary,Type(),Type());
542
543    //pop eax
544    compiler.codeGenerator.op_pop(REG_EAX);
545
546    //jmp [カウンタ減少の場合の判定を飛び越す]
547    const PertialSchedule *pTempPertialSchedule2 = compiler.codeGenerator.op_jmp( 0, sizeof(long), true );
548
549    //jeジャンプ先のオフセット値
550    compiler.codeGenerator.opfix_JmpPertialSchedule( pTempPertialSchedule );
551
552    //判定(カウンタ減少の場合)
553    sprintf(temporary,"%s>=(%s)",variable,JudgeNum);
554    NumOpe(temporary,Type(),Type());
555
556    //pop eax
557    compiler.codeGenerator.op_pop(REG_EAX);
558
559    //jmpジャンプ先のオフセット値
560    compiler.codeGenerator.opfix_JmpPertialSchedule( pTempPertialSchedule2 );
561
562    //cmp eax,0
563    compiler.codeGenerator.op_cmp_value( sizeof(long), REG_EAX, 0 );
564
565ErrorStep:
566
567    //je ...
568    pTempPertialSchedule = compiler.codeGenerator.op_je( 0, sizeof(long), true );
569
570    //レキシカルスコープをレベルアップ
571    compiler.codeGenerator.lexicalScopes.Start( compiler.codeGenerator.GetNativeCodeSize(), LexicalScope::SCOPE_TYPE_FOR );
572
573    //For内をコンパイル
574    CompileBuffer(0,COM_NEXT);
575
576    compiler.codeGenerator.lexicalScopes.CallDestructorsOfScopeEnd();
577
578    if(szNextVariable[0]){
579        if(lstrcmp(szNextVariable,variable)!=0){
580            compiler.errorMessenger.Output(55,szNextVariable,cp);
581        }
582    }
583
584    //jmp ...
585    compiler.codeGenerator.op_jmp_continue();
586
587    //レキシカルスコープをレベルダウン
588    compiler.codeGenerator.lexicalScopes.End();
589
590    //jeジャンプ先のオフセット値
591    compiler.codeGenerator.opfix_JmpPertialSchedule( pTempPertialSchedule );
592
593    //Continueアドレスを復元
594    compiler.codeGenerator.ContinueAreaEnd();
595}
596
597void OpcodeForeach( const char *Parameter )
598{
599    Type resultType;
600    char temporary[VN_SIZE],variable[VN_SIZE],collectionVar[VN_SIZE];
601    bool isError = false;
602
603    //レキシカルスコープをレベルアップ
604    compiler.codeGenerator.lexicalScopes.Start( compiler.codeGenerator.GetNativeCodeSize(), LexicalScope::SCOPE_TYPE_FOR );
605
606    //第1パラメータを取得
607    int i = 0;
608    GetCustomToken( variable, Parameter, i, ESC_IN, true );
609    if(!Parameter[i]){
610        compiler.errorMessenger.Output(12,"Foreach",cp);
611        isError = true;
612        goto ErrorStep;
613    }
614    i++;
615
616    //第2パラメータを取得(in~)
617    lstrcpy( collectionVar, Parameter + i );
618
619    if( !GetVarType( variable, resultType, false ) )
620    {
621        Type collectionType;
622        if( !NumOpe_GetType( collectionVar, Type(), collectionType ) )
623        {
624            isError = true;
625            goto ErrorStep;
626        }
627
628        // 未定義の場合は自動的に定義する
629        sprintf(temporary,"%s=Nothing%c%c%s", variable, 1, ESC_AS, collectionType.GetActualGenericType(0).GetClass().GetFullName().c_str() );
630        OpcodeDim(temporary,DIMFLAG_INITDEBUGVAR);
631    }
632
633    // Resetメソッドを呼び出す
634    sprintf( temporary, "%s.Reset()", collectionVar );
635    Compile( temporary );
636
637    //Continueアドレスのバックアップとセット
638    compiler.codeGenerator.ContinueAreaBegin();
639
640    // MoveNextメソッドを呼び出す
641    sprintf( temporary, "%s.MoveNext()", collectionVar );
642    NumOpe(temporary,Type(),Type());
643
644    //pop eax
645    compiler.codeGenerator.op_pop(REG_EAX);
646
647    //cmp eax,0
648    compiler.codeGenerator.op_cmp_value( sizeof(long), REG_EAX, 0 );
649
650ErrorStep:
651
652    //je ...
653    const PertialSchedule *pTempPertialSchedule = compiler.codeGenerator.op_je( 0, sizeof(long), true );
654
655    if( !isError )
656    {
657        // Currentプロパティから現在の値を取得
658        sprintf( temporary, "%s=%s.Current", variable, collectionVar );
659        Compile( temporary );
660    }
661
662    //For内をコンパイル
663    CompileBuffer(0,COM_NEXT);
664
665    compiler.codeGenerator.lexicalScopes.CallDestructorsOfScopeEnd();
666
667    if(szNextVariable[0]){
668        if(lstrcmp(szNextVariable,variable)!=0){
669            compiler.errorMessenger.Output(55,szNextVariable,cp);
670        }
671    }
672
673    if( !isError )
674    {
675        //jmp ...
676        compiler.codeGenerator.op_jmp_continue();
677    }
678
679    //レキシカルスコープをレベルダウン
680    compiler.codeGenerator.lexicalScopes.End();
681
682    //jeジャンプ先のオフセット値
683    compiler.codeGenerator.opfix_JmpPertialSchedule( pTempPertialSchedule );
684
685    //Continueアドレスを復元
686    compiler.codeGenerator.ContinueAreaEnd();
687}
688
689void OpcodeDo(char *Parameter){
690    extern HANDLE hHeap;
691    int i,i2,i3;
692
693    if(Parameter[0]) compiler.errorMessenger.Output(10,"Do",cp);
694
695    //Continueアドレスのバックアップとセット
696    compiler.codeGenerator.ContinueAreaBegin();
697
698    //レキシカルスコープをレベルアップ
699    compiler.codeGenerator.lexicalScopes.Start( compiler.codeGenerator.GetNativeCodeSize(), LexicalScope::SCOPE_TYPE_DO );
700
701    //Do内をコンパイル
702    CompileBuffer(0,COM_LOOP);
703
704    compiler.codeGenerator.lexicalScopes.CallDestructorsOfScopeEnd();
705
706    const PertialSchedule *pDoPertialSchedule = NULL;
707
708    extern char *basbuf;
709    char temporary[VN_SIZE];
710    for(i=cp-1;;i--){
711        if(IsCommandDelimitation(basbuf[i])){
712            i+=3;
713            if(!(basbuf[i]=='0'||basbuf[i]=='1')){
714                //無条件ループ
715                break;
716            }
717            i3=i;
718
719            for(i+=2,i2=0;;i++,i2++){
720                if(IsCommandDelimitation(basbuf[i])){
721                    temporary[i2]=0;
722                    break;
723                }
724                temporary[i2]=basbuf[i];
725            }
726
727            Type tempType;
728            NumOpe(temporary,Type(),tempType);
729
730            if( tempType.IsDouble() ){
731                //fld qword ptr[esp]
732                compiler.codeGenerator.op_fld_ptr_esp(DEF_DOUBLE);
733
734                //push 0
735                compiler.codeGenerator.op_push_V(0);
736
737                //fild dword ptr[esp]
738                compiler.codeGenerator.op_fld_ptr_esp(DEF_LONG);
739
740                //add esp,sizeof(double)+sizeof(long)
741                compiler.codeGenerator.op_add_esp(sizeof(double)+sizeof(long));
742
743                //fcompp
744                compiler.codeGenerator.op_fcompp();
745
746                //fnstsw ax
747                compiler.codeGenerator.op_fnstsw_ax();
748
749                //test ah,40
750                compiler.codeGenerator.op_test_ah( (char)0x40 );
751
752                if(basbuf[i3]=='0'){
753                    //While
754
755                    //jne 5(ループ終了)
756                    pDoPertialSchedule = compiler.codeGenerator.op_jne( 0, sizeof(char), true );
757                }
758                else if(basbuf[i3]=='1'){
759                    //Until
760
761                    //je 5(ループ終了)
762                    pDoPertialSchedule = compiler.codeGenerator.op_je( 0, sizeof(char), true );
763                }
764            }
765            else if( tempType.IsSingle() ){
766                //fld dword ptr[esp]
767                compiler.codeGenerator.op_fld_ptr_esp(DEF_SINGLE);
768
769                //push 0
770                compiler.codeGenerator.op_push_V(0);
771
772                //fild dword ptr[esp]
773                compiler.codeGenerator.op_fld_ptr_esp(DEF_LONG);
774
775                //add esp,sizeof(float)+sizeof(long)
776                compiler.codeGenerator.op_add_esp(sizeof(float)+sizeof(long));
777
778                //fcompp
779                compiler.codeGenerator.op_fcompp();
780
781                //fnstsw ax
782                compiler.codeGenerator.op_fnstsw_ax();
783
784                //test ah,40
785                compiler.codeGenerator.op_test_ah( (char)0x40 );
786
787                if(basbuf[i3]=='0'){
788                    //While
789
790                    //jne 5(ループ終了)
791                    pDoPertialSchedule = compiler.codeGenerator.op_jne( 0, sizeof(char), true );
792                }
793                else if(basbuf[i3]=='1'){
794                    //Until
795
796                    //je 5(ループ終了)
797                    pDoPertialSchedule = compiler.codeGenerator.op_je( 0, sizeof(char), true );
798                }
799            }
800            else if( tempType.Is64() ){
801                //64ビット型
802
803                //pop eax
804                compiler.codeGenerator.op_pop(REG_EAX);
805
806                //pop ebx
807                compiler.codeGenerator.op_pop(REG_EBX);
808
809                //cmp eax,0
810                compiler.codeGenerator.op_cmp_value( sizeof(long), REG_EAX, 0 );
811
812                //jne
813                const PertialSchedule *pTempPertialSchedule1 = compiler.codeGenerator.op_jne( 0, sizeof(char), true );
814
815                //cmp ebx,0
816                compiler.codeGenerator.op_cmp_value( sizeof(long), REG_EBX, 0 );
817
818                //jne
819                const PertialSchedule *pTempPertialSchedule2 = compiler.codeGenerator.op_jne( 0, sizeof(char), true );
820
821                if(basbuf[i3]=='0'){
822                    //While
823
824                    //jmp 5(ループ終了)
825                    pDoPertialSchedule = compiler.codeGenerator.op_jmp( 0, sizeof(char), true );
826
827                    compiler.codeGenerator.opfix_JmpPertialSchedule( pTempPertialSchedule1 );
828                    compiler.codeGenerator.opfix_JmpPertialSchedule( pTempPertialSchedule2 );
829                }
830                else if(basbuf[i3]=='1'){
831                    //Until
832
833                    //jmp 2(ループを続ける)
834                    const PertialSchedule *pTempPertialSchedule3 = compiler.codeGenerator.op_jmp( 0, sizeof(char), true );
835
836                    compiler.codeGenerator.opfix_JmpPertialSchedule( pTempPertialSchedule1 );
837                    compiler.codeGenerator.opfix_JmpPertialSchedule( pTempPertialSchedule2 );
838
839                    //jmp 5(ループ終了)
840                    pDoPertialSchedule = compiler.codeGenerator.op_jmp( 0, sizeof(char), true );
841
842                    compiler.codeGenerator.opfix_JmpPertialSchedule( pTempPertialSchedule3 );
843                }
844            }
845            else{
846                //pop eax
847                compiler.codeGenerator.op_pop(REG_EAX);
848
849                //cmp eax,0
850                compiler.codeGenerator.op_cmp_value( sizeof(long), REG_EAX, 0 );
851
852                if(basbuf[i3]=='0'){
853                    //While
854
855                    //je 5(ループ終了)
856                    pDoPertialSchedule = compiler.codeGenerator.op_je( 0, sizeof(char), true );
857                }
858                else if(basbuf[i3]=='1'){
859                    //Until
860
861                    //jne 5(ループ終了)
862                    pDoPertialSchedule = compiler.codeGenerator.op_jne( 0, sizeof(char), true );
863                }
864            }
865            break;
866        }
867    }
868
869    //jmp ...
870    compiler.codeGenerator.op_jmp_continue();
871
872    if( pDoPertialSchedule )
873    {
874        compiler.codeGenerator.opfix_JmpPertialSchedule( pDoPertialSchedule );
875    }
876
877    //jmp ...
878    const PertialSchedule *pTempPertialSchedule = compiler.codeGenerator.op_jmp( 0, sizeof(long), true );
879
880    //レキシカルスコープをレベルダウン
881    compiler.codeGenerator.lexicalScopes.End();
882
883    //jmpジャンプ先のオフセット値
884    compiler.codeGenerator.opfix_JmpPertialSchedule( pTempPertialSchedule );
885
886    //Continueアドレスを復元
887    compiler.codeGenerator.ContinueAreaEnd();
888}
889void OpcodeContinue(void){
890    //jmp ...(Continue addr)
891    compiler.codeGenerator.op_jmp_continue();
892}
893
894void OpcodeExitSub(void){
895    if( UserProc::IsGlobalAreaCompiling() ){
896        compiler.errorMessenger.Output(12,"Exit Sub/Function",cp);
897        return;
898    }
899
900    //未解放のローカルオブジェクトのデストラクタを呼び出す
901    compiler.codeGenerator.lexicalScopes.CallDestructorsOfReturn();
902
903    //jmp ...(End Sub/Function)
904    compiler.codeGenerator.op_jmp_exitsub();
905}
906
907//Caseスケジュール
908class SelectSchedule
909{
910public:
911    SelectSchedule( int typeSize )
912        : typeSize( typeSize )
913        , nowCaseSchedule( 0 )
914    {
915    }
916
917    PertialSchedules casePertialSchedules;
918    int typeSize;
919    int nowCaseSchedule;
920};
921std::vector<SelectSchedule> selectSchedules;
922
923void OpcodeSelect(const char *lpszParms)
924{
925    extern HANDLE hHeap;
926    extern char *basbuf;
927    int i,i2,i3,sw,NowCaseCp;
928    char temporary[VN_SIZE];
929   
930    Type type1;
931    bool result = NumOpe(lpszParms,Type(), type1 );
932
933    selectSchedules.push_back( SelectSchedule( type1.GetSize() ) );
934
935    if( result )
936    {
937        if( selectSchedules.back().typeSize < sizeof(long) ){
938            selectSchedules.back().typeSize = sizeof(long);
939        }
940
941        for(i=cp,sw=0;;i++){
942            if(basbuf[i]=='\0'){
943                selectSchedules.pop_back();
944                compiler.errorMessenger.Output(22,"Select",cp);
945                return;
946            }
947            if(basbuf[i]==1&&basbuf[i+1]==ESC_SELECTCASE){
948                for(i2=0;;i++){
949                    if(basbuf[i]==1&&basbuf[i+1]==ESC_SELECTCASE) i2++;
950                    if(basbuf[i]==1&&basbuf[i+1]==ESC_ENDSELECT){
951                        i2--;
952                        if(i2==0) break;
953                    }
954                }
955                continue;
956            }
957            if(basbuf[i]==1&&basbuf[i+1]==ESC_ENDSELECT){
958                if(sw==0){
959                    //add esp,CaseTypeSize
960                    compiler.codeGenerator.op_add_esp( selectSchedules.back().typeSize );
961                }
962                break;
963            }
964            if(basbuf[i]==1&&basbuf[i+1]==ESC_CASE){
965                NowCaseCp=i;
966
967                i++;
968                while(1){
969                    for(i++,i2=0;;i++,i2++){
970                        if(basbuf[i]=='\"'){
971                            i3=GetStringInQuotation(temporary+i2,basbuf+i);
972                            i+=i3-1;
973                            i2+=i3-1;
974                            continue;
975                        }
976                        if(basbuf[i]=='('){
977                            i3=GetStringInPare(temporary+i2,basbuf+i);
978                            i+=i3-1;
979                            i2+=i3-1;
980                            continue;
981                        }
982                        if(basbuf[i]=='['){
983                            i3=GetStringInBracket(temporary+i2,basbuf+i);
984                            i+=i3-1;
985                            i2+=i3-1;
986                            continue;
987                        }
988
989                        if(IsCommandDelimitation(basbuf[i])){
990                            temporary[i2]=0;
991                            break;
992                        }
993                        if(basbuf[i]==','){
994                            temporary[i2]=0;
995                            break;
996                        }
997
998                        temporary[i2]=basbuf[i];
999                    }
1000
1001                    //エラー用
1002                    i2=cp;
1003                    cp=NowCaseCp;
1004
1005                    Type type2;
1006                    if( !NumOpe(temporary,type1,type2) ){
1007                        return;
1008                    }
1009
1010                    cp=i2;
1011
1012                    if(type1.IsObject()){
1013                        std::vector<const UserProc *> subs;
1014                        type1.GetClass().GetDynamicMethods().Enum( CALC_EQUAL, subs );
1015                        if( subs.size() == 0 ){
1016                            return;
1017                        }
1018
1019                        Parameters params;
1020                        params.push_back( new Parameter( "", Type( type2 ) ) );
1021
1022                        //オーバーロードを解決
1023                        const UserProc *pUserProc = OverloadSolution( "==", subs, params, Type( DEF_BOOLEAN ), type1 );
1024
1025                        delete params[0];
1026
1027                        if(!pUserProc){
1028                            //エラー
1029                            return;
1030                        }
1031
1032
1033                        //pop edx
1034                        compiler.codeGenerator.op_pop(REG_EDX);
1035
1036                        //mov ecx,dword ptr[esp]
1037                        compiler.codeGenerator.op_mov_RM(sizeof(long),REG_ECX,REG_ESP,0,MOD_BASE);
1038
1039                        //push edx
1040                        compiler.codeGenerator.op_push(REG_EDX);
1041
1042                        //push ecx
1043                        compiler.codeGenerator.op_push(REG_ECX);
1044
1045                        //call operator_proc    ※ ==演算子
1046                        compiler.codeGenerator.op_call(pUserProc);
1047
1048                        //test eax,eax
1049                        compiler.codeGenerator.op_test(REG_EAX,REG_EAX);
1050
1051                        //jne ...
1052                        selectSchedules.back().casePertialSchedules.push_back(
1053                            compiler.codeGenerator.op_jne( 0, sizeof(long), true )
1054                        );
1055                    }
1056                    else if(type1.IsDouble()){
1057                        ChangeTypeToDouble(type2.GetBasicType());
1058
1059                        //fld qword ptr[esp]
1060                        compiler.codeGenerator.op_fld_ptr_esp(DEF_DOUBLE);
1061
1062                        //add esp,CaseTypeSize
1063                        compiler.codeGenerator.op_add_esp(selectSchedules.back().typeSize);
1064
1065                        //fld qword ptr[esp]
1066                        compiler.codeGenerator.op_fld_ptr_esp(DEF_DOUBLE);
1067
1068                        //fcompp
1069                        compiler.codeGenerator.op_fcompp();
1070
1071                        //fnstsw ax
1072                        compiler.codeGenerator.op_fnstsw_ax();
1073
1074                        //test ah,40
1075                        compiler.codeGenerator.op_test_ah( (char)0x40 );
1076
1077                        //jne ...
1078                        selectSchedules.back().casePertialSchedules.push_back(
1079                            compiler.codeGenerator.op_jne( 0, sizeof(long), true )
1080                        );
1081                    }
1082                    else if(type1.IsSingle()){
1083                        ChangeTypeToSingle(type2.GetBasicType());
1084
1085                        //fld dword ptr[esp]
1086                        compiler.codeGenerator.op_fld_ptr_esp(DEF_SINGLE);
1087
1088                        //add esp,CaseTypeSize
1089                        compiler.codeGenerator.op_add_esp(selectSchedules.back().typeSize);
1090
1091                        //fld dword ptr[esp]
1092                        compiler.codeGenerator.op_fld_ptr_esp(DEF_SINGLE);
1093
1094                        //fcompp
1095                        compiler.codeGenerator.op_fcompp();
1096
1097                        //fnstsw ax
1098                        compiler.codeGenerator.op_fnstsw_ax();
1099
1100                        //test ah,40
1101                        compiler.codeGenerator.op_test_ah( (char)0x40 );
1102
1103                        //jne ...
1104                        selectSchedules.back().casePertialSchedules.push_back(
1105                            compiler.codeGenerator.op_jne( 0, sizeof(long), true )
1106                        );
1107                    }
1108                    else{
1109                        //その他整数型
1110
1111                        //pop ebx
1112                        compiler.codeGenerator.op_pop(REG_EBX);
1113
1114                        //mov eax,dword ptr[esp]
1115                        compiler.codeGenerator.op_mov_RM( sizeof(long), REG_EAX, REG_ESP, 0, MOD_BASE );
1116
1117                        //cmp eax,ebx
1118                        compiler.codeGenerator.op_cmp_RR( REG_EAX, REG_EBX );
1119
1120                        //je ...
1121                        selectSchedules.back().casePertialSchedules.push_back(
1122                            compiler.codeGenerator.op_je( 0, sizeof(long), true )
1123                        );
1124                    }
1125
1126                    if(basbuf[i]!=',') break;
1127                }
1128            }
1129            if(basbuf[i]==1&&basbuf[i+1]==ESC_CASEELSE){
1130                sw=1;
1131
1132                //jmp ...
1133                selectSchedules.back().casePertialSchedules.push_back(
1134                    compiler.codeGenerator.op_jmp( 0, sizeof(long), true )
1135                );
1136            }
1137        }
1138    }
1139
1140    //レキシカルスコープをレベルアップ
1141    compiler.codeGenerator.lexicalScopes.Start( compiler.codeGenerator.GetNativeCodeSize(), LexicalScope::SCOPE_TYPE_SELECT );
1142
1143    //Select Case内をコンパイル
1144    CompileBuffer(ESC_ENDSELECT,0);
1145
1146    //jmp EndSelect
1147    selectSchedules.back().casePertialSchedules.push_back(
1148        compiler.codeGenerator.op_jmp( 0, sizeof(long), true )
1149    );
1150
1151    //最終スケジュール
1152    for(i=selectSchedules.back().nowCaseSchedule;i<(int)selectSchedules.back().casePertialSchedules.size();i++){
1153        compiler.codeGenerator.opfix_JmpPertialSchedule( selectSchedules.back().casePertialSchedules[i] );
1154    }
1155
1156    //レキシカルスコープをレベルダウン
1157    compiler.codeGenerator.lexicalScopes.End();
1158
1159    selectSchedules.pop_back();
1160}
1161void OpcodeCase(char *Parameter){
1162    int i;
1163
1164    if(selectSchedules.back().typeSize==-1){
1165        compiler.errorMessenger.Output(30,"Case",cp);
1166        return;
1167    }
1168
1169    //jmp EndSelect
1170    selectSchedules.back().casePertialSchedules.push_back(
1171        compiler.codeGenerator.op_jmp( 0, sizeof(long), true )
1172    );
1173
1174    i=0;
1175    while(1){
1176        //Caseスケジュール
1177        compiler.codeGenerator.opfix_JmpPertialSchedule( selectSchedules.back().casePertialSchedules[selectSchedules.back().nowCaseSchedule] );
1178        selectSchedules.back().nowCaseSchedule++;
1179
1180        i=JumpOneParameter(Parameter,i);
1181        if(Parameter[i]=='\0') break;
1182    }
1183
1184    //add esp,CaseTypeSize
1185    compiler.codeGenerator.op_add_esp(selectSchedules.back().typeSize);
1186}
1187
1188void OpcodeGosub(char *Parameter){
1189    extern HANDLE hHeap;
1190    int i,LineNum;
1191
1192    if(Parameter[0]=='*'){
1193        i=GetLabelAddress(Parameter+1,0);
1194
1195        if( i == -1 )
1196        {
1197            //jmp ...(schedule)
1198            compiler.codeGenerator.op_jmp_goto_schedule( (const std::string)(Parameter + 1), 0, cp );
1199        }
1200        else
1201        {
1202            //jmp ...
1203            compiler.codeGenerator.op_jmp(
1204                i-compiler.codeGenerator.GetNativeCodeSize(),
1205                sizeof(long),
1206                false,
1207                true
1208            );
1209        }
1210    }
1211    else{
1212        LineNum=atoi(Parameter);
1213        i=GetLabelAddress(0,LineNum);
1214
1215        if( i == -1 )
1216        {
1217            //jmp ...(schedule)
1218            compiler.codeGenerator.op_jmp_goto_schedule( "", LineNum, cp );
1219        }
1220        else
1221        {
1222            //jmp ...
1223            compiler.codeGenerator.op_jmp(
1224                i-compiler.codeGenerator.GetNativeCodeSize(),
1225                sizeof(long),
1226                false,
1227                true
1228            );
1229        }
1230    }
1231}
1232void OpcodeReturn(char *Parameter){
1233    if( UserProc::IsGlobalAreaCompiling() ){
1234        //Gosub~Returnとして扱う
1235
1236        //ret
1237        compiler.codeGenerator.op_ret();
1238    }
1239    else{
1240        //戻り値をセット
1241        if(Parameter[0]){
1242            const UserProc &proc = UserProc::CompilingUserProc();
1243
1244            const char *temp = "_System_ReturnValue";
1245            if(proc.GetName()[0]==1&&proc.GetName()[1]==ESC_OPERATOR)
1246            {
1247            }
1248            else{
1249                temp=proc.GetName().c_str();
1250            }
1251
1252            char temporary[VN_SIZE];
1253            sprintf(temporary,"%s=%s",temp,Parameter);
1254            OpcodeCalc(temporary);
1255        }
1256
1257        //プロシージャを抜け出す(C言語のreturnと同様の処理を行う)
1258        OpcodeExitSub();
1259    }
1260}
1261
1262
1263////////////
1264// ポインタ
1265
1266void OpcodeSetPtrData(char *Parameter,int type){
1267    int i;
1268    char temporary[VN_SIZE];
1269
1270    if(Parameter[0]=='('){
1271        i=JumpStringInPare(Parameter,1);
1272        if(Parameter[i+1]=='\0'){
1273            for(i=0;;i++){
1274                Parameter[i]=Parameter[i+1];
1275                if(Parameter[i]=='\0') break;
1276            }
1277            Parameter[i-1]=0;
1278        }
1279    }
1280
1281    //第1パラメータを取得
1282    i=GetOneParameter(Parameter,0,temporary);
1283    if(!Parameter[i]){
1284        compiler.errorMessenger.Output(1,NULL,cp);
1285        return;
1286    }
1287
1288    Type resultType;
1289    if( !NumOpe(temporary,Type(),resultType) ){
1290        return;
1291    }
1292    if(!resultType.IsWhole()){
1293        compiler.errorMessenger.Output(11,Parameter,cp);
1294        return;
1295    }
1296
1297    ChangeTypeToLong( resultType.GetBasicType() );
1298
1299    //第2パラメータを取得
1300    i=GetOneParameter(Parameter,i,temporary);
1301    if(Parameter[i]){
1302        compiler.errorMessenger.Output(1,NULL,cp);
1303        return;
1304    }
1305
1306    if( !NumOpe(temporary,Type(),resultType) ){
1307        return;
1308    }
1309
1310    if(type==DEF_DOUBLE){
1311        ChangeTypeToDouble_ToFpuReg( resultType.GetBasicType() );
1312
1313        //pop eax
1314        compiler.codeGenerator.op_pop(REG_EAX);
1315
1316        //fstp qword ptr[eax]
1317        compiler.codeGenerator.PutOld(
1318            (char)0xDD,
1319            (char)0x18
1320        );
1321    }
1322    else if(type==DEF_SINGLE){
1323        ChangeTypeToSingle( resultType.GetBasicType() );
1324
1325        //pop ebx
1326        compiler.codeGenerator.op_pop(REG_EBX);
1327
1328        //pop eax
1329        compiler.codeGenerator.op_pop(REG_EAX);
1330
1331        //mov dword ptr[eax],ebx
1332        compiler.codeGenerator.op_mov_MR( sizeof(long), REG_EBX, REG_EAX, 0, MOD_BASE );
1333    }
1334    else if(type==DEF_QWORD){
1335        ChangeTypeToInt64( resultType.GetBasicType() );
1336
1337        //pop ecx
1338        compiler.codeGenerator.op_pop(REG_ECX);
1339
1340        //pop ebx
1341        compiler.codeGenerator.op_pop(REG_EBX);
1342
1343        //pop eax
1344        compiler.codeGenerator.op_pop(REG_EAX);
1345
1346        //mov dword ptr[eax],ecx
1347        compiler.codeGenerator.op_mov_MR( sizeof(long), REG_ECX, REG_EAX, 0, MOD_BASE );
1348
1349        //mov dword ptr[eax+sizeof(long)],ebx
1350        compiler.codeGenerator.op_mov_MR( sizeof(long), REG_EBX, REG_EAX, 0x04, MOD_BASE_DISP8 );
1351    }
1352    else if(type==DEF_DWORD){
1353        ChangeTypeToLong( resultType.GetBasicType() );
1354
1355        //pop ebx
1356        compiler.codeGenerator.op_pop(REG_EBX);
1357
1358        //pop eax
1359        compiler.codeGenerator.op_pop(REG_EAX);
1360
1361        //mov dword ptr[eax],ebx
1362        compiler.codeGenerator.op_mov_MR( sizeof(long), REG_EBX, REG_EAX, 0, MOD_BASE );
1363    }
1364    else if(type==DEF_WORD){
1365        ChangeTypeToLong( resultType.GetBasicType() );
1366
1367        //pop ebx
1368        compiler.codeGenerator.op_pop(REG_EBX);
1369
1370        //pop eax
1371        compiler.codeGenerator.op_pop(REG_EAX);
1372
1373        //mov word ptr[eax],bx
1374        compiler.codeGenerator.op_mov_MR( sizeof(short), REG_EBX, REG_EAX, 0, MOD_BASE );
1375    }
1376    else if(type==DEF_BYTE){
1377        ChangeTypeToLong( resultType.GetBasicType() );
1378
1379        //pop ebx
1380        compiler.codeGenerator.op_pop(REG_EBX);
1381
1382        //pop eax
1383        compiler.codeGenerator.op_pop(REG_EAX);
1384
1385        //mov byte ptr[eax],bl
1386        compiler.codeGenerator.op_mov_MR( sizeof(char), REG_EBX, REG_EAX, 0, MOD_BASE );
1387    }
1388}
Note: See TracBrowser for help on using the repository browser.