Changeset 147 for branches/easy compiler/USourceExecutor.pas
- Timestamp:
- Jan 17, 2018, 3:34:13 PM (7 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
branches/easy compiler/USourceExecutor.pas
r146 r147 22 22 TExecutorVariables = class(TObjectList) 23 23 function Search(Variable: TSourceVariable): TExecutorVariable; 24 end; 25 26 TExecutorRepeat = class 27 RepeatCommand: TCommandRepeat; 28 Terminated: Boolean; 29 end; 30 31 { TExecutorRepeats } 32 33 TExecutorRepeats = class(TObjectList) 34 function Search(RepeatCommand: TCommandRepeat): TExecutorRepeat; 24 35 end; 25 36 … … 31 42 FOnOutput: TOutputEvent; 32 43 Variables: TExecutorVariables; 44 RepeatBlocks: TExecutorRepeats; 45 SkipNext: Boolean; 33 46 procedure ExecuteBeginEnd(BeginEnd: TCommandBeginEnd); 47 procedure ExecuteCommand(Command: TSourceCommand); 48 procedure ExecuteBreak(CommandBreak: TCommandBreak); 49 procedure ExecuteRepeat(CommandRepeat: TCommandRepeat); 50 function ReadValueReference(Reference: TSourceReference): TSourceValue; 51 function ReadVarReference(Reference: TSourceReference): TSourceVariable; 34 52 public 35 53 constructor Create; … … 43 61 implementation 44 62 63 { TExecutorRepeat } 64 65 function TExecutorRepeats.Search(RepeatCommand: TCommandRepeat): TExecutorRepeat; 66 var 67 Item: TExecutorRepeat; 68 begin 69 Result := nil; 70 for Item in Self do 71 if Item.RepeatCommand = RepeatCommand then begin 72 Result := Item; 73 Break; 74 end; 75 end; 76 45 77 { TExecutorVariable } 46 78 … … 71 103 begin 72 104 Variables := TExecutorVariables.Create; 105 RepeatBlocks := TExecutorRepeats.Create; 73 106 end; 74 107 75 108 destructor TSourceExecutor.Destroy; 76 109 begin 110 RepeatBlocks.Free; 77 111 Variables.Free; 78 112 inherited Destroy; … … 81 115 procedure TSourceExecutor.Execute(SourceCode: TSourceCode); 82 116 begin 117 SkipNext := False; 83 118 ExecuteBeginEnd(SourceCode.Main); 84 119 end; 85 120 121 function TSourceExecutor.ReadValueReference(Reference: TSourceReference): TSourceValue; 122 begin 123 Result := nil; 124 if Reference is TSourceReferenceConstant then begin 125 Result := TSourceReferenceConstant(Reference).Constant.Value; 126 end else 127 if Reference is TSourceReferenceVariable then begin 128 Result := Variables.Search(TSourceReferenceVariable(Reference).Variable).Value; 129 end else raise Exception.Create('Unsupported reference'); 130 end; 131 132 function TSourceExecutor.ReadVarReference(Reference: TSourceReference): TSourceVariable; 133 begin 134 Result := nil; 135 if Reference is TSourceReferenceVariable then begin 136 Result := TSourceReferenceVariable(Reference).Variable; 137 end else raise Exception.Create('Unsupported reference'); 138 end; 139 86 140 procedure TSourceExecutor.ExecuteBeginEnd(BeginEnd: TCommandBeginEnd); 87 141 var 88 142 IP: Integer; 89 Instruction: TSourceCommand; 143 begin 144 IP := 0; 145 while IP < BeginEnd.Commands.Count do begin 146 if SkipNext then begin 147 SkipNext := False; 148 Inc(IP); 149 Continue; 150 end; 151 ExecuteCommand(TSourceCommand(BeginEnd.Commands[IP])); 152 Inc(IP); 153 end; 154 end; 155 156 procedure TSourceExecutor.ExecuteBreak(CommandBreak: TCommandBreak); 157 var 158 RepeatBlock: TSourceCommand; 159 ExecutorRepeat: TExecutorRepeat; 160 begin 161 RepeatBlock := CommandBreak.Parent; 162 while not (RepeatBlock is TCommandRepeat) and (RepeatBlock <> nil) do 163 RepeatBlock := RepeatBlock.Parent; 164 if Assigned(RepeatBlock) then begin 165 ExecutorRepeat := RepeatBlocks.Search(RepeatBlock as TCommandRepeat); 166 if Assigned(ExecutorRepeat) then begin 167 ExecutorRepeat.Terminated := True; 168 end else 169 raise Exception.Create('Missing executor repeat block'); 170 end else 171 raise Exception.Create('Used break outside repeat loop'); 172 end; 173 174 procedure TSourceExecutor.ExecuteRepeat(CommandRepeat: TCommandRepeat); 175 var 176 RepeatBlock: TExecutorRepeat; 177 begin 178 RepeatBlock := TExecutorRepeat.Create; 179 RepeatBlock.RepeatCommand := CommandRepeat; 180 RepeatBlock.Terminated := False; 181 RepeatBlocks.Add(RepeatBlock); 182 repeat 183 ExecuteCommand(CommandRepeat.Command); 184 until RepeatBlock.Terminated; 185 RepeatBlocks.Remove(RepeatBlock); 186 end; 187 188 procedure TSourceExecutor.ExecuteCommand(Command: TSourceCommand); 189 var 90 190 Variable: TSourceVariable; 91 191 Value: TSourceValue; … … 93 193 Text: string; 94 194 IntValue: Integer; 95 SkipNext: Boolean; 96 97 function ReadValueReference(Reference: TSourceReference): TSourceValue; 98 begin 99 Result := nil; 100 if Reference is TSourceReferenceConstant then begin 101 Result := TSourceReferenceConstant(Reference).Constant.Value; 102 end else 103 if Reference is TSourceReferenceVariable then begin 104 Result := Variables.Search(TSourceReferenceVariable(Reference).Variable).Value; 105 end else raise Exception.Create('Unsupported reference'); 106 end; 107 108 function ReadVarReference(Reference: TSourceReference): TSourceVariable; 109 begin 110 Result := nil; 111 if Reference is TSourceReferenceVariable then begin 112 Result := TSourceReferenceVariable(Reference).Variable; 113 end else raise Exception.Create('Unsupported reference'); 114 end; 115 116 begin 117 SkipNext := False; 118 IP := 0; 119 while IP < BeginEnd.Instructions.Count do begin 120 if SkipNext then begin 121 SkipNext := False; 122 Inc(IP); 123 Continue; 124 end; 125 Instruction := TSourceCommand(BeginEnd.Instructions[IP]); 126 if Instruction is TCommandFunctionCall then 127 with TCommandFunctionCall(Instruction) do begin 128 if Name = 'print' then begin 129 if Assigned(FOnOutput) then begin 130 Value := ReadValueReference(TSourceReference(Parameters[0])); 131 if Value is TSourceValueString then 132 FOnOutput(TSourceValueString(Value).Value) 133 else if Value is TSourceValueInteger then 134 FOnOutput(IntToStr(TSourceValueInteger(Value).Value)) 135 else raise Exception.Create('Unsupported value type'); 136 end; 195 begin 196 if Command is TCommandFunctionCall then 197 with TCommandFunctionCall(Command) do begin 198 if Name = 'print' then begin 199 if Assigned(FOnOutput) then begin 200 Value := ReadValueReference(TSourceReference(Parameters[0])); 201 if Value is TSourceValueString then 202 FOnOutput(TSourceValueString(Value).Value) 203 else if Value is TSourceValueInteger then 204 FOnOutput(IntToStr(TSourceValueInteger(Value).Value)) 205 else raise Exception.Create('Unsupported value type'); 206 end; 207 end else 208 if Name = 'println' then begin 209 if Assigned(FOnOutput) then begin 210 Value := ReadValueReference(TSourceReference(Parameters[0])); 211 if Value is TSourceValueString then 212 FOnOutput(TSourceValueString(Value).Value + LineEnding) 213 else if Value is TSourceValueInteger then 214 FOnOutput(IntToStr(TSourceValueInteger(Value).Value) + LineEnding) 215 else raise Exception.Create('Unsupported value type'); 216 end; 217 end else 218 if Name = 'inputln' then begin 219 if Assigned(FOnInput) then begin 220 Variable := ReadVarReference(TSourceReference(Parameters[0])); 221 ExecutorVar := Variables.Search(Variable); 222 if ExecutorVar.Value is TSourceValueString then begin 223 TSourceValueString(ExecutorVar.Value).Value := FOnInput; 224 FOnOutput(TSourceValueString(ExecutorVar.Value).Value + LineEnding); 225 end else 226 if ExecutorVar.Value is TSourceValueInteger then begin 227 Text := FOnInput; 228 if TryStrToInt(Text, IntValue) then 229 TSourceValueInteger(ExecutorVar.Value).Value := IntValue 230 else TSourceValueInteger(ExecutorVar.Value).Value := 0; 231 FOnOutput(IntToStr(TSourceValueInteger(ExecutorVar.Value).Value) + LineEnding); 232 end else 233 raise Exception.Create('Unsupported value type'); 234 end; 235 end else 236 if Name = 'assign' then begin 237 Variable := ReadVarReference(TSourceReference(Parameters[0])); 238 Value := ReadValueReference(TSourceReference(Parameters[1])); 239 ExecutorVar := Variables.Search(Variable); 240 if not Assigned(ExecutorVar) then begin 241 ExecutorVar := TExecutorVariable.Create; 242 ExecutorVar.Variable := Variable; 243 Variables.Add(ExecutorVar); 244 ExecutorVar.Value := Variable.ValueType.ValueClass.Create; 245 end; 246 ExecutorVar.Value.Assign(Value); 247 end else 248 if Name = 'increment' then begin 249 Variable := ReadVarReference(TSourceReference(Parameters[0])); 250 Value := ReadValueReference(TSourceReference(Parameters[1])); 251 ExecutorVar := Variables.Search(Variable); 252 if not Assigned(ExecutorVar) then raise Exception.Create('Variable not found'); 253 if (ExecutorVar.Value is TSourceValueInteger) and (Value is TSourceValueInteger) then 254 Inc(TSourceValueInteger(ExecutorVar.Value).Value, TSourceValueInteger(Value).Value) 255 else raise Exception.Create('Wrong type for increment'); 256 end else 257 if Name = 'decrement' then begin 258 Variable := ReadVarReference(TSourceReference(Parameters[0])); 259 Value := ReadValueReference(TSourceReference(Parameters[1])); 260 ExecutorVar := Variables.Search(Variable); 261 if not Assigned(ExecutorVar) then raise Exception.Create('Variable not found'); 262 if (ExecutorVar.Value is TSourceValueInteger) and (Value is TSourceValueInteger) then 263 Dec(TSourceValueInteger(ExecutorVar.Value).Value, TSourceValueInteger(Value).Value) 264 else raise Exception.Create('Wrong type for increment'); 265 end else 266 raise Exception.Create('Unsupported function: ' + TCommandFunctionCall(Command).Name); 267 end else 268 if Command is TCommandBeginEnd then begin 269 ExecuteBeginEnd(TCommandBeginEnd(Command)); 270 end else 271 if Command is TCommandBreak then begin 272 ExecuteBreak(TCommandBreak(Command)); 273 end else 274 if Command is TCommandIfZero then begin 275 ExecutorVar := Variables.Search(TCommandIfZero(Command).Variable.Variable); 276 if Assigned(ExecutorVar) then begin 277 if ExecutorVar.Variable.ValueType.Name = 'Integer' then begin 278 if TSourceValueInteger(ExecutorVar.Value).Value <> 0 then SkipNext := True; 137 279 end else 138 if Name = 'println' then begin 139 if Assigned(FOnOutput) then begin 140 Value := ReadValueReference(TSourceReference(Parameters[0])); 141 if Value is TSourceValueString then 142 FOnOutput(TSourceValueString(Value).Value + LineEnding) 143 else if Value is TSourceValueInteger then 144 FOnOutput(IntToStr(TSourceValueInteger(Value).Value) + LineEnding) 145 else raise Exception.Create('Unsupported value type'); 146 end; 147 end else 148 if Name = 'inputln' then begin 149 if Assigned(FOnInput) then begin 150 Variable := ReadVarReference(TSourceReference(Parameters[0])); 151 ExecutorVar := Variables.Search(Variable); 152 if ExecutorVar.Value is TSourceValueString then begin 153 TSourceValueString(ExecutorVar.Value).Value := FOnInput; 154 FOnOutput(TSourceValueString(ExecutorVar.Value).Value + LineEnding); 155 end else 156 if ExecutorVar.Value is TSourceValueInteger then begin 157 Text := FOnInput; 158 if TryStrToInt(Text, IntValue) then 159 TSourceValueInteger(ExecutorVar.Value).Value := IntValue 160 else TSourceValueInteger(ExecutorVar.Value).Value := 0; 161 FOnOutput(IntToStr(TSourceValueInteger(ExecutorVar.Value).Value) + LineEnding); 162 end else 163 raise Exception.Create('Unsupported value type'); 164 end; 165 end else 166 if Name = 'assign' then begin 167 Variable := ReadVarReference(TSourceReference(Parameters[0])); 168 Value := ReadValueReference(TSourceReference(Parameters[1])); 169 ExecutorVar := Variables.Search(Variable); 170 if not Assigned(ExecutorVar) then begin 171 ExecutorVar := TExecutorVariable.Create; 172 ExecutorVar.Variable := Variable; 173 Variables.Add(ExecutorVar); 174 ExecutorVar.Value := Variable.ValueType.ValueClass.Create; 175 end; 176 ExecutorVar.Value.Assign(Value); 177 end else 178 if Name = 'increment' then begin 179 Variable := ReadVarReference(TSourceReference(Parameters[0])); 180 Value := ReadValueReference(TSourceReference(Parameters[1])); 181 ExecutorVar := Variables.Search(Variable); 182 if not Assigned(ExecutorVar) then raise Exception.Create('Variable not found'); 183 if (ExecutorVar.Value is TSourceValueInteger) and (Value is TSourceValueInteger) then 184 Inc(TSourceValueInteger(ExecutorVar.Value).Value, TSourceValueInteger(Value).Value) 185 else raise Exception.Create('Wrong type for increment'); 186 end else 187 raise Exception.Create('Unsupported function: ' + TCommandFunctionCall(Instruction).Name); 188 end else 189 if Instruction is TCommandBeginEnd then begin 190 ExecuteBeginEnd(TCommandBeginEnd(Instruction)); 191 end else 192 if Instruction is TCommandIfZero then begin 193 ExecutorVar := Variables.Search(TCommandIfZero(Instruction).Variable); 194 if Assigned(ExecutorVar) then begin 195 if ExecutorVar.Variable.ValueType.Name = 'Integer' then begin 196 if TSourceValueInteger(ExecutorVar.Value).Value = 0 then SkipNext := True; 197 end else 198 raise Exception.Create('Can compare only integers'); 199 end else 200 raise Exception.Create('Variable not found'); 201 end else 202 raise Exception.Create('Unsupported instruction'); 203 Inc(IP); 204 end; 280 raise Exception.Create('Can compare only integers'); 281 end else 282 raise Exception.Create('Variable not found'); 283 end else 284 if Command is TCommandRepeat then begin 285 ExecuteRepeat(Command as TCommandRepeat); 286 end else 287 raise Exception.Create('Unsupported instruction'); 205 288 end; 206 289
Note:
See TracChangeset
for help on using the changeset viewer.