Compare commits

...

10 Commits

Author SHA1 Message Date
38c6a9113c Added sub to the builtin functions. 2025-02-25 08:04:43 -05:00
109bcb3fa5 Fixed function calls on builtin.
Random pointer indirection.
2025-02-25 07:56:25 -05:00
79b60e4853 Fixed name error handling. 2025-02-25 07:52:02 -05:00
8cab531129 Fixed memory error in exception printing.
Conflation between char* & char**.
2025-02-25 07:47:08 -05:00
eb3fbca030 Some things are broken.
EVERYTHING IS BROKEN
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA.
2025-02-15 11:03:51 -05:00
40b91b96bd Adds type infrastructure.
Only floats (nums) are available at the moment.
2025-02-08 11:01:56 -05:00
67f659e263 Merge branch 'master' into types. 2025-02-08 10:23:15 -05:00
11401e75a7 Fixed. 2025-02-08 09:25:54 -05:00
a6be116a2d Adds test for integer arithmetic. 2025-02-07 17:33:18 -05:00
3678940537 Adds preliminary type enums. 2025-02-07 17:29:30 -05:00
11 changed files with 171 additions and 67 deletions

View File

@ -1,2 +1,5 @@
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 CC = clang -std=c2x
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_BLOCK] = "BLOCK", [AST_TYPE_EXC] = "EXCEPTION"
}; };
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,6 +50,7 @@ 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;
@ -77,6 +78,20 @@ 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);

47
src/builtin.c Normal file
View File

@ -0,0 +1,47 @@
#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,6 +3,7 @@
#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"
@ -10,24 +11,19 @@
extern AST* root; extern AST* root;
ASTNumData exec_start(AST* ast) { AST* exec_find(char* name);
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();
// n = 42.02 htab_ins(
char* name = malloc(2); // TODO: Write a macro for this pattern. global, "sum", ast_init(AST_TYPE_BIF, ast_bif_data_init(builtin_sum))
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, ((ASTVDefData*)n->data)->name, ((ASTVDefData*)n->data)->val global, "sub", ast_init(AST_TYPE_BIF, ast_bif_data_init(builtin_sub))
); );
// Push global namespace to `scope`. // Push global namespace to `scope`.
@ -36,19 +32,19 @@ ASTNumData exec_start(AST* ast) {
return exec_exp(ast); return exec_exp(ast);
} }
ASTNumData exec_exp(AST* ast) { AST* 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 *(ASTNumData*)ast->data; case AST_TYPE_NUM: return ast;
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);
} }
} }
ASTNumData exec_block(AST* ast) { AST* exec_block(AST* ast) {
ASTBlockData* block = (ASTBlockData*)ast->data; ASTBlockData* block = (ASTBlockData*)ast->data;
HTab* local = htab_init(); HTab* local = htab_init();
@ -56,7 +52,7 @@ ASTNumData 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]);
ASTNumData last = exec_exp(block->inside[block->ln - 1]); AST* last = exec_exp(block->inside[block->ln - 1]);
stack_pop(scope); stack_pop(scope);
htab_destroy(local); htab_destroy(local);
@ -64,42 +60,26 @@ ASTNumData exec_block(AST* ast) {
return last; return last;
} }
ASTNumData exec_call(AST* ast) { AST* exec_call(AST* ast) {
log_dbg("Started call execution."); log_dbg("Started call execution.");
fflush(stdout); ASTCallData* data = (ASTCallData*)ast->data;
ASTCallData* calldata = (ASTCallData*)ast->data; size_t argc = data->argc;
if (calldata->argc >= 1) { AST** argv = data->argv;
if (!strcmp(calldata->to, "sum")) { char* fname = data->to;
double total = exec_exp(calldata->argv[0]);
for (size_t i = 1; i < calldata->argc; AST* fdef = exec_find(fname);
total += exec_exp(calldata->argv[i++]));
return total; if (fdef == NULL)
} else if (!strcmp(calldata->to, "sub")) { return ast_init(
double total = exec_exp(calldata->argv[0]); AST_TYPE_EXC, ast_exc_data_init(strdup("No such function found."))
);
for (size_t i = 1; i < calldata->argc; switch (fdef->type) {
total -= exec_exp(calldata->argv[i++])); case AST_TYPE_BIF:
ASTBIFData bifdata = fdef->data;
return total; return bifdata(argc, argv);
} else if (!strcmp(calldata->to, "mul")) { default: return ast_init(AST_TYPE_EXC, ast_exc_data_init("Good job!"));
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) {
@ -111,11 +91,10 @@ AST* exec_find(char* name) {
if (val != NULL) return val; if (val != NULL) return val;
} }
log_dbgf("Could not find var %s", name); return NULL;
exit(1);
} }
ASTNumData exec_vdef(AST* ast) { AST* 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;
@ -123,7 +102,7 @@ ASTNumData exec_vdef(AST* ast) {
return exec_exp(val); return exec_exp(val);
} }
ASTNumData exec_vref(AST* ast) { AST* 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); size_t i = hash & (HTAB_SPACE - 1); // Magic.
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,7 +4,19 @@
#include <stdlib.h> #include <stdlib.h>
typedef enum { typedef enum {
AST_TYPE_NUM, // A number. // Primitive types.
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.
@ -28,6 +40,20 @@ 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.

17
src/include/builtin.h Normal file
View File

@ -0,0 +1,17 @@
#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`.
ASTNumData exec_start(AST* ast); AST* exec_start(AST* ast);
ASTNumData exec_exp(AST* ast); AST* exec_exp(AST* ast);
ASTNumData exec_block(AST* ast); AST* exec_block(AST* ast);
ASTNumData exec_call(AST* ast); AST* exec_call(AST* ast);
ASTNumData exec_vref(AST* ast); AST* exec_vref(AST* ast);
ASTNumData exec_vdef(AST* ast); AST* 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");
exec_print(exec_start(root)); ast_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
exec_print(exec_start(root)); ast_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,3 +112,20 @@ 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!" ]
}