From 191ef325af74c2d53fdb4caa5d2fefa372098fa1 Mon Sep 17 00:00:00 2001 From: Ville Penttinen Date: Sat, 9 Dec 2023 05:19:58 +0100 Subject: [PATCH 1/3] do not indent Begin body expressions --- src/Visp.Compiler/Syntax/SynWriter.fs | 13 +++++++++- ...macros_cond-macro-1.can parse.verified.txt | 26 +++++++++---------- 2 files changed, 25 insertions(+), 14 deletions(-) diff --git a/src/Visp.Compiler/Syntax/SynWriter.fs b/src/Visp.Compiler/Syntax/SynWriter.fs index df5dfc7..02f9bbf 100644 --- a/src/Visp.Compiler/Syntax/SynWriter.fs +++ b/src/Visp.Compiler/Syntax/SynWriter.fs @@ -410,6 +410,14 @@ module Write = () + let private writeBodyNoIndent<'a> + (w: SynWriter) + (wrt: SynWriter -> WriteState -> 'a -> unit) + (items: seq<'a>) + = + newline w + writeSeq w WriteState.Body newline wrt items + let private writeBody<'a> (w: SynWriter) (wrt: SynWriter -> WriteState -> 'a -> unit) @@ -628,7 +636,10 @@ module Write = if kind = BeginKind.Do then char w '(' - writeBody w writeExpr expr + if kind = BeginKind.Do then + writeBody w writeExpr expr + else + writeBodyNoIndent w writeExpr expr if kind = BeginKind.Do then char w ')' diff --git a/tests/Visp.Compiler.UnitTests/snapshots/tests_macros_cond-macro-1.can parse.verified.txt b/tests/Visp.Compiler.UnitTests/snapshots/tests_macros_cond-macro-1.can parse.verified.txt index 947307c..59a8c59 100644 --- a/tests/Visp.Compiler.UnitTests/snapshots/tests_macros_cond-macro-1.can parse.verified.txt +++ b/tests/Visp.Compiler.UnitTests/snapshots/tests_macros_cond-macro-1.can parse.verified.txt @@ -15,11 +15,11 @@ let visp_result_todo = then // line 22 @"cond-macro-1.visp" - // line 22 @"cond-macro-1.visp" - printfn ("body here1") - // line 22 @"cond-macro-1.visp" - printfn ("body here2") - () + // line 22 @"cond-macro-1.visp" + printfn ("body here1") + // line 22 @"cond-macro-1.visp" + printfn ("body here2") + () else // line 22 @"cond-macro-1.visp" if CoreMethods.isTruthy( @@ -27,10 +27,10 @@ let visp_result_todo = then // line 22 @"cond-macro-1.visp" - // line 22 @"cond-macro-1.visp" - printfn ("here1") - // line 22 @"cond-macro-1.visp" - printfn ("here2") + // line 22 @"cond-macro-1.visp" + printfn ("here1") + // line 22 @"cond-macro-1.visp" + printfn ("here2") else // line 22 @"cond-macro-1.visp" if CoreMethods.isTruthy( @@ -38,10 +38,10 @@ let visp_result_todo = then // line 22 @"cond-macro-1.visp" - // line 22 @"cond-macro-1.visp" - printfn ("default1") - // line 22 @"cond-macro-1.visp" - printfn ("default2") + // line 22 @"cond-macro-1.visp" + printfn ("default1") + // line 22 @"cond-macro-1.visp" + printfn ("default2") else // line 22 @"cond-macro-1.visp" failwith ("unreachable") From 4f4b61bad4167f04e236dafb98c7b2f61de24e10 Mon Sep 17 00:00:00 2001 From: Ville Penttinen Date: Sat, 9 Dec 2023 05:28:13 +0100 Subject: [PATCH 2/3] Add experimental support for macro "functions" --- .../Transforms/SyntaxMacroExpander.fs | 97 ++++++++++++++----- .../ParsingTests.generated.fs | 5 + ...cros_struct-macro-2.can parse.verified.txt | 51 ++++++++++ .../ExecutionTests.generated.fs | 5 + ...os_struct-macro-2.can execute.verified.txt | 6 ++ visp/tests/macros/struct-macro-2.visp | 32 ++++++ 6 files changed, 174 insertions(+), 22 deletions(-) create mode 100644 tests/Visp.Compiler.UnitTests/snapshots/tests_macros_struct-macro-2.can parse.verified.txt create mode 100644 tests/Visp.ExecutionTests/snapshots/tests_macros_struct-macro-2.can execute.verified.txt create mode 100644 visp/tests/macros/struct-macro-2.visp diff --git a/src/Visp.Compiler/Transforms/SyntaxMacroExpander.fs b/src/Visp.Compiler/Transforms/SyntaxMacroExpander.fs index 938bc7e..8250b3f 100644 --- a/src/Visp.Compiler/Transforms/SyntaxMacroExpander.fs +++ b/src/Visp.Compiler/Transforms/SyntaxMacroExpander.fs @@ -25,6 +25,18 @@ let (|DiscardPredicate|Not|) (pat: SynMacroPat) = | SynMacroPat.List([ MatchingText "?discard" true ], _) -> DiscardPredicate | _ -> Not +let (|SymText|_|) (pat: SynMacroBody) = + match pat with + | SynMacroBody.Symbol it -> Some(it.Text) + | _ -> None + +let (|SpecialCall|_|) call (pat: SynMacroBody) = + match pat with + | SynMacroBody.List(k, (SynMacroBody.Symbol sym) :: rest, r) when sym.Text = call -> + Some(k, rest, r) + | _ -> None + + let rec private matchesPat (args: SynMacroBody list) (pats: SynMacroPat list) = // printfn "looking for\n%A\nin\n%A" args pats // TODO: Determine pattern matching @@ -142,14 +154,12 @@ type private TokenizeArgs = t.mode <- TokenizeMode.Default t.depth <- 0 -let private evaluatePatterns - (body: SynMacroBody) - (pats: Dictionary) - (range: range) - : SynExpr = +type private BoundPats = Dictionary + +let private evaluatePatterns (body: SynMacroBody) (pats: BoundPats) (range: range) : SynExpr = - let findPattern bod (pats: Dictionary) = + let findPattern (pats: BoundPats) bod = match bod with | SynMacroBody.Symbol sym -> match pats.TryGetValue(sym.Text) with @@ -157,23 +167,77 @@ let private evaluatePatterns | true, n -> Some(n) | _ -> None + let rec getBody (pats: BoundPats) bod = + match findPattern pats bod with + | Some(it) -> + match it with + | BoundPatternBody.Item it -> getBody pats it + | BoundPatternBody.List lst -> lst |> List.map (getBody pats) |> List.concat + | None -> [ bod ] + let rec tokenize - (pats: Dictionary) + (pats: BoundPats) (res: ResizeArray) (args: TokenizeArgs) - (f: SynMacroBody) + (currentBody: SynMacroBody) = + let handleSymbol args text = + match args.mode with + | TokenizeMode.Macro -> res.Add(SYMBOL text) + | TokenizeMode.Default -> + let tok = LexHelpers.symbolOrKeyword text + + match tok with + | MACRO_NAME _ + | SYNTAX_MACRO -> args.StartMacro() + | _ -> () + + res.Add(tok) + let bound_tokenize = tokenize pats res args - match findPattern f pats with + match findPattern pats currentBody with | Some(pat) -> match pat with | BoundPatternBody.Item(it) -> bound_tokenize it | BoundPatternBody.List(lst) -> lst |> List.iter bound_tokenize | None -> - match f with + match currentBody with + | SpecialCall "m-concat-id" (_, call_args, _) -> + match call_args with + | arg1 :: arg2 :: [] -> + match ((getBody pats arg1), (getBody pats arg2)) with + | ([ SymText lhs ], [ SymText rhs ]) -> handleSymbol args (lhs + rhs) + | _ -> failwithf "todo concat id %A" call_args + + | _ -> failwithf "todo concat id %A" call_args + + () + | SpecialCall "m-map" (_, call_args, _) -> + match call_args with + | (SymText method) :: (SynMacroBody.List(_, list, _)) :: [] -> + let argz = list |> List.map (getBody pats) |> List.concat + + match method with + | "m-name" -> + let names = + argz + |> List.choose (function + | SynMacroBody.Symbol it -> Some(it) + | SynMacroBody.List(_, SynMacroBody.Symbol it :: _, _) -> Some(it) + | SynMacroBody.Ellipsis _ -> None + | it -> failwithf "unsupported m-map %A" it) + |> List.map _.Text + + names |> List.iter (handleSymbol args) + + | _ -> failwithf "unsupported m-map method: %A %A" method call_args + + | _ -> failwithf "todo concat id %A" call_args + + () | SynMacroBody.List(kind, lst, _) -> res.Add(openToken kind) @@ -218,18 +282,7 @@ let private evaluatePatterns () - | 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) + | SynMacroBody.Symbol sym -> handleSymbol args sym.Text use pooled = PooledList.GetPooled() let res = pooled.Value diff --git a/tests/Visp.Compiler.UnitTests/ParsingTests.generated.fs b/tests/Visp.Compiler.UnitTests/ParsingTests.generated.fs index d36d8cf..bc75800 100644 --- a/tests/Visp.Compiler.UnitTests/ParsingTests.generated.fs +++ b/tests/Visp.Compiler.UnitTests/ParsingTests.generated.fs @@ -210,6 +210,11 @@ module ``tests_macros_cond-macro-1`` = [] let ``can parse`` () = TestUtils.runTest "tests/macros/cond-macro-1.visp" +[] +module ``tests_macros_struct-macro-2`` = + [] + let ``can parse`` () = TestUtils.runTest "tests/macros/struct-macro-2.visp" + [] module ``tests_macros_chars-in-macros-0`` = [] diff --git a/tests/Visp.Compiler.UnitTests/snapshots/tests_macros_struct-macro-2.can parse.verified.txt b/tests/Visp.Compiler.UnitTests/snapshots/tests_macros_struct-macro-2.can parse.verified.txt new file mode 100644 index 0000000..51fe013 --- /dev/null +++ b/tests/Visp.Compiler.UnitTests/snapshots/tests_macros_struct-macro-2.can parse.verified.txt @@ -0,0 +1,51 @@ +// This file is auto-generated + +#nowarn "0020" // unused results from functions + +open Visp.Runtime.Library + +let state = { Todo = () } +// line 8 @"struct-macro-2.visp" +let macro_MyStruct2 = "__MACRO_INIT__" +// line 22 @"struct-macro-2.visp" + +[] +// line 22 @"struct-macro-2.visp" +type Example (x: int, y: int) = + // line 22 @"struct-macro-2.visp" + member _.X = + x + // line 22 @"struct-macro-2.visp" + member _.Y = + y + // line 22 @"struct-macro-2.visp" + member d.Sum () = + // line 22 @"struct-macro-2.visp" + CoreMethods.``add``((d.X), (d.Y)) + +// line 22 @"struct-macro-2.visp" +let mkExample x y = + // line 22 @"struct-macro-2.visp" + (new Example(x, y)) + +// line 28 @"struct-macro-2.visp" +let instance = + // line 28 @"struct-macro-2.visp" + mkExample (1) (2) +// line 30 @"struct-macro-2.visp" +printfn ("Example Struct is %A") (instance) +// line 31 @"struct-macro-2.visp" +printfn ("Example IsValueType %A") (instance + |> (fun a1 -> + // line 31 @"struct-macro-2.visp" + (a1.GetType())) + |> (fun a1 -> + // line 31 @"struct-macro-2.visp" + (a1.IsValueType))) +// line 32 @"struct-macro-2.visp" +let visp_result_todo = + // line 32 @"struct-macro-2.visp" + printfn ("Example Result is %i") ((instance.Sum())) +// line 32 @"struct-macro-2.visp" +printfn ("%A") (visp_result_todo) + diff --git a/tests/Visp.ExecutionTests/ExecutionTests.generated.fs b/tests/Visp.ExecutionTests/ExecutionTests.generated.fs index 58f5036..db0ace0 100644 --- a/tests/Visp.ExecutionTests/ExecutionTests.generated.fs +++ b/tests/Visp.ExecutionTests/ExecutionTests.generated.fs @@ -210,6 +210,11 @@ module ``tests_macros_cond-macro-1`` = [] let ``can execute`` () = TestUtils.runTest "tests/macros/cond-macro-1.visp" +[] +module ``tests_macros_struct-macro-2`` = + [] + let ``can execute`` () = TestUtils.runTest "tests/macros/struct-macro-2.visp" + [] module ``tests_macros_chars-in-macros-0`` = [] diff --git a/tests/Visp.ExecutionTests/snapshots/tests_macros_struct-macro-2.can execute.verified.txt b/tests/Visp.ExecutionTests/snapshots/tests_macros_struct-macro-2.can execute.verified.txt new file mode 100644 index 0000000..58d297e --- /dev/null +++ b/tests/Visp.ExecutionTests/snapshots/tests_macros_struct-macro-2.can execute.verified.txt @@ -0,0 +1,6 @@ +Example Struct is struct-macro-2+Example +Example IsValueType true +Example Result is 3 +() + +ExitCode: 0 diff --git a/visp/tests/macros/struct-macro-2.visp b/visp/tests/macros/struct-macro-2.visp new file mode 100644 index 0000000..333cb22 --- /dev/null +++ b/visp/tests/macros/struct-macro-2.visp @@ -0,0 +1,32 @@ +;; Copyright 2023 Ville Penttinen +;; Distributed under the MIT License. +;; https://github.com/vipentti/visp-fs/blob/main/LICENSE.md +;; +;; for basic syntax highlighting +;; vim: set syntax=clojure: + +(syntax-macro MyStruct2 + [(_ typ (arg ctor ...) body ...) + (begin + (#[Struct] + type typ (arg ctor ...) + body ... + ) + + (fn (m-concat-id mk typ) + ((m-map m-name (arg ctor ...))) + (new typ (m-map m-name (arg ctor ...)))) + ) + ]) + +(MyStruct2 Example ([x: int] [y: int]) + (member _.X x) + (member _.Y y) + + (member fn d.Sum () (+ (+X d) (+Y d)))) + +(let instance (mkExample 1 2)) + +(printfn "Example Struct is %A" instance) +(printfn "Example IsValueType %A" (->> instance .GetType +IsValueType)) +(printfn "Example Result is %i" (.Sum instance)) From 6acdc3d525f3833d60d1502905aaea4d39eed693 Mon Sep 17 00:00:00 2001 From: Ville Penttinen Date: Sat, 9 Dec 2023 05:43:06 +0100 Subject: [PATCH 3/3] Allow arithmetic operators in macros (+,-,/ and *) --- src/Visp.Compiler/Syntax/LexHelpers.fs | 4 +++ .../ParsingTests.generated.fs | 5 ++++ ...acros_count-exprs-0.can parse.verified.txt | 26 +++++++++++++++++++ ...os_struct-example-1.can parse.verified.txt | 10 ++++--- ...cros_struct-macro-0.can parse.verified.txt | 3 ++- ...cros_struct-macro-2.can parse.verified.txt | 3 ++- ...cros_syntax-macro-0.can parse.verified.txt | 3 ++- ...cros_syntax-macro-2.can parse.verified.txt | 6 +++-- .../ExecutionTests.generated.fs | 5 ++++ ...ros_count-exprs-0.can execute.verified.txt | 4 +++ visp/tests/macros/count-exprs-0.visp | 17 ++++++++++++ 11 files changed, 77 insertions(+), 9 deletions(-) create mode 100644 tests/Visp.Compiler.UnitTests/snapshots/tests_macros_count-exprs-0.can parse.verified.txt create mode 100644 tests/Visp.ExecutionTests/snapshots/tests_macros_count-exprs-0.can execute.verified.txt create mode 100644 visp/tests/macros/count-exprs-0.visp diff --git a/src/Visp.Compiler/Syntax/LexHelpers.fs b/src/Visp.Compiler/Syntax/LexHelpers.fs index 560fa4d..7bd1f0d 100644 --- a/src/Visp.Compiler/Syntax/LexHelpers.fs +++ b/src/Visp.Compiler/Syntax/LexHelpers.fs @@ -241,6 +241,10 @@ let specialSymbol (s: string) = | it when it.Length > 1 && it[0] = '+' && isLetter it[1] -> Some(PROP_PLUS s) | it when it.Length > 1 && it[0] = '.' && isLetter it[1] -> Some(DOT_METHOD s) | it when it.Length > 1 && it[0] = '-' && isLetter it[1] -> Some(APPLY_METHOD s) + | "+" -> Some(OP_PLUS) + | "-" -> Some(OP_MINUS) + | "/" -> Some(OP_DIV) + | "*" -> Some(OP_MULT) | _ -> None let symbolOrKeyword (s: string) = diff --git a/tests/Visp.Compiler.UnitTests/ParsingTests.generated.fs b/tests/Visp.Compiler.UnitTests/ParsingTests.generated.fs index bc75800..bbb93a6 100644 --- a/tests/Visp.Compiler.UnitTests/ParsingTests.generated.fs +++ b/tests/Visp.Compiler.UnitTests/ParsingTests.generated.fs @@ -195,6 +195,11 @@ module ``tests_macros_struct-example-1`` = [] let ``can parse`` () = TestUtils.runTest "tests/macros/struct-example-1.visp" +[] +module ``tests_macros_count-exprs-0`` = + [] + let ``can parse`` () = TestUtils.runTest "tests/macros/count-exprs-0.visp" + [] module ``tests_macros_syntax-macro-2`` = [] diff --git a/tests/Visp.Compiler.UnitTests/snapshots/tests_macros_count-exprs-0.can parse.verified.txt b/tests/Visp.Compiler.UnitTests/snapshots/tests_macros_count-exprs-0.can parse.verified.txt new file mode 100644 index 0000000..79673d7 --- /dev/null +++ b/tests/Visp.Compiler.UnitTests/snapshots/tests_macros_count-exprs-0.can parse.verified.txt @@ -0,0 +1,26 @@ +// This file is auto-generated + +#nowarn "0020" // unused results from functions + +open Visp.Runtime.Library + +let state = { Todo = () } +// line 8 @"count-exprs-0.visp" +let macro_CountExprsExampleTest1 = "__MACRO_INIT__" +// line 15 @"count-exprs-0.visp" +let exprCount = + // line 15 @"count-exprs-0.visp" + (1) + + ((1) + + ((1) + + ((1) + + ((1) + + ((1) + + (1)))))) +// line 17 @"count-exprs-0.visp" +let visp_result_todo = + // line 17 @"count-exprs-0.visp" + printfn ("exprs: %A") (exprCount) +// line 17 @"count-exprs-0.visp" +printfn ("%A") (visp_result_todo) + diff --git a/tests/Visp.Compiler.UnitTests/snapshots/tests_macros_struct-example-1.can parse.verified.txt b/tests/Visp.Compiler.UnitTests/snapshots/tests_macros_struct-example-1.can parse.verified.txt index 407b808..3b91dde 100644 --- a/tests/Visp.Compiler.UnitTests/snapshots/tests_macros_struct-example-1.can parse.verified.txt +++ b/tests/Visp.Compiler.UnitTests/snapshots/tests_macros_struct-example-1.can parse.verified.txt @@ -17,11 +17,12 @@ type Range (start: int64, len: int64) = // line 8 @"struct-example-1.visp" member _.End = // line 8 @"struct-example-1.visp" - CoreMethods.``add``(start, len) + (start) + + (len) // line 8 @"struct-example-1.visp" member d.Offset v = // line 8 @"struct-example-1.visp" - CoreMethods.``sub``(v, (d.Start)) + v - (d.Start) // line 8 @"struct-example-1.visp" member d.Contains v = @@ -78,13 +79,14 @@ type SourceDestMap (dest: int64, src: int64, len: int64) = ((d.Src).Contains src)) then // line 29 @"struct-example-1.visp" - CoreMethods.``add``(d + (d |> (fun a1 -> // line 29 @"struct-example-1.visp" (a1.Dest)) |> (fun a1 -> // line 29 @"struct-example-1.visp" - (a1.Start)), ((d.Src).Offset src)) + (a1.Start))) + + (((d.Src).Offset src)) else // line 29 @"struct-example-1.visp" if CoreMethods.isTruthy( diff --git a/tests/Visp.Compiler.UnitTests/snapshots/tests_macros_struct-macro-0.can parse.verified.txt b/tests/Visp.Compiler.UnitTests/snapshots/tests_macros_struct-macro-0.can parse.verified.txt index 5a0de22..0c1851e 100644 --- a/tests/Visp.Compiler.UnitTests/snapshots/tests_macros_struct-macro-0.can parse.verified.txt +++ b/tests/Visp.Compiler.UnitTests/snapshots/tests_macros_struct-macro-0.can parse.verified.txt @@ -19,7 +19,8 @@ type Example (x: int, y: int) = // line 16 @"struct-macro-0.visp" member d.Sum () = // line 16 @"struct-macro-0.visp" - CoreMethods.``add``((d.X), (d.Y)) + ((d.X)) + + ((d.Y)) // line 22 @"struct-macro-0.visp" let instance = diff --git a/tests/Visp.Compiler.UnitTests/snapshots/tests_macros_struct-macro-2.can parse.verified.txt b/tests/Visp.Compiler.UnitTests/snapshots/tests_macros_struct-macro-2.can parse.verified.txt index 51fe013..a4f9701 100644 --- a/tests/Visp.Compiler.UnitTests/snapshots/tests_macros_struct-macro-2.can parse.verified.txt +++ b/tests/Visp.Compiler.UnitTests/snapshots/tests_macros_struct-macro-2.can parse.verified.txt @@ -21,7 +21,8 @@ type Example (x: int, y: int) = // line 22 @"struct-macro-2.visp" member d.Sum () = // line 22 @"struct-macro-2.visp" - CoreMethods.``add``((d.X), (d.Y)) + ((d.X)) + + ((d.Y)) // line 22 @"struct-macro-2.visp" let mkExample x y = diff --git a/tests/Visp.Compiler.UnitTests/snapshots/tests_macros_syntax-macro-0.can parse.verified.txt b/tests/Visp.Compiler.UnitTests/snapshots/tests_macros_syntax-macro-0.can parse.verified.txt index 018e60e..0e9a137 100644 --- a/tests/Visp.Compiler.UnitTests/snapshots/tests_macros_syntax-macro-0.can parse.verified.txt +++ b/tests/Visp.Compiler.UnitTests/snapshots/tests_macros_syntax-macro-0.can parse.verified.txt @@ -15,7 +15,8 @@ let name arg = match arg with | (a, b) -> // line 21 @"syntax-macro-0.visp" - CoreMethods.``add``(a, b) + (a) + + (b) | _ -> 0 diff --git a/tests/Visp.Compiler.UnitTests/snapshots/tests_macros_syntax-macro-2.can parse.verified.txt b/tests/Visp.Compiler.UnitTests/snapshots/tests_macros_syntax-macro-2.can parse.verified.txt index 15aa384..6c2cd9a 100644 --- a/tests/Visp.Compiler.UnitTests/snapshots/tests_macros_syntax-macro-2.can parse.verified.txt +++ b/tests/Visp.Compiler.UnitTests/snapshots/tests_macros_syntax-macro-2.can parse.verified.txt @@ -17,14 +17,16 @@ let lambda = match arg with | (a , b) -> // line 28 @"syntax-macro-2.visp" - CoreMethods.``add``(a, b)) + (a) + + (b)) // line 29 @"syntax-macro-2.visp" let named arg = // line 29 @"syntax-macro-2.visp" match arg with | (a , b) -> // line 29 @"syntax-macro-2.visp" - CoreMethods.``add``(a, b) + (a) + + (b) // line 32 @"syntax-macro-2.visp" printfn ("lambda: %i") (lambda (1, 2)) diff --git a/tests/Visp.ExecutionTests/ExecutionTests.generated.fs b/tests/Visp.ExecutionTests/ExecutionTests.generated.fs index db0ace0..b1e4045 100644 --- a/tests/Visp.ExecutionTests/ExecutionTests.generated.fs +++ b/tests/Visp.ExecutionTests/ExecutionTests.generated.fs @@ -195,6 +195,11 @@ module ``tests_macros_struct-example-1`` = [] let ``can execute`` () = TestUtils.runTest "tests/macros/struct-example-1.visp" +[] +module ``tests_macros_count-exprs-0`` = + [] + let ``can execute`` () = TestUtils.runTest "tests/macros/count-exprs-0.visp" + [] module ``tests_macros_syntax-macro-2`` = [] diff --git a/tests/Visp.ExecutionTests/snapshots/tests_macros_count-exprs-0.can execute.verified.txt b/tests/Visp.ExecutionTests/snapshots/tests_macros_count-exprs-0.can execute.verified.txt new file mode 100644 index 0000000..154b77e --- /dev/null +++ b/tests/Visp.ExecutionTests/snapshots/tests_macros_count-exprs-0.can execute.verified.txt @@ -0,0 +1,4 @@ +exprs: 7 +() + +ExitCode: 0 diff --git a/visp/tests/macros/count-exprs-0.visp b/visp/tests/macros/count-exprs-0.visp new file mode 100644 index 0000000..7073643 --- /dev/null +++ b/visp/tests/macros/count-exprs-0.visp @@ -0,0 +1,17 @@ +;; Copyright 2023 Ville Penttinen +;; Distributed under the MIT License. +;; https://github.com/vipentti/visp-fs/blob/main/LICENSE.md +;; +;; for basic syntax highlighting +;; vim: set syntax=clojure: + +(syntax-macro CountExprsExampleTest1 + [(_) 0] + [(_ _) 1] + [(_ head tail ...) + (+ 1 (CountExprsExampleTest1 tail ...))] +) + +(let exprCount (CountExprsExampleTest1 [] [] [] [] [] [] [])) + +(printfn "exprs: %A" exprCount)