PreludeIO を実装する。
2020-10-11 時点の残項目は以下の通り。 入力、出力ともに疎通しているので、大物は例外周りであるといえる。
putChar を追加する。
まず、lib/Prelude.hs に対する追加。これは、これで OK のはず:
$ git diff lib/Prelude.hs diff --git a/compiler/lib/Prelude.hs b/compiler/lib/Prelude.hs index 73dad25..d1f1ea2 100644 --- a/compiler/lib/Prelude.hs +++ b/compiler/lib/Prelude.hs @@ -1186,6 +1186,10 @@ instance (Read a) => Read [a] where readsPrec p = readList -- PreludeIO + +putChar :: Char -> IO () +putChar = Prim.putChar + putStrLn :: String -> IO () putStrLn = Prim.putStrLn
つぎに、PreDefined.hs への追加。これも、これでいいはず:
$ git diff src/PreDefined.hs
diff --git a/compiler/src/PreDefined.hs b/compiler/src/PreDefined.hs
index 27db528..b104be6 100644
--- a/compiler/src/PreDefined.hs
+++ b/compiler/src/PreDefined.hs
@@ -330,6 +330,10 @@ primFloatAtanhCfun = "Prim.floatAtanh" :>: Forall [] ([] :=> (tFloat `fn` tFloa
primFloatShowCfun :: Assump
primFloatShowCfun = "Prim.floatShow" :>: Forall [] ([] :=> (tFloat `fn` tString))
+primPutCharCfun :: Assump
+primPutCharCfun =
+ "Prim.putChar" :>: Forall [] ([] :=> (tChar `fn` TAp tIO tUnit))
+
primPutStrLnCfun :: Assump
primPutStrLnCfun =
"Prim.putStrLn" :>: Forall [] ([] :=> (TAp tList tChar `fn` TAp tIO tUnit))
@@ -387,6 +391,7 @@ primConsMems = [ unitCfun, nilCfun, consCfun, pairCfun, tripleCfun
, errorCfun
, eFAILCfun
, primSeqCfun
+ , primPutCharCfun
, primPutStrLnCfun
, primGetCharCfun
, overloadedCfun
@@ -485,6 +490,7 @@ primNames = fromList (primConsNames ++
, ("Prim.bindIO", "Prim.bindIO")
, ("Prim.failIO", "Prim.failIO")
, ("Prim.seq", "Prim.seq")
+ , ("Prim.putChar", "Prim.putChar")
, ("Prim.putStrLn", "Prim.putStrLn")
, ("Prim.getChar", "Prim.getChar")
])
さらに、runtime への追加だが、これは、今日は中途半端:
$ git diff ../brt/src/jp/ne/sakura/uhideyuki/brt/runtime
diff --git a/brt/src/jp/ne/sakura/uhideyuki/brt/runtime/Prim.java b/brt/src/jp/ne/sakura/uhideyuki/brt/runtime/Prim.java
index 2a33576..0ebc446 100644
--- a/brt/src/jp/ne/sakura/uhideyuki/brt/runtime/Prim.java
+++ b/brt/src/jp/ne/sakura/uhideyuki/brt/runtime/Prim.java
@@ -19,6 +19,10 @@ public class Prim {
return RTLib.seq;
}
+ public static Expr mkputChar(){
+ return RTLib.putChar;
+ }
+
public static Expr mkputStrLn(){
return RTLib.putStrLn;
}
diff --git a/brt/src/jp/ne/sakura/uhideyuki/brt/runtime/RTLib.java b/brt/src/jp/ne/sakura/uhideyuki/brt/runtime/RTLib.java
index 064c005..e6d0247 100644
--- a/brt/src/jp/ne/sakura/uhideyuki/brt/runtime/RTLib.java
+++ b/brt/src/jp/ne/sakura/uhideyuki/brt/runtime/RTLib.java
@@ -22,6 +22,15 @@ class SeqFunc implements LambdaForm {
}
}
+class PutCharFunc implements LambdaForm {
+ public int arity(){ return 1; }
+ public Expr call(AtomExpr[] args){
+ assert args.length == arity();
+ IOWrapper.println("#### putChar is not implemented yet. ####");
+ return RTLib.app(Prim.mkretIO(), RTLib.unit);
+ }
+}
+
class PutStrLnFunc implements LambdaForm {
public int arity(){ return 1; }
public Expr call(AtomExpr[] args){
@@ -175,6 +184,8 @@ public class RTLib {
public static Expr seq = mkFun(new SeqFunc());
+ public static Expr putChar = mkFun(new PutCharFunc());
+
public static Expr putStrLn = mkFun(new PutStrLnFunc());
public static Expr fromChar(int c){ return mkLitChar(c); }
RTLib.putCharFunc の中身がダミーなので、putChar の使用は期待通りに動かない。
unno@unno-FMVD70GN7G ~/work/bissues/111 $ ~/prj/bunny/compiler/bin/bunny testrun t111putchar.hs /home/unno/prj/bunny/compiler/bin/bunnyc -d ./jout/t111putchar --xno-implicit-prelude /home/unno/prj/bunny/compiler/bin/../lib/Prelude.hs /home/unno/prj/bunny/compiler/bin/bunnyc -d ./jout/t111putchar --xlibrary-path /home/unno/prj/bunny/compiler/bin/../lib t111putchar.hs #### putChar is not implemented yet. #### #### putChar is not implemented yet. ####
いちおう、make check が通る状態はキープしてあるので、この途中経過でコミットして、続きは後日。
IO は IOWrapperを介し、コマンドライン実行 runtime と Android ランタイムの両対応が必要な点に注意。
RTLib.PutCharFunc の中身がダミーだったのを実装、また、これにあわせて IOWrapper.java, IOWapper.java2, MainIntentService も修正、putChar が疎通するようになった。
テストとして sample331.hs を追加した。
putChar ができたので、lib/Prelude.hs に以下を追加:
putStr :: String -> IO () putStr s = mapM_ putChar s
期待通り動作した:
unno@unno-FMVD70GN7G ~/work/bissues/111 $ cat t111putstr.hs main = do putStr "Haskell" putChar ' ' putStrLn "Compiler" unno@unno-FMVD70GN7G ~/work/bissues/111 $ runhaskell t111putstr.hs Haskell Compiler unno@unno-FMVD70GN7G ~/work/bissues/111 $ ~/prj/bunny/compiler/bin/bunny testrun t111putstr.hs /home/unno/prj/bunny/compiler/bin/bunnyc -d ./jout/t111putstr --xno-implicit-prelude /home/unno/prj/bunny/compiler/bin/../lib/Prelude.hs /home/unno/prj/bunny/compiler/bin/bunnyc -d ./jout/t111putstr --xlibrary-path /home/unno/prj/bunny/compiler/bin/../lib t111putstr.hs Haskell Compiler
これを sample332.hs とする。
例外をあつかう小さなサンプルを書いてみる。
GHC では Prelude に catch が含まれないようで、動かない。Hugs では動く。
unno@unno-FMVD70GN7G ~/work/bissues/111
$ cat catch_sample1b.hs
main :: IO ()
main = (ioError (userError "Error sample"))
`catch`
(\e -> print e)
unno@unno-FMVD70GN7G ~/work/bissues/111
$ runhaskell catch_sample1b.hs
catch_sample1b.hs:3:3: error:
Variable not in scope: catch :: IO a0 -> (a1 -> IO ()) -> IO ()
|
3 | `catch`
| ^^^^^^^
unno@unno-FMVD70GN7G ~/work/bissues/111
$ runhugs catch_sample1b.hs
user error (Error sample)
GHC で動かすには、Control.Exception をインクルードしたうえで、例外ハンドラ関数の型を指定する必要があるようだ:
unno@unno-FMVD70GN7G ~/work/bissues/111 $ cat catch_sample1.hs import Control.Exception main :: IO () main = (ioError (userError "Error sample")) `catch` ((\e -> print e) :: IOException -> IO ()) unno@unno-FMVD70GN7G ~/work/bissues/111 $ runhaskell catch_sample1.hs user error (Error sample)
Bunny は Haskell 2010 に従うつもりなので、この件については Hugs で動作確認していくしかないかな。