To learn more about the Carp language and its syntax and semantics, check out the Carp Language Guide.
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
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
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
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:
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.
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.
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.
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
<path> in all these cases are symbols, e.g.
To generate html docs from the doc strings, run:
(save-docs <module 1> <module 2> <etc>)
鲮 (type <binding>) 鲮 :t <binding>
鲮 (info <module name>) 鲮 :i <module name>
鲮 (expand 'yourcode) 鲮 :m yourcode
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:
"cflag"- Add a flag to the compiler.
"libflag"- Add a library flag to the compiler.
"pkgconfigflag"- Add a flag to pkg-config invocations.
"compiler"- Set what compiler should be run with the ‘build’ command.
"target"- Set the target triple (useful when cross-compiling).
"title"- Set the title of the current project, will affect the name of the binary produced.
"prompt"- Set the prompt in the repl.
"search-path"- Add a path where the Carp compiler will look for ‘*.carp’ files.
"output-directory"- Where to put build artifacts.
"docs-directory"- Where to put generated docs.
"generate-only" - Set to true if you don’t want to run the C compiler when building.
"echo-c"- When a form is defined using ‘def’ or ‘defn’ its C code will be printed.
"echo-compiler-cmd"- When building the project the command for running the C compiler will be printed.
"print-ast"- The ‘info’ command will print the AST for a binding.
For example, to set the title of your project:
鲮 (Project.config "title" "Fishy")
To use another compiler:
鲮 (Project.config "compiler" "tcc")
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
When invoking the compiler from the command line you can supply the following flags to configure the behaviour:
-bBuild the code, then quit the compiler.
-xBuild and run the code (make sure it has a main function defined), then quit the compiler.
--no-coreRun the compiler without loading any of the core libraries.
--log-memoryThe executable will log all calls to malloc and free.
--optimizeRemoves safety checks (like array bounds access, etc.) and runs the C-compiler with the
--checkRun the compiler without emitting any binary, just report all errors found (in a machine readable way).
--generate-onlyDon’t compile the C source.
--eval-preloadEvaluate the provided string before loading any code (but after loading
鲮 (c '(+ 2 3))
Cross-compilation needs to be enabled early. You can do so in
(Project.config "compiler" "zig cc --target=x86_64-windows-gnu") (Project.config "target" "x86_64-windows-gnu")
carp --eval-preload '(Project.config "compiler" "zig cc --target=x86_64-windows-gnu") (Project.config "target" "x86_64-windows-gnu")' -b whatever.carp