Changeset 236


Ignore:
Timestamp:
Jun 29, 2023, 1:47:58 AM (10 months ago)
Author:
chronos
Message:
  • Fixed: Var function parameters processed correctly for both user defined and internal functions.
Location:
branches/xpascal
Files:
7 edited

Legend:

Unmodified
Added
Removed
  • branches/xpascal/Examples/Example.pas

    r233 r236  
    1717begin
    1818  WriteLn(Text);
     19end;
     20
     21procedure SetText(var Text: string, NewText: string);
     22begin
     23  Text := NewText;
    1924end;
    2025
     
    7277  WriteLn(A);
    7378
     79  SetText(A, 'New text');
     80  WriteLn('New text: ' + A);
     81
    7482  WriteLn('What is your name?');
    7583  ReadLn(A);
  • branches/xpascal/Executor.pas

    r235 r236  
    1010  TExecutorBlock = class;
    1111
     12  TExecutorVariableKind = (vkNormal, vkReference);
     13
    1214  { TExecutorVariable }
    1315
    1416  TExecutorVariable = class
     17  private
     18    FValue: TValue;
     19    function GetValue: TValue;
     20    procedure SetValue(AValue: TValue);
     21  public
    1522    Variable: TVariable;
    16     Value: TValue;
     23    Kind: TExecutorVariableKind;
     24    RefVariable: TExecutorVariable;
    1725    constructor Create;
    1826    destructor Destroy; override;
     27    property Value: TValue read GetValue write SetValue;
    1928  end;
    2029
     
    4251  end;
    4352
    44   { TExecutorFunctionCallbackParam }
    45 
    46   TExecutorFunctionCallbackParam = class
    47     Kind: TFunctionParamKind;
    48     Variable: TExecutorVariable;
    49     Value: TValue;
    50     destructor Destroy; override;
    51   end;
    52 
    53   TExecutorFunctionCallback = function(Params: array of TExecutorFunctionCallbackParam):
     53  TExecutorFunctionCallback = function(Params: array of TExecutorVariable):
    5454    TValue of object;
    5555
     
    116116    FOnInput: TInputEvent;
    117117    SystemBlock: TExecutorBlock;
    118     function ExecuteWriteLn(Params: array of TExecutorFunctionCallbackParam): TValue;
    119     function ExecuteWrite(Params: array of TExecutorFunctionCallbackParam): TValue;
    120     function ExecuteReadLn(Params: array of TExecutorFunctionCallbackParam): TValue;
    121     function ExecuteRead(Params: array of TExecutorFunctionCallbackParam): TValue;
    122     function ExecuteIntToStr(Params: array of TExecutorFunctionCallbackParam): TValue;
    123     function ExecuteStrToInt(Params: array of TExecutorFunctionCallbackParam): TValue;
    124     function ExecuteBoolToStr(Params: array of TExecutorFunctionCallbackParam): TValue;
    125     function ExecuteStrToBool(Params: array of TExecutorFunctionCallbackParam): TValue;
    126     function ExecuteBooleanAssign(Params: array of TExecutorFunctionCallbackParam): TValue;
    127     function ExecuteBooleanNot(Params: array of TExecutorFunctionCallbackParam): TValue;
    128     function ExecuteBooleanEqual(Params: array of TExecutorFunctionCallbackParam): TValue;
    129     function ExecuteBooleanNotEqual(Params: array of TExecutorFunctionCallbackParam): TValue;
    130     function ExecuteStringAssign(Params: array of TExecutorFunctionCallbackParam): TValue;
    131     function ExecuteStringAdd(Params: array of TExecutorFunctionCallbackParam): TValue;
    132     function ExecuteStringEqual(Params: array of TExecutorFunctionCallbackParam): TValue;
    133     function ExecuteStringNotEqual(Params: array of TExecutorFunctionCallbackParam): TValue;
    134     function ExecuteIntegerAssign(Params: array of TExecutorFunctionCallbackParam): TValue;
    135     function ExecuteIntegerAdd(Params: array of TExecutorFunctionCallbackParam): TValue;
    136     function ExecuteIntegerSub(Params: array of TExecutorFunctionCallbackParam): TValue;
    137     function ExecuteIntegerMul(Params: array of TExecutorFunctionCallbackParam): TValue;
    138     function ExecuteIntegerIntDiv(Params: array of TExecutorFunctionCallbackParam): TValue;
    139     function ExecuteIntegerMod(Params: array of TExecutorFunctionCallbackParam): TValue;
    140     function ExecuteIntegerEqual(Params: array of TExecutorFunctionCallbackParam): TValue;
    141     function ExecuteIntegerNotEqual(Params: array of TExecutorFunctionCallbackParam): TValue;
    142     function ExecuteIntegerLesser(Params: array of TExecutorFunctionCallbackParam): TValue;
    143     function ExecuteIntegerHigher(Params: array of TExecutorFunctionCallbackParam): TValue;
    144     function ExecuteIntegerLesserOrEqual(Params: array of TExecutorFunctionCallbackParam): TValue;
    145     function ExecuteIntegerHigherOrEqual(Params: array of TExecutorFunctionCallbackParam): TValue;
    146     function ExecuteIntegerAnd(Params: array of TExecutorFunctionCallbackParam): TValue;
    147     function ExecuteIntegerOr(Params: array of TExecutorFunctionCallbackParam): TValue;
    148     function ExecuteIntegerXor(Params: array of TExecutorFunctionCallbackParam): TValue;
    149     function ExecuteIntegerShr(Params: array of TExecutorFunctionCallbackParam): TValue;
    150     function ExecuteIntegerShl(Params: array of TExecutorFunctionCallbackParam): TValue;
     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;
    151151    procedure InitExecutorBlock(ExecutorBlock: TExecutorBlock; Block: TBlock);
    152152  public
     
    221221end;
    222222
    223 { TExecutorFunctionCallbackParam }
    224 
    225 destructor TExecutorFunctionCallbackParam.Destroy;
    226 begin
    227   FreeAndNil(Value);
    228   inherited;
    229 end;
    230 
    231223{ TExecutorFunction }
    232224
     
    244236{ TExecutorVariable }
    245237
     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
    246260constructor TExecutorVariable.Create;
    247261begin
     
    251265destructor TExecutorVariable.Destroy;
    252266begin
    253   FreeAndNil(Value);
     267  FreeAndNil(FValue);
    254268  inherited;
    255269end;
     
    391405{ TExecutor }
    392406
    393 function TExecutor.ExecuteWriteLn(Params: array of TExecutorFunctionCallbackParam): TValue;
     407function TExecutor.ExecuteWriteLn(Params: array of TExecutorVariable): TValue;
    394408var
    395409  I: Integer;
     
    403417end;
    404418
    405 function TExecutor.ExecuteWrite(Params: array of TExecutorFunctionCallbackParam): TValue;
     419function TExecutor.ExecuteWrite(Params: array of TExecutorVariable): TValue;
    406420var
    407421  I: Integer;
     
    415429end;
    416430
    417 function TExecutor.ExecuteReadLn(Params: array of TExecutorFunctionCallbackParam): TValue;
     431function TExecutor.ExecuteReadLn(Params: array of TExecutorVariable): TValue;
    418432var
    419433  I: Integer;
    420434begin
    421435  Result := nil;
    422   for I := 0 to Length(Params) - 1 do
    423     TValueString(Params[I].Variable.Value).Value := Input;
     436  for I := 0 to Length(Params) - 1 do begin
     437    TValueString(Params[I].Value).Value := Input;
     438  end;
    424439  Output(LineEnding);
    425440end;
    426441
    427 function TExecutor.ExecuteRead(Params: array of TExecutorFunctionCallbackParam): TValue;
     442function TExecutor.ExecuteRead(Params: array of TExecutorVariable): TValue;
    428443var
    429444  I: Integer;
     
    434449end;
    435450
    436 function TExecutor.ExecuteIntToStr(Params: array of TExecutorFunctionCallbackParam): TValue;
     451function TExecutor.ExecuteIntToStr(Params: array of TExecutorVariable): TValue;
    437452begin
    438453  Result := TValueString.Create;
     
    440455end;
    441456
    442 function TExecutor.ExecuteStrToInt(Params: array of TExecutorFunctionCallbackParam): TValue;
     457function TExecutor.ExecuteStrToInt(Params: array of TExecutorVariable): TValue;
    443458begin
    444459  Result := TValueInteger.Create;
     
    446461end;
    447462
    448 function TExecutor.ExecuteBoolToStr(Params: array of TExecutorFunctionCallbackParam): TValue;
     463function TExecutor.ExecuteBoolToStr(Params: array of TExecutorVariable): TValue;
    449464begin
    450465  Result := TValueString.Create;
     
    452467end;
    453468
    454 function TExecutor.ExecuteStrToBool(Params: array of TExecutorFunctionCallbackParam): TValue;
     469function TExecutor.ExecuteStrToBool(Params: array of TExecutorVariable): TValue;
    455470begin
    456471  Result := TValueBoolean.Create;
     
    458473end;
    459474
    460 function TExecutor.ExecuteBooleanAssign(Params: array of TExecutorFunctionCallbackParam): TValue;
     475function TExecutor.ExecuteBooleanAssign(Params: array of TExecutorVariable): TValue;
    461476begin
    462477  Result := TValueBoolean.Create;
     
    464479end;
    465480
    466 function TExecutor.ExecuteBooleanNot(Params: array of TExecutorFunctionCallbackParam): TValue;
     481function TExecutor.ExecuteBooleanNot(Params: array of TExecutorVariable): TValue;
    467482begin
    468483  Result := TValueBoolean.Create;
     
    470485end;
    471486
    472 function TExecutor.ExecuteBooleanEqual(Params: array of TExecutorFunctionCallbackParam): TValue;
     487function TExecutor.ExecuteBooleanEqual(Params: array of TExecutorVariable): TValue;
    473488begin
    474489  Result := TValueBoolean.Create;
     
    477492end;
    478493
    479 function TExecutor.ExecuteBooleanNotEqual(Params: array of TExecutorFunctionCallbackParam): TValue;
     494function TExecutor.ExecuteBooleanNotEqual(Params: array of TExecutorVariable): TValue;
    480495begin
    481496  Result := TValueBoolean.Create;
     
    484499end;
    485500
    486 function TExecutor.ExecuteStringAssign(Params: array of TExecutorFunctionCallbackParam): TValue;
     501function TExecutor.ExecuteStringAssign(Params: array of TExecutorVariable): TValue;
    487502begin
    488503  Result := TValueString.Create;
     
    490505end;
    491506
    492 function TExecutor.ExecuteStringAdd(Params: array of TExecutorFunctionCallbackParam): TValue;
     507function TExecutor.ExecuteStringAdd(Params: array of TExecutorVariable): TValue;
    493508begin
    494509  Result := TValueString.Create;
     
    497512end;
    498513
    499 function TExecutor.ExecuteStringEqual(Params: array of TExecutorFunctionCallbackParam): TValue;
     514function TExecutor.ExecuteStringEqual(Params: array of TExecutorVariable): TValue;
    500515begin
    501516  Result := TValueBoolean.Create;
     
    504519end;
    505520
    506 function TExecutor.ExecuteStringNotEqual(Params: array of TExecutorFunctionCallbackParam): TValue;
     521function TExecutor.ExecuteStringNotEqual(Params: array of TExecutorVariable): TValue;
    507522begin
    508523  Result := TValueBoolean.Create;
     
    511526end;
    512527
    513 function TExecutor.ExecuteIntegerAssign(Params: array of TExecutorFunctionCallbackParam): TValue;
     528function TExecutor.ExecuteIntegerAssign(Params: array of TExecutorVariable): TValue;
    514529begin
    515530  Result := TValueInteger.Create;
     
    517532end;
    518533
    519 function TExecutor.ExecuteIntegerAdd(Params: array of TExecutorFunctionCallbackParam): TValue;
     534function TExecutor.ExecuteIntegerAdd(Params: array of TExecutorVariable): TValue;
    520535begin
    521536  Result := TValueInteger.Create;
     
    524539end;
    525540
    526 function TExecutor.ExecuteIntegerSub(Params: array of TExecutorFunctionCallbackParam): TValue;
     541function TExecutor.ExecuteIntegerSub(Params: array of TExecutorVariable): TValue;
    527542begin
    528543  Result := TValueInteger.Create;
     
    531546end;
    532547
    533 function TExecutor.ExecuteIntegerMul(Params: array of TExecutorFunctionCallbackParam): TValue;
     548function TExecutor.ExecuteIntegerMul(Params: array of TExecutorVariable): TValue;
    534549begin
    535550  Result := TValueInteger.Create;
     
    538553end;
    539554
    540 function TExecutor.ExecuteIntegerIntDiv(Params: array of TExecutorFunctionCallbackParam): TValue;
     555function TExecutor.ExecuteIntegerIntDiv(Params: array of TExecutorVariable): TValue;
    541556begin
    542557  Result := TValueInteger.Create;
     
    545560end;
    546561
    547 function TExecutor.ExecuteIntegerMod(Params: array of TExecutorFunctionCallbackParam): TValue;
     562function TExecutor.ExecuteIntegerMod(Params: array of TExecutorVariable): TValue;
    548563begin
    549564  Result := TValueInteger.Create;
     
    552567end;
    553568
    554 function TExecutor.ExecuteIntegerEqual(Params: array of TExecutorFunctionCallbackParam): TValue;
     569function TExecutor.ExecuteIntegerEqual(Params: array of TExecutorVariable): TValue;
    555570begin
    556571  Result := TValueBoolean.Create;
     
    559574end;
    560575
    561 function TExecutor.ExecuteIntegerNotEqual(Params: array of TExecutorFunctionCallbackParam): TValue;
     576function TExecutor.ExecuteIntegerNotEqual(Params: array of TExecutorVariable): TValue;
    562577begin
    563578  Result := TValueBoolean.Create;
     
    566581end;
    567582
    568 function TExecutor.ExecuteIntegerLesser(Params: array of TExecutorFunctionCallbackParam): TValue;
     583function TExecutor.ExecuteIntegerLesser(Params: array of TExecutorVariable): TValue;
    569584begin
    570585  Result := TValueBoolean.Create;
     
    573588end;
    574589
    575 function TExecutor.ExecuteIntegerHigher(Params: array of TExecutorFunctionCallbackParam): TValue;
     590function TExecutor.ExecuteIntegerHigher(Params: array of TExecutorVariable): TValue;
    576591begin
    577592  Result := TValueBoolean.Create;
     
    580595end;
    581596
    582 function TExecutor.ExecuteIntegerLesserOrEqual(Params: array of TExecutorFunctionCallbackParam): TValue;
     597function TExecutor.ExecuteIntegerLesserOrEqual(Params: array of TExecutorVariable): TValue;
    583598begin
    584599  Result := TValueBoolean.Create;
     
    587602end;
    588603
    589 function TExecutor.ExecuteIntegerHigherOrEqual(Params: array of TExecutorFunctionCallbackParam): TValue;
     604function TExecutor.ExecuteIntegerHigherOrEqual(Params: array of TExecutorVariable): TValue;
    590605begin
    591606  Result := TValueBoolean.Create;
     
    594609end;
    595610
    596 function TExecutor.ExecuteIntegerAnd(Params: array of TExecutorFunctionCallbackParam): TValue;
     611function TExecutor.ExecuteIntegerAnd(Params: array of TExecutorVariable): TValue;
    597612begin
    598613  Result := TValueInteger.Create;
     
    601616end;
    602617
    603 function TExecutor.ExecuteIntegerOr(Params: array of TExecutorFunctionCallbackParam): TValue;
     618function TExecutor.ExecuteIntegerOr(Params: array of TExecutorVariable): TValue;
    604619begin
    605620  Result := TValueInteger.Create;
     
    608623end;
    609624
    610 function TExecutor.ExecuteIntegerXor(Params: array of TExecutorFunctionCallbackParam): TValue;
     625function TExecutor.ExecuteIntegerXor(Params: array of TExecutorVariable): TValue;
    611626begin
    612627  Result := TValueInteger.Create;
     
    615630end;
    616631
    617 function TExecutor.ExecuteIntegerShr(Params: array of TExecutorFunctionCallbackParam): TValue;
     632function TExecutor.ExecuteIntegerShr(Params: array of TExecutorVariable): TValue;
    618633begin
    619634  Result := TValueInteger.Create;
     
    622637end;
    623638
    624 function TExecutor.ExecuteIntegerShl(Params: array of TExecutorFunctionCallbackParam): TValue;
     639function TExecutor.ExecuteIntegerShl(Params: array of TExecutorVariable): TValue;
    625640begin
    626641  Result := TValueInteger.Create;
     
    807822      end;
    808823  end else raise Exception.Create(SExpectedBooleanValue);
    809   Value.Free;
     824  FreeAndNil(Value);
    810825end;
    811826
     
    819834    if Value is TValueBoolean then begin
    820835      BoolValue := TValueBoolean(Value).Value;
    821       Value.Free;
     836      FreeAndNil(Value);
    822837      if not BoolValue then Break;
    823838      ExecuteCommand(Block, WhileDo.Command);
     
    856871    if Value is TValueBoolean then begin
    857872      BoolValue := TValueBoolean(Value).Value;
    858       Value.Free;
     873      FreeAndNil(Value);
    859874      if BoolValue then Break;
    860875    end else raise Exception.Create(SExpectedBooleanValue);
     
    868883begin
    869884  Variable := Block.GetVariable(ForToDo.VariableRef);
    870   Variable.Value.Free;
    871885  Variable.Value := ExecuteExpression(Block, ForToDo.ExpressionFrom);
    872886  Limit := ExecuteExpression(Block, ForToDo.ExpressionTo);
     
    931945var
    932946  ExecutorFunction: TExecutorFunction;
    933   Params: array of TExecutorFunctionCallbackParam;
     947  Params: array of TExecutorVariable;
    934948  I: Integer;
    935949  ExecutorVariable: TExecutorVariable;
     
    939953  ExecutorFunction := Block.GetFunction(FunctionCall.FunctionDef);
    940954  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
    941972    if FunctionCall.FunctionDef.InternalName <> '' then begin
    942973      SetLength(Params, FunctionCall.Params.Count);
    943974      for I := 0 to FunctionCall.Params.Count - 1 do begin
    944         Params[I] := TExecutorFunctionCallbackParam.Create;
    945         Params[I].Kind := FunctionCall.FunctionDef.Params[I].Kind;
    946         if FunctionCall.FunctionDef.Params[I].Kind = pkVar then begin
    947           Variable := TExpressionOperand(FunctionCall.Params[I]).VariableRef;
    948           //InitExecutorBlock(ExecutorFunction.Block, FunctionCall.FunctionDef.Block);
    949           ExecutorVariable := Block.GetVariable(Variable);
    950           Params[I].Variable := ExecutorVariable;
    951         end
    952         else Params[I].Value := ExecuteExpression(Block, FunctionCall.Params[I]);
     975        Variable := FunctionCall.FunctionDef.Block.Variables.SearchByName(
     976          TFunctionParameter(FunctionCall.FunctionDef.Params[I]).Name);
     977        Params[I] := ExecutorFunction.Block.Variables.SearchByVariable(Variable);
    953978      end;
    954979      Result := ExecutorFunction.Callback(Params);
    955       for I := 0 to FunctionCall.Params.Count - 1 do begin
    956         Params[I].Free;
    957       end;
    958980    end else begin
    959       InitExecutorBlock(ExecutorFunction.Block, FunctionCall.FunctionDef.Block);
    960 
    961       // Clean variables
    962       for I := 0 to FunctionCall.Params.Count - 1 do begin
    963         if FunctionCall.FunctionDef.Params[I].Kind = pkVar then begin
    964           Variable := TExpressionOperand(FunctionCall.Params[I]).VariableRef;
    965           ExecutorVariable := Block.Variables.SearchByVariable(Variable);
    966           ExecutorFunction.Block.Variables[I] := ExecutorVariable;
    967         end else begin
    968           Variable := FunctionCall.FunctionDef.Block.Variables.SearchByName(
    969             TFunctionParameter(FunctionCall.FunctionDef.Params[I]).Name);
    970           ExecutorVariable := ExecutorFunction.Block.Variables.SearchByVariable(Variable);
    971           ExecutorVariable.Value.Free;
    972           ExecutorVariable.Value := ExecuteExpression(Block, TExpression(FunctionCall.Params[I]));
    973         end;
    974       end;
    975 
    976981      ExecuteBlock(Block, FunctionCall.FunctionDef.Block, ExecutorFunction.Block);
    977       ExecutorVariable := ExecutorFunction.Block.Variables.SearchByVariable(TVariable(FunctionCall.FunctionDef.Block.Variables.SearchByName('Result')));
     982      ExecutorVariable := ExecutorFunction.Block.Variables.SearchByVariable(
     983        TVariable(FunctionCall.FunctionDef.Block.Variables.SearchByName('Result')));
    978984      Result := ExecutorVariable.Value.Clone;
    979985    end;
     
    985991var
    986992  ExecutorProcedure: TExecutorProcedure;
    987   Params: array of TExecutorFunctionCallbackParam;
     993  Params: array of TExecutorVariable;
    988994  I: Integer;
    989995  ExecutorVariable: TExecutorVariable;
    990996  Variable: TVariable;
     997  ProcedureDef: TProcedure;
    991998begin
    992999  ExecutorProcedure := Block.GetProcedure(ProcedureCall.ProcedureDef);
    9931000  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
    9941018    if ProcedureCall.ProcedureDef.InternalName <> '' then begin
    9951019      SetLength(Params, ProcedureCall.Params.Count);
    9961020      for I := 0 to ProcedureCall.Params.Count - 1 do begin
    997         Params[I] := TExecutorFunctionCallbackParam.Create;
    998         Params[I].Kind := ProcedureCall.ProcedureDef.Params[I].Kind;
    999         if ProcedureCall.ProcedureDef.Params[I].Kind = pkVar then begin
    1000           Variable := TExpressionOperand(ProcedureCall.Params[I]).VariableRef;
    1001           //InitExecutorBlock(ExecutorFunction.Block, FunctionCall.FunctionDef.Block);
    1002           ExecutorVariable := Block.GetVariable(Variable);
    1003           Params[I].Variable := ExecutorVariable;
    1004         end
    1005         else Params[I].Value := ExecuteExpression(Block, ProcedureCall.Params[I]);
     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;
    10061025      end;
     1026
    10071027      ExecutorProcedure.Callback(Params);
    1008       for I := 0 to ProcedureCall.Params.Count - 1 do begin
    1009         Params[I].Free;
    1010       end;
    10111028    end else begin
    1012       InitExecutorBlock(ExecutorProcedure.Block, ProcedureCall.ProcedureDef.Block);
    1013 
    1014       // Clean variables
    1015       for I := 0 to ProcedureCall.Params.Count - 1 do begin
    1016         if ProcedureCall.ProcedureDef.Params[I].Kind = pkVar then begin
    1017           Variable := TExpressionOperand(ProcedureCall.Params[I]).VariableRef;
    1018           ExecutorVariable := Block.Variables.SearchByVariable(Variable);
    1019           ExecutorProcedure.Block.Variables[I].Variable := Variable;
    1020           ExecutorProcedure.Block.Variables[I].Value := ExecutorVariable.Value;
    1021         end else begin
    1022           Variable := ProcedureCall.ProcedureDef.Block.Variables.SearchByName(
    1023             TFunctionParameter(ProcedureCall.ProcedureDef.Params[I]).Name);
    1024           ExecutorVariable := ExecutorProcedure.Block.Variables.SearchByVariable(Variable);
    1025           ExecutorVariable.Value.Free;
    1026           ExecutorVariable.Value := ExecuteExpression(Block, TExpression(ProcedureCall.Params[I]));
    1027         end;
    1028       end;
    1029 
    10301029      ExecuteBlock(Block, ProcedureCall.ProcedureDef.Block, ExecutorProcedure.Block);
    10311030    end;
     
    10391038  Variable: TExecutorVariable;
    10401039  ExecutorFunction: TExecutorFunction;
    1041   Params: array of TExecutorFunctionCallbackParam;
     1040  Params: array of TExecutorVariable;
    10421041begin
    10431042  Value := ExecuteExpression(Block, Assignment.Expression);
     
    10461045  if Assignment.Variable.TypeRef = Assignment.Expression.GetType then begin
    10471046    SetLength(Params, 1);
    1048     Params[0] := TExecutorFunctionCallbackParam.Create;
     1047    Params[0] := TExecutorVariable.Create;
    10491048    Params[0].Value := Value;
    1050     Variable.Value.Free;
    10511049    Variable.Value := ExecutorFunction.Callback(Params);
    10521050  end else raise Exception('Assignment result type is ' + Variable.Variable.TypeRef.Name +
    10531051    ' but value is ' + Assignment.Expression.GetType.Name + '.');
    1054   Value.Free;
     1052  FreeAndNil(Value);
    10551053end;
    10561054
     
    10761074  Value: TValue;
    10771075  ExecutorFunction: TExecutorFunction;
    1078   Params: array of TExecutorFunctionCallbackParam;
     1076  Params: array of TExecutorVariable;
    10791077  FuncName: string;
    10801078begin
     
    10881086  for I := 0 to Expression.Items.Count - 1 do begin
    10891087    Value := ExecuteExpression(Block, TExpression(Expression.Items[I]));
    1090     Params[I] := TExecutorFunctionCallbackParam.Create;
     1088    Params[I] := TExecutorVariable.Create;
    10911089    Params[I].Value := Value;
    10921090  end;
  • branches/xpascal/Generators/GeneratorPascal.pas

    r235 r236  
    1414    procedure GenerateProgram(Block: TBlock;  Prog:TProgram);
    1515    procedure GenerateFunction(ParentBlock: TBlock; FunctionDef: TFunction);
     16    procedure GenerateFunctionParams(ParentBlock: TBlock; Params: TFunctionParameters);
    1617    procedure GenerateProcedure(ParentBlock: TBlock; ProcedureDef: TProcedure);
    1718    procedure GenerateBlock(ParentBlock: TBlock; Block: TBlock);
     
    218219  AddTextLine('{$mode delphi}');
    219220  AddTextLine('');
    220   AddTextLine('uses SysUtils;');
     221  AddTextLine('uses');
     222  AddTextLine('  SysUtils;');
     223  AddTextLine('');
    221224  GenerateBlock(Block, Prog.Block);
    222225  AddTextLine('.');
     
    225228procedure TGeneratorPascal.GenerateFunction(ParentBlock: TBlock;
    226229  FunctionDef: TFunction);
    227 var
    228   I: Integer;
    229230begin
    230231  AddText('function ' + FunctionDef.Name);
    231   if FunctionDef.Params.Count > 0 then begin
    232     AddText('(');
    233     for I := 0 to FunctionDef.Params.Count - 1 do begin
    234       AddText(FunctionDef.Params[I].Name);
    235       AddText(': ');
    236       AddText(FunctionDef.Params[I].TypeRef.Name);
    237       if I > 0 then AddText(', ');
    238     end;
    239     AddText(')');
    240   end;
     232  GenerateFunctionParams(ParentBlock, FunctionDef.Params);
    241233  if Assigned(FunctionDef.ResultType) then begin
    242234    AddText(': ');
     
    259251end;
    260252
    261 procedure TGeneratorPascal.GenerateProcedure(ParentBlock: TBlock;
    262   ProcedureDef: TProcedure);
    263 var
    264   I: Integer;
    265 begin
    266   AddText('procedure ' + ProcedureDef.Name);
    267   if ProcedureDef.Params.Count > 0 then begin
     253procedure TGeneratorPascal.GenerateFunctionParams(ParentBlock: TBlock;
     254  Params: TFunctionParameters);
     255var
     256  I: Integer;
     257begin
     258  if Params.Count > 0 then begin
    268259    AddText('(');
    269     for I := 0 to ProcedureDef.Params.Count - 1 do begin
    270       AddText(ProcedureDef.Params[I].Name);
     260    for I := 0 to Params.Count - 1 do begin
     261      if Params[I].Kind = pkVar then AddText('var ');
     262      if Params[I].Kind = pkConst then AddText('const ');
     263      AddText(Params[I].Name);
    271264      AddText(': ');
    272       AddText(ProcedureDef.Params[I].TypeRef.Name);
     265      AddText(Params[I].TypeRef.Name);
    273266      if I > 0 then AddText(', ');
    274267    end;
    275268    AddText(')');
    276269  end;
     270end;
     271
     272procedure TGeneratorPascal.GenerateProcedure(ParentBlock: TBlock;
     273  ProcedureDef: TProcedure);
     274begin
     275  AddText('procedure ' + ProcedureDef.Name);
     276  GenerateFunctionParams(ParentBlock, ProcedureDef.Params);
    277277  AddTextLine(';');
    278278  if ProcedureDef.InternalName <> '' then begin
  • branches/xpascal/Parser.pas

    r234 r236  
    4444procedure TParser.InitSystemBlock(Block: TBlock);
    4545var
     46  I: Integer;
    4647  TypeBoolean: TType;
    4748  TypeString: TType;
     
    219220      Kind := pkVar;
    220221  end;
     222
     223  for I := 0 to Block.Functions.Count - 1 do
     224    Block.Functions[I].InitVariables;
     225  for I := 0 to Block.Procedures.Count - 1 do
     226    Block.Procedures[I].InitVariables;
    221227end;
    222228
  • branches/xpascal/Parsers/ParserPascal.pas

    r235 r236  
    372372          if Assigned(TypeRef) then begin
    373373            Func.ResultType := TypeRef;
    374             Variable := TVariable.Create;
    375             Variable.Name := 'Result';
    376             Variable.TypeRef := TypeRef;
    377             Variable.Internal := True;
    378             Func.Block.Variables.Add(Variable);
    379374          end else Error('Type ' + Token.Text + ' not found');
    380375        end;
    381376      end;
    382377      Tokenizer.Expect(';', tkSpecialSymbol);
     378      Func.InitVariables;
    383379      if ParseBlock(Block, NewBlock, Func.Block) then begin
    384380        Tokenizer.Expect(';', tkSpecialSymbol);
     
    405401    end;
    406402    Tokenizer.Expect(')', tkSpecialSymbol);
    407     for I := 0 to Params.Count - 1 do begin
    408       Variable := TVariable.Create;
    409       Variable.Name := Params[I].Name;
    410       Variable.TypeRef := Params[I].TypeRef;
    411       Variable.Internal := True;
    412       Block.Variables.Add(Variable);
    413     end;
    414403    Result := True;
    415404  end;
     
    463452        Proc.Params := FunctionParameters;
    464453      end;
    465 
    466454      Tokenizer.Expect(';', tkSpecialSymbol);
     455      Proc.InitVariables;
    467456      if ParseBlock(Block, NewBlock, Proc.Block) then begin
    468457        Tokenizer.Expect(';', tkSpecialSymbol);
  • branches/xpascal/Source.pas

    r233 r236  
    133133    Block: TBlock;
    134134    ParentType: TType;
     135    procedure InitVariables;
    135136    procedure GetValue(Index: Integer; out Value); override;
    136137    function GetField(Index: Integer): TField; override;
     
    159160    Block: TBlock;
    160161    ParentType: TType;
     162    procedure InitVariables;
    161163    procedure GetValue(Index: Integer; out Value); override;
    162164    function GetField(Index: Integer): TField; override;
     
    533535end;
    534536
     537procedure TProcedure.InitVariables;
     538var
     539  I: Integer;
     540  Variable: TVariable;
     541begin
     542  for I := 0 to Params.Count - 1 do begin
     543    Variable := TVariable.Create;
     544    Variable.Name := Params[I].Name;
     545    Variable.TypeRef := Params[I].TypeRef;
     546    Variable.Internal := True;
     547    Block.Variables.Add(Variable);
     548  end;
     549end;
     550
    535551procedure TProcedure.GetValue(Index: Integer; out Value);
    536552begin
     
    932948begin
    933949  Result := 4;
     950end;
     951
     952procedure TFunction.InitVariables;
     953var
     954  I: Integer;
     955  Variable: TVariable;
     956begin
     957  for I := 0 to Params.Count - 1 do begin
     958    Variable := TVariable.Create;
     959    Variable.Name := Params[I].Name;
     960    Variable.TypeRef := Params[I].TypeRef;
     961    Variable.Internal := True;
     962    Block.Variables.Add(Variable);
     963  end;
     964
     965  Variable := TVariable.Create;
     966  Variable.Name := 'Result';
     967  Variable.TypeRef := ResultType;
     968  Variable.Internal := True;
     969  Block.Variables.Add(Variable);
    934970end;
    935971
  • branches/xpascal/Tests.pas

    r235 r236  
    158158    ExpectedOutput := '-1' + LineEnding + '0' + LineEnding;
    159159  end;
     160  with TTestRun(Result.AddNew('function without result usage', TTestRun)) do begin
     161    Source.Add('function IsZero(A: Integer): Boolean;');
     162    Source.Add('begin');
     163    Source.Add('  Result := A = 0;');
     164    Source.Add('end;');
     165    Source.Add('');
     166    Source.Add('begin');
     167    Source.Add('  IsZero(0);');
     168    Source.Add('end.');
     169    ExpectedOutput := '';
     170  end;
    160171  with TTestRun(Result.AddNew('function var parameter', TTestRun)) do begin
    161172    Source.Add('function Test(var A: Integer): Boolean;');
    162173    Source.Add('begin');
    163174    Source.Add('  A := 10;');
    164     Source.Add('  Result := True;');
     175    Source.Add('  Result := 1 = 1;');
    165176    Source.Add('end;');
    166177    Source.Add('');
    167178    Source.Add('var');
    168179    Source.Add('  B: Integer;');
     180    Source.Add('  C: Boolean;');
    169181    Source.Add('begin');
    170182    Source.Add('  B := 1;');
    171     Source.Add('  Test(B);');
     183    Source.Add('  C := Test(B);');
    172184    Source.Add('  WriteLn(IntToStr(B));');
    173185    Source.Add('end.');
    174     ExpectedOutput := '-1' + LineEnding + '0' + LineEnding;
     186    ExpectedOutput := '10' + LineEnding;
    175187  end;
    176188  with TTestRun(Result.AddNew('procedure', TTestRun)) do begin
Note: See TracChangeset for help on using the changeset viewer.