Script Refactoring, ParseGet reads record fields
This commit is contained in:
@@ -687,30 +687,77 @@ var
|
||||
newBase, newIndex: IAstNode;
|
||||
baseType, elemType: IStaticType;
|
||||
isOpt: Boolean;
|
||||
idx: Integer;
|
||||
key: IKeyword;
|
||||
begin
|
||||
I := Node.AsIndexer;
|
||||
newBase := Accept(I.Base);
|
||||
newIndex := Accept(I.Index);
|
||||
baseType := PrepareBaseType(newBase, isOpt);
|
||||
|
||||
// Unwrap optional types to check the underlying structure
|
||||
baseType := PrepareBaseType(newBase, isOpt);
|
||||
elemType := TTypes.Unknown;
|
||||
if baseType.Kind = stSeries then
|
||||
elemType := baseType.AsSeries.ElementType
|
||||
else if baseType.Kind = stRecordSeries then
|
||||
elemType := TTypes.CreateRecord(baseType.AsRecord.Definition)
|
||||
else if baseType.Kind = stTuple then
|
||||
begin
|
||||
// Tuple Indexing (requires constant index for strong typing!)
|
||||
if (newIndex.Kind = akConstant) and (newIndex.AsConstant.Value.Kind = vkScalar) then
|
||||
|
||||
case baseType.Kind of
|
||||
// Case 1: Accessing Tuples (Heterogeneous fixed-size lists)
|
||||
// Static typing requires the index to be a constant integer to determine the specific element type.
|
||||
stTuple:
|
||||
begin
|
||||
var idx := newIndex.AsConstant.Value.AsScalar.Value.AsInt64;
|
||||
var tpl := baseType.AsTuple;
|
||||
if (idx >= 0) and (idx < tpl.Count) then
|
||||
elemType := tpl.Elements[Integer(idx)];
|
||||
if (newIndex.Kind = akConstant) and (newIndex.AsConstant.Value.Kind = vkScalar) then
|
||||
begin
|
||||
var intIdx := newIndex.AsConstant.Value.AsScalar.Value.AsInt64;
|
||||
var tpl := baseType.AsTuple;
|
||||
if (intIdx >= 0) and (intIdx < tpl.Count) then
|
||||
elemType := tpl.Elements[Integer(intIdx)];
|
||||
end;
|
||||
end;
|
||||
|
||||
// Case 2: Accessing Records or Record Series (Field Access)
|
||||
// Static typing requires the index to be a Keyword literal.
|
||||
stRecord, stRecordSeries:
|
||||
begin
|
||||
if newIndex.Kind = akKeyword then
|
||||
begin
|
||||
key := newIndex.AsKeyword.Value;
|
||||
var def := baseType.AsRecord.Definition;
|
||||
|
||||
idx := def.IndexOf(key);
|
||||
if idx >= 0 then
|
||||
begin
|
||||
var fieldType := TTypes.FromScalarKind(def[idx]);
|
||||
|
||||
// If we access a field on a Stream/Series of Records, the result is a Series of that field (Column).
|
||||
// If we access a field on a single Record, the result is the scalar value.
|
||||
if baseType.Kind = stRecordSeries then
|
||||
elemType := TTypes.CreateSeries(fieldType)
|
||||
else
|
||||
elemType := fieldType;
|
||||
end
|
||||
else if Assigned(FLog) then
|
||||
FLog.AddError(Format('Field ":%s" not found in record definition.', [key.Name]), Node);
|
||||
end
|
||||
else if Assigned(FLog) then
|
||||
FLog.AddError('Record access requires a constant keyword literal (e.g. :close).', Node);
|
||||
end;
|
||||
|
||||
// Case 3: Accessing Series via Integer Index (Row Access)
|
||||
// Returns the scalar element at the specific position.
|
||||
stSeries:
|
||||
begin
|
||||
elemType := baseType.AsSeries.ElementType;
|
||||
end;
|
||||
|
||||
// Case 4: Vector / Matrix (Homogeneous)
|
||||
// Accessing a Vector returns the ElementType.
|
||||
stVector:
|
||||
begin
|
||||
elemType := baseType.AsVector.ElementType;
|
||||
end;
|
||||
end;
|
||||
|
||||
// Propagate nullability if the base object was optional
|
||||
elemType := ApplyOptionality(elemType, isOpt);
|
||||
|
||||
Result := TAst.Indexer(Node.Identity, newBase, newIndex, elemType);
|
||||
end;
|
||||
|
||||
|
||||
+725
-362
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user