The Carp Programming Language

by Eric Shimizu Karbstein

This book is a working in progress, I will try to keep up-to-date with the language.

This version of the text assumes you're using the master branch of the language (In the future it will change to version 0.4).

Introdution

Welcome to The Carp Programming Language, an introductory book about Carp. Carp is a small programming language designed to work well for interactive and performance sensitive use cases like games, sound synthesis and visualizations. It uses a ownership system to achieve automatic and deterministic memory management similar of the Rust programming language.

Although it looks like a lisp, it is not. The runtime semantics are much closer to those of ML or Rust.

Who Carp Is For

TODO

Who This Book Is For

This book assumes that you’ve written code in another programming language but doesn’t make any assumptions about which one. We’ve tried to make the material broadly accessible to those from a wide variety of programming backgrounds. We don’t spend a lot of time talking about what programming is or how to think about it. If you’re entirely new to programming, you would be better served by reading a book that specifically provides an introduction to programming.

How to Use This Book

In general, this book assumes that you’re reading it in sequence from front to back. Later chapters build on concepts in earlier chapters, and earlier chapters might not delve into details on a topic; we typically revisit the topic in a later chapter.

In most situations, we'll lead you to the correct version of any code that doesn't compile.

Getting Started

In this chapter we'll discuss 3 topics:

  • Installing and setting the tooling of the language
  • Writing a program that prints Hello, World!
  • How to use the compiler and the REPL

Installation

Note: This book assumes basic familiarity with the command line.

Important Note: Make sure that you have a C/C++ compiler installed, since Carp compiles to C and then it calls a C/C++ compiler to output a native binary.

Binaries

TODO: When 0.4 is released

Arch User Repository

If you use ArchLinux, you probably know what to do, but anyway for the early, still learning, users of the Linux distribution.

You will need the following:

  • A internet connection
  • Yay or any other AUR helper installed

Assuming you have yay installed

$ yay -S carp-git

Then set in your shell configuration file an environment variable that tells the Carp compiler where to find the core library:

export CARP_DIR=/usr/lib/carp/

From Source

Since the language is in a early stages we'll teach how to install from the Carp Github source tree. For that you'll need:

  • A internet connection
  • Git installed
  • Stack installed

Let's start!!

Cloning the repository:

git clone https://github.com/carp-lang/Carp

UNIX and UNIX-like

Building:

It may take a while. This will install the binaries inside $HOME/.local/bin folder.

# Go to the Carp folder
$ cd Carp

# Build AND install command
$ stack install

Setting the core library:

# Putting in the appropriated place
$ mkdir ~/.local/lib/carp
$ cp -r core ~/.local/lib/carp

If your ~/.local/bin is not in the PATH, add it in your shell configuration file

export PATH=$PATH:~/.local/bin

Then you have to add a environment variable in your shell configuration file to tell where the core library is.

export CARP_DIR=~/.local/lib/carp/

Windows

TODO

Hello, World!

Now that you have Carp installed, lets start with the tradition of writing a hello world program. It's a simple program that output in the terminal Hello, World! and that is it.

Creating a Project Directory

Start by making a directory to store your Carp code. It doesn't matter where, but for this book exercises we do recommend to crate a directory in your home directory just to put all book projects.

For UNIX/UNIX-like:

$ mkdir ~/book_projects
$ cd  ~/book_projects
$ mkdir hello_world
$ cd hello_world

For Windows:

> mkdir "%USERPROFILE%\book_projects"
> cd /d "%USERPROFILE%\book_projects"
> mkdir hello_world
> cd hello_world

Writing and Running a Carp Program

The next step is to create a new file called Main.carp.

Note that Carp files end with .carp. If you are using more than one word in your filename, write the first letter of each word as upper case, for example, use HelloWorld.carp instead of Helloworld.carp.

Now open the Main.carp file you just created and enter the code in Listing 1-1

(defn main []
    (println* "Hello, World!"))

Listing 1-1: A program that prints Hello, world!

Save the file and go to the terminal window and enter the following command:

carp -x Main.carp

The -x flag tells the compiler to compile and run the program.

Anatomy of a Carp Program

Let's understand what is going on this program.

(defn main []
                              )

Here we have tree things to look at. The first is the defn, it is a keyword that let us define a new function, it is followed by a function name, in this case it is main, then followed by the parameter list (the [] part), the list is empty because this function does not receive a parameter, if the parameter list was not empty it would have something inside the square brackets.

The main function is special, because it is the first part of the code that runs in every executable Carp program.

Inside of the main function we have:


    (println* "Hello, World!")

This line prints text to the screen. There is some details in here:

The println* here is a Carp macro. Although it is something different than a function, the call syntax is the same, you cannot tell the difference until you look into the function/macro implementation. And everything between e double quotes (") is a string literal.

REPL and Compiler

The REPL

Let's start with the REPL, it stands for Read Eval Print Loop, it is a common feature in many languages and almost cultural in Lisp based languages, the way it works is quite simple, it reads the expression or statement given by the user, then evaluate it, print it's result and do it all over again. A REPL is great tool for testing and prototyping a idea direct from the terminal.

In Carp, you can start the REPL invoking the carp binary without parameters.

On UNIX/UNIX-Like:

$ carp

On Windows:

> carp

Inside the REPL, there is some special features that can be used and probably will be helpful when writing or debugging code.

Help: With no parameter, it displays the general help message, while giving a chapter name.

;; No parameter
(help)

;; With parameter
(help "language")

Type: It receive a symbol and it gives the type of that symbol

(def a 10)
(type a)

It should return:

a : Int

Because a is defined as 10 a Integer number.

Info: It receives a symbol and it gives the information about that symbol

(def a 10)
(info a)

In this example, it should return something like:

a : Int
Defined at line 1, column 1 in 'REPL'

Compiler

Note: Unless your project is a library, you project must have a main function.

Carp compiles to C and then call a C compiler to generate the binary. By default the generated files and binaries will be on a directory called out, but it can be changed in the project configuration.

Configuring the project

This part is quite simple, following the same pattern in the toplevel of the project:

(Project.config <setting> <value>)

To configure more than one setting, just keep adding the same pattern one more time in the next line.

Here is the setting options and what it takes as values:

  • "cflag": Takes a String: Add a flag to the C compiler.
  • "libflag": Takes a String: Add a library flag to the compiler.
  • "compiler": Takes a String: Set what compiler should be run with the build command.
  • "title": Takes a String: Set the title of the current project (the final binary name will be this string)
  • "prompt": Takes a String: Set the prompt in the REPL
  • "search-path": Takes a String: Add a path where the Carp compiler will look for '*.carp' files
  • "output-directory": Takes a String: Where to put build artifacts
  • "docs-directory": Takes a String: Where to put generated docs
  • "generate-only": Takes a Bool: Set to true if you don't want to run the C compiler when building
  • "echo-c": Takes a Bool: When a form is defined using 'def' or 'defn' its C code will be printed
  • "echo-compiler-cmd": Takes a Bool: When building the project the command for running the C compiler will be printed
  • "print-ast": Takes a Bool: The 'info' command will print the AST for a binding

Compiler flags

  • -b: Just compile the files
  • -x: Compile and run the files
  • --optimize: Compile the generated C file with -O3 optimization level
  • --check: Just check the files if they are valid Carp and report all errors
  • --generate-only: Only generate the C file.