Did some work today, including function parsing
This commit is contained in:
parent
85192bb4c1
commit
3bf4a73c2e
4 changed files with 275 additions and 6 deletions
9
make.sh
9
make.sh
|
@ -1 +1,8 @@
|
||||||
gcc `find src/ -name '*.c'` lib/utilitiec/libargumentc.a lib/utilitiec/libdynamicarray.a lib/utilitiec/libpointers.a lib/utilitiec/liballocator-interface.a lib/utilitiec/libStringView.a -lm -ggdb -o bin/flup
|
gcc `find src/ -name '*.c'` \
|
||||||
|
submodules/utilitiec/build/lib/libargumentc.a \
|
||||||
|
submodules/utilitiec/build/lib/libdynamicarray.a \
|
||||||
|
submodules/utilitiec/build/lib/libpointers.a \
|
||||||
|
submodules/utilitiec/build/lib/liballocator-interface.a \
|
||||||
|
submodules/utilitiec/build/lib/libStringView.a \
|
||||||
|
submodules/utilitiec/build/lib/libScratchpad.a \
|
||||||
|
-lm -ggdb -Wall -o bin/flup
|
||||||
|
|
|
@ -1,16 +1,28 @@
|
||||||
#include "interpreter.h"
|
#include "interpreter.h"
|
||||||
|
|
||||||
|
#include <stdalign.h>
|
||||||
|
|
||||||
static int CallFrame_Create(CallFrame* self, FlupFunctionAlternative* f)
|
static int CallFrame_Create(CallFrame* self, FlupFunctionAlternative* f)
|
||||||
{
|
{
|
||||||
if (DynamicArray_Create(&self->stack, sizeof(Value), 8, NULL)) {
|
if (DynamicArray_Create(&self->stack, sizeof(Value), 8, NULL)) {
|
||||||
return ENOMEM;
|
return ENOMEM;
|
||||||
}
|
}
|
||||||
|
self->memory_pad.memory = NULL;
|
||||||
self->function = f;
|
self->function = f;
|
||||||
self->instruction_pointer = f->body_token_start;
|
self->instruction_pointer = f->body_token_start;
|
||||||
|
|
||||||
return EXIT_SUCCESS;
|
return EXIT_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void* CallFrame_Reserve(CallFrame* self, size_t amount, size_t alignment)
|
||||||
|
{
|
||||||
|
if (self->memory_pad.memory == NULL) {
|
||||||
|
if (Scratchpad_Create(&self->memory_pad, 1024, NULL)) return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return Scratchpad_ReserveAligned(&self->memory_pad, amount, alignment);
|
||||||
|
}
|
||||||
|
|
||||||
static FlupFunctionAlternative* FlupFunctionAlternative_Malloc(size_t condition_token_start, size_t condition_token_end, size_t body_token_start, size_t body_token_end)
|
static FlupFunctionAlternative* FlupFunctionAlternative_Malloc(size_t condition_token_start, size_t condition_token_end, size_t body_token_start, size_t body_token_end)
|
||||||
{
|
{
|
||||||
FlupFunctionAlternative* a = malloc(sizeof(FlupFunctionAlternative));
|
FlupFunctionAlternative* a = malloc(sizeof(FlupFunctionAlternative));
|
||||||
|
@ -33,14 +45,257 @@ int Interpreter_Create(Interpreter* self, DynamicArray* tokens)
|
||||||
return EXIT_SUCCESS;
|
return EXIT_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Token* Interpreter_GetToken(Interpreter* self, size_t index)
|
||||||
|
{
|
||||||
|
return DynamicArray_GetPointer(self->tokens, index);
|
||||||
|
}
|
||||||
|
|
||||||
|
Token* Interpreter_ExpectToken(Interpreter* self, CallFrame* top_frame, size_t stop_index)
|
||||||
|
{
|
||||||
|
if (top_frame->instruction_pointer > stop_index) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return Interpreter_GetToken(self, top_frame->instruction_pointer);
|
||||||
|
}
|
||||||
|
|
||||||
|
int Interpreter_ParseFunction(Interpreter* self, CallFrame* top_frame, size_t stop_index)
|
||||||
|
{
|
||||||
|
FlupFunction* f = CallFrame_Reserve(top_frame, sizeof(FlupFunction), alignof(FlupFunction));
|
||||||
|
if (f == NULL) return ENOMEM;
|
||||||
|
|
||||||
|
Token* function_name = Interpreter_GetToken(self, top_frame->instruction_pointer);
|
||||||
|
|
||||||
|
f->name = function_name->get.identifier;
|
||||||
|
top_frame->instruction_pointer++;
|
||||||
|
|
||||||
|
// one token colon
|
||||||
|
top_frame->instruction_pointer++;
|
||||||
|
|
||||||
|
Token* parameter_type = Interpreter_ExpectToken(self, top_frame, stop_index);
|
||||||
|
ParameterDefinition** pdef = &f->parameters;
|
||||||
|
while (parameter_type->type != TOKENTYPE_ARROW) {
|
||||||
|
top_frame->instruction_pointer++;
|
||||||
|
Token* parameter_name = Interpreter_ExpectToken(self, top_frame, stop_index);
|
||||||
|
top_frame->instruction_pointer++;
|
||||||
|
|
||||||
|
if (parameter_type->type != TOKENTYPE_IDENTIFIER) {
|
||||||
|
// TODO: Error message
|
||||||
|
return EXIT_FAILURE;
|
||||||
|
}
|
||||||
|
if (parameter_name->type != TOKENTYPE_IDENTIFIER) {
|
||||||
|
// TODO: Error message
|
||||||
|
return EXIT_FAILURE;
|
||||||
|
}
|
||||||
|
|
||||||
|
*pdef = CallFrame_Reserve(top_frame, sizeof(**pdef), alignof(**pdef));
|
||||||
|
if (*pdef == NULL) {
|
||||||
|
return ENOMEM;
|
||||||
|
}
|
||||||
|
|
||||||
|
(*pdef)->type = parameter_type->get.identifier;
|
||||||
|
(*pdef)->name = parameter_name->get.identifier;
|
||||||
|
pdef = &((*pdef)->next);
|
||||||
|
|
||||||
|
parameter_type = Interpreter_ExpectToken(self, top_frame, stop_index);
|
||||||
|
}
|
||||||
|
|
||||||
|
// one arrow token
|
||||||
|
top_frame->instruction_pointer++;
|
||||||
|
|
||||||
|
{
|
||||||
|
Token* return_type = Interpreter_ExpectToken(self, top_frame, stop_index);
|
||||||
|
if (return_type == NULL) {
|
||||||
|
return EXIT_FAILURE;
|
||||||
|
}
|
||||||
|
if (return_type->type != TOKENTYPE_IDENTIFIER) {
|
||||||
|
return EXIT_FAILURE;
|
||||||
|
}
|
||||||
|
top_frame->instruction_pointer++;
|
||||||
|
|
||||||
|
f->return_type = return_type->get.identifier;
|
||||||
|
}
|
||||||
|
|
||||||
|
// pipe token
|
||||||
|
Token* alternative_start = Interpreter_ExpectToken(self, top_frame, stop_index);
|
||||||
|
if (alternative_start == NULL) {
|
||||||
|
return EXIT_FAILURE;
|
||||||
|
}
|
||||||
|
|
||||||
|
FlupFunctionAlternative** fdef = &f->alternative;
|
||||||
|
while (alternative_start->type == TOKENTYPE_PIPE) {
|
||||||
|
top_frame->instruction_pointer++;
|
||||||
|
size_t condition_start = top_frame->instruction_pointer;
|
||||||
|
|
||||||
|
Token* current;
|
||||||
|
do {
|
||||||
|
current = Interpreter_ExpectToken(self, top_frame, stop_index);
|
||||||
|
top_frame->instruction_pointer++;
|
||||||
|
if (current == NULL) {
|
||||||
|
return EXIT_FAILURE;
|
||||||
|
}
|
||||||
|
} while (current->type != TOKENTYPE_ARROW);
|
||||||
|
size_t condition_end = top_frame->instruction_pointer - 1;
|
||||||
|
|
||||||
|
size_t body_start = top_frame->instruction_pointer + 1;
|
||||||
|
do {
|
||||||
|
current = Interpreter_ExpectToken(self, top_frame, stop_index);
|
||||||
|
top_frame->instruction_pointer++;
|
||||||
|
if (current == NULL) {
|
||||||
|
return EXIT_FAILURE;
|
||||||
|
}
|
||||||
|
} while (current->type != TOKENTYPE_PIPE && current->type != TOKENTYPE_COLON);
|
||||||
|
top_frame->instruction_pointer--;
|
||||||
|
size_t body_end = top_frame->instruction_pointer;
|
||||||
|
|
||||||
|
*fdef = CallFrame_Reserve(top_frame, sizeof(**pdef), alignof(**pdef));
|
||||||
|
if (*fdef == NULL) {
|
||||||
|
return ENOMEM;
|
||||||
|
}
|
||||||
|
(*fdef)->condition_token_start = condition_start;
|
||||||
|
(*fdef)->condition_token_end = condition_end;
|
||||||
|
(*fdef)->body_token_start = body_start;
|
||||||
|
(*fdef)->body_token_end = body_end;
|
||||||
|
|
||||||
|
fdef = &((*fdef)->next);
|
||||||
|
|
||||||
|
alternative_start = Interpreter_ExpectToken(self, top_frame, stop_index);
|
||||||
|
if (alternative_start == NULL) {
|
||||||
|
return EXIT_FAILURE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// one token colon
|
||||||
|
top_frame->instruction_pointer++;
|
||||||
|
|
||||||
|
return EXIT_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
int Interpreter_ExecuteNext(Interpreter* self, size_t stop_token)
|
||||||
|
{
|
||||||
|
size_t frame_count = DynamicArray_GetLength(&self->call_frames);
|
||||||
|
CallFrame* top_frame = DynamicArray_GetPointer(&self->call_frames, frame_count - 1);
|
||||||
|
Token* t = Interpreter_GetToken(self, top_frame->instruction_pointer);
|
||||||
|
switch (t->type) {
|
||||||
|
case TOKENTYPE_INTEGER:
|
||||||
|
{
|
||||||
|
Value* v;
|
||||||
|
DynamicArray_AppendEmpty(&top_frame->stack, (void**) &v);
|
||||||
|
if (v == NULL) return ENOMEM;
|
||||||
|
v->type = VALUETYPE_INT64;
|
||||||
|
v->get.i64 = t->get.integer;
|
||||||
|
top_frame->instruction_pointer++;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case TOKENTYPE_DOUBLE:
|
||||||
|
{
|
||||||
|
Value* v;
|
||||||
|
DynamicArray_AppendEmpty(&top_frame->stack, (void**) &v);
|
||||||
|
if (v == NULL) return ENOMEM;
|
||||||
|
v->type = VALUETYPE_DOUBLE;
|
||||||
|
v->get.f64 = t->get.decimal;
|
||||||
|
top_frame->instruction_pointer++;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case TOKENTYPE_IDENTIFIER:
|
||||||
|
{
|
||||||
|
Token* next = Interpreter_GetToken(self, top_frame->instruction_pointer + 1);
|
||||||
|
if (next != NULL && next->type == TOKENTYPE_COLON) {
|
||||||
|
// function definition
|
||||||
|
return Interpreter_ParseFunction(self, top_frame, stop_token);
|
||||||
|
} else {
|
||||||
|
// regular call
|
||||||
|
}
|
||||||
|
}
|
||||||
|
case TOKENTYPE_LEFT_BRACE:
|
||||||
|
case TOKENTYPE_RIGHT_BRACE:
|
||||||
|
case TOKENTYPE_AMPERSAND:
|
||||||
|
case TOKENTYPE_PLUS:
|
||||||
|
case TOKENTYPE_MINUS:
|
||||||
|
case TOKENTYPE_MULTIPLY:
|
||||||
|
case TOKENTYPE_DIVIDE:
|
||||||
|
case TOKENTYPE_PIPE:
|
||||||
|
case TOKENTYPE_ARROW:
|
||||||
|
case TOKENTYPE_COLON:
|
||||||
|
case TOKENTYPE_EQUALITY:
|
||||||
|
case TOKENTYPE_INEQUALITY:
|
||||||
|
case TOKENTYPE_LESSTHAN:
|
||||||
|
case TOKENTYPE_LESSEQUAL:
|
||||||
|
case TOKENTYPE_GREATERTHAN:
|
||||||
|
case TOKENTYPE_GREATEREQUAL:
|
||||||
|
case TOKENTYPE_COMMA:
|
||||||
|
break;
|
||||||
|
|
||||||
|
case TOKENTYPE_NONE:
|
||||||
|
case TOKENTYPE_ERROR:
|
||||||
|
default:
|
||||||
|
return EXIT_FAILURE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#define RPN(a,b,c) a c b
|
||||||
|
int Interpreter_RunFrame(Interpreter* self)
|
||||||
|
{
|
||||||
|
size_t frame_count = DynamicArray_GetLength(&self->call_frames);
|
||||||
|
CallFrame* top_frame = DynamicArray_GetPointer(&self->call_frames, frame_count - 1);
|
||||||
|
if (
|
||||||
|
top_frame->instruction_pointer >= top_frame->function->condition_token_start
|
||||||
|
&& top_frame->instruction_pointer <= top_frame->function->condition_token_end
|
||||||
|
) {
|
||||||
|
// alternative executing
|
||||||
|
while (top_frame->instruction_pointer <= top_frame->function->condition_token_end) {
|
||||||
|
Interpreter_ExecuteNext(self, top_frame->function->condition_token_end);
|
||||||
|
|
||||||
|
if (RPN(frame_count, DynamicArray_GetLength(&self->call_frames), !=)) {
|
||||||
|
return EXIT_SUCCESS;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
} else {
|
||||||
|
// function executing
|
||||||
|
while (top_frame->instruction_pointer <= top_frame->function->body_token_end) {
|
||||||
|
Interpreter_ExecuteNext(self, top_frame->function->body_token_end);
|
||||||
|
|
||||||
|
if (RPN(frame_count, DynamicArray_GetLength(&self->call_frames), !=)) {
|
||||||
|
return EXIT_SUCCESS;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return EXIT_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int Interpreter_Run(Interpreter* self)
|
||||||
|
{
|
||||||
|
size_t frame_count;
|
||||||
|
do {
|
||||||
|
frame_count = DynamicArray_GetLength(&self->call_frames);
|
||||||
|
|
||||||
|
if (Interpreter_RunFrame(self)) {
|
||||||
|
// TODO: Return the error code
|
||||||
|
return EXIT_FAILURE;
|
||||||
|
}
|
||||||
|
|
||||||
|
} while (frame_count != 0);
|
||||||
|
return EXIT_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
int Interpreter_Interpret(Interpreter* self)
|
int Interpreter_Interpret(Interpreter* self)
|
||||||
{
|
{
|
||||||
CallFrame* first_frame;
|
CallFrame* first_frame;
|
||||||
DynamicArray_AppendEmpty(&self->call_frames, (void**) &first_frame);
|
FlupFunctionAlternative* file_function = FlupFunctionAlternative_Malloc(SIZE_MAX, SIZE_MAX, 0, DynamicArray_GetLength(self->tokens));
|
||||||
if (CallFrame_Create(first_frame, )) {
|
if (file_function == NULL) {
|
||||||
return ENOMEM;
|
return ENOMEM;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
DynamicArray_AppendEmpty(&self->call_frames, (void**) &first_frame);
|
||||||
|
if (CallFrame_Create(first_frame, file_function)) {
|
||||||
|
return ENOMEM;
|
||||||
|
}
|
||||||
|
|
||||||
|
Interpreter_Run(self);
|
||||||
|
|
||||||
return EXIT_SUCCESS;
|
return EXIT_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
#define FLUP_INTERPRETER_H
|
#define FLUP_INTERPRETER_H
|
||||||
|
|
||||||
#include "../submodules/utilitiec/src/dynamicarray/dynamicarray.h"
|
#include "../submodules/utilitiec/src/dynamicarray/dynamicarray.h"
|
||||||
|
#include "../submodules/utilitiec/src/Scratchpad/Scratchpad.h"
|
||||||
|
|
||||||
#include "tokenizer.h"
|
#include "tokenizer.h"
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
@ -15,13 +16,14 @@ typedef struct FlupFunctionAlternative_s {
|
||||||
} FlupFunctionAlternative;
|
} FlupFunctionAlternative;
|
||||||
|
|
||||||
typedef struct ParameterDefinition_s {
|
typedef struct ParameterDefinition_s {
|
||||||
StringView name;
|
|
||||||
StringView type;
|
StringView type;
|
||||||
|
StringView name;
|
||||||
|
struct ParameterDefinition_s* next;
|
||||||
} ParameterDefinition;
|
} ParameterDefinition;
|
||||||
|
|
||||||
typedef struct FlupFunction_s {
|
typedef struct FlupFunction_s {
|
||||||
StringView name;
|
StringView name;
|
||||||
DynamicArray argument_defs; // ParameterDefinition
|
ParameterDefinition* parameters;
|
||||||
StringView return_type;
|
StringView return_type;
|
||||||
FlupFunctionAlternative* alternative;
|
FlupFunctionAlternative* alternative;
|
||||||
} FlupFunction;
|
} FlupFunction;
|
||||||
|
@ -43,8 +45,13 @@ typedef struct Value_s {
|
||||||
|
|
||||||
typedef struct CallFrame_s {
|
typedef struct CallFrame_s {
|
||||||
size_t instruction_pointer;
|
size_t instruction_pointer;
|
||||||
|
/* ip = condition start : start
|
||||||
|
* ip = condition_end + 1 : done
|
||||||
|
*
|
||||||
|
*/
|
||||||
FlupFunctionAlternative* function;
|
FlupFunctionAlternative* function;
|
||||||
DynamicArray stack; // Value
|
DynamicArray stack; // Value
|
||||||
|
Scratchpad memory_pad;
|
||||||
} CallFrame;
|
} CallFrame;
|
||||||
|
|
||||||
typedef struct Interpreter_s {
|
typedef struct Interpreter_s {
|
||||||
|
|
|
@ -1 +1 @@
|
||||||
Subproject commit 7d8ba6fc28487901a6f73d75eb59dabe416fe391
|
Subproject commit c2c3c2d96e6296b439e901c89d868185cdc82960
|
Loading…
Reference in a new issue