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

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

関数パラメータに指定されたジェネリクスの型パラメータ解決に失敗してしまう不具合を修正。
また、エラー行番号がソースコード内の無関係な位置を指し示してしまう不具合を修正。

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