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

Last change on this file since 206 was 206, checked in by dai_9181, 17 years ago

コード全体のリファクタリングを実施

File size: 14.6 KB
RevLine 
[206]1#include "stdafx.h"
2
[182]3#include <jenga/include/smoothie/Smoothie.h>
4#include <jenga/include/smoothie/LexicalAnalysis.h>
5
[193]6#include <Compiler.h>
[206]7#include <Procedure.h>
[195]8#include <NamespaceSupporter.h>
[182]9
[4]10#include "../BasicCompiler_Common/common.h"
11
12#ifdef _AMD64_
13#include "../BasicCompiler64/opcode.h"
14#else
[5]15#include "../BasicCompiler32/opcode.h"
[4]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 //関数ポインタ
[75]64 Type type;
65 if( !GetVarType( name, type, false ) ){
66 return 0;
67 }
68 if( type.IsProcPtr() ){
69 return PROC_PTR;
70 }
[4]71
72 return 0;
73}
74
[46]75void SplitObjectName(const char *name,char *ObjectName,int *pRefType){
[4]76 int i4;
77 for(i4=lstrlen(name)-1;i4>=0;i4--){
78 if(name[i4]=='.'||(name[i4]==1&&name[i4+1]==ESC_PSMEM))
79 break;
80 }
81 if(i4==-1) ObjectName[0]=0;
82 else{
83 //参照タイプを判別
84 if(name[i4]=='.') *pRefType=DEF_OBJECT;
85 else *pRefType=DEF_PTR_OBJECT;
86
87 if(i4==0) GetWithName(ObjectName);
88 else{
89 memcpy(ObjectName,name,i4);
90 ObjectName[i4]=0;
91 }
92 }
93}
[97]94
[75]95bool CallProc( int kind, const void *pProc, const char *fullCallName, const char *lpszParms, Type &resultType, bool isCallOn ){
[50]96
[75]97 //GetSubHash内でエラー提示が行われた場合
98 if(pProc==(Procedure *)-1){
99 return false;
100 }
[50]101
[75]102 if(kind==PROC_DEFAULT){
[50]103 /////////////////////
104 // ユーザー定義関数
105 /////////////////////
106
[206]107 const UserProc *pUserProc = (const UserProc *)pProc;
[50]108
109 //オブジェクト名を取得
110 char ObjectName[VN_SIZE];
111 int RefType;
[75]112 SplitObjectName(fullCallName,ObjectName,&RefType);
[50]113
114
115 ////////////////////////
116 // オーバーロードを解決
117 ////////////////////////
118
[206]119 std::vector<const UserProc *> subs;
[75]120 GetOverloadSubHash(fullCallName,subs);
[50]121 if(subs.size()){
122 //オーバーロードを解決
[75]123 pUserProc=OverloadSolutionWithStrParam(fullCallName,subs,lpszParms,ObjectName);
[50]124
[75]125 if(!pUserProc){
126 return false;
127 }
[50]128 }
129
[75]130 resultType = pUserProc->ReturnType();
[50]131
[75]132 if( isCallOn ){
133 if( !Opcode_CallProc(lpszParms,pUserProc,0,ObjectName,RefType) ){
134 return false;
135 }
[50]136 }
137 }
[75]138 else if(kind==PROC_DLL){
[50]139 /////////////////////////
140 // DLL関数
141 /////////////////////////
[75]142 DllProc *pDllProc = (DllProc *)pProc;
[50]143
[75]144 resultType = pDllProc->ReturnType();
145
146 if( isCallOn ){
147 if( !Opcode_CallDllProc(lpszParms,pDllProc) ){
148 return false;
149 }
150 }
[50]151 }
[75]152 else if(kind==PROC_BUILTIN){
[50]153 /////////////////////////
154 // 組み込み関数
155 /////////////////////////
[75]156 int FuncId = (int)(_int64)pProc;
[50]157
[75]158 if( !Opcode_CallFunc( lpszParms, FuncId, resultType, isCallOn ) ){
159 return false;
[50]160 }
161 }
[75]162 else if(kind==PROC_PTR){
[50]163 /////////////////
164 // 関数ポインタ
165 /////////////////
166
[75]167 Type type;
168 GetVarType(fullCallName,type,false);
[50]169
[193]170 ProcPointer *pProcPtr = compiler.GetMeta().GetProcPointers()[type.GetIndex()];
[75]171 resultType = pProcPtr->ReturnType();
172
173 if( isCallOn ){
174 if( !Opcode_CallProcPtr(fullCallName,lpszParms,pProcPtr) ){
175 return false;
176 }
177 }
[50]178 }
[75]179 else{
180 return false;
181 }
[50]182
[75]183 return true;
[50]184}
[75]185bool CallPropertyMethod( const char *variable, const char *rightSide, Type &resultType){
[50]186 //プロパティ用のメソッドを呼び出す
187
188 //配列要素を取得
189 char VarName[VN_SIZE],ArrayElements[VN_SIZE];
190 GetArrayElement(variable,VarName,ArrayElements);
191
192 //オブジェクト名を取得
193 char ObjectName[VN_SIZE];
194 int RefType;
195 SplitObjectName(VarName,ObjectName,&RefType);
196
197 //オーバーロード用の関数リストを作成
[206]198 std::vector<const UserProc *> subs;
[50]199 GetOverloadSubHash(VarName,subs);
200 if(subs.size()==0){
[75]201 return false;
[50]202 }
203
204 //パラメータを整備
205 char *Parameter;
[75]206 Parameter=(char *)HeapAlloc(hHeap,0,lstrlen(ArrayElements)+lstrlen(rightSide)+32);
[50]207 lstrcpy(Parameter,ArrayElements);
[75]208 if(rightSide){
209 if(Parameter[0]&&rightSide[0]) lstrcat(Parameter,",");
210 lstrcat(Parameter,rightSide);
[50]211 }
212
213 //オーバーロードを解決
[206]214 const UserProc *pUserProc = OverloadSolutionWithStrParam(VarName,subs,Parameter,ObjectName);
[50]215
[75]216 if(pUserProc){
[50]217 //呼び出し
[75]218 Opcode_CallProc(Parameter,pUserProc,0,ObjectName,RefType);
[50]219
[75]220 resultType = pUserProc->ReturnType();
[50]221 }
222
223 HeapDefaultFree(Parameter);
224
[75]225 return true;
[50]226}
227
[75]228bool GetReturnTypeOfPropertyMethod( const char *variable, const char *rightSide, Type &resultType ){
[4]229 //プロパティ用のメソッドを呼び出す
230
231 //配列要素を取得
232 char VarName[VN_SIZE],ArrayElements[VN_SIZE];
233 GetArrayElement(variable,VarName,ArrayElements);
234
235 //オブジェクト名を取得
236 char ObjectName[VN_SIZE];
237 int RefType;
[28]238 SplitObjectName(VarName,ObjectName,&RefType);
[4]239
240 //オーバーロード用の関数リストを作成
[206]241 std::vector<const UserProc *> subs;
[50]242 GetOverloadSubHash(VarName,subs);
243 if(subs.size()==0){
[4]244 return 0;
245 }
246
247 //パラメータを整備
248 char *Parameter;
[75]249 Parameter=(char *)HeapAlloc(hHeap,0,lstrlen(ArrayElements)+lstrlen(rightSide)+32);
[4]250 lstrcpy(Parameter,ArrayElements);
[75]251 if(rightSide){
252 if(Parameter[0]&&rightSide[0]) lstrcat(Parameter,",");
253 lstrcat(Parameter,rightSide);
[4]254 }
255
256 //オーバーロードを解決
[206]257 const UserProc *pUserProc = OverloadSolutionWithStrParam(VarName,subs,Parameter,ObjectName);
[4]258
[75]259 if(pUserProc){
260 resultType = pUserProc->ReturnType();
[4]261 }
262
263 return 1;
264}
265
[38]266//インデクサ(getter)の戻り値を取得
[75]267bool GetReturnTypeOfIndexerGetterProc( const CClass &objClass, Type &resultType ){
[206]268 vector<const UserProc *> subs;
[135]269 objClass.GetMethods().Enum( CALC_ARRAY_GET, subs );
[50]270 if( subs.size() == 0 ){
[38]271 return false;
272 }
273
[75]274 resultType = subs[0]->ReturnType();
[38]275
276 return true;
277}
278
279
[100]280void AddDeclareData(const NamespaceScopes &namespaceScopes, char *buffer,int nowLine){
[4]281 extern HANDLE hHeap;
[75]282 int i2;
[4]283
[75]284 int i=0;
[4]285
[75]286 //Sub/Function
287 Procedure::Kind kind = Procedure::Sub;
288 if(buffer[i]==ESC_SUB){
[4]289 }
[75]290 else if(buffer[i]==ESC_FUNCTION){
291 kind = Procedure::Function;
292 }
[4]293 else{
[75]294 SetError(1,NULL,nowLine);
[4]295 return;
296 }
297 i++;
298
299 //プロシージャ名
[75]300 char procName[VN_SIZE];
301 bool isCdecl = false;
[4]302 for(i2=0;;i++,i2++){
303 if(buffer[i]==1&&buffer[i+1]==ESC_CDECL){
[75]304 isCdecl = true;
[4]305
306 i+=2;
[75]307 procName[i2]=0;
[4]308 break;
309 }
310 if(buffer[i]==','){
[75]311 procName[i2]=0;
[4]312 break;
313 }
314 if(buffer[i]=='\0'){
[75]315 SetError(1,NULL,nowLine);
[4]316 return;
317 }
[75]318 procName[i2]=buffer[i];
[4]319 }
[75]320 i++;
[4]321
322 //ユーザー定義関数との重複チェック
[75]323 if(GetSubHash(procName)){
324 SetError(15,procName,nowLine);
[4]325 return;
326 }
327
328
329 //ライブラリ
[75]330 char dllFileName[MAX_PATH];
331 i = GetOneParameter( buffer, i, dllFileName );
332 Type resultType;
[54]333 _int64 i64data;
[75]334 if( !StaticCalculation( true, dllFileName, 0, &i64data, resultType ) ){
[4]335 return;
336 }
[75]337 if( resultType.GetBasicType() != typeOfPtrChar ){
338 SetError(1,NULL,nowLine);
339 return;
340 }
341 lstrcpy( dllFileName, (char *)i64data );
342 CharUpper(dllFileName);
343 if(!strstr(dllFileName,".")){
344 lstrcat(dllFileName,".DLL");
345 if(lstrlen(dllFileName)>=16){
346 SetError(7,NULL,nowLine);
347 return;
[4]348 }
349 }
350
[54]351 //エイリアス
[75]352 char alias[VN_SIZE];
353 i = GetOneParameter( buffer, i, alias );
354 if( alias[0] ){
355 if( !StaticCalculation( true, alias, 0, &i64data, resultType ) ){
[4]356 return;
357 }
[75]358 if( resultType.GetBasicType() != typeOfPtrChar ){
359 SetError(1,NULL,nowLine);
360 return;
361 }
362 lstrcpy( alias, (char *)i64data );
[4]363 }
364 else{
[54]365 //省略されたときは関数名
[75]366 lstrcpy( alias, procName );
[4]367 }
368
369
[75]370 // オブジェクトを生成
[206]371 DllProc *pDllProc = new DllProc( namespaceScopes, procName, kind, isCdecl, dllFileName, alias );
[4]372
[75]373 // パラメータを解析
374 // ※第1パラメータにに指定するデータの例:"( s As String ) As String"
375 pDllProc->SetParamsAndReturnType( buffer + i, nowLine );
[4]376
[75]377 // パラメータのエラーチェック
[182]378 BOOST_FOREACH( const Parameter *pParam, pDllProc->Params() ){
[75]379 if( pParam->IsObject() ){
380 SetError(25,pParam->GetVarName(),nowLine);
[4]381 }
[75]382 if( !pParam->IsRef() ){
383 if( pParam->IsStruct() ){
384 SetError(28,pParam->GetVarName(),nowLine);
385 }
[4]386 }
[75]387 }
[4]388
[75]389 //戻り値のエラーチェック
390 if( pDllProc->IsFunction() ){
391 // Function定義
[4]392
[75]393 if( pDllProc->ReturnType().IsObject() ){
394 // DLL関数ではオブジェクトを戻り値にできない
395 SetError(40,pDllProc->GetName(),nowLine);
[4]396 }
[75]397 }
[4]398
399
[75]400 /////////////////////////////////
401 // 格納位置を計算してppDeclareHashにセット
402 /////////////////////////////////
[4]403
[75]404 //ハッシュ値を取得
405 int key;
406 key=hash_default(procName);
[4]407
[75]408 extern DllProc **ppDeclareHash;
409 if(ppDeclareHash[key]){
[113]410 DllProc *pTempProc = ppDeclareHash[key];
[75]411 while(1){
[113]412 if( pTempProc->IsEqualSymbol( pDllProc->GetNamespaceScopes(), pDllProc->GetName() ) ){
[75]413 //重複エラー
414 SetError(15,procName,nowLine);
415 return;
416 }
[4]417
[75]418 if(pTempProc->pNextData==0){
419 pTempProc->pNextData=pDllProc;
420 break;
421 }
422 pTempProc=pTempProc->pNextData;
[4]423 }
[75]424 pTempProc=pTempProc->pNextData;
[4]425 }
[75]426 else{
427 ppDeclareHash[key]=pDllProc;
[4]428 }
429}
430
[206]431void UserProcs::CollectUserProcs( const BasicSource &source, UserProcs &userProcs )
432{
[4]433 extern HANDLE hHeap;
434 int i,i2,i3;
435 char temporary[8192];
436
437 //Declare(DLL関数)情報を初期化
[75]438 extern DllProc **ppDeclareHash;
439 ppDeclareHash=(DllProc **)HeapAlloc(hHeap,HEAP_ZERO_MEMORY,MAX_HASH*sizeof(DllProc *));
[4]440
441 //サブルーチン(ユーザー定義)情報を初期化
[206]442 userProcs.Clear();
[4]443
[99]444 // 名前空間管理
[199]445 NamespaceScopes &namespaceScopes = compiler.GetNamespaceSupporter().GetLivingNamespaceScopes();
[101]446 namespaceScopes.clear();
[99]447
[108]448 // Importsされた名前空間の管理
[199]449 NamespaceScopesCollection &importedNamespaces = compiler.GetNamespaceSupporter().GetImportedNamespaces();
[108]450 importedNamespaces.clear();
451
[4]452 i=-1;
453 while(1){
454 i++;
455
[206]456 if(source[i]==1&&(source[i+1]==ESC_CLASS||source[i+1]==ESC_INTERFACE)){
[4]457 /* Class ~ End Class
458 Interface ~ End Interface
459 を飛び越す */
[206]460 i3=GetEndXXXCommand(source[i+1]);
[4]461 for(i+=2,i2=0;;i++,i2++){
[206]462 if(source[i]=='\0') break;
463 if(source[i]==1&&source[i+1]==(char)i3){
[4]464 i++;
465 break;
466 }
467 }
[206]468 if(source[i]=='\0') break;
[4]469 continue;
470 }
471
[206]472 if( source[i] == 1 && source[i+1] == ESC_NAMESPACE ){
[99]473 for(i+=2,i2=0;;i2++,i++){
[206]474 if( IsCommandDelimitation( source[i] ) ){
[99]475 temporary[i2]=0;
476 break;
477 }
[206]478 temporary[i2]=source[i];
[99]479 }
480 namespaceScopes.push_back( temporary );
481
482 continue;
483 }
[206]484 else if( source[i] == 1 && source[i+1] == ESC_ENDNAMESPACE ){
[99]485 if( namespaceScopes.size() <= 0 ){
486 SetError(12, "End Namespace", i );
487 }
488 else{
489 namespaceScopes.pop_back();
490 }
491
492 i += 2;
493 continue;
494 }
[206]495 else if( source[i] == 1 && source[i+1] == ESC_IMPORTS ){
[108]496 for(i+=2,i2=0;;i2++,i++){
[206]497 if( IsCommandDelimitation( source[i] ) ){
[108]498 temporary[i2]=0;
499 break;
500 }
[206]501 temporary[i2]=source[i];
[108]502 }
[199]503 if( !compiler.GetNamespaceSupporter().ImportsNamespace( temporary ) )
[169]504 {
505 SetError(64,temporary,cp );
506 }
[99]507
[108]508 continue;
509 }
[206]510 else if( source[i] == 1 && source[i+1] == ESC_CLEARNAMESPACEIMPORTED ){
[108]511 importedNamespaces.clear();
512 continue;
513 }
514
[206]515 if(source[i]==1&&source[i+1]==ESC_DECLARE){
[4]516 for(i+=2,i2=0;;i2++,i++){
[206]517 if(source[i]=='\n'){
[4]518 temporary[i2]=0;
519 break;
520 }
[206]521 temporary[i2]=source[i];
522 if(source[i]=='\0') break;
[4]523 }
[100]524 AddDeclareData(namespaceScopes,temporary,i);
[4]525
526 continue;
527 }
[206]528 if(source[i]==1&&(source[i+1]==ESC_SUB||source[i+1]==ESC_FUNCTION||source[i+1]==ESC_MACRO)){
529 char statementChar = source[i+1];
[108]530
[4]531 for(i2=0;;i2++,i++){
[206]532 if(IsCommandDelimitation(source[i])){
[4]533 temporary[i2]=0;
534 break;
535 }
[206]536 temporary[i2]=source[i];
537 if(source[i]=='\0') break;
[4]538 }
[206]539 userProcs.Add(namespaceScopes, importedNamespaces, temporary,i,false,NULL,false);
[4]540
[108]541 /* Sub ~ End Sub
542 Function ~ End Function
543 Macro ~ End Macro
544 を飛び越す */
545 char endStatementChar = GetEndXXXCommand( statementChar );
546 for(i2=0;;i++,i2++){
[206]547 if( source[i] == '\0' ) break;
548 if( source[i] == 1 && source[i+1] == endStatementChar ){
[108]549 i++;
550 break;
551 }
552 }
[206]553 if(source[i]=='\0') break;
[4]554 continue;
555 }
556
557 //次の行
558 for(;;i++){
[206]559 if(IsCommandDelimitation(source[i])) break;
[4]560 }
[206]561 if(source[i]=='\0') break;
[4]562 }
563
564 ////////////
565 // 特殊関数
566 ////////////
[100]567 namespaceScopes.clear();
[108]568 importedNamespaces.clear();
[4]569
570 sprintf(temporary,"%c%c_allrem()",1,ESC_SUB);
[206]571 userProcs.Add( namespaceScopes, importedNamespaces, temporary,0,false,NULL,false);
[4]572
573 sprintf(temporary,"%c%c_aullrem()",1,ESC_SUB);
[206]574 userProcs.Add( namespaceScopes, importedNamespaces, temporary,0,false,NULL,false);
[4]575
576 sprintf(temporary,"%c%c_allmul()",1,ESC_SUB);
[206]577 userProcs.Add( namespaceScopes, importedNamespaces, temporary,0,false,NULL,false);
[4]578
579 sprintf(temporary,"%c%c_alldiv()",1,ESC_SUB);
[206]580 userProcs.Add( namespaceScopes, importedNamespaces, temporary,0,false,NULL,false);
[4]581
582 sprintf(temporary,"%c%c_aulldiv()",1,ESC_SUB);
[206]583 userProcs.Add( namespaceScopes, importedNamespaces, temporary,0,false,NULL,false);
[4]584
585 sprintf(temporary,"%c%c_allshl()",1,ESC_SUB);
[206]586 userProcs.Add( namespaceScopes, importedNamespaces, temporary,0,false,NULL,false);
[4]587
588 sprintf(temporary,"%c%c_allshr()",1,ESC_SUB);
[206]589 userProcs.Add( namespaceScopes, importedNamespaces, temporary,0,false,NULL,false);
[4]590
591 sprintf(temporary,"%c%c_aullshr()",1,ESC_SUB);
[206]592 userProcs.Add( namespaceScopes, importedNamespaces, temporary,0,false,NULL,false);
[4]593
594 sprintf(temporary,"%c%c_System_InitStaticLocalVariables()",1,ESC_SUB);
[206]595 userProcs.Add( namespaceScopes, importedNamespaces, temporary,0,false,NULL,false);
[4]596}
[75]597void Delete_di(DllProc *pDllProc){
598 if(pDllProc->pNextData) Delete_di(pDllProc->pNextData);
[4]599
[75]600 delete pDllProc;
[4]601}
602void DeleteDeclareInfo(void){
603 //DLL情報を解放
[75]604 extern DllProc **ppDeclareHash;
[4]605 int i;
606 for(i=0;i<MAX_HASH;i++){
607 if(!ppDeclareHash[i]) continue;
608
609 Delete_di(ppDeclareHash[i]);
610 }
611 HeapDefaultFree(ppDeclareHash);
612}
613
[94]614bool IsNeedProcCompile(){
[206]615 compiler.GetMeta().GetUserProcs().Iterator_Reset();
616 while( compiler.GetMeta().GetUserProcs().Iterator_HasNext() )
617 {
618 UserProc *pUserProc = compiler.GetMeta().GetUserProcs().Iterator_GetNext();
619 if( pUserProc->IsUsing() && pUserProc->IsCompiled() == false ){
620 return true;
[94]621 }
622 }
623 return false;
624}
Note: See TracBrowser for help on using the repository browser.