aboutsummaryrefslogtreecommitdiff
path: root/Sil/Check.icl
diff options
context:
space:
mode:
Diffstat (limited to 'Sil/Check.icl')
-rw-r--r--Sil/Check.icl79
1 files changed, 60 insertions, 19 deletions
diff --git a/Sil/Check.icl b/Sil/Check.icl
index c4ab5f0..fc80324 100644
--- a/Sil/Check.icl
+++ b/Sil/Check.icl
@@ -1,5 +1,6 @@
implementation module Sil.Check
+import StdBool
import StdFile
from StdFunc import flip, o
import StdList
@@ -8,6 +9,7 @@ import StdString
import StdTuple
from Data.Func import $, mapSt, seqSt
+import Data.List
import Data.Maybe
import Data.Tuple
from Text import <+
@@ -16,6 +18,12 @@ import Sil.Syntax
instance toString CheckError
where
+ toString NoMainFunction
+ = "Error: no main function."
+ toString (DuplicateFunctionName n)
+ = "Error: multiply defined: '" <+ n <+ "'."
+ toString (DuplicateLocalName f arg)
+ = "Error: multiply defined: '" <+ arg <+ "' in '" <+ f <+ "'."
toString (ReturnExpressionFromVoidError f)
= "Type error: an expression was returned from void function '" <+ f <+ "'."
toString (NoReturnFromNonVoidError f)
@@ -24,30 +32,63 @@ where
instance <<< CheckError where <<< f e = f <<< toString e <<< "\r\n"
checkProgram :: *(Maybe *File) Program -> *([CheckError], *Maybe *File)
-checkProgram err prog = appFst flatten $ mapSt (flip checkFunction) prog.p_funs err
+checkProgram err prog
+ = checkErrors [checkFunctionNames, checkMainFunction] prog
+ $ appFst flatten $ mapSt (flip checkFunction) prog.p_funs err
+where
+ checkMainFunction :: Program -> [CheckError]
+ checkMainFunction p = case [f \\ f <- p.p_funs | f.f_name == "main"] of
+ [] -> [NoMainFunction]
+ _ -> []
+
+ checkFunctionNames :: Program -> [CheckError]
+ checkFunctionNames p =
+ [ DuplicateFunctionName $ hd fs
+ \\ fs <- tails [f.f_name \\ f <- p.p_funs]
+ | not (isEmpty fs) && isMember (hd fs) (tl fs)]
checkFunction :: *(Maybe *File) Function -> *([CheckError], *Maybe *File)
-checkFunction err f = checkErrors [checkReturnAndVoid] f err
+checkFunction err f = checkErrors [checkLocals, checkReturnAndVoid] f $ noErrors err
where
- checkReturnAndVoid :: Function -> Maybe CheckError
+ checkReturnAndVoid :: Function -> [CheckError]
checkReturnAndVoid f = case f.f_type of
TVoid -> case [st \\ st=:(Return (Just _)) <- allStatements f] of
- [] -> Nothing
- _ -> Just $ ReturnExpressionFromVoidError f.f_name
- _ -> if (sureToReturn f.f_code) Nothing (Just $ NoReturnFromNonVoidError f.f_name)
-
- sureToReturn :: CodeBlock -> Bool
- sureToReturn cb = case cb.cb_content of
- [] -> False
- sts -> case last sts of
- Return _ -> True
- While _ cb` -> sureToReturn cb`
- If bs (Just e) -> all sureToReturn [e:map snd bs]
- If bs Nothing -> all (sureToReturn o snd) bs
- _ -> False
-
-checkErrors :: [(a -> Maybe CheckError)] a *(Maybe *File) -> *([CheckError], *Maybe *File)
-checkErrors cks x err = seqSt error (catMaybes $ map (flip ($) x) cks) $ noErrors err
+ [] -> []
+ _ -> [ReturnExpressionFromVoidError f.f_name]
+ _ -> if (sureToReturn f.f_code) [] [NoReturnFromNonVoidError f.f_name]
+ where
+ sureToReturn :: CodeBlock -> Bool
+ sureToReturn cb = case cb.cb_content of
+ [] -> False
+ sts -> case last sts of
+ Return _ -> True
+ While _ cb` -> sureToReturn cb`
+ If bs (Just e) -> all sureToReturn [e:map snd bs]
+ If bs Nothing -> all (sureToReturn o snd) bs
+ _ -> False
+
+ checkLocals :: Function -> [CheckError]
+ checkLocals f = check [a.arg_name \\ a <- f.f_args] f.f_code
+ where
+ check :: [Name] CodeBlock -> [CheckError]
+ check defined cb =
+ [DuplicateLocalName f.f_name l \\ l <- defined | isMember l locals] ++
+ concatMap (check (locals ++ defined)) (underlyingCBs cb)
+ where locals = [i.init_name \\ i <- cb.cb_init]
+
+ underlyingCBs :: CodeBlock -> [CodeBlock]
+ underlyingCBs cb = concatMap findCBs cb.cb_content
+ where
+ findCBs (Declaration _ _) = []
+ findCBs (Application _) = []
+ findCBs (Return _) = []
+ findCBs (If bs (Just e)) = [e:map snd bs]
+ findCBs (If bs Nothing) = map snd bs
+ findCBs (While _ cb) = [cb]
+ findCBs (MachineStm _) = []
+
+checkErrors :: [(a -> [CheckError])] a *([CheckError], Maybe *File) -> *([CheckError], *Maybe *File)
+checkErrors cks x st = seqSt error (concatMap (flip ($) x) cks) st
error :: CheckError *([CheckError], *Maybe *File) -> *([CheckError], *Maybe *File)
error e (es, err) = ([e:es], err <?< e)