Any sufficiently complicated C or Fortran program contains an ad-hoc, informally-specified, bug-ridden, slow implementation of half of Common Lisp.
- Philip Greenspun
Now your BlitzMax applications can have one too!
lispmax is a module for BlitzMax that can parse and execute a lispy scripting
language.
lispmax depends on a couple of sub-modules from sodaware.mod.
Once sodaware.mod is installed, navigate to the sodaware.mod folder and clone
the lispmax.mod repository.
cd /path/to/blitzmax/mod/sodaware.mod/
git clone https://github.com/sodaware/lispmax.mod.gitThe following lisp expression adds two numbers together:
(+ 10 20)To run this within BlitzMax using lispmax, we need to do the following:
- Create and initialize a LispMax object - this contains the environment (functions, variables etc)
- Parse the expression - this converts a string containing lisp code into something LispMax can use
- Evaluate the expression - this is where the magic happens
In practice, it looks a little like this:
Framework brl.basic
Import sodaware.lispmax
' Create a new LispMax instance.
Local lisp:LispMax = New LispMax
' Load built-in and library functions.
lisp.initializeEnvironment()
' Parse and evaluate the expression.
Local expression:LispMax_Atom = lisp.parseExpression("(+ 10 20)")
Local result:LispMax_Atom = lisp.evaluateExpression(expression)
' Print the result.
lisp.printExpression(result)Running the above example will print 30.
LispMax comes with the following functions built-in:
CAR- Get the first part of a pairCDR- Get the rest of a pair, excluding the CARCONS- Create a new pairNTH- Return the nth item from a list+- Add-- Subtract*- Multiply/- DivideMOD- Modulus=- Equal<- Less than>- Greater thanEQ?- Check if two atoms are equal.NIL?- Predicate to check if an atom is a nilPAIR?- Predicate to check if an atom is a pair.LISTP- Predicate to check if an atom is a list.APPLYLIST- Create a list.OR- LogicalorSTRING-UPCASE- Convert a string to uppercaseSTRING-DOWNCASE- Convert a string to lowercaseRAND- Generate a random integerMILLISECS- Get the number of elapsed milliseconds as an integerPARSE-INTEGER- Parse a string into an integerDEBUGLOG- Write text to the BlitzMax debuglogPRINT- Print a stringPRINT-EXPRESSION- Convert an expression to a string and print it
Library functions (which are defined in lispmax code, not BlitzMax code) can be
found in site-lisp/library.lisp.
Most of these functions behave the same as their Common Lisp counterparts.
LispMax supports defining functions in BlitzMax, or in lispmax itself.
The preferred way to add a native function is to create a type that extends
LispMax_Callable.
For example, to add a function that always returns the string "Hello, World":
Type MyFunction extends LispMax_Callable
Method call:LispMax_Atom(caller:LispMax, args:LispMax_Atom)
Return caller.makeString("Hello, World")
End Method
End Type
lisp.addFunction("my-function", new MyFunction)Native functions are faster than using lispmax code, but they require the application to be recompiled.
Evaluate the following code from within the LispMax environment.
(define (my-function)
"Hello, World")Alternatively, functions can be added using a more lispy syntax:
(defun my-function ()
"Always returns the string Hello World"
"Hello, World")Copyright (C) 2017-2019 Phil Newton
LISPMAX is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
LISPMAX is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License along with LISPMAX. If not, see http://www.gnu.org/licenses/.