aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBad Diode <bd@badd10de.dev>2021-10-08 10:25:59 +0200
committerBad Diode <bd@badd10de.dev>2021-10-08 10:25:59 +0200
commit96d27c2a3e1a0fa0878beb3f9cd02f4b4ed8fdbb (patch)
tree9ec40c0c37630d1b6a7546cc8c9f09fe65809861
downloadbdl-96d27c2a3e1a0fa0878beb3f9cd02f4b4ed8fdbb.tar.gz
bdl-96d27c2a3e1a0fa0878beb3f9cd02f4b4ed8fdbb.zip
Initial commit w/ small readline echo function
-rwxr-xr-x.gitignore1
-rwxr-xr-xMakefile51
-rwxr-xr-xREADME.md53
-rwxr-xr-xsrc/bootstrap/main.c61
-rwxr-xr-xsrc/bootstrap/shorthand.h37
5 files changed, 203 insertions, 0 deletions
diff --git a/.gitignore b/.gitignore
new file mode 100755
index 0000000..378eac2
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1 @@
build
diff --git a/Makefile b/Makefile
new file mode 100755
index 0000000..8bd5560
--- /dev/null
+++ b/Makefile
@@ -0,0 +1,51 @@
1.POSIX:
2.SUFFIXES:
3
4# Source code location and files to watch for changes.
5SRC_DIR := src/bootstrap
6BUILD_DIR := build
7SRC_MAIN := $(SRC_DIR)/main.c
8WATCH_SRC := $(shell find $(SRC_DIR) -name "*.c" -or -name "*.s" -or -name "*.h")
9INC_DIRS := $(shell find $(SRC_DIR) -type d)
10INC_FLAGS := $(addprefix -I,$(INC_DIRS))
11
12# Output executable.
13TARGET := bdl
14BIN := $(BUILD_DIR)/$(TARGET)
15
16# Compiler and linker configuration.
17CC := cc
18CFLAGS := -Wall -Wextra -pedantic
19CFLAGS += $(INC_FLAGS)
20LDFLAGS :=
21LDLIBS :=
22RELEASE_CFLAGS := -DNDEBUG -O2
23DEBUG_CFLAGS := -DDEBUG -O2 -g
24
25.PHONY: tools clean run
26
27# Setup debug/release builds.
28# make clean && make <target> DEBUG=0
29# make clean && make <target> DEBUG=1
30DEBUG ?= 0
31ifeq ($(DEBUG), 1)
32 CFLAGS += $(DEBUG_CFLAGS)
33else
34 CFLAGS += $(RELEASE_CFLAGS)
35endif
36
37main: tools $(BUILD_DIR) $(ROM) $(BIN)
38
39$(BIN): $(SRC_MAIN) $(WATCH_SRC)
40 $(CC) $(CFLAGS) $(LDFLAGS) -o $(BIN) $(SRC_MAIN) $(LDLIBS)
41
42# Create build directory if needed.
43$(BUILD_DIR): tools
44 mkdir -p $(BUILD_DIR)
45
46run: $(BIN)
47 ./$(BIN)
48
49# Remove build directory.
50clean:
51 rm -rf $(BUILD_DIR)
diff --git a/README.md b/README.md
new file mode 100755
index 0000000..4caf1c3
--- /dev/null
+++ b/README.md
@@ -0,0 +1,53 @@
1# Bad Diode's Lisp
2
3For some time I've been meaning to learn more about compilers and programming
4language theory. And so I found myself again delving into a rabbit hole of
5wheel-reinvention for the purpose of fun and learning.
6
7The goals for this project are to build a programming language that can be
8interpreted directly from a VM and with support for compilation to assembly
9(`x86_64` and/or `ARM (thumb or aarch64)`). It could make sense to output
10bytecode for LLVM to take advantage of the built in optimizations, but let's
11just go one step at a time. At the time I know some ARM assembly, but I'm not so
12versed in `x86_64` and know nothing of LLVM bytecode.
13
14I've chosen to implement a Lisp, perhaps a subset of Scheme. The syntax is not
15so important for now, maybe in the future the compiler will take a different
16home-brew language, but hopefully this helps setting the fundamentals for
17a minimal working compiler. In principle, we could keep the internal
18representation and language working as a lisp, but with a different external
19syntax.
20
21The language should have built-in structures for dynamic arrays, hash tables,
22strings (and string views). It should be suitable for use in embedded systems
23and be linked seamlessly with other compiled objects.
24
25Accessing system resources, such as stdio or graphics could be done via function
26calls to the give APIs. This should help decouple the CPU logic from hardware,
27hopefully facilitating porting programs to different platforms (GBA, Rasberry
28Pi, etc.).
29
30The current plan is to build a bootstrap interpreter in C that can be used to
31generate the self-hosted version of itself. I'll try to document the process
32here as best as I can.
33
34The bootstrap implementation should be kept simple, since we can focus on
35optimization once we have a self-hosting compiler.
36
37# Resources
38
39- [Structure and Interpretation of Computer Programs][sicp]
40- [Crafting Interpreters][crafting-interpreters]
41- [Building a Scheme from scratch][scheme-from-scratch]
42- [Compiling a Lisp][compiling-a-lisp]
43- [An Incremental Approach to Compiler Construction][ghuloum11]
44- [Make-A-Lisp Guide][mal]
45- [An Introduction to Scheme and its Implementation][intro-to-scheme-and-imp]
46
47[sicp]: https://mitpress.mit.edu/sites/default/files/sicp/index.html
48[crafting-interpreters]: https://craftinginterpreters.com/
49[scheme-from-scratch]: http://peter.michaux.ca/articles/scheme-from-scratch-introduction
50[compiling-a-lisp]: https://bernsteinbear.com/blog/compiling-a-lisp-0/
51[ghuloum11]: http://scheme2006.cs.uchicago.edu/11-ghuloum.pdf
52[mal]: https://github.com/kanaka/mal/blob/master/process/guide.md
53[intro-to-scheme-and-imp]: https://www.cs.utexas.edu/ftp/garbage/cs345/schintro-v14/schintro_toc.html#SEC271
diff --git a/src/bootstrap/main.c b/src/bootstrap/main.c
new file mode 100755
index 0000000..861c206
--- /dev/null
+++ b/src/bootstrap/main.c
@@ -0,0 +1,61 @@
1#include <stdio.h>
2
3#include "shorthand.h"
4
5typedef struct StringView {
6 char *start;
7 size_t n;
8} StringView;
9
10void
11sv_write(StringView sv) {
12 for (size_t i = 0; i < sv.n; i++) {
13 putchar(sv.start[i]);
14 }
15}
16
17StringView
18read_line(void) {
19 #define RL_BUF_SIZE 1024
20 static char readline_buf[RL_BUF_SIZE];
21
22 // Clear buffer.
23 for (size_t i = 0; i < RL_BUF_SIZE; i++) {
24 readline_buf[i] = 0;
25 }
26
27 // Barebones readline implementation.
28 size_t n = 0;
29 char c;
30 while ((c = getchar()) != '\n') {
31 if (c == '\b') {
32 readline_buf[n] = '\0';
33 n--;
34 } else if (((u8)c >= 0x20 && (u8)c <= 0x7F) && n < RL_BUF_SIZE) {
35 readline_buf[n] = c;
36 n++;
37 }
38 }
39
40 return (StringView){.start = (char *)&readline_buf, .n = n};
41}
42
43void
44display(StringView sv) {
45 if (sv.n != 0) {
46 sv_write(sv);
47 printf("\n");
48 }
49}
50
51#define REPL_PROMPT "bdl> "
52
53int
54main(void) {
55 printf("BDL REPL (Press Ctrl-C to exit)\n");
56 while (true) {
57 printf(REPL_PROMPT);
58 display(read_line());
59 }
60 return 0;
61}
diff --git a/src/bootstrap/shorthand.h b/src/bootstrap/shorthand.h
new file mode 100755
index 0000000..6fcb82c
--- /dev/null
+++ b/src/bootstrap/shorthand.h
@@ -0,0 +1,37 @@
1#ifndef SHORTHAND_H
2#define SHORTHAND_H
3
4#include <assert.h>
5#include <stdbool.h>
6#include <stddef.h>
7#include <stdint.h>
8
9//
10// This simple header just typedefs the basic C define types to a shorter name,
11// loads the quality of life bool macro for _Bool and defines shorthand macros
12// for byte sizes.
13//
14
15typedef uint8_t u8;
16typedef uint16_t u16;
17typedef uint32_t u32;
18typedef uint64_t u64;
19typedef int8_t s8;
20typedef int16_t s16;
21typedef int32_t s32;
22typedef int64_t s64;
23typedef volatile u8 vu8;
24typedef volatile u16 vu16;
25typedef volatile u32 vu32;
26typedef volatile u64 vu64;
27typedef volatile s8 vs8;
28typedef volatile s16 vs16;
29typedef volatile s32 vs32;
30typedef volatile s64 vs64;
31
32#define KB(N) ((u64)(N) * 1024)
33#define MB(N) ((u64)KB(N) * 1024)
34#define GB(N) ((u64)MB(N) * 1024)
35#define TB(N) ((u64)GB(N) * 1024)
36
37#endif // SHORTHAND_H