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

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

インターフェイス実装周りの仕様整備

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