aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.gitignore4
-rw-r--r--Makefile29
-rw-r--r--include/bytecode.h40
-rw-r--r--include/std/buffer.h21
-rw-r--r--src/bytecode.c19
-rw-r--r--src/parser.c4
-rw-r--r--src/std/buffer.c42
7 files changed, 146 insertions, 13 deletions
diff --git a/.gitignore b/.gitignore
index c6275a9..5d6847a 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,2 +1,2 @@
-*.o
-tsl
+build/*
+compile_commands.json \ No newline at end of file
diff --git a/Makefile b/Makefile
index 9ab88c1..e19c75e 100644
--- a/Makefile
+++ b/Makefile
@@ -1,20 +1,29 @@
CFLAGS = -Wall -Wextra -g3 -ansi -pedantic
-OBJ = main.o tokenizer.o parser.o
+OBJ = build/main.o build/tokenizer.o build/parser.o build/bytecode.o build/buffer.o
-all: $(OBJ)
- cc -o tsl $(OBJ) -fPIE
+all: build_dir $(OBJ)
+ cc -o build/tsl $(OBJ) -fPIE
clean:
- rm $(OBJ) tsl
+ rm $(OBJ) build/tsl
+
+build_dir:
+ mkdir -p build
compiledb:
make clean; bear make
-main.o: src/main.c include/tokenizer.h
- cc -c src/main.c $(CFLAGS)
+build/main.o: src/main.c include/tokenizer.h
+ cc -c src/main.c -o build/main.o $(CFLAGS)
+
+build/tokenizer.o: src/tokenizer.c include/tokenizer.h
+ cc -c src/tokenizer.c -o build/tokenizer.o $(CFLAGS)
+
+build/parser.o: src/parser.c include/parser.h
+ cc -c src/parser.c -o build/parser.o $(CFLAGS)
-tokenizer.o: src/tokenizer.c include/tokenizer.h
- cc -c src/tokenizer.c $(CFLAGS)
+build/bytecode.o: src/bytecode.c include/bytecode.h
+ cc -c src/bytecode.c -o build/bytecode.o $(CFLAGS)
-parser.o: src/parser.c include/parser.h
- cc -c src/parser.c $(CFLAGS)
+build/buffer.o: src/std/buffer.c include/std/buffer.h
+ cc -c src/std/buffer.c -o build/buffer.o $(CFLAGS)
diff --git a/include/bytecode.h b/include/bytecode.h
new file mode 100644
index 0000000..4a14b8d
--- /dev/null
+++ b/include/bytecode.h
@@ -0,0 +1,40 @@
+#ifndef TSL_BYTECODE_H
+#define TSL_BYTECODE_H
+
+#include "std/buffer.h"
+#include <stdint.h>
+
+/*
+ All instructions are 4 bytes in size.
+*/
+
+typedef uint8_t TslOpcodeType;
+typedef uint8_t TslRegister;
+typedef uint16_t TslValueIndex;
+
+typedef enum {
+ TSL_OPCODE_ASSIGN
+} TslOpcode;
+
+typedef struct {
+ TslBuffer buffer;
+} TslBytecodeWriter;
+
+typedef struct {
+ TslOpcodeType opcode;
+ union {
+ TslRegister dst_reg;
+ TslRegister src_reg;
+ } type1;
+ union {
+ TslRegister dst_reg;
+ TslValueIndex value_index;
+ } type2;
+} TslInstruction;
+
+void tsl_bytecode_writer_init(TslBytecodeWriter *self);
+void tsl_bytecode_writer_deinit(TslBytecodeWriter *self);
+
+int tsl_bytecode_writer_assign(TslBytecodeWriter *self, TslRegister reg, double value);
+
+#endif /* TSL_BYTECODE_H */
diff --git a/include/std/buffer.h b/include/std/buffer.h
new file mode 100644
index 0000000..dea7dbd
--- /dev/null
+++ b/include/std/buffer.h
@@ -0,0 +1,21 @@
+#ifndef TSL_BUFFER_H
+#define TSL_BUFFER_H
+
+#include <stddef.h>
+
+/*
+ TODO: Optimize small size buffers by using data and size members (16 bytes on x86)
+ instead of heap allocation
+*/
+typedef struct {
+ void *data;
+ size_t size;
+ size_t capacity;
+} TslBuffer;
+
+void tsl_buffer_init(TslBuffer *self);
+void tsl_buffer_deinit(TslBuffer *self);
+
+int tsl_buffer_append(TslBuffer *self, void *data, size_t size);
+
+#endif /* TSL_BUFFER_H */
diff --git a/src/bytecode.c b/src/bytecode.c
new file mode 100644
index 0000000..3e9a6e8
--- /dev/null
+++ b/src/bytecode.c
@@ -0,0 +1,19 @@
+#include "../include/bytecode.h"
+#include <assert.h>
+
+void tsl_bytecode_writer_init(TslBytecodeWriter *self) {
+ assert(sizeof(TslInstruction) == 4);
+ tsl_buffer_init(&self->buffer);
+}
+
+void tsl_bytecode_writer_deinit(TslBytecodeWriter *self) {
+ tsl_buffer_deinit(&self->buffer);
+}
+
+int tsl_bytecode_writer_assign(TslBytecodeWriter *self, TslRegister reg, double value) {
+ TslInstruction instruction;
+ instruction.opcode = TSL_OPCODE_ASSIGN;
+ instruction.type2.dst_reg = reg;
+ instruction.type2.value_index = value;
+ return tsl_buffer_append(&self->buffer, &instruction, sizeof(instruction));
+}
diff --git a/src/parser.c b/src/parser.c
index 1324305..176be63 100644
--- a/src/parser.c
+++ b/src/parser.c
@@ -1,8 +1,10 @@
#include "../include/parser.h"
+#include "../include/bytecode.h"
#include <stdio.h>
typedef struct {
TslTokenizer tokenizer;
+ TslBytecodeWriter bytecode_writer;
} TslParser;
static int tsl_parser_parse_rhs(TslParser *self);
@@ -10,6 +12,7 @@ static int tsl_parser_parse_expressions(TslParser *self, TslToken end_token);
static void tsl_parser_init(TslParser *self, const char *code, size_t code_size) {
tsl_tokenizer_init(&self->tokenizer, code, code_size);
+ tsl_bytecode_writer_init(&self->bytecode_writer);
}
static int tsl_parser_parse_map(TslParser *self) {
@@ -263,7 +266,6 @@ int tsl_parser_parse_expressions(TslParser *self, TslToken end_token) {
return 0;
}
-/* EXPRS */
int tsl_parse(const char *code, size_t code_size) {
TslParser parser;
tsl_parser_init(&parser, code, code_size);
diff --git a/src/std/buffer.c b/src/std/buffer.c
new file mode 100644
index 0000000..3fc5184
--- /dev/null
+++ b/src/std/buffer.c
@@ -0,0 +1,42 @@
+#include "../../include/std/buffer.h"
+#include <stdlib.h>
+#include <string.h>
+
+void tsl_buffer_init(TslBuffer *self) {
+ self->data = NULL;
+ self->size = 0;
+ self->capacity = 0;
+}
+
+void tsl_buffer_deinit(TslBuffer *self) {
+ free(self->data);
+}
+
+static int tsl_buffer_ensure_capacity(TslBuffer *self, size_t new_size) {
+ void *new_ptr;
+ if(new_size <= self->capacity)
+ return 1;
+
+ if(self->capacity != 0) {
+ size_t new_capacity = self->capacity;
+ while(new_capacity < new_size) {
+ new_capacity *= 2;
+ }
+ new_size = new_capacity;
+ }
+ new_ptr = realloc(self->data, new_size);
+ if(!new_ptr)
+ return 0;
+
+ self->data = new_ptr;
+ self->capacity = new_size;
+ return 1;
+}
+
+int tsl_buffer_append(TslBuffer *self, void *data, size_t size) {
+ if(!tsl_buffer_ensure_capacity(self, self->size + size))
+ return 1;
+ memcpy((char*)self->data + self->size, data, size);
+ self->size += size;
+ return 0;
+}