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

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

Throw→Catch間のパラメータ引渡しに対応。
グローバル領域でのTryスコープを可能にした。これで例外処理機構実装完了。
エディタの補間機能にTry/Catch/Finally/EndTryを追加。

File size: 25.2 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;
436const UserProc *UserProc::pGlobalProc = NULL;
437
438
439bool UserProcs::Insert( UserProc *pUserProc, int nowLine )
440{
441 /////////////////////////////////
442 // ハッシュデータに追加
443 /////////////////////////////////
444
445 if( !Put( pUserProc ) )
446 {
447 // 重複しているため、失敗
448 SetError(15,pUserProc->GetName().c_str(),nowLine);
449 return false;
450 }
451
452 return true;
453}
454UserProc *UserProcs::AddUserProc( const NamespaceScopes &namespaceScopes, const NamespaceScopesCollection &importedNamespaces, char *buffer,int nowLine,bool isVirtual,CClass *pobj_c, bool isStatic, char *interfaceName )
455{
456 int i2,i3;
457 char temporary[8192];
458
459 int i=1;
460
461 Procedure::Kind kind = Procedure::Sub;
462 bool isMacro = false;
463 if(buffer[i]==ESC_FUNCTION) kind = Procedure::Function;
464 if(buffer[i]==ESC_MACRO){
465 isMacro = true;
466 }
467
468 i++;
469
470 bool isCdecl = false;
471 bool isExport = false;
472 while(1){
473 if(buffer[i]==1&&buffer[i+1]==ESC_CDECL&& isCdecl == false ){
474 isCdecl = true;
475
476 i+=2;
477 }
478 else if(buffer[i]==1&&buffer[i+1]==ESC_EXPORT&& isExport == false ){
479 isExport = true;
480
481 i+=2;
482 }
483 else break;
484 }
485
486 i2=0;
487 if(buffer[i]==1&&buffer[i+1]==ESC_OPERATOR){
488 if(!pobj_c){
489 SetError(126,NULL,nowLine);
490 return 0;
491 }
492
493 //オペレータの場合
494 temporary[i2++]=buffer[i++];
495 temporary[i2++]=buffer[i++];
496
497 int iCalcId;
498 if(buffer[i]=='='&&buffer[i+1]=='='){
499 iCalcId=CALC_EQUAL;
500 i3=2;
501 }
502 else if(buffer[i]=='='){
503 iCalcId=CALC_SUBSITUATION;
504 i3=1;
505 }
506 else if(buffer[i]=='('){
507 iCalcId=CALC_AS;
508 i3=0;
509 }
510 else if(buffer[i]=='['&&buffer[i+1]==']'&&buffer[i+2]=='='){
511 iCalcId=CALC_ARRAY_SET;
512 i3=3;
513 }
514 else if(buffer[i]=='['&&buffer[i+1]==']'){
515 iCalcId=CALC_ARRAY_GET;
516 i3=2;
517 }
518 else{
519 iCalcId=GetCalcId(buffer+i,&i3);
520 i3++;
521 }
522 if(!iCalcId){
523 SetError(1,NULL,nowLine);
524 return 0;
525 }
526 temporary[i2++]=iCalcId;
527 temporary[i2]=0;
528
529 i+=i3;
530 }
531 else{
532 if(pobj_c){
533 //クラスメンバの場合、デストラクタには~が付くことを考慮
534 if(buffer[i]=='~'){
535 temporary[i2]='~';
536 i++;
537 i2++;
538 }
539 }
540
541 for(;;i++,i2++){
542 if(!IsVariableChar(buffer[i])){
543 temporary[i2]=0;
544 break;
545 }
546 temporary[i2]=buffer[i];
547 }
548
549 char parentName[VN_SIZE], memberName[VN_SIZE];
550 ReferenceKind refKind;
551 if( SplitMemberName( temporary, parentName, memberName, refKind ) )
552 {
553 if( pobj_c )
554 {
555 if( interfaceName )
556 {
557 lstrcpy( interfaceName, parentName );
558 }
559 else
560 {
561 SetError();
562 return NULL;
563 }
564
565 char dummyMemberName[VN_SIZE];
566 if( SplitMemberName( memberName, parentName, dummyMemberName, refKind ) )
567 {
568 SetError(69,temporary,nowLine);
569 return NULL;
570 }
571 }
572 else
573 {
574 SetError(68,temporary,nowLine);
575 return NULL;
576 }
577
578 lstrcpy( temporary, memberName );
579 }
580 }
581
582 if( isMacro ){
583 //大文字に変換
584 CharUpper(temporary);
585
586 //マクロ関数の場合は名前リストに追加
587 macroNames.push_back( temporary );
588 }
589
590 if(!pobj_c){
591 //クラスメンバ以外の場合のみ
592 //重複チェック
593
594 if(GetDeclareHash(temporary)){
595 SetError(15,temporary,nowLine);
596 return 0;
597 }
598 }
599
600 // 識別ID
601 static int id_base=0;
602
603 UserProc *pUserProc = new UserProc( namespaceScopes, importedNamespaces, temporary, kind, isMacro, isCdecl, isExport, (id_base++) );
604 pUserProc->SetParentClass( pobj_c );
605 if( Smoothie::isFullCompile ){
606 // すべての関数・メソッドをコンパイルする
607 pUserProc->Using();
608 }
609
610 // 親インターフェイスをセット
611 if( interfaceName && interfaceName[0] )
612 {
613 ::Interface *pTargetInterface = NULL;
614 BOOST_FOREACH( ::Interface *pInterface, pobj_c->GetInterfaces() )
615 {
616 if( pInterface->GetClass().GetName() == interfaceName )
617 {
618 pTargetInterface = pInterface;
619 break;
620 }
621 }
622 pUserProc->SetInterface( pTargetInterface );
623 }
624
625 if(isExport){
626 pUserProc->Using();
627 }
628
629 // パラメータを解析
630 // ※第1パラメータにに指定するデータの例:"( s As String ) As String"
631 pUserProc->SetParamsAndReturnType( buffer + i, nowLine, isStatic );
632
633 pUserProc->_paramStr = buffer + i;
634
635 // ハッシュに追加
636 if( !Insert( pUserProc, nowLine ) )
637 {
638 return NULL;
639 }
640
641 return pUserProc;
642}
643void UserProcs::EnumGlobalProcs( const char *simpleName, const char *localName, std::vector<const UserProc *> &subs )
644{
645 ///////////////////////////
646 // グローバル関数を検索
647 ///////////////////////////
648
649 // ハッシュ値を取得
650 UserProc *pUserProc = GetHashArrayElement( simpleName );
651 while(pUserProc){
652 if( pUserProc->IsGlobalProcedure() ){
653 if( pUserProc->IsEqualSymbol( localName ) ){
654 subs.push_back( pUserProc );
655 }
656 }
657
658 pUserProc=pUserProc->GetChainNext();
659 }
660}
661
662bool DllProc::SetParamsAndReturnType( const char *sourceOfParams, int nowLine ){
663 int i = 0;
664 int i2,i3,sw;
665 char temporary[8192],temp2[VN_SIZE];
666
667 //ソースコードの位置
668 this->codePos = nowLine;
669
670 //パラメータ
671 if(sourceOfParams[i]!='('){
672 SmoothieException::Throw(1,NULL,nowLine);
673 return 0;
674 }
675 i++;
676
677 while(1){
678 if(sourceOfParams[i]==')') break;
679
680 //ByRef
681 bool isRef;
682 if(sourceOfParams[i]==1&&sourceOfParams[i+1]==ESC_BYVAL){
683 isRef = false;
684 i+=2;
685 }
686 else if(sourceOfParams[i]==1&&sourceOfParams[i+1]==ESC_BYREF){
687 isRef = true;
688 i+=2;
689 }
690 else isRef = false;
691
692 //パラメータ名
693 bool isArray = false;
694 Subscripts subscripts;
695 char name[VN_SIZE];
696 sw=0;
697 for(i2=0;;i++,i2++){
698 if(sourceOfParams[i]=='('){
699 if(!sw) sw=1;
700
701 i3=GetStringInPare(name+i2,sourceOfParams+i);
702 i2+=i3-1;
703 i+=i3-1;
704 continue;
705 }
706 if(sourceOfParams[i]=='['){
707 if(!sw) sw=1;
708
709 i3=GetStringInBracket(name+i2,sourceOfParams+i);
710 i2+=i3-1;
711 i+=i3-1;
712 continue;
713 }
714 if(!IsVariableChar(sourceOfParams[i])){
715 name[i2]=0;
716 break;
717 }
718 name[i2]=sourceOfParams[i];
719 }
720 if(sw){
721 //配列パラメータ
722 if( isRef == false ) SmoothieException::Throw(29,NULL,nowLine);
723 isArray = true;
724
725 if((name[i2-2]=='('&&name[i2-1]==')')||
726 (name[i2-2]=='['&&name[i2-1]==']'))
727 {
728 subscripts.push_back( LONG_MAX );
729
730 name[i2-2]=0;
731 }
732 else{
733 GetArrange(name,temp2,subscripts);
734 lstrcpy(name,temp2);
735 }
736
737 i2=lstrlen(name);
738 }
739
740 //型
741 Type type( DEF_NON );
742 if(lstrcmp(name,"...")==0) type.SetBasicType( DEF_ELLIPSE );
743 else if(sourceOfParams[i]==1&&sourceOfParams[i+1]==ESC_AS){
744 i+=2;
745
746 i2=0;
747 while(sourceOfParams[i]=='*'){
748 temporary[i2]=sourceOfParams[i];
749 i++;
750 i2++;
751 }
752 for(;;i++,i2++){
753 if(!IsVariableChar(sourceOfParams[i])){
754 if(sourceOfParams[i]==1&&(sourceOfParams[i+1]==ESC_FUNCTION||sourceOfParams[i+1]==ESC_SUB)){
755 temporary[i2++]=sourceOfParams[i++];
756 temporary[i2]=sourceOfParams[i];
757 continue;
758 }
759 temporary[i2]=0;
760 break;
761 }
762 temporary[i2]=sourceOfParams[i];
763 }
764
765 compiler.StringToType( temporary, type );
766
767 if( type.IsNull() ){
768 SmoothieException::Throw(3,temporary,nowLine);
769 type.SetBasicType( DEF_PTR_VOID );
770 }
771 }
772 else{
773 type.SetBasicType( Type::GetBasicTypeFromSimpleName(temporary) );
774 SmoothieException::Throw(-103,temporary,nowLine);
775 }
776
777 Parameter *pParam = new Parameter( name, type, isRef );
778 if( isArray ){
779 pParam->SetArray( subscripts );
780 }
781
782 //パラメータを追加
783 this->params.push_back( pParam );
784
785 if(sourceOfParams[i]==','){
786 i++;
787 continue;
788 }
789 else if(sourceOfParams[i]==')') continue;
790 else{
791 SmoothieException::Throw(1,NULL,nowLine);
792 break;
793 }
794 }
795 i++;
796
797 if(sourceOfParams[i]){
798 ///////////////////
799 // 戻り値を取得
800 ///////////////////
801
802 i2=lstrlen(sourceOfParams)-2;
803
804 int sw_as=0;
805 for(;i2>0;i2--){
806 if(sourceOfParams[i2]==')') break;
807
808 if(sourceOfParams[i2]==1&&sourceOfParams[i2+1]==ESC_AS){
809 i2+=2;
810 i3=0;
811 while(sourceOfParams[i2]=='*') temporary[i3++]=sourceOfParams[i2++];
812 for(;;i2++,i3++){
813 if(!IsVariableChar(sourceOfParams[i2])){
814 temporary[i3]=0;
815 break;
816 }
817 temporary[i3]=sourceOfParams[i2];
818 }
819 compiler.StringToType( temporary, this->returnType );
820 if( this->returnType.IsNull() ) SmoothieException::Throw(3,temporary,nowLine);
821
822 sw_as=1;
823 break;
824 }
825 }
826 }
827 else{
828 //戻り値なしのSub定義
829 this->returnType.SetNull();
830 }
831
832 return true;
833}
834
835void DllProcs::Add(const NamespaceScopes &namespaceScopes, char *buffer,int nowLine){
836 int i2;
837
838 int i=0;
839
840 //Sub/Function
841 Procedure::Kind kind = Procedure::Sub;
842 if(buffer[i]==ESC_SUB){
843 }
844 else if(buffer[i]==ESC_FUNCTION){
845 kind = Procedure::Function;
846 }
847 else{
848 SetError(1,NULL,nowLine);
849 return;
850 }
851 i++;
852
853 //プロシージャ名
854 char procName[VN_SIZE];
855 bool isCdecl = false;
856 for(i2=0;;i++,i2++){
857 if(buffer[i]==1&&buffer[i+1]==ESC_CDECL){
858 isCdecl = true;
859
860 i+=2;
861 procName[i2]=0;
862 break;
863 }
864 if(buffer[i]==','){
865 procName[i2]=0;
866 break;
867 }
868 if(buffer[i]=='\0'){
869 SetError(1,NULL,nowLine);
870 return;
871 }
872 procName[i2]=buffer[i];
873 }
874 i++;
875
876 //ユーザー定義関数との重複チェック
877 if(GetSubHash(procName)){
878 SetError(15,procName,nowLine);
879 return;
880 }
881
882
883 //ライブラリ
884 char dllFileName[MAX_PATH];
885 i = GetOneParameter( buffer, i, dllFileName );
886 Type resultType;
887 _int64 i64data;
888 if( !StaticCalculation( true, dllFileName, 0, &i64data, resultType ) ){
889 return;
890 }
891 if( resultType.GetBasicType() != typeOfPtrChar ){
892 SetError(1,NULL,nowLine);
893 return;
894 }
895 lstrcpy( dllFileName, (char *)i64data );
896 CharUpper(dllFileName);
897 if(!strstr(dllFileName,".")){
898 lstrcat(dllFileName,".DLL");
899 if(lstrlen(dllFileName)>=16){
900 SetError(7,NULL,nowLine);
901 return;
902 }
903 }
904
905 //エイリアス
906 char alias[VN_SIZE];
907 i = GetOneParameter( buffer, i, alias );
908 if( alias[0] ){
909 if( !StaticCalculation( true, alias, 0, &i64data, resultType ) ){
910 return;
911 }
912 if( resultType.GetBasicType() != typeOfPtrChar ){
913 SetError(1,NULL,nowLine);
914 return;
915 }
916 lstrcpy( alias, (char *)i64data );
917 }
918 else{
919 //省略されたときは関数名
920 lstrcpy( alias, procName );
921 }
922
923
924 // オブジェクトを生成
925 DllProc *pDllProc = new DllProc( namespaceScopes, procName, kind, isCdecl, dllFileName, alias );
926
927 // パラメータを解析
928 // ※第1パラメータにに指定するデータの例:"( s As String ) As String"
929 pDllProc->SetParamsAndReturnType( buffer + i, nowLine );
930
931 // パラメータのエラーチェック
932 BOOST_FOREACH( const Parameter *pParam, pDllProc->Params() ){
933 if( pParam->IsObject() ){
934 SetError(25,pParam->GetVarName(),nowLine);
935 }
936 if( !pParam->IsRef() ){
937 if( pParam->IsStruct() ){
938 SetError(28,pParam->GetVarName(),nowLine);
939 }
940 }
941 }
942
943 //戻り値のエラーチェック
944 if( pDllProc->IsFunction() ){
945 // Function定義
946
947 if( pDllProc->ReturnType().IsObject() ){
948 // DLL関数ではオブジェクトを戻り値にできない
949 SetError(40,pDllProc->GetName(),nowLine);
950 }
951 }
952
953 // ハッシュマップに追加
954 this->Put( pDllProc );
955}
956
957bool ProcPointer::SetParamsAndReturnType( const char *sourceOfParams, int nowLine ){
958 int i = 0;
959 int i2,i3,sw;
960 char temporary[8192],temp2[VN_SIZE];
961
962 //ソースコードの位置
963 this->codePos = nowLine;
964
965 //パラメータ
966 if(sourceOfParams[i]!='('){
967 SmoothieException::Throw(1,NULL,nowLine);
968 return 0;
969 }
970 i++;
971 while(1){
972 if(sourceOfParams[i]==')') break;
973
974 //ByRef
975 bool isRef;
976 if(sourceOfParams[i]==1&&sourceOfParams[i+1]==ESC_BYVAL){
977 isRef = false;
978 i+=2;
979 }
980 else if(sourceOfParams[i]==1&&sourceOfParams[i+1]==ESC_BYREF){
981 isRef = true;
982 i+=2;
983 }
984 else isRef = false;
985
986 //パラメータ名
987 bool isArray = false;
988 Subscripts subscripts;
989 char name[VN_SIZE];
990 sw=0;
991 for(i2=0;;i++,i2++){
992 if(sourceOfParams[i]=='('){
993 if(!sw) sw=1;
994
995 i3=GetStringInPare(name+i2,sourceOfParams+i);
996 i2+=i3-1;
997 i+=i3-1;
998 continue;
999 }
1000 if(sourceOfParams[i]=='['){
1001 if(!sw) sw=1;
1002
1003 i3=GetStringInBracket(name+i2,sourceOfParams+i);
1004 i2+=i3-1;
1005 i+=i3-1;
1006 continue;
1007 }
1008 if(!IsVariableChar(sourceOfParams[i])){
1009 name[i2]=0;
1010 break;
1011 }
1012 name[i2]=sourceOfParams[i];
1013 }
1014 if(sw){
1015 //配列パラメータ
1016 if( isRef == false ) SmoothieException::Throw(29,NULL,nowLine);
1017 isArray = true;
1018
1019 if((name[i2-2]=='('&&name[i2-1]==')')||
1020 (name[i2-2]=='['&&name[i2-1]==']'))
1021 {
1022 subscripts.push_back( LONG_MAX );
1023
1024 name[i2-2]=0;
1025 }
1026 else{
1027 GetArrange(name,temp2,subscripts);
1028 lstrcpy(name,temp2);
1029 }
1030
1031 i2=lstrlen(name);
1032 }
1033
1034 //型
1035 Type type( DEF_NON );
1036 if(sourceOfParams[i]==1&&sourceOfParams[i+1]==ESC_AS){
1037 i+=2;
1038
1039 i2=0;
1040 while(sourceOfParams[i]=='*'){
1041 temporary[i2]=sourceOfParams[i];
1042 i++;
1043 i2++;
1044 }
1045 for(;;i++,i2++){
1046 if(!IsVariableChar(sourceOfParams[i])){
1047 if(sourceOfParams[i]==1&&(sourceOfParams[i+1]==ESC_FUNCTION||sourceOfParams[i+1]==ESC_SUB)){
1048 temporary[i2++]=sourceOfParams[i++];
1049 temporary[i2]=sourceOfParams[i];
1050 continue;
1051 }
1052 temporary[i2]=0;
1053 break;
1054 }
1055 temporary[i2]=sourceOfParams[i];
1056 }
1057
1058 compiler.StringToType( temporary, type );
1059
1060 if( type.IsNull() ){
1061 SmoothieException::Throw(3,temporary,nowLine);
1062 type.SetBasicType( DEF_PTR_VOID );
1063 }
1064 }
1065 else{
1066 type.SetBasicType( Type::GetBasicTypeFromSimpleName(temporary) );
1067 SmoothieException::Throw(-103,temporary,nowLine);
1068 }
1069
1070 Parameter *pParam = new Parameter( name, type, isRef );
1071 if( isArray ){
1072 pParam->SetArray( subscripts );
1073 }
1074
1075 //パラメータを追加
1076 this->params.push_back( pParam );
1077
1078 if(sourceOfParams[i]==','){
1079 i++;
1080 continue;
1081 }
1082 else if(sourceOfParams[i]==')') continue;
1083 else{
1084 SmoothieException::Throw(1,NULL,nowLine);
1085 break;
1086 }
1087 }
1088 i++;
1089
1090 if(sourceOfParams[i]){
1091 ///////////////////
1092 // 戻り値を取得
1093 ///////////////////
1094
1095 i2=lstrlen(sourceOfParams)-2;
1096
1097 int sw_as=0;
1098 for(;i2>0;i2--){
1099 if(sourceOfParams[i2]==')') break;
1100
1101 if(sourceOfParams[i2]==1&&sourceOfParams[i2+1]==ESC_AS){
1102 i2+=2;
1103 i3=0;
1104 while(sourceOfParams[i2]=='*') temporary[i3++]=sourceOfParams[i2++];
1105 for(;;i2++,i3++){
1106 if(!IsVariableChar(sourceOfParams[i2])){
1107 temporary[i3]=0;
1108 break;
1109 }
1110 temporary[i3]=sourceOfParams[i2];
1111 }
1112 compiler.StringToType( temporary, this->returnType );
1113 if( this->returnType.IsNull() ) SmoothieException::Throw(3,temporary,nowLine);
1114
1115 sw_as=1;
1116 break;
1117 }
1118 }
1119 }
1120 else{
1121 //戻り値なしのSub定義
1122 this->returnType.SetNull();
1123 }
1124
1125 //戻り値のエラーチェック
1126 if( IsFunction() ){
1127 // Function定義
1128
1129 if( this->ReturnType().IsNull() ){
1130 // 戻り値がない
1131 SmoothieException::Throw(26,this->GetName(),nowLine);
1132 }
1133 }
1134 else{
1135 if( !this->ReturnType().IsNull() ){
1136 // Sub定義なのに、戻り値がある
1137 SmoothieException::Throw(38,this->GetName(),nowLine);
1138 }
1139 }
1140
1141 return true;
1142}
1143
1144int ProcPointers::Add( const string &typeExpression )
1145{
1146 DWORD dwProcType = (DWORD)typeExpression[2];
1147 const string &paramStr = typeExpression.substr( 3 );
1148
1149 Procedure::Kind kind = Procedure::Sub;
1150 if( dwProcType == ESC_FUNCTION ){
1151 kind = Procedure::Function;
1152 }
1153
1154 ProcPointer *pProcPointer = new ProcPointer( kind );
1155
1156 //buffer[0]は'('となっている
1157 extern int cp;
1158 pProcPointer->SetParamsAndReturnType( paramStr.c_str(), cp );
1159
1160 this->push_back( pProcPointer );
1161
1162 return (int)this->size()-1;
1163}
1164
1165void ProcPointers::Clear()
1166{
1167 ProcPointers &procPointers = *this;
1168 BOOST_FOREACH( ProcPointer *pProcPointer, procPointers ){
1169 delete pProcPointer;
1170 }
1171 this->clear();
1172}
Note: See TracBrowser for help on using the repository browser.