source: branches/xpascal/Executor.pas

Last change on this file was 236, checked in by chronos, 11 months ago
  • Fixed: Var function parameters processed correctly for both user defined and internal functions.
File size: 38.0 KB
Line 
1unit Executor;
2
3interface
4
5uses
6 Classes, SysUtils, Source, Generics.Collections;
7
8type
9 TExecutorFunctions = class;
10 TExecutorBlock = class;
11
12 TExecutorVariableKind = (vkNormal, vkReference);
13
14 { TExecutorVariable }
15
16 TExecutorVariable = class
17 private
18 FValue: TValue;
19 function GetValue: TValue;
20 procedure SetValue(AValue: TValue);
21 public
22 Variable: TVariable;
23 Kind: TExecutorVariableKind;
24 RefVariable: TExecutorVariable;
25 constructor Create;
26 destructor Destroy; override;
27 property Value: TValue read GetValue write SetValue;
28 end;
29
30 { TExecutorVariables }
31
32 TExecutorVariables = class(TObjectList<TExecutorVariable>)
33 function SearchByVariable(Variable: TVariable): TExecutorVariable;
34 function AddNew(Variable: TVariable): TExecutorVariable;
35 end;
36
37 { TExecutorType }
38
39 TExecutorType = class
40 TypeRef: TType;
41 Functions: TExecutorFunctions;
42 constructor Create;
43 destructor Destroy; override;
44 end;
45
46 { TExecutorTypes }
47
48 TExecutorTypes = class(TObjectList<TExecutorType>)
49 function SearchByType(TypeRef: TType): TExecutorType;
50 function AddNew(TypeRef: TType): TExecutorType;
51 end;
52
53 TExecutorFunctionCallback = function(Params: array of TExecutorVariable):
54 TValue of object;
55
56 { TExecutorFunction }
57
58 TExecutorFunction = class
59 FunctionDef: TFunction;
60 Block: TExecutorBlock;
61 Callback: TExecutorFunctionCallback;
62 constructor Create;
63 destructor Destroy; override;
64 end;
65
66 { TExecutorFunctions }
67
68 TExecutorFunctions = class(TObjectList<TExecutorFunction>)
69 function SearchByFunction(FunctionDef: TFunction): TExecutorFunction;
70 function AddNew(FunctionDef: TFunction): TExecutorFunction;
71 end;
72
73 { TExecutorProcedure }
74
75 TExecutorProcedure = class
76 ProcedureDef: TProcedure;
77 Block: TExecutorBlock;
78 Callback: TExecutorFunctionCallback;
79 constructor Create;
80 destructor Destroy; override;
81 end;
82
83 { TExecutorProcedures }
84
85 TExecutorProcedures = class(TObjectList<TExecutorProcedure>)
86 function SearchByProcedure(ProcedureDef: TProcedure): TExecutorProcedure;
87 function AddNew(ProcedureDef: TProcedure): TExecutorProcedure;
88 end;
89
90 { TExecutorBlock }
91
92 TExecutorBlock = class
93 Parent: TExecutorBlock;
94 Types: TExecutorTypes;
95 Variables: TExecutorVariables;
96 Functions: TExecutorFunctions;
97 Procedures: TExecutorProcedures;
98 function GetFunction(FunctionDef: TFunction): TExecutorFunction;
99 function GetProcedure(ProcedureDef: TProcedure): TExecutorProcedure;
100 function GetType(TypeDef: TType): TExecutorType;
101 function GetVariable(Variable: TVariable): TExecutorVariable;
102 function GetTypeFunction(TypeDef: TType; FunctionDef: TFunction): TExecutorFunction; overload;
103 function GetTypeFunction(TypeDef: TType; FunctionName: string): TExecutorFunction; overload;
104 constructor Create;
105 destructor Destroy; override;
106 end;
107
108 TOutputEvent = procedure (Text: string) of object;
109 TInputEvent = function: string of object;
110
111 { TExecutor }
112
113 TExecutor = class
114 private
115 FOnOutput: TOutputEvent;
116 FOnInput: TInputEvent;
117 SystemBlock: TExecutorBlock;
118 function ExecuteWriteLn(Params: array of TExecutorVariable): TValue;
119 function ExecuteWrite(Params: array of TExecutorVariable): TValue;
120 function ExecuteReadLn(Params: array of TExecutorVariable): TValue;
121 function ExecuteRead(Params: array of TExecutorVariable): TValue;
122 function ExecuteIntToStr(Params: array of TExecutorVariable): TValue;
123 function ExecuteStrToInt(Params: array of TExecutorVariable): TValue;
124 function ExecuteBoolToStr(Params: array of TExecutorVariable): TValue;
125 function ExecuteStrToBool(Params: array of TExecutorVariable): TValue;
126 function ExecuteBooleanAssign(Params: array of TExecutorVariable): TValue;
127 function ExecuteBooleanNot(Params: array of TExecutorVariable): TValue;
128 function ExecuteBooleanEqual(Params: array of TExecutorVariable): TValue;
129 function ExecuteBooleanNotEqual(Params: array of TExecutorVariable): TValue;
130 function ExecuteStringAssign(Params: array of TExecutorVariable): TValue;
131 function ExecuteStringAdd(Params: array of TExecutorVariable): TValue;
132 function ExecuteStringEqual(Params: array of TExecutorVariable): TValue;
133 function ExecuteStringNotEqual(Params: array of TExecutorVariable): TValue;
134 function ExecuteIntegerAssign(Params: array of TExecutorVariable): TValue;
135 function ExecuteIntegerAdd(Params: array of TExecutorVariable): TValue;
136 function ExecuteIntegerSub(Params: array of TExecutorVariable): TValue;
137 function ExecuteIntegerMul(Params: array of TExecutorVariable): TValue;
138 function ExecuteIntegerIntDiv(Params: array of TExecutorVariable): TValue;
139 function ExecuteIntegerMod(Params: array of TExecutorVariable): TValue;
140 function ExecuteIntegerEqual(Params: array of TExecutorVariable): TValue;
141 function ExecuteIntegerNotEqual(Params: array of TExecutorVariable): TValue;
142 function ExecuteIntegerLesser(Params: array of TExecutorVariable): TValue;
143 function ExecuteIntegerHigher(Params: array of TExecutorVariable): TValue;
144 function ExecuteIntegerLesserOrEqual(Params: array of TExecutorVariable): TValue;
145 function ExecuteIntegerHigherOrEqual(Params: array of TExecutorVariable): TValue;
146 function ExecuteIntegerAnd(Params: array of TExecutorVariable): TValue;
147 function ExecuteIntegerOr(Params: array of TExecutorVariable): TValue;
148 function ExecuteIntegerXor(Params: array of TExecutorVariable): TValue;
149 function ExecuteIntegerShr(Params: array of TExecutorVariable): TValue;
150 function ExecuteIntegerShl(Params: array of TExecutorVariable): TValue;
151 procedure InitExecutorBlock(ExecutorBlock: TExecutorBlock; Block: TBlock);
152 public
153 Prog: TProgram;
154 procedure ExecuteProgram(Prog: TProgram);
155 procedure ExecuteBeginEnd(Block: TExecutorBlock; BeginEnd: TBeginEnd);
156 procedure ExecuteCommand(Block: TExecutorBlock; Command: TCommand);
157 procedure ExecuteIfThenElse(Block: TExecutorBlock; IfThenElse: TIfThenElse);
158 procedure ExecuteWhileDo(Block: TExecutorBlock; WhileDo: TWhileDo);
159 procedure ExecuteRepeatUntil(Block: TExecutorBlock; RepeatUntil: TRepeatUntil);
160 procedure ExecuteForToDo(Block: TExecutorBlock; ForToDo: TForToDo);
161 procedure ExecuteContinue(Block: TExecutorBlock; ContinueCmd: TContinue);
162 procedure ExecuteBreak(Block: TExecutorBlock; BreakCmd: TBreak);
163 procedure ExecuteBlock(ParentBlock: TExecutorBlock; Block: TBlock; ExistingBlock: TExecutorBlock = nil);
164 function ExecuteFunctionCall(Block: TExecutorBlock; FunctionCall: TFunctionCall): TValue;
165 procedure ExecuteProcedureCall(Block: TExecutorBlock; ProcedureCall: TProcedureCall);
166 procedure ExecuteAssignment(Block: TExecutorBlock; Assignment: TAssignment);
167 function ExecuteExpression(Block: TExecutorBlock; Expression: TExpression): TValue;
168 function ExecuteExpressionOperation(Block: TExecutorBlock; Expression: TExpressionOperation): TValue;
169 function ExecuteExpressionOperand(Block: TExecutorBlock; Expression: TExpressionOperand): TValue;
170 function ExecuteExpressionBrackets(Block: TExecutorBlock; Expression: TExpressionBrackets): TValue;
171 procedure Run;
172 procedure Output(Text: string);
173 function Input: string;
174 property OnOutput: TOutputEvent read FOnOutput write FOnOutput;
175 property OnInput: TInputEvent read FOnInput write FOnInput;
176 end;
177
178
179implementation
180
181uses
182 SourceNode;
183
184resourcestring
185 SUnsupportedOperandType = 'Unsupported exception operand type.';
186 SUnsupportedCommandType = 'Unsupported command type.';
187 SExpectedBooleanValue = 'Expected boolean value.';
188
189{ TExecutorProcedures }
190
191function TExecutorProcedures.SearchByProcedure(ProcedureDef: TProcedure
192 ): TExecutorProcedure;
193var
194 I: Integer;
195begin
196 I := 0;
197 while (I < Count) and (Items[I].ProcedureDef <> ProcedureDef) do Inc(I);
198 if I < Count then Result := Items[I]
199 else Result := nil;
200end;
201
202function TExecutorProcedures.AddNew(ProcedureDef: TProcedure
203 ): TExecutorProcedure;
204begin
205 Result := TExecutorProcedure.Create;
206 Result.ProcedureDef := ProcedureDef;
207 Add(Result);
208end;
209
210{ TExecutorProcedure }
211
212constructor TExecutorProcedure.Create;
213begin
214 Block := TExecutorBlock.Create;
215end;
216
217destructor TExecutorProcedure.Destroy;
218begin
219 FreeAndNil(Block);
220 inherited;
221end;
222
223{ TExecutorFunction }
224
225constructor TExecutorFunction.Create;
226begin
227 Block := TExecutorBlock.Create;
228end;
229
230destructor TExecutorFunction.Destroy;
231begin
232 FreeAndNil(Block);
233 inherited;
234end;
235
236{ TExecutorVariable }
237
238procedure TExecutorVariable.SetValue(AValue: TValue);
239begin
240 if FValue = AValue then Exit;
241 if Kind = vkNormal then begin
242 FreeAndNil(FValue);
243 FValue := AValue;
244 end else
245 if Kind = vkReference then begin
246 RefVariable.Value := AValue;
247 end;
248end;
249
250function TExecutorVariable.GetValue: TValue;
251begin
252 if Kind = vkNormal then begin
253 Result := FValue;
254 end else
255 if Kind = vkReference then begin
256 Result := RefVariable.Value;
257 end;
258end;
259
260constructor TExecutorVariable.Create;
261begin
262 Value := TValue.Create;
263end;
264
265destructor TExecutorVariable.Destroy;
266begin
267 FreeAndNil(FValue);
268 inherited;
269end;
270
271{ TExecutorType }
272
273constructor TExecutorType.Create;
274begin
275 Functions := TExecutorFunctions.Create;
276end;
277
278destructor TExecutorType.Destroy;
279begin
280 FreeAndNil(Functions);
281 inherited;
282end;
283
284{ TExecutorTypes }
285
286function TExecutorTypes.SearchByType(TypeRef: TType): TExecutorType;
287var
288 I: Integer;
289begin
290 I := 0;
291 while (I < Count) and (Items[I].TypeRef <> TypeRef) do Inc(I);
292 if I < Count then Result := Items[I]
293 else Result := nil;
294end;
295
296function TExecutorTypes.AddNew(TypeRef: TType): TExecutorType;
297begin
298 Result := TExecutorType.Create;
299 Result.TypeRef := TypeRef;
300 Add(Result);
301end;
302
303{ TExecutorFunctions }
304
305function TExecutorFunctions.SearchByFunction(FunctionDef: TFunction
306 ): TExecutorFunction;
307var
308 I: Integer;
309begin
310 I := 0;
311 while (I < Count) and (Items[I].FunctionDef <> FunctionDef) do Inc(I);
312 if I < Count then Result := Items[I]
313 else Result := nil;
314end;
315
316function TExecutorFunctions.AddNew(FunctionDef: TFunction): TExecutorFunction;
317begin
318 Result := TExecutorFunction.Create;
319 Result.FunctionDef := FunctionDef;
320 Add(Result);
321end;
322
323{ TExecutorVariables }
324
325function TExecutorVariables.SearchByVariable(Variable: TVariable): TExecutorVariable;
326var
327 I: Integer;
328begin
329 I := 0;
330 while (I < Count) and (Items[I].Variable <> Variable) do Inc(I);
331 if I < Count then Result := Items[I]
332 else Result := nil;
333end;
334
335function TExecutorVariables.AddNew(Variable: TVariable): TExecutorVariable;
336begin
337 Result := TExecutorVariable.Create;
338 Result.Variable := Variable;
339 Add(Result);
340end;
341
342{ TExecutorBlock }
343
344function TExecutorBlock.GetFunction(FunctionDef: TFunction): TExecutorFunction;
345begin
346 Result := Functions.SearchByFunction(FunctionDef);
347 if not Assigned(Result) and Assigned(Parent) then
348 Result := Parent.GetFunction(FunctionDef);
349end;
350
351function TExecutorBlock.GetProcedure(ProcedureDef: TProcedure
352 ): TExecutorProcedure;
353begin
354 Result := Procedures.SearchByProcedure(ProcedureDef);
355 if not Assigned(Result) and Assigned(Parent) then
356 Result := Parent.GetProcedure(ProcedureDef);
357end;
358
359function TExecutorBlock.GetType(TypeDef: TType): TExecutorType;
360begin
361 Result := Types.SearchByType(TypeDef);
362 if not Assigned(Result) and Assigned(Parent) then
363 Result := Parent.GetType(TypeDef);
364end;
365
366function TExecutorBlock.GetVariable(Variable: TVariable): TExecutorVariable;
367begin
368 Result := Variables.SearchByVariable(Variable);
369 if not Assigned(Result) and Assigned(Parent) then
370 Result := Parent.GetVariable(Variable);
371end;
372
373function TExecutorBlock.GetTypeFunction(TypeDef: TType; FunctionDef: TFunction
374 ): TExecutorFunction;
375var
376 ExecutorType: TExecutorType;
377begin
378 ExecutorType := GetType(TypeDef);
379 Result := ExecutorType.Functions.SearchByFunction(FunctionDef);
380end;
381
382function TExecutorBlock.GetTypeFunction(TypeDef: TType; FunctionName: string
383 ): TExecutorFunction;
384begin
385 Result := GetTypeFunction(TypeDef, TypeDef.Functions.SearchByName(FunctionName));
386end;
387
388constructor TExecutorBlock.Create;
389begin
390 Types := TExecutorTypes.Create;
391 Variables := TExecutorVariables.Create;
392 Functions := TExecutorFunctions.Create;
393 Procedures := TExecutorProcedures.Create;
394end;
395
396destructor TExecutorBlock.Destroy;
397begin
398 FreeAndNil(Variables);
399 FreeAndNil(Functions);
400 FreeAndNil(Procedures);
401 FreeAndNil(Types);
402 inherited;
403end;
404
405{ TExecutor }
406
407function TExecutor.ExecuteWriteLn(Params: array of TExecutorVariable): TValue;
408var
409 I: Integer;
410 Text: string;
411begin
412 Result := nil;
413 Text := '';
414 for I := 0 to Length(Params) - 1 do
415 Text := Text + TValueString(Params[I].Value).Value;
416 Output(Text + LineEnding);
417end;
418
419function TExecutor.ExecuteWrite(Params: array of TExecutorVariable): TValue;
420var
421 I: Integer;
422 Text: string;
423begin
424 Result := nil;
425 Text := '';
426 for I := 0 to Length(Params) - 1 do
427 Text := Text + TValueString(Params[I].Value).Value;
428 Output(Text);
429end;
430
431function TExecutor.ExecuteReadLn(Params: array of TExecutorVariable): TValue;
432var
433 I: Integer;
434begin
435 Result := nil;
436 for I := 0 to Length(Params) - 1 do begin
437 TValueString(Params[I].Value).Value := Input;
438 end;
439 Output(LineEnding);
440end;
441
442function TExecutor.ExecuteRead(Params: array of TExecutorVariable): TValue;
443var
444 I: Integer;
445begin
446 Result := nil;
447 for I := 0 to Length(Params) - 1 do
448 TValueString(Params[I].Value).Value := Input;
449end;
450
451function TExecutor.ExecuteIntToStr(Params: array of TExecutorVariable): TValue;
452begin
453 Result := TValueString.Create;
454 TValueString(Result).Value := IntToStr(TValueInteger(Params[0].Value).Value);
455end;
456
457function TExecutor.ExecuteStrToInt(Params: array of TExecutorVariable): TValue;
458begin
459 Result := TValueInteger.Create;
460 TValueInteger(Result).Value := StrToInt(TValueString(Params[0].Value).Value);
461end;
462
463function TExecutor.ExecuteBoolToStr(Params: array of TExecutorVariable): TValue;
464begin
465 Result := TValueString.Create;
466 TValueString(Result).Value := BoolToStr(TValueBoolean(Params[0].Value).Value);
467end;
468
469function TExecutor.ExecuteStrToBool(Params: array of TExecutorVariable): TValue;
470begin
471 Result := TValueBoolean.Create;
472 TValueBoolean(Result).Value := StrToBool(TValueString(Params[0].Value).Value);
473end;
474
475function TExecutor.ExecuteBooleanAssign(Params: array of TExecutorVariable): TValue;
476begin
477 Result := TValueBoolean.Create;
478 TValueBoolean(Result).Value := TValueBoolean(Params[0].Value).Value;
479end;
480
481function TExecutor.ExecuteBooleanNot(Params: array of TExecutorVariable): TValue;
482begin
483 Result := TValueBoolean.Create;
484 TValueBoolean(Result).Value := not TValueBoolean(Params[0].Value).Value;
485end;
486
487function TExecutor.ExecuteBooleanEqual(Params: array of TExecutorVariable): TValue;
488begin
489 Result := TValueBoolean.Create;
490 TValueBoolean(Result).Value := TValueBoolean(Params[0].Value).Value =
491 TValueBoolean(Params[1].Value).Value;
492end;
493
494function TExecutor.ExecuteBooleanNotEqual(Params: array of TExecutorVariable): TValue;
495begin
496 Result := TValueBoolean.Create;
497 TValueBoolean(Result).Value := TValueBoolean(Params[0].Value).Value <>
498 TValueBoolean(Params[1].Value).Value;
499end;
500
501function TExecutor.ExecuteStringAssign(Params: array of TExecutorVariable): TValue;
502begin
503 Result := TValueString.Create;
504 TValueString(Result).Value := TValueString(Params[0].Value).Value;
505end;
506
507function TExecutor.ExecuteStringAdd(Params: array of TExecutorVariable): TValue;
508begin
509 Result := TValueString.Create;
510 TValueString(Result).Value := TValueString(Params[0].Value).Value +
511 TValueString(Params[1].Value).Value;
512end;
513
514function TExecutor.ExecuteStringEqual(Params: array of TExecutorVariable): TValue;
515begin
516 Result := TValueBoolean.Create;
517 TValueBoolean(Result).Value := TValueString(Params[0].Value).Value =
518 TValueString(Params[1].Value).Value;
519end;
520
521function TExecutor.ExecuteStringNotEqual(Params: array of TExecutorVariable): TValue;
522begin
523 Result := TValueBoolean.Create;
524 TValueBoolean(Result).Value := TValueString(Params[0].Value).Value <>
525 TValueString(Params[1].Value).Value;
526end;
527
528function TExecutor.ExecuteIntegerAssign(Params: array of TExecutorVariable): TValue;
529begin
530 Result := TValueInteger.Create;
531 TValueInteger(Result).Value := TValueInteger(Params[0].Value).Value;
532end;
533
534function TExecutor.ExecuteIntegerAdd(Params: array of TExecutorVariable): TValue;
535begin
536 Result := TValueInteger.Create;
537 TValueInteger(Result).Value := TValueInteger(Params[0].Value).Value +
538 TValueInteger(Params[1].Value).Value;
539end;
540
541function TExecutor.ExecuteIntegerSub(Params: array of TExecutorVariable): TValue;
542begin
543 Result := TValueInteger.Create;
544 TValueInteger(Result).Value := TValueInteger(Params[0].Value).Value -
545 TValueInteger(Params[1].Value).Value;
546end;
547
548function TExecutor.ExecuteIntegerMul(Params: array of TExecutorVariable): TValue;
549begin
550 Result := TValueInteger.Create;
551 TValueInteger(Result).Value := TValueInteger(Params[0].Value).Value *
552 TValueInteger(Params[1].Value).Value;
553end;
554
555function TExecutor.ExecuteIntegerIntDiv(Params: array of TExecutorVariable): TValue;
556begin
557 Result := TValueInteger.Create;
558 TValueInteger(Result).Value := TValueInteger(Params[0].Value).Value div
559 TValueInteger(Params[1].Value).Value;
560end;
561
562function TExecutor.ExecuteIntegerMod(Params: array of TExecutorVariable): TValue;
563begin
564 Result := TValueInteger.Create;
565 TValueInteger(Result).Value := TValueInteger(Params[0].Value).Value mod
566 TValueInteger(Params[1].Value).Value;
567end;
568
569function TExecutor.ExecuteIntegerEqual(Params: array of TExecutorVariable): TValue;
570begin
571 Result := TValueBoolean.Create;
572 TValueBoolean(Result).Value := TValueInteger(Params[0].Value).Value =
573 TValueInteger(Params[1].Value).Value;
574end;
575
576function TExecutor.ExecuteIntegerNotEqual(Params: array of TExecutorVariable): TValue;
577begin
578 Result := TValueBoolean.Create;
579 TValueBoolean(Result).Value := TValueInteger(Params[0].Value).Value <>
580 TValueInteger(Params[1].Value).Value;
581end;
582
583function TExecutor.ExecuteIntegerLesser(Params: array of TExecutorVariable): TValue;
584begin
585 Result := TValueBoolean.Create;
586 TValueBoolean(Result).Value := TValueInteger(Params[0].Value).Value <
587 TValueInteger(Params[1].Value).Value;
588end;
589
590function TExecutor.ExecuteIntegerHigher(Params: array of TExecutorVariable): TValue;
591begin
592 Result := TValueBoolean.Create;
593 TValueBoolean(Result).Value := TValueInteger(Params[0].Value).Value >
594 TValueInteger(Params[1].Value).Value;
595end;
596
597function TExecutor.ExecuteIntegerLesserOrEqual(Params: array of TExecutorVariable): TValue;
598begin
599 Result := TValueBoolean.Create;
600 TValueBoolean(Result).Value := TValueInteger(Params[0].Value).Value <=
601 TValueInteger(Params[1].Value).Value;
602end;
603
604function TExecutor.ExecuteIntegerHigherOrEqual(Params: array of TExecutorVariable): TValue;
605begin
606 Result := TValueBoolean.Create;
607 TValueBoolean(Result).Value := TValueInteger(Params[0].Value).Value >=
608 TValueInteger(Params[1].Value).Value;
609end;
610
611function TExecutor.ExecuteIntegerAnd(Params: array of TExecutorVariable): TValue;
612begin
613 Result := TValueInteger.Create;
614 TValueInteger(Result).Value := TValueInteger(Params[0].Value).Value and
615 TValueInteger(Params[1].Value).Value;
616end;
617
618function TExecutor.ExecuteIntegerOr(Params: array of TExecutorVariable): TValue;
619begin
620 Result := TValueInteger.Create;
621 TValueInteger(Result).Value := TValueInteger(Params[0].Value).Value or
622 TValueInteger(Params[1].Value).Value;
623end;
624
625function TExecutor.ExecuteIntegerXor(Params: array of TExecutorVariable): TValue;
626begin
627 Result := TValueInteger.Create;
628 TValueInteger(Result).Value := TValueInteger(Params[0].Value).Value xor
629 TValueInteger(Params[1].Value).Value;
630end;
631
632function TExecutor.ExecuteIntegerShr(Params: array of TExecutorVariable): TValue;
633begin
634 Result := TValueInteger.Create;
635 TValueInteger(Result).Value := TValueInteger(Params[0].Value).Value shr
636 TValueInteger(Params[1].Value).Value;
637end;
638
639function TExecutor.ExecuteIntegerShl(Params: array of TExecutorVariable): TValue;
640begin
641 Result := TValueInteger.Create;
642 TValueInteger(Result).Value := TValueInteger(Params[0].Value).Value shl
643 TValueInteger(Params[1].Value).Value;
644end;
645
646procedure TExecutor.InitExecutorBlock(ExecutorBlock: TExecutorBlock; Block: TBlock);
647var
648 I: Integer;
649 J: Integer;
650 ExecutorFunction: TExecutorFunction;
651 ExecutorProcedure: TExecutorProcedure;
652 ExecutorType: TExecutorType;
653begin
654 for I := 0 to Block.Types.Count - 1 do begin
655 ExecutorType := ExecutorBlock.Types.AddNew(TType(Block.Types[I]));
656 for J := 0 to ExecutorType.TypeRef.Functions.Count - 1 do begin
657 ExecutorFunction := ExecutorType.Functions.AddNew(TFunction(ExecutorType.TypeRef.Functions[J]));
658 if ExecutorType.TypeRef.Name = 'Boolean' then begin
659 if ExecutorFunction.FunctionDef.Name = '_Assign' then begin
660 ExecutorFunction.Callback := ExecuteBooleanAssign;
661 end else
662 if ExecutorFunction.FunctionDef.Name = '_Equal' then begin
663 ExecutorFunction.Callback := ExecuteBooleanEqual;
664 end;
665 if ExecutorFunction.FunctionDef.Name = '_NotEqual' then begin
666 ExecutorFunction.Callback := ExecuteBooleanNotEqual;
667 end;
668 if ExecutorFunction.FunctionDef.Name = '_Not' then begin
669 ExecutorFunction.Callback := ExecuteBooleanNot;
670 end else
671 end else
672 if ExecutorType.TypeRef.Name = 'string' then begin
673 if ExecutorFunction.FunctionDef.Name = '_Assign' then begin
674 ExecutorFunction.Callback := ExecuteStringAssign;
675 end else
676 if ExecutorFunction.FunctionDef.Name = '_Add' then begin
677 ExecutorFunction.Callback := ExecuteStringAdd;
678 end else
679 if ExecutorFunction.FunctionDef.Name = '_Equal' then begin
680 ExecutorFunction.Callback := ExecuteStringEqual;
681 end;
682 if ExecutorFunction.FunctionDef.Name = '_NotEqual' then begin
683 ExecutorFunction.Callback := ExecuteStringNotEqual;
684 end;
685 end else
686 if ExecutorType.TypeRef.Name = 'Integer' then begin
687 if ExecutorFunction.FunctionDef.Name = '_Assign' then begin
688 ExecutorFunction.Callback := ExecuteIntegerAssign;
689 end else
690 if ExecutorFunction.FunctionDef.Name = '_Add' then begin
691 ExecutorFunction.Callback := ExecuteIntegerAdd;
692 end else
693 if ExecutorFunction.FunctionDef.Name = '_Sub' then begin
694 ExecutorFunction.Callback := ExecuteIntegerSub;
695 end else
696 if ExecutorFunction.FunctionDef.Name = '_Mul' then begin
697 ExecutorFunction.Callback := ExecuteIntegerMul;
698 end else
699 if ExecutorFunction.FunctionDef.Name = '_IntDiv' then begin
700 ExecutorFunction.Callback := ExecuteIntegerIntDiv;
701 end else
702 if ExecutorFunction.FunctionDef.Name = '_IntMod' then begin
703 ExecutorFunction.Callback := ExecuteIntegerMod;
704 end else
705 if ExecutorFunction.FunctionDef.Name = '_Equal' then begin
706 ExecutorFunction.Callback := ExecuteIntegerEqual;
707 end else
708 if ExecutorFunction.FunctionDef.Name = '_NotEqual' then begin
709 ExecutorFunction.Callback := ExecuteIntegerNotEqual;
710 end;
711 if ExecutorFunction.FunctionDef.Name = '_Lesser' then begin
712 ExecutorFunction.Callback := ExecuteIntegerLesser;
713 end else
714 if ExecutorFunction.FunctionDef.Name = '_Higher' then begin
715 ExecutorFunction.Callback := ExecuteIntegerHigher;
716 end;
717 if ExecutorFunction.FunctionDef.Name = '_LesserOrEqual' then begin
718 ExecutorFunction.Callback := ExecuteIntegerLesserOrEqual;
719 end else
720 if ExecutorFunction.FunctionDef.Name = '_HigherOrEqual' then begin
721 ExecutorFunction.Callback := ExecuteIntegerHigherOrEqual;
722 end;
723 if ExecutorFunction.FunctionDef.Name = '_And' then begin
724 ExecutorFunction.Callback := ExecuteIntegerAnd;
725 end;
726 if ExecutorFunction.FunctionDef.Name = '_Or' then begin
727 ExecutorFunction.Callback := ExecuteIntegerOr;
728 end;
729 if ExecutorFunction.FunctionDef.Name = '_Xor' then begin
730 ExecutorFunction.Callback := ExecuteIntegerXor;
731 end;
732 if ExecutorFunction.FunctionDef.Name = '_Shr' then begin
733 ExecutorFunction.Callback := ExecuteIntegerShr;
734 end;
735 if ExecutorFunction.FunctionDef.Name = '_Shl' then begin
736 ExecutorFunction.Callback := ExecuteIntegerShl;
737 end;
738 end;
739 end;
740 end;
741
742 for I := 0 to Block.Variables.Count - 1 do begin
743 ExecutorBlock.Variables.AddNew(TVariable(Block.Variables[I]));
744 end;
745
746 for I := 0 to Block.Functions.Count - 1 do begin
747 ExecutorFunction := ExecutorBlock.Functions.AddNew(TFunction(Block.Functions[I]));
748 if ExecutorFunction.FunctionDef.Name = 'IntToStr' then begin
749 ExecutorFunction.Callback := ExecuteIntToStr;
750 end else
751 if ExecutorFunction.FunctionDef.Name = 'StrToInt' then begin
752 ExecutorFunction.Callback := ExecuteStrToInt;
753 end else
754 if ExecutorFunction.FunctionDef.Name = 'BoolToStr' then begin
755 ExecutorFunction.Callback := ExecuteBoolToStr;
756 end else
757 if ExecutorFunction.FunctionDef.Name = 'StrToBool' then begin
758 ExecutorFunction.Callback := ExecuteStrToBool;
759 end;
760 end;
761
762 for I := 0 to Block.Procedures.Count - 1 do begin
763 ExecutorProcedure := ExecutorBlock.Procedures.AddNew(TProcedure(Block.Procedures[I]));
764 if ExecutorProcedure.ProcedureDef.Name = 'Write' then begin
765 ExecutorProcedure.Callback := ExecuteWrite;
766 end else
767 if ExecutorProcedure.ProcedureDef.Name = 'WriteLn' then begin
768 ExecutorProcedure.Callback := ExecuteWriteLn;
769 end else
770 if ExecutorProcedure.ProcedureDef.Name = 'Read' then begin
771 ExecutorProcedure.Callback := ExecuteRead;
772 end else
773 if ExecutorProcedure.ProcedureDef.Name = 'ReadLn' then begin
774 ExecutorProcedure.Callback := ExecuteReadLn;
775 end;
776 end;
777end;
778
779procedure TExecutor.ExecuteProgram(Prog: TProgram);
780begin
781 SystemBlock := TExecutorBlock.Create;
782 InitExecutorBlock(SystemBlock, Prog.SystemBlock);
783 ExecuteBlock(SystemBlock, Prog.Block);
784 SystemBlock.Free;
785end;
786
787procedure TExecutor.ExecuteBeginEnd(Block: TExecutorBlock; BeginEnd: TBeginEnd);
788var
789 I: Integer;
790begin
791 for I := 0 to BeginEnd.Commands.Count - 1 do
792 ExecuteCommand(Block, BeginEnd.Commands[I]);
793end;
794
795procedure TExecutor.ExecuteCommand(Block: TExecutorBlock; Command: TCommand);
796begin
797 if Command is TBeginEnd then ExecuteBeginEnd(Block, TBeginEnd(Command))
798 else if Command is TFunctionCall then ExecuteFunctionCall(Block, TFunctionCall(Command))
799 else if Command is TProcedureCall then ExecuteProcedureCall(Block, TProcedureCall(Command))
800 else if Command is TAssignment then ExecuteAssignment(Block, TAssignment(Command))
801 else if Command is TIfThenElse then ExecuteIfThenElse(Block, TIfThenElse(Command))
802 else if Command is TWhileDo then ExecuteWhileDo(Block, TWhileDo(Command))
803 else if Command is TRepeatUntil then ExecuteRepeatUntil(Block, TRepeatUntil(Command))
804 else if Command is TForToDo then ExecuteForToDo(Block, TForToDo(Command))
805 else if Command is TBreak then ExecuteBreak(Block, TBreak(Command))
806 else if Command is TContinue then ExecuteContinue(Block, TContinue(Command))
807 else if Command is TEmptyCommand then
808 else raise Exception.Create(SUnsupportedCommandType);
809end;
810
811procedure TExecutor.ExecuteIfThenElse(Block: TExecutorBlock;
812 IfThenElse: TIfThenElse);
813var
814 Value: TValue;
815begin
816 Value := ExecuteExpression(Block, IfThenElse.Expression);
817 if Value is TValueBoolean then begin
818 if TValueBoolean(Value).Value then ExecuteCommand(Block, IfThenElse.CommandThen)
819 else begin
820 if Assigned(IfThenElse.CommandElse) then
821 ExecuteCommand(Block, IfThenElse.CommandElse);
822 end;
823 end else raise Exception.Create(SExpectedBooleanValue);
824 FreeAndNil(Value);
825end;
826
827procedure TExecutor.ExecuteWhileDo(Block: TExecutorBlock; WhileDo: TWhileDo);
828var
829 Value: TValue;
830 BoolValue: Boolean;
831begin
832 while True do begin
833 Value := ExecuteExpression(Block, WhileDo.Expression);
834 if Value is TValueBoolean then begin
835 BoolValue := TValueBoolean(Value).Value;
836 FreeAndNil(Value);
837 if not BoolValue then Break;
838 ExecuteCommand(Block, WhileDo.Command);
839 if WhileDo.DoContinue then begin
840 WhileDo.DoContinue := False;
841 Continue;
842 end;
843 if WhileDo.DoBreak then begin
844 WhileDo.DoBreak := False;
845 Break;
846 end;
847 end else raise Exception.Create(SExpectedBooleanValue);
848 end;
849end;
850
851procedure TExecutor.ExecuteRepeatUntil(Block: TExecutorBlock;
852 RepeatUntil: TRepeatUntil);
853var
854 Value: TValue;
855 I: Integer;
856 BoolValue: Boolean;
857begin
858 while True do begin
859 for I := 0 to RepeatUntil.Commands.Count - 1 do begin
860 ExecuteCommand(Block, TCommand(RepeatUntil.Commands[I]));
861 if RepeatUntil.DoContinue then begin
862 RepeatUntil.DoContinue := False;
863 Continue;
864 end;
865 if RepeatUntil.DoBreak then begin
866 RepeatUntil.DoBreak := False;
867 Break;
868 end;
869 end;
870 Value := ExecuteExpression(Block, RepeatUntil.Expression);
871 if Value is TValueBoolean then begin
872 BoolValue := TValueBoolean(Value).Value;
873 FreeAndNil(Value);
874 if BoolValue then Break;
875 end else raise Exception.Create(SExpectedBooleanValue);
876 end;
877end;
878
879procedure TExecutor.ExecuteForToDo(Block: TExecutorBlock; ForToDo: TForToDo);
880var
881 Variable: TExecutorVariable;
882 Limit: TValue;
883begin
884 Variable := Block.GetVariable(ForToDo.VariableRef);
885 Variable.Value := ExecuteExpression(Block, ForToDo.ExpressionFrom);
886 Limit := ExecuteExpression(Block, ForToDo.ExpressionTo);
887 while True do begin
888 ExecuteCommand(Block, ForToDo.Command);
889 if ForToDo.DoContinue then begin
890 ForToDo.DoContinue := False;
891 Continue;
892 end;
893 if ForToDo.DoBreak then begin
894 ForToDo.DoBreak := False;
895 Break;
896 end;
897 TValueInteger(Variable.Value).Value := TValueInteger(Variable.Value).Value + 1;
898 if TValueInteger(Variable.Value).Value > TValueInteger(Limit).Value then Break;
899 end;
900 Limit.Free;
901end;
902
903procedure TExecutor.ExecuteContinue(Block: TExecutorBlock;
904 ContinueCmd: TContinue);
905var
906 Node: TSourceNode;
907begin
908 Node := ContinueCmd.Parent;
909 while Assigned(Node) and not (Node is TLoop) and Assigned(Node.Parent) do
910 Node := Node.Parent;
911
912 if Node is TLoop then TLoop(Node).DoContinue := True
913 else raise Exception.Create('Break used outside of loop.');
914end;
915
916procedure TExecutor.ExecuteBreak(Block: TExecutorBlock; BreakCmd: TBreak);
917var
918 Node: TSourceNode;
919begin
920 Node := BreakCmd.Parent;
921 while Assigned(Node) and not (Node is TLoop) and Assigned(Node.Parent) do
922 Node := Node.Parent;
923
924 if Node is TLoop then TLoop(Node).DoBreak := True
925 else raise Exception.Create('Break used outside of loop.');
926end;
927
928procedure TExecutor.ExecuteBlock(ParentBlock: TExecutorBlock; Block: TBlock; ExistingBlock: TExecutorBlock = nil);
929var
930 ExecutorBlock: TExecutorBlock;
931begin
932 if Assigned(ExistingBlock) then begin
933 ExecutorBlock := ExistingBlock
934 end else begin
935 ExecutorBlock := TExecutorBlock.Create;
936 InitExecutorBlock(ExecutorBlock, Block);
937 end;
938 ExecutorBlock.Parent := ParentBlock;
939 ExecuteBeginEnd(ExecutorBlock, Block.BeginEnd);
940 if not Assigned(ExistingBlock) then ExecutorBlock.Free;
941end;
942
943function TExecutor.ExecuteFunctionCall(Block: TExecutorBlock;
944 FunctionCall: TFunctionCall): TValue;
945var
946 ExecutorFunction: TExecutorFunction;
947 Params: array of TExecutorVariable;
948 I: Integer;
949 ExecutorVariable: TExecutorVariable;
950 Variable: TVariable;
951begin
952 Result := nil;
953 ExecutorFunction := Block.GetFunction(FunctionCall.FunctionDef);
954 if Assigned(ExecutorFunction) then begin
955 InitExecutorBlock(ExecutorFunction.Block, FunctionCall.FunctionDef.Block);
956
957 // Setup variables
958 for I := 0 to FunctionCall.Params.Count - 1 do begin
959 Variable := FunctionCall.FunctionDef.Block.Variables.SearchByName(
960 TFunctionParameter(FunctionCall.FunctionDef.Params[I]).Name);
961 ExecutorVariable := ExecutorFunction.Block.Variables.SearchByVariable(Variable);
962 if FunctionCall.FunctionDef.Params[I].Kind = pkVar then begin
963 ExecutorVariable.Kind := vkReference;
964 Variable := TExpressionOperand(FunctionCall.Params[I]).VariableRef;
965 ExecutorVariable.RefVariable := Block.Variables.SearchByVariable(Variable);
966 end else begin
967 ExecutorVariable.Kind := vkNormal;
968 ExecutorVariable.Value := ExecuteExpression(Block, TExpression(FunctionCall.Params[I]));
969 end;
970 end;
971
972 if FunctionCall.FunctionDef.InternalName <> '' then begin
973 SetLength(Params, FunctionCall.Params.Count);
974 for I := 0 to FunctionCall.Params.Count - 1 do begin
975 Variable := FunctionCall.FunctionDef.Block.Variables.SearchByName(
976 TFunctionParameter(FunctionCall.FunctionDef.Params[I]).Name);
977 Params[I] := ExecutorFunction.Block.Variables.SearchByVariable(Variable);
978 end;
979 Result := ExecutorFunction.Callback(Params);
980 end else begin
981 ExecuteBlock(Block, FunctionCall.FunctionDef.Block, ExecutorFunction.Block);
982 ExecutorVariable := ExecutorFunction.Block.Variables.SearchByVariable(
983 TVariable(FunctionCall.FunctionDef.Block.Variables.SearchByName('Result')));
984 Result := ExecutorVariable.Value.Clone;
985 end;
986 end else raise Exception.Create('No executor for ' + FunctionCall.FunctionDef.Name + ' function.');
987end;
988
989procedure TExecutor.ExecuteProcedureCall(Block: TExecutorBlock;
990 ProcedureCall: TProcedureCall);
991var
992 ExecutorProcedure: TExecutorProcedure;
993 Params: array of TExecutorVariable;
994 I: Integer;
995 ExecutorVariable: TExecutorVariable;
996 Variable: TVariable;
997 ProcedureDef: TProcedure;
998begin
999 ExecutorProcedure := Block.GetProcedure(ProcedureCall.ProcedureDef);
1000 if Assigned(ExecutorProcedure) then begin
1001 ProcedureDef := ProcedureCall.ProcedureDef;
1002 InitExecutorBlock(ExecutorProcedure.Block, ProcedureDef.Block);
1003
1004 for I := 0 to ProcedureCall.Params.Count - 1 do begin
1005 Variable := ProcedureCall.ProcedureDef.Block.Variables.SearchByName(
1006 TFunctionParameter(ProcedureCall.ProcedureDef.Params[I]).Name);
1007 ExecutorVariable := ExecutorProcedure.Block.Variables.SearchByVariable(Variable);
1008 if ProcedureCall.ProcedureDef.Params[I].Kind = pkVar then begin
1009 ExecutorVariable.Kind := vkReference;
1010 Variable := TExpressionOperand(ProcedureCall.Params[I]).VariableRef;
1011 ExecutorVariable.RefVariable := Block.GetVariable(Variable);
1012 end else begin
1013 ExecutorVariable.Kind := vkNormal;
1014 ExecutorVariable.Value := ExecuteExpression(Block, TExpression(ProcedureCall.Params[I]));
1015 end;
1016 end;
1017
1018 if ProcedureCall.ProcedureDef.InternalName <> '' then begin
1019 SetLength(Params, ProcedureCall.Params.Count);
1020 for I := 0 to ProcedureCall.Params.Count - 1 do begin
1021 Variable := ProcedureCall.ProcedureDef.Block.Variables.SearchByName(
1022 TFunctionParameter(ProcedureCall.ProcedureDef.Params[I]).Name);
1023 ExecutorVariable := ExecutorProcedure.Block.Variables.SearchByVariable(Variable);
1024 Params[I] := ExecutorVariable;
1025 end;
1026
1027 ExecutorProcedure.Callback(Params);
1028 end else begin
1029 ExecuteBlock(Block, ProcedureCall.ProcedureDef.Block, ExecutorProcedure.Block);
1030 end;
1031 end else raise Exception.Create('No executor for ' + ProcedureCall.ProcedureDef.Name + ' function.');
1032end;
1033
1034procedure TExecutor.ExecuteAssignment(Block: TExecutorBlock;
1035 Assignment: TAssignment);
1036var
1037 Value: TValue;
1038 Variable: TExecutorVariable;
1039 ExecutorFunction: TExecutorFunction;
1040 Params: array of TExecutorVariable;
1041begin
1042 Value := ExecuteExpression(Block, Assignment.Expression);
1043 Variable := Block.GetVariable(Assignment.Variable);
1044 ExecutorFunction := Block.GetTypeFunction(Assignment.Variable.TypeRef, '_Assign');
1045 if Assignment.Variable.TypeRef = Assignment.Expression.GetType then begin
1046 SetLength(Params, 1);
1047 Params[0] := TExecutorVariable.Create;
1048 Params[0].Value := Value;
1049 Variable.Value := ExecutorFunction.Callback(Params);
1050 end else raise Exception('Assignment result type is ' + Variable.Variable.TypeRef.Name +
1051 ' but value is ' + Assignment.Expression.GetType.Name + '.');
1052 FreeAndNil(Value);
1053end;
1054
1055function TExecutor.ExecuteExpression(Block: TExecutorBlock;
1056 Expression: TExpression): TValue;
1057begin
1058 if Expression is TExpressionOperation then
1059 Result := ExecuteExpressionOperation(Block, TExpressionOperation(Expression))
1060 else
1061 if Expression is TExpressionOperand then
1062 Result := ExecuteExpressionOperand(Block, TExpressionOperand(Expression))
1063 else
1064 if Expression is TExpressionBrackets then
1065 Result := ExecuteExpressionBrackets(Block, TExpressionBrackets(Expression))
1066 else
1067 raise Exception.Create('Unknown expression class.');
1068end;
1069
1070function TExecutor.ExecuteExpressionOperation(Block: TExecutorBlock;
1071 Expression: TExpressionOperation): TValue;
1072var
1073 I: Integer;
1074 Value: TValue;
1075 ExecutorFunction: TExecutorFunction;
1076 Params: array of TExecutorVariable;
1077 FuncName: string;
1078begin
1079 FuncName := Expression.GetFunctionName;
1080
1081 ExecutorFunction := Block.GetTypeFunction(Expression.FunctionRef.ParentType, FuncName);
1082 if not Assigned(ExecutorFunction) then
1083 raise Exception.Create('Missing operator function ' + FuncName + ' for type ' + Expression.TypeRef.Name);
1084
1085 SetLength(Params, Expression.Items.Count);
1086 for I := 0 to Expression.Items.Count - 1 do begin
1087 Value := ExecuteExpression(Block, TExpression(Expression.Items[I]));
1088 Params[I] := TExecutorVariable.Create;
1089 Params[I].Value := Value;
1090 end;
1091 Result := ExecutorFunction.Callback(Params);
1092 for I := 0 to Expression.Items.Count - 1 do begin
1093 Params[I].Free;
1094 end;
1095end;
1096
1097function TExecutor.ExecuteExpressionOperand(Block: TExecutorBlock;
1098 Expression: TExpressionOperand): TValue;
1099begin
1100 case Expression.OperandType of
1101 otFunctionCall: Result := ExecuteFunctionCall(Block, Expression.FunctionCall);
1102 otConstantDirect: Result := Expression.ConstantDirect.Value.Clone;
1103 otConstantRef: Result := Expression.ConstantRef.Value.Clone;
1104 otVariableRef: Result := Block.Variables.SearchByVariable(Expression.VariableRef).Value.Clone;
1105 else raise Exception.Create(SUnsupportedOperandType);
1106 end;
1107end;
1108
1109function TExecutor.ExecuteExpressionBrackets(Block: TExecutorBlock;
1110 Expression: TExpressionBrackets): TValue;
1111begin
1112 Result := ExecuteExpression(Block, Expression.Expression);
1113end;
1114
1115procedure TExecutor.Run;
1116begin
1117 ExecuteProgram(Prog);
1118end;
1119
1120procedure TExecutor.Output(Text: string);
1121begin
1122 if Assigned(FOnOutput) then
1123 FOnOutput(Text);
1124end;
1125
1126function TExecutor.Input: string;
1127begin
1128 if Assigned(FOnInput) then
1129 Result := FOnInput;
1130end;
1131
1132end.
1133
Note: See TracBrowser for help on using the repository browser.