aboutsummaryrefslogtreecommitdiffstats
path: root/examples/lisp/prelude.scm
diff options
context:
space:
mode:
authorGravatar Peter McGoron 2024-07-10 10:47:55 -0400
committerGravatar Peter McGoron 2024-07-10 10:47:55 -0400
commitb41e2100c214cc983889017009506a9d339b0341 (patch)
tree7463758c0178984a71159b5a67785c467859ff36 /examples/lisp/prelude.scm
parentfix clean (diff)
import flatrate lisp, rename to Universal Service LISP
Diffstat (limited to 'examples/lisp/prelude.scm')
-rw-r--r--examples/lisp/prelude.scm264
1 files changed, 264 insertions, 0 deletions
diff --git a/examples/lisp/prelude.scm b/examples/lisp/prelude.scm
new file mode 100644
index 0000000..b181e34
--- /dev/null
+++ b/examples/lisp/prelude.scm
@@ -0,0 +1,264 @@
+; Copyright (c) 2024, Peter McGoron
+;
+; Redistribution and use in source and binary forms, with or without
+; modification, are permitted provided that the following conditions
+; are met:
+;
+; 1) Redistributions of source code must retain the above copyright
+; notice, this list of conditions and the following disclaimer.
+; 2) Redistributions in binary form must reproduce the above copyright
+; notice, this list of conditions and the following disclaimer in the
+; documentation and/or other materials provided with the distribution.
+;
+; THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+; "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+; LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+; A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+; OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+; SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+; TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+; PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+; LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+; NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+; SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+; Primitives are special syntatic forms. They differ from built-in
+; functions.
+;
+; primitives:
+; __lambda: lambda of one argument
+; __define: define in the environment
+; __define-macro: Like __define but for macros
+; set!
+; if
+;
+; Others:
+; __uniapply: Apply function to single argument
+; <undefined>: A value that can only be passed to __lambda. It cannot
+; be bound to a top-level, or "set!", or added to a list.
+; It can also be the parameter of a __lambda, although
+; it still cannot be used.
+;
+; Macros are functions that return an sexpr.
+
+(__define-macro let
+ (__lambda l ; car = args, cdr = body
+ (if (null? (car args))
+ (cdr args)
+ ; (car args) = ((A a) (B b) ...)
+ ; (car (car args)) = (A a)
+ ; (cdr (car (car args))) = (a)
+ `((__lambda ,(car (car (car args)))
+ (let ,(cdr (car args)) ,@body))
+ ,@(car (cdr (car (car args))))
+ )
+ )
+ )
+)
+
+(__define-macro let* let)
+
+; if and __lambda only execute one statement.
+(__define-macro begin body
+ (let ((first (car body))
+ (rest (cdr body))
+ )
+ (if (null? rest)
+ first
+ `((__lambda <undefined> (begin ,@rest)) ,first)
+ )
+ )
+)
+
+;;; (cond (case1 expr1) (case2 expr2) ... (else exprelse))
+(__define-macro cond body
+ (let ((cases (car body)))
+ (if (null? body)
+ <undefined>
+ (let* ((branch (car cases))
+ (rest (cdr cases))
+ (test (car branch))
+ (to-exec (cdr branch))
+ )
+ (if (null? to-exec)
+ (let ((tmp (gensym)))
+ `(let ((,tmp ,test))
+ (if ,tmp ,tmp (cond ,@rest))
+ )
+ )
+ (if (eqv? test 'else)
+ (if (null? rest)
+ `(begin ,@rest)
+ (error "invalid else clause")
+ )
+ (if (eqv? (car to-exec) '=>)
+ (let ((tmp (gensym))
+ (fun (cdr to-exec))
+ )
+ `(let ((,tmp ,test))
+ (if ,tmp (,fun ,tmp) (cond ,@rest))
+ )
+ )
+ `(if ,tmp (begin ,@rest) (cond ,@rest))
+ )
+ )
+ )
+ )
+ )
+ )
+)
+
+(__define-macro __bindlambda
+ (__lambda l
+ (let ((larg (car l))
+ (args (car (cdr l)))
+ (body (cdr (cdr l)))
+ )
+ (if (null? args)
+ `(__lambda larg
+ (if (not (null? larg))
+ (raise "incorrect number of arguments")
+ (begin ,@body)
+ )
+ )
+ (let* ((argval (cons args))
+ (rest (cdr args))
+ (arg (cons argval))
+ (val (cons (cdr argval)))
+ )
+ `(__lambda ,larg
+ (let ((,arg ,val)) __bindlambda ,larg ,rest ,@body)
+ )
+ )
+ )
+ )
+ )
+)
+
+(__define-macro lambda
+ (__lambda l
+ (let ((args (car l))
+ (body (cdr l))
+ )
+ (if (symbol? args)
+ `(__lambda ,args (begin ,@body))
+ (if (null? args)
+ `(__lambda <undefined> (begin ,@body))
+ (let ((larg (gensym)))
+ `(__bindlambda ,larg ,@body)
+ )
+ )
+ )
+ )
+ )
+)
+
+(__define-macro define-macro
+ (__lambda l
+ (let* ((name-and-args (car l))
+ (name (car name-and-args))
+ (args (cdr name-and-args))
+ (body (cdr l))
+ (tmpname (gensym))
+ )
+ `(__define-macro ,name
+ (lambda ,args ,@body)
+ )
+ )
+ )
+)
+
+(define-macro (and . body)
+ (if (null? body)
+ 1
+ (let ((first (car body))
+ (rest (cdr body))
+ )
+ `(if ,first (and ,@rest) 0)
+ )
+ )
+)
+
+(define-macro (or . body)
+ (if (null? body)
+ 0
+ (let ((first (car body))
+ (rest (cdr body))
+ )
+ `(if ,first 1 (or ,@rest))
+ )
+ )
+)
+
+(define-macro (letrec args . body)
+ (if (null? args)
+ body
+ (let* ((argval (car args))
+ (arg (car argval))
+ (val (car (cdr argval)))
+ (rest (cdr args))
+ )
+ `(let ((,arg <undefined>))
+ (letrec ,rest (begin (set! ,arg ,val) ,@body))
+ )
+ )
+ )
+)
+
+(define-macro (define name . body)
+ (if (symbol? name)
+ `(__define ,name ,@body)
+ (let ((fname (car name))
+ (args (cdr name))
+ (tmparg (gensym))
+ )
+ `(__define ,fname
+ (lambda ,tmparg
+ (letrec ((,fname (lambda ,args ,@body)))
+ (,fname . ,tmparg)
+ )
+ )
+ )
+ )
+ )
+)
+
+;;;;;;;;;;;;;; Standard Library ;;;;;;;;;;;;;;;;;;;
+
+;; for a list of (v1 v2 ... vn)
+;; runs (f vn (... (f v2 (f v1 start))))
+(define (foldl f start l)
+ (letrec
+ ((loop
+ (lambda (ret-list cur-list)
+ (if (eqv? value '())
+ value
+ (loop (f (car cur-list) value)
+ (cdr cur-list))
+ )
+ )
+ ))
+ (loop start l)
+ )
+)
+
+(define (reverse l) (foldl cons '() l))
+
+;; for a list of (v1 v2 ... vn)
+;; runs (f v1 (f v2 (... (f vn start))))
+(define (foldr f start l) (foldl f start (reverse l)))
+
+(define (append . l)
+ (foldr (lambda (to-prepend collected)
+ (foldr cons collected to-prepend)
+ )
+ '()
+ l
+ )
+)
+
+(define (apply f . l) (__uniapply f (__uniapply append l)))
+(define (list . l) l)
+
+;; (define (+ . l) (foldl __bin+ 0 l))
+;; (define (* . l) (foldl __bin* 1 l))