diff options
author | Juan J. Martinez <jjm@usebox.net> | 2022-08-30 23:21:50 +0100 |
---|---|---|
committer | Juan J. Martinez <jjm@usebox.net> | 2022-08-30 23:26:10 +0100 |
commit | 90a8f16e5f1d852f21fbbaf2b0631d348973152a (patch) | |
tree | 44f9e3c284a4d5b8f2c8df708cd6592616714acf | |
parent | aaf2ef628772e5789203544ac6226b467891d1d9 (diff) | |
download | micro-lang-hs-90a8f16e5f1d852f21fbbaf2b0631d348973152a.tar.gz micro-lang-hs-90a8f16e5f1d852f21fbbaf2b0631d348973152a.zip |
Check undefined types
-rw-r--r-- | src/Compiler.hs | 26 | ||||
-rw-r--r-- | src/Error.hs | 3 | ||||
-rw-r--r-- | test/Language.hs | 24 |
3 files changed, 51 insertions, 2 deletions
diff --git a/src/Compiler.hs b/src/Compiler.hs index f788c11..785efab 100644 --- a/src/Compiler.hs +++ b/src/Compiler.hs @@ -3,6 +3,7 @@ module Compiler where import qualified Ast as A import Control.Monad.State import Data.Either (rights) +import Data.Maybe (catMaybes, fromMaybe) import Env import Error import System.Environment (getEnv, getEnvironment) @@ -77,6 +78,29 @@ typecheckReturn (Just value) fret = do else return $ Just $ "invalid return value\n found: " ++ showMaybet r ++ "\n expected: " ++ showMaybet fret Left _ -> return $ Nothing -- error resolving return value +-- built-in types +types = ["bool", "u8", "s8", "u16", "s16"] + +definedType :: A.Type -> Bool +definedType (A.Type t) = t `elem` types +definedType (A.FuncType ts r) = + all definedType ts && fromMaybe False (fmap definedType r) + +verifyFuncTypes :: String -> [A.FuncParam] -> Maybe A.Type -> SourcePos -> [Error] +verifyFuncTypes ident params ret pos = do + ( catMaybes $ + map + ( \(id, t, pos) -> + if not (definedType t) + then Just $ Error UndefinedType ("undefined type in \"" ++ id ++ "\"") pos + else Nothing + ) + params + ) + ++ if not (fromMaybe True (fmap definedType ret)) + then [Error UndefinedType ("undefined return type in \"" ++ ident ++ "\"") pos] + else [] + compile :: A.Expr -> State CompState CompResult compile x = do case x of @@ -90,6 +114,8 @@ compile x = do (A.Func ident params ret body priv anon pos) -> do -- current env (ev, errs) <- get + -- check for undefined types + (ev, errs) <- return $ (ev, (verifyFuncTypes ident params ret pos) ++ errs) -- updated with the function (ev, errs) <- return $ case addSymUniq ev (ident, ftype, pos) of diff --git a/src/Error.hs b/src/Error.hs index 40bb046..9aad85d 100644 --- a/src/Error.hs +++ b/src/Error.hs @@ -4,7 +4,7 @@ import Data.List (sort) import Text.Parsec (SourcePos, errorPos) import Text.Parsec.Error (ParseError, errorMessages, showErrorMessages) -data ErrorType = GenericError | TypeError | UnexpectedReturn | AlreadyDefined | NonCallable | Undefined deriving (Show) +data ErrorType = GenericError | TypeError | UnexpectedReturn | AlreadyDefined | NonCallable | Undefined | UndefinedType deriving (Show) instance Enum ErrorType where fromEnum GenericError = 0 @@ -13,6 +13,7 @@ instance Enum ErrorType where fromEnum AlreadyDefined = 3 fromEnum NonCallable = 4 fromEnum Undefined = 5 + fromEnum UndefinedType = 6 toEnum _ = error "toEnum is undefined for Error" data Error = Error ErrorType String SourcePos diff --git a/test/Language.hs b/test/Language.hs index 448e6ad..12c724a 100644 --- a/test/Language.hs +++ b/test/Language.hs @@ -253,6 +253,26 @@ testCase20 = \}\n" E.Undefined +testCase21 = + TestLabel "undefined type in function parameters" $ + TestCase $ + expectError + "module main\n\ + \def fn(a: undef): bool {\n\ + \return true;\n\ + \}\n" + E.UndefinedType + +testCase22 = + TestLabel "undefined type in function return type" $ + TestCase $ + expectError + "module main\n\ + \def fn(): undef {\n\ + \return true;\n\ + \}\n" + E.UndefinedType + language = [ testCase2, testCase3, @@ -272,5 +292,7 @@ language = testCase17, testCase18, testCase19, - testCase20 + testCase20, + testCase21, + testCase22 ] |