generated from srid/haskell-template
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
068a992
commit 52c5f02
Showing
1 changed file
with
38 additions
and
94 deletions.
There are no files selected for viewing
132 changes: 38 additions & 94 deletions
132
templatespiler-converter/src/Templatespiler/IR/Imperative.hs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,105 +1,49 @@ | ||
{-# LANGUAGE DerivingStrategies #-} | ||
{-# LANGUAGE OverloadedStrings #-} | ||
|
||
-- | A lightweight imperative language that is used as an IR | ||
{- | Imperative flavoured IR for templatespiler. | ||
While there's different details, all imperative languages are gonna largely have the same structure: | ||
- read how many inputs there are | ||
- loop over said variable and read more things | ||
- insert to an array if necessary | ||
- repeat if necessary | ||
- print something (not our concern) | ||
-} | ||
module Templatespiler.IR.Imperative where | ||
|
||
import Templatespiler.IR.Common | ||
import Templatespiler.IR.Common (SingleLineString) | ||
import Prelude hiding (Type) | ||
|
||
import Prettyprinter | ||
newtype VarName = VarName Text | ||
|
||
import Prelude hiding (group) | ||
data Terminal | ||
= StringTerminal | ||
| IntegerTerminal | ||
| FloatTerminal | ||
|
||
withSuffix :: VarName -> Text -> VarName | ||
withSuffix (VarName (n :| ns)) suffix = VarName (n :| (ns <> [suffix])) | ||
|
||
type Program = [Statement] | ||
data Type | ||
= TerminalType Terminal | ||
| -- | An "array", which may be a list or a fixed size array depending on target language. The length must be known at compile time. | ||
ArrayType | ||
VarName | ||
Type | ||
|
||
data Statement | ||
= -- | Variable declaration. This may be a C-style declaration (@int x@) or an assignment (@x = 0@) depending on the target language. | ||
Decl | ||
= -- | Variable declaration, for statically typed languages or initialization for scope | ||
DeclareVar VarName Type | ||
| -- | Read one or more variables from stdin, separated by spaces. Having this as a single statement means more idiomatic usage of things like scanf in C. | ||
ReadVars | ||
SingleLineString | ||
-- ^ Separator string | ||
(NonEmpty (VarName, Type)) | ||
-- ^ Variable names and types | ||
| LoopNTimes | ||
VarName | ||
-- ^ The variable name | ||
VarType | ||
-- ^ The type | ||
| Assign VarName VarType Expr | ||
| -- | Read 1 line of input, split it by some separator, and then read into separate variables | ||
MultiReadAssign | ||
Text | ||
-- ^ Separator | ||
(NonEmpty (VarName, ReadType)) | ||
| For | ||
VarName -- variable name | ||
Expr -- start | ||
Expr -- end | ||
[Statement] -- body | ||
| AppendToArray | ||
[Statement] | ||
| -- | Array assignment | ||
ArrayAssign | ||
VarName | ||
-- ^ array name | ||
Expr | ||
-- ^ index | ||
Expr | ||
-- ^ value | ||
deriving stock (Show) | ||
|
||
data VarType | ||
= IntType | ||
| FloatType | ||
| StringType | ||
| ArrayType Expr VarType | ||
| DynamicArrayType VarType | ||
| TupleOrStructType (Maybe VarName) (NonEmpty VarType) | ||
| UnknownType | ||
deriving stock (Show) | ||
|
||
data Expr | ||
= ConstInt Int | ||
| Var VarName | ||
| ReadAtom ReadType | ||
| TupleOrStruct (Maybe VarName) (NonEmpty Expr) | ||
deriving stock (Show) | ||
|
||
data ReadType | ||
= ReadInt | ||
| ReadFloat | ||
| ReadString | ||
deriving stock (Show, Eq, Ord) | ||
|
||
prettyExpr :: Expr -> Doc nn | ||
prettyExpr (ConstInt i) = pretty i | ||
prettyExpr (Var vn) = pretty vn | ||
prettyExpr (ReadAtom rt) = "read" <+> pretty rt | ||
prettyExpr (TupleOrStruct n es) = pretty n <> tupled (fmap prettyExpr (toList es)) | ||
|
||
prettyVarType :: VarType -> Doc ann | ||
prettyVarType IntType = "Int" | ||
prettyVarType FloatType = "Float" | ||
prettyVarType StringType = "String" | ||
prettyVarType (ArrayType e t) = prettyVarType t <> brackets (prettyExpr e) | ||
prettyVarType (DynamicArrayType t) = prettyVarType t <> "*" | ||
prettyVarType (TupleOrStructType n ts) = pretty n <> tupled (fmap prettyVarType (toList ts)) | ||
prettyVarType UnknownType = "UnknownType" | ||
|
||
instance Pretty ReadType where | ||
pretty ReadInt = "@Int" | ||
pretty ReadFloat = "@Float" | ||
pretty ReadString = "@String" | ||
|
||
instance Pretty Statement where | ||
pretty (Decl vn vt) = prettyVarType vt <+> pretty vn | ||
pretty (Assign vn vt e) = pretty vn <+> "=" <+> prettyExpr e | ||
pretty (MultiReadAssign sep vs) = "read" <+> dquotes (pretty sep) <+> hsep (fmap (\(vn, rt) -> pretty vn <> pretty rt) (toList vs)) | ||
pretty (For vn start end body) = | ||
group $ | ||
vsep | ||
[ nest 2 $ | ||
vsep | ||
[ "for" <+> parens (pretty vn <+> "in" <+> prettyExpr start <> ".." <> prettyExpr end) <+> "{" | ||
, vsep $ toList $ fmap pretty body | ||
] | ||
, "}" | ||
] | ||
pretty (AppendToArray vn idx val) = pretty vn <> brackets (prettyExpr idx) <+> "=" <+> prettyExpr val | ||
|
||
prettyProgram :: Program -> Doc ann | ||
prettyProgram = vsep . fmap pretty | ||
-- ^ Array variable name | ||
VarName | ||
-- ^ Index variable name | ||
VarName | ||
-- ^ Value variable name |