Skip to content

Commit

Permalink
Add type checker
Browse files Browse the repository at this point in the history
  • Loading branch information
guillaumeAbel committed Jan 14, 2024
1 parent 9505160 commit a0f771e
Show file tree
Hide file tree
Showing 5 changed files with 235 additions and 64 deletions.
102 changes: 102 additions & 0 deletions lvtc/lvtc.cabal
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
cabal-version: 2.2

-- This file has been generated from package.yaml by hpack version 0.36.0.
--
-- see: https://github.com/sol/hpack

name: lvtc
version: 0.1.0.0
description: Please see the README on GitHub at <https://github.com/githubuser/lvtc#readme>
homepage: https://github.com/githubuser/lvtc#readme
bug-reports: https://github.com/githubuser/lvtc/issues
author: Author name here
maintainer: [email protected]
copyright: 2023 Author name here
license: BSD-3-Clause
license-file: LICENSE
build-type: Simple
extra-source-files:
README.md
CHANGELOG.md

source-repository head
type: git
location: https://github.com/githubuser/lvtc

library
exposed-modules:
Alias
AST
Builtins
Expression
Leb128Encode
Lexeme
Lib
LvtLibVersion
ParseLvt
Parser
ParseUtil
ShuntingYard
TypeCheck
Wasm
WasmUtils
WatAST
WatLike
WatLikeToWat
WatToWasm
WriteWasm
other-modules:
Paths_lvtc
autogen-modules:
Paths_lvtc
hs-source-dirs:
src
ghc-options: -Wall -Wcompat -Widentities -Wincomplete-record-updates -Wincomplete-uni-patterns -Wmissing-export-lists -Wmissing-home-modules -Wpartial-fields -Wredundant-constraints
build-depends:
base >=4.7 && <5
, bytestring
default-language: Haskell2010

executable lvtc-exe
main-is: Main.hs
other-modules:
Args
Run
Version
Paths_lvtc
autogen-modules:
Paths_lvtc
hs-source-dirs:
app
ghc-options: -Wall -Wcompat -Widentities -Wincomplete-record-updates -Wincomplete-uni-patterns -Wmissing-export-lists -Wmissing-home-modules -Wpartial-fields -Wredundant-constraints -threaded -rtsopts -with-rtsopts=-N
build-depends:
base >=4.7 && <5
, directory
, filepath
, lvtc
default-language: Haskell2010

test-suite lvtc-test
type: exitcode-stdio-1.0
main-is: Spec.hs
other-modules:
UTLexeme
UTParseLvt
UTShuntingYard
UTTypeCheck
UTWasm
UTWat
UTWatLike
Paths_lvtc
autogen-modules:
Paths_lvtc
hs-source-dirs:
test
ghc-options: -Wall -Wcompat -Widentities -Wincomplete-record-updates -Wincomplete-uni-patterns -Wmissing-export-lists -Wmissing-home-modules -Wpartial-fields -Wredundant-constraints -threaded -rtsopts -with-rtsopts=-N
build-depends:
base >=4.7 && <5
, lvtc
, process
, tasty
, tasty-hunit
default-language: Haskell2010
107 changes: 66 additions & 41 deletions lvtc/src/TypeCheck.hs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@ module TypeCheck
) where

import AST
import Debug.Trace

data Env = Env FuncPrototype [VarAssignation] [FuncPrototype]

Expand All @@ -26,11 +25,12 @@ findVarInVar s ((s', v):xs) env
| s == s' = findValueType v env
| otherwise = findVarInVar s xs env

findTypeReturnFunc :: Symbol -> [FuncPrototype] -> Maybe FuncPrototype
findTypeReturnFunc _ [] = Nothing
findTypeReturnFunc s ((s', ps, t):xs)
| s == s' = Just (s', ps, t)
| otherwise = findTypeReturnFunc s xs
findTypeReturnFunc :: Symbol -> Env -> Maybe FuncPrototype
findTypeReturnFunc s (Env (e, s', ps, t) _ _) | s == s' = Just (e, s', ps, t)
findTypeReturnFunc _ (Env _ _ []) = Nothing
findTypeReturnFunc s (Env proto vars ((e, s', ps, t):xs))
| s == s' = Just (e, s', ps, t)
| otherwise = findTypeReturnFunc s (Env proto vars xs)

getValueType :: Value -> Maybe Type
getValueType (Integer _) = Just "Int"
Expand All @@ -40,43 +40,44 @@ getValueType _ = Nothing

checkFuncType :: [Value] -> Env -> Maybe FuncPrototype -> Maybe Type
checkFuncType _ _ Nothing = Nothing
checkFuncType [] _ _ = Nothing
checkFuncType callParams (Env proto params env) (Just (_, ps, t))
checkFuncType callParams (Env proto params env) (Just (_, _, ps, t))
| checkVarsTypes callParams (Just ps) (Env proto params env) = Just t
| otherwise = Nothing

handleFinders :: Maybe Type -> Symbol -> Env -> Maybe Type
handleFinders _ _ (Env (_, [], _) [] _) = Nothing
handleFinders Nothing s (Env proto vars env) = findVarInVar s vars (Env proto vars env)
handleFinders _ _ (Env (_, _, [], _) [] _) = Nothing
handleFinders Nothing s (Env proto vars env) =
findVarInVar s vars (Env proto vars env)
handleFinders (Just t) _ _ = Just t

findValueType :: Value -> Env -> Maybe Type
findValueType (Var s) (Env (ps, params, t) vars env) =
handleFinders (findVarInParams s params (Env (ps, params, t) vars env)) s (Env (ps, params, t) vars env)
findValueType (FuncValue (s, vs)) (Env proto vars env) = checkFuncType vs (Env proto vars env) (findTypeReturnFunc s env)
findValueType (Var s) (Env (e, ps, params, t) vars env) =
handleFinders (findVarInParams s params (Env (e, ps, params, t) vars env))
s (Env (e, ps, params, t) vars env)
findValueType (FuncValue (s, vs)) env =
checkFuncType vs env (findTypeReturnFunc s env)
findValueType v _ = getValueType v

checkValueType :: Type -> Maybe Type -> Bool
checkValueType _ Nothing = False
checkValueType t (Just t') = t == t'

assertTypeAndValue :: Type -> Value -> Env -> Bool
assertTypeAndValue _ (Var _) (Env (_, [], _) [] _) = False
assertTypeAndValue _ (FuncValue _) (Env (_, _, _) _ []) = False
assertTypeAndValue _ (Var _) (Env (_, _, [], _) [] _) = False
assertTypeAndValue t v env = checkValueType t (findValueType v env)

assertMTypeAndValue :: Maybe Type -> Value -> Env -> Bool
assertMTypeAndValue Nothing _ _ = False
assertMTypeAndValue (Just t) v env = assertTypeAndValue t v env
sFu

isTypeValid :: Type -> Bool
isTypeValid "Int" = True
isTypeValid "Bool" = True
isTypeValid _ = False

checkVarsTypes :: [Value] -> Maybe [Var] -> Env -> Bool
checkVarsTypes [] _ _ = False
checkVarsTypes _ Nothing _ = False
checkVarsTypes [] (Just []) _ = True
checkVarsTypes values (Just param) _ | length values /= length param = False
checkVarsTypes [v] (Just [(_, t)]) env = assertTypeAndValue t v env
checkVarsTypes (v:vs) (Just ((_, t):xs)) env
Expand All @@ -86,30 +87,48 @@ checkVarsTypes _ _ _ = False

findFunc :: Symbol -> [FuncPrototype] -> Maybe [Var]
findFunc _ [] = Nothing
findFunc s ((s', params, _):_) | s == s' = Just params
findFunc s ((_, s', params, _):_) | s == s' = Just params
findFunc s (_:xs) = findFunc s xs

checkCall :: FuncCall -> Env -> [Instruction] -> Bool
checkCall (symbol, values) (Env (s, params, t) vars env) xs
| s == symbol && checkVarsTypes values (Just params) (Env (s, params, t) vars env) ||
checkVarsTypes values (findFunc symbol env) (Env (s, params, t) vars env) =
checkInstructions xs (Env (s, params, t) vars env)
checkCall (symbol, values) (Env (e, s, params, t) vars env) xs
| s == symbol &&
checkVarsTypes values (Just params) (Env (e, s, params, t) vars env) ||
checkVarsTypes values (findFunc symbol env)
(Env (e, s, params, t) vars env) =
checkInstructions xs (Env (e, s, params, t) vars env)
| otherwise = False

checkReturn :: Value -> Env -> [Instruction] -> Bool
checkReturn v (Env (s, params, t) vars env) xs
| assertTypeAndValue t v (Env (s, params, t) vars env) =
checkInstructions xs (Env (s, params, t) vars env)
checkReturn v (Env (e, s, params, t) vars env) xs
| assertTypeAndValue t v (Env (e, s, params, t) vars env) =
checkInstructions xs (Env (e, s, params, t) vars env)
checkReturn _ _ _ = False

findInVar :: Symbol -> [Var] -> Bool
findInVar _ [] = False
findInVar s ((s', _):_) | s == s' = True
findInVar s (_:xs) = findInVar s xs

searchName :: Symbol -> [VarAssignation] -> [Var] -> Bool
searchName s [] vars = findInVar s vars
searchName s ((s', _):_) _ | s == s' = True
searchName s (_:xs) params = searchName s xs params

nameExist :: Symbol -> FuncPrototype -> [VarAssignation] -> Bool
nameExist s (_, s', _, _) _ | s == s' = True
nameExist s (_, _, params, _) vs = searchName s vs params

checkDeclaration :: VarDeclaration -> Env -> [Instruction] -> Bool
checkDeclaration ((s, t), v) (Env proto vars env) xs |
assertTypeAndValue t v (Env proto vars env) =
checkInstructions xs (Env proto ((s, v):vars) env)
checkDeclaration ((s, t), v) (Env proto vars env) xs
| not (nameExist s proto vars) &&
assertTypeAndValue t v (Env proto vars env) =
checkInstructions xs (Env proto ((s, v):vars) env)
checkDeclaration _ _ _ = False

checkAssignation :: VarAssignation -> Env -> [Instruction] -> Bool
checkAssignation (s, v) env xs | assertMTypeAndValue (findValueType (Var s) env) v env =
checkAssignation (s, v) env xs |
assertMTypeAndValue (findValueType (Var s) env) v env =
checkInstructions xs env
checkAssignation _ _ _ = False

Expand All @@ -121,32 +140,36 @@ checkCondition _ _ _ = False

checkInstructions :: [Instruction] -> Env -> Bool
checkInstructions [] _ = True
checkInstructions ((Call func):xs) env = checkCall func env xs
checkInstructions ((Function func):xs) env = checkCall func env xs
checkInstructions ((Return ret):xs) env = checkReturn ret env xs
checkInstructions ((Declaration declaration):xs) env = checkDeclaration declaration env xs
checkInstructions ((Assignation assignation):xs) env = checkAssignation assignation env xs
checkInstructions ((Declaration declaration):xs) env =
checkDeclaration declaration env xs
checkInstructions ((Assignation assignation):xs) env =
checkAssignation assignation env xs
checkInstructions ((Cond condition):xs) env = checkCondition condition env xs

checkVarTypes :: [Var] -> Bool
checkVarTypes [] = True
checkVarTypes [x] = isTypeValid (snd x)
checkVarTypes (x:xs) | isTypeValid (snd x) = checkVarTypes xs
checkVarTypes _ = False

checkFunction :: FuncDeclaration -> [FuncPrototype] -> Bool
checkFunction ((_, args, _), _) _ | not (checkVarTypes args) = False
checkFunction ((_, _, t), _) _ | not (isTypeValid t) = False
checkFunction ((_, _, args, _), _) _ | not (checkVarTypes args) = False
checkFunction ((_, _, _, t), _) _ | not (isTypeValid t) = False
checkFunction (prototype, instructions) env
| checkInstructions instructions (Env prototype [] env) = True
checkFunction _ _ = False

checkNotExisting :: FuncDeclaration -> [FuncPrototype] -> Bool
checkNotExisting _ [] = True
checkNotExisting ((s, args, t), instr) ((ls, _, _):xs)
checkNotExisting ((e, s, args, t), instr) ((_, ls, _, _):xs)
| s == ls = False
| otherwise = checkNotExisting ((s, args, t), instr) xs
| otherwise = checkNotExisting ((e, s, args, t), instr) xs

receiveCheckFuncRes :: Bool -> [FuncDeclaration] -> FuncDeclaration -> [FuncPrototype] -> Bool
receiveCheckFuncRes True xs (prototype, _) env = checkDeclarations xs (Just (prototype:env))
receiveCheckFuncRes True xs (prototype, _) env =
checkDeclarations xs (Just (prototype:env))
receiveCheckFuncRes _ _ _ _ = False

checkDeclarations :: [FuncDeclaration] -> Maybe [FuncPrototype] -> Bool
Expand All @@ -158,14 +181,15 @@ checkDeclarations (func:xs) (Just env)
| otherwise = False

createCalcPrototype :: Symbol -> Type -> FuncPrototype
createCalcPrototype s t = (s, [("x", t), ("y", t)], "Int")
createCalcPrototype s t = (False, s, [("x", t), ("y", t)], "Int")

createCompPrototype :: Symbol -> Type -> FuncPrototype
createCompPrototype s t = (s, [("x", t), ("y", t)], "Bool")
createCompPrototype s t = (False, s, [("x", t), ("y", t)], "Bool")

createCompPolyMorph :: Symbol -> [Type] -> [FuncPrototype]
createCompPolyMorph _ [] = []
createCompPolyMorph s (x:xs) = createCompPrototype s x : createCompPolyMorph s xs
createCompPolyMorph s (x:xs) =
createCompPrototype s x : createCompPolyMorph s xs

createCompOp :: [Symbol] -> [FuncPrototype]
createCompOp [] = []
Expand All @@ -176,7 +200,8 @@ createCalcOp [] = []
createCalcOp (x:xs) = createCalcPrototype x "Int" : createCalcOp xs

defaultEnv :: Maybe [FuncPrototype]
defaultEnv = Just (createCalcOp ["+", "-", "*", "%", "/"] ++ createCompOp ["==", "!=", "<", ">", "<=", ">="])
defaultEnv = Just (createCalcOp ["+", "-", "*", "%", "/"] ++
createCompOp ["==", "!=", "<", ">", "<=", ">="])

typeCheck :: [FuncDeclaration] -> Bool
typeCheck expressions = checkDeclarations expressions defaultEnv
4 changes: 3 additions & 1 deletion lvtc/test/Spec.hs
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import UTWatLike
import UTWat
import UTWasm
import UTLexeme
import UTTypeCheck

main :: IO ()
main = defaultMain tests
Expand All @@ -33,7 +34,8 @@ tests = testGroup "Leviator Tests - Compiler"
utWatLike,
utWat,
utWasm,
utLexeme
utLexeme,
uTTypeCheck
]

testParserHelper :: String -> String -> Expression -> IO ()
Expand Down
Loading

0 comments on commit a0f771e

Please sign in to comment.