Skip to content

muqiuhan/MLisp

Repository files navigation

PornLisp

A Lisp dialect implementation in OCaml5

Introduction

This project is the MLisp interpreter.

  • This project is developed entirely in OCaml 5.0 (Current is OCaml5.0.0~alpha1)

Demo

  • REPL
MLisp v0.1.2 (main, Aug 2 2022, 9:52:17) [OCaml 5.0.0~alpha1]

> (env)
- : pair = ((mergesort . #<closure>) (merge . #<closure>) (drop . #<closure>) (take . #<closure>) (length . #<closure>) (null? . #<closure>) (getline . #<closure>) (println . #<closure>) (space .  ) (newline . 
) (cons . #<primitive:pair>) (caddar . #<closure>) (cadar . #<closure>) (caddr . #<closure>) (cadr . #<closure>) (caar . #<closure>) (o . #<closure>) (eval. . #<closure>) (lookup. . #<closure>) (caddar . #<closure>) (cadar . #<closure>) (caddr . #<closure>) (cadr . #<closure>) (caar . #<closure>) (o . #<closure>) (zip. . #<closure>) (list. . #<closure>) (append. . #<closure>) (cons . #<primitive:pair>) (not. . #<closure>) (and. . #<closure>) (null. . #<closure>) (cat . #<primitive:cat>) (int->char . #<primitive:int->char>) (print . #<primitive:print>) (getchar . #<primitive:getchar>) (sym? . #<primitive:sym?>) (atom? . #<primitive:atom?>) (eq . #<primitive:eq>) (cdr . #<primitive:cdr>) (car . #<primitive:car>) (pair . #<primitive:pair>) (list . #<primitive:list>) (<= . #<primitive:<=>) (>= . #<primitive:>=>) (> . #<primitive:>>) (< . #<primitive:<>) (= . #<primitive:=>) (mod . #<primitive:mod>) (/ . #<primitive:/>) (* . #<primitive:*>) (- . #<primitive:->) (+ . #<primitive:+>) (empty-symbol . ))

> (+ 3 5)
- : int = 8

> (and #t #f)
- : boolean = #f

> (and #f #f)
- : boolean = #f

> (or #f #t)
- : boolean = #t

> (or #f #f)
- : boolean = #f

> (if (and #t #f) 3 4)
- : int = 4

> (if (or #t #f) 3 4)
- : int = 3

> (setq x 3)
- : int = 3

> (env)
- : pair = ((x . 3) (mergesort . #<closure>) (merge . #<closure>) (drop . #<closure>) (take . #<closure>) (length . #<closure>) (null? . #<closure>) (getline . #<closure>) (println . #<closure>) (space .  ) (newline . 
) (cons . #<primitive:pair>) (caddar . #<closure>) (cadar . #<closure>) (caddr . #<closure>) (cadr . #<closure>) (caar . #<closure>) (o . #<closure>) (eval. . #<closure>) (lookup. . #<closure>) (caddar . #<closure>) (cadar . #<closure>) (caddr . #<closure>) (cadr . #<closure>) (caar . #<closure>) (o . #<closure>) (zip. . #<closure>) (list. . #<closure>) (append. . #<closure>) (cons . #<primitive:pair>) (not. . #<closure>) (and. . #<closure>) (null. . #<closure>) (cat . #<primitive:cat>) (int->char . #<primitive:int->char>) (print . #<primitive:print>) (getchar . #<primitive:getchar>) (sym? . #<primitive:sym?>) (atom? . #<primitive:atom?>) (eq . #<primitive:eq>) (cdr . #<primitive:cdr>) (car . #<primitive:car>) (pair . #<primitive:pair>) (list . #<primitive:list>) (<= . #<primitive:<=>) (>= . #<primitive:>=>) (> . #<primitive:>>) (< . #<primitive:<>) (= . #<primitive:=>) (mod . #<primitive:mod>) (/ . #<primitive:/>) (* . #<primitive:*>) (- . #<primitive:->) (+ . #<primitive:+>) (empty-symbol . ))

> (+ x 7)
- : int = 10

> (apply pair (list 3 4))
- : pair = (3 . 4)

> (pair 5 6)
- : pair = (5 . 6)

> (setq x (lambda (y) (+ y 1)))
- : closure = #<closure>

> (x 10)
- : int = 11

> (defun x (y) (+ y 1))
- : closure = #<closure>

> (x 10)
- : int = 11

> (defun f (x)
    (if (< x 2)
      1
      (g (- x 1))))
- : closure = #<closure>

> (defun g (x)
    (if (< x 2)
      3
      (f (- x 2))))
- : closure = #<closure>

> (f 10)
- : int = 1

> (g 10)
- : int = 3

> (f (g 10))
- : int = 1

> (let ((x 10)
        (y 20))
    (+ x y))
- : int = 30

> (let* ((x 10)
         (y x))
    (+ x y))
- : int = 20

> (letrec ((f (lambda (x) (g (+ x 1))))
           (g (lambda (x) (+ x 3))))
    (f 0))
- : int = 4

> y

+----------------------------------------------------------------------------
| From : "stdin" , Line: 39 , Column: 0
| | Error: Not found : y
| | Help : Accessing an identifier that has not been defined in the context.
+----------------------------------------------------------------------------
> ())
- : nil = nil

> 
+---------------------------------------------------------------------------------
| From : "stdin" , Line: 39 , Column: 3
| | Error: Syntax error -> Unexcepted character : ')'
| | Help : Usually triggered by wrong characters, such as extra parentheses, etc.
+---------------------------------------------------------------------------------
> 
  • File MLisp supports loading programs from files since version 0.1.2, just pass the MLisp source file as the first argument to mlisp, For example:

File: 05_mutually_recursive_functions.mlisp

 1 │ (defun f (x)
 2 │   (if (< x 2)
 31
 4 │       (g (- x 1))))
 56 │ (defun g (x)
 7 │   (if (< x 2)
 83
 9 │       (f (- x 2))))
1011 │ (println (f 10))
$ mlisp 05_mutually_recursive_functions.mlisp 
1

Compared to REPL, the error message of the file will be more colorful, For example:

File: end_test_errors.mlisp:

 1 │ (println "Please don't be nervous, we are just testing the display of error messages")
 23 │ (defun f (x)
 4 │   (if (< x 2)
 51
 6 │       (g (- x 1))))
 78 │ (defun g (x)
 9 │   (if (< x 2)
103
11 │       (f (- x 2))))
1213 │ (f g)
$ mlisp end_test_errors.mlisp 
"Please don\'t be nervous, we are just testing the display of error messages"

+---------------------------------------------------------------------------------------------------------------------------------------
| From : "end_test_errors.mlisp" , Line: 31 , Column: 5
|------> (f g)
| +----------^
| | Error: Parse error -> Type error : (< int int)
| | Help : Possible type error due to a function call with parameters of a type different from that specified in the function definition.
+---------------------------------------------------------------------------------------------------------------------------------------

Build

From source

Since this project is developed using OCaml5, you need to install the OCaml5 environment. The current latest OCaml5 Release version is OCaml5.0.0~alpha1.You can install this version via opam update && opam switch create 5.0.0~alpha1 --repositories=default,beta=git+https://github.com/ocaml/ocaml-beta-repository.git to install this version of OCaml environment.

  1. Build and install with ocaml pom.ml install
  2. Run all tests via ocaml pom.ml test
  3. Execute via mlisp

NOTE: Uninstall via ocaml pom.ml uninstall

License

Copyright (C) 2022 Muqiu Han

This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.

This program 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 Affero General Public License for more details.

You should have received a copy of the GNU Affero General Public License along with this program. If not, see https://www.gnu.org/licenses/.

About

A Lisp dialect implementation in OCaml

Resources

License

Stars

Watchers

Forks

Packages

No packages published