All Projects → adam-mcdaniel → Wisp

adam-mcdaniel / Wisp

Licence: apache-2.0
A light lisp written in C++

Programming Languages

cpp
1120 projects
language
365 projects
lisp
113 projects

Projects that are alternatives of or similar to Wisp

Brain
An esoteric programming language compiler on top of LLVM based on Brainfuck
Stars: ✭ 112 (-20.57%)
Mutual labels:  interpreter
Lpp 3ds
Lua Player Plus for 3DS
Stars: ✭ 125 (-11.35%)
Mutual labels:  interpreter
Gomacro
Interactive Go interpreter and debugger with REPL, Eval, generics and Lisp-like macros
Stars: ✭ 1,784 (+1165.25%)
Mutual labels:  interpreter
Cpi
Tiny c++ interpreter
Stars: ✭ 116 (-17.73%)
Mutual labels:  interpreter
Lice
A multi-paradigm programming language running on JVM
Stars: ✭ 120 (-14.89%)
Mutual labels:  interpreter
Kinx
Looks like JavaScript, feels like Ruby, and it is a script language fitting in C programmers.
Stars: ✭ 134 (-4.96%)
Mutual labels:  interpreter
Quickjs
The official repo is at bellard/quickjs.
Stars: ✭ 1,429 (+913.48%)
Mutual labels:  interpreter
Sosml
The Online Interpreter for Standard ML, written in TypeScript.
Stars: ✭ 138 (-2.13%)
Mutual labels:  interpreter
Cperl
A perl5 with classes, types, compilable, company friendly, security
Stars: ✭ 125 (-11.35%)
Mutual labels:  interpreter
Brew.js
[WIP] C++ high-level JavaScript API for Nintendo 3DS/Switch
Stars: ✭ 136 (-3.55%)
Mutual labels:  interpreter
Atto
An insanely simple self-hosted functional programming language
Stars: ✭ 119 (-15.6%)
Mutual labels:  interpreter
Simple
The Simple Intelligent and Modular Programming Language and Environment
Stars: ✭ 120 (-14.89%)
Mutual labels:  interpreter
Szl
A lightweight, embeddable scripting language
Stars: ✭ 134 (-4.96%)
Mutual labels:  interpreter
Pointless
Pointless: a scripting language for learning and fun
Stars: ✭ 116 (-17.73%)
Mutual labels:  interpreter
Jssms
JavaScript Sega Master System & Game Gear dynamic recompiling emulator.
Stars: ✭ 136 (-3.55%)
Mutual labels:  interpreter
Apple Juice Actionscript
Pure .NET 2.0 code Implementation of the ActionScript3 compiler and runtime. Can be used to run scripts in environments where "just-in-time compilation" is not possible
Stars: ✭ 112 (-20.57%)
Mutual labels:  interpreter
Ethereal
Ethereal Language Reference Implementation (archived). Currently working on Feral
Stars: ✭ 129 (-8.51%)
Mutual labels:  interpreter
Emacs Cl
Common Lisp implemented in Emacs Lisp.
Stars: ✭ 140 (-0.71%)
Mutual labels:  interpreter
Kivm
🌟This is a pure C++ implementation of Java Virtual Machine (only Java 8 is supported). Inspired by Hotspot In Action.
Stars: ✭ 137 (-2.84%)
Mutual labels:  interpreter
Designpatterns
🔑Elements of Reusable Object-Oriented Software🔓is a software engineering book describing software design patterns. The book's authors are Erich Gamma, Richard Helm, Ralph Johnson and John Vlissides with a foreword by Grady Booch.
Stars: ✭ 134 (-4.96%)
Mutual labels:  interpreter

wisp

A light lisp written in C++ Wisp

Why write a lisp?

Lisp is one of those niche, beautiful languages that people only really use to either

  1. Write a lisp interpreter
  2. Show off how "code is data!!!"

So why add to the list of infinite lisp interpreters?

The answer is simple: I'm bored out of my mind in quarantine. If you were looking to find out why this particular lisp is special, you're fresh out of luck.

But isn't the fact that it's a lisp enough?

Lisp

yes.

Syntax and Special Forms

Like every other lisp, this language uses s-expressions for code syntax and data syntax. So, for example, the s-expression (print 5) is both a valid code snippet, and a valid list containing the items print and 5.

When the data (print 5) is evaluated by the interpreter, it evaluates print and 5, and then applies print to 5.

Here's the result.

>>> (print 5)
5
 => 5

That's super cool! But what if we want to define our own functions? We can use the builtin function defun!

; define a function `fact` that takes an argument `n`
(defun fact (n)
  (if (<= n 1)
     1
     (* n (fact (- n 1)))
   ))

Thats awesome! But did you notice anything different about the defun function? It doesn't evaluate its arguments. If the atom fact were evaluated, it would throw an error like so:

>>> fact
error: the expression `fact` failed in scope { } with message "atom not defined"

This is known as a special form, where certain functions "quote" their arguments. We can quote things ourselves too, but the language automatically quotes arguments to special forms itself.

If you want to "quote" a value yourself, you can do it like this.

; quote the s-expression (1 2 3) so it's not evaluated
>>> (print '(1 2 3))
(1 2 3)
 => (1 2 3)

As you can see, quote negates an evaluation. For example, whenever the expression ''a is evaluated, it becomes 'a. This can be useful for when you want to write long lists of data or variable names without wanting to evaluate them as code.

Special Form Argument Evaluations Purpose
(if cond a b) if only evaluates its cond argument. If cond is truthy (non-zero), then a is evaluated. Otherwise, b is evaluated. This special form is the main method of control flow.
(do a b c ...) do takes a list of s-expressions and evaluates them in the order they were given (in the current scope), and then returns the result of the last s-expression. This special form allows lambda functions to have multi-step bodies.
(scope a b c ...) scope takes a list of s-expressions and evaluates them in the order they were given in a new scope, and then returns the result of the last s-expression. This special form allows the user to evaluate blocks of code in new scopes.
(defun name params body) defun evaluates none of its arguments. This special form allows the user to conveniently define functions.
(define name value) define evaluates the value argument, which is then assigned to name in the current scope. This special form allows the user to bind atoms to values in a scope.
(lambda params body) lambda evaluates none of its arguments. This special form allows the user to define anonymous functions.
(quote x) quote evaluates none of its arguments. This is equivalent to the 'expr syntactic sugar.
(for x list ...) for evaluates only its list argument. for iterates through the list storing each element in x, and then evaluating all of the rest of the values in the for body. It then returns the last value evaluated.
(while cond ...) while evaluates only its cond argument. while evaluates its condition expression every iteration before running. If it is true, it continues to evaluate every expression in the while body. It then returns the last value evaluated.

Examples

Here are some example math-y functions to wrap your head around.

; quicksort
(defun qs (l)
    (if (<= (len l) 1)
        l
        (do
            (define pivot (first l))
            (+
                (qs (filter (lambda (n) (> pivot n)) l))
                (list pivot)
                (qs (tail (filter (lambda (n) (<= pivot n)) l)))
            ))
    ))

; decrement a number
(defun dec (n) (- n 1))
; increment a number
(defun inc (n) (+ n 1))
; not a bool
(defun not (x) (if x 0 1))

; negate a number
(defun neg (n) (- 0 n))

; is a number positive?
(defun is-pos? (n) (> n 0))
; is a number negative?
(defun is-neg? (n) (< n 0))

Usage

Using and compiling wisp

Dependencies

Compile with your C++ compiler of choice. This is compatible with all standard versions of C++ since ANSI C++.

$ git clone https://github.com/adam-mcdaniel/wisp
$ cd wisp
$ g++ wisp.cpp -o wisp

Using the binary

Run wisp in interactive mode:

$ ./wisp
>>> (print "Hello world!")
Hello world!
 => "Hello world!"

Interpret a file:

$ ./wisp -f "examples/hello_world.lisp"
Hello world!

Interpret from command line argument:

$ ./wisp -c '(print "Hello world!")'
Hello world!
Note that the project description data, including the texts, logos, images, and/or trademarks, for each open source project belongs to its rightful owner. If you wish to add or remove any projects, please contact us at [email protected].