<commit_before>module Starling.Tests.Lang.Parser

open NUnit.Framework
open FParsec
open Starling
open Starling.Var
open Starling.Lang.AST
open Starling.Lang.Parser
open Starling.Pretty.Lang.AST
open Starling.Pretty.Types

/// Tests for the parser.
type ParserTests() = 
    
    /// Helper method for building parser tests.
    /// Adapts to Some/None.
    static member ParseResultToOptional a = 
        match a with
        | Success(result, _, _) -> Some result
        | Failure _ -> None
    
    /// Test cases for testing the expression parser.
    static member ExpressionParses = 
        [ TestCaseData("1 + 2 * 3").Returns(Some(Bop(Add, Int 1L, Bop(Mul, Int 2L, Int 3L))))
          
          TestCaseData("(1 + 2) * 3").Returns(Some(Bop(Mul, Bop(Add, Int 1L, Int 2L), Int 3L)))
          
          TestCaseData("1 + 2 < 3 * 4 && true || 5 / 6 > 7 - 8")
              .Returns(Some
                           ((Bop
                                 (Or, Bop(And, Bop(Lt, Bop(Add, Int 1L, Int 2L), Bop(Mul, Int 3L, Int 4L)), True), 
                                  Bop(Gt, Bop(Div, Int 5L, Int 6L), Bop(Sub, Int 7L, Int 8L)))))) ]
        |> List.map (fun d -> d.SetName(sprintf "Parse %A" d.OriginalArguments.[0]))
    
    [<TestCaseSource("ExpressionParses")>]
    /// Tests whether the expression parser works correctly.
    member x.``the expression parser parses test case expressions correctly`` expr = 
        expr
        |> run parseExpression
        |> ParserTests.ParseResultToOptional
    
    /// Test cases for testing the atomic parser.
    static member AtomicParses = 
        [ TestCaseData("foo++").Returns(Some(Postfix(LVIdent "foo", Increment)))
          TestCaseData("foo--").Returns(Some(Postfix(LVIdent "foo", Decrement)))
          TestCaseData("foo = bar").Returns(Some(Fetch(LVIdent "foo", LV(LVIdent "bar"), Direct)))
          TestCaseData("foo = bar++").Returns(Some(Fetch(LVIdent "foo", LV(LVIdent "bar"), Increment)))
          TestCaseData("foo = bar--").Returns(Some(Fetch(LVIdent "foo", LV(LVIdent "bar"), Decrement)))
          TestCaseData("CAS(foo, bar, 2)").Returns(Some(CompareAndSwap(LVIdent "foo", LVIdent "bar", Int 2L))) ]
        |> List.map (fun d -> d.SetName(sprintf "Parse %A" d.OriginalArguments.[0]))

    [<TestCaseSource("AtomicParses")>]
    /// Tests whether the expression parser works correctly.
    member x.``the atomics parser parses test case atomics correctly`` expr = 
        expr
        |> run parseAtomic
        |> ParserTests.ParseResultToOptional
    
    /// Test cases for testing the full parser.
    static member ScriptParses = 
        [ TestCaseData(Starling.Tests.Studies.ticketLock).Returns(Some(Starling.Tests.Studies.ticketLockParsed))
            .SetName("Parse the ticketed lock") ]
    
    [<TestCaseSource("ScriptParses")>]
    /// Tests whether the script parser works correctly.
    member x.``the script parser parses full case studies correctly`` expr = 
        expr
        |> run parseScript
        |> ParserTests.ParseResultToOptional<commit_msg>Add some constraint parser tests.<commit_after>module Starling.Tests.Lang.Parser

open NUnit.Framework
open FParsec
open Starling
open Starling.Var
open Starling.Lang.AST
open Starling.Lang.Parser
open Starling.Pretty.Lang.AST
open Starling.Pretty.Types

/// Tests for the parser.
type ParserTests() = 
    
    /// Helper method for building parser tests.
    /// Adapts to Some/None.
    static member ParseResultToOptional a = 
        match a with
        | Success(result, _, _) -> Some result
        | Failure _ -> None
    
    /// Test cases for testing the expression parser.
    static member ExpressionParses = 
        [ TestCaseData("1 + 2 * 3").Returns(Some(Bop(Add, Int 1L, Bop(Mul, Int 2L, Int 3L))))
          TestCaseData("(1 + 2) * 3").Returns(Some(Bop(Mul, Bop(Add, Int 1L, Int 2L), Int 3L)))
          
          TestCaseData("1 + 2 < 3 * 4 && true || 5 / 6 > 7 - 8")
              .Returns(Some
                           ((Bop
                                 (Or, Bop(And, Bop(Lt, Bop(Add, Int 1L, Int 2L), Bop(Mul, Int 3L, Int 4L)), True), 
                                  Bop(Gt, Bop(Div, Int 5L, Int 6L), Bop(Sub, Int 7L, Int 8L)))))) ]
        |> List.map (fun d -> d.SetName(sprintf "Parse %A" d.OriginalArguments.[0]))
    
    [<TestCaseSource("ExpressionParses")>]
    /// Tests whether the expression parser works correctly.
    member x.``the expression parser parses test case expressions correctly`` expr = 
        expr
        |> run parseExpression
        |> ParserTests.ParseResultToOptional
    
    /// Test cases for testing the atomic parser.
    static member AtomicParses = 
        [ TestCaseData("foo++").Returns(Some(Postfix(LVIdent "foo", Increment)))
          TestCaseData("foo--").Returns(Some(Postfix(LVIdent "foo", Decrement)))
          TestCaseData("foo = bar").Returns(Some(Fetch(LVIdent "foo", LV(LVIdent "bar"), Direct)))
          TestCaseData("foo = bar++").Returns(Some(Fetch(LVIdent "foo", LV(LVIdent "bar"), Increment)))
          TestCaseData("foo = bar--").Returns(Some(Fetch(LVIdent "foo", LV(LVIdent "bar"), Decrement)))
          TestCaseData("CAS(foo, bar, 2)").Returns(Some(CompareAndSwap(LVIdent "foo", LVIdent "bar", Int 2L))) ]
        |> List.map (fun d -> d.SetName(sprintf "Parse %A" d.OriginalArguments.[0]))
    
    [<TestCaseSource("AtomicParses")>]
    /// Tests whether the expression parser works correctly.
    member x.``the atomics parser parses test case atomics correctly`` expr = 
        expr
        |> run parseAtomic
        |> ParserTests.ParseResultToOptional
    
    /// Test cases for testing the constraint parser.
    static member ConstraintParses = 
        [ TestCaseData("constraint emp -> true;").Returns(Some { CView = ViewDef.Unit
                                                                 CExpression = True })
          
          TestCaseData("constraint Func(a, b) -> c > a + b;")
              .Returns(Some { CView = 
                                  ViewDef.Func { Name = "Func"
                                                 Params = [ "a"; "b" ] }
                              CExpression = Bop(Gt, LV(LVIdent "c"), Bop(Add, LV(LVIdent "a"), LV(LVIdent "b"))) }) ]
        |> List.map (fun d -> d.SetName(sprintf "Parse %A" d.OriginalArguments.[0]))
    
    [<TestCaseSource("ConstraintParses")>]
    /// Tests whether the constraint parser works correctly.
    member x.``the constraint parser parses valid constraints correctly`` cs = 
        cs
        |> run parseConstraint
        |> ParserTests.ParseResultToOptional
    
    /// Test cases for testing the full parser.
    static member ScriptParses = 
        [ TestCaseData(Starling.Tests.Studies.ticketLock).Returns(Some(Starling.Tests.Studies.ticketLockParsed))
            .SetName("Parse the ticketed lock") ]
    
    [<TestCaseSource("ScriptParses")>]
    /// Tests whether the script parser works correctly.
    member x.``the script parser parses full case studies correctly`` expr = 
        expr
        |> run parseScript
        |> ParserTests.ParseResultToOptional
{'fraction_non_alphanumeric': 0.12731351654514864, 'fraction_numerical': 0.009113853056646103, 'mean_word_length': 2.3741721854304636, 'pattern_counts': {'":': 0, '<': 12, '<?xml version=': 0, '>': 43, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 9, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '2075050', 'n_tokens_mistral': 2185, 'n_tokens_neox': 2013, 'n_words': 567}