命令型プログラミング言語で記述されたプログラムを型チェックするために、Haskell でプログラムを記述しようとしています。
抽象構文は次のとおりです。
type Name = String
-- プログラムは一連の変数宣言 (リスト) と一連のステートメント (リスト) です。
type Prog = ([TypeEnv],[Stmt])
-- 変数宣言は型と変数名です
type TypeEnv = (Type,Name)
-- タイプは「int」または「bool」、または「int[]..[]」または「bool[]..[]」のいずれかです。
data Type = BaseType BT | ArrayType BT Int deriving Show
data BT = TyInt | TyBool deriving Show
-- ステートメントは次のいずれかです...
data Stmt =
Assign Name Exp -- ...assignment (<name> := <exp>;)
| If Exp [Stmt] [Stmt] -- ...if-then-else (if <bexp> { <stmt>* } else { <stmt>* })
| While Exp [Stmt] -- ...a while-loop (while <bexp> { <stmt>*> })
| Let Name Exp [Stmt] -- ...let bindings (let <name>=<exp> in { <stmt> *})
| LetArray Name [Exp] Exp [Stmt] -- ...let-array binding (letarray <name> [ <exp> ] .. [ <exp> ] := <exp> in { <stmt>* })
| Case Exp [(Int,[Stmt])] -- ...a case statements
| For Name Exp Exp [Stmt] -- ...a for-loop
| ArrayAssign Name [Exp] Exp -- ...or array assignment (<name> [ <exp> ] .. [ <exp> ] := <exp>;)
deriving Show
-- 式は次のいずれかです...
data Exp =
Add Exp Exp -- ...addition (<exp> + <exp>)
| Sub Exp Exp -- ...subtract (<exp> - <exp>)
| Mul Exp Exp -- ...multiplication (<exp> * <exp>)
| Neg Exp -- ...negation (-<exp>)
| Var Name -- ...a variable (<name>)
| LitInt Int -- ...an integer literal (e.g. 3, 0, 42, 1999)
| VarArray Name [Exp] -- ...or an array lookup (<name> [ <exp> ])
| IsEq Exp Exp -- ...test for equality (<exp> == <exp>)
| IsNEq Exp Exp -- ...test for inequality (<exp> != <exp>)
| IsGT Exp Exp -- ...test for greater-than (<exp> > <exp>)
| IsLT Exp Exp -- ...test for less-than (<exp> < <exp>)
| IsGTE Exp Exp -- ...test for greater-or-equal (<exp> >= <exp>)
| IsLTE Exp Exp -- ...test for less-or-equal (<exp> <= <exp>)
| And Exp Exp -- ...boolean and (<bexp> && <bexp>)
| Or Exp Exp -- ...boolean or (<bexp> || <bexp>)
| Not Exp -- ...boolean negation (!<bexp>)
| LitBool Bool -- ... or a boolean literal (true or false)
deriving Show
誰かが私の質問に完全に答える必要はありませんが、これまでに持っているものを提供したいと思います。誰かが私を正しい方向に向けたり、私が完全に間違っているかどうかを教えてくれたりすると、それは非常に役に立ちます.
プログラムを型チェックする関数は typecheck から始まります。typecheck は typecheckstmt を使用して最初のステートメントを型チェックし、typecheckstmtlist を使用してプログラムの残りを型チェックします。次に、これらの関数は typecheckexp を使用して式を型チェックします。明らかに、私は実装の非常に基本的なスケルトンを持っています。私が正しい方向に向かっているかどうか、そして誰かが指針を持っているかどうかを知りたいだけです。
typecheck :: Prog -> Bool
typecheck _ = True
typecheck (types, x: xs) = (typecheckstmt types x) && (typecheckstmtlist types xs)
typecheckstmt :: [TypeEnv] -> Stmt -> Bool
typecheckstmt _ _ = True
typecheckstmt types (Assign x e) = if checkequaltypes x e
then True && typecheckexp types e
else False
typecheckstmt types (If e stmtlst1 stmtlst2) = typecheckexp types e
&& typecheckstmtlist types stmtlst1
&& typecheckstmtlist types stmtlst2
typecheckstmt types (While e stmtlst) = typecheckexp types e
&& typecheckstmtlist types stmtlst
typecheckstmt types (Let x e stmtlst) = if checkequaltype types x e
then True && typecheckexp types e
&& typecheckstmtlist types stmtlst
else False
typecheckstmt types (LetArray x es e2 stmtlst) =
typecheckstmt types (Case e cases) =
typecheckstmt types (For x e1 e2 stmtlst) = if checkequaltype types x e1
&& checkequaltype types x e2
then True && typecheckstmtlist stmtlst
else False
typecheckstmt types (ArrayAssign x es e2) =
typecheckstmtlist :: [TypeEnv] -> [Stmt] -> Bool
typecheckstmtlist _ _ = True
typecheckstmtlist types [x] = typecheckstmt types x
typecheckstmtlist types x:xs = typecheckstmt types x && typecheckstmtlist types xs
typecheckexp :: [TypeEnv] -> Exp -> Bool
typecheckexp types (Add e1 e2) =
typecheckexp types (Sub e1 e2) =
typecheckexp types (Mul e1 e2) =
typecheckexp types (Neg e1) =
typecheckexp types (Var x) =
typecheckexp types (LitInt i) =
typecheckexp types (VarArray x explist) =
typecheckexp types (IsEq e1 e2) =
typecheckexp types (IsNEq e1 e2) =
typecheckexp types (IsGT e1 e2) =
typecheckexp types (IsLT e1 e2) =
typecheckexp types (IsGTE e1 e2) =
typecheckexp types (IsLTE e1 e2) =
typecheckexp types (And e1 e2) =
typecheckexp types (Or e1 e2) =
typecheckexp types (Not e) =
typecheckexp types (LitBool Bool) =
typecheckexplist :: [TypeEnv] -> [Exp] -> Bool
typecheckexplist _ _ = True
typecheckexplist types [x] = typecheckexp types x
typecheckexplist types x:xs = typecheckexp types x && typecheckexplist types xs
checkequaltype :: [TypeEnv] -> Name -> Exp -> Bool
checkequaltype types x e = getTypeOfVar types x && getTypeOfExp types e
getTypeOfVar :: [TypeEnv] -> Name -> Type
getTypeOfExp :: [TypeEnv] -> Exp -> Type
また、何をチェックする必要があるのか についても少し曖昧です。明らかに、変数/式を割り当てて比較する場合は、それらを同じ型にする必要があります。
どんな助けでも大歓迎です。