Keywords as basic scalar type
Script enhancements
This commit is contained in:
+105
-1
@@ -22,7 +22,8 @@ type
|
||||
stMethod,
|
||||
stSeries,
|
||||
stRecord,
|
||||
stRecordSeries
|
||||
stRecordSeries,
|
||||
stGenericRecord
|
||||
);
|
||||
|
||||
TStaticTypeKindHelper = record helper for TStaticTypeKind
|
||||
@@ -40,6 +41,10 @@ type
|
||||
property ReturnType: IStaticType read GetReturnType;
|
||||
end;
|
||||
|
||||
// Defines a mapping for generic record fields (Key -> StaticType)
|
||||
IGenericRecordDefinition = IKeywordMapping<IStaticType>;
|
||||
TGenericRecordRegistry = TKeywordMappingRegistry<IStaticType>;
|
||||
|
||||
// Represents a complete static type definition.
|
||||
IStaticType = interface
|
||||
{$region 'private'}
|
||||
@@ -47,6 +52,7 @@ type
|
||||
function GetElementType: IStaticType;
|
||||
function GetSignature: IMethodSignature;
|
||||
function GetDefinition: IScalarRecordDefinition;
|
||||
function GetGenericDefinition: IGenericRecordDefinition;
|
||||
{$endregion}
|
||||
|
||||
// The kind of type (e.g., Ordinal, Series, etc.)
|
||||
@@ -57,6 +63,8 @@ type
|
||||
property Signature: IMethodSignature read GetSignature;
|
||||
// The definition (if Kind = stRecord or stRecordSeries)
|
||||
property Definition: IScalarRecordDefinition read GetDefinition;
|
||||
// The definition (if Kind = stGenericRecord)
|
||||
property GenericDefinition: IGenericRecordDefinition read GetGenericDefinition;
|
||||
|
||||
// Checks for type equality
|
||||
function IsEqual(const Other: IStaticType): Boolean;
|
||||
@@ -96,6 +104,7 @@ type
|
||||
class function CreateMethod(const AParamTypes: TArray<IStaticType>; const AReturnType: IStaticType): IStaticType; static;
|
||||
class function CreateRecord(const ADef: IScalarRecordDefinition): IStaticType; static;
|
||||
class function CreateRecordSeries(const ADef: IScalarRecordDefinition): IStaticType; static;
|
||||
class function CreateGenericRecord(const ADef: IGenericRecordDefinition): IStaticType; static;
|
||||
|
||||
class function FromScalarKind(AKind: TScalar.TKind): IStaticType; static;
|
||||
end;
|
||||
@@ -134,6 +143,7 @@ begin
|
||||
stSeries: Result := 'Series';
|
||||
stRecord: Result := 'Record';
|
||||
stRecordSeries: Result := 'RecordSeries';
|
||||
stGenericRecord: Result := 'GenericRecord'; // Added
|
||||
else
|
||||
Result := 'ErrorType';
|
||||
end;
|
||||
@@ -149,6 +159,7 @@ type
|
||||
function GetElementType: IStaticType; virtual;
|
||||
function GetSignature: IMethodSignature; virtual;
|
||||
function GetDefinition: IScalarRecordDefinition; virtual;
|
||||
function GetGenericDefinition: IGenericRecordDefinition; virtual; // Added
|
||||
function IsEqual(const Other: IStaticType): Boolean; virtual;
|
||||
function ToString: string; override;
|
||||
end;
|
||||
@@ -169,6 +180,12 @@ begin
|
||||
Result := Default(IScalarRecordDefinition);
|
||||
end;
|
||||
|
||||
// Added
|
||||
function TAbstractStaticType.GetGenericDefinition: IGenericRecordDefinition;
|
||||
begin
|
||||
Result := nil;
|
||||
end;
|
||||
|
||||
function TAbstractStaticType.IsEqual(const Other: IStaticType): Boolean;
|
||||
begin
|
||||
// Default implementation: types are equal if their kinds are equal.
|
||||
@@ -343,6 +360,7 @@ end;
|
||||
|
||||
// ---
|
||||
type
|
||||
// Represents stRecord and stRecordSeries (Scalar Records)
|
||||
TRecordType = class(TAbstractStaticType)
|
||||
private
|
||||
FKind: TStaticTypeKind;
|
||||
@@ -414,6 +432,78 @@ begin
|
||||
Result := Result + '}';
|
||||
end;
|
||||
|
||||
// ---
|
||||
// Added: Represents stGenericRecord
|
||||
type
|
||||
TGenericRecordType = class(TAbstractStaticType)
|
||||
private
|
||||
FDefinition: IGenericRecordDefinition;
|
||||
public
|
||||
constructor Create(const ADef: IGenericRecordDefinition);
|
||||
function GetKind: TStaticTypeKind; override;
|
||||
function GetGenericDefinition: IGenericRecordDefinition; override;
|
||||
function IsEqual(const Other: IStaticType): Boolean; override;
|
||||
function ToString: string; override;
|
||||
end;
|
||||
|
||||
constructor TGenericRecordType.Create(const ADef: IGenericRecordDefinition);
|
||||
begin
|
||||
inherited Create;
|
||||
FDefinition := ADef;
|
||||
end;
|
||||
|
||||
function TGenericRecordType.GetKind: TStaticTypeKind;
|
||||
begin
|
||||
Result := stGenericRecord;
|
||||
end;
|
||||
|
||||
function TGenericRecordType.GetGenericDefinition: IGenericRecordDefinition;
|
||||
begin
|
||||
Result := FDefinition;
|
||||
end;
|
||||
|
||||
function TGenericRecordType.IsEqual(const Other: IStaticType): Boolean;
|
||||
var
|
||||
i: Integer;
|
||||
begin
|
||||
if (not Assigned(Other)) or (Other.Kind <> stGenericRecord) then
|
||||
exit(False);
|
||||
|
||||
var otherDef := Other.GenericDefinition;
|
||||
if (not Assigned(Self.FDefinition)) or (not Assigned(otherDef)) then
|
||||
exit(False);
|
||||
|
||||
if Length(Self.FDefinition.Fields) <> Length(otherDef.Fields) then
|
||||
exit(False);
|
||||
|
||||
for i := 0 to High(Self.FDefinition.Fields) do
|
||||
begin
|
||||
// Compare keys (fast) and static types (must use IsEqual)
|
||||
if (Self.FDefinition.Fields[i].Key <> otherDef.Fields[i].Key)
|
||||
or (not Self.FDefinition.Fields[i].Value.IsEqual(otherDef.Fields[i].Value)) then
|
||||
exit(False);
|
||||
end;
|
||||
|
||||
Result := True;
|
||||
end;
|
||||
|
||||
function TGenericRecordType.ToString: string;
|
||||
var
|
||||
i: Integer;
|
||||
begin
|
||||
Result := GetKind.ToString + '{';
|
||||
if Assigned(FDefinition) then
|
||||
begin
|
||||
for i := 0 to High(FDefinition.Fields) do
|
||||
begin
|
||||
Result := Result + FDefinition.Fields[i].Key.Name + ': ' + FDefinition.Fields[i].Value.ToString;
|
||||
if i < High(FDefinition.Fields) then
|
||||
Result := Result + ', ';
|
||||
end;
|
||||
end;
|
||||
Result := Result + '}';
|
||||
end;
|
||||
|
||||
{ TTypes (Factory) }
|
||||
|
||||
class constructor TTypes.Create;
|
||||
@@ -442,6 +532,12 @@ begin
|
||||
Result := TRecordType.Create(stRecordSeries, ADef);
|
||||
end;
|
||||
|
||||
// Added
|
||||
class function TTypes.CreateGenericRecord(const ADef: IGenericRecordDefinition): IStaticType;
|
||||
begin
|
||||
Result := TGenericRecordType.Create(ADef);
|
||||
end;
|
||||
|
||||
class function TTypes.CreateSeries(const AElementType: IStaticType): IStaticType;
|
||||
begin
|
||||
Result := TSeriesType.Create(AElementType);
|
||||
@@ -484,6 +580,9 @@ begin
|
||||
|
||||
// TODO: Implement full assignment compatibility rules (e.g., for records/series)
|
||||
|
||||
// Allow assigning a scalar record to a generic record? (Maybe later)
|
||||
// Allow assigning a generic record to a scalar record? (If fields match)
|
||||
|
||||
Result := False;
|
||||
end;
|
||||
|
||||
@@ -513,6 +612,10 @@ begin
|
||||
if A.IsEqual(B) then
|
||||
exit(A);
|
||||
|
||||
// Cannot promote stGenericRecord or stRecord with anything other than itself/unknown
|
||||
if (A.Kind in [stRecord, stGenericRecord]) or (B.Kind in [stRecord, stGenericRecord]) then
|
||||
raise ETypeException.CreateFmt('Cannot promote types %s and %s', [A.ToString, B.ToString]);
|
||||
|
||||
// Cannot promote other combinations (e.g., Ordinal and Keyword)
|
||||
raise ETypeException.CreateFmt('Cannot promote types %s and %s', [A.ToString, B.ToString]);
|
||||
end;
|
||||
@@ -562,6 +665,7 @@ begin
|
||||
TScalar.TBinaryOp.Equal, TScalar.TBinaryOp.NotEqual:
|
||||
begin
|
||||
// Allow equality checks for Ordinal, Float, or Keyword
|
||||
// (Records are not yet supported for equality)
|
||||
if not (promotedKind in [stOrdinal, stFloat, stKeyword]) then
|
||||
raise ETypeException.CreateFmt(
|
||||
'Comparison operator %s requires Ordinal, Float, or Keyword, but got %s after promotion',
|
||||
|
||||
Reference in New Issue
Block a user