Ignore:
Timestamp:
Feb 11, 2017, 4:35:08 PM (8 years ago)
Author:
chronos
Message:
  • Modified: Improved interpeter. Better handling of execution of functions and passing value of parameters.
File:
1 edited

Legend:

Unmodified
Added
Removed
  • branches/interpreter/Execute3.pas

    r100 r101  
    88type
    99  TVariableValue = record
     10    VarRef: PVariable;
    1011    BaseType: TBaseType;
    1112    case Integer of
    12       0: (ValueChar: Char);
    13       1: (ValueInteger: Integer);
    14       2: (ValueString: ShortString);
    15       3: (ValueBoolean: Boolean);
     13      btChar: (ValueChar: Char);
     14      btInteger: (ValueInteger: Integer);
     15      btShortString: (ValueString: ShortString);
     16      btBoolean: (ValueBoolean: Boolean);
    1617  end;
    1718  PVariableValue = ^TVariableValue;
     19
     20  { TVariableValues }
    1821
    1922  TVariableValues = record
    2023    Items: array of TVariableValue;
     24    function GetByName(Name: string): PVariableValue;
    2125  end;
    2226
     
    4044var
    4145  ExecutionContexts: TExecutionContexts;
     46  ExecutionContextCurrent: PExecutionContext;
     47  MainCode: PProgramCode;
    4248
    4349procedure ExecuteProgram(ProgramCode: PProgramCode);
     
    4753
    4854procedure ExecuteCommand(Command: PCommand); forward;
     55procedure ExecuteGetValue(GetValue: PGetValue; Value: PVariableValue); forward;
     56procedure AssignVariable(Dest, Source: PVariableValue); forward;
     57procedure ExecuteExecution(Execution: PExecution; ReturnValue: PVariableValue); forward;
     58
     59
     60procedure ShowError(Text: string);
     61begin
     62  WriteLn(Text);
     63  Halt;
     64end;
    4965
    5066procedure ExecuteBeginEnd(BeginEnd: PBeginEnd);
     
    5672end;
    5773
    58 function ExecuteExpressionBoolean(Expression: PExpression): Boolean;
    59 begin
    60 
     74procedure ShowErrorType(Variable: PVariableValue);
     75begin
     76  ShowError('Not suppoted type')
     77end;
     78
     79procedure VariableAdd(Result, Operand: PVariableValue);
     80begin
     81  case Result^.BaseType of
     82    btBoolean: ShowErrorType(Result);
     83    btChar: ShowErrorType(Result);
     84    btInteger: Result^.ValueInteger := Result^.ValueInteger + Operand^.ValueInteger;
     85    btShortString: Result^.ValueString := Result^.ValueString + Operand^.ValueString;
     86  end;
     87end;
     88
     89procedure VariableSubtract(Result, Operand: PVariableValue);
     90begin
     91  case Result^.BaseType of
     92    btBoolean: ShowErrorType(Result);
     93    btChar: ShowErrorType(Result);
     94    btInteger: Result^.ValueInteger := Result^.ValueInteger - Operand^.ValueInteger;
     95    btShortString: ShowErrorType(Result);
     96  end;
     97end;
     98
     99procedure VariableAnd(Result, Operand: PVariableValue);
     100begin
     101  case Result^.BaseType of
     102    btBoolean: Result^.ValueBoolean := Result^.ValueBoolean and Operand^.ValueBoolean;
     103    btChar: ShowErrorType(Result);
     104    btInteger: Result^.ValueInteger := Result^.ValueInteger and Operand^.ValueInteger;
     105    btShortString: ShowErrorType(Result);
     106  end;
     107end;
     108
     109procedure VariableOr(Result, Operand: PVariableValue);
     110begin
     111  case Result^.BaseType of
     112    btBoolean: Result^.ValueBoolean := Result^.ValueBoolean or Operand^.ValueBoolean;
     113    btChar: ShowErrorType(Result);
     114    btInteger: Result^.ValueInteger := Result^.ValueInteger or Operand^.ValueInteger;
     115    btShortString: ShowErrorType(Result);
     116  end;
     117end;
     118
     119procedure VariableEqual(Result, Operand1, Operand2: PVariableValue);
     120begin
     121  case Result^.BaseType of
     122    btBoolean: Result^.ValueBoolean := Operand1^.ValueBoolean = Operand2^.ValueBoolean;
     123    btChar: ShowErrorType(Result);
     124    btInteger: ShowErrorType(Result);
     125    btShortString: ShowErrorType(Result);
     126  end;
     127end;
     128
     129procedure VariableNotEqual(Result, Operand1, Operand2: PVariableValue);
     130begin
     131  case Result^.BaseType of
     132    btBoolean: Result^.ValueBoolean := Operand1^.ValueBoolean <> Operand2^.ValueBoolean;
     133    btChar: ShowErrorType(Result);
     134    btInteger: ShowErrorType(Result);
     135    btShortString: ShowErrorType(Result);
     136  end;
     137end;
     138
     139procedure ExecuteExpression(Expression: PExpression; Value: PVariableValue);
     140var
     141  I: Integer;
     142  SubValue: TVariableValue;
     143begin
     144  if Expression^.NodeType = ntOperator then begin
     145    I := 0;
     146    while I < Length(Expression^.Items) do begin
     147      if Expression^.Items[I].NodeType = ntOperator then begin
     148        ExecuteExpression(@Expression^.Items[I], @SubValue);
     149      end else
     150      if Expression^.Items[I].NodeType = ntValue then begin
     151        ExecuteGetValue(@Expression^.Items[I].Value, @SubValue);
     152      end;
     153
     154      if I = 0 then begin
     155        // Just assign first operand
     156        case Expression^.OperatorType of
     157          opAdd: AssignVariable(Value, @SubValue);
     158          opSubtract: AssignVariable(Value, @SubValue);
     159          opAnd: AssignVariable(Value, @SubValue);
     160          opOr: AssignVariable(Value, @SubValue);
     161          opEqual: AssignVariable(Value, @SubValue);
     162          opNotEqual: AssignVariable(Value, @SubValue);
     163          else ShowError('Unsupported operator type');
     164        end;
     165      end else begin
     166        case Expression^.OperatorType of
     167          opAdd: VariableAdd(Value, @SubValue);
     168          opSubtract: VariableSubtract(Value, @SubValue);
     169          opAnd: VariableAnd(Value, @SubValue);
     170          opOr: VariableOr(Value, @SubValue);
     171          opEqual: VariableEqual(Value, Value, @SubValue);
     172          opNotEqual: VariableNotEqual(Value, Value, @SubValue);
     173          else ShowError('Unsupported operator type');
     174        end;
     175      end;
     176      I := I + 1;
     177    end;
     178  end else
     179  if Expression^.NodeType = ntValue then begin
     180    ExecuteGetValue(@Expression^.Value, Value);
     181  end else ShowError('Uninitialized expression');
     182end;
     183
     184function ExecuteGetValueBoolean(GetValue: PGetValue): Boolean;
     185var
     186  Value: TVariableValue;
     187begin
     188  ExecuteGetValue(GetValue, @Value);
     189  Result := (Value.BaseType = btBoolean) and Value.ValueBoolean;
    61190end;
    62191
    63192procedure ExecuteWhileDo(WhileDo: PWhileDo);
    64193begin
    65   while ExecuteExpressionBoolean(@WhileDo^.Condition) do
     194  while ExecuteGetValueBoolean(@WhileDo^.Condition) do
    66195    ExecuteCommand(@WhileDo^.Command);
    67196end;
    68197
    69198procedure ExecuteIfThenElse(IfThenElse: PIfThenElse);
    70 begin
    71   if ExecuteExpressionBoolean(@IfThenElse^.Condition) then
    72     ExecuteCommand(@IfThenElse^.DoThen)
    73     else ExecuteCommand(@IfThenElse^.DoElse);
    74 end;
    75 
    76 procedure ExecuteExecution(Execution: PExecution);
    77 var
    78   I: Integer;
    79 begin
     199var
     200  Condition: Boolean;
     201begin
     202  Condition := ExecuteGetValueBoolean(@IfThenElse^.Condition);
     203  if Condition then
     204    ExecuteCommand(@IfThenElse^.DoThen);
     205  if (IfThenElse^.DoElse.CmdType <> ctNone) and not Condition then
     206    ExecuteCommand(@IfThenElse^.DoElse);
     207end;
     208
     209procedure AssignConstant(Variable: PVariableValue; Constant: PConstant);
     210begin
     211  Variable^.BaseType := Constant^.DataType^.BaseType;
     212  case Constant^.DataType^.BaseType of
     213    btBoolean: Variable^.ValueBoolean := Constant^.ValueBoolean;
     214    btInteger: Variable^.ValueInteger := Constant^.ValueInteger;
     215    btShortString: Variable^.ValueString := Constant^.ValueString;
     216    btChar: Variable^.ValueChar := Constant^.ValueChar;
     217  end;
     218end;
     219
     220procedure ExecuteGetValue(GetValue: PGetValue; Value: PVariableValue);
     221begin
     222  case GetValue.ReadType of
     223    rtVariable: AssignVariable(Value, ExecutionContextCurrent^.VariableValues.GetByName(GetValue.Variable^.Name));
     224    //rtConstant: Value := ExecutionContextCurrent^.VariableValues.GetByName(GetValue.Variable^.Name);
     225    rtExpression: ExecuteExpression(GetValue.Expression, Value);
     226    rtValue: AssignConstant(Value, @GetValue.Value);
     227    rtFunctionCall: ExecuteExecution(GetValue.FunctionCall, Value)
     228  end;
     229end;
     230
     231procedure AssignVariable(Dest, Source: PVariableValue);
     232begin
     233  Dest.BaseType := Source.BaseType;
     234  case Dest.BaseType of
     235    btInteger: Dest.ValueInteger := Source.ValueInteger;
     236    btChar: Dest.ValueChar := Source.ValueChar;
     237    btBoolean: Dest.ValueBoolean := Source.ValueBoolean;
     238    btShortString: Dest.ValueString := Source.ValueString;
     239  end;
     240end;
     241
     242function IsBuildInFunction(Name: string): Boolean;
     243begin
     244  Result := (Name = 'WriteLn') or (Name = 'Eof') or (Name = 'Halt') or (Name = 'Read') or
     245    (Name = 'Length') or (Name = 'SetLength');
     246end;
     247
     248procedure ExecuteBuildInSetResult(Execution: PExecution; TypeName: string);
     249var
     250  DataType: PType;
     251begin
     252  if Execution^.Func^.Variables.GetByName('Result') = nil then begin
     253    DataType := MainCode.Types.GetByName(TypeName);
     254    Execution^.Func^.Variables.Add(VariableCreate('Result', DataType));
     255    SetLength(ExecutionContextCurrent^.VariableValues.Items, Length(ExecutionContextCurrent^.VariableValues.Items) + 1);
     256    ExecutionContextCurrent^.VariableValues.Items[0].VarRef := @Execution^.Func^.Variables.Items[Length(Execution^.Func^.Variables.Items) - 1];
     257    ExecutionContextCurrent^.VariableValues.Items[0].BaseType := btBoolean;
     258  end;
     259end;
     260
     261procedure ExecuteBuildIn(Execution: PExecution);
     262begin
     263  if Execution^.Func^.Name = 'WriteLn' then begin
     264    WriteLn(ExecutionContextCurrent^.VariableValues.GetByName('Text')^.ValueString)
     265  end else
     266  if Execution^.Func^.Name = 'Halt' then begin
     267    Halt;
     268  end else
     269  if Execution^.Func^.Name = 'Eof' then begin
     270    ExecuteBuildInSetResult(Execution, 'Boolean');
     271    ExecutionContextCurrent^.VariableValues.GetByName('Result')^.ValueBoolean := True;
     272  end else ShowError('Unsupported build-in function.');
     273end;
     274
     275procedure ExecuteExecution(Execution: PExecution; ReturnValue: PVariableValue);
     276var
     277  I: Integer;
     278  Param: PGetValue;
     279  ParamValue: TVariableValue;
     280  DestVar: PVariableValue;
     281  NewContext: TExecutionContext;
     282begin
     283  // Prepare new execution context
     284  FillChar(NewContext, SizeOf(TExecutionContext), 0);
     285  NewContext.LoadFromVariables(@Execution^.Func^.Variables);
     286
     287  // Copy execution parameters to new execution context as local variables
     288  for I := 0 to Length(Execution^.Func^.Parameters.Items) - 1 do begin
     289    DestVar := NewContext.VariableValues.GetByName(
     290      Execution^.Func^.Parameters.Items[I].Name);
     291    Param := @Execution^.Parameters.Items[I];
     292    ExecuteGetValue(Param, @ParamValue);
     293    AssignVariable(DestVar, @ParamValue);
     294  end;
     295
    80296  ExecutionContexts.Add;
    81   ExecutionContexts.Last^.LoadFromVariables(@Execution^.Func^.Variables);
    82 {  Execution^.Func^.Variables.Add(VariableCreate('Result', Execution^.Func^.ReturnType));
    83   for I := 0 to Length(Execution^.Func^.Parameters.Items) - 1 do begin
    84     Execution^.Func^.Variables.Add(VariableCreate(Execution^.Func^.Parameters.Items[I].Name,
    85       Execution^.Func^.Parameters.Items[I].DataType));
    86     case Assignment^.Destination^.DataType^.BaseType of
    87       Execution^.Func^.Variables.Items[Length(Execution^.Func^.Variables.Items) - 1].V
    88     end;
    89   end;
    90 }
    91   ExecuteBeginEnd(@Execution^.Func^.BeginEnd);
     297  ExecutionContexts.Items[Length(ExecutionContexts.Items) - 1] := NewContext;
     298
     299  //WriteLn('Executed ' + Execution^.Func^.Name);
     300  if IsBuildInFunction(Execution^.Func^.Name) then ExecuteBuildIn(Execution)
     301    else ExecuteBeginEnd(@Execution^.Func^.BeginEnd);
     302  if (ReturnValue <> nil) and (Execution^.Func^.ReturnType <> nil) then
     303    AssignVariable(ReturnValue, ExecutionContextCurrent^.VariableValues.GetByName('Result'));
    92304  ExecutionContexts.RemoveLast;
    93305end;
     
    96308var
    97309  DestVariable: PVariableValue;
    98 begin
    99   DestVariable := @ExecutionContexts.Last^.VariableValues.Items[Assignment^.Destination^.Index];
    100   case DestVariable^.BaseType of
    101     btBoolean: DestVariable^.ValueBoolean := ExecuteExpressionBoolean(@Assignment^.Source);
    102     //btChar: Assignment^.Destination.ValueBoolean := ExecuteExpressionChar(@Assignment^.Source);
    103     //btString: Assignment^.Destination.ValueBoolean := ExecuteExpressionString(@Assignment^.Source);
    104     //btInteger: Assignment^.Destination.ValueBoolean := ExecuteExpressionInteger(@Assignment^.Source);
    105   end;
     310  SrcVariable: TVariableValue;
     311begin
     312  DestVariable := ExecutionContextCurrent^.VariableValues.GetByName(Assignment^.Destination^.Name);
     313  FillChar(SrcVariable, SizeOf(TVariableValue), 0);
     314  ExecuteGetValue(@Assignment^.Source, @SrcVariable);
     315  AssignVariable(DestVariable, @SrcVariable);
    106316end;
    107317
     
    112322    ctWhileDo: ExecuteWhileDo(Command^.WhileDo);
    113323    ctIfThenElse: ExecuteIfThenElse(Command^.IfThenElse);
    114     ctExecution: ExecuteExecution(Command^.Execution);
     324    ctExecution: ExecuteExecution(Command^.Execution, nil);
    115325    ctAssignment: ExecuteAssignment(Command^.Assignment);
    116326  end;
     
    119329procedure ExecuteProgram(ProgramCode: PProgramCode);
    120330begin
    121   SetLength(ExecutionContexts.Items, 1);
    122   ExecutionContexts.Last^.LoadFromVariables(@ProgramCode^.Variables);
     331  MainCode := ProgramCode;
     332  ExecutionContexts.Add;
     333  ExecutionContextCurrent^.LoadFromVariables(@ProgramCode^.Variables);
    123334  ExecuteBeginEnd(@ProgramCode^.BeginEnd);
     335end;
     336
     337{ TVariableValues }
     338
     339function TVariableValues.GetByName(Name: string): PVariableValue;
     340var
     341  I: Integer;
     342begin
     343  I := 0;
     344  while (I < Length(Items)) and (Items[I].VarRef^.Name <> Name) do Inc(I);
     345  if I < Length(Items) then Result := @Items[I]
     346    else Result := nil;
    124347end;
    125348
     
    133356  for I := 0 to Length(Variables.Items) - 1 do begin
    134357    VariableValues.Items[I].BaseType := Variables.Items[I].DataType.BaseType;
     358    VariableValues.Items[I].VarRef := @Variables.Items[I];
    135359  end;
    136360end;
     
    146370begin
    147371  SetLength(Items, Length(Items) + 1);
     372  ExecutionContextCurrent := Last;
    148373end;
    149374
     
    151376begin
    152377  SetLength(Items, Length(Items) - 1);
     378  ExecutionContextCurrent := Last;
    153379end;
    154380
Note: See TracChangeset for help on using the changeset viewer.