Timber is intended to be usable in many different situations, ranging from embedded systems to standard desktop applications. The interfaces between the Timber program and the external environment are very different in these cases.
Thus a Timber application must be built for a particular target environment. This distribution provides only one environment, the POSIX environment. Also this is incomplete and a more complete version will be provided in a future release.
module POSIX where type RootType = Env -> Class Prog type Prog = Action struct Env where exit :: Int -> Request () argv :: Array String stdin :: RFile stdout :: WFile openR :: String -> Request (Maybe RFile) openW :: String -> Request (Maybe WFile) startTime :: Time inet :: Internet struct Closable where close :: Request () struct File < Closable where seek :: Int -> Request Int struct RFile < File where read :: Request String installR :: (String -> Action) -> Request () struct WFile < File where write :: String -> Request Int installW :: Action -> Request () data Host = Host String data Port = Port Int struct Internet where tcp :: Sockets struct Socket < Closable where remoteHost :: Host remotePort :: Port inFile :: RFile outFile :: WFile struct Connection < Closable where established :: Action neterror :: String -> Action struct Sockets where connect :: Host -> Port -> (Socket -> Class Connection) -> Request() listen :: Port -> (Socket -> Class Connection) -> Request Closable instance showHost :: Show Host showHost = struct show (Host nm) = nm
The root module of a program targeted for this environment must import POSIX and contain a definition root :: RootType.
Here the type Env collects the services that the environment provides to the program: the program can call a function exit to terminate the program with a status indication, access command line arguments through argv, the standard input and output streams as stdin and stdout, open files for reading and writing, etc. Within a definition
root env = ...these services are accessed using dot notation as env.argv etc.
The read and write on files are non-blocking operations:
Because of the non-blocking nature of input and output, programs need a way to be notified when input is available or output is possible. This is the role of listeners or callbacks; a call
env.stdin.installR inpHandler
installs the action inpHandler as a listener on stdin; whenever input is available (i.e. the user strikes return), the runtime system calls the listener with the input line as argument.
The startTime denotes a Time value, representing the time elapsed since the Epoch. One main use of this value is that its least significant part can serve as random generator seed.
The
Execution of a program proceeds as follows. The runtime system is responsible
for initialization: it creates
an environment object with interface env :: Env, applies root to env and
creates an object of the resulting class; this gives an interface to the initial action of the program.
The run-time system executes this action; this may
lead to creation of more objects, scheduling of future actions etc.
After this initial computation the program comes to rest and
reacts to events, such as scheduled timer events or IO events on files with installed listeners.