To kolejne podejście do stworzenia interpretera języka Atari Action!
Tym razem inicjuję obiekt zawierający wartość całkowitą i automatycznie, w zależności od zakresu tej wartości ustawiam typ całkowity.
Wartość jest podawana za pomocą ShortString, gdyż intepreter będzie interpretował tekst, czyli String i dokona ekstrakcji wartości całkowitej z tego tekstu.
Natomiast potem, po odczytaniu tekstu będzie mi potrzebna liczba całkowita np. do ustawienia zakresu pętli.
Napisałem kod przy pomocy którego ta zamiana następuje wraz z ustawieniem typu całkowitego Action! i dzieje się w nim coś ciekawego.
Główny program wygląda tak:
var
intVar1: TACTION_INT;
begin
try
intVar1 := TACTION_INT.Create;
intVar1.SetV('-1225'); // zapis - wartość w postaci String
WriteLn(intVar1.Value.value_); // odczyt - wartość w postaci Integer
WriteLn;
Write('Press key Enter');
ReadLn;
except
on E: Exception do
Writeln(E.ClassName, ': ', E.Message);
end;
end.
Natomiast program po jawnym wywołaniu SetV(ShrotString) niejawnie wywołuje SetV(TACTION_INT_RECORD).
Moje przeświadczenie o tym bierze się z tego, że program pozbawiony fragmentu SetV(TACTION_INT_RECORD) się nie kompiluje.
Czy coś tu się nie dzieje 2 razy i czy nie będzie miało wpływu na wydajność?
Nadmienię, że inicjowanie za pomocą rekordu jest przewidywane na dalszym etapie, ale według mnie już tutaj działa.
//Delphi 10.2 Community Edition
program Project1;
{$APPTYPE CONSOLE}
{$R *.res}
uses
System.SysUtils,
System.Classes;
type
TACTION_INT_TYPE =
(
BYTE,
INT,
CARD,
OTHER
);
TACTION_INT_RECORD = record
type_: TACTION_INT_TYPE;
value_: Integer;
end;
TACTION_INT = class
private
FValue: TACTION_INT_RECORD;
FInt: Integer;
function IsInt(AStr: ShortString; out AInt: Integer): Boolean;
procedure SetTypeAndValue(AStr: ShortString; out AInt: Integer);
function GetV: TACTION_INT_RECORD;
procedure SetV(AStr: ShortString); overload; {1-jawne}
procedure SetV(ARec: TACTION_INT_RECORD); overload; {2-niejawne}
public
property Value: TACTION_INT_RECORD read GetV write SetV;
end;
function TACTION_INT.IsInt(AStr: ShortString; out AInt: Integer): Boolean;
begin
Result := Integer.TryParse(AStr, AInt);
end;
procedure TACTION_INT.SetTypeAndValue(AStr: ShortString; out AInt: Integer);
begin
if IsInt(AStr, AInt) then
begin
if (AInt >= 0) and (AInt <= 255) then
FValue.type_ := BYTE
else
if (AInt >= -32768) and (AInt <= 32767) then
FValue.type_ := INT
else
if (AInt >= 0) and (AInt <= 65535) then
FValue.type_ := CARD
else
FValue.type_ := OTHER;
end
else
FValue.type_ := OTHER;
if FValue.type_ <> OTHER then
FValue.value_ := AInt
else
FValue.value_ := 0;
end;
function TACTION_INT.GetV: TACTION_INT_RECORD;
begin
Result := FValue;
end;
procedure TACTION_INT.SetV(AStr: ShortString);
var
AInt: Integer;
begin
SetTypeAndValue(AStr, AInt);
end;
procedure TACTION_INT.SetV(ARec: TACTION_INT_RECORD);
var
AStr: ShortString;
AInt: Integer;
begin
AInt := ARec.value_;
AStr := IntToStr(AInt);
SetTypeAndValue(AStr, AInt);
end;
var
intVar1: TACTION_INT;
begin
try
intVar1 := TACTION_INT.Create;
intVar1.SetV('-1225');
WriteLn(intVar1.Value.value_);
WriteLn;
Write('Press key Enter');
ReadLn;
except
on E: Exception do
Writeln(E.ClassName, ': ', E.Message);
end;
end.