Sclisp is a toy project for learning C programming language. It's mostly based on the book Build Your Own Lisp and using mpc parser to parse the characters.
There's a few tweak that didn't exist in the book, like malloc() failure
handler and using the archive library, see Highlights for more
tweaks info. There's also the playground directory which contains my
experiment about call stack overflow, array in function parameter, gcc
builtin arithmetic overflow function, and so on.
The source code mostly using the linux kernel coding style as guidance, like
no curly bracket if there's only one statement in if-else statement or
using tab instead of space for indentation.
You can compile the source code by running the run script like:
./run mainOr if you need some debugging information, you can use this:
./run main-debugIf you make any changes to the mpc parser, you can recompile the archive
library with this:
./run mpcAfter you compile the source code, you can start the REPL like this:
./sclispThere's a few caveats with sclisp and some them are:
-
Sclisp only tested in arch linux. So if you use another linux distro or even another operating system, you might need to tweak the source code or the
runscript, like the linking to readline library. -
Sclisp using double type for the result. This is to make parsing easier by only using 1 type for the number, which can cause a problem.
-
Sclisp only tested using
gcccompiler, so the code might not compile when using other compiler. -
Sclisp depends on operating system to clean up the allocated memory when there's allocation failure or integer overflow, because we exit the program directly without doing the clean up of previous memory allocation. This is bad but i'm still not sure what is the right mechanism to do that with the interpreter.
There might be other caveats that i didn't realize yet, so be careful.
This is the highlight of what i did differently from the book:
-
Separate the source code to
sclisp.c,utils.c,utils.h. Trying to emulate the library structure withutils.candutils.h. -
Rather than compiling the
mpcparser over and over again, we compile it once into an object file and then put that as archive library. This can safe some time during compilation process, especially if we did not change the parser frequently. -
Handle case when allocation with
malloc()orrealloc()failed, which is returningNULLvalue, by exit the program with code 69. -
Handle integer overflow case with
gccbuiltin arithmetic overflow function such as__builtin_uadd_overflow()and__builtin_addc()and exit the program with code 42. -
Trying to implement
reallocarray()from the BSD system, which basicallyrealloc()with multiplication overflow checker (still not sure if this is the right implementation). -
Changing the
mpca_lang()andmpc_cleanup()from thempcparser to take array and array size instead of variadic function. The problem with using variadic function withmpca_lang()is that when we forgot to putNULLat the end of the arguments and there's unknown parser name, we will get segmentation fault error. That's because there's no limit when we try to find the parser withmpca_grammar_find_parser()which will attempt to access some inaccessible memory. And by using array and array size inmpc_cleanup(), we don't need to update the arguments every time we add new parser as long as we use the same array asmpca_lang().
This is the things that i remember doing differently. There might be other things that i forgot to mention, so if you want to find out more, you can check the source code.
This project was mostly built on live stream at youtube. For the playlist, you can check here.
- Build your own lisp book.
- MPC parser.
- Linux kernel coding style.
- C reference.
- C99 rationale pdf.
- GNU history library.
- Where C string literal stored.
- Examine contents of data section in ELF file.
- Memory segments in C/C++ (youtube video).
- Understand the .bss segment in C.
- History about virtual memory (youtube video).
- Linux kernel programming language documentation.
- x86 assembly guide.
- Inline assembly in C.
- Basic integer overflow.
- GCC string literal (pdf).
- C programming static keyword.
- Build C static/archive library.
- Function call stack demo.
- GNU virtual memory documentation.
- Computer science from the bottom up.
- right-left rule to read C declaration.
- Explanation about pointer.
- Explanation about function pointer (youtube video).
- GDB Online Documentation.
- Big endian vs little endian format.