Category Archives: Programming

How to add logging to a Happstack server

Disclaimer: this post describes experience of a Happstack newbie.

A very simple (but already useful!) server in Happstack may be written like this:


import Happstack.Server
import System.Environment
import Control.Monad (when)

main = do
  args <- getArgs
  when (length args < 2) $ error "Usage: ./HelloHTTP <a directory to serve>"

  simpleHTTP nullConf $ serveDirectory EnableBrowsing ["index.htm"] (head args)

This has been pretty sufficient for my simple home page for some time, but now I want logging about who is visiting the page.

Let’s do this!
Continue reading

Part Ia. SECD: a high-level description


Contents

  • SECD: about
  • Part I and Part Ia describe high-level, formal definition of a SECD machine;
  • Part II discusses low-level details of SECD C implementation;
  • Part III (TODO): how to compile a Scheme subset into SECD code.

Things are getting dirty: putting functional in the SECD

Now we’re starting the most interesting part, adding functions into the functional virtual machine. First of all, a function is usually tied to its environment: a pair of function definition (arguments and body) and the environment it has been created in is called closure. So don’t be afraid of this semantic rules for opcode LDF (the newly made closure is underlined):

  • (s, e, LDF.(args body).c, d) => (((args body).e).s, e, c, d)

I want to stress that the environment is paired with the function definition on the stack, producing a closure (args body).e, which may be saved, used as an argument to another function (thus bound to a symbol), and so on.

The closure on top of the stack may be called using opcode AP:

  • (((argnames body).e').argvals.s, e, AP.c, d)
    => ( (), new-frame(argnames, argvals).e', body, s.e.c.d)

Continue reading

Part I. SECD: a high-level description


Contents

  • SECD: about
  • Part I and Part Ia describe high-level, formal definition of a SECD machine;
  • Part II discusses low-level details of SECD implementation in C;
  • Part III (TODO): how to compile a Scheme subset into SECD code.

Part I: What is a SECD machine?

Formally, it is just a tuple of four lists with some set of rigidly defined operations on it. The SECD semantics describes a stack-based virtual machine which is designed to run pure functions. As seen by a computer scientist: one of first denotational semantics for a pure functional language, where operations are transitions between possible machine states.

The components of the tuple are named (unsurprisingly):
Continue reading

SECD: about


Contents

  • SECD: about
  • Part I and Part Ia describe high-level, formal definition of a SECD machine;
  • Part II discusses low-level details of SECD implementation in C;
  • Part III (TODO): how to compile a Scheme subset into SECD code.

What are these posts about

Perhaps, a lot of people studying functional programming languages write their own simplistic Lisp interpreter. First of all, it’s quite easy with a modern functional language: parsing is primitive, the runtime maps straightforwardly to a favorite language’s runtime, etc.

Writing it in C is a more complicated task, since garbage collection and nitty-gritty details of implementation are up to you all of a sudden. I went crazy when I thought about endless conses created with every operation. I don’t want to say that writing a Lisp runtime in C is fundamentally complex, but it’s still true that it’s quite hard to implement something you haven’t quite grokked yet.

I am fond of Haskell and GHC’s functioning often strikes like magic of waving terms into complex pattern that are reduced into normal forms at run time. In order to understand that, I started to study compiler theory. A classic book for understanding functional programming is Functional programming: Application and Implementation by Peter Henderson.  Although it may seem very old (published in 1980) it’s still a good and clear introduction into functional way of thinking. When I came across SECD machine description I was amused by its simplicity and how easy is to encode it in a low-level language and how easy is to map a decent functional language into it at the same time (let’s forget about types for a while, we’re just studying). So I started to write my little SECD interpreter in C.

My little Scheme-to-SECD compiler

So I wrote a simple SECD interpreter in C and a self-hosting Scheme-to-SECD compiler in subset of Scheme. The code may be found here.

Haskell OpenGL animation done right: using closures and channels instead of IORef’s

There is a lot of Haskell OpenGL tutorials on the web introducing to basic OpenGL drawing in Haskell. I’ve read about a dozen of them, but none are highlighting an important issue right: how to react to user’s input? The tutorials either omit this topic, or fall back to ugly and non-idiomatic IORefs to return data from callbacks (even the Haskell wiki goes this way). Although there is a much nicer way to handle GLUT/GLFW callbacks which is explained below.

Continue reading

COSEC: six months

This spring my assembly coding experiments grew to something more: I moved from the x86 real mode to first steps in the protected mode environment, which seemed hostile and quite unusual. A lot of intricate and arcane assembly code needed to fit opportunities of a full 32bit mode really puzzled me first, but my slow progress was persistent enough to run first C code examples and to see a “Hello world” message in an OSless emulator.

I’ve been really impressed by Linux and its kernel and, like a child, wanted to know “how does this thing work”, so writing a linux-like kernel was a pleasant and useful challenge for my programming skills. My guidelines are not fancy: system clearness and simplicity, minimal POSIX-compatibility and experiments inspired by Plan 9 from Bell Labs, like network transparency and resources unification through files. Also I lean to microkernel design as far as it does not complicate the picture.

I haven’t had a definite goal of my project for a long time, I fluctuated between considering this OS just a training ground for system programming and exaggerated expectations for a new OS architecture and language-based features (resembling Singularity software stack), although my experience in writing code for managed platforms and writing interpreters/virtual machines itselves is miserable (and this is my first large project in pure C). Now I came to a definite goal: I want to have a minimal self-hosting POSIX-like OS using C (roughly corresponding to Linux 0.01 functionality, but a bit more slim, there are two decades of history after Linux creation).

Now my system is still quite nascent, but the experiments now involve much more mature things. Now my tiny OS contains:

  • a basic context switching (which is still not used);
  • basic userspace capabilities (and a single system call, SCS_DBG_PRINT, which print a message from userspace);
  • draft of Virtual File System;
  • my own implementation of heap using the firstfit algorithm;
  • implementation of some libc functions.
  • some drivers: keyboard, timers, serial port, PCI probing;

The system is still a single binary with simplest built-in kernel shell (userspace is waiting for FS implementation on order to be able host a functional shell). It is loaded with GRUB according to GNU mutliboot specification, though I have my own bootloader and switch-to-protected-mode code snippets.

Plans for the future are:

  • to add paging and modern-style memory protection;
  • to implement functional VFS and some popular FS drivers like FAT/ext2/iso9660;
  • to make the userspace really work: full-featured process with own address spaces, pipes, sockets;
  • to port Newlib (a C library implementation) and write a system-dependent userspace code for launching bash/gcc/vim on top of it;
  • an ELF loader;
  • to make it cross-platform with ARM support;
  • to start writing a simple network stack (arp, icmp, ip, tcp/udp, telnet/http/ftp);

Here is the source code:

COSEC on Github

In Ukrainian | Українською