Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Use syntax-macros for builtin macros #8

Merged
merged 1 commit into from
Dec 6, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions src/Visp.Compiler/CoreParser.fs
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ module CoreParser =
fileWriter.Write(template.Trim())
fileWriter.WriteLine()
let writer = Visp.Syntax.SynWriter.mkSynWriter fileWriter
let file = transformFile file
Visp.Syntax.SynWriter.Write.writeParsedFile writer file
fileWriter.WriteLine()

Expand All @@ -58,6 +59,7 @@ let state = { Todo = () }

let writer = Visp.Syntax.SynWriter.mkSynWriter fileWriter

let file = transformFile file
Visp.Syntax.SynWriter.Write.writeParsedFile writer file

fileWriter.WriteLine()
Expand Down
12 changes: 1 addition & 11 deletions src/Visp.Compiler/Syntax/SynWriter.fs
Original file line number Diff line number Diff line change
Expand Up @@ -1270,16 +1270,6 @@ module Write =

string w "] |> HashMap.ofList"


let private tfs =
[| Visp.Compiler.Transforms.SyntaxMacros.expand
Visp.Compiler.Transforms.QuasiquoteExpander.expand
Visp.Compiler.Transforms.BuiltinMacros.expand
Visp.Compiler.Transforms.Common.transformLambdaShortHands |]

let expandExpr expr =
Visp.Compiler.Transforms.Helpers.runTransforms tfs expr

let writeParsedFile w (ParsedFile(fragments)) =
let rec writeModuleDecls w (decls: SynModuleDecl list) =
match decls with
Expand All @@ -1303,7 +1293,7 @@ module Write =
()
| SynModuleDecl.ModuleAbbrev _ -> ()
| SynModuleDecl.Require _ -> ()
| SynModuleDecl.Expr(ex, _) -> writeExpr w WriteState.Body (expandExpr ex)
| SynModuleDecl.Expr(ex, _) -> writeExpr w WriteState.Body ex
| SynModuleDecl.Open(target, range) ->
indent w
lineof w range
Expand Down
3 changes: 0 additions & 3 deletions src/Visp.Compiler/Transforms/BuiltinMacroExpander.fs
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,6 @@ open Visp.Compiler.Transforms
let rec expand (expr: SynExpr) =
let inner expr =
match expr with
| SynExpr.FunctionCall(Patterns.SymbolWith "and", args, range) -> handleAnd args range
| SynExpr.FunctionCall(Patterns.SymbolWith "or", args, range) -> handleOr args range
| SynExpr.FunctionCall(Patterns.SymbolWith "cond", args, range) -> handleCond args range
| SynExpr.ThreadLast(items, range) -> SynExpr.ThreadLast(handleThreadables items, range)
| _ -> expr

Expand Down
92 changes: 84 additions & 8 deletions src/Visp.Compiler/Transforms/SyntaxMacroExpander.fs
Original file line number Diff line number Diff line change
Expand Up @@ -103,11 +103,38 @@ let closeToken =
| SynListKind.HashSet -> RBRACE
| SynListKind.AttributeList -> RBRACKET

[<RequireQualifiedAccess>]
type private TokenizeMode =
| Default
| Macro

type private TokenizeArgs =
{ mutable depth: int32
mutable mode: TokenizeMode }

member t.TryNest() =
if t.mode = TokenizeMode.Macro then
t.depth <- t.depth + 1

member t.StartMacro() =
t.mode <- TokenizeMode.Macro
t.TryNest()

member t.TryUnnest() =
if t.mode = TokenizeMode.Macro then
t.depth <- t.depth - 1

if t.depth <= 0 then
t.mode <- TokenizeMode.Default
t.depth <- 0

let private evaluatePatterns
(body: SynMacroBody)
(pats: Dictionary<string, BoundPatternBody>)
(range: range)
: SynExpr =


let findPattern bod (pats: Dictionary<string, BoundPatternBody>) =
match bod with
| SynMacroBody.Symbol sym ->
Expand All @@ -117,22 +144,30 @@ let private evaluatePatterns
| _ -> None

let rec tokenize
(f: SynMacroBody)
(pats: Dictionary<string, BoundPatternBody>)
(res: ResizeArray<token>)
(args: TokenizeArgs)
(f: SynMacroBody)
=

let bound_tokenize = tokenize pats res args

match findPattern f pats with
| Some(pat) ->
match pat with
| BoundPatternBody.Item(it) -> tokenize it pats res
| BoundPatternBody.List(lst) -> lst |> List.iter (fun ex -> tokenize ex pats res)
| BoundPatternBody.Item(it) -> bound_tokenize it
| BoundPatternBody.List(lst) -> lst |> List.iter bound_tokenize

| None ->
match f with
| SynMacroBody.List(kind, lst, _) ->
res.Add(openToken kind)
lst |> List.iter (fun ex -> tokenize ex pats res)

args.TryNest()

lst |> List.iter bound_tokenize

args.TryUnnest()
res.Add(closeToken kind)

| SynMacroBody.Trivia(kind, _) ->
Expand All @@ -158,12 +193,27 @@ let private evaluatePatterns

()

| SynMacroBody.Symbol sym -> res.Add(LexHelpers.symbolOrKeyword sym.Text)
| SynMacroBody.Symbol sym ->
match args.mode with
| TokenizeMode.Macro -> res.Add(SYMBOL sym.Text)
| TokenizeMode.Default ->
let tok = LexHelpers.symbolOrKeyword sym.Text

match tok with
| MACRO_NAME _
| SYNTAX_MACRO -> args.StartMacro()
| _ -> ()

res.Add(tok)

use pooled = PooledList.GetPooled<token>()
let res = pooled.Value

tokenize body pats res
let args =
{ depth = 0
mode = TokenizeMode.Default }

tokenize pats res args body

// Dummy lexbuffer
let lexbuf = LexBuffer<_>.FromString ""
Expand Down Expand Up @@ -198,6 +248,8 @@ let private evaluatePatterns
try
let result = raw_expr getTokens lexbuf

// printfn "result\n%A" result

result
with :? ParseHelpers.SyntaxError as syn ->
LexHelpers.outputSyntaxError syn
Expand All @@ -218,6 +270,20 @@ let private expandSynMacro (SynMacro(_, cases, _) as macro) (SynMacroCall(_, arg
result
| None -> failwith "no matching pattern"

let private hasMacroCall (expr: SynExpr) =
let mutable res = false

// TODO: Provide some iterators for doing this so we can stop earlY?
expr
|> Helpers.transform (function
| SynExpr.SyntaxMacroCall _ as ex ->
res <- true
ex
| it -> it)
|> ignore

res

let expand (expr: SynExpr) =

let collect =
Expand All @@ -233,13 +299,23 @@ let expand (expr: SynExpr) =
)
| it -> it

let mutable didExpand = true

let expandMacros =
function
| SynExpr.SyntaxMacroCall(SynMacroCall(name = name) as call) ->
match macroTable.TryGetMacro(Syntax.textOfSymbol name) with
| Some(syn) -> expandSynMacro syn call
| Some(syn) ->
didExpand <- true
expandSynMacro syn call
| None -> failwithf "macro: %A not found" name
| it -> it

// TODO: this should continue expanding until no more macro invocations are available
[ collect; expandMacros ] |> Helpers.runTransforms1 expr

let mutable expr = expr |> Helpers.transform collect

while hasMacroCall expr do
expr <- Helpers.transform expandMacros expr

expr
Loading