vsedach / Vacietis

C to Common Lisp compiler
Other
307 stars 25 forks source link

Vacietis is a C compiler for Common Lisp systems.

Vacietis works by loading C code into a Common Lisp runtime as though it were Lisp code, where it can then be compiled or evaled. The loaded C code has the same function calling convention as regular CL code and uses the same numerical representations. C memory is backed by regular Common Lisp arrays.

Vacietis comes with a libc implemented in portable Common Lisp.

You can obtain Vacietis from github: git clone https://github.com/vsedach/Vacietis.git

All Vacietis dependencies are available via Quicklisp (http://www.quicklisp.org/). If you put Vacietis in quicklisp/local-projects/ you can just load it with (ql:quickload "vacietis")

C code can be read in the same way as regular Lisp code by using readtables:

(let ((readtable vacietis:c-readtable) (vacietis:compiler-state (vacietis:make-compiler-state))) (read ))

The Vacietis reader keeps track of type and preprocessor macro declarations in a compiler state object bound by compiler-state. This mechanism is exposed to make it possible to create things like C REPLs.

To simplify loading C files, a convenience function is provided that sets up the readtable, compiler state, and additional debugging information before calling LOAD:

(vacietis:load-c-file "/foo/bar/file.c")

The system vacietis.vcc produces a toy C compiler executable that can take a single-file C program and produce an executable program. Currently it needs CCL, CLISP, or SBCL to work. Sample run:

(ql:quickload "vacietis.vcc") will produce the executable vcc/vcc in the Vacietis source directory.

$ ./vcc ../test/programs/hanly-83-scanf/main.c

Produces the file a.out in the current directory.

$ ./a.out Enter 8 numbers separated by blanks or s

Vacietis uses the memory model of Common Lisp as is, so sizeof of the primitive data types (char, int, float etc.) is all 1. This shouldn't be a problem for most C code, but some C programs claim to be portable while making assumptions that things can be cast into an array of chars to be manipulated. These programs won't work under Vacietis.

The basic idea for the Vacietis runtime and memory model comes from Scott L. Burson's Zeta-C compiler for Lisp Machines: http://www.bitsavers.org/bits/TI/Explorer/zeta-c/

The technique for representing pointers to arbitrary C lvalues as closures was first demonstrated by Oleg Kiselyov: http://okmij.org/ftp/Scheme/pointer-as-closure.txt

The idea for a combined single-pass preprocessor/tokenizer/parser comes from Fabrice Bellard's TCC: http://bellard.org/tcc/

The official Vacietis repository is at: https://github.com/vsedach/vacietis

There is a Vacietis mailing list on the web: http://groups.google.com/group/vacietis

Bug reports can be sent to the mailing list: http://groups.google.com/group/vacietis the github issue tracker: https://github.com/vsedach/vacietis or directly to the author: vsedach@gmail.com

(ql:quickload "vacietis.test") (vacietis.test:run-tests) (eos:run! 'vacietis.test.reader::preprocessor-nested) ; individual test case

The Vacietis test suite includes a variety of code that tests the compiler and libc.

Vacietis is authored by Vladimir Sedach vsedach@gmail.com; the latest copyright year is 2012.

Vacietis is licensed under the LLGPL (see the file LICENSE included with the distribution for details).

Portions of the Vacietis libc may be derived from Zeta-C (released into the public domain by its author, Scott L. Burson) and Erik Andersen's andersen@codepoet.org LGPL-licensed uClibc (http://www.uclibc.org/)