diff --git a/Src/AST/Myc.Ast.Binding.pas b/Src/AST/Myc.Ast.Binding.pas index 3a1bac6..6ea999b 100644 --- a/Src/AST/Myc.Ast.Binding.pas +++ b/Src/AST/Myc.Ast.Binding.pas @@ -39,8 +39,8 @@ type procedure EnterScope; procedure ExitScope; - function GetCurrentDescriptor: IScopeDescriptor; function IsValidIdentifier(const Name: string): Boolean; + protected // Stack management for tail-call state is centralized here. function Accept(const Node: IAstNode): TDataValue; override; @@ -65,8 +65,6 @@ type function TransformTernaryExpression(const Node: ITernaryExpressionNode): ITernaryExpressionNode; override; function TransformBinaryExpression(const Node: IBinaryExpressionNode): IBinaryExpressionNode; override; function TransformUnaryExpression(const Node: IUnaryExpressionNode): IUnaryExpressionNode; override; - - property CurrentDescriptor: IScopeDescriptor read GetCurrentDescriptor; end; TBoundIdentifierNode = class(TIdentifierNode) @@ -251,11 +249,6 @@ begin FCurrentDescriptor := FCurrentDescriptor.Parent; end; -function TAstBinder.GetCurrentDescriptor: IScopeDescriptor; -begin - Result := FCurrentDescriptor; -end; - function TAstBinder.IsValidIdentifier(const Name: string): Boolean; var c: Char; diff --git a/Src/AST/Myc.Ast.Evaluator.pas b/Src/AST/Myc.Ast.Evaluator.pas index c0958c7..072b69d 100644 --- a/Src/AST/Myc.Ast.Evaluator.pas +++ b/Src/AST/Myc.Ast.Evaluator.pas @@ -25,14 +25,14 @@ type TEvaluatorVisitor = class(TAstVisitor, IEvaluatorVisitor) private FScope: IExecutionScope; + procedure HandleTCO(var ResultValue: TDataValue); + protected function IsTruthy(const AValue: TDataValue): Boolean; inline; // Returns a closure that can create the correct type of visitor for a lambda's body. function CreateVisitorFactory: TVisitorFactory; virtual; - procedure HandleTCO(var ResultValue: TDataValue); - property Scope: IExecutionScope read FScope; public constructor Create(const AScope: IExecutionScope); diff --git a/Src/Data/Myc.Data.Value.pas b/Src/Data/Myc.Data.Value.pas index 810bf11..6e7e14e 100644 --- a/Src/Data/Myc.Data.Value.pas +++ b/Src/Data/Myc.Data.Value.pas @@ -9,7 +9,8 @@ uses Myc.Data.Series; type - TDataValueKind = (vkVoid, vkScalar, vkText, vkSeries, vkRecordSeries, vkRecord, vkManagedObject, vkMethod, vkInterface, vkGeneric); + TDataValueKind = + (vkVoid, vkScalar, vkText, vkSeries, vkRecordSeries, vkRecord, vkManagedObject, vkMethod, vkInterface, vkPointer, vkGeneric); TDataValue = record type @@ -64,6 +65,9 @@ type class function FromGeneric(const [ref] AValue: T): TDataValue; static; inline; function AsGeneric: T; inline; + class function FromPtr(const AValue: Pointer): TDataValue; static; inline; + function AsPtr: Pointer; inline; + class function Defer(const Value: TDataValue; const Calc: TFunc): TDataValue; overload; static; class function Map(const SourceSeries: ISeries; const MapperFunc: TFunc): ISeries; static; @@ -243,6 +247,15 @@ begin Result := (FInterface as TObjVal).Value; end; +function TDataValue.AsPtr: Pointer; +begin + if FKind = Ord(vkLazy) then + exit(AsLazy.Value.AsPtr); + if (FKind <> Ord(vkPointer)) then + raise EInvalidCast.Create('Cannot read value as pointer.'); + Result := Pointer(FScalar.Value.AsInt64); +end; + function TDataValue.AsRecord: TScalarRecord; begin if FKind = Ord(vkLazy) then @@ -320,6 +333,13 @@ begin Result.FInterface := TVal.Create(AValue); end; +class function TDataValue.FromPtr(const AValue: Pointer): TDataValue; +begin + Assert(sizeof(Pointer) <= sizeof(Int64)); + Result.FKind := Ord(vkPointer); + Result.FScalar.FromInt64(Int64(AValue)); +end; + class function TDataValue.FromSeries(const AValue: ISeries): TDataValue; begin Result.FKind := Ord(vkSeries);