Integrated Boolean and DateTime as core types
This commit is contained in:
+46
-29
@@ -17,6 +17,8 @@ type
|
||||
stVoid,
|
||||
stOrdinal, // Int64
|
||||
stFloat, // Double
|
||||
stBoolean,
|
||||
stDateTime,
|
||||
stText,
|
||||
stKeyword,
|
||||
stMethod,
|
||||
@@ -51,8 +53,7 @@ type
|
||||
{$region 'private'}
|
||||
function GetKind: TStaticTypeKind;
|
||||
function GetElementType: IStaticType;
|
||||
// function GetSignature: IMethodSignature; // (* REMOVED *)
|
||||
function GetSignatures: TArray<IMethodSignature>; // (* ADDED *)
|
||||
function GetSignatures: TArray<IMethodSignature>;
|
||||
function GetDefinition: IScalarRecordDefinition;
|
||||
function GetGenericDefinition: IGenericRecordDefinition;
|
||||
{$endregion}
|
||||
@@ -92,6 +93,10 @@ type
|
||||
FOrdinal: IStaticType;
|
||||
class var
|
||||
FFloat: IStaticType;
|
||||
class var
|
||||
FBoolean: IStaticType;
|
||||
class var
|
||||
FDateTime: IStaticType;
|
||||
class var
|
||||
FText: IStaticType;
|
||||
class var
|
||||
@@ -103,6 +108,8 @@ type
|
||||
class property Void: IStaticType read FVoid;
|
||||
class property Ordinal: IStaticType read FOrdinal;
|
||||
class property Float: IStaticType read FFloat;
|
||||
class property Boolean: IStaticType read FBoolean;
|
||||
class property DateTime: IStaticType read FDateTime;
|
||||
class property Text: IStaticType read FText;
|
||||
class property Keyword: IStaticType read FKeyword;
|
||||
|
||||
@@ -146,7 +153,7 @@ implementation
|
||||
|
||||
uses
|
||||
System.Generics.Defaults,
|
||||
System.Hash; // Added for TStringBuilder in TMethodType.ToString
|
||||
System.Hash;
|
||||
|
||||
{ TStaticTypeKindHelper }
|
||||
|
||||
@@ -157,6 +164,8 @@ begin
|
||||
stVoid: Result := 'Void';
|
||||
stOrdinal: Result := 'Ordinal';
|
||||
stFloat: Result := 'Float';
|
||||
stBoolean: Result := 'Boolean';
|
||||
stDateTime: Result := 'DateTime';
|
||||
stText: Result := 'Text';
|
||||
stKeyword: Result := 'Keyword';
|
||||
stMethod: Result := 'Method';
|
||||
@@ -177,7 +186,7 @@ type
|
||||
// IStaticType (default implementations for non-applicable properties)
|
||||
function GetKind: TStaticTypeKind; virtual; abstract;
|
||||
function GetElementType: IStaticType; virtual;
|
||||
function GetSignatures: TArray<IMethodSignature>; virtual; // (* CHANGED *)
|
||||
function GetSignatures: TArray<IMethodSignature>; virtual;
|
||||
function GetDefinition: IScalarRecordDefinition; virtual;
|
||||
function GetGenericDefinition: IGenericRecordDefinition; virtual;
|
||||
function IsEqual(const Other: IStaticType): Boolean; virtual;
|
||||
@@ -190,9 +199,9 @@ begin
|
||||
Result := nil;
|
||||
end;
|
||||
|
||||
function TAbstractStaticType.GetSignatures: TArray<IMethodSignature>; // (* CHANGED *)
|
||||
function TAbstractStaticType.GetSignatures: TArray<IMethodSignature>;
|
||||
begin
|
||||
Result := nil; // (* CHANGED *)
|
||||
Result := nil;
|
||||
end;
|
||||
|
||||
function TAbstractStaticType.GetDefinition: IScalarRecordDefinition;
|
||||
@@ -342,7 +351,6 @@ end;
|
||||
|
||||
// ---
|
||||
type
|
||||
// (* ENTIRE TMethodType IMPLEMENTATION REPLACED *)
|
||||
TMethodType = class(TAbstractStaticType)
|
||||
private
|
||||
FSignatures: TArray<IMethodSignature>;
|
||||
@@ -482,7 +490,7 @@ type
|
||||
function GetKind: TStaticTypeKind; override;
|
||||
function GetDefinition: IScalarRecordDefinition; override;
|
||||
function IsEqual(const Other: IStaticType): Boolean; override;
|
||||
function GetHashCode: Integer; override; // Added
|
||||
function GetHashCode: Integer; override;
|
||||
function ToString: string; override;
|
||||
end;
|
||||
|
||||
@@ -575,7 +583,7 @@ type
|
||||
function GetKind: TStaticTypeKind; override;
|
||||
function GetGenericDefinition: IGenericRecordDefinition; override;
|
||||
function IsEqual(const Other: IStaticType): Boolean; override;
|
||||
function GetHashCode: Integer; override; // Added
|
||||
function GetHashCode: Integer; override;
|
||||
function ToString: string; override;
|
||||
end;
|
||||
|
||||
@@ -669,6 +677,8 @@ begin
|
||||
FVoid := TSimpleStaticType.Create(stVoid);
|
||||
FOrdinal := TSimpleStaticType.Create(stOrdinal);
|
||||
FFloat := TSimpleStaticType.Create(stFloat);
|
||||
FBoolean := TSimpleStaticType.Create(stBoolean);
|
||||
FDateTime := TSimpleStaticType.Create(stDateTime);
|
||||
FText := TSimpleStaticType.Create(stText);
|
||||
FKeyword := TSimpleStaticType.Create(stKeyword);
|
||||
end;
|
||||
@@ -717,6 +727,8 @@ begin
|
||||
TScalar.TKind.Ordinal: Result := FOrdinal;
|
||||
TScalar.TKind.Float: Result := FFloat;
|
||||
TScalar.TKind.Keyword: Result := FKeyword;
|
||||
TScalar.TKind.Boolean: Result := FBoolean;
|
||||
TScalar.TKind.DateTime: Result := FDateTime;
|
||||
else
|
||||
raise ETypeException.Create('Cannot convert invalid TScalar.TKind to TStaticType.');
|
||||
end;
|
||||
@@ -742,6 +754,14 @@ begin
|
||||
if (Target.Kind = stFloat) and (Source.Kind = stOrdinal) then
|
||||
exit(True);
|
||||
|
||||
// Allow assigning Boolean to Ordinal (0/1)
|
||||
if (Target.Kind = stOrdinal) and (Source.Kind = stBoolean) then
|
||||
exit(True);
|
||||
|
||||
// Allow assigning DateTime to Float (TDateTime is Double)
|
||||
if (Target.Kind = stFloat) and (Source.Kind = stDateTime) then
|
||||
exit(True);
|
||||
|
||||
// Allow discarding the return value of a method (e.g., in a 'do' block).
|
||||
if (Target.Kind = stVoid) and (Source.Kind = stMethod) then
|
||||
exit(True);
|
||||
@@ -750,9 +770,6 @@ begin
|
||||
if (Target.Kind = stOrdinal) and (Source.Kind = stKeyword) then
|
||||
exit(True);
|
||||
|
||||
// Allow assigning a scalar record to a generic record? (Maybe later)
|
||||
// Allow assigning a generic record to a scalar record? (If fields match)
|
||||
|
||||
// Default: Assignment is not allowed if no specific rule matches.
|
||||
Result := False;
|
||||
end;
|
||||
@@ -779,7 +796,8 @@ begin
|
||||
if (A.Kind = stOrdinal) and (B.Kind = stOrdinal) then
|
||||
exit(TTypes.Ordinal);
|
||||
|
||||
// If types are identical (incl. Keyword, Text, etc.), return that type.
|
||||
// Implicit DateTime/Boolean logic via Ordinal/Float mapping?
|
||||
// If types are identical (incl. Keyword, Text, Boolean, DateTime), return that type.
|
||||
if A.IsEqual(B) then
|
||||
exit(A);
|
||||
|
||||
@@ -787,7 +805,7 @@ begin
|
||||
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)
|
||||
// Cannot promote other combinations
|
||||
raise ETypeException.CreateFmt('Cannot promote types %s and %s', [A.ToString, B.ToString]);
|
||||
end;
|
||||
|
||||
@@ -817,8 +835,8 @@ begin
|
||||
case Op of
|
||||
TScalar.TBinaryOp.Add, TScalar.TBinaryOp.Subtract, TScalar.TBinaryOp.Multiply:
|
||||
begin
|
||||
// Numeric operations require Ordinal or Float
|
||||
if not (promotedKind in [stOrdinal, stFloat]) then
|
||||
// Numeric operations require Ordinal, Float, or DateTime(as Float)
|
||||
if not (promotedKind in [stOrdinal, stFloat, stDateTime]) then
|
||||
raise ETypeException
|
||||
.CreateFmt('Operator %s requires Ordinal or Float, but got %s after promotion', [Op.ToString, promotedType.ToString]);
|
||||
Result := promotedType; // Result has the promoted type
|
||||
@@ -827,7 +845,7 @@ begin
|
||||
TScalar.TBinaryOp.Divide:
|
||||
begin
|
||||
// Division requires Ordinal or Float, but *always* results in Float
|
||||
if not (promotedKind in [stOrdinal, stFloat]) then
|
||||
if not (promotedKind in [stOrdinal, stFloat, stDateTime]) then
|
||||
raise ETypeException
|
||||
.CreateFmt('Operator %s requires Ordinal or Float, but got %s after promotion', [Op.ToString, promotedType.ToString]);
|
||||
Result := TTypes.Float;
|
||||
@@ -835,24 +853,23 @@ 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
|
||||
// Allow equality checks for Ordinal, Float, Keyword, Boolean, DateTime
|
||||
if not (promotedKind in [stOrdinal, stFloat, stKeyword, stBoolean, stDateTime]) then
|
||||
raise ETypeException.CreateFmt(
|
||||
'Comparison operator %s requires Ordinal, Float, or Keyword, but got %s after promotion',
|
||||
'Comparison operator %s requires scalar type, but got %s after promotion',
|
||||
[Op.ToString, promotedType.ToString]);
|
||||
// Result is always Ordinal (boolean)
|
||||
Result := TTypes.Ordinal;
|
||||
// Result is always Boolean
|
||||
Result := TTypes.Boolean;
|
||||
end;
|
||||
|
||||
TScalar.TBinaryOp.Less, TScalar.TBinaryOp.Greater, TScalar.TBinaryOp.LessOrEqual, TScalar.TBinaryOp.GreaterOrEqual:
|
||||
begin
|
||||
// Comparison requires Ordinal or Float (Keywords are not ordered)
|
||||
if not (promotedKind in [stOrdinal, stFloat]) then
|
||||
if not (promotedKind in [stOrdinal, stFloat, stDateTime]) then
|
||||
raise ETypeException.CreateFmt(
|
||||
'Comparison operator %s requires Ordinal or Float, but got %s after promotion',
|
||||
'Comparison operator %s requires ordered type (Ordinal, Float, DateTime), but got %s after promotion',
|
||||
[Op.ToString, promotedType.ToString]);
|
||||
Result := TTypes.Ordinal;
|
||||
Result := TTypes.Boolean;
|
||||
end;
|
||||
else
|
||||
raise ETypeException.Create('Unknown binary operator for type resolution.');
|
||||
@@ -880,10 +897,10 @@ begin
|
||||
|
||||
TScalar.TUnaryOp.Not:
|
||||
begin
|
||||
// Logical not only applies to Ordinal (booleans)
|
||||
if not (rightKind = stOrdinal) then
|
||||
// Logical not only applies to Boolean (or Ordinal if treated as bool)
|
||||
if not (rightKind in [stOrdinal, stBoolean]) then
|
||||
raise ETypeException.CreateFmt('Logical not cannot be applied to %s', [Right.ToString]);
|
||||
Result := TTypes.Ordinal;
|
||||
Result := TTypes.Boolean;
|
||||
end;
|
||||
else
|
||||
raise ETypeException.Create('Unknown unary operator for type resolution.');
|
||||
|
||||
Reference in New Issue
Block a user