ASt Types
This commit is contained in:
+356
-189
@@ -8,6 +8,8 @@ uses
|
|||||||
Myc.Data.Scalar;
|
Myc.Data.Scalar;
|
||||||
|
|
||||||
type
|
type
|
||||||
|
IStaticType = interface;
|
||||||
|
|
||||||
// Defines the categories of types available in the language.
|
// Defines the categories of types available in the language.
|
||||||
TStaticTypeKind = (
|
TStaticTypeKind = (
|
||||||
stUnknown, // Used during inference before a type is known
|
stUnknown, // Used during inference before a type is known
|
||||||
@@ -26,64 +28,85 @@ type
|
|||||||
function ToString: string;
|
function ToString: string;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
// Defines the signature of a method
|
||||||
|
IMethodSignature = interface
|
||||||
|
{$region 'private'}
|
||||||
|
function GetParamTypes: TArray<IStaticType>;
|
||||||
|
function GetReturnType: IStaticType;
|
||||||
|
{$endregion}
|
||||||
|
property ParamTypes: TArray<IStaticType> read GetParamTypes;
|
||||||
|
property ReturnType: IStaticType read GetReturnType;
|
||||||
|
end;
|
||||||
|
|
||||||
// Represents a complete static type definition.
|
// Represents a complete static type definition.
|
||||||
// This is a managed record, passed by value, cheap to copy.
|
IStaticType = interface
|
||||||
TStaticType = record
|
{$region 'private'}
|
||||||
public
|
function GetKind: TStaticTypeKind;
|
||||||
type
|
function GetElementType: IStaticType;
|
||||||
// Forward declaration for mutual recursion
|
function GetSignature: IMethodSignature;
|
||||||
PStaticType = ^TStaticType;
|
function GetDefinition: TScalarRecordDefinition;
|
||||||
|
{$endregion}
|
||||||
|
|
||||||
// Defines the signature of a method
|
// The kind of type (e.g., Ordinal, Series, etc.)
|
||||||
IMethodSignature = interface
|
property Kind: TStaticTypeKind read GetKind;
|
||||||
{$region 'private'}
|
// The element type (if Kind = stSeries)
|
||||||
function GetParamTypes: TArray<TStaticType>;
|
property ElementType: IStaticType read GetElementType;
|
||||||
function GetReturnType: TStaticType;
|
// The signature (if Kind = stMethod)
|
||||||
{$endregion}
|
property Signature: IMethodSignature read GetSignature;
|
||||||
property ParamTypes: TArray<TStaticType> read GetParamTypes;
|
// The definition (if Kind = stRecord or stRecordSeries)
|
||||||
property ReturnType: TStaticType read GetReturnType;
|
property Definition: TScalarRecordDefinition read GetDefinition;
|
||||||
end;
|
|
||||||
|
|
||||||
public
|
|
||||||
Kind: TStaticTypeKind;
|
|
||||||
// Used if Kind = stMethod
|
|
||||||
Signature: IMethodSignature;
|
|
||||||
// Used if Kind = stSeries
|
|
||||||
ElementType: PStaticType;
|
|
||||||
// Used if Kind = stRecord or stRecordSeries
|
|
||||||
Definition: TScalarRecordDefinition;
|
|
||||||
|
|
||||||
class operator Initialize(out Dest: TStaticType);
|
|
||||||
class operator Finalize(var Dest: TStaticType);
|
|
||||||
|
|
||||||
// Factory functions
|
|
||||||
class function Create(AKind: TStaticTypeKind): TStaticType; static;
|
|
||||||
class function CreateSeries(const AElementType: TStaticType): TStaticType; static;
|
|
||||||
class function CreateMethod(const AParamTypes: TArray<TStaticType>; const AReturnType: TStaticType): TStaticType; static;
|
|
||||||
class function CreateRecord(const ADef: TScalarRecordDefinition): TStaticType; static;
|
|
||||||
class function CreateRecordSeries(const ADef: TScalarRecordDefinition): TStaticType; static;
|
|
||||||
|
|
||||||
class function FromScalarKind(AKind: TScalar.TKind): TStaticType; static;
|
|
||||||
|
|
||||||
|
// Checks for type equality
|
||||||
|
function IsEqual(const Other: IStaticType): Boolean;
|
||||||
function ToString: string;
|
function ToString: string;
|
||||||
class operator Equal(const A, B: TStaticType): Boolean;
|
|
||||||
class operator NotEqual(A, B: TStaticType): Boolean; inline;
|
|
||||||
end;
|
end;
|
||||||
|
|
||||||
ETypeException = class(Exception);
|
ETypeException = class(Exception);
|
||||||
|
|
||||||
|
// Factory and Flyweight access for static types.
|
||||||
|
// Use this record to create or access all IStaticType instances.
|
||||||
|
TTypes = record
|
||||||
|
private
|
||||||
|
class var
|
||||||
|
FUnknown: IStaticType;
|
||||||
|
class var
|
||||||
|
FVoid: IStaticType;
|
||||||
|
class var
|
||||||
|
FOrdinal: IStaticType;
|
||||||
|
class var
|
||||||
|
FFloat: IStaticType;
|
||||||
|
class var
|
||||||
|
FText: IStaticType;
|
||||||
|
class constructor Create;
|
||||||
|
public
|
||||||
|
// Flyweight accessors for simple types
|
||||||
|
class property Unknown: IStaticType read FUnknown;
|
||||||
|
class property Void: IStaticType read FVoid;
|
||||||
|
class property Ordinal: IStaticType read FOrdinal;
|
||||||
|
class property Float: IStaticType read FFloat;
|
||||||
|
class property Text: IStaticType read FText;
|
||||||
|
|
||||||
|
// Factory functions for complex types
|
||||||
|
class function CreateSeries(const AElementType: IStaticType): IStaticType; static;
|
||||||
|
class function CreateMethod(const AParamTypes: TArray<IStaticType>; const AReturnType: IStaticType): IStaticType; static;
|
||||||
|
class function CreateRecord(const ADef: TScalarRecordDefinition): IStaticType; static;
|
||||||
|
class function CreateRecordSeries(const ADef: TScalarRecordDefinition): IStaticType; static;
|
||||||
|
|
||||||
|
class function FromScalarKind(AKind: TScalar.TKind): IStaticType; static;
|
||||||
|
end;
|
||||||
|
|
||||||
// Defines the rules of the type system.
|
// Defines the rules of the type system.
|
||||||
TTypeRules = record
|
TTypeRules = record
|
||||||
private
|
private
|
||||||
class function Promote(const A, B: TStaticType): TStaticType; static;
|
class function Promote(const A, B: IStaticType): IStaticType; static;
|
||||||
public
|
public
|
||||||
// Checks if a value of type 'Source' can be assigned to 'Target'.
|
// Checks if a value of type 'Source' can be assigned to 'Target'.
|
||||||
class function CanAssign(const Target, Source: TStaticType): Boolean; static;
|
class function CanAssign(const Target, Source: IStaticType): Boolean; static;
|
||||||
// Determines the result type of a binary operation.
|
// Determines the result type of a binary operation.
|
||||||
// Raises ETypeException on failure.
|
// Raises ETypeException on failure.
|
||||||
class function ResolveBinaryOp(Op: TScalar.TBinaryOp; const Left, Right: TStaticType): TStaticType; static;
|
class function ResolveBinaryOp(Op: TScalar.TBinaryOp; const Left, Right: IStaticType): IStaticType; static;
|
||||||
// Determines the result type of a unary operation.
|
// Determines the result type of a unary operation.
|
||||||
class function ResolveUnaryOp(Op: TScalar.TUnaryOp; const Right: TStaticType): TStaticType; static;
|
class function ResolveUnaryOp(Op: TScalar.TUnaryOp; const Right: IStaticType): IStaticType; static;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
implementation
|
implementation
|
||||||
@@ -91,36 +114,6 @@ implementation
|
|||||||
uses
|
uses
|
||||||
System.Generics.Defaults;
|
System.Generics.Defaults;
|
||||||
|
|
||||||
type
|
|
||||||
TMethodSignature = class(TInterfacedObject, TStaticType.IMethodSignature)
|
|
||||||
private
|
|
||||||
FParamTypes: TArray<TStaticType>;
|
|
||||||
FReturnType: TStaticType;
|
|
||||||
function GetParamTypes: TArray<TStaticType>;
|
|
||||||
function GetReturnType: TStaticType;
|
|
||||||
public
|
|
||||||
constructor Create(const AParamTypes: TArray<TStaticType>; const AReturnType: TStaticType);
|
|
||||||
end;
|
|
||||||
|
|
||||||
{ TMethodSignature }
|
|
||||||
|
|
||||||
constructor TMethodSignature.Create(const AParamTypes: TArray<TStaticType>; const AReturnType: TStaticType);
|
|
||||||
begin
|
|
||||||
inherited Create;
|
|
||||||
FParamTypes := AParamTypes;
|
|
||||||
FReturnType := AReturnType;
|
|
||||||
end;
|
|
||||||
|
|
||||||
function TMethodSignature.GetParamTypes: TArray<TStaticType>;
|
|
||||||
begin
|
|
||||||
Result := FParamTypes;
|
|
||||||
end;
|
|
||||||
|
|
||||||
function TMethodSignature.GetReturnType: TStaticType;
|
|
||||||
begin
|
|
||||||
Result := FReturnType;
|
|
||||||
end;
|
|
||||||
|
|
||||||
{ TStaticTypeKindHelper }
|
{ TStaticTypeKindHelper }
|
||||||
|
|
||||||
function TStaticTypeKindHelper.ToString: string;
|
function TStaticTypeKindHelper.ToString: string;
|
||||||
@@ -140,150 +133,324 @@ begin
|
|||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
{ TStaticType }
|
// --- Abstract Base Implementation ---
|
||||||
|
|
||||||
class operator TStaticType.Initialize(out Dest: TStaticType);
|
type
|
||||||
begin
|
TAbstractStaticType = class(TInterfacedObject, IStaticType)
|
||||||
Dest.Kind := stUnknown;
|
protected
|
||||||
Dest.Signature := nil;
|
// IStaticType (default implementations for non-applicable properties)
|
||||||
Dest.ElementType := nil;
|
function GetKind: TStaticTypeKind; virtual; abstract;
|
||||||
end;
|
function GetElementType: IStaticType; virtual;
|
||||||
|
function GetSignature: IMethodSignature; virtual;
|
||||||
class operator TStaticType.Finalize(var Dest: TStaticType);
|
function GetDefinition: TScalarRecordDefinition; virtual;
|
||||||
begin
|
function IsEqual(const Other: IStaticType): Boolean; virtual;
|
||||||
Dest.Signature := nil;
|
function ToString: string; override;
|
||||||
if Dest.ElementType <> nil then
|
|
||||||
begin
|
|
||||||
Finalize(Dest.ElementType^);
|
|
||||||
FreeMem(Dest.ElementType);
|
|
||||||
Dest.ElementType := nil;
|
|
||||||
end;
|
end;
|
||||||
// TScalarRecordDefinition (FFields) is not owned by this record.
|
|
||||||
|
function TAbstractStaticType.GetElementType: IStaticType;
|
||||||
|
begin
|
||||||
|
Result := nil;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
class operator TStaticType.Equal(const A, B: TStaticType): Boolean;
|
function TAbstractStaticType.GetSignature: IMethodSignature;
|
||||||
|
begin
|
||||||
|
Result := nil;
|
||||||
|
end;
|
||||||
|
|
||||||
|
function TAbstractStaticType.GetDefinition: TScalarRecordDefinition;
|
||||||
|
begin
|
||||||
|
// Return an empty/invalid definition
|
||||||
|
Result := Default(TScalarRecordDefinition);
|
||||||
|
end;
|
||||||
|
|
||||||
|
function TAbstractStaticType.IsEqual(const Other: IStaticType): Boolean;
|
||||||
|
begin
|
||||||
|
// Default implementation: types are equal if their kinds are equal.
|
||||||
|
// Complex types (Series, Record, Method) MUST override this.
|
||||||
|
if not Assigned(Other) then
|
||||||
|
exit(False);
|
||||||
|
Result := (GetKind = Other.Kind);
|
||||||
|
end;
|
||||||
|
|
||||||
|
function TAbstractStaticType.ToString: string;
|
||||||
|
begin
|
||||||
|
Result := GetKind.ToString;
|
||||||
|
end;
|
||||||
|
|
||||||
|
// --- Simple (Flyweight) Type Implementations ---
|
||||||
|
|
||||||
|
type
|
||||||
|
TSimpleStaticType = class(TAbstractStaticType)
|
||||||
|
private
|
||||||
|
FKind: TStaticTypeKind;
|
||||||
|
public
|
||||||
|
constructor Create(AKind: TStaticTypeKind);
|
||||||
|
function GetKind: TStaticTypeKind; override;
|
||||||
|
end;
|
||||||
|
|
||||||
|
constructor TSimpleStaticType.Create(AKind: TStaticTypeKind);
|
||||||
|
begin
|
||||||
|
inherited Create;
|
||||||
|
FKind := AKind;
|
||||||
|
end;
|
||||||
|
|
||||||
|
function TSimpleStaticType.GetKind: TStaticTypeKind;
|
||||||
|
begin
|
||||||
|
Result := FKind;
|
||||||
|
end;
|
||||||
|
|
||||||
|
// --- Complex Type Implementations ---
|
||||||
|
|
||||||
|
type
|
||||||
|
TSeriesType = class(TAbstractStaticType)
|
||||||
|
private
|
||||||
|
FElementType: IStaticType;
|
||||||
|
public
|
||||||
|
constructor Create(AElementType: IStaticType);
|
||||||
|
function GetKind: TStaticTypeKind; override;
|
||||||
|
function GetElementType: IStaticType; override;
|
||||||
|
function IsEqual(const Other: IStaticType): Boolean; override;
|
||||||
|
function ToString: string; override;
|
||||||
|
end;
|
||||||
|
|
||||||
|
constructor TSeriesType.Create(AElementType: IStaticType);
|
||||||
|
begin
|
||||||
|
inherited Create;
|
||||||
|
FElementType := AElementType;
|
||||||
|
end;
|
||||||
|
|
||||||
|
function TSeriesType.GetKind: TStaticTypeKind;
|
||||||
|
begin
|
||||||
|
Result := stSeries;
|
||||||
|
end;
|
||||||
|
|
||||||
|
function TSeriesType.GetElementType: IStaticType;
|
||||||
|
begin
|
||||||
|
Result := FElementType;
|
||||||
|
end;
|
||||||
|
|
||||||
|
function TSeriesType.IsEqual(const Other: IStaticType): Boolean;
|
||||||
|
begin
|
||||||
|
Result := (Assigned(Other)) and (Other.Kind = stSeries) and (Self.FElementType.IsEqual(Other.ElementType));
|
||||||
|
end;
|
||||||
|
|
||||||
|
function TSeriesType.ToString: string;
|
||||||
|
begin
|
||||||
|
Result := 'Series<' + FElementType.ToString + '>';
|
||||||
|
end;
|
||||||
|
|
||||||
|
// ---
|
||||||
|
type
|
||||||
|
TMethodSignature = class(TInterfacedObject, IMethodSignature)
|
||||||
|
private
|
||||||
|
FParamTypes: TArray<IStaticType>;
|
||||||
|
FReturnType: IStaticType;
|
||||||
|
function GetParamTypes: TArray<IStaticType>;
|
||||||
|
function GetReturnType: IStaticType;
|
||||||
|
public
|
||||||
|
constructor Create(const AParamTypes: TArray<IStaticType>; const AReturnType: IStaticType);
|
||||||
|
end;
|
||||||
|
|
||||||
|
constructor TMethodSignature.Create(const AParamTypes: TArray<IStaticType>; const AReturnType: IStaticType);
|
||||||
|
begin
|
||||||
|
inherited Create;
|
||||||
|
FParamTypes := AParamTypes;
|
||||||
|
FReturnType := AReturnType;
|
||||||
|
end;
|
||||||
|
|
||||||
|
function TMethodSignature.GetParamTypes: TArray<IStaticType>;
|
||||||
|
begin
|
||||||
|
Result := FParamTypes;
|
||||||
|
end;
|
||||||
|
|
||||||
|
function TMethodSignature.GetReturnType: IStaticType;
|
||||||
|
begin
|
||||||
|
Result := FReturnType;
|
||||||
|
end;
|
||||||
|
|
||||||
|
// ---
|
||||||
|
type
|
||||||
|
TMethodType = class(TAbstractStaticType)
|
||||||
|
private
|
||||||
|
FSignature: IMethodSignature;
|
||||||
|
public
|
||||||
|
constructor Create(AParamTypes: TArray<IStaticType>; AReturnType: IStaticType);
|
||||||
|
function GetKind: TStaticTypeKind; override;
|
||||||
|
function GetSignature: IMethodSignature; override;
|
||||||
|
function IsEqual(const Other: IStaticType): Boolean; override;
|
||||||
|
function ToString: string; override;
|
||||||
|
end;
|
||||||
|
|
||||||
|
constructor TMethodType.Create(AParamTypes: TArray<IStaticType>; AReturnType: IStaticType);
|
||||||
|
begin
|
||||||
|
inherited Create;
|
||||||
|
FSignature := TMethodSignature.Create(AParamTypes, AReturnType);
|
||||||
|
end;
|
||||||
|
|
||||||
|
function TMethodType.GetKind: TStaticTypeKind;
|
||||||
|
begin
|
||||||
|
Result := stMethod;
|
||||||
|
end;
|
||||||
|
|
||||||
|
function TMethodType.GetSignature: IMethodSignature;
|
||||||
|
begin
|
||||||
|
Result := FSignature;
|
||||||
|
end;
|
||||||
|
|
||||||
|
function TMethodType.IsEqual(const Other: IStaticType): Boolean;
|
||||||
var
|
var
|
||||||
i: Integer;
|
i: Integer;
|
||||||
begin
|
begin
|
||||||
if A.Kind <> B.Kind then
|
if (not Assigned(Other)) or (Other.Kind <> stMethod) then
|
||||||
exit(False);
|
exit(False);
|
||||||
|
|
||||||
case A.Kind of
|
var otherSig := Other.Signature;
|
||||||
stSeries: Result := A.ElementType^ = B.ElementType^;
|
if not Self.FSignature.ReturnType.IsEqual(otherSig.ReturnType) then
|
||||||
stRecord, stRecordSeries:
|
exit(False);
|
||||||
begin
|
|
||||||
if Length(A.Definition.Fields) <> Length(B.Definition.Fields) then
|
if Length(Self.FSignature.ParamTypes) <> Length(otherSig.ParamTypes) then
|
||||||
exit(False);
|
exit(False);
|
||||||
for i := 0 to High(A.Definition.Fields) do
|
|
||||||
begin
|
for i := 0 to High(Self.FSignature.ParamTypes) do
|
||||||
if (A.Definition.Fields[i].Name <> B.Definition.Fields[i].Name)
|
begin
|
||||||
or (A.Definition.Fields[i].Kind <> B.Definition.Fields[i].Kind) then
|
if not Self.FSignature.ParamTypes[i].IsEqual(otherSig.ParamTypes[i]) then
|
||||||
exit(False);
|
exit(False);
|
||||||
end;
|
|
||||||
Result := True;
|
|
||||||
end;
|
|
||||||
stMethod:
|
|
||||||
begin
|
|
||||||
if A.Signature.ReturnType <> B.Signature.ReturnType then
|
|
||||||
exit(False);
|
|
||||||
if Length(A.Signature.ParamTypes) <> Length(B.Signature.ParamTypes) then
|
|
||||||
exit(False);
|
|
||||||
for i := 0 to High(A.Signature.ParamTypes) do
|
|
||||||
begin
|
|
||||||
if A.Signature.ParamTypes[i] <> B.Signature.ParamTypes[i] then
|
|
||||||
exit(False);
|
|
||||||
end;
|
|
||||||
Result := True;
|
|
||||||
end;
|
|
||||||
else
|
|
||||||
// stUnknown, stVoid, stOrdinal, stFloat, stText are equal if their kinds are equal.
|
|
||||||
Result := True;
|
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
Result := True;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
class function TStaticType.Create(AKind: TStaticTypeKind): TStaticType;
|
function TMethodType.ToString: string;
|
||||||
|
var
|
||||||
|
i: Integer;
|
||||||
|
paramStr: string;
|
||||||
begin
|
begin
|
||||||
Result.Kind := AKind;
|
paramStr := '';
|
||||||
|
for i := 0 to High(FSignature.ParamTypes) do
|
||||||
|
begin
|
||||||
|
paramStr := paramStr + FSignature.ParamTypes[i].ToString;
|
||||||
|
if i < High(FSignature.ParamTypes) then
|
||||||
|
paramStr := paramStr + ', ';
|
||||||
|
end;
|
||||||
|
Result := Format('Method(%s): %s', [paramStr, FSignature.ReturnType.ToString]);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
class function TStaticType.CreateMethod(const AParamTypes: TArray<TStaticType>; const AReturnType: TStaticType): TStaticType;
|
// ---
|
||||||
|
type
|
||||||
|
TRecordType = class(TAbstractStaticType)
|
||||||
|
private
|
||||||
|
FKind: TStaticTypeKind;
|
||||||
|
FDefinition: TScalarRecordDefinition;
|
||||||
|
public
|
||||||
|
constructor Create(AKind: TStaticTypeKind; ADef: TScalarRecordDefinition);
|
||||||
|
function GetKind: TStaticTypeKind; override;
|
||||||
|
function GetDefinition: TScalarRecordDefinition; override;
|
||||||
|
function IsEqual(const Other: IStaticType): Boolean; override;
|
||||||
|
function ToString: string; override;
|
||||||
|
end;
|
||||||
|
|
||||||
|
constructor TRecordType.Create(AKind: TStaticTypeKind; ADef: TScalarRecordDefinition);
|
||||||
begin
|
begin
|
||||||
Result.Kind := stMethod;
|
inherited Create;
|
||||||
Result.Signature := TMethodSignature.Create(AParamTypes, AReturnType);
|
Assert(AKind in [stRecord, stRecordSeries]);
|
||||||
|
FKind := AKind;
|
||||||
|
FDefinition := ADef;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
class function TStaticType.CreateRecord(const ADef: TScalarRecordDefinition): TStaticType;
|
function TRecordType.GetKind: TStaticTypeKind;
|
||||||
begin
|
begin
|
||||||
Result.Kind := stRecord;
|
Result := FKind;
|
||||||
Result.Definition := ADef;
|
|
||||||
end;
|
end;
|
||||||
|
|
||||||
class function TStaticType.CreateRecordSeries(const ADef: TScalarRecordDefinition): TStaticType;
|
function TRecordType.GetDefinition: TScalarRecordDefinition;
|
||||||
begin
|
begin
|
||||||
Result.Kind := stRecordSeries;
|
Result := FDefinition;
|
||||||
Result.Definition := ADef;
|
|
||||||
end;
|
end;
|
||||||
|
|
||||||
class function TStaticType.CreateSeries(const AElementType: TStaticType): TStaticType;
|
function TRecordType.IsEqual(const Other: IStaticType): Boolean;
|
||||||
|
var
|
||||||
|
i: Integer;
|
||||||
begin
|
begin
|
||||||
Result.Kind := stSeries;
|
if (not Assigned(Other)) or (Other.Kind <> GetKind) then
|
||||||
New(Result.ElementType);
|
exit(False);
|
||||||
Result.ElementType^ := AElementType;
|
|
||||||
|
var otherDef := Other.Definition;
|
||||||
|
if Length(Self.FDefinition.Fields) <> Length(otherDef.Fields) then
|
||||||
|
exit(False);
|
||||||
|
|
||||||
|
for i := 0 to High(Self.FDefinition.Fields) do
|
||||||
|
begin
|
||||||
|
if (Self.FDefinition.Fields[i].Name <> otherDef.Fields[i].Name) or (Self.FDefinition.Fields[i].Kind <> otherDef.Fields[i].Kind) then
|
||||||
|
exit(False);
|
||||||
|
end;
|
||||||
|
|
||||||
|
Result := True;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
class function TStaticType.FromScalarKind(AKind: TScalar.TKind): TStaticType;
|
function TRecordType.ToString: string;
|
||||||
|
var
|
||||||
|
i: Integer;
|
||||||
|
begin
|
||||||
|
Result := GetKind.ToString + '{';
|
||||||
|
for i := 0 to High(FDefinition.Fields) do
|
||||||
|
begin
|
||||||
|
Result := Result + FDefinition.Fields[i].Name + ': ' + FDefinition.Fields[i].Kind.ToString;
|
||||||
|
if i < High(FDefinition.Fields) then
|
||||||
|
Result := Result + ', ';
|
||||||
|
end;
|
||||||
|
Result := Result + '}';
|
||||||
|
end;
|
||||||
|
|
||||||
|
{ TTypes (Factory) }
|
||||||
|
|
||||||
|
class constructor TTypes.Create;
|
||||||
|
begin
|
||||||
|
// Create the flyweight singletons
|
||||||
|
FUnknown := TSimpleStaticType.Create(stUnknown);
|
||||||
|
FVoid := TSimpleStaticType.Create(stVoid);
|
||||||
|
FOrdinal := TSimpleStaticType.Create(stOrdinal);
|
||||||
|
FFloat := TSimpleStaticType.Create(stFloat);
|
||||||
|
FText := TSimpleStaticType.Create(stText);
|
||||||
|
end;
|
||||||
|
|
||||||
|
class function TTypes.CreateMethod(const AParamTypes: TArray<IStaticType>; const AReturnType: IStaticType): IStaticType;
|
||||||
|
begin
|
||||||
|
Result := TMethodType.Create(AParamTypes, AReturnType);
|
||||||
|
end;
|
||||||
|
|
||||||
|
class function TTypes.CreateRecord(const ADef: TScalarRecordDefinition): IStaticType;
|
||||||
|
begin
|
||||||
|
Result := TRecordType.Create(stRecord, ADef);
|
||||||
|
end;
|
||||||
|
|
||||||
|
class function TTypes.CreateRecordSeries(const ADef: TScalarRecordDefinition): IStaticType;
|
||||||
|
begin
|
||||||
|
Result := TRecordType.Create(stRecordSeries, ADef);
|
||||||
|
end;
|
||||||
|
|
||||||
|
class function TTypes.CreateSeries(const AElementType: IStaticType): IStaticType;
|
||||||
|
begin
|
||||||
|
Result := TSeriesType.Create(AElementType);
|
||||||
|
end;
|
||||||
|
|
||||||
|
class function TTypes.FromScalarKind(AKind: TScalar.TKind): IStaticType;
|
||||||
begin
|
begin
|
||||||
case AKind of
|
case AKind of
|
||||||
TScalar.TKind.Ordinal: Result.Kind := stOrdinal;
|
TScalar.TKind.Ordinal: Result := FOrdinal;
|
||||||
TScalar.TKind.Float: Result.Kind := stFloat;
|
TScalar.TKind.Float: Result := FFloat;
|
||||||
else
|
else
|
||||||
raise ETypeException.Create('Cannot convert invalid TScalar.TKind to TStaticType.');
|
raise ETypeException.Create('Cannot convert invalid TScalar.TKind to TStaticType.');
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
function TStaticType.ToString: string;
|
|
||||||
var
|
|
||||||
i: Integer;
|
|
||||||
paramStr: string;
|
|
||||||
begin
|
|
||||||
Result := Kind.ToString;
|
|
||||||
case Kind of
|
|
||||||
stSeries: Result := 'Series<' + ElementType^.ToString + '>';
|
|
||||||
stRecord, stRecordSeries:
|
|
||||||
begin
|
|
||||||
Result := Result + '{';
|
|
||||||
for i := 0 to High(Definition.Fields) do
|
|
||||||
begin
|
|
||||||
Result := Result + Definition.Fields[i].Name + ': ' + Definition.Fields[i].Kind.ToString;
|
|
||||||
if i < High(Definition.Fields) then
|
|
||||||
Result := Result + ', ';
|
|
||||||
end;
|
|
||||||
Result := Result + '}';
|
|
||||||
end;
|
|
||||||
stMethod:
|
|
||||||
begin
|
|
||||||
paramStr := '';
|
|
||||||
for i := 0 to High(Signature.ParamTypes) do
|
|
||||||
begin
|
|
||||||
paramStr := paramStr + Signature.ParamTypes[i].ToString;
|
|
||||||
if i < High(Signature.ParamTypes) then
|
|
||||||
paramStr := paramStr + ', ';
|
|
||||||
end;
|
|
||||||
Result := Format('Method(%s): %s', [paramStr, Signature.ReturnType.ToString]);
|
|
||||||
end;
|
|
||||||
end;
|
|
||||||
end;
|
|
||||||
|
|
||||||
class operator TStaticType.NotEqual(A, B: TStaticType): Boolean;
|
|
||||||
begin
|
|
||||||
Result := not (A = B);
|
|
||||||
end;
|
|
||||||
|
|
||||||
{ TTypeRules }
|
{ TTypeRules }
|
||||||
|
|
||||||
class function TTypeRules.CanAssign(const Target, Source: TStaticType): Boolean;
|
class function TTypeRules.CanAssign(const Target, Source: IStaticType): Boolean;
|
||||||
begin
|
begin
|
||||||
if Target = Source then
|
if (not Assigned(Target)) or (not Assigned(Source)) then
|
||||||
|
exit(False);
|
||||||
|
|
||||||
|
if Target.IsEqual(Source) then
|
||||||
exit(True);
|
exit(True);
|
||||||
|
|
||||||
// Allow assigning an integer (Ordinal) to a float variable.
|
// Allow assigning an integer (Ordinal) to a float variable.
|
||||||
@@ -295,22 +462,22 @@ begin
|
|||||||
Result := False;
|
Result := False;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
class function TTypeRules.Promote(const A, B: TStaticType): TStaticType;
|
class function TTypeRules.Promote(const A, B: IStaticType): IStaticType;
|
||||||
begin
|
begin
|
||||||
// Numeric promotion rule: Float wins
|
// Numeric promotion rule: Float wins
|
||||||
if (A.Kind = stFloat) and (B.Kind = stFloat) then
|
if (A.Kind = stFloat) and (B.Kind = stFloat) then
|
||||||
exit(TStaticType.Create(stFloat));
|
exit(TTypes.Float);
|
||||||
if (A.Kind = stFloat) and (B.Kind = stOrdinal) then
|
if (A.Kind = stFloat) and (B.Kind = stOrdinal) then
|
||||||
exit(TStaticType.Create(stFloat));
|
exit(TTypes.Float);
|
||||||
if (A.Kind = stOrdinal) and (B.Kind = stFloat) then
|
if (A.Kind = stOrdinal) and (B.Kind = stFloat) then
|
||||||
exit(TStaticType.Create(stFloat));
|
exit(TTypes.Float);
|
||||||
if (A.Kind = stOrdinal) and (B.Kind = stOrdinal) then
|
if (A.Kind = stOrdinal) and (B.Kind = stOrdinal) then
|
||||||
exit(TStaticType.Create(stOrdinal));
|
exit(TTypes.Ordinal);
|
||||||
|
|
||||||
raise ETypeException.CreateFmt('Cannot promote types %s and %s', [A.ToString, B.ToString]);
|
raise ETypeException.CreateFmt('Cannot promote types %s and %s', [A.ToString, B.ToString]);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
class function TTypeRules.ResolveBinaryOp(Op: TScalar.TBinaryOp; const Left, Right: TStaticType): TStaticType;
|
class function TTypeRules.ResolveBinaryOp(Op: TScalar.TBinaryOp; const Left, Right: IStaticType): IStaticType;
|
||||||
begin
|
begin
|
||||||
case Op of
|
case Op of
|
||||||
TScalar.TBinaryOp.Add, TScalar.TBinaryOp.Subtract, TScalar.TBinaryOp.Multiply:
|
TScalar.TBinaryOp.Add, TScalar.TBinaryOp.Subtract, TScalar.TBinaryOp.Multiply:
|
||||||
@@ -326,7 +493,7 @@ begin
|
|||||||
begin
|
begin
|
||||||
// Division *always* results in Float, even Ordinal / Ordinal
|
// Division *always* results in Float, even Ordinal / Ordinal
|
||||||
if (Left.Kind in [stOrdinal, stFloat]) and (Right.Kind in [stOrdinal, stFloat]) then
|
if (Left.Kind in [stOrdinal, stFloat]) and (Right.Kind in [stOrdinal, stFloat]) then
|
||||||
Result := TStaticType.Create(stFloat)
|
Result := TTypes.Float
|
||||||
else
|
else
|
||||||
raise ETypeException.CreateFmt('Operator %s cannot be applied to %s and %s', [Op.ToString, Left.ToString, Right.ToString]);
|
raise ETypeException.CreateFmt('Operator %s cannot be applied to %s and %s', [Op.ToString, Left.ToString, Right.ToString]);
|
||||||
end;
|
end;
|
||||||
@@ -340,7 +507,7 @@ begin
|
|||||||
begin
|
begin
|
||||||
// Comparison operations: Check if promotion is possible, but always return Ordinal (boolean)
|
// Comparison operations: Check if promotion is possible, but always return Ordinal (boolean)
|
||||||
if (Left.Kind in [stOrdinal, stFloat]) and (Right.Kind in [stOrdinal, stFloat]) then
|
if (Left.Kind in [stOrdinal, stFloat]) and (Right.Kind in [stOrdinal, stFloat]) then
|
||||||
Result := TStaticType.Create(stOrdinal)
|
Result := TTypes.Ordinal
|
||||||
else
|
else
|
||||||
raise ETypeException
|
raise ETypeException
|
||||||
.CreateFmt('Comparison operator %s cannot be applied to %s and %s', [Op.ToString, Left.ToString, Right.ToString]);
|
.CreateFmt('Comparison operator %s cannot be applied to %s and %s', [Op.ToString, Left.ToString, Right.ToString]);
|
||||||
@@ -350,7 +517,7 @@ begin
|
|||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
class function TTypeRules.ResolveUnaryOp(Op: TScalar.TUnaryOp; const Right: TStaticType): TStaticType;
|
class function TTypeRules.ResolveUnaryOp(Op: TScalar.TUnaryOp; const Right: IStaticType): IStaticType;
|
||||||
begin
|
begin
|
||||||
case Op of
|
case Op of
|
||||||
TScalar.TUnaryOp.Negate:
|
TScalar.TUnaryOp.Negate:
|
||||||
@@ -364,7 +531,7 @@ begin
|
|||||||
begin
|
begin
|
||||||
if not (Right.Kind = stOrdinal) then
|
if not (Right.Kind = stOrdinal) then
|
||||||
raise ETypeException.CreateFmt('Logical not cannot be applied to %s', [Right.ToString]);
|
raise ETypeException.CreateFmt('Logical not cannot be applied to %s', [Right.ToString]);
|
||||||
Result := TStaticType.Create(stOrdinal);
|
Result := TTypes.Ordinal;
|
||||||
end;
|
end;
|
||||||
else
|
else
|
||||||
raise ETypeException.Create('Unknown unary operator for type resolution.');
|
raise ETypeException.Create('Unknown unary operator for type resolution.');
|
||||||
|
|||||||
Reference in New Issue
Block a user