AST list refactoring
This commit is contained in:
@@ -318,7 +318,7 @@ var
|
||||
finalType: IStaticType;
|
||||
begin
|
||||
T := Node.AsTuple;
|
||||
var count := Length(T.Elements);
|
||||
var count := T.Count;
|
||||
|
||||
SetLength(newElements, count);
|
||||
SetLength(elementTypes, count);
|
||||
@@ -327,8 +327,13 @@ begin
|
||||
// Recursively type-check all elements first to determine their static types.
|
||||
for i := 0 to count - 1 do
|
||||
begin
|
||||
newElements[i] := Accept(T.Elements[i]);
|
||||
elementTypes[i] := newElements[i].AsTypedNode.StaticType;
|
||||
newElements[i] := Accept(T.Items[i]);
|
||||
// FIX: Ensure the node is typed before accessing StaticType.
|
||||
// Structural nodes (like RecordField) are NOT typed and might crash or return garbage.
|
||||
if newElements[i].IsTyped then
|
||||
elementTypes[i] := newElements[i].AsTypedNode.StaticType
|
||||
else
|
||||
elementTypes[i] := TTypes.Unknown;
|
||||
end;
|
||||
|
||||
// 2. Inference Logic: Tuple vs. Vector vs. Matrix
|
||||
@@ -343,6 +348,8 @@ begin
|
||||
isHomogeneous := True;
|
||||
|
||||
// Check for Homogeneity (Exact type equality of all elements)
|
||||
// Note: If any element is Unknown, we assume Heterogeneous (Tuple) unless all are unknown?
|
||||
// For now, Unknown breaks homogeneity.
|
||||
for i := 1 to count - 1 do
|
||||
begin
|
||||
if not firstType.IsEqual(elementTypes[i]) then
|
||||
@@ -352,7 +359,7 @@ begin
|
||||
end;
|
||||
end;
|
||||
|
||||
if isHomogeneous then
|
||||
if isHomogeneous and (firstType.Kind <> stUnknown) then
|
||||
begin
|
||||
// It is at least a Vector.
|
||||
// Check if it should be promoted to a Matrix (i.e., elements are Vectors or Matrices).
|
||||
@@ -418,10 +425,10 @@ end;
|
||||
function TTypeChecker.VisitRecurNode(const Node: IAstNode): IAstNode;
|
||||
var
|
||||
R: IRecurNode;
|
||||
args: IArgumentList;
|
||||
args: ITupleNode;
|
||||
begin
|
||||
R := Node.AsRecur;
|
||||
args := Accept(R.Arguments).AsArgumentList;
|
||||
args := Accept(R.Arguments).AsTuple;
|
||||
Result := TAst.Recur(Node.Identity, args, TTypes.Void);
|
||||
end;
|
||||
|
||||
@@ -508,10 +515,12 @@ function TTypeChecker.VisitBlockExpression(const Node: IAstNode): IAstNode;
|
||||
var
|
||||
newBlock: IBlockExpressionNode;
|
||||
blockType: IStaticType;
|
||||
exprs: IExpressionList;
|
||||
exprs: ITupleNode;
|
||||
i: Integer;
|
||||
begin
|
||||
// 1. Transform children via inherited logic
|
||||
// This delegates to TAstTransformer.VisitBlockExpression, which calls Visit(B.Expressions).
|
||||
// B.Expressions is a Tuple, so it routes to TTypeChecker.VisitTuple.
|
||||
var transformedNode := inherited VisitBlockExpression(Node);
|
||||
|
||||
// Safety check: Did the transformer return a node?
|
||||
@@ -527,13 +536,13 @@ begin
|
||||
// Check for NIL entries which indicate failed transformation of children
|
||||
for i := 0 to exprs.Count - 1 do
|
||||
begin
|
||||
if exprs[i] = nil then
|
||||
if exprs.Items[i] = nil then
|
||||
raise ECompilationFailed.Create(
|
||||
[TCompilerError.Create(elError, Format('Internal Error: Block expression #%d transformed to nil.', [i]), Node)]);
|
||||
end;
|
||||
|
||||
// The type of the block is the type of the last expression
|
||||
blockType := exprs[exprs.Count - 1].AsTypedNode.StaticType;
|
||||
blockType := exprs.Items[exprs.Count - 1].AsTypedNode.StaticType;
|
||||
end
|
||||
else
|
||||
begin
|
||||
@@ -555,6 +564,8 @@ var
|
||||
finalDescriptor: IScopeDescriptor;
|
||||
paramIdent: IIdentifierNode;
|
||||
injectedType: IStaticType;
|
||||
paramsTuple: ITupleNode;
|
||||
paramsAsNodes: TArray<IAstNode>;
|
||||
begin
|
||||
L := Node.AsLambdaExpression;
|
||||
|
||||
@@ -574,12 +585,13 @@ begin
|
||||
|
||||
FCurrentContext := TTypeContext.Create(FCurrentContext, L.Layout, upvalueTypes, nil);
|
||||
try
|
||||
SetLength(newParams, L.Parameters.Count);
|
||||
SetLength(paramTypes, L.Parameters.Count);
|
||||
paramsTuple := L.Parameters;
|
||||
SetLength(newParams, paramsTuple.Count);
|
||||
SetLength(paramTypes, paramsTuple.Count);
|
||||
|
||||
for i := 0 to L.Parameters.Count - 1 do
|
||||
for i := 0 to paramsTuple.Count - 1 do
|
||||
begin
|
||||
paramIdent := L.Parameters[i];
|
||||
paramIdent := paramsTuple.Items[i].AsIdentifier;
|
||||
injectedType := paramIdent.AsTypedNode.StaticType;
|
||||
|
||||
if injectedType.Kind = stUnknown then
|
||||
@@ -605,7 +617,12 @@ begin
|
||||
temp.Free;
|
||||
end;
|
||||
|
||||
var paramList := TParameterList.Create(newParams, L.Parameters.Identity);
|
||||
SetLength(paramsAsNodes, Length(newParams));
|
||||
for i := 0 to High(newParams) do
|
||||
paramsAsNodes[i] := newParams[i];
|
||||
|
||||
var paramList := TAst.Tuple(L.Parameters.Identity, paramsAsNodes);
|
||||
|
||||
Result :=
|
||||
TAst.LambdaExpr(Node.Identity, paramList, newBody, L.Layout, finalDescriptor, L.Upvalues, L.HasNestedLambdas, L.IsPure, methodType);
|
||||
end;
|
||||
@@ -619,17 +636,18 @@ var
|
||||
hasUnknownArgs: Boolean;
|
||||
bestSig: IMethodSignature;
|
||||
match: Boolean;
|
||||
newArgs: ITupleNode;
|
||||
begin
|
||||
newCall := inherited VisitFunctionCall(Node).AsFunctionCall;
|
||||
var newCallee := newCall.Callee;
|
||||
var newArgs := newCall.Arguments;
|
||||
newArgs := newCall.Arguments;
|
||||
|
||||
SetLength(argTypes, newArgs.Count);
|
||||
hasUnknownArgs := False;
|
||||
|
||||
for i := 0 to newArgs.Count - 1 do
|
||||
begin
|
||||
argTypes[i] := newArgs[i].AsTypedNode.StaticType;
|
||||
argTypes[i] := newArgs.Items[i].AsTypedNode.StaticType;
|
||||
if argTypes[i].Kind = stUnknown then
|
||||
hasUnknownArgs := True;
|
||||
end;
|
||||
@@ -707,7 +725,7 @@ begin
|
||||
elemType := TTypes.CreateRecord(baseType.AsRecord.Definition)
|
||||
else if baseType.Kind = stTuple then
|
||||
begin
|
||||
// NEW: Tuple Indexing (requires constant index for strong typing!)
|
||||
// Tuple Indexing (requires constant index for strong typing!)
|
||||
if (newIndex.Kind = akConstant) and (newIndex.AsConstant.Value.Kind = vkScalar) then
|
||||
begin
|
||||
var idx := newIndex.AsConstant.Value.AsScalar.Value.AsInt64;
|
||||
@@ -762,19 +780,29 @@ var
|
||||
isScalar: Boolean;
|
||||
valType: IStaticType;
|
||||
key: IKeyword;
|
||||
newFieldList: IRecordFieldList;
|
||||
newFields: ITupleNode;
|
||||
begin
|
||||
R := Node.AsRecordLiteral;
|
||||
newFieldList := inherited VisitRecordFieldList(R.Fields).AsRecordFieldList;
|
||||
|
||||
var count := newFieldList.Count;
|
||||
// FIX: Do NOT use inherited VisitRecordLiteral() here, because it expects an IRecordLiteralNode
|
||||
// but R.Fields is an ITupleNode. Using inherited would dispatch to VisitRecordLiteral with wrong type
|
||||
// or trigger recursive confusion.
|
||||
// Instead, directly visit the fields Tuple. This routes to TTypeChecker.VisitTuple.
|
||||
|
||||
newFields := Visit(R.Fields).AsTuple;
|
||||
|
||||
var count := newFields.Count;
|
||||
SetLength(fieldTypes, count);
|
||||
SetLength(scalarFieldTypes, count);
|
||||
isScalar := True;
|
||||
|
||||
for i := 0 to count - 1 do
|
||||
begin
|
||||
var field := newFieldList[i];
|
||||
// Note: Elements of the fields tuple are RecordFieldNodes.
|
||||
// RecordFieldNodes are NOT Typed (IAstTypedNode), they are structural.
|
||||
// So we cannot check .StaticType on the field itself.
|
||||
// We must check the .Value of the field.
|
||||
var field := newFields.Items[i].AsRecordField;
|
||||
key := field.Key.Value;
|
||||
valType := field.Value.AsTypedNode.StaticType;
|
||||
|
||||
@@ -815,7 +843,7 @@ begin
|
||||
resultType := TTypes.CreateGenericRecord(genericDef);
|
||||
end;
|
||||
|
||||
Result := TAst.RecordLiteral(Node.Identity, newFieldList, scalarDef, genericDef, resultType);
|
||||
Result := TAst.RecordLiteral(Node.Identity, newFields, scalarDef, genericDef, resultType);
|
||||
end;
|
||||
|
||||
function TTypeChecker.VisitCreateSeries(const Node: IAstNode): IAstNode;
|
||||
@@ -895,6 +923,7 @@ var
|
||||
paramTypes: TList<IStaticType>;
|
||||
lambda: ILambdaExpressionNode;
|
||||
newParams: TArray<IIdentifierNode>;
|
||||
newParamsAsNodes: TArray<IAstNode>;
|
||||
inferredType: IStaticType;
|
||||
begin
|
||||
P := Node.AsPipe;
|
||||
@@ -947,7 +976,7 @@ begin
|
||||
SetLength(newParams, lambda.Parameters.Count);
|
||||
for k := 0 to lambda.Parameters.Count - 1 do
|
||||
begin
|
||||
var oldP := lambda.Parameters[k];
|
||||
var oldP := lambda.Parameters.Items[k].AsIdentifier;
|
||||
var typeToInject :=
|
||||
if k < paramTypes.Count then paramTypes[k]
|
||||
else TTypes.Unknown;
|
||||
@@ -955,10 +984,15 @@ begin
|
||||
newParams[k] := TAst.Identifier(oldP.Identity.AsNamed, oldP.Address, typeToInject);
|
||||
end;
|
||||
|
||||
// Convert for Tuple Factory
|
||||
SetLength(newParamsAsNodes, Length(newParams));
|
||||
for k := 0 to High(newParams) do
|
||||
newParamsAsNodes[k] := newParams[k];
|
||||
|
||||
var preTypedLambda :=
|
||||
TAst.LambdaExpr(
|
||||
lambda.Identity,
|
||||
TParameterList.Create(newParams, lambda.Parameters.Identity),
|
||||
TAst.Tuple(lambda.Parameters.Identity, newParamsAsNodes),
|
||||
lambda.Body,
|
||||
lambda.Layout,
|
||||
lambda.Descriptor,
|
||||
|
||||
Reference in New Issue
Block a user