Предыдущая серия была тут - http://18delphi.blogspot.com/2013/11/gui-2.html
Теперь хочется рассказать про устройство TscriptContext.
В целом это конечно - "стек значений".
Но не только... Но об этом - позже.
Пока - про стек..
Стек значений - это ОДИН из краеугольных камней устройства нашей тестовой машины.
Теорию можно почитать тут - http://ru.wikipedia.org/wiki/Forth
И кстати ещё одна забавная ссылка - http://ru.wikipedia.org/wiki/%D0%9A%D0%BE%D0%BD%D0%BA%D0%B0%D1%82%D0%B5%D0%BD%D0%B0%D1%82%D0%B8%D0%B2%D0%BD%D1%8B%D0%B9_%D1%8F%D0%B7%D1%8B%D0%BA_%D0%BF%D1%80%D0%BE%D0%B3%D1%80%D0%B0%D0%BC%D0%BC%D0%B8%D1%80%D0%BE%D0%B2%D0%B0%D0%BD%D0%B8%D1%8F
А пока - займёмся практикой.
Как выглядит стек значений внутри.
Примерно вот так:
Замечу лишь, что ещё есть наследник от TscriptContext - TscriptCompileContext:
Он используется в процессе компиляции кода и служит для обеспечения возможности управления процессом разбора кода (парсинга) и собственно построения компилируемого кода.
О нём подробнее я напишу в следующих сериях.
Теперь хочется рассказать про устройство TscriptContext.
В целом это конечно - "стек значений".
Но не только... Но об этом - позже.
Пока - про стек..
Стек значений - это ОДИН из краеугольных камней устройства нашей тестовой машины.
Теорию можно почитать тут - http://ru.wikipedia.org/wiki/Forth
И кстати ещё одна забавная ссылка - http://ru.wikipedia.org/wiki/%D0%9A%D0%BE%D0%BD%D0%BA%D0%B0%D1%82%D0%B5%D0%BD%D0%B0%D1%82%D0%B8%D0%B2%D0%BD%D1%8B%D0%B9_%D1%8F%D0%B7%D1%8B%D0%BA_%D0%BF%D1%80%D0%BE%D0%B3%D1%80%D0%B0%D0%BC%D0%BC%D0%B8%D1%80%D0%BE%D0%B2%D0%B0%D0%BD%D0%B8%D1%8F
А пока - займёмся практикой.
Как выглядит стек значений внутри.
Примерно вот так:
interface
type
TscriptValueType = (script_vtVoid, script_vtInteger, script_vtBoolean, script_vtString, script_vtObject);
TscriptValue = {$IfDef XE}record{$Else}object{$EndIf}
private
rType : TscriptValueType;
rInteger : Integer;
rBoolean : Boolean;
rString : String;
rObject : TObject;
public
function AsInteger: Integer;
function AsBoolean: Boolean;
function AsString: String;
function AsObject: TObject;
function EQ(anOther: TscriptValue): Boolean;
end;//TscriptValue
function TscriptValue_C(aValue: Integer): TscriptValue; overload;
function TscriptValue_C(aValue: Boolean): TscriptValue; overload;
function TscriptValue_C(aValue: String): TscriptValue; overload;
function TscriptValue_C(aValue: TObject): TscriptValue; overload;
// - преобразовать это в "вариантную запись" - оставляю самым пытливым читателям
_ItemType_ = TscriptValue;
_List_Parent_ = TRefcounted;
{$Include _List_.imp.pas}
TscriptContext = class(_List_)
public
function PopInteger: Integer;
function PopBoolean: Boolean;
function PopString: String;
function PopObject: TObject;
procedure PushInteger(aValue: Integer);
procedure PushBoolean(aValue: Boolean);
procedure PushString(aValue: String);
procedure PushObject(aValue: TObject);
end;//TscriptContext
implementation
function IsSame(const A: _ItemType_;
const B: _ItemType_): Boolean;
begin
Result := A.EQ(B);
end;//IsSame
procedure FreeItem(var thePlace: _ItemType_);
begin
Finalize(thePlace);
end;//FreeItem
procedure FillItem(var thePlace: _ItemType_;
const aFrom: _ItemType_);
begin
thePlace := aFrom;
end;//FillItem
{$Include _List_.imp.pas}
function TscriptValue.AsInteger: Integer;
begin
Assert(rType = script_vtInteger);
Result := rInteger;
end;
function TscriptValue.AsBoolean: Boolean;
begin
Assert(rType = script_vtBoolean);
Result := rBoolean;
end;
function TscriptValue.AsString: String;
begin
Assert(rType = script_vtString);
Result := rInteger;
end;
function TscriptValue.AsObject: TObject;
begin
Assert(rType = script_vtObject);
Result := rObject;
end;
function TscriptValue.EQ(anOther: TscriptValue): Boolean;
begin
Result := (rType = anOther.rType);
if Result then
begin
Case rType of
script_vtInteger:
Result := Self.AsInteger = anOther.AsInteger;
script_vtBoolean:
Result := Self.AsBoolean = anOther.AsBoolean;
script_vtString:
Result := Self.AsString = anOther.AsString;
script_vtObject:
Result := Self.AsObject = anOther.AsObject;
else
begin
Assert(false);
Result := false;
end;//else
end;//Case rType
end;//Result
end;
function TscriptValue_C(aValue: Integer): TscriptValue;
begin
Result.rType := script_vtInteger;
Result.rInteger := aValue;
end;
function TscriptValue_C(aValue: Boolean): TscriptValue;
begin
Result.rType := script_vtBoolean;
Result.rBoolean := aValue;
end;
function TscriptValue_C(aValue: String): TscriptValue;
begin
Result.rType := script_vtString;
Result.rString := aValue;
end;
function TscriptValue_C(aValue: TObject): TscriptValue;
begin
Result.rType := script_vtObject;
Result.rObject := aValue;
end;
function TscriptContext.PopInteger: Integer;
begin
Result := Self.Last.AsInteger;
Delete(Pred(Count));
end;
function TscriptContext.PopBoolean: Boolean;
begin
Result := Self.Last.AsBoolean;
Delete(Pred(Count));
end;
function TscriptContext.PopString: String;
begin
Result := Self.Last.AsInteger;
Delete(Pred(Count));
end;
function TscriptContext.PopObject: TObject;
begin
Result := Self.Last.AsObject;
Delete(Pred(Count));
end;
procedure TscriptContext.PushInteger(aValue: Integer);
begin
Self.Add(TscriptValue_C(aValue));
end;
procedure TscriptContext.PushBoolean(aValue: Boolean);
begin
Self.Add(TscriptValue_C(aValue));
end;
procedure TscriptContext.PushString(aValue: String);
begin
Self.Add(TscriptValue_C(aValue));
end;
procedure TscriptContext.PushObject(aValue: TObject);
begin
Self.Add(TscriptValue_C(aValue));
end;
Вот как-то так пока...Замечу лишь, что ещё есть наследник от TscriptContext - TscriptCompileContext:
TscriptCompileContext = class(TscriptContext)
property Parser: IscriptParser;
{* - Текущий парсер. }
property Code: TscriptCode;
{* - Текущий компилируемый код. }
end;//TscriptCompileContext
Он используется в процессе компиляции кода и служит для обеспечения возможности управления процессом разбора кода (парсинга) и собственно построения компилируемого кода.
О нём подробнее я напишу в следующих сериях.
Комментариев нет:
Отправить комментарий