Changeset 101
- Timestamp:
- Feb 11, 2017, 4:35:08 PM (8 years ago)
- Location:
- branches/interpreter
- Files:
-
- 4 edited
Legend:
- Unmodified
- Added
- Removed
-
branches/interpreter/Execute3.pas
r100 r101 8 8 type 9 9 TVariableValue = record 10 VarRef: PVariable; 10 11 BaseType: TBaseType; 11 12 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); 16 17 end; 17 18 PVariableValue = ^TVariableValue; 19 20 { TVariableValues } 18 21 19 22 TVariableValues = record 20 23 Items: array of TVariableValue; 24 function GetByName(Name: string): PVariableValue; 21 25 end; 22 26 … … 40 44 var 41 45 ExecutionContexts: TExecutionContexts; 46 ExecutionContextCurrent: PExecutionContext; 47 MainCode: PProgramCode; 42 48 43 49 procedure ExecuteProgram(ProgramCode: PProgramCode); … … 47 53 48 54 procedure ExecuteCommand(Command: PCommand); forward; 55 procedure ExecuteGetValue(GetValue: PGetValue; Value: PVariableValue); forward; 56 procedure AssignVariable(Dest, Source: PVariableValue); forward; 57 procedure ExecuteExecution(Execution: PExecution; ReturnValue: PVariableValue); forward; 58 59 60 procedure ShowError(Text: string); 61 begin 62 WriteLn(Text); 63 Halt; 64 end; 49 65 50 66 procedure ExecuteBeginEnd(BeginEnd: PBeginEnd); … … 56 72 end; 57 73 58 function ExecuteExpressionBoolean(Expression: PExpression): Boolean; 59 begin 60 74 procedure ShowErrorType(Variable: PVariableValue); 75 begin 76 ShowError('Not suppoted type') 77 end; 78 79 procedure VariableAdd(Result, Operand: PVariableValue); 80 begin 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; 87 end; 88 89 procedure VariableSubtract(Result, Operand: PVariableValue); 90 begin 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; 97 end; 98 99 procedure VariableAnd(Result, Operand: PVariableValue); 100 begin 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; 107 end; 108 109 procedure VariableOr(Result, Operand: PVariableValue); 110 begin 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; 117 end; 118 119 procedure VariableEqual(Result, Operand1, Operand2: PVariableValue); 120 begin 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; 127 end; 128 129 procedure VariableNotEqual(Result, Operand1, Operand2: PVariableValue); 130 begin 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; 137 end; 138 139 procedure ExecuteExpression(Expression: PExpression; Value: PVariableValue); 140 var 141 I: Integer; 142 SubValue: TVariableValue; 143 begin 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'); 182 end; 183 184 function ExecuteGetValueBoolean(GetValue: PGetValue): Boolean; 185 var 186 Value: TVariableValue; 187 begin 188 ExecuteGetValue(GetValue, @Value); 189 Result := (Value.BaseType = btBoolean) and Value.ValueBoolean; 61 190 end; 62 191 63 192 procedure ExecuteWhileDo(WhileDo: PWhileDo); 64 193 begin 65 while Execute ExpressionBoolean(@WhileDo^.Condition) do194 while ExecuteGetValueBoolean(@WhileDo^.Condition) do 66 195 ExecuteCommand(@WhileDo^.Command); 67 196 end; 68 197 69 198 procedure 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 199 var 200 Condition: Boolean; 201 begin 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); 207 end; 208 209 procedure AssignConstant(Variable: PVariableValue; Constant: PConstant); 210 begin 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; 218 end; 219 220 procedure ExecuteGetValue(GetValue: PGetValue; Value: PVariableValue); 221 begin 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; 229 end; 230 231 procedure AssignVariable(Dest, Source: PVariableValue); 232 begin 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; 240 end; 241 242 function IsBuildInFunction(Name: string): Boolean; 243 begin 244 Result := (Name = 'WriteLn') or (Name = 'Eof') or (Name = 'Halt') or (Name = 'Read') or 245 (Name = 'Length') or (Name = 'SetLength'); 246 end; 247 248 procedure ExecuteBuildInSetResult(Execution: PExecution; TypeName: string); 249 var 250 DataType: PType; 251 begin 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; 259 end; 260 261 procedure ExecuteBuildIn(Execution: PExecution); 262 begin 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.'); 273 end; 274 275 procedure ExecuteExecution(Execution: PExecution; ReturnValue: PVariableValue); 276 var 277 I: Integer; 278 Param: PGetValue; 279 ParamValue: TVariableValue; 280 DestVar: PVariableValue; 281 NewContext: TExecutionContext; 282 begin 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 80 296 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')); 92 304 ExecutionContexts.RemoveLast; 93 305 end; … … 96 308 var 97 309 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; 311 begin 312 DestVariable := ExecutionContextCurrent^.VariableValues.GetByName(Assignment^.Destination^.Name); 313 FillChar(SrcVariable, SizeOf(TVariableValue), 0); 314 ExecuteGetValue(@Assignment^.Source, @SrcVariable); 315 AssignVariable(DestVariable, @SrcVariable); 106 316 end; 107 317 … … 112 322 ctWhileDo: ExecuteWhileDo(Command^.WhileDo); 113 323 ctIfThenElse: ExecuteIfThenElse(Command^.IfThenElse); 114 ctExecution: ExecuteExecution(Command^.Execution );324 ctExecution: ExecuteExecution(Command^.Execution, nil); 115 325 ctAssignment: ExecuteAssignment(Command^.Assignment); 116 326 end; … … 119 329 procedure ExecuteProgram(ProgramCode: PProgramCode); 120 330 begin 121 SetLength(ExecutionContexts.Items, 1); 122 ExecutionContexts.Last^.LoadFromVariables(@ProgramCode^.Variables); 331 MainCode := ProgramCode; 332 ExecutionContexts.Add; 333 ExecutionContextCurrent^.LoadFromVariables(@ProgramCode^.Variables); 123 334 ExecuteBeginEnd(@ProgramCode^.BeginEnd); 335 end; 336 337 { TVariableValues } 338 339 function TVariableValues.GetByName(Name: string): PVariableValue; 340 var 341 I: Integer; 342 begin 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; 124 347 end; 125 348 … … 133 356 for I := 0 to Length(Variables.Items) - 1 do begin 134 357 VariableValues.Items[I].BaseType := Variables.Items[I].DataType.BaseType; 358 VariableValues.Items[I].VarRef := @Variables.Items[I]; 135 359 end; 136 360 end; … … 146 370 begin 147 371 SetLength(Items, Length(Items) + 1); 372 ExecutionContextCurrent := Last; 148 373 end; 149 374 … … 151 376 begin 152 377 SetLength(Items, Length(Items) - 1); 378 ExecutionContextCurrent := Last; 153 379 end; 154 380 -
branches/interpreter/Parser3.pas
r100 r101 90 90 N := N * 10; 91 91 I := I - 1; 92 end; 93 end; 94 95 function IntToStr(Value: Integer): string; 96 begin 97 Result := ''; 98 while Value > 0 do begin 99 Result := Chr(Ord('0') + Value mod 10) + Result; 100 Value := Value div 10; 92 101 end; 93 102 end; … … 292 301 if CheckNext('(') then begin 293 302 Expect('('); 303 SetLength(SubExpression.Items, 0); 294 304 if ParseExpression(@SubExpression) then begin 295 305 SetLength(Expression^.Items, Length(Expression^.Items) + 1); … … 316 326 // Build expression tree using operator precedence 317 327 for II := 0 to Length(OperatorPrecedence) - 1 do begin 318 I := 1;328 I := 0; 319 329 while (I < Length(Expression^.Items) - 1) do begin 320 330 if (TExpression(Expression^.Items[I]).NodeType = ntOperator) and … … 338 348 end; 339 349 end; 350 351 if Length(Expression^.Items) = 1 then begin 352 Expression^.NodeType := Expression^.Items[0].NodeType; 353 Expression^.OperatorType := Expression^.Items[0].OperatorType; 354 Expression^.Value := Expression^.Items[0].Value; 355 // Move subtitem one node up 356 SetLength(Expression^.Items, Length(Expression^.Items[0].Items)); 357 I := Length(Expression^.Items) - 1; 358 while I >= 0 do begin 359 Expression^.Items[I] := Expression^.Items[0].Items[I]; 360 I := I - 1; 361 end; 362 end else ShowError('Expression error ' + IntToStr(Length(Expression^.Items))); 340 363 end; 341 364 end; … … 362 385 Value: TConstant; 363 386 begin 387 FillChar(Expression, SizeOf(TExpression), 0); 388 FillChar(FunctionCall, SizeOf(TFunctionCall), 0); 389 FillChar(Value, SizeOf(TConstant), 0); 390 364 391 Result := True; 365 392 if not NoExpression and ParseExpression(@Expression) then begin … … 443 470 Assignment: TAssignment; 444 471 begin 472 FillChar(IfThenElse, SizeOf(TIfThenElse), 0); 473 FillChar(WhileDo, SizeOf(TWhileDo), 0); 474 FillChar(BeginEnd, SizeOf(TBeginEnd), 0); 475 FillChar(Execution, SizeOf(TExecution), 0); 476 FillChar(Assignment, SizeOf(TAssignment), 0); 477 445 478 Result := True; 446 479 if ParseBeginEnd(@BeginEnd) then begin … … 632 665 begin 633 666 SetLength(ProgramCode^.Types.Items, 0); 634 ProgramCode^.Types.Add(TypeCreate('string', bt Integer));667 ProgramCode^.Types.Add(TypeCreate('string', btShortString)); 635 668 TypeString := ProgramCode^.Types.GetLast; 636 669 ProgramCode^.Types.Add(TypeCreate('Boolean', btBoolean)); … … 650 683 FuncWriteLn := ProgramCode^.Functions.GetLast; 651 684 FuncWriteLn^.Parameters.Add(FunctionParameterCreate('Text', TypeString)); 685 FuncWriteLn^.Variables.Add(VariableCreate('Text', TypeString)); 652 686 ProgramCode^.Functions.Add(FunctionCreate('Read', nil)); 653 687 FuncRead := ProgramCode^.Functions.GetLast; … … 657 691 FuncLength := ProgramCode^.Functions.GetLast; 658 692 FuncLength^.Parameters.Add(FunctionParameterCreate('Array', TypeArray)); 693 FuncLength^.Variables.Add(VariableCreate('Array', TypeArray)); 659 694 ProgramCode^.Functions.Add(FunctionCreate('SetLength', nil)); 660 695 FuncSetLength := ProgramCode^.Functions.GetLast; 661 696 FuncSetLength^.Parameters.Add(FunctionParameterCreate('Array', TypeArray)); 697 FuncSetLength^.Variables.Add(VariableCreate('Array', TypeArray)); 662 698 FuncSetLength^.Parameters.Add(FunctionParameterCreate('Count', TypeInteger)); 699 FuncSetLength^.Variables.Add(VariableCreate('Count', TypeInteger)); 663 700 end; 664 701 -
branches/interpreter/Source3.pas
r100 r101 17 17 TOperator = (opNone, opAdd, opSubtract, opAnd, opOr, opNot, opEqual, opNotEqual); 18 18 19 TBaseType = (bt Boolean, btInteger, btChar, btShortString, btArray);19 TBaseType = (btNone, btBoolean, btInteger, btChar, btShortString, btArray); 20 20 21 21 TType = record … … 84 84 TFunctionCall = procedure ; 85 85 86 TCmdType = (ct WhileDo, ctIfThenElse, ctBeginEnd, ctAssignment, ctExecution);86 TCmdType = (ctNone, ctWhileDo, ctIfThenElse, ctBeginEnd, ctAssignment, ctExecution); 87 87 TCommand = record 88 88 CmdType: TCmdType; -
branches/interpreter/project3.lpi
r100 r101 101 101 <StackChecks Value="True"/> 102 102 </Checks> 103 <VerifyObjMethodCallValidity Value="True"/>104 103 </CodeGeneration> 105 104 </CompilerOptions>
Note:
See TracChangeset
for help on using the changeset viewer.