anchor.diff:        runRepl ()
   
   open LLVMSharp
  +open FParsec
   
   let [<Literal>] ``my-cool-jit`` = "my cool jit"
   
   let tests () = 
     [
  -    "1.0"
  -    "variable"
  -    "45 + 3.0"
  -    "s < 3"
  -    "foo(y, 4.0 + z)"
  -  ] 
  -  |> Seq.iter (fun program -> Driver.run (new StringReader(program)))
  +    // "def foo(x y) x+foo(y, 4.0);"
  +    // "def foo(x y) x+y y;"
  +    // "def foo(x y) x+y );"
  +    "extern sin(a);"
  +  ]
  +  |> Seq.map (fun program ->
  +    async {
  +      let result = Parser.run program
  +      match result with
  +      | Success(tree, _,_) -> printfn "%A" tree
  +      | Failure(errorMessage, _, _) -> failwith errorMessage
  +    })
  +  |> Async.Parallel
  +  |> Async.RunSynchronously
   
   
   [<EntryPoint>]
  
positive.code:         printfn ""
          printfn "☠️ %s" message
          printfn ""
  
    let run = runParserOnString parseExpr () "" 
  
  module Driver =
  
  
negative.code: 
      override op.ToString() = op.Code
  
    type Prototype = string * seq<string>
  
    type Decl =
    (* proto - This type represents the "prototype" for a function, which captures
     * its name, and its argument names (thus implicitly the number of arguments the
     * function takes). *)
      | Prototype of Prototype
  
    (* func - This type represents a function definition itself. *)
      | Function of Prototype: Prototype * Body: Expr
  
      override decl.ToString() = 
        let prototypeToString (name, args) = 
          let argRepresentation = String.concat " " args
          sprintf "%s %s" name argRepresentation
        match decl with
        | Prototype (name, args) -> prototypeToString (name, args)
        | Function (prototype, body) ->
          sprintf "%s %s" (prototypeToString prototype) (body.ToString())
  
  module Lexer =
    open FParsec
    open Token
  
    let parseWhiteSpace = spaces
    
    let parseLeftParen = pstring LeftParen .>> parseWhiteSpace
  
    let parseRightParen = pstring RightParen .>> parseWhiteSpace
  
    let parseComma = pstring Comma .>> parseWhiteSpace
    let isSymbolicOperatorChar = isAnyOf SpecialCharacters
  
  
    let remainingOperatorCharsAndWhiteSpace = manySatisfy isSymbolicOperatorChar .>> parseWhiteSpace
  
    let parseWhiteSpace1 = spaces1
  
    let parseBetweenBrackets = between parseLeftParen parseRightParen
  
    let parseDef = skipString Def .>> parseWhiteSpace
  
    let parseExtern = skipString Extern .>> parseWhiteSpace
  
  module Parser =
    open FParsec
    open AST
    open Lexer
  
    type UserState = unit
  
    [<RequireQualifiedAccess>]
    module private Expr =
      type private AST.Operator with
      
        member op.Precedence =
          match op with
          | Plus -> 20
          | LessThan -> 10
          | Minus -> 30
          | Multiply -> 40
  
        member op.Associativity =
          match op with
          | Plus -> Associativity.Left
          | _ -> Associativity.Left
  
      let private parseExpr, parseExprRef = createParserForwardedToRef<Expr, _>()
  
      let parseIdentifier = 
        let options = IdentifierOptions()
        let parseIdentifierWithOptions = identifier options
        parseIdentifierWithOptions .>> parseWhiteSpace
  
      let private parseValue =
  
        let parseNumber : Parser<Expr, UserState> = pfloat .>> spaces |>> Number
  
        let parseVariable = parseIdentifier |>> Variable
  
        let parseCall =
          let parseArgs =
            let parseExprs = sepBy parseExpr parseComma
            let parseArguments = between parseLeftParen parseRightParen parseExprs
            parseArguments |>> seq
          let operator = parseIdentifier
          operator .>>. parseArgs |>> Call
  
        choice [
          parseNumber
          attempt parseCall
          attempt parseVariable
        ]
    
      let private addSymbolicInfixOperators (op : Operator) opp =
        let operator = 
          InfixOperator(
            op.Code,
            remainingOperatorCharsAndWhiteSpace,
            op.Precedence,
            op.Associativity,
            (),
            fun _ lhs rhs -> BinaryOperation(op, lhs, rhs)
        )
        (opp : OperatorPrecedenceParser<_, _, _>).AddOperator(operator)
      
      let private operatorPrecendenceParser = 
        let parseTerm = 
          parseValue .>> parseWhiteSpace
          <|> parseBetweenBrackets parseExpr
        let opp = OperatorPrecedenceParser()
        do 
          opp.TermParser <- parseTerm
          addSymbolicInfixOperators LessThan opp
          addSymbolicInfixOperators Plus opp
          addSymbolicInfixOperators Minus opp
          addSymbolicInfixOperators Multiply opp
        opp
  
      let private parseBinaryOperation = operatorPrecendenceParser.ExpressionParser
  
      do parseExprRef := parseBinaryOperation
  
      let parse = parseWhiteSpace >>. parseExpr
           
    [<RequireQualifiedAccess>]
    module private Decl =
  
      type private Decl with
        static member EmptyPrototype = ("", Seq.empty)
  
      let private parseTopLevel =
        let parsePrototype = 
          let parseArgument = sepBy Expr.parseIdentifier parseWhiteSpace
          let parseArguments = between parseLeftParen parseRightParen parseArgument
          Expr.parseIdentifier .>> parseWhiteSpace .>>. parseArguments |>> (fun (name, args) -> (name, seq args))
        let parseDefinition = 
          parseDef .>> parseWhiteSpace >>. parsePrototype .>>. Expr.parse |>> Function
        let parseExtern =
          parseExtern .>> parseWhiteSpace >>. parsePrototype |>> Prototype
        let parseTopLevel =
          Expr.parse |>> (fun body -> Function (Decl.EmptyPrototype, body))
  
        choice [
          parseDefinition
          attempt parseExtern
          attempt parseTopLevel
        ]
  
      let parse = parseTopLevel 
    
    let parse = parseWhiteSpace >>. Decl.parse
  
    let run = runParserOnString parse () "" 
  
    let showResult = 
      function
      | Success(result, _, _) ->
  