Quip

Introduction

I'm a programming language geek. And every programming language geek has to, at some point, attempt to design a language. I've been trying since the late 1980s, going through quite a few different things in that time. This is my latest project.

I work mostly in C++. I wanted something that would interface nicely with standard libraries (libc on Unix, and also add-ons like Qt and SQLite). But I find C++ lacking in several areas.

Goals

Here's my list of primary goals (which can also be read as a list of shortcomings of C++):

I want a language that does all of that, while maintaining the ability to interface easily with C/C++ libraries.

STL does some of those, but I really don't like the syntax, e.g., using the shift operators for stream I/O.

The Boehm garbage collector adds GC, but conservative collectors make me nervous.

The Name

The name "Quip" originally came from "Quick Programming". It's also nice that the ".q" file name extension is not in common use.

Approach

I considered two approaches. The first is a new language, with a syntax similar to C++, with a full compiler (and maybe an interpreter, too). To be able to call C and C++ APIs, this language would need to maintain compatibility at the object layout / method call / name mangling level, which would be pretty difficult to do. In addition, writing a compiler is a big project.

The second approach is to build a framework around C++, along with some build tools. This is what Quip does.

Framework

This section explains how Quip addresses each of the goals listed earlier.

Garbage Collection

GC is done via reference-counting, using a "smart pointer" type. Heap-allocated classes do "typedef SmartPtr<Foo> P type, and "Foo::P" is used in place of the usual "Foo*".

In complex systems, where there are loops in the object graph, the programmer must use "Foo*" for backward pointers. This allows reference counts to decrement to zero, avoiding memory leaks.

(Note that there's no actual requirement that all heap-allocated objects be garbage collected. Quip code can interface to C++ libraries that have their own memory management scheme.)

String, list, and dictionary types; I/O library

These are all pretty straightforward. There are lots of examples to look at (C++ STL, Java, .NET, Perl, Python), and Quip tries to take the best bits from each.

Regular expressions

I ended up choosing PEGs instead of regular expressions. For a description of PEGs and an explanation of why they're better than REs, see Bryan Ford's paper from POPL '04.

Quip provides a PEG class, as well as simpler PEG functions on the String class.

Module system and scripts

Modules are written as a single .q file. Interface and implementation code are denoted by @interface and @implementation sections. Module imports use the @import directive. The Quip build tool reads .q files and generates .cpp and .h files, which are handed off to the C++ compiler. All dependences are handled by the build tool. It can either run the code immediately (like a script) or build an executable. (Actually, it always builds an executable; running it immediately is optional.) On Unix systems, you can start a script with "#!/usr/bin/quip".

(Yes, this looks a bit like Objective-C, though I'm trying to be a bit less kludgey.)

Pros and Cons of the C++ Framework Approach

A C++ framework has some advantages:

There are also disadvantages:

Status

This is an ongoing project. I'm planning to publish source code and documentation when it's ready for public consumption.