My current pet project is coming along quite well: the implementation is complete up to chapter four (Scanning). More importantly, the AoRTE proof (absence of runtime errors) is also completely done. The only shortcomings are a handful of package bodies that are compiled with SPARK_mode => off: Ada.Command_Line and SPARK.Text_IO come to mind.

A few days ago, Bob has published the fifth chapter of his book. It is mainly about theory, and the only code it contains is a tool that generates source code for a part of the interpreter (the type hierarchy of the abstract syntax tree).

I thought about this for a while, and came to the conclusion I would not follow his path. Instead, I planned to write the types by hand. Here is why: generating source code is not really a problem, and since the generator would not be part of the final program, I would write it in plain Ada (without proving anything). The resulting code, however, would be part of the interpreter and thus needs to be proven. I could add the necessary annotations by hand, but that would defeat a big advantage of the generator: one can make changes at a high level (namely, change the input to the generator) and regenerate the sources. This is fine for ordinary languages, but it will kill my hand-written annotations.

Meanwhile, about a dozen Lox ports have appeared on github. I looked at all those I could find, but nobody seems to have written code related to the new chapter. Either the other developers have not yet found the time to implement the generator, or they, too, have their doubts.

Somehow, this lack of activity has prompted me to revise my decision: I will implement the generator, and I will generate annotations as well. After all, this project was meant to help me learn something new, and to be a challenge. But what good is a challenge unless it is challenging?

This should keep me busy in the coming days (I have not yet written any code for the generator). A quick Google search tells me that I can build multiple executables from the same project with GNAT, so that simplifies things on the organisational side.

Watch this site (or better yet, github) for updates!

Kein Kommentar

von kirjoittaessani

For some time, I've taken an interest in software engineering. With that, I mean robust software. After learning about Ada (my first project is from 2011), I haven't looked back (at C/C++, that is); Since then, I've learned a little about formal methods. So far, a few half-hearted attempts at SPARK/Ada have been the only results.

Now, I have stumbled across a project of Bob Nystrom's: He has designed a simple programming language, Lox, and is writing (and continuously publishing) a book on how to implement it. He has chosen Java and C, but quite a few folks have taken his code and re-implemented it in various languages: Alejandro Martinez (Swift), Ivan Katanic (C++), Paul Jackson (Go), Sasha Matijasic (Python).

So, why not do a SPARK port? I have some past experience with various parsers, so writing the bare code should not be that hard. Once that is done, annotations could be added and proofs done. The advantage of this project is that Bob is doing it now, chapter by chapter; I expect to follow at more or less the same pace, so if SPARKifying means I have to change something fundamental, I do not have to do that to the complete program. Instead, I can deal with problems as they crop up in the early stages.

I should add that SPARK can be used in different ways (or maybe I should say intensities). In the simplest case, only absence of runtime errors is proven. However, it is also possible to prove functional correctness at various levels: For example, one might set out to prove that a sorting subroutine actually returns a sorted list. This approach can be extended to more and more routines and eventually encompass the whole program. I do not know how far down this path I will (manage to) go, and in any case I have no idea how to prove functional correctness for a compiler.

Time will tell, I guess. Back to writing code now.

Kein Kommentar

von kirjoittaessani

Gestern habe ich festgestellt, daß Traktor auf K2-isch gar nicht (oder nicht mehr) /'bagwa/ heißt, sondern /'bagBa/, also mit bilabialem R.

Kein Kommentar

von kirjoittaessani

Öfter mal was neues: ich habe jetzt ein Studientagebuch.

Kein Kommentar

von kirjoittaessani

So ein 25x25-Go-Brett sieht, wenn man erstmal angefangen hat zu spielen, ganz schön furchteinflößend aus.

2 Kommentare

von kirjoittaessani

Here's a solution for a problem I have been unable to find anything about on the net, so I would like to share it with you.
It results from a particular combination of choices that are not exactly mainstream, so it is probably quite rare:


First, I use the i3 window manager. Like many of the more usual window managers, it supports the notion of work spaces. I also use multiple monitors, and this is where i3 is different: instead of building up a huge desktop stretching over all monitors (and changing its contents via workspaces), each monitor is taken seperately; and each can be assigned one or more workspaces.You start working on a different workspace either by moving the mouse pointer, or by a key combination.

Here's where factor number three comes in: I use an absolute pointing device, namely a Wacom Intuos3. By default, the tablet maps to the whole screen area -- treating it as a single desktop,
conceptually very diferent from i3's approach.

Culture Clash

This shows: when I switch to a different screen, i3 has the ability to warp the mouse pointer, i.e. make it jump to the newly focused window. This is a nice touch for an ordinary (relative) mouse, but an absolute mouse will jump right back. You have to manually move it over.
It might seem like a good idea to switch screens using the mouse instead, but this does not work well if you need a workspace that lingers at the back of your other monitor -- you have to click on a tiny icon at the bottom. Besides, using the mouse to switch workspaces does feels wrong with keyboard-centric i3.
I ended up using a key combination and moving the mouse over, which feels redundant and annoying.

I looked for a way to confine my Intuos to just the active monitor, but have been unsuccessful until recently. Here's my setup:


First, bund workspaces to monitors:
workspace 1 output HDMI-0
workspace 2 output HDMI-0
workspace 3 output HDMI-0
workspace 4 output HDMI-0
workspace 5 output HDMI-0
workspace 6 output DVI-I-1
workspace 7 output DVI-I-1
workspace 8 output DVI-I-1
workspace 9 output DVI-I-1

Then, replace the ordinary workspace-switching key combinations by extended ones that also remap the input device:

bindsym $mod+1 exec --no-startup-id " i3-msg workspace 1; exec $HOME/bin/wacom-left"
bindsym $mod+2 exec --no-startup-id " i3-msg workspace 2; exec $HOME/bin/wacom-left"
bindsym $mod+3 exec --no-startup-id " i3-msg workspace 3; exec $HOME/bin/wacom-left"
bindsym $mod+4 exec --no-startup-id " i3-msg workspace 4; exec $HOME/bin/wacom-left"
bindsym $mod+5 exec --no-startup-id " i3-msg workspace 5; exec $HOME/bin/wacom-left"
bindsym $mod+6 exec --no-startup-id " i3-msg workspace 6; exec $HOME/bin/wacom-right"
bindsym $mod+7 exec --no-startup-id " i3-msg workspace 7; exec $HOME/bin/wacom-right"
bindsym $mod+8 exec --no-startup-id " i3-msg workspace 8; exec $HOME/bin/wacom-right"
bindsym $mod+9 exec --no-startup-id " i3-msg workspace 9; exec $HOME/bin/wacom-right"
bindsym $mod+0 exec --no-startup-id " i3-msg workspace 10; exec $HOME/bin/wacom-right"

Note the double quotes -- single quotes get messed up in some internal shell call and lead to weird error messages.
The remap scripts apply a coordinate transformation matrix that depends on your monitor setup and sizes.
#!/bin/bash -x
xinput set-prop "Wacom Intuos3 6x8 stylus" --type=float \
"Coordinate Transformation Matrix" 0.6 0 0 0 1 0 0 0 1

For some hints on how to calculate the proper matrices, see the linuxwacom wiki.

Kein Kommentar

von kirjoittaessani

Nach meinem Systemwechsel auf dem Desktop habe ich mich mit meinem iPhone immer ein bißchen wie ein Außerirdischer gefühlt: so richtig Spaß macht es nur auf dem Planeten iTunes, und iTunes ist weit weg. Als das iPhone den Geist aufgab, lag es also nah, auch hier einen Systemwechsel zu vollziehen. Das heißt fast automatisch Android  (nur mit Jolla habe ich kurz geliebäugelt). Das erst Problem war, in der Fülle der Hersteller und Geräte etwas passendes zu finden. Gelandet bin ich schließlich beim Galaxy A3, das eine angemessene Ausstattung in einem nicht allzu großen Gerät unterbringt.
Etwas in den Abmessungen des iPhone 4 wäre mir lieber gewesen, ich habe aber nichts passendes gefunden.
Die erste große Überraschung mit dem neuen Gerät war, daß es um die Konnektivität nicht so gut bestellt ist wie gedacht. Das Android-Lager setzt genauso auf Cloud-Dienste wie die Firma Apple, und eine lokale Datensicherung oder die Verwaltung des Smartphones vom Rechner aus ist nicht vorgesehen. Zum Abgleich von Musik gibt es MTP, aber das erwies sich also so gruselig instabil, daß es nicht sinnvoll nutzbar ist.
Wenn der neurotische Kram nicht funktioniert, helfen meist Standard-Tools. In diesem Falle ist das ein Android-sshd namens SSHDroid,mit dem ich meine Plattensammlung bequem und sicher aufs Telefon bringen kann. Damit sie dort dann auch erkannt werden, ist derzeit noch ein Reboot vonnöten, ich bin aber guter Hoffnung, das noch verbessern zu können.

1 Kommentar

von kirjoittaessani

Rsnapshot is flawed, claims Espen.   I've stumbled upon a problem he does not directly mention: when a backup run fails, it won't be retried until (ana)cron decides to run the job again. This should not be a problem for hourly runs, but can become troublesome for the weeklies and monthlies. Even worse, cron runs might be correlated with backup failures: when anacron tends to run your backup job two minutes before you connect the external hard drive, you might be without any long-term backup while merrily retiring old hourlies.

I am convinced a better solution will consider all backup lines (including weekly and monthly runs) at each invocation (say, hourly). Here's a proposition: for each line, compare the time stamp of the most recent copy to the oldest copy in the next (more frequent) line. If the difference is sufficiently large, perform a migration.

In other words: if the oldest daily backup is more recent than the latest weekly by at least a week, call rsnapshot weekly to move that copy over.

Here's the script I use:



[ -d $TARGET ] || exit 2

function invoke() {
  if [ -e $TARGET/$SERIES.0 ]; then
    MTIME=`stat -c %Y $TARGET/$SERIES.0`
    if [ -e $TARGET/$PRED.0 ]; then
      PENDING=`ls -1dv $TARGET/$PRED.* |tail -1`
      PTIME=`stat -c %Y $PENDING`
    if [ $((PTIME-MTIME)) -gt $PERIOD ]; then
      rsnapshot $1
    rsnapshot $1


invoke monthly $((30*24*3600)) weekly
invoke weekly $((7*24*3600)) daily
invoke daily $((24*3600)) hourly
rsnapshot hourly

It goes into /etc/cron.hourly, and this is the only place rsnapshot is called -- no more fiddling around with half a dozen cron entries.

Kein Kommentar

von kirjoittaessani

Inzwischen habe ich Zeit gehabt, mein EMail-Setup im Alltag zu testen und noch ein paar Verbesserungen anzubringen. Die größte Änderung ist dabei die Einbindung von procmail gewesen.


Ich bin ein großer Freund von Mailinglisten, und komme allein deswegen um das Filtern nicht herum (lies: Listenmail soll in passende Ordner wegsortiert werden, um den Posteingang freizuhalten). Bei dienstlichen Mails habe ich dafür auf die etwas umständlich einzurichtenden Filterregeln des Exchange-Serers zurückgegriffen, privat Mails blieben einfach ungefiltert, weil mein Provider hier nichts anbietet. Beides ist kein haltbarer Zustand, es musste also eine lokale Lösung her.


Procmail ist ein Mail delivery agent (MDA), der sehr mächtige Filterfunktionen bietet (die weit über das bloße Wegsortieren hinausgehen). Diesen galt es jetzt nur noch mit offlineimap zu verheiraten. Mein erster Ansatz -- ein Cronjob, der die gesammelten Mails auf Neuzugänge durchsucht -- erwies sich als unzureichend:  viel zu leicht hat man eine exponentiell arbeitende Mail-Loop gebaut. Hier lohnt es sich gar nicht, die genauen Fehler zu suchen, denn schon das Konzept stimmt nicht: ein MDA stellt Mail zu, wenn aber offlineimap die lokalen Mails mit dem Server abgleicht, sind sie schon längst zugestellt.


Ich musste also die Mail aus der Inbox des Servers erst zustellen, bevor offlineimap sie zu Gesicht bekam. Dazu kann man z.B. Fetchmail verwenden oder aber das modernere getmail. Dessen Autor hat übrigens ein paar deutliche Worte für fetchmail übrig. 

Ich habe mich dann für einen Fork entschieden, der auf meine verschlüsselte Passwortdatei zugreifen kann:

passwordeval = gpg -d ~/.mutt/pw.gpg |awk '/my_gwdg/{print $NF}' |tr -d '"'

Getmail kann die Zustellung an Procmail delegieren:

type = MDA_external
path = /usr/bin/procmail
arguments = ("$HOME/.procmailrc.gwdg",)

delete = true
message_log = ~/Mail/getmail.log

Die Inbox liegt in der Mailverarbeitung jetzt also vor der Zustellung und ist für offlineimap tabu:

folderfilter = lambda folder: folder not in ['INBOX']

Das heißt andererseits, daß ich lokal einen neuen Posteingang brauche, damit offlineimap diesen wieder mit dem Server synchronisieren kann. Das geht mit einer passenden Zeile in der procmailrc:



Jetzt word meine Mail per Getmail vom Server nur aus der Inbox abgeholt, üer procmail hefiltert und zugestellt, befor sie per offlineimap wieder auf dem Server landet, und zwar schön sortiert in Dutzenden von Ordnern -- bloß nicht in der Inbox, sonst haben wir doch woeder eine Loop. und hanz nebenbei bietet mir procmail die Möglichkeit, nach Herzenslust Mailinglist-Tags aus Betreffzeilen zu entfernen oder z.B. Mails von mir an mich gleich in Todos zu verwandeln.

Kein Kommentar

von kirjoittaessani

Ein paar Gedanken zu Terror der Tentakel von A. Lee Martinez:

Für eine richtige Rezension fehlen mir Zeit und Lust, aber zwei Punkte, die mich besonders gestört haben, will ich erwähnen. Zum einen vermisse ich "Show, don't tell" -- stattdessen finden sich endlose, ziemlich witzlose Dialoge, die die Story voranbringen sollen. Zum anderen gibt es viel zu viel erzählerische Magie -- ob die Handelnden z.B. einen Kampf gewinnen oder durch Konstruktion einer aberwitzigen Maschine einen Ausweg aus einer schwierigen Lage finden, richtet sich rein nach den Wünschen des Autors, ist aus der inneren Logik der Geschichte aber nicht zu erklären. Da müssen drei von fünf Sternen reichen. 

Kein Kommentar

von kirjoittaessani