Macro expander integrated in binder
This commit is contained in:
+10
-32
@@ -38,6 +38,7 @@ type
|
||||
tkQuote, // '
|
||||
tkBacktick, // `
|
||||
tkTilde, // ~
|
||||
tkAt, // @
|
||||
tkIdentifier,
|
||||
tkNumber,
|
||||
tkString,
|
||||
@@ -251,6 +252,11 @@ begin
|
||||
Result.Kind := tkTilde;
|
||||
Advance;
|
||||
end;
|
||||
'@':
|
||||
begin
|
||||
Result.Kind := tkAt;
|
||||
Advance;
|
||||
end;
|
||||
'"':
|
||||
begin
|
||||
Result.Kind := tkString;
|
||||
@@ -351,7 +357,6 @@ begin
|
||||
|
||||
head := elements[0];
|
||||
|
||||
// Convert the rest of the list to an array for the factory functions
|
||||
SetLength(tailTokens, elements.Count - 1);
|
||||
SetLength(tailNodes, elements.Count - 1);
|
||||
for var i := 0 to High(tailNodes) do
|
||||
@@ -391,7 +396,6 @@ begin
|
||||
end
|
||||
else if SameText(head.Token.Text, 'defmacro') then
|
||||
begin
|
||||
// (defmacro name [params] body)
|
||||
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.');
|
||||
if elements[2].Params = nil then
|
||||
@@ -424,34 +428,10 @@ begin
|
||||
else if SameText(head.Token.Text, 'get') then
|
||||
Result := TAst.Indexer(tailNodes[0], tailNodes[1])
|
||||
else if (Length(head.Token.Text) > 1) and (head.Token.Text.StartsWith('.')) then
|
||||
Result := TAst.MemberAccess(tailNodes[0], TAst.Identifier(head.Token.Text.Substring(1)))
|
||||
else
|
||||
begin
|
||||
if Length(tailNodes) = 1 then
|
||||
begin
|
||||
for var op := Low(TScalar.TUnaryOp) to High(TScalar.TUnaryOp) do
|
||||
begin
|
||||
if head.Token.Text = op.ToString then
|
||||
begin
|
||||
Result := TAst.UnaryExpr(op, tailNodes[0]);
|
||||
break
|
||||
end;
|
||||
end;
|
||||
end
|
||||
else if Length(tailNodes) = 2 then
|
||||
begin
|
||||
for var op := Low(TScalar.TBinaryOp) to High(TScalar.TBinaryOp) do
|
||||
begin
|
||||
if head.Token.Text = op.ToString then
|
||||
begin
|
||||
Result := TAst.BinaryExpr(tailNodes[0], op, tailNodes[1]);
|
||||
break
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
Result := TAst.MemberAccess(tailNodes[0], TAst.Identifier(head.Token.Text.Substring(1)));
|
||||
end;
|
||||
|
||||
// If no special form matched, treat it as a generic function call.
|
||||
if Result = nil then
|
||||
Result := TAst.FunctionCall(head.Node, tailNodes);
|
||||
|
||||
@@ -480,14 +460,13 @@ begin
|
||||
tkTilde:
|
||||
begin
|
||||
NextToken;
|
||||
// Check for unquote-splicing ('~@')
|
||||
if (FCurrentToken.Kind = tkIdentifier) and (FCurrentToken.Text = '@') then
|
||||
if FCurrentToken.Kind = tkAt then
|
||||
begin
|
||||
NextToken;
|
||||
expr := ParseExpression;
|
||||
Result.Node := TAst.UnquoteSplicing(expr.Node);
|
||||
end
|
||||
else // It's a regular unquote ('~')
|
||||
else
|
||||
begin
|
||||
expr := ParseExpression;
|
||||
Result.Node := TAst.Unquote(expr.Node);
|
||||
@@ -498,7 +477,6 @@ begin
|
||||
begin
|
||||
NextToken;
|
||||
expr := ParseExpression;
|
||||
// A regular quote '(...) can be desugared into (quote (...))
|
||||
Result.Node := TAst.FunctionCall(TAst.Identifier('quote'), [expr.Node]);
|
||||
exit;
|
||||
end;
|
||||
|
||||
Reference in New Issue
Block a user