Changeset 214


Ignore:
Timestamp:
Apr 23, 2020, 12:24:31 AM (4 years ago)
Author:
chronos
Message:
  • Added: Execution of user defined functions.
Location:
branches/interpreter2
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • branches/interpreter2/Test.pas

    r212 r214  
    2525    WriteLn('DoThen');
    2626  end else WriteLn('DoElse');
     27 
     28  if IsZero(1) then begin
     29    WriteLn('Is really zero');
     30  end;
    2731
    2832  // While-Do
  • branches/interpreter2/UExecutor.pas

    r212 r214  
    1010type
    1111  TExecutorFunctions = class;
     12  TExecutorBlock = class;
    1213
    1314  { TExecutorVariable }
     
    4546  TExecutorFunctionCallback = function(Params: array of TValue): TValue of object;
    4647
     48  { TExecutorFunction }
     49
    4750  TExecutorFunction = class
    4851    FunctionDef: TFunction;
     52    Block: TExecutorBlock;
    4953    Callback: TExecutorFunctionCallback;
     54    constructor Create;
     55    destructor Destroy; override;
    5056  end;
    5157
     
    8591    function ExecuteIntToStr(Params: array of TValue): TValue;
    8692    function ExecuteStrToInt(Params: array of TValue): TValue;
     93    function ExecuteBooleanAssign(Params: array of TValue): TValue;
     94    function ExecuteBooleanEqual(Params: array of TValue): TValue;
     95    function ExecuteBooleanNotEqual(Params: array of TValue): TValue;
    8796    function ExecuteStringAssign(Params: array of TValue): TValue;
    8897    function ExecuteStringAdd(Params: array of TValue): TValue;
     
    106115    procedure ExecuteContinue(Block: TExecutorBlock; ContinueCmd: TContinue);
    107116    procedure ExecuteBreak(Block: TExecutorBlock; BreakCmd: TBreak);
    108     procedure ExecuteBlock(ParentBlock: TExecutorBlock; Block: TBlock);
     117    procedure ExecuteBlock(ParentBlock: TExecutorBlock; Block: TBlock; ExistingBlock: TExecutorBlock = nil);
    109118    function ExecuteFunctionCall(Block: TExecutorBlock; FunctionCall: TFunctionCall): TValue;
    110119    procedure ExecuteAssignment(Block: TExecutorBlock; Assignment: TAssignment);
     
    120129implementation
    121130
     131{ TExecutorFunction }
     132
     133constructor TExecutorFunction.Create;
     134begin
     135  Block := TExecutorBlock.Create;
     136end;
     137
     138destructor TExecutorFunction.Destroy;
     139begin
     140  Block.Free;
     141  inherited Destroy;
     142end;
     143
    122144{ TExecutorVariable }
    123145
     
    295317end;
    296318
     319function TExecutor.ExecuteBooleanAssign(Params: array of TValue): TValue;
     320begin
     321  Result := TValueBoolean.Create;
     322  TValueBoolean(Result).Value := TValueBoolean(Params[0]).Value;
     323end;
     324
     325function TExecutor.ExecuteBooleanEqual(Params: array of TValue): TValue;
     326begin
     327  Result := TValueBoolean.Create;
     328  TValueBoolean(Result).Value := TValueBoolean(Params[0]).Value = TValueBoolean(Params[1]).Value;
     329end;
     330
     331function TExecutor.ExecuteBooleanNotEqual(Params: array of TValue): TValue;
     332begin
     333  Result := TValueBoolean.Create;
     334  TValueBoolean(Result).Value := TValueBoolean(Params[0]).Value <> TValueBoolean(Params[1]).Value;
     335end;
     336
    297337function TExecutor.ExecuteStringAssign(Params: array of TValue): TValue;
    298338begin
     
    360400    for J := 0 to ExecutorType.TypeRef.Functions.Count - 1 do begin
    361401      ExecutorFunction := ExecutorType.Functions.AddNew(TFunction(ExecutorType.TypeRef.Functions[J]));
     402      if ExecutorType.TypeRef.Name = 'Boolean' then begin
     403        if ExecutorFunction.FunctionDef.Name = '_Assign' then begin
     404          ExecutorFunction.Callback := ExecuteBooleanAssign;
     405        end else
     406        if ExecutorFunction.FunctionDef.Name = '_Equal' then begin
     407          ExecutorFunction.Callback := ExecuteBooleanEqual;
     408        end;
     409        if ExecutorFunction.FunctionDef.Name = '_NotEqual' then begin
     410          ExecutorFunction.Callback := ExecuteBooleanNotEqual;
     411        end;
     412      end else
    362413      if ExecutorType.TypeRef.Name = 'string' then begin
    363414        if ExecutorFunction.FunctionDef.Name = '_Assign' then begin
     
    373424          ExecutorFunction.Callback := ExecuteStringNotEqual;
    374425        end;
    375       end;
     426      end else
    376427      if ExecutorType.TypeRef.Name = 'Integer' then begin
    377428        if ExecutorFunction.FunctionDef.Name = '_Assign' then begin
     
    557608end;
    558609
    559 procedure TExecutor.ExecuteBlock(ParentBlock: TExecutorBlock; Block: TBlock);
     610procedure TExecutor.ExecuteBlock(ParentBlock: TExecutorBlock; Block: TBlock; ExistingBlock: TExecutorBlock = nil);
    560611var
    561612  ExecutorBlock: TExecutorBlock;
    562613begin
    563   ExecutorBlock := TExecutorBlock.Create;
     614  if Assigned(ExistingBlock) then begin
     615    ExecutorBlock := ExistingBlock
     616  end else begin
     617    ExecutorBlock := TExecutorBlock.Create;
     618    InitExecutorBlock(ExecutorBlock, Block);
     619  end;
    564620  ExecutorBlock.Parent := ParentBlock;
    565   InitExecutorBlock(ExecutorBlock, Block);
    566621  ExecuteBeginEnd(ExecutorBlock, Block.BeginEnd);
    567   ExecutorBlock.Free;
     622  if not Assigned(ExistingBlock) then ExecutorBlock.Free;
    568623end;
    569624
     
    574629  Params: array of TValue;
    575630  I: Integer;
     631  ExecutorVariable: TExecutorVariable;
     632  Variable: TVariable;
    576633begin
    577634  Result := nil;
    578635  ExecutorFunction := Block.GetFunction(FunctionCall.FunctionDef);
    579636  if Assigned(ExecutorFunction) then begin
    580     SetLength(Params, FunctionCall.Params.Count);
    581     for I := 0 to FunctionCall.Params.Count - 1 do begin
    582       Params[I] := ExecuteExpression(Block, TExpression(FunctionCall.Params[0]));
    583     end;
    584     Result := ExecutorFunction.Callback(Params);
    585     for I := 0 to FunctionCall.Params.Count - 1 do begin
    586       Params[I].Free;
     637    if FunctionCall.FunctionDef.InternalName <> '' then begin
     638      SetLength(Params, FunctionCall.Params.Count);
     639      for I := 0 to FunctionCall.Params.Count - 1 do begin
     640        Params[I] := ExecuteExpression(Block, TExpression(FunctionCall.Params[0]));
     641      end;
     642      Result := ExecutorFunction.Callback(Params);
     643      for I := 0 to FunctionCall.Params.Count - 1 do begin
     644        Params[I].Free;
     645      end;
     646    end else begin
     647      InitExecutorBlock(ExecutorFunction.Block, FunctionCall.FunctionDef.Block);
     648      for I := 0 to FunctionCall.Params.Count - 1 do begin
     649        Variable := FunctionCall.FunctionDef.Block.Variables.SearchByName(TFunctionParameter(FunctionCall.FunctionDef.Params[I]).Name);
     650        ExecutorVariable := ExecutorFunction.Block.Variables.SearchByVariable(Variable);
     651        ExecutorVariable.Value.Free;
     652        ExecutorVariable.Value := ExecuteExpression(Block, TExpression(FunctionCall.Params[I]));
     653      end;
     654      ExecuteBlock(Block, FunctionCall.FunctionDef.Block, ExecutorFunction.Block);
     655      ExecutorVariable := ExecutorFunction.Block.Variables.SearchByVariable(TVariable(FunctionCall.FunctionDef.Block.Variables.SearchByName('Result')));
     656      Result := ExecutorVariable.Value;
    587657    end;
    588658  end else raise Exception.Create('No executor for ' + FunctionCall.FunctionDef.Name + ' function.');
Note: See TracChangeset for help on using the changeset viewer.