mirror of
https://github.com/anoma/juvix.git
synced 2025-01-08 08:39:26 +03:00
Conversion of Nat representation to JuvixCore integers (#1661)
* nat to int wip * nat to int wip * fix condition * nats in core * bugfixes * tests * make ormolu happy * fix case
This commit is contained in:
parent
af0379a310
commit
445376e338
@ -1,6 +1,6 @@
|
|||||||
module Juvix.Compiler.Core.Data.BinderList where
|
module Juvix.Compiler.Core.Data.BinderList where
|
||||||
|
|
||||||
import Juvix.Compiler.Core.Language hiding (cons, lookup, uncons)
|
import Juvix.Compiler.Core.Language hiding (cons, drop, lookup, uncons)
|
||||||
import Juvix.Prelude qualified as Prelude
|
import Juvix.Prelude qualified as Prelude
|
||||||
|
|
||||||
-- | if we have \x\y. b, the binderlist in b is [y, x]
|
-- | if we have \x\y. b, the binderlist in b is [y, x]
|
||||||
@ -14,11 +14,11 @@ makeLenses ''BinderList
|
|||||||
fromList :: [a] -> BinderList a
|
fromList :: [a] -> BinderList a
|
||||||
fromList l = BinderList (length l) l
|
fromList l = BinderList (length l) l
|
||||||
|
|
||||||
drop' :: Int -> BinderList a -> BinderList a
|
drop :: Int -> BinderList a -> BinderList a
|
||||||
drop' k (BinderList n l) = BinderList (n - k) (dropExact k l)
|
drop k (BinderList n l) = BinderList (n - k) (dropExact k l)
|
||||||
|
|
||||||
tail' :: BinderList a -> BinderList a
|
tail :: BinderList a -> BinderList a
|
||||||
tail' = snd . fromJust . uncons
|
tail = snd . fromJust . uncons
|
||||||
|
|
||||||
uncons :: BinderList a -> Maybe (a, BinderList a)
|
uncons :: BinderList a -> Maybe (a, BinderList a)
|
||||||
uncons l = second helper <$> Prelude.uncons (l ^. blMap)
|
uncons l = second helper <$> Prelude.uncons (l ^. blMap)
|
||||||
@ -60,7 +60,7 @@ lookupsSortedRev bl = go [] 0 bl
|
|||||||
(v : vs) ->
|
(v : vs) ->
|
||||||
let skipped = v ^. varIndex - off
|
let skipped = v ^. varIndex - off
|
||||||
off' = off + skipped
|
off' = off + skipped
|
||||||
ctx' = drop' skipped ctx
|
ctx' = drop skipped ctx
|
||||||
in go ((v, head' ctx') : acc) off' ctx' vs
|
in go ((v, head' ctx') : acc) off' ctx' vs
|
||||||
head' :: BinderList a -> a
|
head' :: BinderList a -> a
|
||||||
head' = lookup 0
|
head' = lookup 0
|
||||||
|
@ -1,5 +1,10 @@
|
|||||||
module Juvix.Compiler.Core.Data.InfoTable where
|
module Juvix.Compiler.Core.Data.InfoTable
|
||||||
|
( module Juvix.Compiler.Core.Data.InfoTable,
|
||||||
|
module Juvix.Compiler.Concrete.Data.Builtins,
|
||||||
|
)
|
||||||
|
where
|
||||||
|
|
||||||
|
import Juvix.Compiler.Concrete.Data.Builtins
|
||||||
import Juvix.Compiler.Core.Language
|
import Juvix.Compiler.Core.Language
|
||||||
|
|
||||||
type IdentContext = HashMap Symbol Node
|
type IdentContext = HashMap Symbol Node
|
||||||
@ -43,7 +48,8 @@ data IdentifierInfo = IdentifierInfo
|
|||||||
_identifierType :: Type,
|
_identifierType :: Type,
|
||||||
_identifierArgsNum :: Int,
|
_identifierArgsNum :: Int,
|
||||||
_identifierArgsInfo :: [ArgumentInfo],
|
_identifierArgsInfo :: [ArgumentInfo],
|
||||||
_identifierIsExported :: Bool
|
_identifierIsExported :: Bool,
|
||||||
|
_identifierBuiltin :: Maybe BuiltinFunction
|
||||||
}
|
}
|
||||||
|
|
||||||
data ArgumentInfo = ArgumentInfo
|
data ArgumentInfo = ArgumentInfo
|
||||||
@ -60,7 +66,8 @@ data InductiveInfo = InductiveInfo
|
|||||||
_inductiveKind :: Type,
|
_inductiveKind :: Type,
|
||||||
_inductiveConstructors :: [ConstructorInfo],
|
_inductiveConstructors :: [ConstructorInfo],
|
||||||
_inductiveParams :: [ParameterInfo],
|
_inductiveParams :: [ParameterInfo],
|
||||||
_inductivePositive :: Bool
|
_inductivePositive :: Bool,
|
||||||
|
_inductiveBuiltin :: Maybe BuiltinInductive
|
||||||
}
|
}
|
||||||
|
|
||||||
data ConstructorInfo = ConstructorInfo
|
data ConstructorInfo = ConstructorInfo
|
||||||
@ -69,7 +76,8 @@ data ConstructorInfo = ConstructorInfo
|
|||||||
_constructorTag :: Tag,
|
_constructorTag :: Tag,
|
||||||
_constructorType :: Type,
|
_constructorType :: Type,
|
||||||
_constructorArgsNum :: Int,
|
_constructorArgsNum :: Int,
|
||||||
_constructorInductive :: Symbol
|
_constructorInductive :: Symbol,
|
||||||
|
_constructorBuiltin :: Maybe BuiltinConstructor
|
||||||
}
|
}
|
||||||
|
|
||||||
data ParameterInfo = ParameterInfo
|
data ParameterInfo = ParameterInfo
|
||||||
|
@ -24,6 +24,21 @@ getConstructorInfo tag = do
|
|||||||
tab <- getInfoTable
|
tab <- getInfoTable
|
||||||
return $ fromJust (HashMap.lookup tag (tab ^. infoConstructors))
|
return $ fromJust (HashMap.lookup tag (tab ^. infoConstructors))
|
||||||
|
|
||||||
|
getInductiveInfo :: Member InfoTableBuilder r => Symbol -> Sem r InductiveInfo
|
||||||
|
getInductiveInfo sym = do
|
||||||
|
tab <- getInfoTable
|
||||||
|
return $ fromJust (HashMap.lookup sym (tab ^. infoInductives))
|
||||||
|
|
||||||
|
getIdentifierInfo :: Member InfoTableBuilder r => Symbol -> Sem r IdentifierInfo
|
||||||
|
getIdentifierInfo sym = do
|
||||||
|
tab <- getInfoTable
|
||||||
|
return $ fromJust (HashMap.lookup sym (tab ^. infoIdentifiers))
|
||||||
|
|
||||||
|
getBoolSymbol :: Member InfoTableBuilder r => Sem r Symbol
|
||||||
|
getBoolSymbol = do
|
||||||
|
ci <- getConstructorInfo (BuiltinTag TagTrue)
|
||||||
|
return $ ci ^. constructorInductive
|
||||||
|
|
||||||
checkSymbolDefined :: Member InfoTableBuilder r => Symbol -> Sem r Bool
|
checkSymbolDefined :: Member InfoTableBuilder r => Symbol -> Sem r Bool
|
||||||
checkSymbolDefined sym = do
|
checkSymbolDefined sym = do
|
||||||
tab <- getInfoTable
|
tab <- getInfoTable
|
||||||
|
@ -7,5 +7,6 @@ data TransformationId
|
|||||||
| TopEtaExpand
|
| TopEtaExpand
|
||||||
| RemoveTypeArgs
|
| RemoveTypeArgs
|
||||||
| MoveApps
|
| MoveApps
|
||||||
|
| NatToInt
|
||||||
| Identity
|
| Identity
|
||||||
deriving stock (Data)
|
deriving stock (Data)
|
||||||
|
@ -46,6 +46,7 @@ pcompletions = do
|
|||||||
Identity -> strIdentity
|
Identity -> strIdentity
|
||||||
RemoveTypeArgs -> strRemoveTypeArgs
|
RemoveTypeArgs -> strRemoveTypeArgs
|
||||||
MoveApps -> strMoveApps
|
MoveApps -> strMoveApps
|
||||||
|
NatToInt -> strNatToInt
|
||||||
|
|
||||||
lexeme :: MonadParsec e Text m => m a -> m a
|
lexeme :: MonadParsec e Text m => m a -> m a
|
||||||
lexeme = L.lexeme L.hspace
|
lexeme = L.lexeme L.hspace
|
||||||
@ -63,6 +64,7 @@ transformation =
|
|||||||
<|> symbol strTopEtaExpand $> TopEtaExpand
|
<|> symbol strTopEtaExpand $> TopEtaExpand
|
||||||
<|> symbol strRemoveTypeArgs $> RemoveTypeArgs
|
<|> symbol strRemoveTypeArgs $> RemoveTypeArgs
|
||||||
<|> symbol strMoveApps $> MoveApps
|
<|> symbol strMoveApps $> MoveApps
|
||||||
|
<|> symbol strNatToInt $> NatToInt
|
||||||
|
|
||||||
allStrings :: [Text]
|
allStrings :: [Text]
|
||||||
allStrings =
|
allStrings =
|
||||||
@ -87,3 +89,6 @@ strRemoveTypeArgs = "remove-type-args"
|
|||||||
|
|
||||||
strMoveApps :: Text
|
strMoveApps :: Text
|
||||||
strMoveApps = "move-apps"
|
strMoveApps = "move-apps"
|
||||||
|
|
||||||
|
strNatToInt :: Text
|
||||||
|
strNatToInt = "nat-to-int"
|
||||||
|
@ -70,10 +70,10 @@ eval !ctx !env0 = convertRuntimeNodes . eval' env0
|
|||||||
let !vs' = map (eval' env' . (^. letItemValue)) (toList vs)
|
let !vs' = map (eval' env' . (^. letItemValue)) (toList vs)
|
||||||
!env' = revAppend vs' env
|
!env' = revAppend vs' env
|
||||||
in foldr GHC.pseq (eval' env' b) vs'
|
in foldr GHC.pseq (eval' env' b) vs'
|
||||||
NCase (Case i v bs def) ->
|
NCase (Case i sym v bs def) ->
|
||||||
case eval' env v of
|
case eval' env v of
|
||||||
NCtr (Constr _ tag args) -> branch n env args tag def bs
|
NCtr (Constr _ tag args) -> branch n env args tag def bs
|
||||||
v' -> evalError "matching on non-data" (substEnv env (mkCase i v' bs def))
|
v' -> evalError "matching on non-data" (substEnv env (mkCase i sym v' bs def))
|
||||||
NMatch (Match _ vs bs) ->
|
NMatch (Match _ vs bs) ->
|
||||||
let !vs' = map' (eval' env) (toList vs)
|
let !vs' = map' (eval' env) (toList vs)
|
||||||
in match n env vs' bs
|
in match n env vs' bs
|
||||||
|
@ -55,6 +55,9 @@ mkLambda i bi b = NLam (Lambda i bi b)
|
|||||||
mkLambda' :: Node -> Node
|
mkLambda' :: Node -> Node
|
||||||
mkLambda' = mkLambda Info.empty emptyBinder
|
mkLambda' = mkLambda Info.empty emptyBinder
|
||||||
|
|
||||||
|
mkLambdaTy :: Node -> Node -> Node
|
||||||
|
mkLambdaTy ty = mkLambda Info.empty (Binder "?" Nothing ty)
|
||||||
|
|
||||||
mkLetItem' :: Node -> LetItem
|
mkLetItem' :: Node -> LetItem
|
||||||
mkLetItem' = LetItem emptyBinder
|
mkLetItem' = LetItem emptyBinder
|
||||||
|
|
||||||
@ -70,10 +73,10 @@ mkLetRec i vs b = NRec (LetRec i vs b)
|
|||||||
mkLetRec' :: NonEmpty Node -> Node -> Node
|
mkLetRec' :: NonEmpty Node -> Node -> Node
|
||||||
mkLetRec' = mkLetRec Info.empty . fmap mkLetItem'
|
mkLetRec' = mkLetRec Info.empty . fmap mkLetItem'
|
||||||
|
|
||||||
mkCase :: Info -> Node -> [CaseBranch] -> Maybe Node -> Node
|
mkCase :: Info -> Symbol -> Node -> [CaseBranch] -> Maybe Node -> Node
|
||||||
mkCase i v bs def = NCase (Case i v bs def)
|
mkCase i sym v bs def = NCase (Case i sym v bs def)
|
||||||
|
|
||||||
mkCase' :: Node -> [CaseBranch] -> Maybe Node -> Node
|
mkCase' :: Symbol -> Node -> [CaseBranch] -> Maybe Node -> Node
|
||||||
mkCase' = mkCase Info.empty
|
mkCase' = mkCase Info.empty
|
||||||
|
|
||||||
mkMatch :: Info -> NonEmpty Node -> [MatchBranch] -> Node
|
mkMatch :: Info -> NonEmpty Node -> [MatchBranch] -> Node
|
||||||
@ -82,8 +85,8 @@ mkMatch i vs bs = NMatch (Match i vs bs)
|
|||||||
mkMatch' :: NonEmpty Node -> [MatchBranch] -> Node
|
mkMatch' :: NonEmpty Node -> [MatchBranch] -> Node
|
||||||
mkMatch' = mkMatch Info.empty
|
mkMatch' = mkMatch Info.empty
|
||||||
|
|
||||||
mkIf :: Info -> Node -> Node -> Node -> Node
|
mkIf :: Info -> Symbol -> Node -> Node -> Node -> Node
|
||||||
mkIf i v b1 b2 = mkCase i v [br] (Just b2)
|
mkIf i sym v b1 b2 = mkCase i sym v [br] (Just b2)
|
||||||
where
|
where
|
||||||
br =
|
br =
|
||||||
CaseBranch
|
CaseBranch
|
||||||
@ -94,7 +97,7 @@ mkIf i v b1 b2 = mkCase i v [br] (Just b2)
|
|||||||
_caseBranchBody = b1
|
_caseBranchBody = b1
|
||||||
}
|
}
|
||||||
|
|
||||||
mkIf' :: Node -> Node -> Node -> Node
|
mkIf' :: Symbol -> Node -> Node -> Node -> Node
|
||||||
mkIf' = mkIf Info.empty
|
mkIf' = mkIf Info.empty
|
||||||
|
|
||||||
{------------------------------------------------------------------------}
|
{------------------------------------------------------------------------}
|
||||||
@ -480,7 +483,7 @@ destruct = \case
|
|||||||
]
|
]
|
||||||
in mkLetRec i' items' (b' ^. childNode)
|
in mkLetRec i' items' (b' ^. childNode)
|
||||||
}
|
}
|
||||||
NCase (Case i v brs mdef) ->
|
NCase (Case i sym v brs mdef) ->
|
||||||
let branchChildren :: [([Binder], NodeChild)]
|
let branchChildren :: [([Binder], NodeChild)]
|
||||||
branchChildren =
|
branchChildren =
|
||||||
[ (binders, manyBinders binders (br ^. caseBranchBody))
|
[ (binders, manyBinders binders (br ^. caseBranchBody))
|
||||||
@ -520,7 +523,7 @@ destruct = \case
|
|||||||
_nodeSubinfos = map (^. caseBranchInfo) brs,
|
_nodeSubinfos = map (^. caseBranchInfo) brs,
|
||||||
_nodeChildren = noBinders v : allNodes,
|
_nodeChildren = noBinders v : allNodes,
|
||||||
_nodeReassemble = someChildrenI $ \i' is' (v' :| allNodes') ->
|
_nodeReassemble = someChildrenI $ \i' is' (v' :| allNodes') ->
|
||||||
mkCase i' (v' ^. childNode) (mkBranches is' allNodes') Nothing
|
mkCase i' sym (v' ^. childNode) (mkBranches is' allNodes') Nothing
|
||||||
}
|
}
|
||||||
Just def ->
|
Just def ->
|
||||||
NodeDetails
|
NodeDetails
|
||||||
@ -528,7 +531,7 @@ destruct = \case
|
|||||||
_nodeSubinfos = map (^. caseBranchInfo) brs,
|
_nodeSubinfos = map (^. caseBranchInfo) brs,
|
||||||
_nodeChildren = noBinders v : noBinders def : allNodes,
|
_nodeChildren = noBinders v : noBinders def : allNodes,
|
||||||
_nodeReassemble = twoManyChildrenI $ \i' is' v' def' allNodes' ->
|
_nodeReassemble = twoManyChildrenI $ \i' is' v' def' allNodes' ->
|
||||||
mkCase i' (v' ^. childNode) (mkBranches is' allNodes') (Just (def' ^. childNode))
|
mkCase i' sym (v' ^. childNode) (mkBranches is' allNodes') (Just (def' ^. childNode))
|
||||||
}
|
}
|
||||||
NMatch (Match i vs branches) ->
|
NMatch (Match i vs branches) ->
|
||||||
let allNodes :: [NodeChild]
|
let allNodes :: [NodeChild]
|
||||||
|
@ -112,6 +112,14 @@ fromRecur c =
|
|||||||
fromPair :: Functor g => d -> g (c, Node) -> g (Recur' (c, d))
|
fromPair :: Functor g => d -> g (c, Node) -> g (Recur' (c, d))
|
||||||
fromPair d = fmap (\(c, x) -> Recur' ((c, d), x))
|
fromPair d = fmap (\(c, x) -> Recur' ((c, d), x))
|
||||||
|
|
||||||
|
fromRecur' :: Functor g => d -> g (Recur' c) -> g (Recur' (c, d))
|
||||||
|
fromRecur' d =
|
||||||
|
fmap
|
||||||
|
( \case
|
||||||
|
End' x -> End' x
|
||||||
|
Recur' (c, x) -> Recur' ((c, d), x)
|
||||||
|
)
|
||||||
|
|
||||||
nodeMapG' ::
|
nodeMapG' ::
|
||||||
Monad m =>
|
Monad m =>
|
||||||
Sing dir ->
|
Sing dir ->
|
||||||
|
@ -6,21 +6,21 @@ import Juvix.Compiler.Core.Extra.Recursors.Map
|
|||||||
import Juvix.Compiler.Core.Extra.Recursors.Parameters
|
import Juvix.Compiler.Core.Extra.Recursors.Parameters
|
||||||
|
|
||||||
dmapLRM :: Monad m => (BinderList Binder -> Node -> m Recur) -> Node -> m Node
|
dmapLRM :: Monad m => (BinderList Binder -> Node -> m Recur) -> Node -> m Node
|
||||||
dmapLRM f = nodeMapG' STopDown binderInfoCollector (\bi -> fromRecur bi . f bi)
|
dmapLRM f = dmapLRM' (mempty, f)
|
||||||
|
|
||||||
dmapLM :: Monad m => (BinderList Binder -> Node -> m Node) -> Node -> m Node
|
dmapLM :: Monad m => (BinderList Binder -> Node -> m Node) -> Node -> m Node
|
||||||
dmapLM f = nodeMapG' STopDown binderInfoCollector (\bi -> fromSimple bi . f bi)
|
dmapLM f = dmapLM' (mempty, f)
|
||||||
|
|
||||||
umapLM :: Monad m => (BinderList Binder -> Node -> m Node) -> Node -> m Node
|
umapLM :: Monad m => (BinderList Binder -> Node -> m Node) -> Node -> m Node
|
||||||
umapLM f = nodeMapG' SBottomUp binderInfoCollector f
|
umapLM f = nodeMapG' SBottomUp binderInfoCollector f
|
||||||
|
|
||||||
dmapNRM :: Monad m => (Index -> Node -> m Recur) -> Node -> m Node
|
dmapNRM :: Monad m => (Level -> Node -> m Recur) -> Node -> m Node
|
||||||
dmapNRM f = nodeMapG' STopDown binderNumCollector (\bi -> fromRecur bi . f bi)
|
dmapNRM f = dmapNRM' (0, f)
|
||||||
|
|
||||||
dmapNM :: Monad m => (Index -> Node -> m Node) -> Node -> m Node
|
dmapNM :: Monad m => (Level -> Node -> m Node) -> Node -> m Node
|
||||||
dmapNM f = nodeMapG' STopDown binderNumCollector (\bi -> fromSimple bi . f bi)
|
dmapNM f = dmapNM' (0, f)
|
||||||
|
|
||||||
umapNM :: Monad m => (Index -> Node -> m Node) -> Node -> m Node
|
umapNM :: Monad m => (Level -> Node -> m Node) -> Node -> m Node
|
||||||
umapNM f = nodeMapG' SBottomUp binderNumCollector f
|
umapNM f = nodeMapG' SBottomUp binderNumCollector f
|
||||||
|
|
||||||
dmapRM :: Monad m => (Node -> m Recur) -> Node -> m Node
|
dmapRM :: Monad m => (Node -> m Recur) -> Node -> m Node
|
||||||
@ -41,13 +41,13 @@ dmapLM' f = nodeMapG' STopDown (binderInfoCollector' (fst f)) (\bi -> fromSimple
|
|||||||
umapLM' :: Monad m => (BinderList Binder, BinderList Binder -> Node -> m Node) -> Node -> m Node
|
umapLM' :: Monad m => (BinderList Binder, BinderList Binder -> Node -> m Node) -> Node -> m Node
|
||||||
umapLM' f = nodeMapG' SBottomUp (binderInfoCollector' (fst f)) (snd f)
|
umapLM' f = nodeMapG' SBottomUp (binderInfoCollector' (fst f)) (snd f)
|
||||||
|
|
||||||
dmapNRM' :: Monad m => (Index, Index -> Node -> m Recur) -> Node -> m Node
|
dmapNRM' :: Monad m => (Level, Level -> Node -> m Recur) -> Node -> m Node
|
||||||
dmapNRM' f = nodeMapG' STopDown (binderNumCollector' (fst f)) (\bi -> fromRecur bi . snd f bi)
|
dmapNRM' f = nodeMapG' STopDown (binderNumCollector' (fst f)) (\bi -> fromRecur bi . snd f bi)
|
||||||
|
|
||||||
dmapNM' :: Monad m => (Index, Index -> Node -> m Node) -> Node -> m Node
|
dmapNM' :: Monad m => (Level, Level -> Node -> m Node) -> Node -> m Node
|
||||||
dmapNM' f = nodeMapG' STopDown (binderNumCollector' (fst f)) (\bi -> fromSimple bi . snd f bi)
|
dmapNM' f = nodeMapG' STopDown (binderNumCollector' (fst f)) (\bi -> fromSimple bi . snd f bi)
|
||||||
|
|
||||||
umapNM' :: Monad m => (Index, Index -> Node -> m Node) -> Node -> m Node
|
umapNM' :: Monad m => (Level, Level -> Node -> m Node) -> Node -> m Node
|
||||||
umapNM' f = nodeMapG' SBottomUp (binderNumCollector' (fst f)) (snd f)
|
umapNM' f = nodeMapG' SBottomUp (binderNumCollector' (fst f)) (snd f)
|
||||||
|
|
||||||
dmapLR :: (BinderList Binder -> Node -> Recur) -> Node -> Node
|
dmapLR :: (BinderList Binder -> Node -> Recur) -> Node -> Node
|
||||||
@ -59,13 +59,13 @@ dmapL f = runIdentity . dmapLM (embedIden f)
|
|||||||
umapL :: (BinderList Binder -> Node -> Node) -> Node -> Node
|
umapL :: (BinderList Binder -> Node -> Node) -> Node -> Node
|
||||||
umapL f = runIdentity . umapLM (embedIden f)
|
umapL f = runIdentity . umapLM (embedIden f)
|
||||||
|
|
||||||
dmapNR :: (Index -> Node -> Recur) -> Node -> Node
|
dmapNR :: (Level -> Node -> Recur) -> Node -> Node
|
||||||
dmapNR f = runIdentity . dmapNRM (embedIden f)
|
dmapNR f = runIdentity . dmapNRM (embedIden f)
|
||||||
|
|
||||||
dmapN :: (Index -> Node -> Node) -> Node -> Node
|
dmapN :: (Level -> Node -> Node) -> Node -> Node
|
||||||
dmapN f = runIdentity . dmapNM (embedIden f)
|
dmapN f = runIdentity . dmapNM (embedIden f)
|
||||||
|
|
||||||
umapN :: (Index -> Node -> Node) -> Node -> Node
|
umapN :: (Level -> Node -> Node) -> Node -> Node
|
||||||
umapN f = runIdentity . umapNM (embedIden f)
|
umapN f = runIdentity . umapNM (embedIden f)
|
||||||
|
|
||||||
dmapR :: (Node -> Recur) -> Node -> Node
|
dmapR :: (Node -> Recur) -> Node -> Node
|
||||||
@ -86,28 +86,46 @@ dmapL' f = runIdentity . dmapLM' (embedIden f)
|
|||||||
umapL' :: (BinderList Binder, BinderList Binder -> Node -> Node) -> Node -> Node
|
umapL' :: (BinderList Binder, BinderList Binder -> Node -> Node) -> Node -> Node
|
||||||
umapL' f = runIdentity . umapLM' (embedIden f)
|
umapL' f = runIdentity . umapLM' (embedIden f)
|
||||||
|
|
||||||
dmapNR' :: (Index, Index -> Node -> Recur) -> Node -> Node
|
dmapNR' :: (Level, Level -> Node -> Recur) -> Node -> Node
|
||||||
dmapNR' f = runIdentity . dmapNRM' (embedIden f)
|
dmapNR' f = runIdentity . dmapNRM' (embedIden f)
|
||||||
|
|
||||||
dmapN' :: (Index, Index -> Node -> Node) -> Node -> Node
|
dmapN' :: (Level, Level -> Node -> Node) -> Node -> Node
|
||||||
dmapN' f = runIdentity . dmapNM' (embedIden f)
|
dmapN' f = runIdentity . dmapNM' (embedIden f)
|
||||||
|
|
||||||
umapN' :: (Index, Index -> Node -> Node) -> Node -> Node
|
umapN' :: (Level, Level -> Node -> Node) -> Node -> Node
|
||||||
umapN' f = runIdentity . umapNM' (embedIden f)
|
umapN' f = runIdentity . umapNM' (embedIden f)
|
||||||
|
|
||||||
dmapCLM :: Monad m => (c -> BinderList Binder -> Node -> m (c, Node)) -> c -> Node -> m Node
|
dmapCLM' :: Monad m => (BinderList Binder, c -> BinderList Binder -> Node -> m (c, Node)) -> c -> Node -> m Node
|
||||||
dmapCLM f ini = nodeMapG' STopDown (pairCollector (identityCollector ini) binderInfoCollector) (\(c, bi) -> fromPair bi . f c bi)
|
dmapCLM' f ini = nodeMapG' STopDown (pairCollector (identityCollector ini) (binderInfoCollector' (fst f))) (\(c, bi) -> fromPair bi . snd f c bi)
|
||||||
|
|
||||||
dmapCNM :: Monad m => (c -> Index -> Node -> m (c, Node)) -> c -> Node -> m Node
|
dmapCLRM' :: Monad m => (BinderList Binder, c -> BinderList Binder -> Node -> m (Recur' c)) -> c -> Node -> m Node
|
||||||
|
dmapCLRM' f ini = nodeMapG' STopDown (pairCollector (identityCollector ini) (binderInfoCollector' (fst f))) (\(c, bi) -> fromRecur' bi . snd f c bi)
|
||||||
|
|
||||||
|
dmapCNRM' :: Monad m => (Level, c -> Level -> Node -> m (Recur' c)) -> c -> Node -> m Node
|
||||||
|
dmapCNRM' f ini = nodeMapG' STopDown (pairCollector (identityCollector ini) (binderNumCollector' (fst f))) (\(c, bi) -> fromRecur' bi . snd f c bi)
|
||||||
|
|
||||||
|
dmapCLM :: Monad m => (c -> BinderList Binder -> Node -> m (c, Node)) -> c -> Node -> m Node
|
||||||
|
dmapCLM f = dmapCLM' (mempty, f)
|
||||||
|
|
||||||
|
dmapCNM :: Monad m => (c -> Level -> Node -> m (c, Node)) -> c -> Node -> m Node
|
||||||
dmapCNM f ini = nodeMapG' STopDown (pairCollector (identityCollector ini) binderNumCollector) (\(c, bi) -> fromPair bi . f c bi)
|
dmapCNM f ini = nodeMapG' STopDown (pairCollector (identityCollector ini) binderNumCollector) (\(c, bi) -> fromPair bi . f c bi)
|
||||||
|
|
||||||
dmapCM :: Monad m => (c -> Node -> m (c, Node)) -> c -> Node -> m Node
|
dmapCM :: Monad m => (c -> Node -> m (c, Node)) -> c -> Node -> m Node
|
||||||
dmapCM f ini = nodeMapG' STopDown (identityCollector ini) (\c -> fmap Recur' . f c)
|
dmapCM f ini = nodeMapG' STopDown (identityCollector ini) (\c -> fmap Recur' . f c)
|
||||||
|
|
||||||
|
dmapCL' :: (BinderList Binder, c -> BinderList Binder -> Node -> (c, Node)) -> c -> Node -> Node
|
||||||
|
dmapCL' f ini = runIdentity . dmapCLM' (embedIden f) ini
|
||||||
|
|
||||||
|
dmapCLR' :: (BinderList Binder, c -> BinderList Binder -> Node -> Recur' c) -> c -> Node -> Node
|
||||||
|
dmapCLR' f ini = runIdentity . dmapCLRM' (embedIden f) ini
|
||||||
|
|
||||||
|
dmapCNR' :: (Level, c -> Level -> Node -> Recur' c) -> c -> Node -> Node
|
||||||
|
dmapCNR' f ini = runIdentity . dmapCNRM' (embedIden f) ini
|
||||||
|
|
||||||
dmapCL :: (c -> BinderList Binder -> Node -> (c, Node)) -> c -> Node -> Node
|
dmapCL :: (c -> BinderList Binder -> Node -> (c, Node)) -> c -> Node -> Node
|
||||||
dmapCL f ini = runIdentity . dmapCLM (embedIden f) ini
|
dmapCL f ini = runIdentity . dmapCLM (embedIden f) ini
|
||||||
|
|
||||||
dmapCN :: (c -> Index -> Node -> (c, Node)) -> c -> Node -> Node
|
dmapCN :: (c -> Level -> Node -> (c, Node)) -> c -> Node -> Node
|
||||||
dmapCN f ini = runIdentity . dmapCNM (embedIden f) ini
|
dmapCN f ini = runIdentity . dmapCNM (embedIden f) ini
|
||||||
|
|
||||||
dmapC :: (c -> Node -> (c, Node)) -> c -> Node -> Node
|
dmapC :: (c -> Node -> (c, Node)) -> c -> Node -> Node
|
||||||
|
@ -52,5 +52,5 @@ mkLet i v b = NLet (Let i item b)
|
|||||||
mkLet' :: Node -> Node -> Node
|
mkLet' :: Node -> Node -> Node
|
||||||
mkLet' = mkLet (LetInfo "" Nothing TyDynamic)
|
mkLet' = mkLet (LetInfo "" Nothing TyDynamic)
|
||||||
|
|
||||||
mkCase :: CaseInfo -> Node -> [CaseBranch] -> Maybe Node -> Node
|
mkCase :: CaseInfo -> Symbol -> Node -> [CaseBranch] -> Maybe Node -> Node
|
||||||
mkCase ci v bs def = NCase (Case ci v bs def)
|
mkCase ci sym v bs def = NCase (Case ci sym v bs def)
|
||||||
|
@ -10,6 +10,7 @@ import Juvix.Data.Keyword.All
|
|||||||
( kwAny,
|
( kwAny,
|
||||||
kwAssign,
|
kwAssign,
|
||||||
kwBind,
|
kwBind,
|
||||||
|
kwBuiltin,
|
||||||
kwCase,
|
kwCase,
|
||||||
kwColon,
|
kwColon,
|
||||||
kwComma,
|
kwComma,
|
||||||
@ -52,6 +53,7 @@ allKeywordStrings = keywordsStrings allKeywords
|
|||||||
allKeywords :: [Keyword]
|
allKeywords :: [Keyword]
|
||||||
allKeywords =
|
allKeywords =
|
||||||
[ kwAssign,
|
[ kwAssign,
|
||||||
|
kwBuiltin,
|
||||||
kwLet,
|
kwLet,
|
||||||
kwLetRec,
|
kwLetRec,
|
||||||
kwIn,
|
kwIn,
|
||||||
|
@ -114,6 +114,7 @@ data LetRec' i a ty = LetRec
|
|||||||
-- branches default`. `Case` is lazy: only the selected branch is evaluated.
|
-- branches default`. `Case` is lazy: only the selected branch is evaluated.
|
||||||
data Case' i bi a = Case
|
data Case' i bi a = Case
|
||||||
{ _caseInfo :: i,
|
{ _caseInfo :: i,
|
||||||
|
_caseInductive :: Symbol,
|
||||||
_caseValue :: !a,
|
_caseValue :: !a,
|
||||||
_caseBranches :: ![CaseBranch' bi a],
|
_caseBranches :: ![CaseBranch' bi a],
|
||||||
_caseDefault :: !(Maybe a)
|
_caseDefault :: !(Maybe a)
|
||||||
@ -338,7 +339,7 @@ instance Eq a => Eq (Constr' i a) where
|
|||||||
(Constr _ tag1 args1) == (Constr _ tag2 args2) = tag1 == tag2 && args1 == args2
|
(Constr _ tag1 args1) == (Constr _ tag2 args2) = tag1 == tag2 && args1 == args2
|
||||||
|
|
||||||
instance Eq a => Eq (Case' i bi a) where
|
instance Eq a => Eq (Case' i bi a) where
|
||||||
(Case _ v1 bs1 def1) == (Case _ v2 bs2 def2) = v1 == v2 && bs1 == bs2 && def1 == def2
|
(Case _ sym1 v1 bs1 def1) == (Case _ sym2 v2 bs2 def2) = sym1 == sym2 && v1 == v2 && bs1 == bs2 && def1 == def2
|
||||||
|
|
||||||
instance Eq a => Eq (CaseBranch' i a) where
|
instance Eq a => Eq (CaseBranch' i a) where
|
||||||
(==) =
|
(==) =
|
||||||
|
@ -158,7 +158,19 @@ ppCodeLet' name mty lt = do
|
|||||||
return $ kwLet <+> n' <> tty <+> kwAssign <+> v' <+> kwIn <> line <> b'
|
return $ kwLet <+> n' <> tty <+> kwAssign <+> v' <+> kwIn <> line <> b'
|
||||||
|
|
||||||
ppCodeCase' :: (PrettyCode a, Member (Reader Options) r) => [[Text]] -> [Text] -> Case' i bi a -> Sem r (Doc Ann)
|
ppCodeCase' :: (PrettyCode a, Member (Reader Options) r) => [[Text]] -> [Text] -> Case' i bi a -> Sem r (Doc Ann)
|
||||||
ppCodeCase' branchBinderNames branchTagNames Case {..} = do
|
ppCodeCase' branchBinderNames branchTagNames Case {..} =
|
||||||
|
case _caseBranches of
|
||||||
|
[CaseBranch _ (BuiltinTag TagTrue) _ _ br1, CaseBranch _ (BuiltinTag TagTrue) _ _ br2] -> do
|
||||||
|
br1' <- ppCode br1
|
||||||
|
br2' <- ppCode br2
|
||||||
|
v <- ppCode _caseValue
|
||||||
|
return $ kwIf <+> v <+> kwThen <+> br1' <+> kwElse <+> br2'
|
||||||
|
[CaseBranch _ (BuiltinTag TagTrue) _ _ br1] | isJust _caseDefault -> do
|
||||||
|
br1' <- ppCode br1
|
||||||
|
br2' <- ppCode (fromJust _caseDefault)
|
||||||
|
v <- ppCode _caseValue
|
||||||
|
return $ kwIf <+> v <+> kwThen <+> br1' <+> kwElse <+> br2'
|
||||||
|
_ -> do
|
||||||
let branchBodies = map (^. caseBranchBody) _caseBranches
|
let branchBodies = map (^. caseBranchBody) _caseBranches
|
||||||
bns <- mapM (mapM (ppName KNameLocal)) branchBinderNames
|
bns <- mapM (mapM (ppName KNameLocal)) branchBinderNames
|
||||||
cns <- mapM (ppName KNameConstructor) branchTagNames
|
cns <- mapM (ppName KNameConstructor) branchTagNames
|
||||||
@ -505,6 +517,15 @@ kwMatch = keyword Str.match_
|
|||||||
kwWith :: Doc Ann
|
kwWith :: Doc Ann
|
||||||
kwWith = keyword Str.with_
|
kwWith = keyword Str.with_
|
||||||
|
|
||||||
|
kwIf :: Doc Ann
|
||||||
|
kwIf = keyword Str.if_
|
||||||
|
|
||||||
|
kwThen :: Doc Ann
|
||||||
|
kwThen = keyword Str.then_
|
||||||
|
|
||||||
|
kwElse :: Doc Ann
|
||||||
|
kwElse = keyword Str.else_
|
||||||
|
|
||||||
kwDefault :: Doc Ann
|
kwDefault :: Doc Ann
|
||||||
kwDefault = keyword Str.underscore
|
kwDefault = keyword Str.underscore
|
||||||
|
|
||||||
|
@ -14,6 +14,7 @@ import Juvix.Compiler.Core.Transformation.Eta
|
|||||||
import Juvix.Compiler.Core.Transformation.Identity
|
import Juvix.Compiler.Core.Transformation.Identity
|
||||||
import Juvix.Compiler.Core.Transformation.LambdaLifting
|
import Juvix.Compiler.Core.Transformation.LambdaLifting
|
||||||
import Juvix.Compiler.Core.Transformation.MoveApps
|
import Juvix.Compiler.Core.Transformation.MoveApps
|
||||||
|
import Juvix.Compiler.Core.Transformation.NatToInt
|
||||||
import Juvix.Compiler.Core.Transformation.RemoveTypeArgs
|
import Juvix.Compiler.Core.Transformation.RemoveTypeArgs
|
||||||
import Juvix.Compiler.Core.Transformation.TopEtaExpand
|
import Juvix.Compiler.Core.Transformation.TopEtaExpand
|
||||||
|
|
||||||
@ -27,3 +28,4 @@ applyTransformations ts tbl = foldl' (flip appTrans) tbl ts
|
|||||||
TopEtaExpand -> topEtaExpand
|
TopEtaExpand -> topEtaExpand
|
||||||
RemoveTypeArgs -> removeTypeArgs
|
RemoveTypeArgs -> removeTypeArgs
|
||||||
MoveApps -> moveApps
|
MoveApps -> moveApps
|
||||||
|
NatToInt -> natToInt
|
||||||
|
@ -57,7 +57,8 @@ lambdaLiftNode aboveBl top =
|
|||||||
_identifierType = typeFromArgs argsInfo,
|
_identifierType = typeFromArgs argsInfo,
|
||||||
_identifierArgsNum = length allfreevars,
|
_identifierArgsNum = length allfreevars,
|
||||||
_identifierArgsInfo = argsInfo,
|
_identifierArgsInfo = argsInfo,
|
||||||
_identifierIsExported = False
|
_identifierIsExported = False,
|
||||||
|
_identifierBuiltin = Nothing
|
||||||
}
|
}
|
||||||
registerIdentNode f fBody'
|
registerIdentNode f fBody'
|
||||||
let fApp = mkApps' (mkIdent mempty f) (map NVar allfreevars)
|
let fApp = mkApps' (mkIdent mempty f) (map NVar allfreevars)
|
||||||
@ -117,7 +118,8 @@ lambdaLiftNode aboveBl top =
|
|||||||
_identifierType = typeFromArgs argsInfo,
|
_identifierType = typeFromArgs argsInfo,
|
||||||
_identifierArgsNum = length recItemsFreeVars,
|
_identifierArgsNum = length recItemsFreeVars,
|
||||||
_identifierArgsInfo = argsInfo,
|
_identifierArgsInfo = argsInfo,
|
||||||
_identifierIsExported = False
|
_identifierIsExported = False,
|
||||||
|
_identifierBuiltin = Nothing
|
||||||
}
|
}
|
||||||
| (sym, (itemBinder, b)) <- zipExact topSyms (zipExact letRecBinders' liftedDefs)
|
| (sym, (itemBinder, b)) <- zipExact topSyms (zipExact letRecBinders' liftedDefs)
|
||||||
]
|
]
|
||||||
|
93
src/Juvix/Compiler/Core/Transformation/NatToInt.hs
Normal file
93
src/Juvix/Compiler/Core/Transformation/NatToInt.hs
Normal file
@ -0,0 +1,93 @@
|
|||||||
|
module Juvix.Compiler.Core.Transformation.NatToInt (natToInt) where
|
||||||
|
|
||||||
|
import Data.HashMap.Strict qualified as HashMap
|
||||||
|
import Data.List qualified as List
|
||||||
|
import Juvix.Compiler.Core.Extra
|
||||||
|
import Juvix.Compiler.Core.Info qualified as Info
|
||||||
|
import Juvix.Compiler.Core.Info.NameInfo
|
||||||
|
import Juvix.Compiler.Core.Transformation.Base
|
||||||
|
|
||||||
|
convertNode :: InfoTable -> Node -> Node
|
||||||
|
convertNode tab = convert [] 0
|
||||||
|
where
|
||||||
|
convert :: [Level] -> Level -> Node -> Node
|
||||||
|
convert levels bl node = dmapCNR' (bl, go) levels node
|
||||||
|
|
||||||
|
go :: [Level] -> Level -> Node -> Recur' [Level]
|
||||||
|
go levels bl node = case node of
|
||||||
|
NVar (Var {..}) ->
|
||||||
|
End' (mkVar _varInfo (_varIndex + length (filter (\x -> x >= bl - _varIndex) levels)))
|
||||||
|
NApp (App _ (NApp (App _ (NIdt (Ident {..})) l)) r) ->
|
||||||
|
Recur' (levels, convertIdentApp node (\op -> mkBuiltinApp _identInfo op [l, r]) _identSymbol)
|
||||||
|
NApp (App _ (NIdt (Ident {..})) l) ->
|
||||||
|
Recur' (levels, convertIdentApp node (\op -> mkLambdaTy mkTypeInteger' $ mkBuiltinApp _identInfo op [l, mkVar' 0]) _identSymbol)
|
||||||
|
NIdt (Ident {..}) ->
|
||||||
|
Recur'
|
||||||
|
( levels,
|
||||||
|
convertIdentApp
|
||||||
|
node
|
||||||
|
( \op ->
|
||||||
|
mkLambdaTy mkTypeInteger' $
|
||||||
|
mkLambdaTy mkTypeInteger' $
|
||||||
|
mkBuiltinApp _identInfo op [mkVar' 1, mkVar' 0]
|
||||||
|
)
|
||||||
|
_identSymbol
|
||||||
|
)
|
||||||
|
NCtr (Constr {..}) ->
|
||||||
|
let ci = fromJust $ HashMap.lookup _constrTag (tab ^. infoConstructors)
|
||||||
|
in case ci ^. constructorBuiltin of
|
||||||
|
Just BuiltinNatZero ->
|
||||||
|
Recur' (levels, mkConstant _constrInfo (ConstInteger 0))
|
||||||
|
Just BuiltinNatSuc ->
|
||||||
|
Recur' (levels, mkBuiltinApp _constrInfo OpIntAdd (_constrArgs ++ [mkConstant' (ConstInteger 1)]))
|
||||||
|
_ -> Recur' (levels, node)
|
||||||
|
NCase (Case {..}) ->
|
||||||
|
let ii = fromJust $ HashMap.lookup _caseInductive (tab ^. infoInductives)
|
||||||
|
in case ii ^. inductiveBuiltin of
|
||||||
|
Just BuiltinNat ->
|
||||||
|
case _caseBranches of
|
||||||
|
[br] -> makeIf br (maybeBranch _caseDefault)
|
||||||
|
[br1, br2] ->
|
||||||
|
if
|
||||||
|
| br1 ^. caseBranchBindersNum == 1 && br2 ^. caseBranchBindersNum == 0 ->
|
||||||
|
makeIf br1 (br2 ^. caseBranchBody)
|
||||||
|
| br2 ^. caseBranchBindersNum == 1 && br1 ^. caseBranchBindersNum == 0 ->
|
||||||
|
makeIf br2 (br1 ^. caseBranchBody)
|
||||||
|
| otherwise ->
|
||||||
|
impossible
|
||||||
|
[] -> Recur' (levels, fromJust _caseDefault)
|
||||||
|
_ -> impossible
|
||||||
|
_ -> Recur' (levels, node)
|
||||||
|
where
|
||||||
|
makeIf :: CaseBranch -> Node -> Recur' [Level]
|
||||||
|
makeIf CaseBranch {..} br =
|
||||||
|
let ci = fromJust $ HashMap.lookup (BuiltinTag TagTrue) (tab ^. infoConstructors)
|
||||||
|
sym = ci ^. constructorInductive
|
||||||
|
in case _caseBranchBindersNum of
|
||||||
|
0 ->
|
||||||
|
Recur' (levels, mkIf _caseInfo sym (mkBuiltinApp' OpEq [_caseValue, mkConstant' (ConstInteger 0)]) _caseBranchBody br)
|
||||||
|
1 ->
|
||||||
|
End' $
|
||||||
|
mkLet mempty (emptyBinder {_binderName = name}) (mkBuiltinApp' OpIntSub [convert levels bl _caseValue, mkConstant' (ConstInteger 1)]) $
|
||||||
|
mkIf
|
||||||
|
_caseInfo
|
||||||
|
sym
|
||||||
|
(mkBuiltinApp' OpIntLe [mkConstant' (ConstInteger 0), mkVar (Info.singleton (NameInfo name)) 0])
|
||||||
|
(convert levels (bl + 1) _caseBranchBody)
|
||||||
|
(convert (bl : levels) bl br)
|
||||||
|
where
|
||||||
|
name = List.head _caseBranchBinders ^. binderName
|
||||||
|
_ -> impossible
|
||||||
|
maybeBranch :: Maybe Node -> Node
|
||||||
|
maybeBranch = fromMaybe (mkBuiltinApp' OpFail [mkConstant' (ConstString "no matching branch")])
|
||||||
|
_ -> Recur' (levels, node)
|
||||||
|
|
||||||
|
convertIdentApp :: Node -> (BuiltinOp -> Node) -> Symbol -> Node
|
||||||
|
convertIdentApp node f sym =
|
||||||
|
let ii = fromJust $ HashMap.lookup sym (tab ^. infoIdentifiers)
|
||||||
|
in case ii ^. identifierBuiltin of
|
||||||
|
Just BuiltinNatPlus -> f OpIntAdd
|
||||||
|
_ -> node
|
||||||
|
|
||||||
|
natToInt :: InfoTable -> InfoTable
|
||||||
|
natToInt tab = mapT (const (convertNode tab)) tab
|
@ -49,7 +49,7 @@ convertNode tab = convert mempty
|
|||||||
args' = filterArgs ty _constrArgs
|
args' = filterArgs ty _constrArgs
|
||||||
in End (mkConstr _constrInfo _constrTag (map (convert vars) args'))
|
in End (mkConstr _constrInfo _constrTag (map (convert vars) args'))
|
||||||
NCase (Case {..}) ->
|
NCase (Case {..}) ->
|
||||||
End (mkCase _caseInfo (convert vars _caseValue) (map convertBranch _caseBranches) (fmap (convert vars) _caseDefault))
|
End (mkCase _caseInfo _caseInductive (convert vars _caseValue) (map convertBranch _caseBranches) (fmap (convert vars) _caseDefault))
|
||||||
where
|
where
|
||||||
convertBranch :: CaseBranch -> CaseBranch
|
convertBranch :: CaseBranch -> CaseBranch
|
||||||
convertBranch br@CaseBranch {..} =
|
convertBranch br@CaseBranch {..} =
|
||||||
|
@ -121,7 +121,8 @@ goInductiveDef i = do
|
|||||||
_inductiveKind = mkDynamic',
|
_inductiveKind = mkDynamic',
|
||||||
_inductiveConstructors = ctorInfos,
|
_inductiveConstructors = ctorInfos,
|
||||||
_inductiveParams = [],
|
_inductiveParams = [],
|
||||||
_inductivePositive = i ^. Internal.inductivePositive
|
_inductivePositive = i ^. Internal.inductivePositive,
|
||||||
|
_inductiveBuiltin = i ^. Internal.inductiveBuiltin
|
||||||
}
|
}
|
||||||
registerInductive (mkIdentIndex (i ^. Internal.inductiveName)) info
|
registerInductive (mkIdentIndex (i ^. Internal.inductiveName)) info
|
||||||
|
|
||||||
@ -132,7 +133,8 @@ goConstructor ::
|
|||||||
Internal.InductiveConstructorDef ->
|
Internal.InductiveConstructorDef ->
|
||||||
Sem r ConstructorInfo
|
Sem r ConstructorInfo
|
||||||
goConstructor sym ctor = do
|
goConstructor sym ctor = do
|
||||||
tag <- mBuiltin >>= ctorTag
|
mblt <- mBuiltin
|
||||||
|
tag <- ctorTag mblt
|
||||||
ty <- ctorType
|
ty <- ctorType
|
||||||
let info =
|
let info =
|
||||||
ConstructorInfo
|
ConstructorInfo
|
||||||
@ -141,7 +143,8 @@ goConstructor sym ctor = do
|
|||||||
_constructorTag = tag,
|
_constructorTag = tag,
|
||||||
_constructorType = ty,
|
_constructorType = ty,
|
||||||
_constructorArgsNum = length (ctor ^. Internal.inductiveConstructorParameters),
|
_constructorArgsNum = length (ctor ^. Internal.inductiveConstructorParameters),
|
||||||
_constructorInductive = sym
|
_constructorInductive = sym,
|
||||||
|
_constructorBuiltin = mblt
|
||||||
}
|
}
|
||||||
registerConstructor (mkIdentIndex (ctor ^. Internal.inductiveConstructorName)) info
|
registerConstructor (mkIdentIndex (ctor ^. Internal.inductiveConstructorName)) info
|
||||||
return info
|
return info
|
||||||
@ -198,7 +201,8 @@ goFunctionDefIden (f, sym) = do
|
|||||||
_identifierType = funTy,
|
_identifierType = funTy,
|
||||||
_identifierArgsNum = 0,
|
_identifierArgsNum = 0,
|
||||||
_identifierArgsInfo = [],
|
_identifierArgsInfo = [],
|
||||||
_identifierIsExported = False
|
_identifierIsExported = False,
|
||||||
|
_identifierBuiltin = f ^. Internal.funDefBuiltin
|
||||||
}
|
}
|
||||||
registerIdent (mkIdentIndex (f ^. Internal.funDefName)) info
|
registerIdent (mkIdentIndex (f ^. Internal.funDefName)) info
|
||||||
when (f ^. Internal.funDefName . Internal.nameText == Str.main) (registerMain sym)
|
when (f ^. Internal.funDefName . Internal.nameText == Str.main) (registerMain sym)
|
||||||
@ -286,7 +290,8 @@ goAxiomInductive a = whenJust (a ^. Internal.axiomBuiltin) builtinInductive
|
|||||||
_inductiveKind = mkDynamic',
|
_inductiveKind = mkDynamic',
|
||||||
_inductiveConstructors = [],
|
_inductiveConstructors = [],
|
||||||
_inductiveParams = [],
|
_inductiveParams = [],
|
||||||
_inductivePositive = False
|
_inductivePositive = False,
|
||||||
|
_inductiveBuiltin = Nothing
|
||||||
}
|
}
|
||||||
registerInductive (mkIdentIndex (a ^. Internal.axiomName)) info
|
registerInductive (mkIdentIndex (a ^. Internal.axiomName)) info
|
||||||
|
|
||||||
@ -307,7 +312,8 @@ goAxiomDef a = case a ^. Internal.axiomBuiltin >>= builtinBody of
|
|||||||
_identifierType = ty,
|
_identifierType = ty,
|
||||||
_identifierArgsNum = 0,
|
_identifierArgsNum = 0,
|
||||||
_identifierArgsInfo = [],
|
_identifierArgsInfo = [],
|
||||||
_identifierIsExported = False
|
_identifierIsExported = False,
|
||||||
|
_identifierBuiltin = Nothing
|
||||||
}
|
}
|
||||||
registerIdent (mkIdentIndex (a ^. Internal.axiomName)) info
|
registerIdent (mkIdentIndex (a ^. Internal.axiomName)) info
|
||||||
registerIdentNode sym body
|
registerIdentNode sym body
|
||||||
@ -554,9 +560,10 @@ goApplication a = do
|
|||||||
funInfo <- HashMap.lookupDefault impossible n <$> asks (^. Internal.infoFunctions)
|
funInfo <- HashMap.lookupDefault impossible n <$> asks (^. Internal.infoFunctions)
|
||||||
case funInfo ^. Internal.functionInfoDef . Internal.funDefBuiltin of
|
case funInfo ^. Internal.functionInfoDef . Internal.funDefBuiltin of
|
||||||
Just Internal.BuiltinBoolIf -> do
|
Just Internal.BuiltinBoolIf -> do
|
||||||
|
sym <- getBoolSymbol
|
||||||
as <- exprArgs
|
as <- exprArgs
|
||||||
case as of
|
case as of
|
||||||
(v : b1 : b2 : xs) -> return (mkApps' (mkIf' v b1 b2) xs)
|
(v : b1 : b2 : xs) -> return (mkApps' (mkIf' sym v b1 b2) xs)
|
||||||
_ -> error "if must be called with 3 arguments"
|
_ -> error "if must be called with 3 arguments"
|
||||||
_ -> app
|
_ -> app
|
||||||
_ -> app
|
_ -> app
|
||||||
|
@ -45,34 +45,36 @@ guardSymbolNotDefined sym err = do
|
|||||||
|
|
||||||
createBuiltinConstr ::
|
createBuiltinConstr ::
|
||||||
Symbol ->
|
Symbol ->
|
||||||
BuiltinDataTag ->
|
Tag ->
|
||||||
Text ->
|
Text ->
|
||||||
Type ->
|
Type ->
|
||||||
Interval ->
|
Interval ->
|
||||||
|
Maybe BuiltinConstructor ->
|
||||||
Sem r ConstructorInfo
|
Sem r ConstructorInfo
|
||||||
createBuiltinConstr sym btag nameTxt ty i = do
|
createBuiltinConstr sym tag nameTxt ty i cblt = do
|
||||||
let n = builtinConstrArgsNum btag
|
|
||||||
return $
|
return $
|
||||||
ConstructorInfo
|
ConstructorInfo
|
||||||
{ _constructorName = nameTxt,
|
{ _constructorName = nameTxt,
|
||||||
_constructorLocation = Just i,
|
_constructorLocation = Just i,
|
||||||
_constructorTag = BuiltinTag btag,
|
_constructorTag = tag,
|
||||||
_constructorType = ty,
|
_constructorType = ty,
|
||||||
_constructorArgsNum = n,
|
_constructorArgsNum = length (typeArgs ty),
|
||||||
_constructorInductive = sym
|
_constructorInductive = sym,
|
||||||
|
_constructorBuiltin = cblt
|
||||||
}
|
}
|
||||||
|
|
||||||
declareInductiveBuiltins ::
|
declareInductiveBuiltins ::
|
||||||
Member InfoTableBuilder r =>
|
Member InfoTableBuilder r =>
|
||||||
Text ->
|
Text ->
|
||||||
[(BuiltinDataTag, Text, Type -> Type)] ->
|
Maybe BuiltinInductive ->
|
||||||
|
[(Tag, Text, Type -> Type, Maybe BuiltinConstructor)] ->
|
||||||
ParsecS r ()
|
ParsecS r ()
|
||||||
declareInductiveBuiltins indName ctrs = do
|
declareInductiveBuiltins indName blt ctrs = do
|
||||||
loc <- curLoc
|
loc <- curLoc
|
||||||
let i = mkInterval loc loc
|
let i = mkInterval loc loc
|
||||||
sym <- lift freshSymbol
|
sym <- lift freshSymbol
|
||||||
let ty = mkIdent' sym
|
let ty = mkIdent' sym
|
||||||
constrs <- lift $ mapM (\(tag, name, fty) -> createBuiltinConstr sym tag name (fty ty) i) ctrs
|
constrs <- lift $ mapM (\(tag, name, fty, cblt) -> createBuiltinConstr sym tag name (fty ty) i cblt) ctrs
|
||||||
lift $
|
lift $
|
||||||
registerInductive
|
registerInductive
|
||||||
indName
|
indName
|
||||||
@ -83,7 +85,8 @@ declareInductiveBuiltins indName ctrs = do
|
|||||||
_inductiveKind = mkDynamic',
|
_inductiveKind = mkDynamic',
|
||||||
_inductiveConstructors = constrs,
|
_inductiveConstructors = constrs,
|
||||||
_inductivePositive = True,
|
_inductivePositive = True,
|
||||||
_inductiveParams = []
|
_inductiveParams = [],
|
||||||
|
_inductiveBuiltin = blt
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
lift $ mapM_ (\ci -> registerConstructor (ci ^. constructorName) ci) constrs
|
lift $ mapM_ (\ci -> registerConstructor (ci ^. constructorName) ci) constrs
|
||||||
@ -92,18 +95,31 @@ declareIOBuiltins :: Member InfoTableBuilder r => ParsecS r ()
|
|||||||
declareIOBuiltins =
|
declareIOBuiltins =
|
||||||
declareInductiveBuiltins
|
declareInductiveBuiltins
|
||||||
"IO"
|
"IO"
|
||||||
[ (TagReturn, "return", mkPi' mkDynamic'),
|
Nothing
|
||||||
(TagBind, "bind", \ty -> mkPi' ty (mkPi' (mkPi' mkDynamic' ty) ty)),
|
[ (BuiltinTag TagReturn, "return", mkPi' mkDynamic', Nothing),
|
||||||
(TagWrite, "write", mkPi' mkDynamic'),
|
(BuiltinTag TagBind, "bind", \ty -> mkPi' ty (mkPi' (mkPi' mkDynamic' ty) ty), Nothing),
|
||||||
(TagReadLn, "readLn", id)
|
(BuiltinTag TagWrite, "write", mkPi' mkDynamic', Nothing),
|
||||||
|
(BuiltinTag TagReadLn, "readLn", id, Nothing)
|
||||||
]
|
]
|
||||||
|
|
||||||
declareBoolBuiltins :: Member InfoTableBuilder r => ParsecS r ()
|
declareBoolBuiltins :: Member InfoTableBuilder r => ParsecS r ()
|
||||||
declareBoolBuiltins =
|
declareBoolBuiltins =
|
||||||
declareInductiveBuiltins
|
declareInductiveBuiltins
|
||||||
"bool"
|
"bool"
|
||||||
[ (TagTrue, "true", id),
|
(Just BuiltinBool)
|
||||||
(TagFalse, "false", id)
|
[ (BuiltinTag TagTrue, "true", id, Just BuiltinBoolTrue),
|
||||||
|
(BuiltinTag TagFalse, "false", id, Just BuiltinBoolFalse)
|
||||||
|
]
|
||||||
|
|
||||||
|
declareNatBuiltins :: Member InfoTableBuilder r => ParsecS r ()
|
||||||
|
declareNatBuiltins = do
|
||||||
|
tagZero <- lift freshTag
|
||||||
|
tagSuc <- lift freshTag
|
||||||
|
declareInductiveBuiltins
|
||||||
|
"nat"
|
||||||
|
(Just BuiltinNat)
|
||||||
|
[ (tagZero, "zero", id, Just BuiltinNatZero),
|
||||||
|
(tagSuc, "suc", \x -> mkPi' x x, Just BuiltinNatSuc)
|
||||||
]
|
]
|
||||||
|
|
||||||
parseToplevel ::
|
parseToplevel ::
|
||||||
@ -112,6 +128,7 @@ parseToplevel ::
|
|||||||
parseToplevel = do
|
parseToplevel = do
|
||||||
declareIOBuiltins
|
declareIOBuiltins
|
||||||
declareBoolBuiltins
|
declareBoolBuiltins
|
||||||
|
declareNatBuiltins
|
||||||
space
|
space
|
||||||
P.endBy statement (kw kwSemicolon)
|
P.endBy statement (kw kwSemicolon)
|
||||||
r <- optional expression
|
r <- optional expression
|
||||||
@ -121,11 +138,23 @@ parseToplevel = do
|
|||||||
statement ::
|
statement ::
|
||||||
Member InfoTableBuilder r =>
|
Member InfoTableBuilder r =>
|
||||||
ParsecS r ()
|
ParsecS r ()
|
||||||
statement = statementDef <|> statementInductive
|
statement = statementBuiltin <|> void statementDef <|> statementInductive
|
||||||
|
|
||||||
|
statementBuiltin ::
|
||||||
|
Member InfoTableBuilder r =>
|
||||||
|
ParsecS r ()
|
||||||
|
statementBuiltin = do
|
||||||
|
off <- P.getOffset
|
||||||
|
kw kwBuiltin
|
||||||
|
sym <- statementDef
|
||||||
|
ii <- lift $ getIdentifierInfo sym
|
||||||
|
case ii ^. identifierName of
|
||||||
|
"plus" -> lift $ registerIdent (ii ^. identifierName) ii {_identifierBuiltin = Just BuiltinNatPlus}
|
||||||
|
_ -> parseFailure off "unrecorgnized builtin definition"
|
||||||
|
|
||||||
statementDef ::
|
statementDef ::
|
||||||
Member InfoTableBuilder r =>
|
Member InfoTableBuilder r =>
|
||||||
ParsecS r ()
|
ParsecS r Symbol
|
||||||
statementDef = do
|
statementDef = do
|
||||||
kw kwDef
|
kw kwDef
|
||||||
off <- P.getOffset
|
off <- P.getOffset
|
||||||
@ -140,6 +169,7 @@ statementDef = do
|
|||||||
let fi = fromMaybe impossible $ HashMap.lookup sym (tab ^. infoIdentifiers)
|
let fi = fromMaybe impossible $ HashMap.lookup sym (tab ^. infoIdentifiers)
|
||||||
ty = fi ^. identifierType
|
ty = fi ^. identifierType
|
||||||
parseDefinition sym ty
|
parseDefinition sym ty
|
||||||
|
return sym
|
||||||
Just IdentInd {} ->
|
Just IdentInd {} ->
|
||||||
parseFailure off ("duplicate identifier: " ++ fromText txt)
|
parseFailure off ("duplicate identifier: " ++ fromText txt)
|
||||||
Just IdentConstr {} ->
|
Just IdentConstr {} ->
|
||||||
@ -156,10 +186,12 @@ statementDef = do
|
|||||||
_identifierType = ty,
|
_identifierType = ty,
|
||||||
_identifierArgsNum = 0,
|
_identifierArgsNum = 0,
|
||||||
_identifierArgsInfo = [],
|
_identifierArgsInfo = [],
|
||||||
_identifierIsExported = False
|
_identifierIsExported = False,
|
||||||
|
_identifierBuiltin = Nothing
|
||||||
}
|
}
|
||||||
lift $ registerIdent txt info
|
lift $ registerIdent txt info
|
||||||
void $ optional (parseDefinition sym ty)
|
void $ optional (parseDefinition sym ty)
|
||||||
|
return sym
|
||||||
|
|
||||||
parseDefinition ::
|
parseDefinition ::
|
||||||
Member InfoTableBuilder r =>
|
Member InfoTableBuilder r =>
|
||||||
@ -208,7 +240,8 @@ statementInductive = do
|
|||||||
_inductiveKind = fromMaybe (mkUniv' 0) mty,
|
_inductiveKind = fromMaybe (mkUniv' 0) mty,
|
||||||
_inductiveConstructors = [],
|
_inductiveConstructors = [],
|
||||||
_inductiveParams = [],
|
_inductiveParams = [],
|
||||||
_inductivePositive = True
|
_inductivePositive = True,
|
||||||
|
_inductiveBuiltin = Nothing
|
||||||
}
|
}
|
||||||
lift $ registerInductive txt ii
|
lift $ registerInductive txt ii
|
||||||
ctrs <- braces $ P.sepEndBy (constrDecl sym) (kw kwSemicolon)
|
ctrs <- braces $ P.sepEndBy (constrDecl sym) (kw kwSemicolon)
|
||||||
@ -233,7 +266,8 @@ constrDecl symInd = do
|
|||||||
_constructorTag = tag,
|
_constructorTag = tag,
|
||||||
_constructorArgsNum = length (typeArgs ty),
|
_constructorArgsNum = length (typeArgs ty),
|
||||||
_constructorType = ty,
|
_constructorType = ty,
|
||||||
_constructorInductive = symInd
|
_constructorInductive = symInd,
|
||||||
|
_constructorBuiltin = Nothing
|
||||||
}
|
}
|
||||||
lift $ registerConstructor txt ci
|
lift $ registerConstructor txt ci
|
||||||
return ci
|
return ci
|
||||||
@ -742,11 +776,23 @@ exprCase' off value varsNum vars = do
|
|||||||
bs <- P.sepEndBy (caseBranchP varsNum vars) (kw kwSemicolon)
|
bs <- P.sepEndBy (caseBranchP varsNum vars) (kw kwSemicolon)
|
||||||
let bss = map fromLeft' $ filter isLeft bs
|
let bss = map fromLeft' $ filter isLeft bs
|
||||||
let def' = map fromRight' $ filter isRight bs
|
let def' = map fromRight' $ filter isRight bs
|
||||||
|
case bss of
|
||||||
|
CaseBranch {..} : _ -> do
|
||||||
|
ci <- lift $ getConstructorInfo _caseBranchTag
|
||||||
|
let sym = ci ^. constructorInductive
|
||||||
case def' of
|
case def' of
|
||||||
[def] ->
|
[def] ->
|
||||||
return $ mkCase' value bss (Just def)
|
return $ mkCase' sym value bss (Just def)
|
||||||
[] ->
|
[] ->
|
||||||
return $ mkCase' value bss Nothing
|
return $ mkCase' sym value bss Nothing
|
||||||
|
_ ->
|
||||||
|
parseFailure off "multiple default branches"
|
||||||
|
[] ->
|
||||||
|
case def' of
|
||||||
|
[_] ->
|
||||||
|
parseFailure off "case with only the default branch not allowed"
|
||||||
|
[] ->
|
||||||
|
parseFailure off "case without branches not allowed"
|
||||||
_ ->
|
_ ->
|
||||||
parseFailure off "multiple default branches"
|
parseFailure off "multiple default branches"
|
||||||
|
|
||||||
@ -818,7 +864,8 @@ exprIf varsNum vars = do
|
|||||||
br1 <- bracedExpr varsNum vars
|
br1 <- bracedExpr varsNum vars
|
||||||
kw kwElse
|
kw kwElse
|
||||||
br2 <- bracedExpr varsNum vars
|
br2 <- bracedExpr varsNum vars
|
||||||
return $ mkIf Info.empty value br1 br2
|
sym <- lift getBoolSymbol
|
||||||
|
return $ mkIf mempty sym value br1 br2
|
||||||
|
|
||||||
exprMatch ::
|
exprMatch ::
|
||||||
Member InfoTableBuilder r =>
|
Member InfoTableBuilder r =>
|
||||||
|
@ -259,5 +259,10 @@ tests =
|
|||||||
"Applications with lets and cases in function position"
|
"Applications with lets and cases in function position"
|
||||||
"."
|
"."
|
||||||
"test046.jvc"
|
"test046.jvc"
|
||||||
"out/test046.out"
|
"out/test046.out",
|
||||||
|
PosTest
|
||||||
|
"Builtin natural numbers"
|
||||||
|
"."
|
||||||
|
"test047.jvc"
|
||||||
|
"out/test047.out"
|
||||||
]
|
]
|
||||||
|
@ -3,7 +3,7 @@ module Core.Transformation where
|
|||||||
import Base
|
import Base
|
||||||
import Core.Transformation.Identity qualified as Identity
|
import Core.Transformation.Identity qualified as Identity
|
||||||
import Core.Transformation.Lifting qualified as Lifting
|
import Core.Transformation.Lifting qualified as Lifting
|
||||||
import Core.Transformation.RemoveTypeArgs qualified as RemoveTypeArgs
|
import Core.Transformation.Pipeline qualified as Pipeline
|
||||||
import Core.Transformation.TopEtaExpand qualified as TopEtaExpand
|
import Core.Transformation.TopEtaExpand qualified as TopEtaExpand
|
||||||
|
|
||||||
allTests :: TestTree
|
allTests :: TestTree
|
||||||
@ -13,5 +13,5 @@ allTests =
|
|||||||
[ Identity.allTests,
|
[ Identity.allTests,
|
||||||
TopEtaExpand.allTests,
|
TopEtaExpand.allTests,
|
||||||
Lifting.allTests,
|
Lifting.allTests,
|
||||||
RemoveTypeArgs.allTests
|
Pipeline.allTests
|
||||||
]
|
]
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
module Core.Transformation.RemoveTypeArgs (allTests) where
|
module Core.Transformation.Pipeline (allTests) where
|
||||||
|
|
||||||
import Base
|
import Base
|
||||||
import Core.Eval.Positive qualified as Eval
|
import Core.Eval.Positive qualified as Eval
|
||||||
@ -6,10 +6,10 @@ import Core.Transformation.Base
|
|||||||
import Juvix.Compiler.Core.Transformation
|
import Juvix.Compiler.Core.Transformation
|
||||||
|
|
||||||
allTests :: TestTree
|
allTests :: TestTree
|
||||||
allTests = testGroup "Move applications and remove type arguments" (map liftTest Eval.tests)
|
allTests = testGroup "Transformation pipeline" (map liftTest Eval.tests)
|
||||||
|
|
||||||
pipe :: [TransformationId]
|
pipe :: [TransformationId]
|
||||||
pipe = [LambdaLifting, MoveApps, RemoveTypeArgs]
|
pipe = [NatToInt, LambdaLifting, MoveApps, RemoveTypeArgs, TopEtaExpand]
|
||||||
|
|
||||||
liftTest :: Eval.PosTest -> TestTree
|
liftTest :: Eval.PosTest -> TestTree
|
||||||
liftTest _testEval =
|
liftTest _testEval =
|
3
tests/Core/positive/out/test047.out
Normal file
3
tests/Core/positive/out/test047.out
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
3
|
||||||
|
136
|
||||||
|
true
|
@ -9,11 +9,11 @@ def snd := \p case p of { pair _ x := x };
|
|||||||
|
|
||||||
def compose := \f \g \x f (g x);
|
def compose := \f \g \x f (g x);
|
||||||
|
|
||||||
def zero := \f \x x;
|
def czero := \f \x x;
|
||||||
|
|
||||||
def num := \n
|
def num := \n
|
||||||
if n = 0 then
|
if n = 0 then
|
||||||
zero
|
czero
|
||||||
else
|
else
|
||||||
\f compose f (num (n - 1) f);
|
\f compose f (num (n - 1) f);
|
||||||
|
|
||||||
@ -32,7 +32,7 @@ def pred := \n
|
|||||||
pair (fst x) (succ (snd x))
|
pair (fst x) (succ (snd x))
|
||||||
else
|
else
|
||||||
pair (succ (fst x)) (succ (snd x)))
|
pair (succ (fst x)) (succ (snd x)))
|
||||||
(pair zero zero)
|
(pair czero czero)
|
||||||
);
|
);
|
||||||
|
|
||||||
def toInt := \n n (+ 1) 0;
|
def toInt := \n n (+ 1) 0;
|
||||||
@ -41,11 +41,11 @@ def writeLn := \x write x >> write "\n";
|
|||||||
|
|
||||||
def fib := \n
|
def fib := \n
|
||||||
if isZero n then
|
if isZero n then
|
||||||
zero
|
czero
|
||||||
else
|
else
|
||||||
let n' := pred n in
|
let n' := pred n in
|
||||||
if isZero n' then
|
if isZero n' then
|
||||||
succ zero
|
succ czero
|
||||||
else
|
else
|
||||||
add (fib n') (fib (pred n'));
|
add (fib n') (fib (pred n'));
|
||||||
|
|
||||||
|
@ -5,7 +5,7 @@ inductive list {
|
|||||||
cons : any -> list -> list;
|
cons : any -> list -> list;
|
||||||
};
|
};
|
||||||
|
|
||||||
def f := \l (case l of { cons x _ := x; nil := \x x } ) (let y := \x x in (let z := \x x in case l of { _ := \x x } z) y) 7;
|
def f := \l (case l of { cons x _ := x; nil := \x x } ) (let y := \x x in (let z := \x x in case l of { cons _ _ := \x x } z) y) 7;
|
||||||
|
|
||||||
def main := f (cons (\x \y x y + 2) nil);
|
def main := f (cons (\x \y x y + 2) nil);
|
||||||
|
|
||||||
|
38
tests/Core/positive/test047.jvc
Normal file
38
tests/Core/positive/test047.jvc
Normal file
@ -0,0 +1,38 @@
|
|||||||
|
-- builtin natural numbers
|
||||||
|
|
||||||
|
builtin def plus := \x \y case x of {
|
||||||
|
zero := y;
|
||||||
|
suc x' := suc (plus x' y);
|
||||||
|
};
|
||||||
|
|
||||||
|
def from_int := \n if n = 0 then zero else suc (from_int (n - 1));
|
||||||
|
|
||||||
|
def to_int := \x case x of {
|
||||||
|
suc x' := to_int x' + 1;
|
||||||
|
zero := 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
def even := \x case x of {
|
||||||
|
suc x' := case x' of {
|
||||||
|
zero := false;
|
||||||
|
suc y := even y;
|
||||||
|
};
|
||||||
|
_ := true;
|
||||||
|
};
|
||||||
|
|
||||||
|
def f := \x case x of {
|
||||||
|
suc x' := (\z case z of {
|
||||||
|
zero := even x';
|
||||||
|
suc y := f y;
|
||||||
|
}) x';
|
||||||
|
_ := even x;
|
||||||
|
};
|
||||||
|
|
||||||
|
def writeLn := \x write x >> write "\n";
|
||||||
|
|
||||||
|
def main :=
|
||||||
|
writeLn (to_int (if even (from_int 124) then plus (suc zero) (suc (suc zero)) else zero)) >>
|
||||||
|
writeLn (to_int (plus (from_int 126) (from_int 10))) >>
|
||||||
|
writeLn (f (from_int 65));
|
||||||
|
|
||||||
|
main
|
Loading…
Reference in New Issue
Block a user