Which language is more expressive, Lisp or Haskell?

I want to encourage you to forget the word expressive,” or at least, strive to give it a particular sense in your language advocacy, because it means different things in different contexts, often nuanced and slightly contradictory things.

When Lisp is promoted as an expressive language, what is meant is that there is a complete macro system, and it is not difficult to write either abstract code or quite frankly machine-friendly, near-optimal code. But when Haskell is promoted as an expressive language, what is usually meant is that it has an extremely powerful type system that can express very abstract ideas. Few people seem to know it has a complete macro system inspired by Lisp—this does not seem to be a factor in its expressiveness.”

In a certain sense, every strongly-typed language is less expressive than a weakly-typed language. Many classes of error that the strongly-typed language prevents the weakly-typed language would allow. There are literally more expressions” in the weakly-typed language. This loss of expressiveness” does not seem to keep advocates of Haskell from getting enough sleep, even though there are certainly programs that do not type check (or could not be made to within the confines of any particular regime) that are nonetheless correct, despite their unlikelihood.

Any program that my machine can execute can be written in assembly. Does that make assembly the most-expressive language? What if I want to say one thing and have it mean the same thing on different machines? Portability, in other words. If that constrains my options, does that also reduce expressiveness or improve it? Can you say more with haiku or with any random jumble of words?

A J program might be abstract over matrix dimensions for free. Can something be more expressive sometimes and less in others, depending on the context?

How does high-level” vs. “low-level” fit into this? Prolog is more high-level;” it has actual relations rather than just functions, and it will often figure out what you mean without you telling it how to do it. Yet, as Paul Graham once observed, it often actually requires more code to make a program in Prolog. And if it is more high-level,” why did the Fifth Generation Project fail, and why does it sort of languish as an interesting class project but not widely used today?

More questions than answers, as usual.

November 12, 2015






People often ask me which functional language they should study first. This is my road map” to functional programming languages.

Clojure is a very nice, highly pure functional language. It’s an untyped Lisp language, which means it emphasizes syntax macros, but it is just a really nicely designed language, very well-suited to data processing and gluing together Java libraries.

Haskell is the flagship typed functional language. Lots of ideas in FP reach their high water mark in this language, which is famous for being difficult to learn and very mind expanding. If you’re interested in terseness and correctness, it’s recommended, but it can require some study before being able to use it in anger.

Factor is, IMO, the to-beat concatenative language. It’s a very different computational model, similar to Forth, where everything is a stack operator, but object-oriented, principled, and has a large and helpful standard library, making it easy to do things like build trivial GUIs and do XML processing.

Prolog is the go-to declarative/logic programming language. Great for learning about non-determinism and doing natural language processing, it has a built-in database and generic parsing framework. The flagship implementation is SWI-Prolog, which has a rich standard library, though the language has a lot of crufty spots due to its age.

J is the open-source array-oriented functional language. In the tradition of APL (which defined its own character set), it is based on the idea of matrix operators and implicit iteration. Its relatives are widely used in finance. The language is basically unreadable to the untrained eye but reaches new levels of terseness.

These represent, IMO, nice local maxima.” Underneath most of these there are some nice variants that present somewhat different tradeoffs with the same basic flavor.

Under Clojure, you’d find other Lisp variants, namely Racket, Common Lisp (SBCL, Clozure), Scheme (Guile, Chicken), newLisp, and LUSH, which each represent different tradeoffs: Racket is a nice learning environment based on Scheme but with a vast built-in library; Common Lisp is closer to C++ in terms of size, features and pragmatism; Scheme is a tiny academic language with many incompatible implementations, newLisp and LUSH are specific Lisp implementations with small domains (one of which is scientific computing).

Under Haskell, you would mostly find OCaml and Standard ML (SML/NJ, Moscow ML, MLton, Poly/ML), which are smaller and simpler languages. OCaml has a vibrant pragmatic community centered around finance where Standard ML is used almost exclusively in academia. The CLR implementation is called F#, and mostly resembles OCaml; Scala would be the JVM language most similar to Haskell. I personally have a small beef with Scala because I think it is the worst of both worlds,” both large and complex, hard to comprehend, and by supporting all of Haskell and Java, it winds up being a bit too big and kitchen-sinky. But it has its fans, particularly at RiskSense. Standard ML is more like Scheme: an academic language with a tiny core. It’s famous for its package system though, which only OCaml really does justice to—even Haskell doesn’t have as much power, here, though type classes are pretty convenient. Mythryl is another ML-derived language, a bit closer to C.

Under Factor there is basically Forth, which is still supposedly used by embedded systems (every Forth is different) and Joy, which nobody really knows, an academic exercise that never really went anywhere.

Prolog really only has Logtalk, which is a powerful object-oriented extension, and a few really obscure attempts to modernize it, whose names escape me. Prolog is not widely used, but much more so than any other language in this category (except maybe SQL, if you count that.)

Finally, J has Kx, which is not free, and APL, which is also not free and quite odd (Dyalog being the flagship APL implementation.) But the arguments for the other ones are not especially strong.

October 14, 2015






If you’re like me, you’re always in search of new ways to fetishize your books. I recently started keeping track of my books at all—a few too many of my expensive computer science tomes have walked away without my really knowing who has them. This has to stop, but solving this problem is boring and easy. You just go install Delicious Monster or BookPedia or something.

If we want to make the task harder, and thus, more fun, we have to go further than that. We have to assign books call numbers. This is the only way to convert your freeloading friends into legitimate library patrons.

What Librarians Do

What do librarians do? I never really asked myself this question. I assumed they had things to do other than ssh!”ing people but I never really probed further than that. It turns out one of their major problems is classifying the books. Perhaps you thought, as I did, that every book has a magic code on the inside flap with where it should be placed! Well, many do, but many do not, and aside from that, this just gets you the class of the book, not whatever additional information you might want to incorporate into the call number.

You may be surprised to discover, as I was, that every library (potentially!) uses different call numbers to identify books. The call number usually incorporates some auxilliary information about the book, like the author, title, or year of publication. There are three purposes for the call number: to make it possible to uniquely identify a book, to give your patrons a way to look for a book, and to give you a unique relative placement for the book on the shelves. The latter thing there implies sortabililty.

Methods

There are four ways to classify books, and they each have strengths and weaknesses. The Library of Congress classification (LoC) has a pleasant hideous formality, but the tables are quite enormous and it has a tendency to scatter related things into different corners. Dewey (DDC) has that childish air to it, but can be delivered in a single abbreviated volume and produces short and tidy call numbers. Universal Decimal Classification (UDC) adds some syntatic horror and can be had in a real electronic format. It is, unfortunately, almost totally unheard of here in America. And then there is the Colon Classification, which deserves a special, lengthy introduction.

Colon Classification

The primary problem as perceived by LoC and DDC is: where does this book go on the shelves? And that question raises design concerns: one wants books to be together with other books on the same topic rather than sorted by color or author’s favorite animal. So both spend most of their effort trying to figure out what the real subject of the book is, so they can produce a call number that puts things together helpfully.

This isn’t the only perspective though. Colon instead seems to be saying: let’s create a precise, formal statement about the subject of a book. That statement can then be encoded into a terse syntax, and we’ll use that syntax as the class portion of the call number.

All of the work done in other systems to produce the total classification is just part of the personality” facet of the book under CC. A further four facets can be used to narrow the book down by time, space, noun and verb (called matter” and energy” but I prefer my words). Then, each class or subclass can define its own facets. History, for instance, using additional time and space facets to discuss the subject of the book, freeing up the other two for the origin of the book itself. Literature makes the author a facet. And then there are a great number of additional devices” that can be used to go further: books can be promoted to classic” status and made into their own category; anteriorizing and posteriorizing facets to describe the structure of the book. The language and form, whether it is a commentary on some other book, etc. can all be encoded. Further, the personality” can be combined with other personalities with special codes to indicate, for instance, the book contains both, or the book is in one subject biased for people who know another, or the book compares or discusses the similarities or differences between two subjects. Facets can be connected with each other. And this whole process can be nested in a recursive fashion, leading to terms like second round energy.”

While shockingly powerful as a way of encoding a statement about a book, it suffers greatly from the huge complexity. The sorting rules are not at all intuitive: some sections are to be treated as integers, others as decimals. There is an octavizing digit” that changes the sorting order, so you count 1, 2, 3, … 8, 91, 92, 93, … 991, 992, etc., but each class of character has one (so, z for lower-case alphabetic characters). Additionally, much complexity is spent trying to save a character here or there: instead of writing 2010, you would write N1, or N14 for 2014. It’s not clear to me that the syntax would be all that parseable to a lay person after any amount of use.

APL

The whole thing reminds me a lot of APL. Reading the book A Programming Language is a fairly uncomfortable affair because of the strange order and missing information. One gets the sense that the language doesn’t really make a distinction between syntax and semantics. It jumps around strangely from low-level to high-level concerns and back. It’s kind of a poor spec.

Colon Classification, 6th Edition is a lot better, but still has that sort of feel to it. One of the early definitions specifies the character set for the call number as containing some Greek letters.” Which ones? Read two more pages, and you’ll see them listed in their sort order. Similarly, what appears in what order in the call number? It says the collection number can go above” the class and the book number can go below” the class when printed vertically (two different rules) but for the normal left-to-right direction nothing is said explicitly. I infer that it would go collection-class-book from the order it would appear vertically.

In other ways, it reminds me of SGML, prior to XML. The chronological device” that saves you a whole digit or two, for instance, is very reminiscent of not needing closing tags. With a class number like L,45;421:6;253:f.44’N5, how much worse is the two-character longer L,45;421:6;253:f.44’1950, really?

The benefit of CC is the facets. But on your bookshelf, you don’t benefit much from the facets. Either your collection is so small, every category has one book, or your collection is so huge, only the first part matters anyway. The facets might help if you needed to do faceted search, but you’re either looking for one of your own books, or you’re doing an electronic search, where the facets don’t need to be called out explicitly.

It would probably be beneficial for searching to have a comprehensive statement of the subject matter of a book. And in that case, having a complex of facets like CC provides would probably be helpful. But if you aren’t using it as the call number, there’s no need for the syntax to be so murdersome. Choosing a restricted vocabulary and a sensible metadata format would be enough; whatever you chose, if it has an electronic representation that can be parsed by a machine, you’re done—there’s no need to create horrors like the above. Even a basic full-text search on any of the words in the sentence Research in the cure of the tuberculosis of lungs by x-ray conducted in India in 1950s” would get you meaningful results.

Planes

Ranganathan structured CC with a separate language” plane for the human expression and a number” plane for constructing the call number. I’m not sure his syntax is worth so much it would be worth saving (Medicine,Lungs;Tuberculosis:Treatment;X-ray:Research.India’1950) instead of something else, but it raises the question (for me) of whether it would be meaningful or helpful to use CC to develop statements about the subject of books_, even if one were using DDC to file them on the shelf.

Improvements?

The detour through CC was intellectually refreshing. The system is quite interesting, but ultimately, seems to be more like two half-solutions to two problems than a complete solution to either a metadata problem or a call number problem. I could see someone else applying the system—particularly if they have a large collection of Indian religious texts, as that’s the only fully-elaborated example in the book. For someone like me, a computer science-y guy with a fondness for formality and a large collection of CS-related books, I’m not convinced you’d be able to implement the system faithfully anyway. I think you’d wind up having to create so much from scratch (and fail to properly apply so much of the many and complex rules) that you’d be no better off than trying to come up with something yourself out of whole cloth. For instance, these ideas occurred to me while reading Colon Classification, 6th Edition:

  • Maybe I should co-opt another Greek letter for the Main Class for computer science. Perhaps Λ?
  • I could devise a real collation around an actual character encoding (such as Unicode) if only I…
    • removed the Greek letters or sorted them to the end instead of after the nearest similar Latin letter”
    • removed the octave device”
  • I should get rid of the chronological device,” because it doesn’t save enough
  • I should write a formal grammar for the syntax of this thing

And so forth.

Conclusion

Ultimately, I have decided to go forward with Dewey Decimal Classification. The abbreviated guide for one edition out-of-date can be had for $15 on Amazon. For a small collection like mine, this will be totally sufficient to the task of putting my books in order. DDC is also widely-used in sub-collegiate libraries. My wife won’t find it nearly as objectionable, and my son may benefit from being exposed to it. Also, you can find code like mine to query OCLC to look up DDC classes for books, and many books come with a DDC classification printed in them as part of the CIP data.

I would still like to think about the metadata problem. CC is very interesting and powerful, and might provide some inspiration here, but I think ultimately other modern systems are probably just as powerful and without the drawbacks.

For a better-written take on the same problem, please see this article by David Mundie.

March 27, 2014






John Carmack says VR is going to change the world. That ain’t gonna happen. Here’s why:

Zero mainstream non-gaming applications

The PC revolutionized the world because every office with a typewriter or a calculator eventually switched to a PC. Nearly every office function is augmented or replaced by a computerized version. A word processor is manifestly better than a typewriter. The calculator became a spreadsheet. The centerpiece of the meeting is a Powerpoint presentation; several participants are remote.

To suggest that something is going to be as big or bigger than the PC revolution, one must have in mind that whatever it is will augment or replace every PC. So what’s the lady at the DMV going to do with a VR headset? Immerse herself in the web-based registration database?

Casual gaming is worth more than dedicated gaming

The biggest phenomenons in gaming of the last ten years were Angry Birds and Farmville. While gamer geeks obsess over technical specifications and drool over technology like the Oculus Rift, the rest of the world is quietly Candy Crushing at the DMV. If I can’t play your game in a waiting room, I’m not going to play your game at all. This is the kind of fact that upsets the true believer, much like college students love to hate pop musicians for the sin of making fun, accessible music. The greater the love and technical finesse in a genre, the smaller the appeal, the higher the cost of bringing a new product to market, and the lower the revenue. Grand Theft Auto is a major outlier.

Looking like a tool = failure

Where have all those bluetooth headsets gone? Five years ago they were the unmistakable symbol of being serious business. Today they’re the unforgivable mark of being a tool. People who still use them keep them politely in their shirt pocket when not in use. I wish I could say this is in response to the unbelievable rudeness of being one second away from answering your phone while conversing in person on a ten second delay, but I know the truth. They’re just unfashionable. Using your touchscreen phone does not make you look like a tool.

We don’t want more bandwidth with our tools

Someone tried to sell me on this technology with this: Imagine a world in which you can actually lose track of, or be mistaken about exactly which level of simulation you’re currently experiencing.” Imagine all that, minus all your understanding of how computers work, minus your operational knowledge. This is a horror movie scenario, not a technology someone will buy for themselves to experience. Programmers and power users may imagine they want a higher bandwidth interface to the machine, but muggles want that about as badly as they want a higher bandwidth interface to their washing machine. Take your discomfort and square it? No thanks. The harder a tool is to put down, the more specialized it is, the less mass appeal it has.

Imagine the possibilities, man

Asking for examples how use outside gaming, I got a few good specialized ideas but mostly a bunch of bad ones.

  • Education. Why would children watch a slideshow about ancient Egypt when they can walk in a digital recreation made by brilliant artists/game designers who worked with leading historians, archeologists, etc. I’ll warrant that experiencing things first hand’ will make people learn faster/better.”

For one thing, comparing a musty, shitty old slideshow to a state-of-the-art, Hollywood-budgeted masterpiece isn’t a fair comparison. As it happens, we already have something like that though: IMAX movies. And guess what? It’s neither saving nor destroying education, and the idea that virtual reality might help it is assumed rather than proven.

To take a brief detour, everybody loves to complain about education, but where is the proof that what we have is a technical problem? I think technology is the one avenue to improving education that has actually been explored. A good half of teachers are complete technophobes, the other half are clearly tech-obsessed, yet the results speak for themselves. What is needed is individualized education from motivated educators not especially wedded to bureaucracy and non-educational goals (test results, raising costs, etc.) These are systemic problems that are totally orthogonal to technology. There is no technical problem with teaching, just systematized wrong incentives.

  • Training simulations.

Sure, but again, niche. The whole DMV office might have a need for one or two VR helmets at that point. They also only have one or two photocopiers—is that the kind of change the world” we’re talking about, with our big ol’ teary puppydog eyes?

  • It’s the next step after 2D displays. If you look at human history, we started with writing, then newspapers, then radio, followed by television. The way in which we consume media hasn’t changed from television/displays. Virtual reality is the next evolutionary step in media consumption. The final step being human-computer interfaces.”

Something can be the next step” and still not be the next big thing.” Writing is used for entertainment, but it’s not solely useful for entertainment. 3D might be better if it were free, but as long as it comes with a helmet tax or a glasses tax the improvement will have to offset the cost. How will 3D improve the news or the sitcom?

It’s helpful to compare to color. Color is a much bigger win than 3D, and it comes without imposing any nerd taxes. It isn’t invasive, in the sense that I can just walk away from a color TV. I don’t have to dismount or untangle myself or place anything in its charger. If there were a 3D TV I could just look at and see 3D, it would immediately destroy VR helmets and conventional 3D TVs. That would be a big advance, no question. But more than that, everything benefits from color: news, entertainment, information, emergency broadcasts, etc. The benefit of 3D is almost entirely limited to entertainment.

  • Supposedly the porn industry is one of the largest drivers of technology when it comes to media consumption.”

Invariably, somebody wants to bring up porn. To me, this is the least compelling capstone on the whole rickety arch. Your DVD player had a Select Angle” button on it. This was added by the porn industry, for obvious reasons—let’s face it, it would be a very odd cinematographic decision to provide the viewer with such options in a real movie. But notice your Blu-ray player does not have this button, because this feature was never used in real life.

I’m sure there are people who will be very interested in this application of technology. However, I doubt this will be a major driver of technological adoption. Everybody had a DVD player with the Select Angle button, but very few got that DVD player just to watch porn. Products that have such limited uses tend to be bought sparingly so as to fit in the sock drawer. The internet has already accomplished everything that can be hoped for vis-a-vis pornography.

  • It’s a cost issue

The technologists pimping VR have always laid out some kind of bizarre assumption that everybody would buy a VR helmet if only it were cheaper or more accessible or there were more somethings taking advantage of it. But this is like saying everybody would buy books with six-foot pages if only the cost were low enough. After all, such a book would be so much more immersive—you certainly couldn’t do anything else while reading it! Yet enormous books remain niche items, quietly resented by their owners for taking up too much shelf space and being too onerous for serious study on the toilet.

True technical innovation is mostly the drab story of accepting lower fidelity in exchange for secondary benefits. I’d much rather have a beautiful calligraphic script Bible written on the finest parchment than some movable type piece of junk with smeared ink and letters missing. Barring that, I’d much rather have a nice leather-bound edition on good quality acid-free paper with proper justification and footnotes, a beautiful font and proper ligatures. But apparently I’ll settle for one with no ligatures at all, rendered in dark grey Times New Roman on a light grey background—if I can keep it with a few thousand of my other favorite books on a Kindle or a Nook. (The recharge time on a paper book is utterly unbeatable, though the backlighting is, for the most part, atrocious.)

  • But it’s so much more real and immersive!

Have you noticed soap operas feel weird and unnatural for some reason you can’t quite put your finger on? It’s because they’re recorded in a 60 frames per second video format, unlike theatrical releases, which are still shot in 24 frames per second. For whatever reason, 24 fps seems to put our minds in the right place for movies. Reviews of the new Hobbit” movie were largely in agreement that the high frame rate” edition was less pleasant, robbing the movie of its cinematic look.” Technical virtuosity may be incompatible with an immersive cinematic experience. Looking better” made the movie worse.

We should not be too bothered by the idea that we have reached the limits of human perception with a particular medium. Audio CDs are essentially optimal for music. They encode much more than we can hear and stereo seems to be as much information as we need to reconstruct a reasonable semblance of depth. Competing platforms like SuperAudio haven’t really gained any traction partly because nobody can hear a tangible difference. The bigger reason for their flop obviously being that they were superceded by a lower fidelity alternative with better secondary benefits: MP3s.

Right now the TV industry is trying to get us excited about the idea of 4K TVs which promise pixels so small we’d have to be inches from the screen to see them. At the proper viewing distance from a normal” HD TV it would be impossible to see the pixels. Even streaming 720p to my 1080p TV I can see no discernible degradation of quality. Anyone trying to foist truly absurd levels of fidelity like 24/192 audio and 4K on us is missing the fact that people are watching movies on their phones and listening to music through bundled $10 earbuds, and perfectly happy about both. They will be using the next big thing, in home and office, working and playing.

A brief history of VR

Do you remember the video game Descent? It came out in 1994 and sported compatibility with several 3D systems of the day, like the iGlasses (no relation to Apple). We’re talking resolutions in the 320x240 range. The game was kind of a big deal, but the iGlasses? Not a big hit.

What about the Virtual Boy? It came out in 1995 and I got one, absolutely loved it: real 3D in bright red on black. The manual had some puzzling health remarks though: take a break every hour, for instance, and even the games mandated it (“auto pause”). It also mentioned that you might get headaches from playing with it or nausea, and you should really stop if you have a seizure. Monochrome plus headaches equals a very small fan base.

Suppose you have a technology. Only one gender is interested in maximizing fidelity of their entertainment, so you’ve already eliminated half the population. Now remove the 10% that lack depth perception for whatever reason, and another 10% that get nauseated or simply don’t like it. Cut it in half again to get the die-hard gamers. Now we’re talking about 10-20% of the population who might desperately want one of these things. Now you have to make it affordable and compelling. This is looking less and less like a mass-market hit. Niche? Sure. Sustain a company or two? Maybe, sure. A world-changing industry? Extremely doubtful.

Conclusion

I have no idea what the next revolution in computing is, but I can tell you what it won’t be: anything that improves” something by raising its fidelity while making you look like a goober.


Read the original thread at HN.

October 22, 2013






The best tool we have in computing is the relation. We have exactly two ways of representing a relation. One is a function. The other is a table. What could be more clear than this:

Table 1: Cats
Name Markings Disposition
Abby black and white skittish
Happy black and white talkative
Cookie calico warm
Ben black paternal

The programming language Prolog is explicitly relational. We would represent the preceeding table in Prolog explicitly with the following code:

% cats(Name, Markings, Disposition)
cats(abby, black_and_white, skittish).
cats(happy, black_and_white, talkative).
cats(cookie, calico, warm).
cats(ben, black, paternal).

This is pretty close to the table, but with a little alignment we can get closer:

% Name         Markings         Disposition)
cats(abby,   black_and_white, skittish).
cats(happy,  black_and_white, talkative).
cats(cookie, calico,          warm).
cats(ben,    black,           paternal).

Or using commas to demarcate columns:

% Name         Markings         Disposition)
  cats(abby  , black_and_white, skittish).
  cats(happy , black_and_white, talkative).
  cats(cookie, calico         , warm).
  cats(ben   , black          , paternal).

A better approach would be to adopt elastic tabs, permitting a much more natural visual representation.

% Name Markings Disposition
cats(abby, black_and_white, skittish).
cats(happy, black_and_white, talkative).
cats(cookie, calico, warm).
cats(ben, black, paternal).

Another way of representing it:

% Name Markings Disposition
cats( abby, black_and_white, skittish ).
cats( happy, black_and_white, talkative ).
cats( cookie, calico, warm ).
cats( ben, black, paternal ).

I leave it to other developers to decide which of these is nicer to look at.

A clear side-benefit to using elastic tabs is that the alignment is not based on a stable uniform character width. This means you can use fonts intended for reading, rather than fonts made to waste space.

What’s the downside? Apart from gedit, no editor implements elastic tabstops. The technology remains a good idea without meaningful implementations in common editors.

Why is this unused? I’m not sure. Reading about Emacs’s smart tabs” it sounds like Emacs itself doesn’t have a good way to do an absolute positioning. Calculating the distance in spaces from one tab to one absolute position is arithmetic, but laying out the page according to regions is not easy. Moreover, the code won’t render correctly in uninformed editors.

How important is correct rendering in other editors? Word documents don’t render correctly in Pages and vice-versa. The more complex the editor, the more likely it is that similar software won’t work identically. Yet programmers seem to hold beliefs that prevent the situation from getting better: we should be able to use any editor to edit the code, and the code should look the same in every editor.

Another thing that would greatly help: literate programming. Unfortunately, in this case, the elastic tabs have been simulated by an unbordered table. In order to export this properly to source code, the table would have to be eliminated in a syntactically acceptable fashion. Better would be writing literate tools that understand elastic tabs. Either way it’s more stuff to code, and for a tiny audience.

September 25, 2013






This is an implementation of Intermediate Challenge #125, Halt! It’s simulation time!”

The crux of the problem comes down to a table of virtual machine instructions like this:

Instruction Description
AND a b M[a] = M[a] bit-wise and M[b]
SET a c M[a] = c
JZ x a Start executing instructions at index x if M[a] == 0

I came up with the virtual machine abstraction, a 5-tuple machine with values for code, instruction pointer, instruction count, register values and whether or not the machine is halted. Then I defined some functions like get_register/3, set_register/4, set_instruction_pointer/3 which take a machine and some other arguments (a register number, for instance) and then return a value or a new machine with the appropriate change having been made. This is defined in halt_machine.pl.

Then I wrote a parser for the assembler input. It’s quite simple, looking essentially like:

instruction(and(A,B))           --> "AND", whites, int(A), whites, int(B).
instruction(set(A,C))           --> "SET", whites, int(A), whites, int(C).
instruction(jump_if_zero(X, A)) --> "JZ",  whites, int(X), whites, int(A).

The entry point to the parser handles the rest:

instructions([Inst|Instructions]) -->
instruction(Inst),
blanks,
!,
instructions(Instructions).
instructions([]) --> [].
    
program(Program) --> integer(_), blanks, instructions(Program).

A sample program like this:

3
SET 1 15
AND 0 1
JZ  0 1

will thus be parsed into a program” like so: [set(1,15), and(0,1), jump_if_zero(0,1)]. The assembler is defined in halt_parser.pl.

The table of operations is encoded directly using a custom operator:

:- op(700, xfy, :=).

spec(and(A,B))          :- m(A) := m(A) /\ m(B).
spec(set(A,C))          :- m(A) := C.
spec(jump_if_zero(X,A)) :- (m(A) = 0) -> ip := X ; advance.

Our evaluator is designed to first try to evaluate the instruction by loading and trying to evaluate the specification:

evaluate(M, X, V) :-
clause(spec(X), Body), evaluate(M, Body, V).

So, if I were to try evaluate(M, and(0,1), V) it will expand to evaluate(M, m(0) := m(0) /\ m(1), V). The rest of the rules for evaluate/3 handle the expansion in various ways:

evaluate(_, A,           A) :- number(A).
evaluate(M, m(A),        V) :- get_register(M, A, V).
evaluate(M, A /\ B,      V) :- evaluate(M, A, RA), evaluate(M, B, RB),
V is RA /\ RB.
evaluate(M, A -> B ; C,  V) :- evaluate(M, A, RA),
RA -> evaluate(M, B, V) ; evaluate(M, C, V).
evaluate(M, m(A) := B,   V) :- evaluate(M, B, RB), set_register(M, A, RB, V).

evaluate(M, advance,     V) :- advance(M, V).
evaluate(M, ip := X,    MA) :- set_instruction_pointer(M, X, MA).

The evaluation of m(0) := m(0) /\ m(1) will trigger the evaluation of m(0) /\ m(1), which will trigger the evaluation of m(0), then m(1), then A /\ B as it breaks the expression down into parts and evaluates each subtree, before evaluating m(0) := V to update the register. Special cases such as halted := true and ip := X are handled by calling special procedures to update other aspects of the machine.

The gain here is hard to overstate. Prolog doesn’t have arrays, for instance, but our sublanguage does.It’s easy to verify that the formal specification embedded in Prolog does the right thing, and it’s easy to verify that the sublanguage evaluator does the right thing. I think this technique will probably generalize nicely to other scenarios with Prolog. The rest of the code is visible in halt_assembler.pl.

This module doesn’t export the evaluation function directly; instead, callers are expected to provide the code and allow this module to handle executing it via execute/1 and execute/2, which run the code on a new machine, either discarding the final machine or returning it. The execution is also quite simple:

execute(Code, FinalMachine) :-
initialize(Code, InitialMachine),
execute_loop(InitialMachine, FinalMachine).

The loop is also pretty simple:

execute_loop(Machine0, MachineN) :-
execute_one(Machine0, Machine1),

%% if we're halted, display the message; otherwise continue
((is_halted(Machine1) ; instruction_count(Machine1, 10000))
-> do_halt(Machine1)
; execute_loop(Machine1, MachineN)).

The halt semantics there are as specified; either the machine just executed HALT or we’re at instruction 10,000. execute_one simply finds the next instruction and prepares to execute it. do_halt prints out whether the machine halted of its own accord or if it hit the 10,000 instruction barrier.

The main program is suitably simple:

process_file(File) :-
halt_parser:parse_file(File, Code),
halt_assembler:execute(Code).

May 30, 2013 prolog