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

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

SmootheException::Throw → SetError
末尾以外のパラメータにデフォルト値を指定するとエラーになってしまうバグを修正。

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