Fixed weak self method pointer bug
Better formatting of function calls in pretty printer
This commit is contained in:
@@ -45,10 +45,10 @@ end;
|
|||||||
|
|
||||||
destructor TUpvalueAnalyzer.Destroy;
|
destructor TUpvalueAnalyzer.Destroy;
|
||||||
begin
|
begin
|
||||||
FBoxedDeclarations.Free;
|
|
||||||
for var dict in FDeclarationMap.Values do
|
for var dict in FDeclarationMap.Values do
|
||||||
dict.Free;
|
dict.Free;
|
||||||
FDeclarationMap.Free;
|
FDeclarationMap.Free;
|
||||||
|
FBoxedDeclarations.Free;
|
||||||
inherited Destroy;
|
inherited Destroy;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
|||||||
@@ -193,46 +193,43 @@ begin
|
|||||||
|
|
||||||
var scopeDescriptor := boundNode.ScopeDescriptor;
|
var scopeDescriptor := boundNode.ScopeDescriptor;
|
||||||
var params := boundNode.Parameters;
|
var params := boundNode.Parameters;
|
||||||
|
|
||||||
// [weak] prevents a reference cycle since the closure captures itself for 'recur'.
|
|
||||||
var [weak] closure: TDataValue.TFunc;
|
|
||||||
var cNode: ILambdaExpressionNode := Node;
|
var cNode: ILambdaExpressionNode := Node;
|
||||||
|
|
||||||
|
// [unsafe] prevents a reference cycle since the closure captures itself for 'recur'.
|
||||||
|
var [unsafe] closure: TDataValue.TFunc;
|
||||||
closure :=
|
closure :=
|
||||||
TDataValue.TFunc(
|
function(const ArgValues: TArray<TDataValue>): TDataValue
|
||||||
function(const ArgValues: TArray<TDataValue>): TDataValue
|
var
|
||||||
var
|
lambdaScope: IExecutionScope;
|
||||||
lambdaScope: IExecutionScope;
|
bodyVisitor: IAstVisitor;
|
||||||
bodyVisitor: IAstVisitor;
|
i: Integer;
|
||||||
i: Integer;
|
adr: TResolvedAddress;
|
||||||
adr: TResolvedAddress;
|
begin
|
||||||
|
if (Length(ArgValues) <> Length(params)) then
|
||||||
|
raise EArgumentException.CreateFmt('Argument count mismatch: expected %d, got %d', [Length(params), Length(ArgValues)]);
|
||||||
|
|
||||||
|
// Create the new execution scope for this function call.
|
||||||
|
lambdaScope := TScope.CreateScope(closureScope, scopeDescriptor, capturedCells);
|
||||||
|
|
||||||
|
adr.Kind := akLocalOrParent;
|
||||||
|
adr.ScopeDepth := 0;
|
||||||
|
|
||||||
|
// Capture the closure itself in slot 0 for 'recur' to find it.
|
||||||
|
adr.SlotIndex := 0;
|
||||||
|
lambdaScope[adr] := closure;
|
||||||
|
|
||||||
|
// Populate the scope with the actual parameters passed to the function.
|
||||||
|
for i := 0 to High(ArgValues) do
|
||||||
begin
|
begin
|
||||||
if (Length(ArgValues) <> Length(params)) then
|
// Parameters in a bound lambda must be bound identifiers.
|
||||||
raise EArgumentException.CreateFmt('Argument count mismatch: expected %d, got %d', [Length(params), Length(ArgValues)]);
|
adr.SlotIndex := (params[i] as TBoundIdentifierNode).Address.SlotIndex;
|
||||||
|
lambdaScope[adr] := ArgValues[i];
|
||||||
|
end;
|
||||||
|
|
||||||
// Create the new execution scope for this function call.
|
// Create a visitor with the new scope and execute the lambda's body.
|
||||||
lambdaScope := TScope.CreateScope(closureScope, scopeDescriptor, capturedCells);
|
bodyVisitor := visitorFactory(lambdaScope);
|
||||||
|
Result := cNode.Body.Accept(bodyVisitor);
|
||||||
adr.Kind := akLocalOrParent;
|
end;
|
||||||
adr.ScopeDepth := 0;
|
|
||||||
|
|
||||||
// Capture the closure itself in slot 0 for 'recur' to find it.
|
|
||||||
adr.SlotIndex := 0;
|
|
||||||
lambdaScope[adr] := TDataValue(closure);
|
|
||||||
|
|
||||||
// Populate the scope with the actual parameters passed to the function.
|
|
||||||
for i := 0 to High(ArgValues) do
|
|
||||||
begin
|
|
||||||
// Parameters in a bound lambda must be bound identifiers.
|
|
||||||
adr.SlotIndex := (params[i] as TBoundIdentifierNode).Address.SlotIndex;
|
|
||||||
lambdaScope[adr] := ArgValues[i];
|
|
||||||
end;
|
|
||||||
|
|
||||||
// Create a visitor with the new scope and execute the lambda's body.
|
|
||||||
bodyVisitor := visitorFactory(lambdaScope);
|
|
||||||
Result := cNode.Body.Accept(bodyVisitor);
|
|
||||||
end
|
|
||||||
);
|
|
||||||
|
|
||||||
// The result of visiting a lambda node is the callable closure itself.
|
// The result of visiting a lambda node is the callable closure itself.
|
||||||
Result := closure;
|
Result := closure;
|
||||||
|
|||||||
@@ -398,13 +398,11 @@ begin
|
|||||||
begin
|
begin
|
||||||
if (Length(tailNodes) <> 3) or (tailTokens[0].Kind <> tkIdentifier) then
|
if (Length(tailNodes) <> 3) or (tailTokens[0].Kind <> tkIdentifier) then
|
||||||
raise Exception.Create('Syntax Error: ''defmacro'' requires a name, a parameter list, and a body.');
|
raise Exception.Create('Syntax Error: ''defmacro'' requires a name, a parameter list, and a body.');
|
||||||
if elements[2].Params = nil then
|
|
||||||
raise Exception.Create('Syntax Error: Expected a parameter list [...] after macro name.');
|
|
||||||
|
|
||||||
var macroName := IIdentifierNode(tailNodes[0]);
|
var macroName := IIdentifierNode(tailNodes[0]);
|
||||||
var macroParams := elements[2].Params;
|
var macroParams := elements[2].Params;
|
||||||
|
|
||||||
if tailTokens[2].Kind <> tkQuote then
|
if tailTokens[2].Kind <> tkBacktick then
|
||||||
raise Exception.Create('Syntax Error: Expected a quasiquote as macro body.');
|
raise Exception.Create('Syntax Error: Expected a quasiquote as macro body.');
|
||||||
|
|
||||||
var macroBody := IQuasiQuoteNode(tailNodes[2]);
|
var macroBody := IQuasiQuoteNode(tailNodes[2]);
|
||||||
@@ -421,8 +419,6 @@ begin
|
|||||||
begin
|
begin
|
||||||
if Length(tailNodes) <> 2 then
|
if Length(tailNodes) <> 2 then
|
||||||
raise Exception.Create('Syntax Error: ''fn'' requires a parameter list and a body.');
|
raise Exception.Create('Syntax Error: ''fn'' requires a parameter list and a body.');
|
||||||
if elements[1].Params = nil then
|
|
||||||
raise Exception.Create('Syntax Error: Expected a parameter list [...] after ''fn''.');
|
|
||||||
Result := TAst.LambdaExpr(elements[1].Params, tailNodes[1]);
|
Result := TAst.LambdaExpr(elements[1].Params, tailNodes[1]);
|
||||||
end
|
end
|
||||||
else if SameText(head.Token.Text, 'do') then
|
else if SameText(head.Token.Text, 'do') then
|
||||||
@@ -453,6 +449,7 @@ var
|
|||||||
expr: TExpr;
|
expr: TExpr;
|
||||||
begin
|
begin
|
||||||
// Handle reader macros.
|
// Handle reader macros.
|
||||||
|
Result.Token := FCurrentToken;
|
||||||
case FCurrentToken.Kind of
|
case FCurrentToken.Kind of
|
||||||
tkBacktick:
|
tkBacktick:
|
||||||
begin
|
begin
|
||||||
@@ -735,14 +732,11 @@ begin
|
|||||||
Indent;
|
Indent;
|
||||||
for arg in Node.Arguments do
|
for arg in Node.Arguments do
|
||||||
begin
|
begin
|
||||||
NewLine;
|
Append(' ');
|
||||||
arg.Accept(Self);
|
arg.Accept(Self);
|
||||||
end;
|
end;
|
||||||
Unindent;
|
Unindent;
|
||||||
|
|
||||||
if Length(Node.Arguments) > 0 then
|
|
||||||
NewLine;
|
|
||||||
|
|
||||||
Append(')');
|
Append(')');
|
||||||
Result := TDataValue.Void;
|
Result := TDataValue.Void;
|
||||||
end;
|
end;
|
||||||
@@ -762,12 +756,11 @@ begin
|
|||||||
Indent;
|
Indent;
|
||||||
for arg in Node.Arguments do
|
for arg in Node.Arguments do
|
||||||
begin
|
begin
|
||||||
NewLine;
|
Append(' ');
|
||||||
arg.Accept(Self);
|
arg.Accept(Self);
|
||||||
end;
|
end;
|
||||||
Unindent;
|
Unindent;
|
||||||
if Length(Node.Arguments) > 0 then
|
|
||||||
NewLine;
|
|
||||||
Append(')');
|
Append(')');
|
||||||
Result := TDataValue.Void;
|
Result := TDataValue.Void;
|
||||||
end;
|
end;
|
||||||
|
|||||||
Reference in New Issue
Block a user