Skip to content

Commit

Permalink
basic python support working
Browse files Browse the repository at this point in the history
  • Loading branch information
bristermitten committed Aug 25, 2023
1 parent 9d629a4 commit 4610769
Show file tree
Hide file tree
Showing 14 changed files with 156 additions and 60 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -145,7 +145,7 @@ Charlie
We can describe the inputs using Templatespiler like so
```js
prices: list (sep-by " " [item : String, price : Float])
orders: list (sep-by " " [
orders: list ([
name: String,
order: list (sep-by " " [quantity : Integer, item : String])
])
Expand Down
2 changes: 2 additions & 0 deletions templatespiler-bnf/src/Language/Templatespiler/Abs.hs
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ data BindingGroup' a = BindingGroup a [Binding' a]
type BindingOrCombinator = BindingOrCombinator' BNFC'Position
data BindingOrCombinator' a
= NamedBinding a (Binding' a)
| GroupBinding a (BindingGroup' a)
| ParenBinding a (Binding' a)
| UnnamedBinding a (Combinator' a)
deriving (C.Eq, C.Ord, C.Show, C.Read, C.Functor, C.Foldable, C.Traversable, C.Data, C.Typeable, C.Generic)
Expand Down Expand Up @@ -101,6 +102,7 @@ instance HasPosition BindingGroup where
instance HasPosition BindingOrCombinator where
hasPosition = \case
NamedBinding p _ -> p
GroupBinding p _ -> p
ParenBinding p _ -> p
UnnamedBinding p _ -> p

Expand Down
1 change: 1 addition & 0 deletions templatespiler-bnf/src/Language/Templatespiler/Doc.txt
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@ All other symbols are terminals.
| | **|** | **eps**
| | **|** | //Binding// //[Binding]//
| //BindingOrCombinator// | -> | //Binding//
| | **|** | //BindingGroup//
| | **|** | ``(`` //Binding// ``)``
| | **|** | //Combinator//
| //Combinator// | -> | ``(`` //Combinator// ``)``
Expand Down
1 change: 1 addition & 0 deletions templatespiler-bnf/src/Language/Templatespiler/Par.y
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,7 @@ ListBinding
BindingOrCombinator :: { (Language.Templatespiler.Abs.BNFC'Position, Language.Templatespiler.Abs.BindingOrCombinator) }
BindingOrCombinator
: Binding { (fst $1, Language.Templatespiler.Abs.NamedBinding (fst $1) (snd $1)) }
| BindingGroup { (fst $1, Language.Templatespiler.Abs.GroupBinding (fst $1) (snd $1)) }
| '(' Binding ')' { (uncurry Language.Templatespiler.Abs.BNFC'Position (tokenLineCol $1), Language.Templatespiler.Abs.ParenBinding (uncurry Language.Templatespiler.Abs.BNFC'Position (tokenLineCol $1)) (snd $2)) }
| Combinator { (fst $1, Language.Templatespiler.Abs.UnnamedBinding (fst $1) (snd $1)) }

Expand Down
1 change: 1 addition & 0 deletions templatespiler-bnf/src/Language/Templatespiler/Print.hs
Original file line number Diff line number Diff line change
Expand Up @@ -168,6 +168,7 @@ instance Print [Language.Templatespiler.Abs.Binding' a] where
instance Print (Language.Templatespiler.Abs.BindingOrCombinator' a) where
prt i = \case
Language.Templatespiler.Abs.NamedBinding _ binding -> prPrec i 0 (concatD [prt 0 binding])
Language.Templatespiler.Abs.GroupBinding _ bindinggroup -> prPrec i 0 (concatD [prt 0 bindinggroup])
Language.Templatespiler.Abs.ParenBinding _ binding -> prPrec i 0 (concatD [doc (showString "("), prt 0 binding, doc (showString ")")])
Language.Templatespiler.Abs.UnnamedBinding _ combinator -> prPrec i 0 (concatD [prt 0 combinator])

Expand Down
1 change: 1 addition & 0 deletions templatespiler-bnf/src/Language/Templatespiler/Skel.hs
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ transBindingGroup x = case x of
transBindingOrCombinator :: Show a => Language.Templatespiler.Abs.BindingOrCombinator' a -> Result
transBindingOrCombinator x = case x of
Language.Templatespiler.Abs.NamedBinding _ binding -> failure x
Language.Templatespiler.Abs.GroupBinding _ bindinggroup -> failure x
Language.Templatespiler.Abs.ParenBinding _ binding -> failure x
Language.Templatespiler.Abs.UnnamedBinding _ combinator -> failure x

Expand Down
Binary file modified templatespiler-converter/src/Main
Binary file not shown.
15 changes: 10 additions & 5 deletions templatespiler-converter/src/Main.hs
Original file line number Diff line number Diff line change
Expand Up @@ -4,18 +4,23 @@ import Control.Monad.Writer (execWriter, runWriter)
import Language.Templatespiler.Par
import Main.Utf8 qualified as Utf8
import Prettyprinter.Render.Text
import Shower (shower)
import Shower (printer, shower)
import Templatespiler.Convert (toImperative)
import Templatespiler.Convert.Python (convertToPython)

main :: IO ()
main = do
Utf8.withUtf8 $ do
file <- readFileText "./test.tmpspl"
file <- readFileText "../test.tmpspl"
let tokens = myLexer file
case pBindingList tokens of
Left err -> putStrLn $ shower err
Right bs -> do
putStrLn "Parsed:"
putStrLn $ shower bs
putDoc $ execWriter $ convertToPython bs
-- putStrLn "Parsed:"
-- putStrLn $ shower bs
putStrLn ""
let imp = toImperative bs
printer imp
putStrLn ""
putDoc $ execWriter $ convertToPython imp
putStrLn ""
45 changes: 38 additions & 7 deletions templatespiler-converter/src/Templatespiler/Convert.hs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,9 @@ module Templatespiler.Convert where

import Control.Monad.Writer
import Language.Templatespiler.Abs
import Templatespiler.IR.Imperative as Imp
import Shower (shower)
import Templatespiler.IR.Imperative (withSuffix)
import Templatespiler.IR.Imperative qualified as Imp

toImperative :: BindingList -> [Imp.Statement]
toImperative (BindingList _ bs) = foldMap toImperativeBinding bs
Expand All @@ -11,14 +13,43 @@ toImperative (BindingList _ bs) = foldMap toImperativeBinding bs
toImperativeBinding (Binding _ n t) = execWriter $ do
case t of
StringType _ -> do
tell [Decl n (Read n [ReadString])]
tell [Imp.Assign (toVarName n) Imp.StringType (Imp.ReadAtom Imp.ReadString)]
IntegerType _ -> do
tell [Decl n (Read n [ReadInt])]
tell [Imp.Assign (toVarName n) Imp.IntType (Imp.ReadAtom Imp.ReadInt)]
FloatType _ -> do
tell [Decl n (Read n [ReadFloat])]
tell [Imp.Assign (toVarName n) Imp.FloatType (Imp.ReadAtom Imp.ReadFloat)]
CombinatorType _ combin -> do
toImperativeCombinator n combin

toImperativeCombinator :: Ident -> Combinator' BNFC'Position -> Writer [Statement] ()
toImperativeCombinator n (ListCombinator b) = do
tell [Decl ()]
toImperativeBindingOrCombinator :: BindingOrCombinator -> Writer [Imp.Statement] ()
toImperativeBindingOrCombinator (NamedBinding _ b) = tell $ toImperativeBinding b
toImperativeBindingOrCombinator (ParenBinding _ b) = tell $ toImperativeBinding b
toImperativeBindingOrCombinator (UnnamedBinding _ c) = toImperativeCombinator (Ident "unnamed") c
toImperativeBindingOrCombinator (GroupBinding _ (BindingGroup _ bs)) = do
tell $ foldMap toImperativeBinding bs

toImperativeCombinator :: Ident -> Combinator' BNFC'Position -> Writer [Imp.Statement] ()
toImperativeCombinator n (ParenCombinator _ c) = toImperativeCombinator n c
toImperativeCombinator n (SepByCombinator _ sep c) = do
let (BindingGroup _ bs) = c
let toReadAssign (Binding _ n t) =
( toVarName n
, case t of
StringType _ -> Imp.ReadString
IntegerType _ -> Imp.ReadInt
FloatType _ -> Imp.ReadFloat
CombinatorType _ c -> error ("CombinatorType in toReadAssign: " <> toText (shower c))
)
tell [Imp.MultiReadAssign (toText sep) (toReadAssign <$> bs)]
toImperativeCombinator n (ListCombinator _ b) = do
let lenName = toVarName n `withSuffix` "len"
tell [Imp.Assign lenName Imp.IntType (Imp.ReadAtom Imp.ReadInt)]
tell [Imp.Decl (toVarName n) (Imp.ArrayType Imp.UnknownType)]
let (_, b') = runWriter $ toImperativeBindingOrCombinator b
tell [Imp.For (toVarName "i") (Imp.ConstInt 0) (Imp.Var lenName) b']

toVarName :: Ident -> Imp.VarName
toVarName (Ident n) = toVarName' n

toVarName' :: (ToText s) => s -> Imp.VarName
toVarName' s = Imp.VarName (toText s :| [])
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
module Templatespiler.Convert.Common (tell, identToText, identToDoc, indented, indentDepth, DocBuilder) where
module Templatespiler.Convert.Common (tell, identToText, identToDoc, indented, indentDepth, Doc', DocBuilder, write) where

import Control.Monad.Writer
import Language.Templatespiler.Abs (Ident (..))
import Prettyprinter (Doc, Pretty (pretty), indent)

type Ann = ()

type Doc' = Doc Ann

type DocBuilder a = Writer (Doc Ann) a

identToText :: Ident -> Text
Expand All @@ -23,3 +25,6 @@ indented b = do
let (d, a) = runWriter b
tell (indent indentDepth a)
pure d

write :: Doc Ann -> DocBuilder ()
write = tell
111 changes: 69 additions & 42 deletions templatespiler-converter/src/Templatespiler/Convert/Python.hs
Original file line number Diff line number Diff line change
@@ -1,48 +1,75 @@
module Templatespiler.Convert.Python where

import Control.Monad (foldM)
import Language.Templatespiler.Abs as Abs
import Prettyprinter (Pretty (pretty))
import Templatespiler.Convert.Common
import Templatespiler.IR.Imperative as IR

convertToPython :: BindingList -> DocBuilder ()
convertToPython (BindingList _ bindings) = foldM (\_ b -> writeBinding b) () bindings

writeBinding :: Binding -> DocBuilder ()
writeBinding (Binding _ n t) = do
tell (identToDoc n)
tell " = "
writeType t
tell "\n"

writeType :: Abs.Type -> DocBuilder ()
writeType (Abs.StringType _) = tell "input()"
writeType (Abs.IntegerType _) = tell "int(input())"
writeType (Abs.FloatType _) = tell "float(input())"
writeType (Abs.CombinatorType _ combin) = writeCombinator combin

writeCombinator :: Combinator -> DocBuilder ()
writeCombinator (ParenCombinator _ c) = writeCombinator c
writeCombinator (ArrayCombinator _ len c) = do
tell "for i"
tell " in range(0, "

writeVarOrConstInt len
tell "):\n"
indented $ do
writeBindingOrCombinator c
writeCombinator (ListCombinator _ c) = do
tell "length = int(input())\n"
tell "for i in range(0, length):\n"
indented $ do
writeBindingOrCombinator c
writeCombinator other = error ("writeCombinator: " <> show other)

writeBindingOrCombinator :: BindingOrCombinator -> DocBuilder ()
writeBindingOrCombinator (NamedBinding _ b) = writeBinding b
writeBindingOrCombinator (ParenBinding _ b) = writeBinding b
writeBindingOrCombinator (UnnamedBinding _ c) = writeCombinator c

writeVarOrConstInt :: VarOrConstInt -> DocBuilder ()
writeVarOrConstInt (ConstInt _ v) = tell (pretty v)
writeVarOrConstInt (ConstVar _ v) = tell (identToDoc v)
convertToPython :: [Statement] -> DocBuilder ()
convertToPython = foldM (\_ b -> writeBinding b) ()

writeBinding :: Statement -> DocBuilder ()
writeBinding (Decl name t) = do
writeVarName name
write " = "
writeDefaultVarType t
write "\n"
writeBinding (Assign name t val) = do
writeVarName name
write " = "
writeExpr val
write "\n"
writeBinding (For name start end body) = do
write "for "
writeVarName name
write " in range("
writeExpr start
write ", "
writeExpr end
write "):\n"
indented $ mapM_ writeBinding body
write "\n"
writeBinding (MultiReadAssign sep parts) = do
write "line = input()\n"
write "parts = line.split("
write (pretty $ toPyStrLit sep)
write ")\n"
mapM_ writeMultiReadAssignPart (zip [0 ..] parts)
where
writeMultiReadAssignPart :: (Int, (VarName, ReadType)) -> DocBuilder ()
writeMultiReadAssignPart (idx, (name, rt)) = do
writeVarName name
write " = "
writeReadAtom ("parts[" <> pretty idx <> "]") rt
write "\n"

writeExpr :: Expr -> DocBuilder ()
writeExpr (ConstInt i) = write (pretty i)
writeExpr (Var name) = writeVarName name
writeExpr (ReadAtom rt) = writeReadAtom "input()" rt

toPyStrLit :: Text -> Text
toPyStrLit s = "'" <> s <> "'"

writeReadAtom :: Doc' -> ReadType -> DocBuilder ()
writeReadAtom source ReadInt = write ("int(" <> source <> ")")
writeReadAtom source ReadFloat = write ("float(" <> source <> ")")
writeReadAtom source ReadString = write source

writeDefaultVarType :: VarType -> DocBuilder ()
writeDefaultVarType IntType = write "0"
writeDefaultVarType FloatType = write "0.0"
writeDefaultVarType StringType = write "''"
writeDefaultVarType (ArrayType t) = do
write "[]"

writeVarName :: VarName -> DocBuilder ()
writeVarName (VarName ns) = writeVarName' (toList ns)
where
writeVarName' :: [Text] -> DocBuilder ()
writeVarName' [] = pass
writeVarName' [n] = write (pretty n)
writeVarName' (n : ns) = do
write (pretty n)
write "_"
writeVarName' ns
25 changes: 23 additions & 2 deletions templatespiler-converter/src/Templatespiler/IR/Imperative.hs
Original file line number Diff line number Diff line change
Expand Up @@ -7,26 +7,47 @@ module Templatespiler.IR.Imperative where
newtype VarName
= VarName
(NonEmpty Text)
deriving (Show)

withSuffix :: VarName -> Text -> VarName
withSuffix (VarName (n :| ns)) suffix = VarName (n :| (ns <> [suffix]))

data Statement
= Decl VarName Expr
= -- | Variable declaration. This may be a C-style declaration (@int x@) or an assignment (@x = 0@) depending on the target language.
Decl
VarName
-- ^ The variable name
VarType
-- ^ The type
| Assign VarName VarType Expr
| MultiReadAssign
Text -- Separator
[(VarName, ReadType)]
| For
VarName -- variable name
Expr -- start
Expr -- end
[Statement] -- body
deriving (Show)

data VarType
= IntType
| FloatType
| StringType
| ArrayType VarType
| UnknownType
deriving (Show)

data Expr
= ConstInt Int
| Var VarName
| Read VarName [ReadType]
| ReadAtom ReadType
| TupleOrStruct (Maybe VarName) (NonEmpty Expr)
deriving (Show)

data ReadType
= ReadInt
| ReadFloat
| ReadString
| ReadConst Text
deriving (Show)
1 change: 1 addition & 0 deletions templatespiler.cf
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ BindingGroup. BindingGroup ::= "[" [Binding] "]" ;
separator Binding "," ;

NamedBinding. BindingOrCombinator ::= Binding;
GroupBinding. BindingOrCombinator ::= BindingGroup;
ParenBinding . BindingOrCombinator ::= "(" Binding ")" ;
UnnamedBinding. BindingOrCombinator ::= Combinator;

Expand Down
4 changes: 2 additions & 2 deletions test.tmpspl
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
prices: list (sep-by " " [item : String, price : Float])
orders: list (sep-by " " [
orders: list [
name: String,
order: list (sep-by " " [quantity : Integer, item : String])
])
]

0 comments on commit 4610769

Please sign in to comment.