-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathTreeConverter.pas
1636 lines (1331 loc) · 51.6 KB
/
TreeConverter.pas
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
/// Þíèò êîíâåðòîðà ñèíòàêñè÷åñêîãî äåðåâà â ñåìàíòè÷åñêîå, îäíîâðåìåííî îïòèìèçèðóþùèé äåðåâî
unit TreeConverter;
interface
uses
System,
System.IO,
System.Collections,
System.Collections.Generic,
System.Reflection,
System.Reflection.Emit,
ASyntaxTree,
ASemanticTree,
CommonUnit;
type
SemanticException = class(Exception)
Loc: Location;
constructor Create(message: string; Loc: Location);
begin
inherited Create(message);
self.Loc := Loc;
end;
end;
GetSyntaxTreeProc = function(UnitName: string; Dir: string): UnitTree;
GConverter = class
private
GetSyntaxTree: GetSyntaxTreeProc;
LocalVars: List<string>;
Variables: Dictionary<string, SVariableNode>;
// Methods: Dictionary<FunctionNode, SFunctionNode>;
OtherMethods: List<SFunctionNode>;
Methods: Dictionary<FunctionNode, SFunctionNode>;
//Labels: Dictionary<string, SLabelNode>;
LabelsName: List<string>;
Labels: List<SLabelNode>;
// namepace êîòîðûå ïðîïèñàíû â uses
usesNamespaces: List<string>;
usesAliases: Dictionary<string, string>;
procedure DelVarFromList(Name: string);
procedure VarToList(Name: string; Variable: SVariableNode);
function ParametersMatch(parameters: array of &Type; ParametersInfo: array of ParameterInfo): boolean;
function GetType(typeName: string): &Type;
function GetMethod(_type: &Type; mthdName: string; ParamTypes: array of &Type): MethodInfo;
function GetProperty(_type: &Type; propName: string; ParamTypes: array of &Type): PropertyInfo;
function GetVar(Name: string; Loc: Location): SVariableNode;
function CreateMainFunctionNode: SFunctionNode;
function GetStandartAssemblyPath: string;
procedure InitNamespaces(_Assembly: Assembly);
procedure LoadAssembly(Name: string; Loc: Location);
function SelfFunctionExist(Name: string): boolean;
function GetSelfFunction(Name: string; PassedParameters: List<ExpressionNode>): SCallOwnFunctionNode;
function ConvertSubIdentNode(_type: &Type; Ident: IdentNode; IdentParseIndex: integer; ForRead: boolean): SStmtNode;
function ConvertIdentNode(Ident: IdentNode; ForRead: boolean): SStmtNode;
function ConvertFunctionNode(Func: FunctionNode): SFunctionNode;
function ConvertFunctionNode(Func: NetFunctionNode): SNetFunctionNode;
function ConvertFunctionNode(Func: NativeFunctionNode): SNativeFunctionNode;
function ConvertStatementNode(Stmt: StatementNode): SStmtNode;
function ConvertExpressionNode(Expr: ExpressionNode; ExpectedType: &Type): SExprNode;
function ConvertExpressionNode(Expr: ExpressionNode): SExprNode;
function OptimizeExpressionNode(Expr: SExprNode): SExprNode;
procedure Optimize;
function ConvertExpressionNodeAndOptimize(Expr: ExpressionNode): SExprNode;
function ConvertTypeExpressionNode(TypeExpr: TypeExpression): STypeExpr;
// procedure CreateSemanticTree(SyntaxTree: ProgramNode): SProgramNode;
procedure CreateSemanticTree;
protected
TypeList: Dictionary<string, STypeExpr>;
public
SyntaxTree: ProgramNode;
SemanticTree: SProgramNode;
constructor Create(Prog: ProgramNode; GetSyntaxTree: GetSyntaxTreeProc);
constructor Create(Prog: ProgramNode; GetSyntaxTree: GetSyntaxTreeProc; Recourse: boolean);
end;
var
Types := new Dictionary<string, &Type>;
Assemblies := new List<Assembly>;
namespaces := new List<string>;
AllUnitsFilenames := new List<string>;
AllUnits := new List<GConverter>;
implementation
constructor GConverter.Create(Prog: ProgramNode; GetSyntaxTree: GetSyntaxTreeProc; Recourse: boolean);
begin
if not Recourse then
begin
Types := new Dictionary<string, &Type>;
Assemblies := new List<Assembly>;
namespaces := new List<string>;
AllUnitsFilenames := new List<string>;
AllUnits := new List<GConverter>;
end;
self.GetSyntaxTree := GetSyntaxTree;
SyntaxTree := Prog;
CreateSemanticTree;
end;
constructor GConverter.Create(Prog: ProgramNode; GetSyntaxTree: GetSyntaxTreeProc);
begin
Types := new Dictionary<string, &Type>;
Assemblies := new List<Assembly>;
namespaces := new List<string>;
AllUnitsFilenames := new List<string>;
AllUnits := new List<GConverter>;
self.GetSyntaxTree := GetSyntaxTree;
SyntaxTree := Prog;
CreateSemanticTree;
end;
procedure GConverter.CreateSemanticTree;
begin
if (SyntaxTree is UnitTree) then
begin
SemanticTree := new SUnitTree;
(SemanticTree as SUnitTree).UnitName := (SyntaxTree as UnitTree).UnitName;
end
else if (SyntaxTree is LibraryTree) then
begin
SemanticTree := new SLibraryTree;
(SemanticTree as SLibraryTree).LibraryName := (SyntaxTree as LibraryTree).LibraryName;
end
else
begin
SemanticTree := new SProgramTree;
(SemanticTree as SProgramTree).ProgramName := (SyntaxTree as ProgramTree).ProgramName;
end;
SemanticTree.GlobalVarList := new List<SGlobalVarNode>;
SemanticTree.SGeneric_Functions := new List<SFunctionNode>;
SemanticTree.UsedUnits := new List<SProgramNode>;
TypeList := new Dictionary<string, STypeExpr>;
// Init vars
LocalVars := new List<string>;
Variables := new Dictionary<string, SVariableNode>;
Methods := new Dictionary<FunctionNode, SFunctionNode>;
usesAliases := new Dictionary<string, string>;
//namespaces := new List<string>;
//Types := new Dictionary<string, &Type>;
// Ñòàíäàðòíàÿ áèáëèîòåêà ïîäêëþ÷àåòñÿ â ëþáîì ñëó÷àå
LoadAssembly('mscorlib.dll', SyntaxTree);
// Îáðàáîòêà äèðåêòèâ
foreach d: CompilerDirective in Options.CompilerDirectives do
begin
if d.Name.ToLower = 'reference' then LoadAssembly(d.Value, d);
end;
OtherMethods := new List<SFunctionNode>;
usesNamespaces := new List<string>;
foreach a: IdentNode in SyntaxTree.Generic_Uses do
if namespaces.Contains(a.ToString.ToLower) then
usesNamespaces.Add(a.ToString.ToLower)
else
begin
if not (Path.GetFileNameWithoutExtension(SyntaxTree.SourceFilename) = a.ToString) then
begin
var GConv: GConverter;
if AllUnitsFilenames.Contains(a.ToString) then
begin
GConv := AllUnits[AllUnitsFilenames.IndexOf(a.ToString)];
end
else
begin
var g := GetSyntaxTree(a.ToString, Path.GetDirectoryName(self.SyntaxTree.SourceFilename));
GConv := new GConverter(g, GetSyntaxTree, true);
AllUnits.Add(GConv);
AllUnitsFilenames.Add(Path.GetFileNameWithoutExtension(g.SourceFilename));
end;
SemanticTree.UsedUnits.Add(GConv.SemanticTree);
// Äîáàâëÿåì ìåòîäû èç Þíèòà äëÿ òîãî, ÷òîáû ïîòîì íà íèõ ññûëàòüñÿ
foreach f: SFunctionNode in GConv.SemanticTree.SGeneric_Functions do
OtherMethods.Add(f);
foreach variable: SGlobalVarNode in GConv.SemanticTree.GlobalVarList do
VarToList(variable.Name, variable);
// äîáàâëåíèå òîãî TypeList'a ñþäà
foreach pair: KeyValuePair<string, STypeExpr> in GConv.TypeList do
begin
TypeList.Add(pair.Key, pair.Value);
end;
{foreach pair: KeyValuePair<string, &Type> in Types do
begin
if not Types.ContainsKey(pair.Key) then
Types.Add(pair.Key, pair.Value);
end;}
end;
end;
for var i := 0 to SyntaxTree.Generic_Types.Count - 1 do
begin
if not TypeList.ContainsKey(SyntaxTree.Generic_Types[i].Name) then
TypeList.Add(SyntaxTree.Generic_Types[i].Name, ConvertTypeExpressionNode(SyntaxTree.Generic_Types[i].Expr))
else raise new SemanticException(string.Format('ïîâòîðíîå îáüÿâëåíèå {0}', SyntaxTree.Generic_Types[i].Name), SyntaxTree.Generic_Types[i])
end;
// Âåðèôèêàöèÿ UsesAliases
foreach pair: KeyValuePair<IdentNode, IdentNode> in SyntaxTree.Generic_UsesAliases do
if namespaces.Contains(pair.Value.ToString.ToLower) then
usesAliases.Add(pair.Key.ToString.ToLower, pair.Value.ToString.ToLower)
else
raise new SemanticException(string.Format('{0} íå ÿâëÿåòüñÿ namespace{1}îì', pair.Key.ToString, #39), pair.Key);
for var i := 0 to SyntaxTree.Generic_Vars.Count - 1 do
begin
if (SyntaxTree.Generic_Vars[i] is TypeVarNode) then
begin
var TypeVarN := TypeVarNode(SyntaxTree.Generic_Vars[i]);
var GlobalDeclareNode := new SGlobalDeclareNode;
GlobalDeclareNode.Name := TypeVarN.Name;
GlobalDeclareNode._Type := ConvertTypeExpressionNode(SyntaxTree.Generic_Vars[i].Expr);
VarToList(GlobalDeclareNode.Name, GlobalDeclareNode);
SemanticTree.GlobalVarList.Add(GlobalDeclareNode);
end;
end;
{if optimize and not isUnit then
SemanticTree.SGeneric_Functions.Insert(0, CreateMainFunctionNode)
else
begin}
if SemanticTree is SProgramTree then SemanticTree.SGeneric_Functions.Insert(0, CreateMainFunctionNode);
foreach fNode: FunctionNode in SyntaxTree.Generic_Functions do
if not methods.ContainsKey(fNode) then
SemanticTree.SGeneric_Functions.Add(ConvertFunctionNode(fNode));
//end;
end;
function GConverter.GetVar(Name: string; Loc: Location): SVariableNode;
begin
Name := Name.ToLower;
if Variables.ContainsKey(Name) then
Result := Variables[Name]
else raise new SemanticException('íåîáúÿâëåííàÿ ïåðåìåííàÿ "' + Name + '"', Loc);
end;
procedure GConverter.VarToList(Name: string; Variable: SVariableNode);
begin
Name := Name.ToLower;
if not Variables.ContainsKey(Name) then
begin
Variables.Add(Name, Variable);
LocalVars.Add(Name);
end
else
raise new Exception('Ïîâòîðíîå îáüÿâëåíèå ïåðåìåííîé ' + Name);
end;
procedure GConverter.DelVarFromList(Name: string);
begin
Name := Name.ToLower;
Variables.Remove(Name);
LocalVars.Remove(Name);
end;
function NoVoidOrNil(_type: &Type): boolean;
begin
if (_type <> typeof(void)) and (_type <> nil) then
Result := True
else Result := False;
end;
function GConverter.CreateMainFunctionNode: SFunctionNode;
begin
var Func := new NetFunctionNode;
Func.IsFunction := False;
Func.Name := 'Main';
Func.Body := SyntaxTree.MainFunction;
Func.ParametersType := new List<FunctionParameter>;
// Ñîçäàíèå ïàðàìåòðà (string[] args)
var param := new FunctionParameterVar;
param.Name := 'args';
var ArgsArr := new TypeExprArray;
var OfTypeExpr := new TypeExpressionRef;
OfTypeExpr.TypeName := 'system.string';
ArgsArr.OfType := OfTypeExpr;
param.TypeExpr := ArgsArr;
Func.ParametersType.Add(param);
{ Func.IsFunction := True;
var RetType := new TypeExpressionRef;
RetType.TypeName := 'System.Int32';
Func.ReturnType := RetType;}
Result := ConvertFunctionNode(Func);
end;
function GConverter.ConvertFunctionNode(Func: FunctionNode): SFunctionNode;
begin
if Func is NativeFunctionNode then
Result := ConvertFunctionNode((Func as NativeFunctionNode))
else if Func is NetFunctionNode then
Result := ConvertFunctionNode((Func as NetFunctionNode))
else raise new Exception('ôèãíÿ');
end;
function GConverter.ConvertFunctionNode(Func: NativeFunctionNode): SNativeFunctionNode;
begin
Result := new SNativeFunctionNode;
Result.Name := func.Name;
Result.DllName := func.DllName;
Result.DllNameMethod := func.DllNameMethod;
if func.CharSet <> nil then
begin
var d := new Dictionary<string, System.Runtime.InteropServices.CharSet>;
d.Add('ansi', System.Runtime.InteropServices.CharSet.Ansi);
d.Add('auto', System.Runtime.InteropServices.CharSet.Auto);
d.Add('none', System.Runtime.InteropServices.CharSet.None);
d.Add('unicode', System.Runtime.InteropServices.CharSet.Unicode);
if d.ContainsKey(func.CharSet) then
Result.CharSet := d[func.CharSet]
else
raise new Exception('íå îïðåäåëåíà êîäèðîâêà âûçîâà ïîäïðîãðàììû èç íåóïðàâëÿåìîé dll');
end
else Result.CharSet := System.Runtime.InteropServices.CharSet.Unicode; // ïî óìîë÷àíèþ
if (func.IsFunction) then
Result.ReturnType := ConvertTypeExpressionNode(Func.ReturnType)
else
Result.ReturnType := typeof(void);
Result.ParametersType := new List<SParameterNode>;
for var i := 0 to Func.ParametersType.Count - 1 do
begin
if (Func.ParametersType[i] is FunctionParameterVar) then
begin
var SParamType := new SParameterNode;
SParamType.Name := (Func.ParametersType[i] as FunctionParameterVar).Name;
SParamType._Type := ConvertTypeExpressionNode(Func.ParametersType[i].TypeExpr);
Result.ParametersType.Add(SParamType);
end
else if (Func.ParametersType[i] is FunctionParameterList) then
begin
var ParameterList := FunctionParameterList(Func.ParametersType[i]);
var _type := ConvertTypeExpressionNode(ParameterList.TypeExpr);
for var a := 0 to ParameterList.ParList.Count - 1 do
begin
var SParamType := new SParameterNode;
SParamType.Name := ParameterList.ParList[a];
SParamType._Type := _type;
Result.ParametersType.Add(SParamType);
end;
end;
end;
Methods[Func] := Result;
end;
function GConverter.ConvertFunctionNode(Func: NetFunctionNode): SNetFunctionNode;
begin
Result := new SNetFunctionNode;
Result.Name := func.Name;
if (func.IsFunction) then
Result.ReturnType := ConvertTypeExpressionNode(Func.ReturnType)
else
Result.ReturnType := typeof(void);
Result.ParametersType := new List<SParameterNode>;
LabelsName := new List<string>;
Labels := new List<SLabelNode>;
var oldLocalVars := LocalVars;
LocalVars := new List<string>;
for var i := 0 to Func.ParametersType.Count - 1 do
begin
if (Func.ParametersType[i] is FunctionParameterVar) then
begin
var SParamType := new SParameterNode;
SParamType.Name := (Func.ParametersType[i] as FunctionParameterVar).Name;
SParamType._Type := ConvertTypeExpressionNode(Func.ParametersType[i].TypeExpr);
Result.ParametersType.Add(SParamType);
VarToList(SParamType.Name, SParamType)
end
else if (Func.ParametersType[i] is FunctionParameterList) then
begin
var ParameterList := FunctionParameterList(Func.ParametersType[i]);
var _type := ConvertTypeExpressionNode(ParameterList.TypeExpr);
for var a := 0 to ParameterList.ParList.Count - 1 do
begin
var SParamType := new SParameterNode;
SParamType.Name := ParameterList.ParList[a];
SParamType._Type := _type;
Result.ParametersType.Add(SParamType);
VarToList(SParamType.Name, SParamType)
end;
end;
end;
if (func.IsFunction) and (Result.ReturnType <> typeof(void)) then
begin
var ResVar := new SVariableNode;
ResVar._Type := Result.ReturnType;
ResVar.Name := 'result';
VarToList('result', ResVar);
end;
Methods[Func] := Result;
Result.Body := ConvertStatementNode(func.Body);
for var i := 0 to LocalVars.Count - 1 do Variables.Remove(LocalVars.Item[i]);
LocalVars := oldLocalVars;
for var i := 0 to LabelsName.Count - 1 do
begin
if not Labels[i].HasLabelDefNode then
raise new SemanticException(string.Format('Label {0} íèãäå íå îáüÿâëåí, ÷òîáû íà íåãî ññûëàòüñÿ', LabelsName[i]), Labels[i]);
end;
LabelsName.Clear;
Labels.Clear;
end;
function GConverter.GetSelfFunction(Name: string; PassedParameters: List<ExpressionNode>): SCallOwnFunctionNode;
begin
Result := new SCallOwnFunctionNode;
// Äîáàâëåíèå òèïîâ ïàðàìåòðîâ
Result.PassedParameters := new List<SExprNode>;
for var i := 0 to PassedParameters.Count - 1 do
begin
Result.PassedParameters.Add(ConvertExpressionNode(PassedParameters[i]));
end;
var OtherOverloadFunctions := new List<SFunctionNode>;
for var i := 0 to OtherMethods.Count - 1 do
begin
if OtherMethods[i].Name.ToLower = Name then
OtherOverloadFunctions.Add(OtherMethods[i]);
end;
for var i := 0 to OtherOverloadFunctions.Count - 1 do
begin
var ParametersMatch: boolean;
if not (OtherOverloadFunctions[i].ParametersType.Count <> Result.PassedParameters.Count) then
begin
ParametersMatch := True;
for var a := 0 to OtherOverloadFunctions[i].ParametersType.Count - 1 do
begin
if not OtherOverloadFunctions[i].ParametersType[a]._Type.IsAssignableFrom(Result.PassedParameters[a]._Type) then
begin
ParametersMatch := False;
break;
end;
end;
end else ParametersMatch := False;
if ParametersMatch then
begin
Result._Function := OtherOverloadFunctions[i];
Result._Type := OtherOverloadFunctions[i].ReturnType;
exit;
end;
end;
// Ïîèñê overload ôóíêöèé
var OverloadFunctions := new List<FunctionNode>;
for var i := 0 to SyntaxTree.Generic_Functions.Count - 1 do
begin
if SyntaxTree.Generic_Functions[i].Name.ToLower = Name then
OverloadFunctions.Add(SyntaxTree.Generic_Functions[i]);
end;
for var i := 0 to OverloadFunctions.Count - 1 do
begin
var ParametersMatch: boolean;
if not (OverloadFunctions[i].ParametersType.Count <> Result.PassedParameters.Count) then
begin
ParametersMatch := True;
for var a := 0 to OverloadFunctions[i].ParametersType.Count - 1 do
begin
if not ConvertTypeExpressionNode(OverloadFunctions[i].ParametersType[a].TypeExpr).IsAssignableFrom(Result.PassedParameters[a]._Type) then
begin
ParametersMatch := False;
break;
end;
end;
end else ParametersMatch := False;
if ParametersMatch then
begin
var SFunc: SFunctionNode;
if Methods.ContainsKey(OverloadFunctions[i]) then
SFunc := Methods[OverloadFunctions[i]]
else
begin
SFunc := ConvertFunctionNode(OverloadFunctions[i]);
SemanticTree.SGeneric_Functions.Add(SFunc);
end;
Result._Function := SFunc;
Result._Type := SFunc.ReturnType;
exit;
end;
end;
Result := nil;
end;
function GConverter.SelfFunctionExist(Name: string): boolean;
begin
Result := False;
for var i := 0 to SyntaxTree.Generic_Functions.Count - 1 do
if (SyntaxTree.Generic_Functions[i].Name.ToLower) = Name then
begin
Result := True;
exit;
end;
for var i := 0 to OtherMethods.Count - 1 do
if (OtherMethods[i].Name.ToLower) = Name then
begin
Result := True;
exit;
end;
end;
// typeName must be LowerCase
function GConverter.GetType(typeName: string): &Type;
begin
// Îáðàáîòêà íà uses Alias
var typeNameStrArr := typeName.Split('.');
foreach s: string in self.usesAliases.Keys do
begin
if typeNameStrArr[0] = s then
begin
typeName := self.usesAliases[s];
for var i := 1 to typeNameStrArr.Length - 1 do
typeName := typeName + '.' + typeNameStrArr[i];
end;
end;
if Types.ContainsKey(typeName) then
Result := Types[typeName]
else
begin
foreach names: IdentNode in SyntaxTree.Generic_Uses do
begin
if Types.ContainsKey(names.ToString.ToLower + '.' + typeName) then
begin
Result := Types[names.ToString.ToLower + '.' + typeName];
exit;
end;
end;
end;
end;
function GConverter.ParametersMatch(parameters: array of &Type; ParametersInfo: array of ParameterInfo): boolean;
begin
Result := True;
if ParametersInfo.Length = parameters.Length then
begin
for var i := 0 to parameters.Length - 1 do
if not (ParametersInfo[i].ParameterType.IsAssignableFrom(parameters[i])) then
begin
Result := False;
exit;
end;
end else Result := False;
end;
// propName must be LowerCase
function GConverter.GetProperty(_type: &Type; propName: string; ParamTypes: array of &Type): PropertyInfo;
begin
var props := _type.GetProperties;
foreach pi: PropertyInfo in props do
if pi.Name.ToLower = propName then
begin
if ParametersMatch(ParamTypes, pi.GetIndexParameters) then
begin
result := pi;
exit;
end;
end;
end;
// mthdName must be LowerCase
function GConverter.GetMethod(_type: &Type; mthdName: string; ParamTypes: array of &Type): MethodInfo;
begin
var mthds := _type.GetMethods;
foreach mi: MethodInfo in mthds do
if mi.Name.ToLower = mthdName then
begin
if ParametersMatch(ParamTypes, mi.GetParameters) then
begin
result := mi;
exit;
end;
end;
end;
function GConverter.ConvertSubIdentNode(_type: &Type; Ident: IdentNode; IdentParseIndex: integer; ForRead: boolean): SStmtNode;
begin
if not (Ident.IdentList.Count >= 1) then raise new SemanticException('îæèäàëñÿ èäåíòèôèêàòîð', Ident);
var CurRealIdentName := Ident.IdentList[IdentParseIndex];
var CurIdentName := CurRealIdentName.ToLower;
var _Types := new &Type[Ident.BracketList.Count];
var PassPar := new List<SExprNode>;
var SquareTypes := new &Type[Ident.SquareBracketList.Count];
var SquarePassPar := new List<SExprNode>;
if Ident.IdentList.Count - 1 = IdentParseIndex then
begin
for var a := 0 to Ident.BracketList.Count - 1 do
begin
var par := ConvertExpressionNode(Ident.BracketList[a]);
PassPar.Add(par);
_Types[a] := par._Type;
end;
for var a := 0 to Ident.SquareBracketList.Count - 1 do
begin
var par := ConvertExpressionNode(Ident.SquareBracketList[a]);
SquareTypes[a] := par._Type;
SquarePassPar.Add(par);
end;
end;
/// Íåëüçÿ èñïîëüçîâàòü ñòàíäàðòíûé ìåòîä, òàê êàê îí ÷óâñòâèòåëåí ê ðåãèñòðó
var MthdInfo := GetMethod(_type, CurIdentName, _Types);
if MthdInfo <> nil then
begin
var CallFunctionNode := new SCallOtherFunctionNode;
CallFunctionNode.MthdInfo := MthdInfo;
CallFunctionNode._Type := MthdInfo.ReturnType;
CallFunctionNode.PassedParameters := PassPar;
Result := CallFunctionNode;
end
else
begin
var Prop := GetProperty(_type, CurIdentName, SquareTypes);
if Prop <> nil then
begin
var PropertyNode := new SPropertyNode;
PropertyNode.PassedParameters := SquarePassPar;
PropertyNode.NeedRead := ForRead;
PropertyNode.Prop := Prop;
PropertyNode._Type := Prop.PropertyType;
Result := PropertyNode;
end
else
begin
var b := _type;
var d := b.GetMembers(BindingFlags.Public or BindingFlags.Default or BindingFlags.Static);
var g := b.GetMember(CurRealIdentName);
if g.Length = 1 then
for var i := 0 to d.Length - 1 do
if d[i] = g[0] then
begin
var IntLit := new SIntegerLiteral;
IntLit.Value := i;
IntLit._Type := typeof(integer);
Result := IntLit;
end;
end;
end;
if Result = nil then
raise new SemanticException('Íåèçâåñòíûé èäåíòèôèêàòîð ' + CurIdentName, Ident )
else
begin
if ((SquarePassPar.Count > 0)) and (Ident.IdentList.Count = IdentParseIndex - 1) then
begin
if (Result is SExprNode) and NoVoidOrNil((Result as SExprNode)._Type) then
if (Result as SExprNode)._Type.IsArray then
begin
var ArrayElemNode := new SArrayElemNode;
ArrayElemNode.Arr := SExprNode(Result);
ArrayElemNode.Index := SquarePassPar;
ArrayElemNode._Type := (Result as SExprNode)._Type.GetElementType;
Result := ArrayElemNode;
end;
end;
if Ident.IdentList.Count - 1 > IdentParseIndex then
begin
if (Result is SExprNode) and NoVoidOrNil((Result as SExprNode)._Type) then
begin
var FirstStmt := SExprNode(Result);
Result := new SDotNode;
(Result as SDotNode).FirstStmt := FirstStmt;
(Result as SDotNode).SecondStmt := ConvertSubIdentNode(FirstStmt._Type, Ident, IdentParseIndex + 1, ForRead);
if ((Result as SDotNode).SecondStmt is SExprNode) then
(Result as SDotNode)._Type := ((Result as SDotNode).SecondStmt as SExprNode)._Type;
exit;
end else raise new SemanticException(string.Format('{0} íå âîçâðàùàåò íè÷åãî, ïîýòîìó òî÷êà ïîñëå íåãî çàïðåùåíà', CurRealIdentName), Ident);
end
else if Ident.SubIdentNode <> nil then
begin
if (Result is SExprNode) and NoVoidOrNil((Result as SExprNode)._Type) then
begin
var FirstStmt := SExprNode(Result);
Result := new SDotNode;
(Result as SDotNode).FirstStmt := FirstStmt;
(Result as SDotNode).SecondStmt := ConvertSubIdentNode(FirstStmt._Type, Ident.SubIdentNode, 0, ForRead);
if ((Result as SDotNode).SecondStmt is SExprNode) then
(Result as SDotNode)._Type := ((Result as SDotNode).SecondStmt as SExprNode)._Type;
exit;
end else raise new SemanticException(string.Format('{0} íå âîçâðàùàåò íè÷åãî, ïîýòîìó òî÷êà ïîñëå íåãî çàïðåùåíà', CurRealIdentName), Ident);
end;
end;
end;
function GConverter.ConvertIdentNode(Ident: IdentNode; ForRead: boolean): SStmtNode;
begin
var CurRealIdentName := '';
for var IdentParseIndex := 0 to Ident.IdentList.Count - 1 do
begin
if IdentParseIndex = 0 then
CurRealIdentName := Ident.IdentList[IdentParseIndex]
else
CurRealIdentName := CurRealIdentName + '.' + Ident.IdentList[IdentParseIndex];
var CurIdentName := CurRealIdentName.ToLower;
// Åñëè ýòî namespace èëè namespace-alias òî ïðûãàåì äàëüøå
if Namespaces.Contains(CurIdentName) or self.usesAliases.ContainsKey(CurIdentName) then
continue;
if Variables.ContainsKey(CurIdentName) then
Result := GetVar(CurIdentName, Ident)
else if SelfFunctionExist(CurIdentName) then
begin
if Ident.IdentList.Count - 1 = IdentParseIndex then
Result := GetSelfFunction(CurIdentName, Ident.BracketList)
else
begin
Result := GetSelfFunction(CurIdentName, new List<ExpressionNode>);
end;
if Result = nil then raise new SemanticException('íå íàéäåíî ïîäõîäÿùåé ïðîöåäóðû ' + CurRealIdentName, Ident);
end
else
begin
var t := GetType(CurIdentName);
if t <> nil then
begin
Result := ConvertSubIdentNode(t, Ident, IdentParseIndex + 1, ForRead);
exit;
end;
end;
if Result = nil then
raise new SemanticException('Íåèçâåñòíûé èäåíòèôèêàòîð ' + CurIdentName, Ident )
else
begin
if (Ident.IdentList.Count - 1 > IdentParseIndex) and (Result is SExprNode) then
begin
var FirstStmt := SExprNode(Result);
Result := new SDotNode;
(Result as SDotNode).FirstStmt := FirstStmt;
(Result as SDotNode).SecondStmt := ConvertSubIdentNode(FirstStmt._Type, Ident, IdentParseIndex + 1, ForRead);
if ((Result as SDotNode).SecondStmt is SExprNode) then
(Result as SDotNode)._Type := ((Result as SDotNode).SecondStmt as SExprNode)._Type;
exit;
end;
(*
if (Ident.SquareBracketExpr <> nil) and (Ident.IdentList.Count = IdentParseIndex - 1) then
begin
if (Result is SExprNode) and NoVoidOrNil((Result as SExprNode)._Type) then
if (Result as SExprNode)._Type.IsArray then
begin
var ArrayElemNode := new SArrayElemNode;
ArrayElemNode.Arr := SExprNode(Result);
ArrayElemNode.Index := ConvertExpressionNode(Ident.SquareBracketExpr);
ArrayElemNode._Type := (Result as SExprNode)._Type.GetElementType;
Result := ArrayElemNode;
end;
end;
if Ident.IdentList.Count - 1 > IdentParseIndex then
begin
if (Result is SExprNode) and NoVoidOrNil((Result as SExprNode)._Type) then
begin
var FirstStmt := SExprNode(Result);
Result := new SDotNode;
(Result as SDotNode).FirstStmt := FirstStmt;
(Result as SDotNode).SecondStmt := ConvertSubIdentNode(FirstStmt._Type, Ident, IdentParseIndex + 1, ForRead);
if ((Result as SDotNode).SecondStmt is SExprNode) then
(Result as SDotNode)._Type := ((Result as SDotNode).SecondStmt as SExprNode)._Type;
exit;
end else raise new SemanticException(string.Format('{0} íå âîçâðàùàåò íè÷åãî, ïîýòîìó òî÷êà ïîñëå íåãî çàïðåùåíà', CurRealIdentName), Ident);
end
else if Ident.SubIdentNode <> nil then
begin
if (Result is SExprNode) and NoVoidOrNil((Result as SExprNode)._Type) then
begin
var FirstStmt := SExprNode(Result);
Result := new SDotNode;
(Result as SDotNode).DotFirstStmtAdd(FirstStmt);
(Result as SDotNode).SecondStmt := ConvertSubIdentNode(FirstStmt._Type, Ident.SubIdentNode, 0, ForRead);
if ((Result as SDotNode).SecondStmt is SExprNode) then
(Result as SDotNode)._Type := ((Result as SDotNode).SecondStmt as SExprNode)._Type;
exit;
end else raise new SemanticException(string.Format('{0} íå âîçâðàùàåò íè÷åãî, ïîýòîìó òî÷êà ïîñëå íåãî çàïðåùåíà', CurRealIdentName), Ident);
end; *)
end;
end; // for
end;
function GConverter.ConvertStatementNode(Stmt: StatementNode): SStmtNode;
label 53;
begin
if Stmt = nil then
begin
Result := nil;
exit;
end;
if (Stmt is StatementsNode) then
begin
Result := new SStmtListNode;
(Result as SStmtListNode).StmtList := new List<SStmtNode>;
var oldLocalVars := LocalVars;
LocalVars := new List<string>;
for var i := 0 to (Stmt as StatementsNode).Statements.Count - 1 do
(Result as SStmtListNode).StmtList.Add(ConvertStatementNode((Stmt as StatementsNode).Statements[i]));
for var i := 0 to LocalVars.Count - 1 do Variables.Remove(LocalVars.Item[i]);
LocalVars := oldLocalVars;
end
else if (Stmt is ExitNode) then
begin
Result := new SExitNode;
end
else if (Stmt is BreakNode) then
begin
Result := new SBreakNode;
end
else if (Stmt is ContinueNode) then
begin
Result := new SContinueNode;
end
else if (Stmt is ReturnNode) then
begin
Result := new SReturnNode;
(Result as SReturnNode).Expr := ConvertExpressionNode((Stmt as ReturnNode).Expr);
end
else if (Stmt is PrintNode) then
begin
Result := new SPrintNode;
(Result as SPrintNode).Expr := ConvertExpressionNode((Stmt as PrintNode).Expr);
end
else if (Stmt is RaiseNode) then
begin
Result := new SRaiseNode;
(Result as SRaiseNode).Expr := ConvertExpressionNode((Stmt as RaiseNode).Expr);
if typeof(System.Exception).IsSubclassOf((Result as SRaiseNode).Expr._Type) then
raise new SemanticException('Òèï èñêëþ÷åíèÿ äîëæåí áûòü System.Exception èëè åãî ïîòîìêîì',
(Stmt as RaiseNode).Expr);
end
else if (Stmt is AssignNode) then
begin
var AssignN := AssignNode(Stmt);
var t := ConvertIdentNode(AssignN.Ident, false);
if (t is SVariableNode) then
begin
Result := new SVarAssignNode;
(Result as SVarAssignNode).Expr := ConvertExpressionNode(AssignN.Expr);
(Result as SVarAssignNode).Variable := SVariableNode(t)
end
else if (t is SPropertyNode) then
begin
Result := new SPropertyAssignNode;
(Result as SPropertyAssignNode).Expr := ConvertExpressionNode(AssignN.Expr);
(Result as SPropertyAssignNode).Prop := SPropertyNode(t);
end
else if (t is SArrayElemNode) then
begin
Result := new SArrayAssignNode;
(Result as SArrayAssignNode).Expr := ConvertExpressionNode(AssignN.Expr);
(Result as SArrayAssignNode).Arr := SArrayElemNode(t);
end
else if (t is SDotNode) and (((t as SDotNode).SecondStmt is SVariableNode)
or ((t as SDotNode).SecondStmt is SPropertyNode) or ((t as SDotNode).SecondStmt is SArrayElemNode)) then
begin
Result := new SDotAssignNode;
(Result as SDotAssignNode).Expr := ConvertExpressionNode(AssignN.Expr);
(Result as SDotAssignNode).DotNode := SDotNode(t);
end
else raise new SemanticException('íå íàéäåíà ïåðåìåííàÿ', AssignN)
end
else if (Stmt is TypeDeclareNode) then
begin
var TypeDeclareStmt := TypeDeclareNode(stmt);
if TypeDeclareStmt.VarList.Count = 1 then
begin
var SDeclare := new SDeclareNode;
SDeclare.Name := TypeDeclareStmt.VarList[0];
SDeclare._Type := ConvertTypeExpressionNode(TypeDeclareStmt.Expr);
VarToList(SDeclare.Name, SDeclare);