ToruNiina / lispiny

a spiny lisp.

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

lispiny

a spiny lisp which uses a lot of > instead of ).

It runs at compile time.

Example Code

#include <lispiny.hpp>

int main()
{
    using namespace lispiny;

    constexpr auto env  = list<1, string("")>;
    constexpr auto cond = lambda<list<lt, arg<0>, 20>>;
    constexpr auto body = lambda<list<
            list<plus, arg<0>, 1>,
            list<plus, arg<1>,
                list<if_, list<eq, 0, list<modulus, arg<0>, 15>>, string("FizzBuzz\n"),
                list<if_, list<eq, 0, list<modulus, arg<0>, 3>>, string("Fizz\n"),
                list<if_, list<eq, 0, list<modulus, arg<0>, 5>>, string("Buzz\n"),
                          list<plus, list<to_string, arg<0>>, string("\n")>
            >>>>
        >>;

    constexpr auto result = eval<list<while_, env, cond, body>>;
    std::cout << car<cdr<result>> << std::endl;

    return 0;
}
$ g++-10 -std=c++20 main.cpp -O2 -Wall -Wextra -Wpedantic -Wfatal-errors -I. -o fizzbuzz
$ ./fizzbuzz
1
2
Fizz
4
Buzz
Fizz
7
8
Fizz
Buzz
11
Fizz
13
14
FizzBuzz
16
17
Fizz
19

Usage

cons, car, cdr, list

Because it is a LISP, you can use cons, car, and cdr.

list<1, 2, 3> is an alias of cons<1, cons<2, cons<3, nil>>>.

basic calculation

You can use basic arithmetic operators and comparison operators.

  • plus, minus, multiplies, divides, modulus, to_string.
  • eq, ne, lt, lt_eq, gt, gt_eq.
#include <lispiny.hpp>

int main()
{
    using namespace lispiny;

    static_assert(eval<list<plus, 1, 2>> ==   3);
    static_assert(eval<list<eq,   1, 2>> == nil);
    static_assert(eval<list<lt,   1, 2>> ==   T);

    static_assert(eval<list<plus, string("foo"), string("bar")>> == string("foobar"));
    static_assert(eval<list<to_string, 42>> == string("42"));

    return 0;
}

function

You can define an anonymous function and capture it as a constexpr value.

#include <lispiny.hpp>

int main()
{
    using namespace lispiny;

    constexpr auto plus10 = lambda<list<plus, 10, arg<0>>>;

    static_assert(eval<list<plus10, 1>> == 11);
    static_assert(eval<list<plus10, 2>> == 12);

    return 0;
}

control flow

  • list<if_, [cond], [then], [else]>

[cond] should be evaluated into T or nil. If T, the whole list will be evaluated into [then]. Otherwise, [else].

#include <lispiny.hpp>

int main()
{
    using namespace lispiny;

    static_assert(eval<list<if_,   T, 42, string("foo")>> == 42);
    static_assert(eval<list<if_, nil, 42, string("foo")>> == string("foo"));

    return 0;
}
  • list<while_, [env], [cond], [body]>

[env] is a list and updated in every iteration. [body] is a function that takes [env] and returns a list. The returned list will be the next [env].

[cond] is a function that takes [env] and returns T or nil. If <cond, env> returns nil, then the calculation stops and returns env at that time.

#include <lispiny.hpp>

int main()
{
    using namespace lispiny;

    constexpr auto env  = list<1, string("")>;
    constexpr auto cond = lambda<list<lt, arg<0>, 20>>;
    constexpr auto body = lambda<list<
            list<plus, arg<0>, 1>,
            list<plus, arg<1>,
                list<if_, list<eq, 0, list<modulus, arg<0>, 15>>, string("FizzBuzz\n"),
                list<if_, list<eq, 0, list<modulus, arg<0>, 3>>, string("Fizz\n"),
                list<if_, list<eq, 0, list<modulus, arg<0>, 5>>, string("Buzz\n"),
                          list<plus, list<to_string, arg<0>>, string("\n")>
            >>>>
        >>;

    constexpr auto result = eval<list<while_, env, cond, body>>;
    std::cout << car<cdr<result>> << std::endl;
}

About

a spiny lisp.

License:MIT License


Languages

Language:C++ 99.4%Language:Makefile 0.6%