Простой интерпретатор, написанный на Haskell, сохраняет вывод печати до конца, а не когда он приходит через оператор печати

Ниже я попытался создать очень простой интерпретатор, который переведен с Java-версии программы, описанной в главе 1 «Современная реализация компилятора на Java» Эндрю В. Appel и работает непосредственно с деревом, представляющим язык.

По сути, моя проблема в том, что он сохраняет весь вывод до конца, прежде чем что-либо вообще будет напечатано. Мне просто нужен совет о том, как его реструктурировать, чтобы операторы print печатались так, как они интерпретируются.

module Interpreter where

--------------------------------------------------------------------

type Id         =   [Char]
type Output     =   [Char]
type Value      =   Int
type Table      =   [(Id, Value)]

data Stm        =   CompoundStm Stm Stm |
                    AssignStm Id Exp |
                    PrintStm ExpList deriving Show

data Exp        =   IdExp Id |
                    NumExp Value |
                    OpExp Exp Op Exp |
                    EseqExp Stm Exp deriving Show

data ExpList    =   PairExpList Exp ExpList |
                    LastExpList Exp deriving Show

data Op         =   Plus | Minus | Times | Div deriving Show

--------------------------------------------------------------------

example ::  Stm
example =   CompoundStm (AssignStm "a" (OpExp (NumExp 5) Plus (NumExp 3))) 
            (CompoundStm (AssignStm "b" (EseqExp (PrintStm (PairExpList (IdExp "a")
             (LastExpList (OpExp (IdExp "a") Minus (NumExp 1))))) (OpExp (NumExp 10) Times
              (IdExp "a")))) (PrintStm (LastExpList (IdExp "b"))))

--------------------------------------------------------------------

tableUpdate                             ::  Table -> Id -> Value -> Table
tableUpdate t i v                       =   (i,v):t

tableLookup                             ::  Table -> Id -> Value
tableLookup ((x,v):t) i | x == i        =   v
tableLookup ((x,v):t) i | x /= i        =   tableLookup t i

--------------------------------------------------------------------

execute                                 ::  Stm -> IO()
execute s                               =   putStr ((\(o,_)->o) (interpStm s ("",[])))

interpStm                               ::  Stm -> (Output, Table) -> (Output, Table)
interpStm (CompoundStm l r) ot          =   interpStm r (interpStm l ot)
interpStm (PrintStm el) (o,t)           =   (interpExpList el o t)
interpStm (AssignStm i e) (o,t)         =   f i (interpExp e (o,t))
        where
            f i (v,o,t)                 =   (o, tableUpdate t i v)

interpExp                               ::  Exp -> (Output, Table) -> (Value, Output, Table)
interpExp (IdExp i) (o,t)               =   (tableLookup t i, o, t)
interpExp (NumExp v) (o,t)              =   (v, o, t)
interpExp (EseqExp s e) ot              =   interpExp e (interpStm s ot)
interpExp (OpExp l op r) (o,t)          =   f (interpExp l (o,t)) op r
        where
            f (v,o,t) op r              =   g v op (interpExp r (o,t))
            g v1 Plus (v2,o,t)          =   (v1 + v2, o, t)
            g v1 Minus (v2,o,t)         =   (v1 - v2, o, t)
            g v1 Times (v2,o,t)         =   (v1 * v2, o, t)
            g v1 Div (v2,o,t)           =   (v1 `div` v2, o, t)

interpExpList                           ::  ExpList -> Output -> Table -> (Output, Table)
interpExpList (LastExpList e) o t       =   f (interpExp e (o,t))       
        where
            f (v, o, t)                 =   (o ++ (show v) ++ "\n", t)
interpExpList (PairExpList e el) o t    =   f (interpExp e (o,t))
        where
            f (v, o, t)                 =   interpExpList el (o ++ (show v) ++ " ") t
8
задан DMK 23 January 2013 в 14:23
поделиться