Home

Awesome

<p align=center><img src="./media/color-rounded-text.svg" alt="crumb icon" height="150"/></p>

The Crumb Programming Language

Crumb is a high level, functional, interpreted, dynamically typed, general-purpose programming language, with a terse syntax, and a verbose standard library.

It features:

*With the exception of IO

Click here to Get Started.


table = (map (range 10) {_ y ->
  <- (map (range 10) {item x ->
    <- (multiply (add x 1) (add y 1))
  })
})

From examples/mult-table.crumb


Game of Life in Crumb From examples/game-of-life.crumb


Find more examples under the examples directory.

Getting Started

Install

You do not need to clone this repo. Instead, follow the instructions in this template repo.

If you are on VSCode, you can install the Crumb syntax highlighter extension. The source for the extension can be found here.

Basics

All function calls are done with s-expressions (think lisp). For example,

(print "hello world")

In this case, the function print is applied with the string "hello world" as an argument.

All data in crumb is one of 6 different types:

  1. string
  2. integer
  3. float
  4. function / native function
  5. list
  6. void

We can store this data in variables, for example,

a = 5
b = "hello"

We can combine data together to form lists,

magic_list = (list 123 "hello" 42.0)

Lists are always passed by value.

We can encapsulate code in functions using curly braces,

f = {
  (print "Funky!")
}

(f) // prints "Funky"

Functions can get arguments, denoted using the "->" symbol. For example,

add_two_things = {a b ->
  (print (add a b))
}

(add_two_things 3 5) // prints 8

They can also return values using the "<-" symbol,

geometric_mean = {a b ->
  <- (power (multiply a b) 0.5)
}

(print (geometric_mean 3 5) "\n") // prints 3.87...

Functions operate in a few important ways:

  1. Function applications are dynamically scoped.
  2. Functions cannot create side effects.
  3. Like in JavaScript and Python, all functions are first-class.

Most of the features you may expect in a programming language are implemented in the form of functions. For example, here is a Fizzbuzz program using the add, loop, if, remainder, is, and print functions,

(loop 100 {i ->
  i = (add i 1)

  (if (is (remainder i 15) 0) {
      (print "fizzbuzz\n")
    } (is (remainder i 3) 0) {
      (print "fizz\n")
    } (is (remainder i 5) 0) {
      (print "buzz\n")
    } {(print i "\n")}
  )
})

From examples/fizzbuzz.crumb

You should now be ready to write your own Crumb programs! More info on how to build applications with events, files, code-splitting, and more, is found in the standard library documentation below.

Standard Library

IO

Comparisons

Logical Operators

Arithmetic

Control

Types

List and String

Syntax

Crumb utilizes a notably terse syntax definition. The whole syntax can described in 6 lines of EBNF. Additionally, there are no reserved words, and only 7 reserved symbols.

EBNF

program = start, statement, end;
statement = {return | assignment | value};
return = "<-", value;
assignment = identifier, "=", value;
value = application | function | int | float | string | identifier;
application = "(", {value}, ")";
function = "{", [{identifier}, "->"], statement, "}";

Syntax Diagram

Crumb syntax diagram, generated with DrawGrammar.

Tokens

"="
"("
")"
"{"
"}"
"->"
"<-"
identifier
int
float
string
start
end

Specifics

Strings are characters surrounded by quotes, for example:

"hello world"
"this is\nsplit between new lines"
"\e[31mthis text is in red\e[0m"

Escape codes in Crumb are equivalent to their respective C escape codes. The list of supported escape codes is:

"\a"
"\b"
"\f"
"\n" 
"\r"
"\t"
"\v"
"\e"
"\\"
"\""
"\x4d" // for arbitrary ascii chars

Integers are groups of number characters, that may be preceded by - for example:

1234
-14
345

Floats are like integers, but have a decimal in them, for example:

13.45
-2.3
745.0

Identifiers are any collection of characters, that are not separated by whitespace, don't begin with quotes or numbers, and are not any reserved symbols, for example:

hello
x₂
symbol1
+

Comments start with "//", and end with the end of a line, for example:

// this is a program that prints hi
(print "hi") // this prints hi

Development

To identify the current interpreter version, use the -v flag.

./crumb -v

When debugging the interpreter, it may be useful to compile with the -g flag.

gcc src/*.c -g -Wall -lm -o crumb

This will allow Valgrind to provide extra information,

valgrind --leak-check=full -s ./crumb -d YOURCODE.crumb

To obtain debug information about how your code is interpreted (Tokens, AST, etc.), add the -d flag.

./crumb -d YOURCODE.crumb

Credit