LIPS Scheme Documentation
website·Indexed 30 days ago
https://lips.js.orgA Scheme interpreter implemented in JavaScript. The documentation covers core language features including S-expressions, Lisp macros, continuations, and streams, as well as LIPS-specific features like SXML, environment chains, and integration with the browser and GNU Emacs. It includes a comprehensive function and macro reference, SRFI support, and details on version 1.0.0-beta releases.
What's inside LIPS Scheme
- LIPS (LIPS Is Pretty Simple) is a powerful Lisp interpreter written in JavaScript designed to be a fully R7RS-compliant Scheme programming language. It achieves nearly 100% compatibility with Chibi R7RS tests and features a small JavaScript core with a Standard Library implemented in basic Scheme.
Overview of LIPS Scheme interpreter
LIPS (recursive acronym for "LIPS Is Pretty Simple") is an implementation of the Scheme programming language written in JavaScript. It extends standard Scheme with additional features to enhance its power and facilitate interaction with JavaScript environments.Understand the LIPS Scheme Finite State Machine Lexer
The LIPS Scheme Lexer uses a Finite State Machine (FSM) to tokenize input. It iterates over every character and evaluates a set of rules to determine state transitions. A token is completed when a rule sequence results in a state that finishes withnull. If no rules match while in a non-null state, characters are collected into the current token. This approach allows for dynamic syntax extensions and is used for both reading LIPS Scheme code and I/O ports.Use the LIPS Scheme Node.js REPL
The Node.js REPL allows interaction with LIPS Scheme from the command line. It supports syntax highlighting, auto-indentation, and parentheses matching (as of v1.0.0-beta.20). To handle copy-pasting of Scheme code correctly, it supports the Node.js 'paste bracket mode' (available in Node.js v20.6.0+ and v18.19.0+).Implement custom syntax extensions in LIPS Scheme
LIPS Scheme supports syntax extensions that allow developers to define new syntax by mapping a specific sequence of characters to a parser function. When the parser encounters the defined character sequence, it executes the associated function (similar to a reader macro in Common Lisp) and replaces the sequence with the function's return value.Use the LIPS Scheme Web REPL
The Web REPL provides an interactive session for LIPS Scheme accessible via the home page or as a bookmarklet. It is built using jQuery Terminal and includes the following developer features:
- Syntax highlighting via Prism.js
- Parentheses matching (visual jump to matching bracket on close parenthesis)
- Auto-indentation for manual entry and pasted code
- Docstring tooltips when hovering over symbols
Inspect LIPS objects using JavaScript reflection
LIPS objects can be inspected using standard JavaScript methods and specific LIPS procedures to reveal their internal properties and prototypes.// LIPS Procedures for inspection (dir object) // Returns all accessible properties, including those from the prototype chain (env) // Returns everything inside the current environment // Standard JavaScript methods Object.keys(obj) // Returns all string keys Object.values(obj) // Returns the values of the object Object.entries(obj) // Returns [key, value] pairs Object.getOwnPropertySymbols(obj) // Returns all symbol propertiesEvaluate code in a specific environment with let-env
Thelet-envmacro evaluates the provided body within the context of a given environment object.let-env-valuesadds specific variable mappings from an environment while maintaining lexical scope.(let-env env body) (let-env-values env ((name var)) body)Define custom string representations in LIPS Scheme
Users can define how objects are represented as strings by providing an object with atoStringlambda. Additionally, theadd-repr!function can be used to add string representations to objects.Implement higher-order functions in Scheme
Functions in Scheme are first-class citizens and can be passed as arguments to other functions or returned as values. Built-in higher-order functions includemap(returns a new list) andfor-each(returns an unspecified value).;; Using built-in map (map square '(1 2 3 4)) ;; ==> (1 4 9 16) (map (lambda (x) (* x 10)) '(1 2 3 4)) ;; ==> (10 20 30 40) ;; Defining a custom filter function (define (filter fn lst) (if (null? lst) '() (let ((item (car lst))) (if (fn item) (cons item (filter fn (cdr lst))) (filter fn (cdr lst)))))) (filter odd? '(1 2 3 4 5)) ;; ==> (1 3 5)Implement custom parser logic using standard input
In LIPS syntax extensions,current-input-portpoints to the parser stream. This allows you to implement custom parser logic similar to Common Lisp reader macros by using functions likepeek-charandread-charto consume the input stream manually.(define (raw-string) (if (char=? (peek-char) #") (begin (read-char) (let loop ((result (vector)) (char (peek-char))) (read-char) (if (char=? char #") (apply string (vector->list result)) (loop (vector-append result (vector char)) (peek-char))))))) (set-special! "$" raw-string lips.specials.SYMBOL) (print $:"foo \ bar") ;; ==> "foo \\ bar"Recommended learning resources for Scheme hygienic macros
Because dedicated books on Scheme hygienic macros are scarce, the following documents and guides are recommended for learning
syntax-rulesand hygienic macro systems:- Writing Powerful Macros in Scheme by Marc Nieper-Wißkirchen.
- JRM’s Syntax-rules Primer for the Merely Eccentric.
- An Advanced Syntax-Rules Primer for the Mildly Insane by Al Petrofsky.
- Oleg Kiselyov's advanced usage of Scheme macros (available on okmij.org).
- Community-curated links on Reddit regarding Scheme macros.