Skip to content

Latest commit

 

History

97 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

* YALL DOCUMENTATION

** Demo Video

https://youtu.be/X38Ry1Jk7FU

** Installation

*** Dependencies 
To install YALL you will need ~cmake~ installed.

*** Install Process

To build the project and install it in you ~/.local/bin/

Run the command

#+begin_src
cmake -H. -Btmp -DCMAKE_INSTALL_PREFIX =~/.local/bin/
#+end_src

Then

#+begin_src 
cmake --build tmp --clean-first --target install
#+end_src

** YALL a simple extensible lisp dialect

This program consists of two parts 1 the demo script which feeds some
example code into a non interactive YALL process.

The other part is an the yall executable it's self.

you can run it interactively with

#+begin_src 
lisp -i
#+end_src


or

#+begin_src 
lisp --interactive
#+end_src

If you want to pass it input from an existing file run

#+begin_src 
lisp < file_to_run.scm
#+end_src

Since yall is heavily inspired by scheme it's recommended to set your
editor to its' scheme or at least lisp mode for better syntax
highlighting.



** Functions Available In YALL

*** +
adds 2 values together and returns the result as an integer
#+begin_src scheme
  (+ <symboli-expression> <symboli-expression>)
#+end_src

*** -
subtract the first argument from the second argument and returns the
result as an integer
#+begin_src scheme
  (- <symboli-expression> <symboli-expression>)
#+end_src

*** *
multiply 2 values together and returns the result as an integer
#+begin_src scheme
  (* <symboli-expression> <symboli-expression>)
#+end_src
*** =
Compares 2 integers for equivalence and returns the result as a boolean
#+begin_src scheme
  (= <symboli-expression> <symboli-expression>)
#+end_src
*** eq
Compares 2 expressions for equivalence and returns the result as a boolean
(note that all functions equivalent)
#+begin_src scheme
  (eq <symboli-expression> <symboli-expression>)
#+end_src
*** if
Takes 2 or 3 arguments. the first being a condition that results in a
boolean the second being the expression to return if this is true and
the optional third will be returned if it is false.

If no third argument is provided and the condition is evaluated to be
#f then the #f is returned.

#+begin_src scheme
  (if <condition> <then> <else>)
#+end_src
*** list
Takes a variable number of arguments of at least one and returns the
result as a list.
#+begin_src scheme
  (list <symboli-expression>+)
#+end_src
*** append
Takes 2 lists and appends them then returns the result as a list.
#+begin_src scheme
  (append <list> <list>)
#+end_src
*** cons
Takes 2 arguments and produces either a cons cell or a list.

If the second argument is a list then it will return a list with the
first argument at the front of the list

Otherwise a cons cell is returned with the first and second arguments
as it's contents.

#+begin_src scheme
  (cons <symbolic-expression> <symbolic-expression>)
#+end_src
*** car
Takes one argument of either a cons cell or a list and returns the first element.

#+begin_src scheme
  (car <cons-or-list>)
#+end_src
*** cdr
Takes one argument of either a cons cell or a list and returns
everything other than the first argument.
#+begin_src scheme
  (cdr <cons-or-list>)
#+end_src
*** sleep
Takes one argument of an integer n and halts the YALL for n seconds
the number of seconds is then returned.
#+begin_src scheme
  (sleep <int>)
#+end_src
*** print
Takes a symbolic expression and prints the string representation. It's
argument is then used as it's returned value.
#+begin_src scheme
  (print <expression>)
#+end_src
** Supported Types
*** Supported Symbols
Symbols can contain a series of letters, numbers and dashes however
the first character must always be a letter.

The exception to this is the built in symbols *, -, and +

The regular expression for this would look something like [a-Z]([a-Z]|-|[0-9])+

*** Numbers
Numbers can be any valid C++ int. There is no attempt by YALL to handle integer overflow.

*** Booleans
The only supported booleans are #t for true and #f for false

*** Containers

**** Lists
Lists in YALL can be created with the list function

(list + 2 3) => (#<YALL Function> 2 3)

Alternatively quoting an expression will also create a list without
evaluating it's contents

(quote (+ 2 3)) => (+ 2 3)

**** Cons Cells
Lists in YALL can be created with the cons function

(cons 1 2) => (1 . 2)

Alternatively quoting a dotted expression to create a cons cell without
evaluating it's contents

(quote (+ . 2)) => (+ . 2)

* Language Overview

** What is YALL?

YALL is a lisp dialect inspired by Scheme

** How does it work

YALL can be ran interactively and non interactively

to run it interactively call it with the ~-i~

We can now begin evaluating expressions

** What are expressions

Expressions are a made up of what are known as symbolic expressions.

an expression consists of to parentheses

Here is an example

#+begin_src scheme
(+ 1 2)
#+end_src


The first argument is a function call and the others are it's arguments

The when ran this evaluates to 

#+begin_src 
3
#+end_src

** Functions
YALL has a single namespace for both functions and variables so you
can store and call other functions.

functions are created with the lambda keyword followed by a list of
arguments and th body of the function
#+begin_src scheme
      (lambda (argOne argTwo) ; arguments
        (+ argOne argTwo))  ; body
#+end_src


We can store values using define

#+begin_src scheme
    (define double
      (lambda (a) (* a 2)))
#+end_src

#+RESULTS:

Then we can call the function just like any built in one

#+begin_src scheme
  (double 10)
#+end_src

#+RESULTS:
: 20

Since functions act as variables you can also pass them as arguments

This will partially apply the first argument 
#+begin_src scheme
  (define curry
       (lambda (fn arg)
         (lambda (y) (fn 1 y))))
#+end_src

#+begin_src scheme
  (curry + 1) ; a function 
#+end_src

#+begin_src scheme
  ((curry + 1) 2)
#+end_src

#+RESULTS:
: 3

** Definitions are limited
Unfortunately a current limitation of YALL is that bindings can not be
back referenced.

#+begin_src scheme
(define caller (lambda (x) (x 1)))
#+end_src

#+begin_src scheme
(define isOne (lambda (num) (= num 1)))
#+end_src

#+begin_src scheme
(caller isOne)
#+end_src

will work but

#+begin_src scheme
(define caller (lambda () (isOne 1)))
#+end_src

#+begin_src scheme
(define isOne (lambda (num) (= num 1)))
#+end_src

#+begin_src scheme
(caller)
#+end_src

Will fail

For this same reason recursion is not possible.
** let

In addition can define new lexically scoped blocks using ~let~

#+begin_src scheme
  (let ((a 1)
        (b 2))
    (+ a b))
#+end_src

#+RESULTS:
: 3

Just like anything else you can also define functions in let
declarations.

** Code as data

YALL also allows for code to be used as data. Use the quote keyword to
prevent evaluation of an expression.

#+begin_src scheme
  (quote (+ 1 2))
#+end_src

Then you can access the contents with the functions ~car~ and ~cdr~

You can think of them as the same thing as first and rest
#+begin_src scheme
  (car (quote (+ 1 2)))
#+end_src

Just due to the time constants of the course proper meta programming
(since you can not unquote an expression) is not fully supported since
there is now.

for example
#+begin_src scheme 
  ((car (quote (+ 1 2))) 1 2)  
#+end_src

will fail to function since the ~+~ will remain quoted.

However accessing numbers will function as expected

#+begin_src scheme
  (+  (car (quote (1 2))) 3)
#+end_src

For this reason I included the ~list~ function but this will allow for ~+~
to evaluate to a function

#+begin_src scheme
  ((car (list + 1 2)) 1 2)  
#+end_src


** YALL supports conditional logic

#t is for true
#f is for false

The only built in conditional logic is ~if~
#+begin_src scheme
    (if (= 1 1)
        (quote (yes they are))
        (quote (no they are not)))
#+end_src

With this most common logic can be defined
#+begin_src scheme
 (define not (lambda (condition)
               (if condition
                   #f
                   #t)))
#+end_src

#+begin_src scheme
  (not (= 1 1))
#+end_src

you can compare symbols with ~eq~

Note that to compare symbols they need to be quoted

otherwise their values will be compared

src scheme
  (eq (quote a) (quote b))
#+end_src

src scheme
  (eq (quote a) (quote a))
#+end_src

#+begin_src scheme
  (eq 1 1)
#+end_src

** Acknowledgments

Since this was my first attempt at writing a proper parser lot's of
research was necessary to get started.

I would like to thank the Make a Lisp Project in particular the

https://github.com/kanaka/mal/blob/master/process/guide.md#step1

Which gave me a good Idea of what was needed to write a proper
tokenizer and parser.

No code was used from the project but multiple ideas inspired my
reader implementation.

Since my language (scheme like) is quite different from the one
created in MAL (clojure like) only the core ideas of writing a lisp
parser where able to be reused.

About

YALL a simple extensible lisp dialect written in C++

Resources

Stars

5 stars

Watchers

1 watching

Forks

Releases

Packages

Contributors

Languages