Script Refactoring, ParseGet reads record fields

This commit is contained in:
Michael Schimmel
2026-01-07 00:28:38 +01:00
parent 8a29cf7f74
commit 0d3ccd1c63
3 changed files with 786 additions and 376 deletions
File diff suppressed because one or more lines are too long
+60 -13
View File
@@ -687,30 +687,77 @@ var
newBase, newIndex: IAstNode; newBase, newIndex: IAstNode;
baseType, elemType: IStaticType; baseType, elemType: IStaticType;
isOpt: Boolean; isOpt: Boolean;
idx: Integer;
key: IKeyword;
begin begin
I := Node.AsIndexer; I := Node.AsIndexer;
newBase := Accept(I.Base); newBase := Accept(I.Base);
newIndex := Accept(I.Index); newIndex := Accept(I.Index);
baseType := PrepareBaseType(newBase, isOpt);
// Unwrap optional types to check the underlying structure
baseType := PrepareBaseType(newBase, isOpt);
elemType := TTypes.Unknown; elemType := TTypes.Unknown;
if baseType.Kind = stSeries then
elemType := baseType.AsSeries.ElementType case baseType.Kind of
else if baseType.Kind = stRecordSeries then // Case 1: Accessing Tuples (Heterogeneous fixed-size lists)
elemType := TTypes.CreateRecord(baseType.AsRecord.Definition) // Static typing requires the index to be a constant integer to determine the specific element type.
else if baseType.Kind = stTuple then stTuple:
begin
// Tuple Indexing (requires constant index for strong typing!)
if (newIndex.Kind = akConstant) and (newIndex.AsConstant.Value.Kind = vkScalar) then
begin begin
var idx := newIndex.AsConstant.Value.AsScalar.Value.AsInt64; if (newIndex.Kind = akConstant) and (newIndex.AsConstant.Value.Kind = vkScalar) then
var tpl := baseType.AsTuple; begin
if (idx >= 0) and (idx < tpl.Count) then var intIdx := newIndex.AsConstant.Value.AsScalar.Value.AsInt64;
elemType := tpl.Elements[Integer(idx)]; 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;
end; end;
// Propagate nullability if the base object was optional
elemType := ApplyOptionality(elemType, isOpt); elemType := ApplyOptionality(elemType, isOpt);
Result := TAst.Indexer(Node.Identity, newBase, newIndex, elemType); Result := TAst.Indexer(Node.Identity, newBase, newIndex, elemType);
end; end;
+725 -362
View File
File diff suppressed because it is too large Load Diff