This document serves as a small specification for Minimalisp. It explains all features of the language and highlights its grammer. Minimalisp is not really an actual Lisp since it lacks common Lisp features such as macros. It only uses Lisp syntax. Whether that justifies having Lisp in its name is a different question.
Minimalisp tries to keep keywords and special syntax to a minimum. It is furthermore a dynamically typed language.
Similar to many other Lisps, Minimalisp uses semicolons for comments.
; This is a comment
Naturally, Minimalisp uses prefix notation and S-expressions. In Minimalisp everything is an expression.
(+ 1 (- 2 1) (/ 4 2))
Functions can be directly assigned to an identifier.
(defun say-hello (name) (println name))
It is also possible to create an anonymous function.
(lambda (name) (println name))
Minimalisp allows the definition of global and local variables.
; Global variable
(defvar num 1)
; let defines local variables
(let (result (+ num 1))
(println result))
Minimalisp automatically returns the last expression of a function.
(defun add-and-sub-one (n)
(let (result (+ n 1))
(- result 1))
(add-and-sub-one 5) ; returns 5
Minimalisp knows strings, numbers, booleans, functions, and lists.
; numbers
(defvar num 1)
(defvar floating-num 1.2)
; strings
(defvar name "Charles")
; booleans
(defvar t true)
(defvar f false)
; functions (both are actually the same)
(defvar f (lambda (x) (+ x 1)))
(defun f (x) (+ x 1))
; lists
(defvar l '(1 2 3 4 5))
Furthermore, Minimalisp uses nil.
; nothing
(defvar unknown nil)
In Minimalisp everything except false and nil is truthy.
; Prints 'Yes!'
(if "the truth"
(println "Yes!")
(println "No!"))
The root element of Minimalisp is a program that is composed out of zero or more declarations.
program → declaration* EOF
Each declaration is either a variable definition, a function definition, or an expression.
declaration → varDef | funcDef | expression
Let’s take the easy one first: a variable definition has the following structure.
varDef → "(" "defvar" IDENTIFIER expression ")"
Functions look similar to variable definitions but additionally have parameters.
funcDef → "(" "defun" IDENTIFIER "(" IDENTIFIER* ")" expression ")"
Expressions can be furthermore divided.
expression → if | let | call | primary
If expressions have the following form.
if → "(" "if" expression expression expression ")"
Let expressions are similarly straight forward.
let → "(" "let" "(" ( IDENTIFIER expression )+ ")" expression ")"
Call specifies how function calls are structured.
call → "(" IDENTIFIER expression* ")"
Primary is everything else.
primary → NUMBER | STRING | BOOLEAN | NIL | IDENTIFIER | list | lambda list → "'" "(" expression* ")" lambda → "(" "lambda" "(" IDENTIFIER* ")" expression ")"