Keywords as basic scalar type

This commit is contained in:
Michael Schimmel
2025-10-31 21:15:08 +01:00
parent 8abec8e98f
commit 689dede600
9 changed files with 292 additions and 264 deletions
+22 -16
View File
@@ -381,6 +381,9 @@ begin
exit(False);
var otherDef := Other.Definition;
if (not Assigned(Self.FDefinition)) or (not Assigned(otherDef)) then
exit(False); // Should not happen if Kind is equal, but defensive check
if Length(Self.FDefinition.Fields) <> Length(otherDef.Fields) then
exit(False);
@@ -399,11 +402,14 @@ var
i: Integer;
begin
Result := GetKind.ToString + '{';
for i := 0 to High(FDefinition.Fields) do
if Assigned(FDefinition) then
begin
Result := Result + FDefinition.Fields[i].Key.Name + ': ' + FDefinition.Fields[i].Value.ToString;
if i < High(FDefinition.Fields) then
Result := Result + ', ';
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;
@@ -446,6 +452,7 @@ begin
case AKind of
TScalar.TKind.Ordinal: Result := FOrdinal;
TScalar.TKind.Float: Result := FFloat;
TScalar.TKind.Keyword: Result := FKeyword;
else
raise ETypeException.Create('Cannot convert invalid TScalar.TKind to TStaticType.');
end;
@@ -472,6 +479,9 @@ begin
if (Target.Kind = stVoid) and (Source.Kind = stMethod) then
exit(True);
if (Target.Kind = stOrdinal) and (Source.Kind = stKeyword) then
exit(True);
// TODO: Implement full assignment compatibility rules (e.g., for records/series)
Result := False;
@@ -499,11 +509,11 @@ begin
if (A.Kind = stOrdinal) and (B.Kind = stOrdinal) then
exit(TTypes.Ordinal);
// If types are identical and not numeric, return that type (e.g. Text + Text might be valid later)
// If types are identical (incl. Keyword, Text, etc.), return that type.
if A.IsEqual(B) then
exit(A);
// Cannot promote other combinations during basic inference
// Cannot promote other combinations (e.g., Ordinal and Keyword)
raise ETypeException.CreateFmt('Cannot promote types %s and %s', [A.ToString, B.ToString]);
end;
@@ -551,24 +561,18 @@ begin
TScalar.TBinaryOp.Equal, TScalar.TBinaryOp.NotEqual:
begin
// Allow equality checks for Keywords
if (promotedKind = stKeyword) then
begin
Result := TTypes.Ordinal;
exit;
end;
// Comparison requires Ordinal or Float, but *always* results in Ordinal (boolean)
if not (promotedKind in [stOrdinal, stFloat]) then
// Allow equality checks for Ordinal, Float, or Keyword
if not (promotedKind in [stOrdinal, stFloat, stKeyword]) then
raise ETypeException.CreateFmt(
'Comparison operator %s requires Ordinal, Float, or Keyword, but got %s after promotion',
[Op.ToString, promotedType.ToString]);
// Result is always Ordinal (boolean)
Result := TTypes.Ordinal;
end;
TScalar.TBinaryOp.Less, TScalar.TBinaryOp.Greater, TScalar.TBinaryOp.LessOrEqual, TScalar.TBinaryOp.GreaterOrEqual:
begin
// Comparison requires Ordinal or Float, but *always* results in Ordinal (boolean)
// Comparison requires Ordinal or Float (Keywords are not ordered)
if not (promotedKind in [stOrdinal, stFloat]) then
raise ETypeException.CreateFmt(
'Comparison operator %s requires Ordinal or Float, but got %s after promotion',
@@ -593,6 +597,7 @@ begin
case Op of
TScalar.TUnaryOp.Negate:
begin
// Negation requires Ordinal or Float
if not (rightKind in [stOrdinal, stFloat]) then
raise ETypeException.CreateFmt('Unary negation cannot be applied to %s', [Right.ToString]);
Result := Right; // Negation preserves type
@@ -600,6 +605,7 @@ begin
TScalar.TUnaryOp.Not:
begin
// Logical not only applies to Ordinal (booleans)
if not (rightKind = stOrdinal) then
raise ETypeException.CreateFmt('Logical not cannot be applied to %s', [Right.ToString]);
Result := TTypes.Ordinal;