source: dev/trunk/ab5.0/abdev/BasicCompiler_Common/Subroutine.cpp@ 465

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

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

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