source: dev/trunk/ab5.0/abdev/BasicCompiler_Common/src/Procedure.cpp@ 456

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

共変戻り値のオーバーロードをサポートした。

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