Compare commits

..

No commits in common. "38c6a9113c1070da550f9f32e5832bbcbdea43f5" and "b8ce19329964ac52eab733a300c67b40abb80783" have entirely different histories.

11 changed files with 67 additions and 171 deletions

View File

@ -1,5 +1,2 @@
FIX EXCEPTION PRINTING (probably broken because of string literals being dereferenced)
1. Change editor to GNU Readline. 1. Change editor to GNU Readline.
2. Make variables persist through lines in the editor. 2. Make variables persist through lines in the editor.

View File

@ -11,7 +11,7 @@ TEST_DIR = test
TEST_BUILD_DIR = $(BUILD_DIR)/test TEST_BUILD_DIR = $(BUILD_DIR)/test
TEST_OBJ_DIR = $(TEST_BUILD_DIR)/obj TEST_OBJ_DIR = $(TEST_BUILD_DIR)/obj
CC = clang -std=c2x CC = clang
LINK = clang LINK = clang
CFLAGS = -Wall -DDBG -ggdb -fsanitize=leak CFLAGS = -Wall -DDBG -ggdb -fsanitize=leak
LDFLAGS = -lm LDFLAGS = -lm

View File

@ -9,7 +9,7 @@ extern AST* root;
static char* asttype_names[] = { static char* asttype_names[] = {
[AST_TYPE_CALL] = "FUNC CALL", [AST_TYPE_NUM] = "NUMBER", [AST_TYPE_CALL] = "FUNC CALL", [AST_TYPE_NUM] = "NUMBER",
[AST_TYPE_VREF] = "VAR REFERENCE", [AST_TYPE_VDEF] = "VAR DEFINITION", [AST_TYPE_VREF] = "VAR REFERENCE", [AST_TYPE_VDEF] = "VAR DEFINITION",
[AST_TYPE_BLOCK] = "BLOCK", [AST_TYPE_EXC] = "EXCEPTION" [AST_TYPE_BLOCK] = "BLOCK",
}; };
AST* ast_init(ASTType type, void* data) { AST* ast_init(ASTType type, void* data) {
@ -25,10 +25,10 @@ void ast_destroy(AST* ast) {
if (!ast) return; if (!ast) return;
switch (ast->type) { switch (ast->type) {
case AST_TYPE_NUM: ast_num_data_destroy(ast->data); break; case AST_TYPE_NUM: ast_num_data_destroy(ast->data); break;
case AST_TYPE_CALL: ast_call_data_destroy(ast->data); break; case AST_TYPE_CALL: ast_call_data_destroy(ast->data); break;
case AST_TYPE_VREF: ast_vref_data_destroy(ast->data); break; case AST_TYPE_VREF: ast_vref_data_destroy(ast->data); break;
case AST_TYPE_VDEF: ast_vdef_data_destroy(ast->data); break; case AST_TYPE_VDEF: ast_vdef_data_destroy(ast->data); break;
case AST_TYPE_BLOCK: ast_block_data_destroy(ast->data); break; case AST_TYPE_BLOCK: ast_block_data_destroy(ast->data); break;
default: default:
log_dbgf("Unknown ast type %d (max: %d)", ast->type, AST_TYPE_MAX); log_dbgf("Unknown ast type %d (max: %d)", ast->type, AST_TYPE_MAX);
@ -50,7 +50,6 @@ void ast_print_i(AST* ast, int i) {
printf("%s %lf\n", INDENT_spacing->buf, *(ASTNumData*)ast->data); printf("%s %lf\n", INDENT_spacing->buf, *(ASTNumData*)ast->data);
break; break;
case AST_TYPE_CALL: ast_call_print(ast->data, i + 2); break; case AST_TYPE_CALL: ast_call_print(ast->data, i + 2); break;
case AST_TYPE_EXC: ast_exc_print(ast->data, i + 2); break;
case AST_TYPE_VREF: ast_vref_print(ast->data, i + 2); break; case AST_TYPE_VREF: ast_vref_print(ast->data, i + 2); break;
case AST_TYPE_VDEF: ast_vdef_print(ast->data, i + 2); break; case AST_TYPE_VDEF: ast_vdef_print(ast->data, i + 2); break;
case AST_TYPE_BLOCK: ast_block_print(ast->data, i + 2); break; case AST_TYPE_BLOCK: ast_block_print(ast->data, i + 2); break;
@ -78,20 +77,6 @@ void ast_num_print(ASTNumData* data, int i) {
INDENT_END; INDENT_END;
} }
ASTExcData ast_exc_data_init(char* msg) { return (ASTExcData)msg; }
void ast_exc_print(ASTExcData data, int i) {
INDENT_BEGIN(i);
INDENT_TITLE("ASTExcData", data);
INDENT_FIELD("msg", "\"%s\"", data);
INDENT_END;
}
ASTBIFData* ast_bif_data_init(AST* fn(size_t, AST**)) {
return (ASTBIFData*)fn;
}
ASTCallData* ast_call_data_init(char* to, size_t argc, AST** argv) { ASTCallData* ast_call_data_init(char* to, size_t argc, AST** argv) {
talloc(ASTCallData, call); talloc(ASTCallData, call);

View File

@ -1,47 +0,0 @@
#include "include/builtin.h"
#include "include/ast.h"
#include "include/util.h"
#include <stdarg.h>
#include <stdio.h>
AST* builtin_sum(size_t argc, AST** argv) {
log_dbg("Got here");
ASTNumData total = 0;
for (int i = 0; i < argc; i++) {
AST* arg = argv[i];
if (arg->type != AST_TYPE_NUM)
return ast_init(
AST_TYPE_EXC,
ast_exc_data_init("Sum can't sum some non-num arguments.")
);
total += *(ASTNumData*)arg->data;
}
return ast_init(AST_TYPE_NUM, ast_num_data_init(total));
}
AST* builtin_sub(size_t argc, AST** argv) {
log_dbg("Got here");
AST* first = *argv;
if (first->type != AST_TYPE_NUM)
return ast_init(
AST_TYPE_EXC, ast_exc_data_init("Can't subtract non-num arguments.")
);
ASTNumData total = *(ASTNumData*)first->data;
for (int i = 1; i < argc; i++) {
AST* arg = argv[i];
if (arg->type != AST_TYPE_NUM)
return ast_init(
AST_TYPE_EXC,
ast_exc_data_init("Can't subtract non-num arguments.")
);
total -= *(ASTNumData*)arg->data;
}
return ast_init(AST_TYPE_NUM, ast_num_data_init(total));
}

View File

@ -3,7 +3,6 @@
#include <string.h> #include <string.h>
#include "include/ast.h" #include "include/ast.h"
#include "include/builtin.h"
#include "include/exec.h" #include "include/exec.h"
#include "include/htab.h" #include "include/htab.h"
#include "include/stack.h" #include "include/stack.h"
@ -11,19 +10,24 @@
extern AST* root; extern AST* root;
AST* exec_find(char* name); ASTNumData exec_start(AST* ast) {
AST* exec_start(AST* ast) {
scope = stack_init(); scope = stack_init();
// Global scope. Just dummy values for testing.
HTab* global = htab_init(); HTab* global = htab_init();
htab_ins( // n = 42.02
global, "sum", ast_init(AST_TYPE_BIF, ast_bif_data_init(builtin_sum)) char* name = malloc(2); // TODO: Write a macro for this pattern.
strcpy(name, "n");
AST* n = ast_init(
AST_TYPE_VDEF,
ast_vdef_data_init(
name, ast_init(AST_TYPE_NUM, ast_num_data_init(42.02))
)
); );
htab_ins( htab_ins(
global, "sub", ast_init(AST_TYPE_BIF, ast_bif_data_init(builtin_sub)) global, ((ASTVDefData*)n->data)->name, ((ASTVDefData*)n->data)->val
); );
// Push global namespace to `scope`. // Push global namespace to `scope`.
@ -32,19 +36,19 @@ AST* exec_start(AST* ast) {
return exec_exp(ast); return exec_exp(ast);
} }
AST* exec_exp(AST* ast) { ASTNumData exec_exp(AST* ast) {
log_dbg("Started execution."); log_dbg("Started execution.");
switch (ast->type) { switch (ast->type) {
case AST_TYPE_BLOCK: return exec_block(ast); case AST_TYPE_BLOCK: return exec_block(ast);
case AST_TYPE_CALL: return exec_call(ast); case AST_TYPE_CALL: return exec_call(ast);
case AST_TYPE_NUM: return ast; case AST_TYPE_NUM: return *(ASTNumData*)ast->data;
case AST_TYPE_VREF: return exec_vref(ast); case AST_TYPE_VREF: return exec_vref(ast);
case AST_TYPE_VDEF: return exec_vdef(ast); case AST_TYPE_VDEF: return exec_vdef(ast);
default: printf("what\n"); exit(1); default: printf("what\n"); exit(1);
} }
} }
AST* exec_block(AST* ast) { ASTNumData exec_block(AST* ast) {
ASTBlockData* block = (ASTBlockData*)ast->data; ASTBlockData* block = (ASTBlockData*)ast->data;
HTab* local = htab_init(); HTab* local = htab_init();
@ -52,7 +56,7 @@ AST* exec_block(AST* ast) {
// Loop through all but last ast. // Loop through all but last ast.
for (int i = 0; i < block->ln - 1; i++) exec_exp(block->inside[i]); for (int i = 0; i < block->ln - 1; i++) exec_exp(block->inside[i]);
AST* last = exec_exp(block->inside[block->ln - 1]); ASTNumData last = exec_exp(block->inside[block->ln - 1]);
stack_pop(scope); stack_pop(scope);
htab_destroy(local); htab_destroy(local);
@ -60,26 +64,42 @@ AST* exec_block(AST* ast) {
return last; return last;
} }
AST* exec_call(AST* ast) { ASTNumData exec_call(AST* ast) {
log_dbg("Started call execution."); log_dbg("Started call execution.");
ASTCallData* data = (ASTCallData*)ast->data; fflush(stdout);
size_t argc = data->argc; ASTCallData* calldata = (ASTCallData*)ast->data;
AST** argv = data->argv; if (calldata->argc >= 1) {
char* fname = data->to; if (!strcmp(calldata->to, "sum")) {
double total = exec_exp(calldata->argv[0]);
AST* fdef = exec_find(fname); for (size_t i = 1; i < calldata->argc;
total += exec_exp(calldata->argv[i++]));
if (fdef == NULL) return total;
return ast_init( } else if (!strcmp(calldata->to, "sub")) {
AST_TYPE_EXC, ast_exc_data_init(strdup("No such function found.")) double total = exec_exp(calldata->argv[0]);
);
switch (fdef->type) { for (size_t i = 1; i < calldata->argc;
case AST_TYPE_BIF: total -= exec_exp(calldata->argv[i++]));
ASTBIFData bifdata = fdef->data;
return bifdata(argc, argv); return total;
default: return ast_init(AST_TYPE_EXC, ast_exc_data_init("Good job!")); } else if (!strcmp(calldata->to, "mul")) {
double total = exec_exp(calldata->argv[0]);
for (size_t i = 1; i < calldata->argc;
total *= exec_exp(calldata->argv[i++]));
return total;
} else if (!strcmp(calldata->to, "div")) {
double total = exec_exp(calldata->argv[0]);
for (size_t i = 1; i < calldata->argc;
total /= exec_exp(calldata->argv[i++]));
return total;
}
} }
return -1000;
} }
AST* exec_find(char* name) { AST* exec_find(char* name) {
@ -91,10 +111,11 @@ AST* exec_find(char* name) {
if (val != NULL) return val; if (val != NULL) return val;
} }
return NULL; log_dbgf("Could not find var %s", name);
exit(1);
} }
AST* exec_vdef(AST* ast) { ASTNumData exec_vdef(AST* ast) {
ASTVDefData* data = (ASTVDefData*)ast->data; ASTVDefData* data = (ASTVDefData*)ast->data;
AST* val = data->val; AST* val = data->val;
char* key = data->name; char* key = data->name;
@ -102,7 +123,7 @@ AST* exec_vdef(AST* ast) {
return exec_exp(val); return exec_exp(val);
} }
AST* exec_vref(AST* ast) { ASTNumData exec_vref(AST* ast) {
log_dbg("attempting to reference var"); log_dbg("attempting to reference var");
ASTVrefData* vref = (ASTVrefData*)ast->data; ASTVrefData* vref = (ASTVrefData*)ast->data;

View File

@ -20,7 +20,7 @@ void htab_destroy(HTab *htab) {
// Get the index of a key. // Get the index of a key.
size_t geti(char* key) { size_t geti(char* key) {
uint64_t hash = fnv1a_hash(key, strlen(key)); uint64_t hash = fnv1a_hash(key, strlen(key));
size_t i = hash & (HTAB_SPACE - 1); // Magic. size_t i = hash & (HTAB_SPACE - 1);
return i; return i;
} }
@ -32,7 +32,7 @@ void* htab_get(HTab* htab, char* key) {
void htab_ins(HTab* htab, char* key, void* data) { void htab_ins(HTab* htab, char* key, void* data) {
size_t i = geti(key); size_t i = geti(key);
//assert((*htab)[i] == NULL); assert((*htab)[i] == NULL);
(*htab)[i] = data; (*htab)[i] = data;
log_dbgf("Inserted something to hash table @ index %lu", i); log_dbgf("Inserted something to hash table @ index %lu", i);
} }

View File

@ -4,19 +4,7 @@
#include <stdlib.h> #include <stdlib.h>
typedef enum { typedef enum {
// Primitive types. AST_TYPE_NUM, // A number.
AST_TYPE_NUM, // A number (float).
AST_TYPE_STR, // A string
AST_TYPE_INT, // An integer.
AST_TYPE_SYM, // A symbol.
AST_TYPE_EXC, // Exception.
// Collection types:
AST_TYPE_VEC, // A vector (fixed size, fixed type).
AST_TYPE_LIST, // A list (variable size, variable type).
// Misc. types.
AST_TYPE_BIF, // Built-in function.
AST_TYPE_CALL, // A function call. AST_TYPE_CALL, // A function call.
AST_TYPE_VDEF, // A variable definition. AST_TYPE_VDEF, // A variable definition.
AST_TYPE_VREF, // A variable reference. AST_TYPE_VREF, // A variable reference.
@ -40,20 +28,6 @@ ASTNumData* ast_num_data_init(double val);
void ast_num_data_destroy(ASTNumData* num); void ast_num_data_destroy(ASTNumData* num);
void ast_num_print(ASTNumData*, int i); void ast_num_print(ASTNumData*, int i);
// An exception.
typedef char* ASTExcData;
ASTExcData ast_exc_data_init(char* msg);
void ast_exc_data_destroy(ASTExcData* exc);
void ast_exc_print(ASTExcData, int i);
// A built-in function.
typedef AST* (*ASTBIFData)(size_t argc, AST** argv);
// Create a built-in function.
ASTBIFData* ast_bif_data_init(AST* fn(size_t, AST**));
// There is no `ASTBIFData` destroy function, as function pointers are immortal.
typedef struct { typedef struct {
char* to; // What the call's to. char* to; // What the call's to.
size_t argc; // Argument count. size_t argc; // Argument count.

View File

@ -1,17 +0,0 @@
#ifndef BUILTIN_H
#define BUILTIN_H
#include "ast.h"
// Sum some nums.
AST* builtin_sum(size_t argc, AST** argv);
// Subtract nums.
AST* builtin_sub(size_t argc, AST** argv);
// The list of built-in functions.
static AST* (*builtin_fns[])(size_t argc, AST** argv) = {
builtin_sum, builtin_sub
};
#endif

View File

@ -8,12 +8,12 @@
extern Stack* scope; extern Stack* scope;
// Start executing at the root of the AST. Initialize the `scope`. // Start executing at the root of the AST. Initialize the `scope`.
AST* exec_start(AST* ast); ASTNumData exec_start(AST* ast);
AST* exec_exp(AST* ast); ASTNumData exec_exp(AST* ast);
AST* exec_block(AST* ast); ASTNumData exec_block(AST* ast);
AST* exec_call(AST* ast); ASTNumData exec_call(AST* ast);
AST* exec_vref(AST* ast); ASTNumData exec_vref(AST* ast);
AST* exec_vdef(AST* ast); ASTNumData exec_vdef(AST* ast);
void exec_print(double n); void exec_print(double n);
#endif #endif

View File

@ -23,7 +23,7 @@ int main(int argc, char** argv) {
if (argc - 1 && strlen(argv[1]) > 0 && (inp = argv[1]) && !yyparse()) { if (argc - 1 && strlen(argv[1]) > 0 && (inp = argv[1]) && !yyparse()) {
log_dbg("Parsed successfully!\n"); log_dbg("Parsed successfully!\n");
ast_print(exec_start(root)); exec_print(exec_start(root));
HTab* global = stack_pop(scope); HTab* global = stack_pop(scope);
htab_destroy(global); htab_destroy(global);
stack_destroy(scope); stack_destroy(scope);
@ -62,7 +62,7 @@ int main(int argc, char** argv) {
ast_print(root); ast_print(root);
#endif #endif
ast_print(exec_start(root)); exec_print(exec_start(root));
HTab* global = stack_pop(scope); HTab* global = stack_pop(scope);
htab_destroy(global); htab_destroy(global);
stack_destroy(scope); stack_destroy(scope);

View File

@ -112,20 +112,3 @@ bin() { ./scl.out $1 | tail -n1; }
# run bin "f(n)=2*n; f(2)" # run bin "f(n)=2*n; f(2)"
# [ "$output" = "= 4.000000" ] # [ "$output" = "= 4.000000" ]
#} #}
@test "type stuff" {
run bin "x:int=1"
[ "$output" = "= 1" ]
run bin "x=1.5; type(x)"
[ "$output" = "= num"]
run bin "x:int=1.5; type(x)"
[ "$output" = "= int" ]
run bin "x:int=1.5"
[ "$output" = "= 1" ]
run bin "print(\"Hello, world!\")"
[ "$output" = "= Hello, world!" ]
}