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

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

インターフェイスを実装

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