Ignore:
Timestamp:
Jun 26, 2023, 6:08:23 PM (11 months ago)
Author:
chronos
Message:
  • Added: Support for procedures.
  • Added: Project pascal file can be opened from main menu. Last file name is remembered.
  • Modified: Improved XML output of source structure.
File:
1 edited

Legend:

Unmodified
Added
Removed
  • branches/xpascal/Executor.pas

    r231 r233  
    7171  end;
    7272
     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
    7390  { TExecutorBlock }
    7491
     
    7895    Variables: TExecutorVariables;
    7996    Functions: TExecutorFunctions;
     97    Procedures: TExecutorProcedures;
    8098    function GetFunction(FunctionDef: TFunction): TExecutorFunction;
     99    function GetProcedure(ProcedureDef: TProcedure): TExecutorProcedure;
    81100    function GetType(TypeDef: TType): TExecutorType;
    82101    function GetVariable(Variable: TVariable): TExecutorVariable;
     
    144163    procedure ExecuteBlock(ParentBlock: TExecutorBlock; Block: TBlock; ExistingBlock: TExecutorBlock = nil);
    145164    function ExecuteFunctionCall(Block: TExecutorBlock; FunctionCall: TFunctionCall): TValue;
     165    function ExecuteProcedureCall(Block: TExecutorBlock; ProcedureCall: TProcedureCall): TValue;
    146166    procedure ExecuteAssignment(Block: TExecutorBlock; Assignment: TAssignment);
    147167    function ExecuteExpression(Block: TExecutorBlock; Expression: TExpression): TValue;
     
    167187  SExpectedBooleanValue = 'Expected boolean value.';
    168188
     189{ TExecutorProcedures }
     190
     191function TExecutorProcedures.SearchByProcedure(ProcedureDef: TProcedure
     192  ): TExecutorProcedure;
     193var
     194  I: Integer;
     195begin
     196  I := 0;
     197  while (I < Count) and (TExecutorProcedure(Items[I]).ProcedureDef <> ProcedureDef) do Inc(I);
     198  if I < Count then Result := TExecutorProcedure(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
    169223{ TExecutorFunctionCallbackParam }
    170224
     
    281335end;
    282336
     337function TExecutorBlock.GetProcedure(ProcedureDef: TProcedure
     338  ): TExecutorProcedure;
     339begin
     340  Result := Procedures.SearchByProcedure(ProcedureDef);
     341  if not Assigned(Result) and Assigned(Parent) then
     342    Result := Parent.GetProcedure(ProcedureDef);
     343end;
     344
    283345function TExecutorBlock.GetType(TypeDef: TType): TExecutorType;
    284346begin
     
    315377  Variables := TExecutorVariables.Create;
    316378  Functions := TExecutorFunctions.Create;
     379  Procedures := TExecutorProcedures.Create;
    317380end;
    318381
     
    321384  FreeAndNil(Variables);
    322385  FreeAndNil(Functions);
     386  FreeAndNil(Procedures);
    323387  FreeAndNil(Types);
    324388  inherited;
     
    703767begin
    704768  for I := 0 to BeginEnd.Commands.Count - 1 do
    705     ExecuteCommand(Block, TCommand(BeginEnd.Commands[I]));
     769    ExecuteCommand(Block, BeginEnd.Commands[I]);
    706770end;
    707771
     
    710774  if Command is TBeginEnd then ExecuteBeginEnd(Block, TBeginEnd(Command))
    711775  else if Command is TFunctionCall then ExecuteFunctionCall(Block, TFunctionCall(Command))
     776  else if Command is TProcedureCall then ExecuteProcedureCall(Block, TProcedureCall(Command))
    712777  else if Command is TAssignment then ExecuteAssignment(Block, TAssignment(Command))
    713778  else if Command is TIfThenElse then ExecuteIfThenElse(Block, TIfThenElse(Command))
     
    899964end;
    900965
     966function TExecutor.ExecuteProcedureCall(Block: TExecutorBlock;
     967  ProcedureCall: TProcedureCall): TValue;
     968var
     969  ExecutorProcedure: TExecutorProcedure;
     970  Params: array of TExecutorFunctionCallbackParam;
     971  I: Integer;
     972  ExecutorVariable: TExecutorVariable;
     973  Variable: TVariable;
     974begin
     975  Result := nil;
     976  ExecutorProcedure := Block.GetProcedure(ProcedureCall.ProcedureDef);
     977  if Assigned(ExecutorProcedure) then begin
     978    if ProcedureCall.ProcedureDef.InternalName <> '' then begin
     979      SetLength(Params, ProcedureCall.Params.Count);
     980      for I := 0 to ProcedureCall.Params.Count - 1 do begin
     981        Params[I] := TExecutorFunctionCallbackParam.Create;
     982        Params[I].Kind := ProcedureCall.ProcedureDef.Params[I].Kind;
     983        if ProcedureCall.ProcedureDef.Params[I].Kind = pkVar then begin
     984          Variable := TExpressionOperand(ProcedureCall.Params[I]).VariableRef;
     985          //InitExecutorBlock(ExecutorFunction.Block, FunctionCall.FunctionDef.Block);
     986          ExecutorVariable := Block.GetVariable(Variable);
     987          Params[I].Variable := ExecutorVariable;
     988        end
     989        else Params[I].Value := ExecuteExpression(Block, ProcedureCall.Params[I]);
     990      end;
     991      Result := ExecutorProcedure.Callback(Params);
     992      for I := 0 to ProcedureCall.Params.Count - 1 do begin
     993        //if FunctionCall.Params[I].
     994        Params[I].Free;
     995      end;
     996    end else begin
     997      InitExecutorBlock(ExecutorProcedure.Block, ProcedureCall.ProcedureDef.Block);
     998      for I := 0 to ProcedureCall.Params.Count - 1 do begin
     999        Variable := ProcedureCall.ProcedureDef.Block.Variables.SearchByName(
     1000          TFunctionParameter(ProcedureCall.ProcedureDef.Params[I]).Name);
     1001        ExecutorVariable := ExecutorProcedure.Block.Variables.SearchByVariable(Variable);
     1002        ExecutorVariable.Value.Free;
     1003        ExecutorVariable.Value := ExecuteExpression(Block, TExpression(ProcedureCall.Params[I]));
     1004      end;
     1005      ExecuteBlock(Block, ProcedureCall.ProcedureDef.Block, ExecutorProcedure.Block);
     1006      ExecutorVariable := ExecutorProcedure.Block.Variables.SearchByVariable(
     1007        TVariable(ProcedureCall.ProcedureDef.Block.Variables.SearchByName('Result')));
     1008      Result := ExecutorVariable.Value.Clone;
     1009    end;
     1010  end else raise Exception.Create('No executor for ' + ProcedureCall.ProcedureDef.Name + ' function.');
     1011end;
     1012
    9011013procedure TExecutor.ExecuteAssignment(Block: TExecutorBlock;
    9021014  Assignment: TAssignment);
Note: See TracChangeset for help on using the changeset viewer.