<commit_before>module Circuit.Format.Sexp where

import Text.Parsec
import qualified Circuit.Builder as B
import Control.Monad
import Control.Monad.Trans
import Circuit
import Data.Either (rights)

data Sexp = Sexp String [Sexp] | Atom String
          deriving (Eq, Show)

type SexpParser = ParsecT String () B.Builder

parse :: [String] -> Circuit
parse ss = B.buildCircuit $ do
    outs <- rights <$> mapM (runParserT parseSexp () "") ss
    B.outputs outs

parseNInputs :: Int -> [String] -> Circuit
parseNInputs n ss = B.buildCircuit $ do
    _    <- B.inputs n
    outs <- rights <$> mapM (runParserT parseSexp () "") ss
    B.outputs outs

parseSexp :: SexpParser Ref
parseSexp = try parseSub <|> try parseAdd <|> try parseNegate <|> try parseMul <|> try parseInput <|> parseConst

parseSub :: SexpParser Ref
parseSub = do
    _ <- string "Add("
    x <- parseSexp
    _ <- string ", Mul(Integer(-1), "
    y <- parseSexp
    _ <- string "))"
    lift (B.circSub x y)

parseAdd :: SexpParser Ref
parseAdd = do
    _ <- string "Add("
    args <- parseSexp `sepBy` string ", "
    when (length args < 2) $
        (unexpected "gate requires 2 or more arguments")
    _ <- string ")"
    lift (B.circSum args)

parseNegate :: SexpParser Ref
parseNegate = do
    _ <- string "Mul(Integer(-1), "
    x <- parseSexp
    _ <- string ")"
    y <- lift (B.constant 1)
    lift (B.circSub y x)

parseMul :: SexpParser Ref
parseMul = do
    _ <- string "Mul("
    args <- parseSexp `sepBy` string ", "
    when (length args < 2) $
        (unexpected "gate requires 2 or more arguments")
    _ <- string ")"
    lift (B.circProd args)

parseInput :: SexpParser Ref
parseInput = do
    _ <- string "Symbol('x"
    n <- read <$> many digit
    _ <- string "')"
    lift (B.input_n n)

parseConst :: SexpParser Ref
parseConst = do
    _ <- string "Symbol('y"
    n <- read <$> many digit
    _ <- string "')"
    lift (B.secret_n n)


-- parseSexp :: String -> Builder (Ref
-- parseSexp :: String -> (Sexp, String)
-- parseSexp s = Sexp elem (map parseSexp
--   where
--     op = takeWhile (/= '(') s
--     r0 = tail (dropWhile (/= '('))
--     r1 =<commit_msg>Just parse negative integers as negatives for now<commit_after>module Circuit.Format.Sexp where

import Text.Parsec
import qualified Circuit.Builder as B
import Control.Monad
import Control.Monad.Trans
import Circuit
import Data.Either (rights)

data Sexp = Sexp String [Sexp] | Atom String
          deriving (Eq, Show)

type SexpParser = ParsecT String () B.Builder

parse :: [String] -> Circuit
parse ss = B.buildCircuit $ do
    outs <- rights <$> mapM (runParserT parseSexp () "") ss
    B.outputs outs

parseNInputs :: Int -> [String] -> Circuit
parseNInputs n ss = B.buildCircuit $ do
    _    <- B.inputs n
    outs <- rights <$> mapM (runParserT parseSexp () "") ss
    B.outputs outs

parseNInputs1 :: Int -> String -> Circuit
parseNInputs1 n s = B.buildCircuit $ do
    _   <- B.inputs n
    out <- either (error.show) id <$> runParserT parseSexp () "" s
    B.output out

parseSexp :: SexpParser Ref
parseSexp = try parseAdd <|> try parseMul <|> try parseInput <|> try parseConst <|> parseInteger

-- parseSub :: SexpParser Ref
-- parseSub = do
--     _ <- string "Add("
--     x <- parseSexp
--     _ <- string ", Mul(Integer(-1), "
--     y <- parseSexp
--     _ <- string "))"
--     lift (B.circSub x y)

parseAdd :: SexpParser Ref
parseAdd = do
    _ <- string "Add("
    args <- parseSexp `sepBy` string ", "
    when (length args < 2) $
        (unexpected "gate requires 2 or more arguments")
    _ <- string ")"
    lift (B.circSum args)

-- parseNegate :: SexpParser Ref
-- parseNegate = do
--     _ <- string "Mul(Integer(-1), "
--     x <- parseSexp
--     _ <- string ")"
--     y <- lift (B.constant 1)
--     lift (B.circSub y x)

parseMul :: SexpParser Ref
parseMul = do
    _ <- string "Mul("
    args <- parseSexp `sepBy` string ", "
    when (length args < 2) $
        (unexpected "gate requires 2 or more arguments")
    _ <- string ")"
    lift (B.circProd args)

parseInput :: SexpParser Ref
parseInput = do
    _ <- string "Symbol('x"
    n <- read <$> many digit
    _ <- string "')"
    lift (B.input_n n)

parseConst :: SexpParser Ref
parseConst = do
    _ <- string "Symbol('y"
    n <- read <$> many digit
    _ <- string "')"
    lift (B.secret_n n)

parseInteger :: SexpParser Ref
parseInteger = do
    _ <- string "Integer("
    n <- read <$> many (digit <|> char '-')
    _ <- string ")"
    lift (B.constant n)
{'fraction_non_alphanumeric': 0.14143205497672356, 'fraction_numerical': 0.003990246065174019, 'mean_word_length': 2.547169811320755, 'pattern_counts': {'":': 0, '<': 80, '<?xml version=': 0, '>': 33, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '4008849', 'n_tokens_mistral': 1604, 'n_tokens_neox': 1511, 'n_words': 465}