308 id2C IOInsert i = id2C (IOInsertWithType empty) i |
308 id2C IOInsert i = id2C (IOInsertWithType empty) i |
309 id2C (IOInsertWithType d) (Identifier i t) = do |
309 id2C (IOInsertWithType d) (Identifier i t) = do |
310 tom <- gets (Set.member n . toMangle) |
310 tom <- gets (Set.member n . toMangle) |
311 cu <- gets currentUnit |
311 cu <- gets currentUnit |
312 let (i', t') = case (t, tom) of |
312 let (i', t') = case (t, tom) of |
313 (BTFunction _ p _, True) -> (cu ++ i ++ ('_' : show (length p)), t) |
313 (BTFunction _ e p _, True) -> ((if e then id else (++) cu) $ i ++ ('_' : show (length p)), t) |
314 (BTFunction _ _ _, _) -> (cu ++ i, t) |
314 (BTFunction _ e _ _, _) -> ((if e then id else (++) cu) i, t) |
315 (BTVarParam t'', _) -> ('(' : '*' : i ++ ")" , t'') |
315 (BTVarParam t'', _) -> ('(' : '*' : i ++ ")" , t'') |
316 _ -> (i, t) |
316 _ -> (i, t) |
317 modify (\s -> s{currentScope = Map.insertWith (++) n [Record i' t' d] (currentScope s), lastIdentifier = n}) |
317 modify (\s -> s{currentScope = Map.insertWith (++) n [Record i' t' d] (currentScope s), lastIdentifier = n}) |
318 return $ text i' |
318 return $ text i' |
319 where |
319 where |
479 abc = hcat . punctuate comma . map (char . fst) $ ps |
479 abc = hcat . punctuate comma . map (char . fst) $ ps |
480 cparams = hcat . punctuate comma . map (\(c, v) -> if v then char '&' <> parens (char c) else char c) $ ps |
480 cparams = hcat . punctuate comma . map (\(c, v) -> if v then char '&' <> parens (char c) else char c) $ ps |
481 ps = zip ['a'..] (toIsVarList params) |
481 ps = zip ['a'..] (toIsVarList params) |
482 |
482 |
483 fun2C :: Bool -> String -> TypeVarDeclaration -> State RenderState [Doc] |
483 fun2C :: Bool -> String -> TypeVarDeclaration -> State RenderState [Doc] |
484 fun2C _ _ (FunctionDeclaration name _ overload returnType params Nothing) = do |
484 fun2C _ _ (FunctionDeclaration name _ overload external returnType params Nothing) = do |
485 t <- type2C returnType |
485 t <- type2C returnType |
486 t'<- gets lastType |
486 t'<- gets lastType |
487 bts <- typeVarDecl2BaseType params |
487 bts <- typeVarDecl2BaseType params |
488 p <- withState' id $ functionParams2C params |
488 p <- withState' id $ functionParams2C params |
489 n <- liftM render . id2C IOInsert $ setBaseType (BTFunction False bts t') name |
489 n <- liftM render . id2C IOInsert $ setBaseType (BTFunction False external bts t') name |
490 let decor = if overload then text "__attribute__((overloadable))" else empty |
490 let decor = if overload then text "__attribute__((overloadable))" else empty |
491 return [t empty <+> decor <+> text n <> parens p] |
491 return [t empty <+> decor <+> text n <> parens p] |
492 |
492 |
493 fun2C True rv (FunctionDeclaration name@(Identifier i _) inline overload returnType params (Just (tvars, phrase))) = do |
493 fun2C True rv (FunctionDeclaration name@(Identifier i _) inline overload external returnType params (Just (tvars, phrase))) = do |
494 let isVoid = case returnType of |
494 let isVoid = case returnType of |
495 VoidType -> True |
495 VoidType -> True |
496 _ -> False |
496 _ -> False |
497 |
497 |
498 let res = docToLower $ text rv <> if isVoid then empty else text "_result" |
498 let res = docToLower $ text rv <> if isVoid then empty else text "_result" |
501 |
501 |
502 bts <- typeVarDecl2BaseType params |
502 bts <- typeVarDecl2BaseType params |
503 --cu <- gets currentUnit |
503 --cu <- gets currentUnit |
504 notDeclared <- liftM isNothing . gets $ Map.lookup (map toLower i) . currentScope |
504 notDeclared <- liftM isNothing . gets $ Map.lookup (map toLower i) . currentScope |
505 |
505 |
506 n <- liftM render . id2C IOInsert $ setBaseType (BTFunction hasVars bts t') name |
506 n <- liftM render . id2C IOInsert $ setBaseType (BTFunction hasVars external bts t') name |
507 let resultId = if isVoid |
507 let resultId = if isVoid |
508 then n -- void type doesn't have result, solving recursive procedure calls |
508 then n -- void type doesn't have result, solving recursive procedure calls |
509 else (render res) |
509 else (render res) |
510 |
510 |
511 (p, ph) <- withState' (\st -> st{currentScope = Map.insertWith un (map toLower rv) [Record resultId (if isVoid then (BTFunction hasVars bts t') else t') empty] $ currentScope st |
511 (p, ph) <- withState' (\st -> st{currentScope = Map.insertWith un (map toLower rv) [Record resultId (if isVoid then (BTFunction hasVars False bts t') else t') empty] $ currentScope st |
512 , currentFunctionResult = if isVoid then [] else render res}) $ do |
512 , currentFunctionResult = if isVoid then [] else render res}) $ do |
513 p <- functionParams2C params |
513 p <- functionParams2C params |
514 ph <- liftM2 ($+$) (typesAndVars2C False False True tvars) (phrase2C' phrase) |
514 ph <- liftM2 ($+$) (typesAndVars2C False False True tvars) (phrase2C' phrase) |
515 return (p, ph) |
515 return (p, ph) |
516 |
516 |
537 phrase2C' p = phrase2C p |
537 phrase2C' p = phrase2C p |
538 un [a] b = a : b |
538 un [a] b = a : b |
539 un _ _ = error "fun2C u: pattern not matched" |
539 un _ _ = error "fun2C u: pattern not matched" |
540 hasVars = hasPassByReference params |
540 hasVars = hasPassByReference params |
541 |
541 |
542 fun2C False _ (FunctionDeclaration (Identifier name _) _ _ _ _ _) = error $ "nested functions not allowed: " ++ name |
542 fun2C False _ (FunctionDeclaration (Identifier name _) _ _ _ _ _ _) = error $ "nested functions not allowed: " ++ name |
543 fun2C _ tv _ = error $ "fun2C: I don't render " ++ show tv |
543 fun2C _ tv _ = error $ "fun2C: I don't render " ++ show tv |
544 |
544 |
545 -- the second bool indicates whether declare variable as extern or not |
545 -- the second bool indicates whether declare variable as extern or not |
546 -- the third bool indicates whether include types or not |
546 -- the third bool indicates whether include types or not |
547 -- the fourth bool indicates whether ignore initialization or not (basically for dynamic arrays since we cannot do initialization in function params) |
547 -- the fourth bool indicates whether ignore initialization or not (basically for dynamic arrays since we cannot do initialization in function params) |
548 tvar2C :: Bool -> Bool -> Bool -> Bool -> TypeVarDeclaration -> State RenderState [Doc] |
548 tvar2C :: Bool -> Bool -> Bool -> Bool -> TypeVarDeclaration -> State RenderState [Doc] |
549 tvar2C b _ includeType _ f@(FunctionDeclaration (Identifier name _) _ _ _ _ _) = do |
549 tvar2C b _ includeType _ f@(FunctionDeclaration (Identifier name _) _ _ _ _ _ _) = do |
550 t <- fun2C b name f |
550 t <- fun2C b name f |
551 if includeType then return t else return [] |
551 if includeType then return t else return [] |
552 tvar2C _ _ includeType _ (TypeDeclaration i' t) = do |
552 tvar2C _ _ includeType _ (TypeDeclaration i' t) = do |
553 i <- id2CTyped t i' |
553 i <- id2CTyped t i' |
554 tp <- type2C t |
554 tp <- type2C t |
939 e1 <- expr2C expr1 |
939 e1 <- expr2C expr1 |
940 t1 <- gets lastType |
940 t1 <- gets lastType |
941 e2 <- expr2C expr2 |
941 e2 <- expr2C expr2 |
942 t2 <- gets lastType |
942 t2 <- gets lastType |
943 case (op2C op, t1, t2) of |
943 case (op2C op, t1, t2) of |
944 ("+", BTAString, BTAString) -> expr2C $ BuiltInFunCall [expr1, expr2] (SimpleReference $ Identifier "_strconcatA" (BTFunction False [(False, t1), (False, t2)] BTString)) |
944 ("+", BTAString, BTAString) -> expr2C $ BuiltInFunCall [expr1, expr2] (SimpleReference $ Identifier "_strconcatA" (fff t1 t2 BTString)) |
945 ("+", BTAString, BTChar) -> expr2C $ BuiltInFunCall [expr1, expr2] (SimpleReference $ Identifier "_strappendA" (BTFunction False [(False, t1), (False, t2)] BTAString)) |
945 ("+", BTAString, BTChar) -> expr2C $ BuiltInFunCall [expr1, expr2] (SimpleReference $ Identifier "_strappendA" (fff t1 t2 BTAString)) |
946 ("!=", BTAString, BTAString) -> expr2C $ BuiltInFunCall [expr1, expr2] (SimpleReference $ Identifier "_strncompareA" (BTFunction False [(False, t1), (False, t2)] BTBool)) |
946 ("!=", BTAString, BTAString) -> expr2C $ BuiltInFunCall [expr1, expr2] (SimpleReference $ Identifier "_strncompareA" (fff t1 t2 BTBool)) |
947 (_, BTAString, _) -> error $ "unhandled bin op with ansistring on the left side: " ++ show bop |
947 (_, BTAString, _) -> error $ "unhandled bin op with ansistring on the left side: " ++ show bop |
948 (_, _, BTAString) -> error $ "unhandled bin op with ansistring on the right side: " ++ show bop |
948 (_, _, BTAString) -> error $ "unhandled bin op with ansistring on the right side: " ++ show bop |
949 ("+", BTString, BTString) -> expr2C $ BuiltInFunCall [expr1, expr2] (SimpleReference $ Identifier "_strconcat" (BTFunction False [(False, t1), (False, t2)] BTString)) |
949 ("+", BTString, BTString) -> expr2C $ BuiltInFunCall [expr1, expr2] (SimpleReference $ Identifier "_strconcat" (fff t1 t2 BTString)) |
950 ("+", BTString, BTChar) -> expr2C $ BuiltInFunCall [expr1, expr2] (SimpleReference $ Identifier "_strappend" (BTFunction False [(False, t1), (False, t2)] BTString)) |
950 ("+", BTString, BTChar) -> expr2C $ BuiltInFunCall [expr1, expr2] (SimpleReference $ Identifier "_strappend" (fff t1 t2 BTString)) |
951 ("+", BTChar, BTString) -> expr2C $ BuiltInFunCall [expr1, expr2] (SimpleReference $ Identifier "_strprepend" (BTFunction False [(False, t1), (False, t2)] BTString)) |
951 ("+", BTChar, BTString) -> expr2C $ BuiltInFunCall [expr1, expr2] (SimpleReference $ Identifier "_strprepend" (fff t1 t2 BTString)) |
952 ("+", BTChar, BTChar) -> expr2C $ BuiltInFunCall [expr1, expr2] (SimpleReference $ Identifier "_chrconcat" (BTFunction False [(False, t1), (False, t2)] BTString)) |
952 ("+", BTChar, BTChar) -> expr2C $ BuiltInFunCall [expr1, expr2] (SimpleReference $ Identifier "_chrconcat" (fff t1 t2 BTString)) |
953 ("==", BTString, BTChar) -> expr2C $ BuiltInFunCall [expr1, expr2] (SimpleReference $ Identifier "_strcomparec" (BTFunction False [(False, t1), (False, t2)] BTBool)) |
953 ("==", BTString, BTChar) -> expr2C $ BuiltInFunCall [expr1, expr2] (SimpleReference $ Identifier "_strcomparec" (fff t1 t2 BTBool)) |
954 |
954 |
955 -- for function/procedure comparision |
955 -- for function/procedure comparision |
956 ("==", BTVoid, _) -> procCompare expr1 expr2 "==" |
956 ("==", BTVoid, _) -> procCompare expr1 expr2 "==" |
957 ("==", BTFunction _ _ _, _) -> procCompare expr1 expr2 "==" |
957 ("==", BTFunction _ _ _ _, _) -> procCompare expr1 expr2 "==" |
958 |
958 |
959 ("!=", BTVoid, _) -> procCompare expr1 expr2 "!=" |
959 ("!=", BTVoid, _) -> procCompare expr1 expr2 "!=" |
960 ("!=", BTFunction _ _ _, _) -> procCompare expr1 expr2 "!=" |
960 ("!=", BTFunction _ _ _ _, _) -> procCompare expr1 expr2 "!=" |
961 |
961 |
962 ("==", BTString, BTString) -> expr2C $ BuiltInFunCall [expr1, expr2] (SimpleReference $ Identifier "_strcompare" (BTFunction False [(False, t1), (False, t2)] BTBool)) |
962 ("==", BTString, BTString) -> expr2C $ BuiltInFunCall [expr1, expr2] (SimpleReference $ Identifier "_strcompare" (fff t1 t2 BTBool)) |
963 ("!=", BTString, _) -> expr2C $ BuiltInFunCall [expr1, expr2] (SimpleReference $ Identifier "_strncompare" (BTFunction False [(False, t1), (False, t2)] BTBool)) |
963 ("!=", BTString, _) -> expr2C $ BuiltInFunCall [expr1, expr2] (SimpleReference $ Identifier "_strncompare" (fff t1 t2 BTBool)) |
964 ("&", BTBool, _) -> return $ parens e1 <+> text "&&" <+> parens e2 |
964 ("&", BTBool, _) -> return $ parens e1 <+> text "&&" <+> parens e2 |
965 ("|", BTBool, _) -> return $ parens e1 <+> text "||" <+> parens e2 |
965 ("|", BTBool, _) -> return $ parens e1 <+> text "||" <+> parens e2 |
966 (_, BTRecord t1 _, BTRecord t2 _) -> do |
966 (_, BTRecord t1 _, BTRecord t2 _) -> do |
967 i <- op2CTyped op [SimpleType (Identifier t1 undefined), SimpleType (Identifier t2 undefined)] |
967 i <- op2CTyped op [SimpleType (Identifier t1 undefined), SimpleType (Identifier t2 undefined)] |
968 ref2C $ FunCall [expr1, expr2] (SimpleReference i) |
968 ref2C $ FunCall [expr1, expr2] (SimpleReference i) |
990 e2' <- return $ case (o, t1, t2) of |
990 e2' <- return $ case (o, t1, t2) of |
991 ("-", BTInt False, BTInt False) -> parens $ text "(int64_t)" <+> parens e2 |
991 ("-", BTInt False, BTInt False) -> parens $ text "(int64_t)" <+> parens e2 |
992 _ -> parens e2 |
992 _ -> parens e2 |
993 return $ e1' <+> o' <+> e2' |
993 return $ e1' <+> o' <+> e2' |
994 where |
994 where |
|
995 fff t1 t2 = BTFunction False False [(False, t1), (False, t2)] |
995 boolOps = ["==", "!=", "<", ">", "<=", ">="] |
996 boolOps = ["==", "!=", "<", ">", "<=", ">="] |
996 procCompare expr1 expr2 op = |
997 procCompare expr1 expr2 op = |
997 case (expr1, expr2) of |
998 case (expr1, expr2) of |
998 (Reference r1, Reference r2) -> do |
999 (Reference r1, Reference r2) -> do |
999 id1 <- ref2C r1 |
1000 id1 <- ref2C r1 |
1183 _ -> error $ "ref2C FunCall erroneous type cast detected: " ++ show f ++ "\nType detected: " ++ show t ++ "\n" ++ show ref ++ "\n" ++ show params ++ "\n" ++ show t |
1184 _ -> error $ "ref2C FunCall erroneous type cast detected: " ++ show f ++ "\nType detected: " ++ show t ++ "\n" ++ show ref ++ "\n" ++ show params ++ "\n" ++ show t |
1184 where |
1185 where |
1185 fref2C (SimpleReference name) = id2C (IOLookupFunction $ length params) name |
1186 fref2C (SimpleReference name) = id2C (IOLookupFunction $ length params) name |
1186 fref2C a = ref2C a |
1187 fref2C a = ref2C a |
1187 expr2CHelper :: (Expression, (Bool, BaseType)) -> State RenderState Doc |
1188 expr2CHelper :: (Expression, (Bool, BaseType)) -> State RenderState Doc |
1188 expr2CHelper (e, (_, BTFunction _ _ _)) = do |
1189 expr2CHelper (e, (_, BTFunction _ _ _ _)) = do |
1189 modify (\s -> s{isFunctionType = True}) |
1190 modify (\s -> s{isFunctionType = True}) |
1190 expr2C e |
1191 expr2C e |
1191 expr2CHelper (e, (isVar, _)) = if isVar then liftM (((<>) $ text "&") . parens) $ (expr2C e) else expr2C e |
1192 expr2CHelper (e, (isVar, _)) = if isVar then liftM (((<>) $ text "&") . parens) $ (expr2C e) else expr2C e |
1192 |
1193 |
1193 ref2C (Address ref) = do |
1194 ref2C (Address ref) = do |
1194 r <- ref2C ref |
1195 r <- ref2C ref |
1195 lt <- gets lastType |
1196 lt <- gets lastType |
1196 case lt of |
1197 case lt of |
1197 BTFunction True _ _ -> return $ text "&" <> parens r |
1198 BTFunction True _ _ _ -> return $ text "&" <> parens r |
1198 _ -> return $ text "&" <> parens r |
1199 _ -> return $ text "&" <> parens r |
1199 ref2C (TypeCast t'@(Identifier i _) expr) = do |
1200 ref2C (TypeCast t'@(Identifier i _) expr) = do |
1200 lt <- expr2C expr >> gets lastType |
1201 lt <- expr2C expr >> gets lastType |
1201 case (map toLower i, lt) of |
1202 case (map toLower i, lt) of |
1202 ("pchar", BTString) -> ref2C $ FunCall [expr] (SimpleReference (Identifier "_pchar" $ BTPointerTo BTChar)) |
1203 ("pchar", BTString) -> ref2C $ FunCall [expr] (SimpleReference (Identifier "_pchar" $ BTPointerTo BTChar)) |