Thursday, May 01, 2014

Lowering in language design, part one

Programming language designers and users talk a lot about the "height" of language features; some languages are considered to be very "high level" and some are considered to be very "low level". A "high level" language is generally speaking one which emphasizes the business concerns of the program, and a low-level language is one that emphasizes the mechanisms of the underlying hardware. As two extreme examples, here's a program fragment in my favourite high-level language, Inform7:

Overlying relates one thing to various things. The verb to
overlie (it overlies, they overlie, it is overlying) implies 
the overlying relation. 

The jacket overlies the shirt. The shoes overlie the socks. 
The slacks overlie the undershorts. The shirt overlies the

Before wearing something when something (called the impediment)
which overlies the noun is worn by the player: try taking off
the impediment; if the player is wearing the impediment, stop 
the action.

This is part of the source code of a game;1 specifically, this is the code that adds a rule to the game that describes what happens when a player attempts to put on a pair of socks while wearing shoes. Note that the function which takes two objects and returns a Boolean indicating whether one overlies the other is not written as a function but rather as a relation associated with a verb, and that the language even allows you to provide a conjugation for a non-standard verb so that you can use it in any natural English form in your program. It is hard to imagine a language getting closer to the business domain.

By contrast, x86 assembler is a very low-level language:

add ebx, eax
neg ebx 
add eax, ebx
dec ecx

In one sense we know exactly what this fragment is doing; adding, negating and decrementing the values in registers eax, ebx and ecx. Why? Hard to say. The business domain is nowhere found here; this is all mechanism.