GithubHelp home page GithubHelp logo

lsp's Introduction

What is this?

This is an interpreter for a minimalistic LISP inspired programming language, written as a learning exercise.

How to use

This projects uses the Make build system.

Building and running lsp

Building the interpreter

# in lsp/
make

Running programs

./lsp # starts the REPL
./lsp lsps/fibonacci.lsp # runs the fibonacci example descripbed below
./lsp lsps/sort.lsp # runs the sorting example descripbed below

./lsp -l lsps/sort.lsp # loads lsps/sort.lsp and starts the REPL

Building and running the tests

Building the test programs

Lsp uses the Mocka library for unittesting, and it has to be installed to build the test programs.

# in lsp/tests//
make

Running the tests

# in lsp/tests//
# run tests
make runall

Examples

Fibonacci

;; Prints the largest fibonacci number storable in the lsp int
(defun fibo-max ()
 (progn
  (defun fibo-max-rec (x y c)
   (if (gt y 0)
    (progn
     ; (println x y c)
     (fibo-max-rec y (+ x y) (+ c 1)))
    (list x (- c 1))))
  (fibo-max-rec 0 1 0)))

;; print the highest fibonacci number one can store in
;; a 64-bit signed integer
(println (car (fibo-max))) ; 7540113804746346429 (the 92nd fibonacci number)

List exclusion

;; Returns lst without excl
(defun list-excl (lst acc excl)
  (if (> (len lst) 0)
      (let ((front (car lst)) (rest (cdr lst)) (accl acc))
        (if (! (= front excl))
            (setq accl (append front acc)))
        (return (list-excl rest accl excl)))
        (return acc)))

(list-excl (1 2 3 4 5) '() 3) ; (1 2 4 5)

Sorting

(defun list-excl-helper (lst acc excl)
  (if (> (len lst) 0)
      (let ((front (car lst)) (rest (cdr lst)) (accl acc))
        (if (! (= front excl))
            (setq accl (append front acc)))
        (return (list-excl-helper rest accl excl)))
        (return acc)))

(defun list-excl (lst excl)
  (return (list-excl-helper lst '() excl)))

(defun list-min-helper (lst acc-min)
  (if (> (len lst) 0)
      (if (< (car lst) acc-min)
          (return (list-min-helper (cdr lst) (car lst)))
        (return (list-min-helper (cdr lst) acc-min)))
    (return acc-min)))

(defun list-min (lst)
  (list-min-helper lst 9223372036854775807))

(defun list-sort-helper (lst acc)
  (if (> (len lst) 0)
        (return (list-sort-helper (list-excl lst (list-min lst)) (append (list-min lst) (acc))))
    (return acc)))

(defun list-sort (lst)
  (return (list-sort-helper lst '())))

(println (list-sort (92839 7589 263695 123 5 71)))    ; (5 71 123 7589 92839 263695)
(println (list-sort (27371 958709721 -12312 751565))) ; (-12312 27371 751565 958709721)

Arithmetic

;; Primitives
(+ 1 2 3 4 5) ; expected = 15
(* 10 10)     ; expected = 100
(* 10 10 10)  ; expected = 1000
(- 10 10 3)   ; expected = -3

;; Composite
(+ 10 (* 3 (- 10 4))) ; expected = 28

Comparison operators (gt, lt, eql, not)

; Operations
(gt x y)  ; x > y
(lt x y)  ; x < y
(eql x y) ; x == y
(not x)   ; C-style logical not; true if x is 0, false if x is non-zero

; Usage
(println *x* "==" *y* "=>" (if (eql *x* *y*) "true" "false"))      ; prints "true" if *x* == *y*
(println *x* ">" *y* "=>" (if (gt *x* *y*) "true" "false"))        ; prints "true" if *x* > *y*
(println *x* "<" *y* "=>" (if (lt *x* *y*) "true" "false"))        ; prints "true" if *x* < *y
(println *x* "<=" *y* "=>" (if (not (gt *x* *y*)) "true" "false")) ; prints "true" if *x* <= *y
(println *x* ">=" *y* "=>" (if (not (lt *x* *y*)) "true" "false")) ; prints "true" if *x* >= *y

Variables

Creating globals (defvar)

(defvar *x* 1) ; *x* is now a global variable with the value 1
(defvar *lst* (1 2 3)) ; *lst* is now a global variable containing the list (1 2 3)

Creating locals (let)

; Create a local x and assign it the value 2
(let ((x 2))
    ; x is only visible inside this scope
    (println "local x" x)) ; outputs: local x 2

; Create two local variables; x and y
(let ((x 2) (y 3))
    (println "local x" x "local y" y)) ; outputs: local x 2 local y 3

; Shadowing - the "closest" variable in the scope is used
(let ((x 1) (y 1))
 (println "#1" x y)    ; #1 1 1
 (let ((x 2) (y 2))
  (println "#2" x y)   ; #2 2 2
  (let ((x 3) (y 3))
   (println "#3" x y)) ; #3 3 3
  (println "#2" x y))  ; #2 2 2
 (println "#1" x y))   ; #1 1 1

;; Outputs
; #1 1 1
; #2 2 2
; #3 3 3
; #2 2 2
; #1 1 1

Setting variables (setq)

(defvar *x* 1) ; *x* is now a global variable with the value 1
(print *x*)    ; outputs: 1
(setq *x* 14) ;; updating the *x* global
(print *x*)    ; outputs: 14

Builtins

quote and eval

; (quote <expr>) returns <expr> without changing it
; '(<expr>)  is the shorthand for (quote <expr>)
(quote (+ 1 2 3)) ; (+ 1 2 3)
'(+ 1 2 3)        ; (+ 1 2 3)

; Normal (without quote)
(+ 1 2 3)         ; 6

; (eval <expr>) evaluates the <expr> and returns the result
(eval (quote (+ 1 2 3))) ; 6
(eval '(+ 1 2 3)) ; 6

reverse

(reverse (1 2 3)) ; --> (3 2 1)

car, cfr, len

; (len lst) returns the length of the list lst
(len (1 2 3)) ; 3
(len (1 2 3 (1 2 3))) ; 4

; (car lst) returns the first element of the list lst
(car (1 2 3)) ; 1

; (cdr lst) returns the list lst with the first element removed
(cdr (1 2 3)) ; (2 3)

load-file

; (load-file <filename>) loads the lsp file <filename> making its contents available
(if (! (load-file "tests/lsps/unittest.lsp"))
 (progn
  (println "ERROR: Unable to load unittest library! ===")
  (println "=== Are you sure this is ran from the tests directory? ===")
  (exit 1)))

(assert-equal 1 1)
(assert-true 78597397123)
(assert-true -1264629723)
(assert-false (> 2 3))
; ... assertions ...

(println "=== Finished comparison tests! ===")
(println *unittest-successes* "successes")
(println *unittest-failures* "failures")

Contents of tests/lsps/unittest.lsp

(defvar *unittest-successes* 0)
(defvar *unittest-failures* 0)

(defun assert-true (condition)
  (if (assert condition)
        (setq *unittest-successes* (+ *unittest-successes* 1))
      (setq *unittest-failures* (+ *unittest-failures* 1))))

(defun assert-false (condition)
  (assert-true (! condition)))

(defun assert-equal (cnd1 cnd2)
  (assert-true (= cnd1 cnd2)))

(defun assert-not-equal (cnd1 cnd2)
  (assert-true (! (= cnd1 cnd2))))

(defun assert-< (cnd1 cnd2)
  (assert-true (< cnd1 cnd2)))

(defun assert-> (cnd1 cnd2)
  (assert-true (> cnd1 cnd2)))

(defun assert-<= (cnd1 cnd2)
  (assert-true (<= cnd1 cnd2)))

(defun assert->= (cnd1 cnd2)
  (assert-true (>= cnd1 cnd2)))

(defun unittest (name tests)
  (progn
    (println "== Running unittest" name "===")
    ; (let ((unittest-successes 0) (unittest-failures 0))
      (eval tests)
      (println "=== Completed unittest" name "===")
      (println *unittest-successes* "successes")
      (println *unittest-failures* "failures")
     ; )
  ))

;; example unittest
;; (unittest "test-something"
;;        '(unittest/assert-true 1))

***

lsp's People

Watchers

 avatar

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.