source: dev/trunk/abdev/BasicCompiler_Common/Subroutine.cpp @ 342

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

vtblの構造を変更。vtblMasterListをはさんでvtblを表現した。
その他メンバ名変更。
ClassPrototypeクラスを追加。

File size: 14.7 KB
Line 
1#include "stdafx.h"
2
3#include <jenga/include/smoothie/Smoothie.h>
4#include <jenga/include/smoothie/LexicalAnalysis.h>
5
6#include <Compiler.h>
7#include <Procedure.h>
8#include <NamespaceSupporter.h>
9
10#include "../BasicCompiler_Common/common.h"
11
12#ifdef _AMD64_
13#include "../BasicCompiler64/opcode.h"
14#else
15#include "../BasicCompiler32/opcode.h"
16#endif
17
18int GetCallProcName(char *buffer,char *name){
19    int i2,i3,IsStr=0;
20
21    for(i2=0;;i2++){
22        if(buffer[i2]=='\"') IsStr^=1;
23        if(IsDBCSLeadByte(buffer[i2])){
24            name[i2]=buffer[i2];
25            i2++;
26            name[i2]=buffer[i2];
27            continue;
28        }
29        if(buffer[i2]=='['&&IsStr==0){
30            i3=GetStringInBracket(name+i2,buffer+i2);
31            i2+=i3-1;
32            continue;
33        }
34        if(buffer[i2]=='('&&IsStr==0){
35            name[i2]=0;
36            break;
37        }
38        if(buffer[i2]=='='&&IsStr==0){
39            name[i2]=0;
40            break;
41        }
42
43        name[i2]=buffer[i2];
44        if(buffer[i2]=='\0') break;
45    }
46    return i2;
47}
48
49int GetProc(char *name,void **ppInfo){
50
51    //ユーザー定義関数
52    *ppInfo=(void *)GetSubHash(name);
53    if(*ppInfo) return PROC_DEFAULT;
54
55    //DLL関数
56    *ppInfo=(void *)GetDeclareHash(name);
57    if(*ppInfo) return PROC_DLL;
58
59    //コンパイラ埋め込み型
60    *ppInfo=(void *)(_int64)GetFunctionFromName(name);
61    if(*ppInfo) return PROC_BUILTIN;
62
63
64    /////////////////////////////////////////////////////////////////
65    //関数ポインタ、またはデリゲート
66    /////////////////////////////////////////////////////////////////
67
68    Type type;
69    if( !GetVarType( name, type, false ) ){
70        return 0;
71    }
72
73    if( type.IsProcPtr() )
74    {
75        // 関数ポインタ
76        return PROC_PTR;
77    }
78
79    if( type.IsDelegate() )
80    {
81        // デリゲート
82        return PROC_DELEGATE;
83    }
84
85    return 0;
86}
87
88void SplitObjectName(const char *name,char *ObjectName, ReferenceKind &referenceFind )
89{
90    referenceFind = RefNon;
91
92    int i4;
93    for(i4=lstrlen(name)-1;i4>=0;i4--){
94        if(name[i4]=='.'||(name[i4]==1&&name[i4+1]==ESC_PSMEM))
95            break;
96    }
97    if(i4==-1) ObjectName[0]=0;
98    else{
99        //参照タイプを判別
100        if(name[i4]=='.')
101        {
102            referenceFind = RefDot;
103        }
104        else
105        {
106            referenceFind = RefPointer;
107        }
108
109        if(i4==0) GetWithName(ObjectName);
110        else{
111            memcpy(ObjectName,name,i4);
112            ObjectName[i4]=0;
113        }
114    }
115}
116
117bool CallProc( int kind, const void *pProc, const char *fullCallName, const char *lpszParms, const Type &baseType, Type &resultType, bool isCallOn )
118{
119    //GetSubHash内でエラー提示が行われた場合
120    if(pProc==(Procedure *)-1){
121        return false;
122    }
123
124    if(kind==PROC_DEFAULT){
125        /////////////////////
126        // ユーザー定義関数
127        /////////////////////
128
129        const UserProc *pUserProc = (const UserProc *)pProc;
130
131        //オブジェクト名を取得
132        char ObjectName[VN_SIZE];
133        ReferenceKind referenceKind;
134        SplitObjectName(fullCallName,ObjectName, referenceKind );
135
136
137        ////////////////////////
138        // オーバーロードを解決
139        ////////////////////////
140
141        std::vector<const UserProc *> subs;
142        GetOverloadSubHash(fullCallName,subs);
143        if(subs.size()){
144            //オーバーロードを解決
145            pUserProc=OverloadSolutionWithStrParam(fullCallName,subs,lpszParms,ObjectName);
146
147            if(!pUserProc){
148                return false;
149            }
150        }
151
152        resultType = pUserProc->ReturnType();
153
154        if( isCallOn ){
155            if( !Opcode_CallProc(lpszParms,pUserProc,0,ObjectName ) ){
156                return false;
157            }
158        }
159    }
160    else if(kind==PROC_DLL){
161        /////////////////////////
162        // DLL関数
163        /////////////////////////
164        DllProc *pDllProc = (DllProc *)pProc;
165
166        resultType = pDllProc->ReturnType();
167
168        if( isCallOn ){
169            if( !Opcode_CallDllProc(lpszParms,pDllProc) ){
170                return false;
171            }
172        }
173    }
174    else if(kind==PROC_BUILTIN){
175        /////////////////////////
176        // 組み込み関数
177        /////////////////////////
178        int FuncId = (int)(_int64)pProc;
179
180        if( !Opcode_CallFunc( lpszParms, FuncId, baseType, resultType, isCallOn ) ){
181            return false;
182        }
183    }
184    else if(kind==PROC_PTR){
185        /////////////////
186        // 関数ポインタ
187        /////////////////
188
189        Type type;
190        GetVarType(fullCallName,type,false);
191
192        ProcPointer *pProcPtr = compiler.GetObjectModule().meta.GetProcPointers()[type.GetIndex()];
193        resultType = pProcPtr->ReturnType();
194
195        if( isCallOn ){
196            if( !Opcode_CallProcPtr(fullCallName,lpszParms,pProcPtr) ){
197                return false;
198            }
199        }
200    }
201    else if( kind == PROC_DELEGATE )
202    {
203        // デリゲート
204        char tempName[VN_SIZE];
205        lstrcpy( tempName, fullCallName );
206        lstrcat( tempName, ".Call" );
207
208        void *pInfo=(void *)GetSubHash( tempName );
209        if( !pInfo )
210        {
211            Jenga::Throw( "デリゲートの内部Callメソッドの取得に失敗" );
212        }
213
214        return CallProc( PROC_DEFAULT, pInfo, tempName, lpszParms, baseType, resultType, isCallOn );
215    }
216    else{
217        return false;
218    }
219
220    return true;
221}
222bool CallPropertyMethod( const char *variable, const char *rightSide, Type &resultType){
223    //プロパティ用のメソッドを呼び出す
224
225    //配列要素を取得
226    char VarName[VN_SIZE],ArrayElements[VN_SIZE];
227    GetArrayElement(variable,VarName,ArrayElements);
228
229    //オブジェクト名を取得
230    char ObjectName[VN_SIZE];
231    ReferenceKind referenceKind;
232    SplitObjectName(VarName,ObjectName, referenceKind );
233
234    //オーバーロード用の関数リストを作成
235    std::vector<const UserProc *> subs;
236    GetOverloadSubHash(VarName,subs);
237    if(subs.size()==0){
238        return false;
239    }
240
241    //パラメータを整備
242    char *Parameter;
243    Parameter=(char *)HeapAlloc(hHeap,0,lstrlen(ArrayElements)+lstrlen(rightSide)+32);
244    lstrcpy(Parameter,ArrayElements);
245    if(rightSide){
246        if(Parameter[0]&&rightSide[0]) lstrcat(Parameter,",");
247        lstrcat(Parameter,rightSide);
248    }
249
250    //オーバーロードを解決
251    const UserProc *pUserProc = OverloadSolutionWithStrParam(VarName,subs,Parameter,ObjectName);
252
253    if(pUserProc){
254        //呼び出し
255        Opcode_CallProc(Parameter,pUserProc,0,ObjectName);
256
257        resultType = pUserProc->ReturnType();
258
259        Type leftType;
260        GetVarType( ObjectName, leftType, false );
261
262        // 型パラメータを解決
263        ResolveFormalGenericTypeParameter( resultType, leftType, pUserProc );
264    }
265
266    HeapDefaultFree(Parameter);
267
268    return true;
269}
270
271bool GetReturnTypeOfPropertyMethod( const char *variable, const char *rightSide, Type &resultType ){
272    //プロパティ用のメソッドを呼び出す
273
274    //配列要素を取得
275    char VarName[VN_SIZE],ArrayElements[VN_SIZE];
276    GetArrayElement(variable,VarName,ArrayElements);
277
278    //オブジェクト名を取得
279    char ObjectName[VN_SIZE];
280    ReferenceKind referenceKind;
281    SplitObjectName(VarName,ObjectName, referenceKind );
282
283    //オーバーロード用の関数リストを作成
284    std::vector<const UserProc *> subs;
285    GetOverloadSubHash(VarName,subs);
286    if(subs.size()==0){
287        return 0;
288    }
289
290    //パラメータを整備
291    char *Parameter;
292    Parameter=(char *)HeapAlloc(hHeap,0,lstrlen(ArrayElements)+lstrlen(rightSide)+32);
293    lstrcpy(Parameter,ArrayElements);
294    if(rightSide){
295        if(Parameter[0]&&rightSide[0]) lstrcat(Parameter,",");
296        lstrcat(Parameter,rightSide);
297    }
298
299    //オーバーロードを解決
300    const UserProc *pUserProc = OverloadSolutionWithStrParam(VarName,subs,Parameter,ObjectName);
301
302    if(pUserProc){
303        resultType = pUserProc->ReturnType();
304    }
305
306    return 1;
307}
308
309//インデクサ(getter)の戻り値を取得
310bool GetReturnTypeOfIndexerGetterProc( const Type &classType, Type &resultType )
311{
312    vector<const UserProc *> subs;
313    classType.GetClass().GetDynamicMethods().Enum( CALC_ARRAY_GET, subs );
314    if( subs.size() == 0 ){
315        return false;
316    }
317
318    const UserProc *pUserProc = subs[0];
319
320    resultType = pUserProc->ReturnType();
321
322
323    // 型パラメータを解決
324    ResolveFormalGenericTypeParameter( resultType, classType, pUserProc );
325
326    return true;
327}
328
329void CollectProcedures( const BasicSource &source, UserProcs &userProcs, DllProcs &dllProcs )
330{
331    extern HANDLE hHeap;
332    int i,i2,i3;
333    char temporary[8192];
334
335    // 名前空間管理
336    NamespaceScopes &namespaceScopes = compiler.GetNamespaceSupporter().GetLivingNamespaceScopes();
337    namespaceScopes.clear();
338
339    // Importsされた名前空間の管理
340    NamespaceScopesCollection &importedNamespaces = compiler.GetNamespaceSupporter().GetImportedNamespaces();
341    importedNamespaces.clear();
342
343    i=-1;
344    while(1){
345        i++;
346
347        if(source[i]==1&&(source[i+1]==ESC_CLASS||source[i+1]==ESC_INTERFACE)){
348            /*  Class ~ End Class
349                Interface ~ End Interface
350                を飛び越す           */
351            i3=GetEndXXXCommand(source[i+1]);
352            for(i+=2,i2=0;;i++,i2++){
353                if(source[i]=='\0') break;
354                if(source[i]==1&&source[i+1]==(char)i3){
355                    i++;
356                    break;
357                }
358            }
359            if(source[i]=='\0') break;
360            continue;
361        }
362
363        if( source[i] == 1 && source[i+1] == ESC_NAMESPACE ){
364            for(i+=2,i2=0;;i2++,i++){
365                if( IsCommandDelimitation( source[i] ) ){
366                    temporary[i2]=0;
367                    break;
368                }
369                temporary[i2]=source[i];
370            }
371            namespaceScopes.push_back( temporary );
372
373            continue;
374        }
375        else if( source[i] == 1 && source[i+1] == ESC_ENDNAMESPACE ){
376            if( namespaceScopes.size() <= 0 ){
377                SetError(12, "End Namespace", i );
378            }
379            else{
380                namespaceScopes.pop_back();
381            }
382
383            i += 2;
384            continue;
385        }
386        else if( source[i] == 1 && source[i+1] == ESC_IMPORTS ){
387            for(i+=2,i2=0;;i2++,i++){
388                if( IsCommandDelimitation( source[i] ) ){
389                    temporary[i2]=0;
390                    break;
391                }
392                temporary[i2]=source[i];
393            }
394            if( !compiler.GetNamespaceSupporter().ImportsNamespace( temporary ) )
395            {
396                SetError(64,temporary,cp );
397            }
398
399            continue;
400        }
401        else if( source[i] == 1 && source[i+1] == ESC_CLEARNAMESPACEIMPORTED ){
402            importedNamespaces.clear();
403            continue;
404        }
405
406        if(source[i]==1&&source[i+1]==ESC_DECLARE){
407            for(i+=2,i2=0;;i2++,i++){
408                if(source[i]=='\n'){
409                    temporary[i2]=0;
410                    break;
411                }
412                temporary[i2]=source[i];
413                if(source[i]=='\0') break;
414            }
415            dllProcs.Add(namespaceScopes,temporary,i);
416
417            continue;
418        }
419        if(source[i]==1&&(source[i+1]==ESC_SUB||source[i+1]==ESC_FUNCTION||source[i+1]==ESC_MACRO)){
420            char statementChar = source[i+1];
421
422            for(i2=0;;i2++,i++){
423                if(IsCommandDelimitation(source[i])){
424                    temporary[i2]=0;
425                    break;
426                }
427                temporary[i2]=source[i];
428                if(source[i]=='\0') break;
429            }
430            userProcs.Add(namespaceScopes, importedNamespaces, temporary,i,false,NULL,false);
431
432            /*  Sub ~ End Sub
433                Function ~ End Function
434                Macro ~ End Macro
435                を飛び越す           */
436            char endStatementChar = GetEndXXXCommand( statementChar );
437            for(i2=0;;i++,i2++){
438                if( source[i] == '\0' ) break;
439                if( source[i] == 1 && source[i+1] == endStatementChar ){
440                    i++;
441                    break;
442                }
443            }
444            if(source[i]=='\0') break;
445            continue;
446        }
447
448        //次の行
449        for(;;i++){
450            if(IsCommandDelimitation(source[i])) break;
451        }
452        if(source[i]=='\0') break;
453    }
454
455    ////////////
456    // 特殊関数
457    ////////////
458    namespaceScopes.clear();
459    importedNamespaces.clear();
460
461    compiler.globalAreaProcName = "_System_GlobalArea_" + compiler.GetModuleName();
462    sprintf(temporary,"%c%c%s()",1,ESC_SUB,compiler.globalAreaProcName.c_str());
463    userProcs.Add( namespaceScopes, importedNamespaces, temporary,0,false,NULL,false);
464}
465
466bool IsNeedProcCompile(){
467    compiler.GetObjectModule().meta.GetUserProcs().Iterator_Reset();
468    while( compiler.GetObjectModule().meta.GetUserProcs().Iterator_HasNext() )
469    {
470        UserProc *pUserProc = compiler.GetObjectModule().meta.GetUserProcs().Iterator_GetNext();
471        if( pUserProc->IsUsing() && pUserProc->IsCompiled() == false ){
472            return true;
473        }
474    }
475    return false;
476}
477
478void CompileBufferInProcedure( const UserProc &userProc ){
479    if( userProc.IsCompiled() ) return;
480
481    _compile_proc( &userProc );
482
483/*
484    // ログを履く
485    char temporary[8192];
486    temporary[0]=0;
487    lstrcat( temporary, "------------------------------------------------------------------\n" );
488    sprintf( temporary + lstrlen(temporary), "【 %s のコード情報】\n", userProc.GetFullName().c_str() );
489    sprintf( temporary + lstrlen(temporary), "code size: %d bytes\n", userProc.GetCodeSize() );
490    lstrcat( temporary, "------------------------------------------------------------------\n" );
491    lstrcat( temporary, "\n" );
492    Smoothie::Logger::Put( temporary );*/
493}
494void CompileLocal(){
495    if( compiler.IsDll() )
496    {
497        //DLLの場合はグローバル変数を初期化するための関数を一番初めにコンパイルする
498        const UserProc *pUserProc=GetSubHash("_System_InitDllGlobalVariables");
499        if(pUserProc){
500            CompileBufferInProcedure( *pUserProc );
501        }
502        else SetError(300,NULL,cp);
503    }
504    else
505    {
506        // グローバル領域を一番初めにコンパイルする
507        extern const UserProc *pSub_System_GlobalArea;
508        CompileBufferInProcedure( *pSub_System_GlobalArea );
509    }
510
511    //_System_TypeBase_InitializeUserTypesは一番最後にコンパイル
512    extern const UserProc *pSubStaticMethod_System_TypeBase_InitializeUserTypes;
513    pSubStaticMethod_System_TypeBase_InitializeUserTypes->CompleteCompile();
514
515    //_System_InitStaticLocalVariablesは一番最後にコンパイル
516    //※一般関数内の静的変数オブジェクトをすべて収集しなければならない
517    extern const UserProc *pSub_System_InitStaticLocalVariables;
518    pSub_System_InitStaticLocalVariables->CompleteCompile();
519
520    //_System_Call_Destructor_of_GlobalObjectは一番最後にコンパイル
521    extern const UserProc *pSub_System_Call_Destructor_of_GlobalObject;
522    pSub_System_Call_Destructor_of_GlobalObject->CompleteCompile();
523
524    // _System_CGarbageCollection.RegisterGlobalRootsは一番最後にコンパイル
525    extern const UserProc *pUserProc_System_CGarbageCollection_RegisterGlobalRoots;
526    pUserProc_System_CGarbageCollection_RegisterGlobalRoots->CompleteCompile();
527
528repeat:
529    compiler.GetObjectModule().meta.GetUserProcs().Iterator_Reset();
530    while( compiler.GetObjectModule().meta.GetUserProcs().Iterator_HasNext() )
531    {
532        UserProc *pUserProc = compiler.GetObjectModule().meta.GetUserProcs().Iterator_GetNext();
533        CompileBufferInProcedure( *pUserProc );
534    }
535
536    if( IsNeedProcCompile() ){
537        //プロシージャコンパイルによって、プロシージャコンパイルが必要になる場合
538        goto repeat;
539    }
540
541    if( !compiler.IsStaticLibrary() )
542    {
543        //_System_TypeBase_InitializeUserTypesは最後のほうでコンパイル
544        pSubStaticMethod_System_TypeBase_InitializeUserTypes->KillCompileStatus();
545        CompileBufferInProcedure( *pSubStaticMethod_System_TypeBase_InitializeUserTypes );
546
547        if( IsNeedProcCompile() ){
548            //プロシージャコンパイルによって、プロシージャコンパイルが必要になる場合
549
550            compiler.GetObjectModule().meta.GetUserProcs().Iterator_Reset();
551            while( compiler.GetObjectModule().meta.GetUserProcs().Iterator_HasNext() )
552            {
553                UserProc *pUserProc = compiler.GetObjectModule().meta.GetUserProcs().Iterator_GetNext();
554                CompileBufferInProcedure( *pUserProc );
555            }
556        }
557
558        //_System_InitStaticLocalVariablesは一番最後にコンパイル
559        pSub_System_InitStaticLocalVariables->KillCompileStatus();
560        CompileBufferInProcedure( *pSub_System_InitStaticLocalVariables );
561
562        //_System_Call_Destructor_of_GlobalObjectは一番最後にコンパイル
563        pSub_System_Call_Destructor_of_GlobalObject->KillCompileStatus();
564        CompileBufferInProcedure( *pSub_System_Call_Destructor_of_GlobalObject );
565
566        // _System_CGarbageCollection.RegisterGlobalRootsは一番最後にコンパイル
567        pUserProc_System_CGarbageCollection_RegisterGlobalRoots->KillCompileStatus();
568        CompileBufferInProcedure( *pUserProc_System_CGarbageCollection_RegisterGlobalRoots );
569    }
570}
Note: See TracBrowser for help on using the repository browser.