Changeset 202 for branches/interpreter2/UExecutor.pas
- Timestamp:
- Apr 17, 2020, 12:09:15 AM (5 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
branches/interpreter2/UExecutor.pas
r201 r202 9 9 10 10 type 11 TExecutorFunctions = class; 12 11 13 TExecutorVariable = class 12 14 Variable: TVariable; 13 Value: string;15 Value: TValue; 14 16 end; 15 17 … … 21 23 end; 22 24 23 TExecutorFunctionCallback = function(Params: array of string): string of object; 25 { TExecutorType } 26 27 TExecutorType = class 28 TypeRef: TType; 29 Functions: TExecutorFunctions; 30 constructor Create; 31 destructor Destroy; override; 32 end; 33 34 { TExecutorTypes } 35 36 TExecutorTypes = class(TObjectList) 37 function SearchByType(TypeRef: TType): TExecutorType; 38 function AddNew(TypeRef: TType): TExecutorType; 39 end; 40 41 TExecutorFunctionCallback = function(Params: array of TValue): TValue of object; 24 42 25 43 TExecutorFunction = class … … 39 57 TExecutorBlock = class 40 58 Parent: TExecutorBlock; 59 Types: TExecutorTypes; 41 60 Variables: TExecutorVariables; 42 61 Functions: TExecutorFunctions; 43 62 function GetFunction(FunctionDef: TFunction): TExecutorFunction; 63 function GetType(TypeDef: TType): TExecutorType; 64 function GetVariable(Variable: TVariable): TExecutorVariable; 65 function GetTypeFunction(TypeDef: TType; FunctionDef: TFunction): TExecutorFunction; overload; 66 function GetTypeFunction(TypeDef: TType; FunctionName: string): TExecutorFunction; overload; 44 67 constructor Create; 45 68 destructor Destroy; override; … … 54 77 FOnOutput: TOutputEvent; 55 78 SystemBlock: TExecutorBlock; 56 function ExecuteWriteLn(Params: array of string): string; 57 function ExecuteWrite(Params: array of string): string; 79 function ExecuteWriteLn(Params: array of TValue): TValue; 80 function ExecuteWrite(Params: array of TValue): TValue; 81 function ExecuteIntToStr(Params: array of TValue): TValue; 82 function ExecuteStrToInt(Params: array of TValue): TValue; 83 function ExecuteStringAssign(Params: array of TValue): TValue; 84 function ExecuteStringAdd(Params: array of TValue): TValue; 85 function ExecuteStringEqual(Params: array of TValue): TValue; 86 function ExecuteStringNotEqual(Params: array of TValue): TValue; 87 function ExecuteIntegerAssign(Params: array of TValue): TValue; 88 function ExecuteIntegerAdd(Params: array of TValue): TValue; 89 function ExecuteIntegerSub(Params: array of TValue): TValue; 90 function ExecuteIntegerEqual(Params: array of TValue): TValue; 91 function ExecuteIntegerNotEqual(Params: array of TValue): TValue; 58 92 procedure InitExecutorBlock(ExecutorBlock: TExecutorBlock; Block: TBlock); 59 93 public … … 64 98 procedure ExecuteIfThenElse(Block: TExecutorBlock; IfThenElse: TIfThenElse); 65 99 procedure ExecuteWhileDo(Block: TExecutorBlock; WhileDo: TWhileDo); 100 procedure ExecuteForToDo(Block: TExecutorBlock; ForToDo: TForToDo); 66 101 procedure ExecuteBlock(ParentBlock: TExecutorBlock;Block: TBlock); 67 function ExecuteFunctionCall(Block: TExecutorBlock; FunctionCall: TFunctionCall): string;102 function ExecuteFunctionCall(Block: TExecutorBlock; FunctionCall: TFunctionCall): TValue; 68 103 procedure ExecuteAssignment(Block: TExecutorBlock; Assignment: TAssignment); 69 function ExecuteExpression(Block: TExecutorBlock; Expression: TExpression): string; 104 function ExecuteExpression(Block: TExecutorBlock; Expression: TExpression): TValue; 105 function ExecuteExpressionOperation(Block: TExecutorBlock; Expression: TExpressionOperation): TValue; 106 function ExecuteExpressionOperand(Block: TExecutorBlock; Expression: TExpressionOperand): TValue; 70 107 procedure Run; 71 108 procedure Output(Text: string); … … 75 112 76 113 implementation 114 115 { TExecutorType } 116 117 constructor TExecutorType.Create; 118 begin 119 Functions := TExecutorFunctions.Create; 120 end; 121 122 destructor TExecutorType.Destroy; 123 begin 124 Functions.Free; 125 inherited Destroy; 126 end; 127 128 { TExecutorTypes } 129 130 function TExecutorTypes.SearchByType(TypeRef: TType): TExecutorType; 131 var 132 I: Integer; 133 begin 134 I := 0; 135 while (I < Count) and (TExecutorType(Items[I]).TypeRef <> TypeRef) do Inc(I); 136 if I < Count then Result := TExecutorType(Items[I]) 137 else Result := nil; 138 end; 139 140 function TExecutorTypes.AddNew(TypeRef: TType): TExecutorType; 141 begin 142 Result := TExecutorType.Create; 143 Result.TypeRef := TypeRef; 144 Add(Result); 145 end; 77 146 78 147 { TExecutorFunctions } … … 124 193 end; 125 194 195 function TExecutorBlock.GetType(TypeDef: TType): TExecutorType; 196 begin 197 Result := Types.SearchByType(TypeDef); 198 if not Assigned(Result) and Assigned(Parent) then 199 Result := Parent.GetType(TypeDef); 200 end; 201 202 function TExecutorBlock.GetVariable(Variable: TVariable): TExecutorVariable; 203 begin 204 Result := Variables.SearchByVariable(Variable); 205 if not Assigned(Result) and Assigned(Parent) then 206 Result := Parent.GetVariable(Variable); 207 end; 208 209 function TExecutorBlock.GetTypeFunction(TypeDef: TType; FunctionDef: TFunction 210 ): TExecutorFunction; 211 var 212 ExecutorType: TExecutorType; 213 begin 214 ExecutorType := GetType(TypeDef); 215 Result := ExecutorType.Functions.SearchByFunction(FunctionDef); 216 end; 217 218 function TExecutorBlock.GetTypeFunction(TypeDef: TType; FunctionName: string 219 ): TExecutorFunction; 220 begin 221 Result := GetTypeFunction(TypeDef, TypeDef.Functions.SearchByName(FunctionName)); 222 end; 223 126 224 constructor TExecutorBlock.Create; 127 225 begin 226 Types := TExecutorTypes.Create; 128 227 Variables := TExecutorVariables.Create; 129 228 Functions := TExecutorFunctions.Create; … … 134 233 Variables.Free; 135 234 Functions.Free; 235 Types.Free; 136 236 inherited Destroy; 137 237 end; … … 139 239 { TExecutor } 140 240 141 function TExecutor.ExecuteWriteLn(Params: array of string): string;241 function TExecutor.ExecuteWriteLn(Params: array of TValue): TValue; 142 242 var 143 243 I: Integer; 144 244 Text: string; 145 245 begin 146 Result := '';246 Result := nil; 147 247 Text := ''; 148 248 for I := 0 to Length(Params) - 1 do 149 Text := Text + Params[I];249 Text := Text + TValueString(Params[I]).Value; 150 250 Output(Text + LineEnding); 151 251 end; 152 252 153 function TExecutor.ExecuteWrite(Params: array of string): string;253 function TExecutor.ExecuteWrite(Params: array of TValue): TValue; 154 254 var 155 255 I: Integer; 156 256 Text: string; 157 257 begin 158 Result := '';258 Result := nil; 159 259 Text := ''; 160 260 for I := 0 to Length(Params) - 1 do 161 Text := Text + Params[I];261 Text := Text + TValueString(Params[I]).Value; 162 262 Output(Text); 163 263 end; 164 264 265 function TExecutor.ExecuteIntToStr(Params: array of TValue): TValue; 266 begin 267 Result := TValueString.Create; 268 TValueString(Result).Value := IntToStr(TValueInteger(Params[0]).Value); 269 end; 270 271 function TExecutor.ExecuteStrToInt(Params: array of TValue): TValue; 272 begin 273 Result := TValueInteger.Create; 274 TValueInteger(Result).Value := StrToInt(TValueString(Params[0]).Value); 275 end; 276 277 function TExecutor.ExecuteStringAssign(Params: array of TValue): TValue; 278 begin 279 Result := TValueString.Create; 280 TValueString(Result).Value := TValueString(Params[0]).Value; 281 end; 282 283 function TExecutor.ExecuteStringAdd(Params: array of TValue): TValue; 284 begin 285 Result := TValueString.Create; 286 TValueString(Result).Value := TValueString(Params[0]).Value + TValueString(Params[1]).Value; 287 end; 288 289 function TExecutor.ExecuteStringEqual(Params: array of TValue): TValue; 290 begin 291 Result := TValueBoolean.Create; 292 TValueBoolean(Result).Value := TValueString(Params[0]).Value = TValueString(Params[1]).Value; 293 end; 294 295 function TExecutor.ExecuteStringNotEqual(Params: array of TValue): TValue; 296 begin 297 Result := TValueBoolean.Create; 298 TValueBoolean(Result).Value := TValueString(Params[0]).Value <> TValueString(Params[1]).Value; 299 end; 300 301 function TExecutor.ExecuteIntegerAssign(Params: array of TValue): TValue; 302 begin 303 Result := TValueInteger.Create; 304 TValueInteger(Result).Value := TValueInteger(Params[0]).Value; 305 end; 306 307 function TExecutor.ExecuteIntegerAdd(Params: array of TValue): TValue; 308 begin 309 Result := TValueInteger.Create; 310 TValueInteger(Result).Value := TValueInteger(Params[0]).Value + TValueInteger(Params[1]).Value; 311 end; 312 313 function TExecutor.ExecuteIntegerSub(Params: array of TValue): TValue; 314 begin 315 Result := TValueInteger.Create; 316 TValueInteger(Result).Value := TValueInteger(Params[0]).Value - TValueInteger(Params[1]).Value; 317 end; 318 319 function TExecutor.ExecuteIntegerEqual(Params: array of TValue): TValue; 320 begin 321 Result := TValueBoolean.Create; 322 TValueBoolean(Result).Value := TValueInteger(Params[0]).Value = TValueInteger(Params[1]).Value; 323 end; 324 325 function TExecutor.ExecuteIntegerNotEqual(Params: array of TValue): TValue; 326 begin 327 Result := TValueBoolean.Create; 328 TValueBoolean(Result).Value := TValueInteger(Params[0]).Value <> TValueInteger(Params[1]).Value; 329 end; 330 165 331 procedure TExecutor.InitExecutorBlock(ExecutorBlock: TExecutorBlock; Block: TBlock); 166 332 var 167 333 I: Integer; 334 J: Integer; 168 335 ExecutorFunction: TExecutorFunction; 169 begin 336 ExecutorType: TExecutorType; 337 begin 338 for I := 0 to Block.Types.Count - 1 do begin 339 ExecutorType := ExecutorBlock.Types.AddNew(TType(Block.Types[I])); 340 for J := 0 to ExecutorType.TypeRef.Functions.Count - 1 do begin 341 ExecutorFunction := ExecutorType.Functions.AddNew(TFunction(ExecutorType.TypeRef.Functions[J])); 342 if ExecutorType.TypeRef.Name = 'string' then begin 343 if ExecutorFunction.FunctionDef.Name = '_Assign' then begin 344 ExecutorFunction.Callback := ExecuteStringAssign; 345 end else 346 if ExecutorFunction.FunctionDef.Name = '_Add' then begin 347 ExecutorFunction.Callback := ExecuteStringAdd; 348 end else 349 if ExecutorFunction.FunctionDef.Name = '_Equal' then begin 350 ExecutorFunction.Callback := ExecuteStringEqual; 351 end; 352 if ExecutorFunction.FunctionDef.Name = '_NotEqual' then begin 353 ExecutorFunction.Callback := ExecuteStringNotEqual; 354 end; 355 end; 356 if ExecutorType.TypeRef.Name = 'Integer' then begin 357 if ExecutorFunction.FunctionDef.Name = '_Assign' then begin 358 ExecutorFunction.Callback := ExecuteIntegerAssign; 359 end else 360 if ExecutorFunction.FunctionDef.Name = '_Add' then begin 361 ExecutorFunction.Callback := ExecuteIntegerAdd; 362 end else 363 if ExecutorFunction.FunctionDef.Name = '_Sub' then begin 364 ExecutorFunction.Callback := ExecuteIntegerSub; 365 end else 366 if ExecutorFunction.FunctionDef.Name = '_Equal' then begin 367 ExecutorFunction.Callback := ExecuteIntegerEqual; 368 end else 369 if ExecutorFunction.FunctionDef.Name = '_NotEqual' then begin 370 ExecutorFunction.Callback := ExecuteIntegerNotEqual; 371 end; 372 end; 373 end; 374 end; 170 375 for I := 0 to Block.Variables.Count - 1 do 171 376 ExecutorBlock.Variables.AddNew(TVariable(Block.Variables[I])); 172 377 for I := 0 to Block.Functions.Count - 1 do begin 173 378 ExecutorFunction := ExecutorBlock.Functions.AddNew(TFunction(Block.Functions[I])); 174 if ExecutorFunction.FunctionDef.Name = 'Write' then ExecutorFunction.Callback := ExecuteWrite 175 else if ExecutorFunction.FunctionDef.Name = 'WriteLn' then ExecutorFunction.Callback := ExecuteWriteLn; 379 if ExecutorFunction.FunctionDef.Name = 'Write' then begin 380 ExecutorFunction.Callback := ExecuteWrite; 381 end else 382 if ExecutorFunction.FunctionDef.Name = 'WriteLn' then begin 383 ExecutorFunction.Callback := ExecuteWriteLn; 384 end; 385 if ExecutorFunction.FunctionDef.Name = 'IntToStr' then begin 386 ExecutorFunction.Callback := ExecuteIntToStr; 387 end else 388 if ExecutorFunction.FunctionDef.Name = 'StrToInt' then begin 389 ExecutorFunction.Callback := ExecuteStrToInt; 390 end; 176 391 end; 177 392 end; … … 200 415 else if Command is TIfThenElse then ExecuteIfThenElse(Block, TIfThenElse(Command)) 201 416 else if Command is TWhileDo then ExecuteWhileDo(Block, TWhileDo(Command)) 417 else if Command is TForToDo then ExecuteForToDo(Block, TForToDo(Command)) 202 418 else raise Exception.Create('Unsupported command type'); 203 419 end; … … 206 422 IfThenElse: TIfThenElse); 207 423 var 208 Value: string;424 Value: TValue; 209 425 begin 210 426 Value := ExecuteExpression(Block, IfThenElse.Expression); 211 if Value <> '' then ExecuteCommand(Block, IfThenElse.CommandThen) 212 else ExecuteCommand(Block, IfThenElse.CommandElse); 427 if Value is TValueBoolean then begin 428 if TValueBoolean(Value).Value then ExecuteCommand(Block, IfThenElse.CommandThen) 429 else ExecuteCommand(Block, IfThenElse.CommandElse); 430 end else raise Exception.Create('Expected boolean value.'); 213 431 end; 214 432 215 433 procedure TExecutor.ExecuteWhileDo(Block: TExecutorBlock; WhileDo: TWhileDo); 216 434 var 217 Value: string;435 Value: TValue; 218 436 begin 219 437 while True do begin 220 438 Value := ExecuteExpression(Block, WhileDo.Expression); 221 if Value <> '' then Continue 222 else Break; 439 if Value is TValueBoolean then begin 440 if not TValueBoolean(Value).Value then Break; 441 ExecuteCommand(Block, WhileDo.Command); 442 end else raise Exception.Create('Expected boolean value.'); 443 end; 444 end; 445 446 procedure TExecutor.ExecuteForToDo(Block: TExecutorBlock; ForToDo: TForToDo); 447 var 448 Value: TValue; 449 Variable: TExecutorVariable; 450 Limit: TValue; 451 begin 452 Variable := Block.GetVariable(ForToDo.VariableRef); 453 Variable.Value := ExecuteExpression(Block, ForToDo.ExpressionFrom); 454 Limit := ExecuteExpression(Block, ForToDo.ExpressionTo); 455 while True do begin 456 ExecuteCommand(Block, ForToDo.Command); 457 TValueInteger(Variable.Value).Value := TValueInteger(Variable.Value).Value + 1; 458 if TValueInteger(Variable.Value).Value > TValueInteger(Limit).Value then Break; 223 459 end; 224 460 end; … … 236 472 237 473 function TExecutor.ExecuteFunctionCall(Block: TExecutorBlock; 238 FunctionCall: TFunctionCall): string;474 FunctionCall: TFunctionCall): TValue; 239 475 var 240 476 ExecutorFunction: TExecutorFunction; 241 Params: array of string;242 I: Integer; 243 begin 244 Result := '';477 Params: array of TValue; 478 I: Integer; 479 begin 480 Result := nil; 245 481 ExecutorFunction := Block.GetFunction(FunctionCall.FunctionDef); 246 482 if Assigned(ExecutorFunction) then begin 247 483 SetLength(Params, FunctionCall.Params.Count); 248 for I := 0 to FunctionCall.Params.Count - 1 do 484 for I := 0 to FunctionCall.Params.Count - 1 do begin 249 485 Params[I] := ExecuteExpression(Block, TExpression(FunctionCall.Params[0])); 486 end; 250 487 Result := ExecutorFunction.Callback(Params); 251 488 end else raise Exception.Create('No executor for ' + FunctionCall.FunctionDef.Name + ' function.'); … … 255 492 Assignment: TAssignment); 256 493 var 257 Value: string;494 Value: TValue; 258 495 Variable: TExecutorVariable; 496 ExecutorFunction: TExecutorFunction; 497 Params: array of TValue; 259 498 begin 260 499 Value := ExecuteExpression(Block, Assignment.Expression); 261 Variable := Block.Variables.SearchByVariable(Assignment.Variable); 262 Variable.Value := Value; 500 Variable := Block.GetVariable(Assignment.Variable); 501 ExecutorFunction := Block.GetTypeFunction(Assignment.Variable.TypeRef, '_Assign'); 502 if Assignment.Variable.TypeRef = Assignment.Expression.GetType then begin; 503 SetLength(Params, 1); 504 Params[0] := Value; 505 Variable.Value := ExecutorFunction.Callback(Params); 506 end else raise Exception('Assignment result type is ' + Variable.Variable.TypeRef.Name + 507 ' but value is ' + Assignment.Expression.GetType.Name + '.'); 263 508 end; 264 509 265 510 function TExecutor.ExecuteExpression(Block: TExecutorBlock; 266 Expression: TExpression): string; 511 Expression: TExpression): TValue; 512 begin 513 if Expression is TExpressionOperation then 514 Result := ExecuteExpressionOperation(Block, TExpressionOperation(Expression)) 515 else 516 if Expression is TExpressionOperand then 517 Result := ExecuteExpressionOperand(Block, TExpressionOperand(Expression)) 518 else raise Exception.Create('Unknown expression class.'); 519 end; 520 521 function TExecutor.ExecuteExpressionOperation(Block: TExecutorBlock; 522 Expression: TExpressionOperation): TValue; 523 var 524 I: Integer; 525 Value: TValue; 526 ExecutorFunction: TExecutorFunction; 527 Params: array of TValue; 528 FuncName: string; 529 begin 530 if Expression.Operation = eoAdd then FuncName := '_Add' 531 else if Expression.Operation = eoSub then FuncName := '_Sub' 532 else if Expression.Operation = eoEqual then FuncName := '_Equal' 533 else if Expression.Operation = eoNotEqual then FuncName := '_NotEqual' 534 else raise Exception.Create('Unsupported operation type.'); 535 536 ExecutorFunction := Block.GetTypeFunction(Expression.TypeRef, FuncName); 537 Result := Expression.TypeRef.ValueClass.Create; 538 539 SetLength(Params, Expression.Items.Count); 540 for I := 0 to Expression.Items.Count - 1 do begin 541 Value := ExecuteExpression(Block, TExpression(Expression.Items[I])); 542 Params[I] := Value; 543 end; 544 Result := ExecutorFunction.Callback(Params); 545 end; 546 547 function TExecutor.ExecuteExpressionOperand(Block: TExecutorBlock; 548 Expression: TExpressionOperand): TValue; 267 549 begin 268 550 if Assigned(Expression.VariableRef) then begin … … 274 556 if Assigned(Expression.FunctionCall) then begin 275 557 Result := ExecuteFunctionCall(Block, Expression.FunctionCall); 276 end ;558 end else raise Exception.Create('Unsupported exception operand type.'); 277 559 end; 278 560
Note:
See TracChangeset
for help on using the changeset viewer.