source: dev/trunk/abdev/BasicCompiler_Common/src/Procedure.cpp@ 382

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

ジェネリクスインターフェイス実装時のオーバーロード解決ロジックを改良。(型パラメータを戻り値に持つメソッドのオーバーロードをミスしてしまうバグを修正)

File size: 25.8 KB
Line 
1#include "stdafx.h"
2
3#include <jenga/include/smoothie/Smoothie.h>
4#include <jenga/include/smoothie/SmoothieException.h>
5#include <jenga/include/smoothie/LexicalAnalysis.h>
6
7#include <Compiler.h>
8#include <Procedure.h>
9#include <NamespaceSupporter.h>
10
11#include "../common.h"
12#ifdef _AMD64_
13#include "../../BasicCompiler64/opcode.h"
14#else
15#include "../../BasicCompiler32/opcode.h"
16#endif
17
18
19bool UserProc::IsEqualForOverride( const Types &actualTypeParametersForThisProc, const UserProc *pUserProc ) const
20{
21 if( this->GetName() == pUserProc->GetName() // 名前空間及び名前が等しい
22 && this->Params().Equals( pUserProc->Params() ) ) // パラメータが等しい
23 {
24 if( this->returnType.Equals( pUserProc->returnType ) )
25 {
26 // 戻り値が等しい
27 return true;
28 }
29
30 if( this->returnType.IsTypeParameter() )
31 {
32 // 型パラメータだったとき
33 if( actualTypeParametersForThisProc[this->returnType.GetFormalTypeIndex()].Equals( pUserProc->returnType ) )
34 {
35 // 戻り値が等しい
36 return true;
37 }
38 }
39 }
40 return false;
41}
42
43
44std::string UserProc::GetFullName() const
45{
46 if( HasParentClass() ){
47 return GetParentClass().GetName() + "." + GetName();
48 }
49
50 return GetName();
51}
52bool UserProc::IsCastOperator() const
53{
54 if( GetName()[0] == 1 && GetName()[1] == ESC_OPERATOR && GetName()[2] == CALC_AS )
55 {
56 return true;
57 }
58 return false;
59}
60const NamespaceScopes &UserProc::GetNamespaceScopes() const
61{
62 if( HasParentClass() ){
63 return GetParentClassPtr()->GetNamespaceScopes();
64 }
65 return Symbol::GetNamespaceScopes();
66}
67const NamespaceScopesCollection &UserProc::GetImportedNamespaces() const
68{
69 if( pParentClass )
70 {
71 return pParentClass->GetImportedNamespaces();
72 }
73 return importedNamespaces;
74}
75bool UserProc::IsVirtual() const
76{
77 if( pMethod == NULL ){
78 return false;
79 }
80 return ( pMethod->IsVirtual() != 0 );
81}
82const CMethod &UserProc::GetMethod() const
83{
84 if( !HasParentClass() )
85 {
86 Jenga::Throw( "グローバル関数に対してUserProc::GetMethodメソッドが呼ばれた" );
87 }
88 return *pMethod;
89}
90
91bool UserProc::SetParamsAndReturnType( const char *sourceOfParams, int nowLine, bool isStatic ){
92 int i = 0;
93 int i2,i3,sw;
94 char temporary[8192],temp2[VN_SIZE];
95
96 //ソースコードの位置
97 this->codePos = nowLine;
98
99 //パラメータ
100 if(sourceOfParams[i]!='('){
101 SmoothieException::Throw(1,NULL,nowLine);
102 return 0;
103 }
104 i++;
105 if(sourceOfParams[i]!=')'&& this->pParentClass ){
106 //クラスのメンバ関数の場合のみ、デストラクタにパラメータがある場合にエラーをだす
107 if(this->GetName()[0]=='~'){
108 SmoothieException::Throw(114,NULL,nowLine);
109 i=JumpStringInPare(sourceOfParams,i);
110 }
111 }
112 while(1){
113 if(sourceOfParams[i]==')') break;
114
115 //ByRef
116 bool isRef;
117 if(sourceOfParams[i]==1&&sourceOfParams[i+1]==ESC_BYVAL){
118 isRef = false;
119 i+=2;
120 }
121 else if(sourceOfParams[i]==1&&sourceOfParams[i+1]==ESC_BYREF){
122 isRef = true;
123 i+=2;
124 }
125 else isRef = false;
126
127 //パラメータ名
128 bool isArray = false;
129 Subscripts subscripts;
130 char name[VN_SIZE];
131 sw=0;
132 for(i2=0;;i++,i2++){
133 if(sourceOfParams[i]=='('){
134 if(!sw) sw=1;
135
136 i3=GetStringInPare(name+i2,sourceOfParams+i);
137 i2+=i3-1;
138 i+=i3-1;
139 continue;
140 }
141 if(sourceOfParams[i]=='['){
142 if(!sw) sw=1;
143
144 i3=GetStringInBracket(name+i2,sourceOfParams+i);
145 i2+=i3-1;
146 i+=i3-1;
147 continue;
148 }
149 if(!IsVariableChar(sourceOfParams[i])){
150 name[i2]=0;
151 break;
152 }
153 name[i2]=sourceOfParams[i];
154 }
155 if(sw){
156 //配列パラメータ
157 if( isRef == false ) SmoothieException::Throw(29,NULL,nowLine);
158 isArray = true;
159
160 if((name[i2-2]=='('&&name[i2-1]==')')||
161 (name[i2-2]=='['&&name[i2-1]==']'))
162 {
163 subscripts.push_back( LONG_MAX );
164
165 name[i2-2]=0;
166 }
167 else{
168 GetArrange(name,temp2,subscripts);
169 lstrcpy(name,temp2);
170 }
171
172 i2=lstrlen(name);
173 }
174
175 Type type( DEF_NON );
176 char initValue[8192] = "";
177 if( sourceOfParams[i] == '=' ){
178 i++;
179 i = GetOneParameter( sourceOfParams, i, initValue );
180
181 // TODO: エラー用 fix me!!!
182 //cp = nowLine;
183
184 NumOpe_GetType( initValue, GetStringTypeInfo(), type );
185
186 if( IS_LITERAL(type.GetIndex()) )
187 {
188 type.SetIndex( -1 );
189 }
190 }
191 else if(sourceOfParams[i]==1&&sourceOfParams[i+1]==ESC_AS){
192 // As指定
193 i+=2;
194
195 i2=0;
196 while(sourceOfParams[i]=='*'){
197 temporary[i2]=sourceOfParams[i];
198 i++;
199 i2++;
200 }
201 for(;;i++,i2++){
202 if(!IsVariableChar(sourceOfParams[i])){
203 if(sourceOfParams[i]==1&&(sourceOfParams[i+1]==ESC_FUNCTION||sourceOfParams[i+1]==ESC_SUB)){
204 temporary[i2++]=sourceOfParams[i++];
205 temporary[i2]=sourceOfParams[i];
206 continue;
207 }
208 temporary[i2]=0;
209 break;
210 }
211 temporary[i2]=sourceOfParams[i];
212 }
213
214 compiler.StringToType( temporary, type );
215
216 if( type.IsNull() ){
217 SmoothieException::Throw(3,temporary,nowLine);
218 type.SetBasicType( DEF_PTR_VOID );
219 }
220
221 if( type.IsObject() ){
222 if( type.GetClass().IsBlittableType() ){
223 // Blittable型のときは基本型として扱う
224 type = type.GetClass().GetBlittableType();
225 }
226 }
227 }
228 else{
229 type.SetBasicType( Type::GetBasicTypeFromSimpleName(temporary) );
230 SmoothieException::Throw(-103,temporary,nowLine);
231 }
232
233 Parameter *pParam = new Parameter( name, type, isRef, initValue );
234 if( isArray ){
235 pParam->SetArray( subscripts );
236 }
237
238 //パラメータを追加
239 this->params.push_back( pParam );
240
241 if(sourceOfParams[i]==','){
242 i++;
243 continue;
244 }
245 else if(sourceOfParams[i]==')') continue;
246 else{
247 SmoothieException::Throw(1,NULL,nowLine);
248 break;
249 }
250 }
251 this->secondParmNum = (int)this->params.size();
252 i++;
253 if(sourceOfParams[i]=='('){
254 i++;
255 while(1){
256 if(sourceOfParams[i]==')') break;
257
258 //ByRef
259 bool isRef;
260 if(sourceOfParams[i]==1&&sourceOfParams[i+1]==ESC_BYVAL){
261 isRef = false;
262 i+=2;
263 }
264 else if(sourceOfParams[i]==1&&sourceOfParams[i+1]==ESC_BYREF){
265 isRef = true;
266 i+=2;
267 }
268 else isRef = false;
269
270 //パラメータ名
271 bool isArray = false;
272 Subscripts subscripts;
273 char name[VN_SIZE];
274 sw=0;
275 for(i2=0;;i++,i2++){
276 if(sourceOfParams[i]=='('){
277 if(!sw) sw=1;
278
279 i3=GetStringInPare(name+i2,sourceOfParams+i);
280 i2+=i3-1;
281 i+=i3-1;
282 continue;
283 }
284 if(sourceOfParams[i]=='['){
285 if(!sw) sw=1;
286
287 i3=GetStringInBracket(name+i2,sourceOfParams+i);
288 i2+=i3-1;
289 i+=i3-1;
290 continue;
291 }
292 if(!IsVariableChar(sourceOfParams[i])){
293 name[i2]=0;
294 break;
295 }
296 name[i2]=sourceOfParams[i];
297 }
298 if(sw){
299 //配列パラメータ
300 if( isRef == false ) SmoothieException::Throw(29,NULL,nowLine);
301 isArray = true;
302
303 if((name[i2-2]=='('&&name[i2-1]==')')||
304 (name[i2-2]=='['&&name[i2-1]==']'))
305 {
306 subscripts.push_back( LONG_MAX );
307
308 name[i2-2]=0;
309 }
310 else{
311 GetArrange(name,temp2,subscripts);
312 lstrcpy(name,temp2);
313 }
314
315 i2=lstrlen(name);
316 }
317
318 //型
319 Type type( DEF_NON );
320 if(sourceOfParams[i]==1&&sourceOfParams[i+1]==ESC_AS){
321 i+=2;
322
323 i2=0;
324 while(sourceOfParams[i]=='*'){
325 temporary[i2]=sourceOfParams[i];
326 i++;
327 i2++;
328 }
329 for(;;i++,i2++){
330 if(!IsVariableChar(sourceOfParams[i])){
331 if(sourceOfParams[i]==1&&(sourceOfParams[i+1]==ESC_FUNCTION||sourceOfParams[i+1]==ESC_SUB)){
332 temporary[i2++]=sourceOfParams[i++];
333 temporary[i2]=sourceOfParams[i];
334 continue;
335 }
336 temporary[i2]=0;
337 break;
338 }
339 temporary[i2]=sourceOfParams[i];
340 }
341
342 compiler.StringToType( temporary, type );
343
344 if( type.IsNull() ){
345 SmoothieException::Throw(3,temporary,nowLine);
346 type.SetBasicType( DEF_PTR_VOID );
347 }
348 }
349 else{
350 type.SetBasicType( Type::GetBasicTypeFromSimpleName(temporary) );
351 SmoothieException::Throw(-103,temporary,nowLine);
352 }
353
354 Parameter *pParam = new Parameter( name, type, isRef );
355 if( isArray ){
356 pParam->SetArray( subscripts );
357 }
358
359 //パラメータを追加
360 this->params.push_back( pParam );
361
362 if(sourceOfParams[i]==','){
363 i++;
364 continue;
365 }
366 else if(sourceOfParams[i]==')') continue;
367 else{
368 SmoothieException::Throw(1,NULL,nowLine);
369 break;
370 }
371 }
372 i++;
373 }
374
375 if(sourceOfParams[i]){
376 ///////////////////
377 // 戻り値を取得
378 ///////////////////
379
380 if( !this->IsFunction() ){
381 // Sub/Macroの場合
382 SmoothieException::Throw(38,this->GetName(),nowLine);
383 }
384
385 if( this->pParentClass ){
386 if( this->GetName() == this->pParentClass->GetName() ||
387 this->GetName()[0]=='~'){
388 //クラスのコンストラクタ、デストラクタがFunction定義の場合はエラーをだす
389 SmoothieException::Throw(115,NULL,nowLine);
390 }
391 }
392
393
394 i2=lstrlen(sourceOfParams)-2;
395
396 int sw_as=0;
397 for(;i2>0;i2--){
398 if(sourceOfParams[i2]==')') break;
399
400 if(sourceOfParams[i2]==1&&sourceOfParams[i2+1]==ESC_AS){
401 i2+=2;
402 i3=0;
403 while(sourceOfParams[i2]=='*') temporary[i3++]=sourceOfParams[i2++];
404 for(;;i2++,i3++){
405 if( IsCommandDelimitation( sourceOfParams[i2] ) )
406 {
407 temporary[i3]=0;
408 break;
409 }
410 temporary[i3]=sourceOfParams[i2];
411 }
412 compiler.StringToType( temporary, this->returnType );
413 if( this->returnType.IsNull() ) SmoothieException::Throw(3,temporary,nowLine);
414
415 sw_as=1;
416 break;
417 }
418 }
419
420 if(!sw_as){
421 SmoothieException::Throw(-104,this->GetName().c_str(),nowLine);
422
423 this->returnType.SetBasicType( DEF_DOUBLE );
424 }
425 }
426 else{
427 //戻り値なしのSub定義
428 this->returnType.SetNull();
429 }
430
431 //リアルパラメータ領域を取得(_System_LocalThisを考慮して2つだけ多く確保する場合がある)
432
433 if( this->pParentClass && isStatic == false ){
434 //オブジェクトメンバの場合は、第一パラメータを_System_LocalThis引き渡し用として利用
435 string name = "_System_LocalThis";
436 Type type( DEF_PTR_VOID );
437 this->realParams.push_back( new Parameter( name, type ) );
438 }
439
440 if( this->returnType.IsStruct() ){
441 //構造体を戻り値として持つ場合
442 //※第一パラメータ(Thisポインタありの場合は第二パラメータ)を戻り値用の参照宣言にする
443
444 string name = this->GetName();
445 if(name[0]==1&&name[1]==ESC_OPERATOR){
446 name="_System_ReturnValue";
447 }
448 Type type( DEF_STRUCT, this->returnType.GetIndex() );
449 this->realParams.push_back( new Parameter( name, type, true ) );
450 }
451
452 //パラメータをコピー
453 BOOST_FOREACH( Parameter *pParam, params ){
454 this->realParams.push_back( new Parameter( *pParam ) );
455 }
456
457 return true;
458}
459
460const UserProc *UserProc::pCompilingUserProc = NULL;
461const UserProc *UserProc::pGlobalProc = NULL;
462
463
464bool UserProcs::Insert( UserProc *pUserProc, int nowLine )
465{
466 /////////////////////////////////
467 // ハッシュデータに追加
468 /////////////////////////////////
469
470 if( !Put( pUserProc ) )
471 {
472 // 重複しているため、失敗
473 SetError(15,pUserProc->GetName().c_str(),nowLine);
474 return false;
475 }
476
477 return true;
478}
479UserProc *UserProcs::AddUserProc( const NamespaceScopes &namespaceScopes, const NamespaceScopesCollection &importedNamespaces, char *buffer,int nowLine,bool isVirtual,CClass *pobj_c, bool isStatic, char *interfaceName )
480{
481 int i2,i3;
482 char temporary[8192];
483
484 int i=1;
485
486 Procedure::Kind kind = Procedure::Sub;
487 bool isMacro = false;
488 if(buffer[i]==ESC_FUNCTION) kind = Procedure::Function;
489 if(buffer[i]==ESC_MACRO){
490 isMacro = true;
491 }
492
493 i++;
494
495 bool isCdecl = false;
496 bool isExport = false;
497 while(1){
498 if(buffer[i]==1&&buffer[i+1]==ESC_CDECL&& isCdecl == false ){
499 isCdecl = true;
500
501 i+=2;
502 }
503 else if(buffer[i]==1&&buffer[i+1]==ESC_EXPORT&& isExport == false ){
504 isExport = true;
505
506 i+=2;
507 }
508 else break;
509 }
510
511 i2=0;
512 if(buffer[i]==1&&buffer[i+1]==ESC_OPERATOR){
513 if(!pobj_c){
514 SetError(126,NULL,nowLine);
515 return 0;
516 }
517
518 //オペレータの場合
519 temporary[i2++]=buffer[i++];
520 temporary[i2++]=buffer[i++];
521
522 int iCalcId;
523 if(buffer[i]=='='&&buffer[i+1]=='='){
524 iCalcId=CALC_EQUAL;
525 i3=2;
526 }
527 else if(buffer[i]=='='){
528 iCalcId=CALC_SUBSITUATION;
529 i3=1;
530 }
531 else if(buffer[i]=='('){
532 iCalcId=CALC_AS;
533 i3=0;
534 }
535 else if(buffer[i]=='['&&buffer[i+1]==']'&&buffer[i+2]=='='){
536 iCalcId=CALC_ARRAY_SET;
537 i3=3;
538 }
539 else if(buffer[i]=='['&&buffer[i+1]==']'){
540 iCalcId=CALC_ARRAY_GET;
541 i3=2;
542 }
543 else{
544 iCalcId=GetCalcId(buffer+i,&i3);
545 i3++;
546 }
547 if(!iCalcId){
548 SetError(1,NULL,nowLine);
549 return 0;
550 }
551 temporary[i2++]=iCalcId;
552 temporary[i2]=0;
553
554 i+=i3;
555 }
556 else{
557 if(pobj_c){
558 //クラスメンバの場合、デストラクタには~が付くことを考慮
559 if(buffer[i]=='~'){
560 temporary[i2]='~';
561 i++;
562 i2++;
563 }
564 }
565
566 for(;;i++,i2++){
567 if(!IsVariableChar(buffer[i])){
568 temporary[i2]=0;
569 break;
570 }
571 temporary[i2]=buffer[i];
572 }
573
574 char parentName[VN_SIZE], memberName[VN_SIZE];
575 ReferenceKind refKind;
576 if( SplitMemberName( temporary, parentName, memberName, refKind ) )
577 {
578 if( pobj_c )
579 {
580 if( interfaceName )
581 {
582 lstrcpy( interfaceName, parentName );
583 }
584 else
585 {
586 SetError();
587 return NULL;
588 }
589
590 char dummyMemberName[VN_SIZE];
591 if( SplitMemberName( memberName, parentName, dummyMemberName, refKind ) )
592 {
593 SetError(69,temporary,nowLine);
594 return NULL;
595 }
596 }
597 else
598 {
599 SetError(68,temporary,nowLine);
600 return NULL;
601 }
602
603 lstrcpy( temporary, memberName );
604 }
605 }
606
607 if( isMacro ){
608 //大文字に変換
609 CharUpper(temporary);
610
611 //マクロ関数の場合は名前リストに追加
612 macroNames.push_back( temporary );
613 }
614
615 if(!pobj_c){
616 //クラスメンバ以外の場合のみ
617 //重複チェック
618
619 if(GetDeclareHash(temporary)){
620 SetError(15,temporary,nowLine);
621 return 0;
622 }
623 }
624
625 // 識別ID
626 static int id_base=0;
627
628 UserProc *pUserProc = new UserProc( namespaceScopes, importedNamespaces, temporary, kind, isMacro, isCdecl, isExport, (id_base++) );
629 pUserProc->SetParentClass( pobj_c );
630 if( Smoothie::isFullCompile ){
631 // すべての関数・メソッドをコンパイルする
632 pUserProc->Using();
633 }
634
635 // 親インターフェイスをセット
636 if( interfaceName && interfaceName[0] )
637 {
638 ::Interface *pTargetInterface = NULL;
639 BOOST_FOREACH( ::Interface *pInterface, pobj_c->GetInterfaces() )
640 {
641 if( pInterface->GetClass().GetName() == interfaceName )
642 {
643 pTargetInterface = pInterface;
644 break;
645 }
646 }
647 pUserProc->SetInterface( pTargetInterface );
648 }
649
650 if(isExport){
651 pUserProc->Using();
652 }
653
654 // パラメータを解析
655 // ※第1パラメータにに指定するデータの例:"( s As String ) As String"
656 pUserProc->SetParamsAndReturnType( buffer + i, nowLine, isStatic );
657
658 pUserProc->_paramStr = buffer + i;
659
660 // ハッシュに追加
661 if( !Insert( pUserProc, nowLine ) )
662 {
663 return NULL;
664 }
665
666 return pUserProc;
667}
668void UserProcs::EnumGlobalProcs( const char *simpleName, const char *localName, std::vector<const UserProc *> &subs )
669{
670 ///////////////////////////
671 // グローバル関数を検索
672 ///////////////////////////
673
674 // ハッシュ値を取得
675 UserProc *pUserProc = GetHashArrayElement( simpleName );
676 while(pUserProc){
677 if( pUserProc->IsGlobalProcedure() ){
678 if( pUserProc->IsEqualSymbol( localName ) ){
679 subs.push_back( pUserProc );
680 }
681 }
682
683 pUserProc=pUserProc->GetChainNext();
684 }
685}
686
687bool DllProc::SetParamsAndReturnType( const char *sourceOfParams, int nowLine ){
688 int i = 0;
689 int i2,i3,sw;
690 char temporary[8192],temp2[VN_SIZE];
691
692 //ソースコードの位置
693 this->codePos = nowLine;
694
695 //パラメータ
696 if(sourceOfParams[i]!='('){
697 SmoothieException::Throw(1,NULL,nowLine);
698 return 0;
699 }
700 i++;
701
702 while(1){
703 if(sourceOfParams[i]==')') break;
704
705 //ByRef
706 bool isRef;
707 if(sourceOfParams[i]==1&&sourceOfParams[i+1]==ESC_BYVAL){
708 isRef = false;
709 i+=2;
710 }
711 else if(sourceOfParams[i]==1&&sourceOfParams[i+1]==ESC_BYREF){
712 isRef = true;
713 i+=2;
714 }
715 else isRef = false;
716
717 //パラメータ名
718 bool isArray = false;
719 Subscripts subscripts;
720 char name[VN_SIZE];
721 sw=0;
722 for(i2=0;;i++,i2++){
723 if(sourceOfParams[i]=='('){
724 if(!sw) sw=1;
725
726 i3=GetStringInPare(name+i2,sourceOfParams+i);
727 i2+=i3-1;
728 i+=i3-1;
729 continue;
730 }
731 if(sourceOfParams[i]=='['){
732 if(!sw) sw=1;
733
734 i3=GetStringInBracket(name+i2,sourceOfParams+i);
735 i2+=i3-1;
736 i+=i3-1;
737 continue;
738 }
739 if(!IsVariableChar(sourceOfParams[i])){
740 name[i2]=0;
741 break;
742 }
743 name[i2]=sourceOfParams[i];
744 }
745 if(sw){
746 //配列パラメータ
747 if( isRef == false ) SmoothieException::Throw(29,NULL,nowLine);
748 isArray = true;
749
750 if((name[i2-2]=='('&&name[i2-1]==')')||
751 (name[i2-2]=='['&&name[i2-1]==']'))
752 {
753 subscripts.push_back( LONG_MAX );
754
755 name[i2-2]=0;
756 }
757 else{
758 GetArrange(name,temp2,subscripts);
759 lstrcpy(name,temp2);
760 }
761
762 i2=lstrlen(name);
763 }
764
765 //型
766 Type type( DEF_NON );
767 if(lstrcmp(name,"...")==0) type.SetBasicType( DEF_ELLIPSE );
768 else if(sourceOfParams[i]==1&&sourceOfParams[i+1]==ESC_AS){
769 i+=2;
770
771 i2=0;
772 while(sourceOfParams[i]=='*'){
773 temporary[i2]=sourceOfParams[i];
774 i++;
775 i2++;
776 }
777 for(;;i++,i2++){
778 if(!IsVariableChar(sourceOfParams[i])){
779 if(sourceOfParams[i]==1&&(sourceOfParams[i+1]==ESC_FUNCTION||sourceOfParams[i+1]==ESC_SUB)){
780 temporary[i2++]=sourceOfParams[i++];
781 temporary[i2]=sourceOfParams[i];
782 continue;
783 }
784 temporary[i2]=0;
785 break;
786 }
787 temporary[i2]=sourceOfParams[i];
788 }
789
790 compiler.StringToType( temporary, type );
791
792 if( type.IsNull() ){
793 SmoothieException::Throw(3,temporary,nowLine);
794 type.SetBasicType( DEF_PTR_VOID );
795 }
796 }
797 else{
798 type.SetBasicType( Type::GetBasicTypeFromSimpleName(temporary) );
799 SmoothieException::Throw(-103,temporary,nowLine);
800 }
801
802 Parameter *pParam = new Parameter( name, type, isRef );
803 if( isArray ){
804 pParam->SetArray( subscripts );
805 }
806
807 //パラメータを追加
808 this->params.push_back( pParam );
809
810 if(sourceOfParams[i]==','){
811 i++;
812 continue;
813 }
814 else if(sourceOfParams[i]==')') continue;
815 else{
816 SmoothieException::Throw(1,NULL,nowLine);
817 break;
818 }
819 }
820 i++;
821
822 if(sourceOfParams[i]){
823 ///////////////////
824 // 戻り値を取得
825 ///////////////////
826
827 i2=lstrlen(sourceOfParams)-2;
828
829 int sw_as=0;
830 for(;i2>0;i2--){
831 if(sourceOfParams[i2]==')') break;
832
833 if(sourceOfParams[i2]==1&&sourceOfParams[i2+1]==ESC_AS){
834 i2+=2;
835 i3=0;
836 while(sourceOfParams[i2]=='*') temporary[i3++]=sourceOfParams[i2++];
837 for(;;i2++,i3++){
838 if(!IsVariableChar(sourceOfParams[i2])){
839 temporary[i3]=0;
840 break;
841 }
842 temporary[i3]=sourceOfParams[i2];
843 }
844 compiler.StringToType( temporary, this->returnType );
845 if( this->returnType.IsNull() ) SmoothieException::Throw(3,temporary,nowLine);
846
847 sw_as=1;
848 break;
849 }
850 }
851 }
852 else{
853 //戻り値なしのSub定義
854 this->returnType.SetNull();
855 }
856
857 return true;
858}
859
860void DllProcs::Add(const NamespaceScopes &namespaceScopes, char *buffer,int nowLine){
861 int i2;
862
863 int i=0;
864
865 //Sub/Function
866 Procedure::Kind kind = Procedure::Sub;
867 if(buffer[i]==ESC_SUB){
868 }
869 else if(buffer[i]==ESC_FUNCTION){
870 kind = Procedure::Function;
871 }
872 else{
873 SetError(1,NULL,nowLine);
874 return;
875 }
876 i++;
877
878 //プロシージャ名
879 char procName[VN_SIZE];
880 bool isCdecl = false;
881 for(i2=0;;i++,i2++){
882 if(buffer[i]==1&&buffer[i+1]==ESC_CDECL){
883 isCdecl = true;
884
885 i+=2;
886 procName[i2]=0;
887 break;
888 }
889 if(buffer[i]==','){
890 procName[i2]=0;
891 break;
892 }
893 if(buffer[i]=='\0'){
894 SetError(1,NULL,nowLine);
895 return;
896 }
897 procName[i2]=buffer[i];
898 }
899 i++;
900
901 //ユーザー定義関数との重複チェック
902 if(GetSubHash(procName)){
903 SetError(15,procName,nowLine);
904 return;
905 }
906
907
908 //ライブラリ
909 char dllFileName[MAX_PATH];
910 i = GetOneParameter( buffer, i, dllFileName );
911 Type resultType;
912 _int64 i64data;
913 if( !StaticCalculation( true, dllFileName, 0, &i64data, resultType ) ){
914 return;
915 }
916 if( resultType.GetBasicType() != typeOfPtrChar ){
917 SetError(1,NULL,nowLine);
918 return;
919 }
920 lstrcpy( dllFileName, (char *)i64data );
921 CharUpper(dllFileName);
922 if(!strstr(dllFileName,".")){
923 lstrcat(dllFileName,".DLL");
924 if(lstrlen(dllFileName)>=16){
925 SetError(7,NULL,nowLine);
926 return;
927 }
928 }
929
930 //エイリアス
931 char alias[VN_SIZE];
932 i = GetOneParameter( buffer, i, alias );
933 if( alias[0] ){
934 if( !StaticCalculation( true, alias, 0, &i64data, resultType ) ){
935 return;
936 }
937 if( resultType.GetBasicType() != typeOfPtrChar ){
938 SetError(1,NULL,nowLine);
939 return;
940 }
941 lstrcpy( alias, (char *)i64data );
942 }
943 else{
944 //省略されたときは関数名
945 lstrcpy( alias, procName );
946 }
947
948
949 // オブジェクトを生成
950 DllProc *pDllProc = new DllProc( namespaceScopes, procName, kind, isCdecl, dllFileName, alias );
951
952 // パラメータを解析
953 // ※第1パラメータにに指定するデータの例:"( s As String ) As String"
954 pDllProc->SetParamsAndReturnType( buffer + i, nowLine );
955
956 // パラメータのエラーチェック
957 BOOST_FOREACH( const Parameter *pParam, pDllProc->Params() ){
958 if( pParam->IsObject() ){
959 SetError(25,pParam->GetVarName(),nowLine);
960 }
961 if( !pParam->IsRef() ){
962 if( pParam->IsStruct() ){
963 SetError(28,pParam->GetVarName(),nowLine);
964 }
965 }
966 }
967
968 //戻り値のエラーチェック
969 if( pDllProc->IsFunction() ){
970 // Function定義
971
972 if( pDllProc->ReturnType().IsObject() ){
973 // DLL関数ではオブジェクトを戻り値にできない
974 SetError(40,pDllProc->GetName(),nowLine);
975 }
976 }
977
978 // ハッシュマップに追加
979 this->Put( pDllProc );
980}
981
982bool ProcPointer::SetParamsAndReturnType( const char *sourceOfParams, int nowLine ){
983 int i = 0;
984 int i2,i3,sw;
985 char temporary[8192],temp2[VN_SIZE];
986
987 //ソースコードの位置
988 this->codePos = nowLine;
989
990 //パラメータ
991 if(sourceOfParams[i]!='('){
992 SmoothieException::Throw(1,NULL,nowLine);
993 return 0;
994 }
995 i++;
996 while(1){
997 if(sourceOfParams[i]==')') break;
998
999 //ByRef
1000 bool isRef;
1001 if(sourceOfParams[i]==1&&sourceOfParams[i+1]==ESC_BYVAL){
1002 isRef = false;
1003 i+=2;
1004 }
1005 else if(sourceOfParams[i]==1&&sourceOfParams[i+1]==ESC_BYREF){
1006 isRef = true;
1007 i+=2;
1008 }
1009 else isRef = false;
1010
1011 //パラメータ名
1012 bool isArray = false;
1013 Subscripts subscripts;
1014 char name[VN_SIZE];
1015 sw=0;
1016 for(i2=0;;i++,i2++){
1017 if(sourceOfParams[i]=='('){
1018 if(!sw) sw=1;
1019
1020 i3=GetStringInPare(name+i2,sourceOfParams+i);
1021 i2+=i3-1;
1022 i+=i3-1;
1023 continue;
1024 }
1025 if(sourceOfParams[i]=='['){
1026 if(!sw) sw=1;
1027
1028 i3=GetStringInBracket(name+i2,sourceOfParams+i);
1029 i2+=i3-1;
1030 i+=i3-1;
1031 continue;
1032 }
1033 if(!IsVariableChar(sourceOfParams[i])){
1034 name[i2]=0;
1035 break;
1036 }
1037 name[i2]=sourceOfParams[i];
1038 }
1039 if(sw){
1040 //配列パラメータ
1041 if( isRef == false ) SmoothieException::Throw(29,NULL,nowLine);
1042 isArray = true;
1043
1044 if((name[i2-2]=='('&&name[i2-1]==')')||
1045 (name[i2-2]=='['&&name[i2-1]==']'))
1046 {
1047 subscripts.push_back( LONG_MAX );
1048
1049 name[i2-2]=0;
1050 }
1051 else{
1052 GetArrange(name,temp2,subscripts);
1053 lstrcpy(name,temp2);
1054 }
1055
1056 i2=lstrlen(name);
1057 }
1058
1059 //型
1060 Type type( DEF_NON );
1061 if(sourceOfParams[i]==1&&sourceOfParams[i+1]==ESC_AS){
1062 i+=2;
1063
1064 i2=0;
1065 while(sourceOfParams[i]=='*'){
1066 temporary[i2]=sourceOfParams[i];
1067 i++;
1068 i2++;
1069 }
1070 for(;;i++,i2++){
1071 if(!IsVariableChar(sourceOfParams[i])){
1072 if(sourceOfParams[i]==1&&(sourceOfParams[i+1]==ESC_FUNCTION||sourceOfParams[i+1]==ESC_SUB)){
1073 temporary[i2++]=sourceOfParams[i++];
1074 temporary[i2]=sourceOfParams[i];
1075 continue;
1076 }
1077 temporary[i2]=0;
1078 break;
1079 }
1080 temporary[i2]=sourceOfParams[i];
1081 }
1082
1083 compiler.StringToType( temporary, type );
1084
1085 if( type.IsNull() ){
1086 SmoothieException::Throw(3,temporary,nowLine);
1087 type.SetBasicType( DEF_PTR_VOID );
1088 }
1089 }
1090 else{
1091 type.SetBasicType( Type::GetBasicTypeFromSimpleName(temporary) );
1092 SmoothieException::Throw(-103,temporary,nowLine);
1093 }
1094
1095 Parameter *pParam = new Parameter( name, type, isRef );
1096 if( isArray ){
1097 pParam->SetArray( subscripts );
1098 }
1099
1100 //パラメータを追加
1101 this->params.push_back( pParam );
1102
1103 if(sourceOfParams[i]==','){
1104 i++;
1105 continue;
1106 }
1107 else if(sourceOfParams[i]==')') continue;
1108 else{
1109 SmoothieException::Throw(1,NULL,nowLine);
1110 break;
1111 }
1112 }
1113 i++;
1114
1115 if(sourceOfParams[i]){
1116 ///////////////////
1117 // 戻り値を取得
1118 ///////////////////
1119
1120 i2=lstrlen(sourceOfParams)-2;
1121
1122 int sw_as=0;
1123 for(;i2>0;i2--){
1124 if(sourceOfParams[i2]==')') break;
1125
1126 if(sourceOfParams[i2]==1&&sourceOfParams[i2+1]==ESC_AS){
1127 i2+=2;
1128 i3=0;
1129 while(sourceOfParams[i2]=='*') temporary[i3++]=sourceOfParams[i2++];
1130 for(;;i2++,i3++){
1131 if(!IsVariableChar(sourceOfParams[i2])){
1132 temporary[i3]=0;
1133 break;
1134 }
1135 temporary[i3]=sourceOfParams[i2];
1136 }
1137 compiler.StringToType( temporary, this->returnType );
1138 if( this->returnType.IsNull() ) SmoothieException::Throw(3,temporary,nowLine);
1139
1140 sw_as=1;
1141 break;
1142 }
1143 }
1144 }
1145 else{
1146 //戻り値なしのSub定義
1147 this->returnType.SetNull();
1148 }
1149
1150 //戻り値のエラーチェック
1151 if( IsFunction() ){
1152 // Function定義
1153
1154 if( this->ReturnType().IsNull() ){
1155 // 戻り値がない
1156 SmoothieException::Throw(26,this->GetName(),nowLine);
1157 }
1158 }
1159 else{
1160 if( !this->ReturnType().IsNull() ){
1161 // Sub定義なのに、戻り値がある
1162 SmoothieException::Throw(38,this->GetName(),nowLine);
1163 }
1164 }
1165
1166 return true;
1167}
1168
1169int ProcPointers::Add( const string &typeExpression )
1170{
1171 DWORD dwProcType = (DWORD)typeExpression[2];
1172 const string &paramStr = typeExpression.substr( 3 );
1173
1174 Procedure::Kind kind = Procedure::Sub;
1175 if( dwProcType == ESC_FUNCTION ){
1176 kind = Procedure::Function;
1177 }
1178
1179 ProcPointer *pProcPointer = new ProcPointer( kind );
1180
1181 //buffer[0]は'('となっている
1182 extern int cp;
1183 pProcPointer->SetParamsAndReturnType( paramStr.c_str(), cp );
1184
1185 this->push_back( pProcPointer );
1186
1187 return (int)this->size()-1;
1188}
1189
1190void ProcPointers::Clear()
1191{
1192 ProcPointers &procPointers = *this;
1193 BOOST_FOREACH( ProcPointer *pProcPointer, procPointers ){
1194 delete pProcPointer;
1195 }
1196 this->clear();
1197}
Note: See TracBrowser for help on using the repository browser.