Skip to content

Commit

Permalink
Fix SynWriter normalizeString with generics
Browse files Browse the repository at this point in the history
  • Loading branch information
vipentti committed Dec 30, 2023
1 parent 475a5bf commit a6262a2
Show file tree
Hide file tree
Showing 10 changed files with 207 additions and 8 deletions.
40 changes: 32 additions & 8 deletions src/Visp.Compiler/Syntax/SynWriter.fs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

module Visp.Syntax.SynWriter

open System
open SpanUtils.Extensions
open Visp.Compiler.Writer
open Visp.Common
Expand Down Expand Up @@ -261,6 +262,15 @@ module Write =

sb.ToStringAndReturn()

let private countChars ch (span: ReadOnlySpan<char>) =
let mutable c = 0

for ms in span do
if ms = ch then
c <- c + 1

c

let normalizeString (name: string) =
let mutable sb = PooledStringBuilder.Get()
sb.EnsureCapacity(name.Length) |> ignore
Expand All @@ -270,15 +280,29 @@ module Write =
sb <- sb.Append('_')
()

for ch in name do
if Set.contains ch escapableChars then
needs_escape <- true
let nameSpan = name.AsSpan()

// TODO: Allow ^ also
if ch = '^' then
sb <- sb.Append('\'')
else
sb <- sb.Append(ch)
// TODO: Actual generic argument support
let countLess = countChars '<' nameSpan
let countGreater = countChars '>' nameSpan

if countLess = countGreater && countLess > 0 then
for ch in name do
// TODO: Allow ^ also
if ch = '^' then
sb <- sb.Append('\'')
else
sb <- sb.Append(ch)
else
for ch in name do
if Set.contains ch escapableChars then
needs_escape <- true

// TODO: Allow ^ also
if ch = '^' then
sb <- sb.Append('\'')
else
sb <- sb.Append(ch)

(PooledStringBuilder.ToStringAndReturn(sb), needs_escape)

Expand Down
5 changes: 5 additions & 0 deletions tests/Visp.Compiler.UnitTests/ParsingTests.generated.fs
Original file line number Diff line number Diff line change
Expand Up @@ -190,6 +190,11 @@ module ``tests_parsing_tuple-0`` =
[<Fact>]
let ``can parse`` () = TestUtils.runTest "tests/parsing/tuple-0.visp"

[<VerifyXunit.UsesVerify>]
module ``tests_parsing_generic-method-or-variable-0`` =
[<Fact>]
let ``can parse`` () = TestUtils.runTest "tests/parsing/generic-method-or-variable-0.visp"

[<VerifyXunit.UsesVerify>]
module ``tests_parsing_generic-args-0`` =
[<Fact>]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -190,6 +190,11 @@ module ``tests_parsing_tuple-0`` =
[<Fact>]
let ``structured output`` () = TestUtils.runStructuredOutputTest "tests/parsing/tuple-0.visp"

[<VerifyXunit.UsesVerify>]
module ``tests_parsing_generic-method-or-variable-0`` =
[<Fact>]
let ``structured output`` () = TestUtils.runStructuredOutputTest "tests/parsing/generic-method-or-variable-0.visp"

[<VerifyXunit.UsesVerify>]
module ``tests_parsing_generic-args-0`` =
[<Fact>]
Expand Down
5 changes: 5 additions & 0 deletions tests/Visp.Compiler.UnitTests/TokenOutputTests.generated.fs
Original file line number Diff line number Diff line change
Expand Up @@ -190,6 +190,11 @@ module ``tests_parsing_tuple-0`` =
[<Fact>]
let ``returns tokens`` () = TestUtils.runTokenTest "tests/parsing/tuple-0.visp"

[<VerifyXunit.UsesVerify>]
module ``tests_parsing_generic-method-or-variable-0`` =
[<Fact>]
let ``returns tokens`` () = TestUtils.runTokenTest "tests/parsing/generic-method-or-variable-0.visp"

[<VerifyXunit.UsesVerify>]
module ``tests_parsing_generic-args-0`` =
[<Fact>]
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
ParsedFile
[AnonModule
([Expr
(FunctionDef
(SynSymbol MyGenMethod<^T>, None,
Args (List [Typed (Named (SynSymbol v, (8,22--8,23)), Ident ^T, (8,21--8,28))], (8,20--8,29)),
[FunctionCall
(Symbol (SynSymbol printfn),
[Const (String ("Value is %A", Regular, (8,39--8,52)), (8,39--8,52)); Symbol (SynSymbol v)],
(8,31--8,54))], None, (8,1--8,55)), (8,0--8,56));
Expr
(LetOrUse
(Named (SynSymbol items, (10,5--10,10)),
ThreadLast
([Expr (Symbol (SynSymbol Set.empty<_>), (10,16--10,28));
Expr
(FunctionCall (Symbol (SynSymbol Set.add), [Const (Int32 1, (10,38--10,39))], (10,30--10,39)),
(10,29--10,40));
Expr
(FunctionCall (Symbol (SynSymbol Set.add), [Const (Int32 2, (10,50--10,51))], (10,42--10,51)),
(10,41--10,52))], (10,12--10,52)), None, [], (10,1--10,53)), (10,0--10,54));
Expr
(FunctionCall
(Symbol (SynSymbol printfn),
[Const (String ("Items: %A", Regular, (12,9--12,20)), (12,9--12,20)); Symbol (SynSymbol items)],
(12,1--12,26)), (12,0--12,27));
Expr
(FunctionCall
(Symbol (SynSymbol printfn),
[Const (String ("Singleton %A", Regular, (13,9--13,23)), (13,9--13,23));
FunctionCall (Symbol (SynSymbol Set.singleton<int>), [Const (Int32 1, (13,44--13,45))], (13,25--13,45))],
(13,1--13,46)), (13,0--13,47));
Expr
(LetOrUse
(Named (SynSymbol visp_result_todo, (14,0--14,35)),
FunctionCall
(Symbol (SynSymbol MyGenMethod<string>),
[Const (String ("hello world", Regular, (14,21--14,34)), (14,21--14,34))], (14,1--14,34)), None, [],
(14,0--14,35)), (14,0--14,35));
Expr
(FunctionCall
(Symbol (SynSymbol printfn),
[Const (String ("%A", Regular, (14,0--14,35)), (14,0--14,35)); Symbol (SynSymbol visp_result_todo)],
(14,0--14,35)), (14,0--14,35))], (8,0--14,35))]
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
// This file is auto-generated

#nowarn "0020" // unused results from functions

open Visp.Runtime.Library

let state = { Todo = () }
// line 8 @"generic-method-or-variable-0.visp"
let MyGenMethod<'T> (v: 'T) =
// line 8 @"generic-method-or-variable-0.visp"
printfn "Value is %A" v

// line 10 @"generic-method-or-variable-0.visp"
let items =
// line 10 @"generic-method-or-variable-0.visp"
Set.empty<_>
|> Set.add 1
|> Set.add 2
// line 12 @"generic-method-or-variable-0.visp"
printfn "Items: %A" items
// line 13 @"generic-method-or-variable-0.visp"
printfn "Singleton %A" (Set.singleton<int> 1)
// line 14 @"generic-method-or-variable-0.visp"
let visp_result_todo =
// line 14 @"generic-method-or-variable-0.visp"
MyGenMethod<string> "hello world"
// line 14 @"generic-method-or-variable-0.visp"
printfn "%A" visp_result_todo

Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
LPAREN Default 0 1 LParen
FN Default 0 1 LParen
SYMBOL "MyGenMethod" Default 0 1 LParen
OP_LESS Default 0 1 LParen
SYMBOL "^T" Default 0 1 LParen
OP_GREATER Default 0 1 LParen
LPAREN Default 0 2 LParen
LBRACKET Default 0 2 LParen
SYMBOL "v" Default 0 2 LParen
COLON Default 0 2 LParen
SYMBOL "^T" Default 0 2 LParen
RBRACKET Default 0 2 LParen
RPAREN Default 0 1 LParen
LPAREN Default 0 2 LParen
SYMBOL "printfn" Default 0 2 LParen
STRING ("Value is %A", Regular, Token []) Default 0 2 LParen
SYMBOL "v" Default 0 2 LParen
RPAREN Default 0 1 LParen
RPAREN Default 0 0 Default
LPAREN Default 0 1 LParen
LET Default 0 1 LParen
SYMBOL "items" Default 0 1 LParen
LPAREN Default 0 2 LParen
THREAD_LAST Default 0 2 LParen
SYMBOL "Set.empty" Default 0 2 LParen
OP_LESS Default 0 2 LParen
SYMBOL "_" Default 0 2 LParen
OP_GREATER Default 0 2 LParen
LPAREN Default 0 3 LParen
SYMBOL "Set.add" Default 0 3 LParen
INT32 (1, false) Default 0 3 LParen
RPAREN Default 0 2 LParen
LPAREN Default 0 3 LParen
SYMBOL "Set.add" Default 0 3 LParen
INT32 (2, false) Default 0 3 LParen
RPAREN Default 0 2 LParen
RPAREN Default 0 1 LParen
RPAREN Default 0 0 Default
LPAREN Default 0 1 LParen
SYMBOL "printfn" Default 0 1 LParen
STRING ("Items: %A", Regular, Token []) Default 0 1 LParen
SYMBOL "items" Default 0 1 LParen
RPAREN Default 0 0 Default
LPAREN Default 0 1 LParen
SYMBOL "printfn" Default 0 1 LParen
STRING ("Singleton %A", Regular, Token []) Default 0 1 LParen
LPAREN Default 0 2 LParen
SYMBOL "Set.singleton" Default 0 2 LParen
OP_LESS Default 0 2 LParen
SYMBOL "int" Default 0 2 LParen
OP_GREATER Default 0 2 LParen
INT32 (1, false) Default 0 2 LParen
RPAREN Default 0 1 LParen
RPAREN Default 0 0 Default
LPAREN Default 0 1 LParen
SYMBOL "MyGenMethod" Default 0 1 LParen
OP_LESS Default 0 1 LParen
SYMBOL "string" Default 0 1 LParen
OP_GREATER Default 0 1 LParen
STRING ("hello world", Regular, Token []) Default 0 1 LParen
RPAREN Default 0 0 Default
EOF Default 0 0 Default
5 changes: 5 additions & 0 deletions tests/Visp.ExecutionTests/ExecutionTests.generated.fs
Original file line number Diff line number Diff line change
Expand Up @@ -190,6 +190,11 @@ module ``tests_parsing_tuple-0`` =
[<Fact>]
let ``can execute`` () = TestUtils.runTest "tests/parsing/tuple-0.visp"

[<VerifyXunit.UsesVerify>]
module ``tests_parsing_generic-method-or-variable-0`` =
[<Fact>]
let ``can execute`` () = TestUtils.runTest "tests/parsing/generic-method-or-variable-0.visp"

[<VerifyXunit.UsesVerify>]
module ``tests_parsing_generic-args-0`` =
[<Fact>]
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
Items: set [1; 2]
Singleton set [1]
Value is "hello world"
()

ExitCode: 0
14 changes: 14 additions & 0 deletions visp/tests/parsing/generic-method-or-variable-0.visp
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
;; 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:

(fn MyGenMethod<^T> ([v: ^T]) (printfn "Value is %A" v))

(let items (->> Set.empty<_> (Set.add 1) (Set.add 2)))

(printfn "Items: %A" items)
(printfn "Singleton %A" (Set.singleton<int> 1))
(MyGenMethod<string> "hello world")

0 comments on commit a6262a2

Please sign in to comment.