forked from bmx-ng/bcc
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathdecl.bmx
2167 lines (1744 loc) · 49.2 KB
/
decl.bmx
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
' Copyright (c) 2013-2014 Bruce A Henderson
'
' Based on the public domain Monkey "trans" by Mark Sibly
'
' This software is provided 'as-is', without any express or implied
' warranty. In no event will the authors be held liable for any damages
' arising from the use of this software.
'
' Permission is granted to anyone to use this software for any purpose,
' including commercial applications, and to alter it and redistribute it
' freely, subject to the following restrictions:
'
' 1. The origin of this software must not be misrepresented; you must not
' claim that you wrote the original software. If you use this software
' in a product, an acknowledgment in the product documentation would be
' appreciated but is not required.
'
' 2. Altered source versions must be plainly marked as such, and must not be
' misrepresented as being the original software.
'
' 3. This notice may not be removed or altered from any source
' distribution.
'
Const DECL_EXTERN:Int= $010000
Const DECL_PRIVATE:Int= $020000
Const DECL_ABSTRACT:Int= $040000
Const DECL_FINAL:Int= $080000
Const DECL_SEMANTED:Int= $100000
Const DECL_SEMANTING:Int= $200000
Const DECL_POINTER:Int= $400000
Const DECL_ARG:Int= $800000
Const DECL_INITONLY:Int=$1000000
Const CLASS_INTERFACE:Int= $001000
Const CLASS_THROWABLE:Int= $002000
Global _env:TScopeDecl
Global _envStack:TList=New TList
Global _appInstance:TAppDecl
Global _loopnest:Int
Function PushEnv( env:TScopeDecl )
If _env _envStack.AddLast( _env )
_env=env
End Function
Function PopEnv()
_env=TScopeDecl( _envStack.RemoveLast() )
End Function
Type TFuncDeclList Extends TList
End Type
Type TDecl
Field ident$
Field munged$
Field errInfo$
Field actual:TDecl
Field scope:TScopeDecl
Field attrs:Int
Field metadata:String
Field declImported:Int = False
Method New()
errInfo=_errInfo
actual=Self
End Method
Method OnCopy:TDecl() Abstract
Method ToString$()
If TClassDecl( scope ) Return scope.ToString()+"."+ident
Return ident
End Method
Method IsExtern:Int()
Return (attrs & DECL_EXTERN)<>0
End Method
Method IsPrivate:Int()
Return (attrs & DECL_PRIVATE)<>0
End Method
Method IsAbstract:Int()
Return (attrs & DECL_ABSTRACT)<>0
End Method
Method IsSemanted:Int()
Return (attrs & DECL_SEMANTED)<>0
End Method
Method IsSemanting:Int()
Return (attrs & DECL_SEMANTING)<>0
End Method
Method FuncScope:TFuncDecl()
If TFuncDecl( Self ) Return TFuncDecl( Self )
If scope Return scope.FuncScope()
End Method
Method ClassScope:TClassDecl()
If TClassDecl( Self ) Return TClassDecl( Self )
If scope Return scope.ClassScope()
End Method
Method ModuleScope:TModuleDecl()
If TModuleDecl( Self ) Return TModuleDecl( Self )
' "app" is a module container
If TAppDecl( Self ) Return TAppDecl( Self).mainModule
If scope Return scope.ModuleScope()
End Method
Method AppScope:TAppDecl()
If TAppDecl( Self ) Return TAppDecl( Self )
If scope Return scope.AppScope()
End Method
Method CheckAccess:Int()
If IsPrivate() And ModuleScope()<>_env.ModuleScope() Return False
Return True
End Method
Method AssertAccess()
If Not CheckAccess()
Err ToString() +" is private."
EndIf
End Method
Method Copy:TDecl()
Local t:TDecl=OnCopy()
t.munged=munged
t.errInfo=errInfo
Return t
End Method
Method Semant()
If IsSemanted() Return
If IsSemanting() Err "Cyclic declaration of '"+ident+"'."
If actual<>Self
actual.Semant
EndIf
PushErr errInfo
If scope
PushEnv scope
EndIf
attrs:|DECL_SEMANTING
'If ident And ClassScope() Print "Semanting "+ToString()
OnSemant
attrs:&~DECL_SEMANTING
attrs:|DECL_SEMANTED
If scope
'If Not IsExtern()
If TFuncDecl(Self) And attrs & FUNC_PTR
DebugLog "**** " + ident
Else
scope._semanted.AddLast Self
If TGlobalDecl( Self )
' FIXME
If AppScope() Then
AppScope().semantedGlobals.AddLast TGlobalDecl( Self )
End If
EndIf
If TModuleDecl( scope )
'DebugStop
' FIXME
Local app:TAppDecl = AppScope()
If app Then
app._semanted.AddLast Self
End If
EndIf
EndIf
If TValDecl(Self) And TValDecl(Self).deferInit Then
TValDecl(Self).SemantInit
End If
PopEnv
Else
If TValDecl(Self) And TValDecl(Self).deferInit Then
TValDecl(Self).SemantInit
End If
EndIf
PopErr
End Method
Method InitInstance:TDecl( decl:TDecl )
decl.ident=ident
decl.munged=munged
decl.errInfo=errInfo
decl.actual=actual
decl.scope=Null
decl.attrs=attrs & ~(DECL_SEMANTED|DECL_SEMANTING)
Return decl
End Method
Method GenInstance:TDecl()
InternalErr
End Method
Method OnSemant() Abstract
End Type
Type TValDecl Extends TDecl
'pre-semant
Field declTy:TType
Field declInit:TExpr
'post-semant
Field ty:TType
Field init:TExpr
Field deferInit:Int = False
Method ToString$()
Local t$=Super.ToString()
If ty Return t+":"+ty.ToString()
If declTy Return t+":"+declTy.ToString()
Return t+":?"
End Method
Method CopyInit:TExpr()
If init Return init.Copy()
End Method
Method OnSemant()
If declTy
' ensure to set the scope for a function pointer array before semanting
If TArrayType(declTy) And TFunctionPtrType(TArrayType(declTy).elemType) Then
If Not TFunctionPtrType(TArrayType(declTy).elemType).func.scope Then
If scope Then
TFunctionPtrType(TArrayType(declTy).elemType).func.scope = scope
Else
TFunctionPtrType(TArrayType(declTy).elemType).func.scope = _env
End If
End If
End If
' pass the scope into the function ptr
If TFunctionPtrType(declTy) Then
If Not TFunctionPtrType(declTy).func.scope Then
If scope Then
TFunctionPtrType(declTy).func.scope = scope
Else
TFunctionPtrType(declTy).func.scope = _env
End If
End If
End If
ty=declTy.Semant()
If Not deferInit Then
SemantInit()
End If
Else If declInit
If Not deferInit Then
SemantInit()
End If
Else
InternalErr
EndIf
End Method
Method SemantInit()
' for field initialisation, create a stub New() method to use as current scope
' since fields are initialised in New(). Otherwise the scope would be "class", which is
' incorrect for processing field inits.
If TFieldDecl(Self) And declInit Then
Local newScope:TFuncDecl = New TFuncDecl.CreateF( "new", Null,Null,FUNC_METHOD )
newScope.scope = _env
PushEnv(newScope)
End If
If declTy
If declInit Then
If TFunctionPtrType(ty) Then
' the default munged function value as defined in the interface
If TInvokeExpr(declInit) Then
init = declInit.Copy()
Else If TConstExpr(declInit) Then
init = declInit.Copy().Semant()
Else
Local expr:TExpr
If TFuncCallExpr(declInit) Then
expr=declInit.Copy().Semant()
Else If TNullExpr(declInit) Then
expr = declInit
Else
Local argExpr:TExpr[] = New TExpr[0]
For Local arg:TArgDecl = EachIn TFunctionPtrType(ty).func.argDecls
Local ldecl:TLocalDecl = New TLocalDecl.Create(arg.ident, arg.declTy, Null, 0)
ldecl.Semant()
Local aexp:TVarExpr = New TVarExpr.Create(ldecl)
'Local aexp:TIdentTypeExpr = New TIdentTypeExpr.Create(arg.declTy)
aexp.Semant()
argExpr :+ [aexp]
Next
expr=declInit.Copy().SemantFunc(argExpr, False, False)
If Not expr Then
expr = declInit.Copy().Semant()
End If
End If
If expr.exprType.EqualsType( ty ) Then
init = expr
Else
init = New TCastExpr.Create( ty,expr,CAST_EXPLICIT ).Semant()
End If
End If
Else
init=declInit.Copy().SemantAndCast(ty)
End If
End If
Else If declInit
init=declInit.Copy().Semant()
ty=init.exprType
End If
' remove the temporary scope
If TFieldDecl(Self) And declInit Then
PopEnv()
End If
End Method
End Type
Type TConstDecl Extends TValDecl
Field value$
Method Create:TConstDecl( ident$,ty:TType,init:TExpr,attrs:Int )
Self.ident=ident
Self.munged=ident
Self.declTy=ty
Self.declInit=init
Self.attrs=attrs
Return Self
End Method
Method GenInstance:TDecl()
Local inst:TConstDecl = New TConstDecl
InitInstance inst
inst.declTy=declTy
inst.declInit=declInit
Return inst
End Method
Method OnCopy:TDecl()
Return New TConstDecl.Create( ident,ty,CopyInit(), attrs )
End Method
Method OnSemant()
Super.OnSemant()
'If Not IsExtern() value=init.Eval()
If init Then
value=init.Eval()
If TStringType(ty) And Not _appInstance.hasStringConst(value) Then
_appInstance.mapStringConsts(value)
End If
End If
End Method
Method ToString$()
Return "Const "+Super.ToString()
End Method
End Type
Type TVarDecl Extends TValDecl
End Type
Type TLocalDecl Extends TVarDecl
Method Create:TLocalDecl( ident$,ty:TType,init:TExpr,attrs:Int=0 )
Self.ident=ident
Self.declTy=ty
Self.declInit=init
Self.attrs=attrs
Return Self
End Method
Method OnCopy:TDecl()
Return New TLocalDecl.Create( ident,ty,CopyInit(),attrs )
End Method
Method ToString$()
Return "Local "+Super.ToString()
End Method
End Type
Type TArgDecl Extends TLocalDecl
Field castTo:String
Method Create:TArgDecl( ident$,ty:TType,init:TExpr,attrs:Int=0 )
Self.ident=ident
Self.declTy=ty
Self.declInit=init
Self.attrs=attrs
Return Self
End Method
Method GenInstance:TDecl()
Local inst:TArgDecl=New TArgDecl
InitInstance inst
inst.declTy=declTy
inst.declInit=declInit
Return inst
End Method
Method OnCopy:TDecl()
Local d:TArgDecl = New TArgDecl.Create( ident,ty,CopyInit(),attrs )
d.ty = d.declTy
d.init = d.declInit
Return d
End Method
Method ToString$()
Return Super.ToString()
End Method
End Type
Type TGlobalDecl Extends TVarDecl
Field inited:Int
Method Create:TGlobalDecl( ident$,ty:TType,init:TExpr,attrs:Int=0 )
Self.deferInit = True
Self.ident=ident
Self.declTy=ty
Self.declInit=init
Self.attrs=attrs
Return Self
End Method
Method OnCopy:TDecl()
Return New TGlobalDecl.Create( ident,ty,CopyInit(),attrs )
End Method
Method ToString$()
Return "Global "+Super.ToString()
End Method
Method GenInstance:TDecl()
' PushErr errInfo
' Err "Global variables cannot be used inside generic classes."
Local inst:TGlobalDecl=New TGlobalDecl
InitInstance inst
inst.declTy=declTy
inst.declInit=declInit
Return inst
End Method
End Type
Type TFieldDecl Extends TVarDecl
' location offset in object variable data
Field offset:Int
Method Create:TFieldDecl( ident$,ty:TType,init:TExpr,attrs:Int=0 )
Self.ident=ident
Self.declTy=ty
Self.declInit=init
Self.attrs=attrs
Return Self
End Method
Method OnCopy:TDecl()
Return New TFieldDecl.Create( ident,ty,CopyInit(),attrs )
End Method
Method ToString$()
Return "Field "+Super.ToString()
End Method
Method GenInstance:TDecl()
Local inst:TFieldDecl=New TFieldDecl
InitInstance inst
inst.declTy=declTy
inst.declInit=declInit
Return inst
End Method
End Type
Type TAliasDecl Extends TDecl
Field decl:Object
Method Create:TAliasDecl( ident$,decl:Object,attrs:Int=0 )
Self.ident=ident
Self.decl=decl
Self.attrs=attrs
Return Self
End Method
Method OnCopy:TDecl()
Return New TAliasDecl.Create( ident,decl,attrs )
End Method
Method OnSemant()
End Method
End Type
Type TScopeDecl Extends TDecl
'Private
Field _decls:TList=New TList'<TDecl>
Field _semanted:TList=New TList'<TDecl>
Field declsMap:TMap=New TMap'<Object>
'Public
Method OnCopy:TDecl()
InternalErr
End Method
Method Decls:TList()
Return _decls
End Method
Method Semanted:TList()
Return _semanted
End Method
Method FuncDecls:TList( id$="" )
Local fdecls:TList=New TList
For Local decl:TDecl=EachIn _decls
If id And decl.ident<>id Continue
Local fdecl:TFuncDecl=TFuncDecl( decl )
If fdecl fdecls.AddLast fdecl
Next
Return fdecls
End Method
Method MethodDecls:TList( id$="" )
Local fdecls:TList=New TList
For Local decl:TDecl=EachIn _decls
If id And decl.ident<>id Continue
Local fdecl:TFuncDecl=TFuncDecl( decl )
If fdecl And fdecl.IsMethod() fdecls.AddLast fdecl
Next
Return fdecls
End Method
Method SemantedFuncs:TList( id$="" )
Local fdecls:TList=New TList
For Local decl:TDecl=EachIn _semanted
If id And decl.ident<>id Continue
Local fdecl:TFuncDecl=TFuncDecl( decl )
If fdecl fdecls.AddLast fdecl
Next
Return fdecls
End Method
Method SemantedMethods:TList( id$="" )
Local fdecls:TList=New TList
For Local decl:TDecl=EachIn _semanted
If id And decl.ident<>id Continue
Local fdecl:TFuncDecl=TFuncDecl( decl )
If fdecl And fdecl.IsMethod() fdecls.AddLast fdecl
Next
Return fdecls
End Method
Method InsertDecl( decl:TDecl )
If decl.scope And Not (decl.attrs & DECL_INITONLY) InternalErr
Local ident$=decl.ident
If Not ident Return
If Not decl.scope Then
decl.scope=Self
End If
_decls.AddLast decl
'Local _decls:TMap
Local tdecl_:Object=declsMap.ValueForKey( ident.ToLower() )
'If TFuncDecl( decl )
' Local funcs:TFuncDeclList=TFuncDeclList( tdecl_ )
' If funcs Or Not tdecl_
' If Not funcs
' funcs=New TFuncDeclList
' declsMap.Insert ident.ToLower(),funcs
' EndIf
' funcs.AddLast TFuncDecl( decl )
' Else
' Err "Duplicate identifier '"+ident+"'."
' EndIf
'Else
If Not tdecl_
'DebugLog "Adding " + decl.ident
declsMap.Insert ident.ToLower(),decl
Else
Err "Duplicate identifier '"+ident+"'."
EndIf
End Method
Method InsertDecls( _decls:TList )
For Local decl:TDecl=EachIn _decls
InsertDecl decl
Next
End Method
'This is overridden by TClassDecl and TModuleDecl
Method GetDecl:Object( ident$ )
'DebugLog "GetDecl (" + Self.ident + ") : " + ident
Local decl:Object=Object(declsMap.ValueForKey( ident.ToLower() ))
If Not decl Then
If Self.ident.ToLower() = ident.ToLower() Then
' name matches but we are a "module", but not a *real* module..
' .. so we can't be looking for ourself
If TModuleDecl(Self) And Self.ident.Find(".") = - 1 Then
decl = Null
Else
decl = Self
End If
End If
End If
If Not decl Return Null
Local adecl:TAliasDecl=TAliasDecl( decl )
If Not adecl Return decl
If adecl.CheckAccess() Return adecl.decl
End Method
Method FindDecl:Object( ident$, override:Int = False )
If Not override And _env<>Self Return GetDecl( ident )
Local tscope:TScopeDecl=Self
While tscope
Local decl:TDecl=TDecl(tscope.GetDecl( ident ))
If decl Return decl
tscope=tscope.scope
Wend
End Method
' Method FindDecl:Object( ident$, static:Int = False )
' Local decl:Object=GetDecl( ident )
'
' If Not static Or Not decl Then
' If decl Return decl
' Else
' If Not TFieldDecl(decl) And Not (TFuncDecl(decl) And TFuncDecl(decl).IsMethod()) Then
' Return decl
' End If
' End If
' If scope Return scope.FindDecl( ident, static )
' End Method
Method FindValDecl:TValDecl( ident$, static:Int = False )
Local decl:TValDecl=TValDecl( FindDecl( ident ) )
' we found a field but we don't have access to it?
If TFieldDecl(decl) And static Then
' see if there's another decl with the same name elsewhere that we may...
' field's scope.scope will be a module.
If decl.scope And decl.scope.scope Then
Local vDecl:TValDecl = TValDecl( decl.scope.scope.FindDecl( ident, True ) )
If vDecl Then
decl = vDecl
End If
End If
End If
If Not decl Then
' didn't find it? Maybe it is in module local scope?
' issue arises when a global initialises with a local variable in the module scope.
Local fdecl:TFuncDecl = TFuncDecl(FindDecl("LocalMain"))
If fdecl Then
decl = TValDecl( fdecl.FindDecl( ident ) )
End If
End If
If Not decl Return Null
decl.AssertAccess
decl.Semant
Return decl
End Method
Method FindType:TType( ident$,args:TType[] )
'DebugLog Self.ident + "::FindType::" + ident
Local decl:Object=(GetDecl( ident ))
If decl Then
Local ty:TType=TType(decl)
If ty
If args.Length Err "Wrong number of type arguments"
Return ty
EndIf
Local cdecl:TClassDecl=TClassDecl( decl )
If cdecl
cdecl.AssertAccess
cdecl=cdecl.GenClassInstance( args )
cdecl.Semant
Return cdecl.objectType
EndIf
EndIf
If scope Return scope.FindType( ident,args )
End Method
Method FindScopeDecl:TScopeDecl( ident$ )
Local decl:TScopeDecl=TScopeDecl( FindDecl( ident ) )
If Not decl Return Null
decl.AssertAccess
decl.Semant
Return decl
End Method
Rem
Method FindClassDecl:TClassDecl( ident$,args:TClassDecl[] = Null )
Local decl:TClassDecl=TClassDecl( GetDecl( ident ) )
If Not args Then
args = New TClassDecl[0]
End If
If Not decl
If scope Return scope.FindClassDecl( ident,args )
Return Null
EndIf
decl.AssertAccess
decl.Semant
Return decl.GenClassInstance( args )
End Method
End Rem
Method FindModuleDecl:TModuleDecl( ident$ )
'DebugStop
Local decl:TModuleDecl=TModuleDecl( GetDecl( ident ) )
If Not decl
If scope Return scope.FindModuleDecl( ident )
Return Null
EndIf
decl.AssertAccess
' only semant on "real" module
If Not decl.declImported Then
decl.Semant
End If
Return decl
End Method
Method FindFuncDecl:TFuncDecl( ident$,argExprs:TExpr[] = Null,explicit:Int=False, isArg:Int = False )
'DebugLog "FindFuncDecl : " + ident
'If ident = "lua_pushcclosure" Then DebugStop
'Local funcs:TFuncDeclList=TFuncDeclList( FindDecl( ident ) )
Local f:TDecl = TDecl(findDecl(ident))
If Not f Then Return Null
Local func:TFuncDecl = TFuncDecl(f)
If Not func Then
If TVarDecl(f) Then
If Not f.IsSemanted() Then
f.Semant()
End If
If TFunctionPtrType(TVarDecl(f).ty) Then
func = TFunctionPtrType(TVarDecl(f).ty).func
If Not func.scope Then
func.scope = f.scope
End If
If Not func.ident Then
func.ident = f.ident
End If
End If
End If
End If
If Not func Return Null
If Not argExprs
argExprs = New TExpr[0]
End If
'For Local func:TFuncDecl=EachIn funcs
func.Semant()
'Next
Local match:TFuncDecl,isexact:Int
Local _err$
'DebugStop
'For Local func:TFuncDecl=EachIn funcs
While True
If Not func.CheckAccess() Exit
Local argDecls:TArgDecl[]=func.argDecls
If argExprs.Length>argDecls.Length Exit
Local exact:Int=True
Local possible:Int=True
' we found a matching name - this is probably the one we mean...
If isArg Then
match=func
Exit
End If
For Local i:Int=0 Until argDecls.Length
If i<argExprs.Length And argExprs[i]
Local declTy:TType=argDecls[i].ty
Local exprTy:TType=argExprs[i].exprType
If TFunctionPtrType(declTy) And TInvokeExpr(argExprs[i]) Then
If TFunctionPtrType(declTy).equalsDecl(TInvokeExpr(argExprs[i]).decl) Continue
End If
' not ideal - since the arg is configured as a Byte Ptr, we can't check that the function is of the correct type.
If IsPointerType(declTy, TType.T_BYTE) And TInvokeExpr(argExprs[i]) And TInvokeExpr(argExprs[i]).invokedWithBraces = 0 Then
Continue
End If
If TFunctionPtrType(declTy) And IsPointerType(exprTy, TType.T_BYTE) Then
Continue
End If
If exprTy.EqualsType( declTy ) Continue
exact=False
If Not explicit And exprTy.ExtendsType( declTy ) Continue
Else If argDecls[i].init
exact=False
If Not explicit Exit
Else
If func.attrs & FUNC_PTR Then
exact=False
Exit
End If
EndIf
possible=False
Exit
Next
If Not possible Exit
If exact
If isexact
Err "Unable to determine overload to use: "+match.ToString()+" or "+func.ToString()+"."
Else
_err=""
match=func
isexact=True
EndIf
Else
If Not isexact
If match
_err="Unable to determine overload to use: "+match.ToString()+" or "+func.ToString()+"."
Else
match=func
EndIf
EndIf
EndIf
Exit
Wend
If Not isexact
If _err Err _err
If explicit Return Null
EndIf
' last try... maybe we are trying to use it as a function pointer? (no args)
If Not match Then
If func And Not argExprs Then
match = func
match.maybeFunctionPtr = True
End If
End If
If Not match
Local t$
For Local i:Int=0 Until argExprs.Length
If t t:+","
If argExprs[i] t:+argExprs[i].exprType.ToString()
Next
Err "Unable to find overload for "+ident+"("+t+")."
EndIf
match.AssertAccess
Return match
End Method
Method FindLoop:TStmt(ident:String)
If TBlockDecl(scope) And TBlockDecl(scope).extra Then
Local loop:TLoopStmt = TLoopStmt(TBlockDecl(scope).extra)
If loop.loopLabel And loop.loopLabel.ident = ident Then
Return loop
End If
End If
If TFuncDecl(scope) Or TModuleDecl(scope)
Return Null
End If
If scope Return scope.FindLoop( ident )
End Method
Method OnSemant()
End Method
End Type
Type TBlockDecl Extends TScopeDecl
Field stmts:TList=New TList
Field extra:Object
Method Create:TBlockDecl( scope:TScopeDecl )
Self.scope=scope
Return Self
End Method
Method AddStmt( stmt:TStmt )
stmts.AddLast stmt
End Method
Method OnCopy:TDecl()
Local t:TBlockDecl=New TBlockDecl
For Local stmt:TStmt=EachIn stmts
t.AddStmt stmt.Copy( t )
Next
t.extra = extra
Return t
End Method
Method OnSemant()
PushEnv Self
For Local stmt:TStmt=EachIn stmts
stmt.Semant
Next
PopEnv
End Method
Method CopyBlock:TBlockDecl( scope:TScopeDecl )
Local t:TBlockDecl=TBlockDecl( Copy() )
t.scope=scope
Return t
End Method
End Type
Const FUNC_METHOD:Int= $0001 'mutually exclusive with ctor
Const FUNC_CTOR:Int= $0002
Const FUNC_PROPERTY:Int= $0004
Const FUNC_PTR:Int= $0100
Const FUNC_BUILTIN:Int = $0080
Const FUNC_INIT:Int = $0200
Const FUNC_NESTED:Int = $0400
'Fix! A func is NOT a block/scope!
'
Type TFuncDecl Extends TBlockDecl
Field retType:TType