The Compiler Manual

To learn more about the Carp language and its syntax and semantics, check out the Carp Language Guide.

REPL Basics

The Carp language is very tightly integrated with the REPL, everything you want to do to your program can be controlled from here.

To load code from disk, use (load "filename.carp"), this will add the source file filename.carp to the current ‘project’. A project is a light weight concept in the repl that ties together source files and compiler settings much like in an IDE like Eclipse or Visual Studio.

To build your current project, call (build). This will emit an executable or dynamic library depending on if you have defined a main-function or not. Please note that a project emitting a library will not initialize global variables automatically, the user of the library needs to call the C function carp_init_globals or the Carp function System.carp-init-globals instead.

Everything emitted by the compiler will be saved in a directory named out by default. This, and other settings regarding the project can be changed by various commands. To see a list of available commands, call (help "project").

There are a bunch of handy shortcuts for doing common things at the REPL:

:r   Reload all the files of the project
:b   Build the project
:x   Run the executable (if it exists)
:c   Look at the emitted C code
:e   Display the environment with all the function bindings and their types
:p   Show project information and settings
:h   Show the help screen
:q   Quit the repl

Differences compared to REPL:s in other Lisp:s

While powerful, the REPL in Carp currently has some big limitations compared to most other Lisp:s. If you type in an expression and press enter one of the following things will happen:

  1. If you’re calling a dynamic function (something defined with defndynamic, or a built in command) it will be executed right away. This works very much like a classic, dynamically typed Lisp interpreter. The dynamic functions are not available in compiled code! Their main usage is in macros and to programatically control your build settings.

  2. If you’re calling a function defined with defn it’s a “normal” Carp function which will be compiled (via C) to an executable binary, which is then run in a child process to the REPL. This means that the function has no chance to modify anything else in your program, like global variables and the like.

  3. If the top-level form isn’t a function call, the REPL might get confused. For example, entering an array of calls to a Carp function will give unexpected results (the array will be dynamic but the function calls will not). The easiest way to work around that at the moment is to wrap the expression in a defn and call that one instead. This will be fixed in a future version of Carp.

Adding annotations

Carp has a flexible metadata system (inspired by the one in Clojure) that lets anyone add and retrieve data on the bindings in the environment. The general way to do that is with (meta-set! <path> <key> <value>) and (meta <path> <key>).

A couple of useful macros are implemented on top of this system:

(doc <path> "This is a nice function.") ; Documentation
(sig <path> (Fn [Int] Bool))            ; Type annotation
(private <path>)                        ; Will make the function inaccesible to other modules

Note that <path> in all these cases are symbols, e.g. foo or

To generate html docs from the doc strings, run:

(save-docs <module 1> <module 2> <etc>)

Getting types from bindings

 (type <binding>)
 :t <binding>

Listing bindings in a module

 (info <module name>)
 :i <module name>

Expanding a macro

 (expand 'yourcode)
 :m yourcode

Configuring a project

The current session in the repl is called a “project” and can be configured using the (Project.config <setting> <value>) command. The following settings can be configured with this command:

For example, to set the title of your project:

 (Project.config "title" "Fishy")

To use another compiler:

 (Project.config "compiler" "tcc")

Profile settings

If a file called profile.carp is placed in the XDG config folder carp/, that file will get loaded after the compiler has started (after loading the core libraries but before any other source files are loaded). This file is meant for user specific settings that you want in all your projects, like little helper functions and other customizations.

On Windows this file is located at C:/Users/USERNAME/AppData/Roaming/carp/profile.carp.

Compiler flags

When invoking the compiler from the command line you can supply the following flags to configure the behaviour:

Inspecting the C code generated by an expression

 (c '(+ 2 3))


Cross-compilation needs to be enabled early. You can do so in profile.carp as:

(Project.config "compiler" "zig cc --target=x86_64-windows-gnu")
(Project.config "target" "x86_64-windows-gnu")

Or using --eval-preload as:

carp --eval-preload '(Project.config "compiler" "zig cc --target=x86_64-windows-gnu") (Project.config "target" "x86_64-windows-gnu")' -b whatever.carp